2
\$\begingroup\$

I've been thinking about making Javascript Prototypes that represent HTML elements. For example a form prototype with build in ajax requests and form element prototypes. Or a list with list item prototypes.

I think that the biggest benefit of this approach is that it reduces repetitive code.

Here is an example of what I have in mind.

var LightParticle = function() {
 this.setWidth(10);
 this.setHeight(10);
 this.setTop(0);
 this.setLeft(0);
 this.setPosition("absolute");
 this.setBackground("white");
 this.setClassName("LightParticle");
};
LightParticle.prototype = {
 setWidth : function(width) {
 this.width = width; 
 },
 getWidth : function() {
 return this.width;
 },
 setHeight : function(height) {
 this.height = height; 
 },
 getHeight : function() {
 return this.height;
 },
 setTop : function(top) {
 this.top = top; 
 },
 getTop : function() {
 return this.top;
 },
 setLeft : function(left) {
 this.left = left; 
 },
 getLeft : function() {
 return this.left;
 },
 setBackground : function(background) {
 this.background = background; 
 },
 getBackground : function() {
 return this.background;
 },
 setClassName : function(className) {
 this.className = className; 
 },
 getClassName : function() {
 return this.className;
 },
 setElement : function(element) {
 this.element = element;
 },
 getElement : function(element) {
 return this.element;
 },
 setPosition : function(position) {
 this.position = position;
 },
 getPosition : function(position) {
 return this.position;
 },
 setSize : function(size) {
 this.setWidth(size);
 this.setHeight(size);
 },
 getStyle : function() {
 return {
 position: this.getPosition(),
 width : this.getWidth(),
 height : this.getHeight(),
 top : this.getTop(),
 left: this.getLeft(),
 background: this.getBackground()
 } 
 },
 getView : function() {
 var element = $("<div></div>");
 element
 .addClass(this.getClassName())
 .css(this.getStyle());
 this.setElement(element);
 return element; 
 },
 pulsate : function (speed) {
 var height = this.getHeight();
 var width = this.getWidth();
 var top = this.getTop();
 var left = this.getLeft();
 if(this.getElement().height() == height) {
 height = height * 4;
 width = width * 4;
 top = top - (height/2);
 left = left - (width/2);
 }
 $(this.getElement()).animate({
 "height":height, 
 "width": width,
 "top": top,
 "left":left
 }, speed);
 var that = this;
 setTimeout(function(){
 that.pulsate(speed);
 }, speed); 
 }
}
function addRandomParticle() {
 try {
 var particle = new LightParticle();
 var seed = Math.floor(Math.random() * 70) + 1;
 particle.setBackground("#" + Math.floor((Math.abs(Math.sin(seed) * 16777215)) % 16777215).toString(16));
 particle.setSize(Math.floor(Math.random() * 70) + 10);
 particle.setTop(Math.floor(Math.random() * $(window).height()));
 particle.setLeft(Math.floor(Math.random() * $(window).width()));
 $('#canvas').append(particle.getView());
 particle.pulsate(Math.floor(Math.random() * 2000) + 500);
 } catch(error) {
 console.log(error.message);
 }
}
$(document).ready(function() {
 try {
 for(var i = 0; i < 100; i++) {
 addRandomParticle(); 
 }
 } catch(error) {
 console.log(error.message);
 }
});

So far I'm not satisfied with the getters and setters since they have no datatype validation.

Does anyone have any idea how I can improve this? Or does someone know a completely better approach to reduce javascript code/events?

Jeff Vanzella
4,3182 gold badges24 silver badges33 bronze badges
asked Jul 11, 2013 at 12:02
\$\endgroup\$
9
  • \$\begingroup\$ How does this "reduce repetitive code to a minimum" ? \$\endgroup\$ Commented Jul 11, 2013 at 12:15
  • 1
    \$\begingroup\$ Not really related to your question, but why so many try/catch? It's javascript, not java. Exceptions are really exceptional. \$\endgroup\$ Commented Jul 11, 2013 at 12:29
  • \$\begingroup\$ The setters and getters also look more like the verbosity of java than like a dry framework. \$\endgroup\$ Commented Jul 11, 2013 at 12:46
  • \$\begingroup\$ Since you're using jQuery already, how about replacing that entire class with var particle = $("<div></div>").addClass("LightParticle").css({position: "absolute", width: "10px", height: "10px", background: "white"}); - from there, animate it however you like. E.g. using jquery's animate()... \$\endgroup\$ Commented Jul 11, 2013 at 23:57
  • 2
    \$\begingroup\$ @Sem Oh, I understand that, but 70% of your code right now is constructing the particle. If you want to avoid repetition, then don't duplicate jQuery's functionality. Besides, a jQuery obj already "represents an HTML element" (or several, of course). Build on top of that, wrap things in functions, etc.. For a more direct HTML-to-obj connection, look at Prototype JS, which extends prototypes (which is nasty, although the resulting syntax is neat, IMHO) \$\endgroup\$ Commented Jul 12, 2013 at 23:18

1 Answer 1

2
\$\begingroup\$

As dystroy mentioned, the setters and getters are really not JavaScript style, neither are the many try/catch statements in your functions.

However, if you insist on having all these getters and setters, you should create a utility function that generates a getter/setter for you. Since you have default values for most properties in your LightParticle I was thinking something along the lines of this :

function addGetterSetter( o , property , defaultValue ){
 var postFix = property[0].toUpperCase() + property.slice(1),
 getter = 'get' + postFix,
 setter = 'set' + postFix;
 o[getter] = function(){
 return this[property] || defaultValue;
 }
 o[setter] = function( value ){
 this[property] = value;
 return this;
 } 
} 

And then you would

var LightParticle = function() {},
 prototype = LightParticle.prototype;
addGetterSetter( prototype , width , 10 );
addGetterSetter( prototype , height , 10 );
addGetterSetter( prototype , top , 0 );
addGetterSetter( prototype , left , 0 );
addGetterSetter( prototype , position, 'absolute' );
addGetterSetter( prototype , background, 'white' );
addGetterSetter( prototype , className , 'LightParticle' );
answered Apr 23, 2014 at 20:23
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.