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?

\$\endgroup\$
  • \$\begingroup\$ How does this "reduce repetitive code to a minimum" ? \$\endgroup\$ – Denys Séguret Jul 11 '13 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\$ – Florian Margaine Jul 11 '13 at 12:29
  • \$\begingroup\$ The setters and getters also look more like the verbosity of java than like a dry framework. \$\endgroup\$ – Denys Séguret Jul 11 '13 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\$ – Flambino Jul 11 '13 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\$ – Flambino Jul 12 '13 at 23:18
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' );
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.