0

So I know that classes in Javascript are a bit different as Javascript has this whole everything is an object thing. I'm trying to build a class that contains the information to create a simple div in HTML.

Please see the following code:

Javascript:

$(document).ready(function(){
    var test1 = new OutputHTMLChunk();
    test1.setClass('test');
    test1.setHTMLContent('Test');
    $('#main_container').append(test1.getOutputArea());

    var test2 = new OutputHTMLChunk();
    test2.setClass('wooo');
    test2.setHTMLContent('This is test2');
    $('#main_container').append(test2.getOutputArea());
    $('#main_container').append(test1.getOutputArea());
});

var OutputHTMLChunk = (function(){

    var _part1 = '<div class="';
    var _outputClass = 'output_area';
    var _part2 = '">';
    var _part3 = '</div>';
    var _HTMLContent = '';

    function OutputHTMLChunk(){

    }

    OutputHTMLChunk.prototype.setClass = function(classValue){
        _outputClass = classValue;
    }

    OutputHTMLChunk.prototype.getClass = function(){
        return _outputClass;
    }

    OutputHTMLChunk.prototype.setHTMLContent = function(HTMLContent){
        _HTMLContent = HTMLContent;
    }

    OutputHTMLChunk.prototype.getHTMLContent = function(){
        return _HTMLContent;
    }

    var AssembleArea = function(){
        var output = _part1 + _outputClass + _part2 + _HTMLContent + _part3;
        return output;
    }

    OutputHTMLChunk.prototype.getOutputArea = function(){
        return AssembleArea();
    }

    return OutputHTMLChunk;
})();

Output:

<div class="test">Test</div>
<div class="wooo">This is test2</div>
<div class="wooo">This is test2</div>

So I read here that this is the reason that the second call of test1 is using the variable from test2, it's because the variables are not unique to the newly created objects.

Now if I follow that and change OutputHTMLChunk to the following, my output is still incorrect:

Javascript:

var OutputHTMLChunk = (function(){

    this._part1 = '<div class="';
    this._outputClass = 'output_area';
    this._part2 = '">';
    this._part3 = '</div>';
    this._HTMLContent = '';

    function OutputHTMLChunk(){

    }

    OutputHTMLChunk.prototype.setClass = function(classValue){
        this._outputClass = classValue;
    }

    OutputHTMLChunk.prototype.getClass = function(){
        return this._outputClass;
    }

    OutputHTMLChunk.prototype.setHTMLContent = function(HTMLContent){
        this._HTMLContent = HTMLContent;
    }

    OutputHTMLChunk.prototype.getHTMLContent = function(){
        return this._HTMLContent;
    }

    var AssembleArea = function(){
        var output = this._part1 + this._outputClass + this._part2 + this._HTMLContent + this._part3;
        return output;
    }

    OutputHTMLChunk.prototype.getOutputArea = function(){
        return AssembleArea();
    }

    return OutputHTMLChunk;
})();

Output:

<div class="output_area"></div>
<div class="output_area"></div>
<div class="output_area"></div>

All in all, what I really want from this is the following output:

<div class="test">Test</div>
<div class="wooo">This is test2</div>
<div class="test">Test</div>
Community
  • 1
  • 1
Joseph
  • 3,899
  • 10
  • 33
  • 52
  • 2
    you are aware that you are reinventing the wheel/over complicating everything ? Creating HTML elements, adding/removing css classes is quit arbitrary in Javascript/Jquery. However if you are doing this for practice purposes it might be a good question. – kasper Taeymans Feb 26 '15 at 12:50
  • @kasperTaeymans, Thanks, yeah just for practice, I had this idea of using JS classes to add HTML elements and just tried to go with it. Haha :) – Joseph Feb 26 '15 at 12:59

2 Answers2

2

You need to place instance-specific properties (and variables) in the constructor, not your class IEFE module.

var OutputHTMLChunk = (function(){
    function OutputHTMLChunk(){
        this._part1 = '<div class="';
        this._outputClass = 'output_area';
        this._part2 = '">';
        this._part3 = '</div>';
        this._HTMLContent = '';
    }

    OutputHTMLChunk.prototype.…
    OutputHTMLChunk.prototype.getOutputArea = function(){
        return this._part1 + this._outputClass + this._part2 + this._HTMLContent + this._part3;
    };
    return OutputHTMLChunk;
})();

Of course, those three "parts" are non instance-specific, you can make those "static" constant values in your class scope. However, there's actually no reason to do so as you're not using them in multiple locations, your code would be much clearer if you simply placed literals in your getOutputArea method.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

Note the differences:

  1. The _part variables are constants.
  2. The constructor OutputHTMLChunk sets the instance variables.
  3. Each of methods uses this.variable to access the instance variables.
  4. As AssembleArea is not a method on the object but it still needs the object we bind it to this for it by using AssembleArea.call(this) if it was a method we could have used this.AssembleArea().

In:

var OutputHTMLChunk = (function(){

    var _part1 = '<div class="';
    var _part2 = '">';
    var _part3 = '</div>';

    function OutputHTMLChunk(){
      this._outputClass = 'output_area';
      this._HTMLContent = '';
    }

    OutputHTMLChunk.prototype.setClass = function(classValue){
        this._outputClass = classValue;
    }

    OutputHTMLChunk.prototype.getClass = function(){
        return this._outputClass;
    }

    OutputHTMLChunk.prototype.setHTMLContent = function(HTMLContent){
        this._HTMLContent = HTMLContent;
    }

    OutputHTMLChunk.prototype.getHTMLContent = function(){
        return this._HTMLContent;
    }

    var AssembleArea = function(){
        var output = _part1 + this._outputClass + _part2 + this._HTMLContent + _part3;
        return output;
    }

    OutputHTMLChunk.prototype.getOutputArea = function(){
        return AssembleArea.call(this);
    }

    return OutputHTMLChunk;
})();

To make AssembleArea a method, rather ones above use the following definitions for AssembleArea and getOutputArea:

    OutputHTMLChunk.prototype.AssembleArea = function(){
        var output = _part1 + this._outputClass + _part2 + this._HTMLContent + _part3;
        return output;
    }

    OutputHTMLChunk.prototype.getOutputArea = function(){
        return this.AssembleArea();
    }

Perhaps the difference will be apparent.

Dan D.
  • 73,243
  • 15
  • 104
  • 123
  • Thanks! Could you clarify point 4 for me? My intention was for AssembleArea to be a method, is there a better way I could have done this? – Joseph Feb 26 '15 at 12:57