0

I am developing a Javascript framework that makes working with the DOM easier. Right now I have an object called ez that has methods for working with the DOM. Here is my code:

var ez = new Object();
ez.get = function(v,type) {
    switch(type) {
        case 'id': this.elementData = document.getElementById(v);
            break;
        case 'class': this.elementData = document.getElementsByClassName(v);
            break;
        case 'tag': this.elementData = document.getElementsByTagName(v);
            break;
        case 'css': this.elementData = document.querySelectorAll(v);
    }
    return this; //returns itself
}
ez.content = function() {
        alert(this.elementData); //returns undefined
}

Then, in another Javascript file (which comes after this one in the HTML file) I execute the following code onload:

window.onload = function() {
    ez.get('test','id').content(); //"test" is the id of an element in the DOM and it does have a text node called "test" also
}

What I want is for ez.get() to return itself (which it does seem to do) and then for it to retain its elementData property. The issue is that the property's value is not retained after I return this, and it becomes undefined. I'm trying to do something similar to what JQuery does, where you can chain-link method calls because each method returns the object.

UPDATE

Okay, I did shorten my code for the post but here is the full code:

var ez = new Object();
ez.get = function(v,type) {
    switch(type) {
        case 'id': this.elementData = document.getElementById(v);
            break;
        case 'class': this.elementData = document.getElementsByClassName(v);
            break;
        case 'tag': this.elementData = document.getElementsByTagName(v);
            break;
        case 'css': this.elementData = document.querySelectorAll(v);
    }
    return this;
}
ez.isElementSet = function(execute) {
    if(this.hasOwnProperty('elementData')) {
        return execute();
    } else {
        return null;
    }
}
ez.content = function() {
    return this.isElementSet(function() {
        return this.elementData.innerHTML;
    });
}
window.onload = function() {
    alert(ez.get('test','id').content());
}

Here is the HTML:

<!DOCTYPE html>
    <head>
        <title>EzDom</title>
        <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
        <link rel='stylesheet' type='text/css' href='css/style.css' />
        <script type='text/javascript' src='ez.js'></script>
        <script type='text/javascript' src='script.js'></script>
    </head>
    <body>
        <p id='test'>Test.</p>
    </body>
</html>
  • It seems to work as expected here: http://jsfiddle.net/jfriend00/t61669cL/ – jfriend00 Aug 31 '15 at 17:08
  • Hmm. What I did to fix it was changed all instances of "this" to "ez" and then it worked. – Tai Kwangi Chicken Aug 31 '15 at 17:13
  • It works fine with `this` in my jsFiddle so obviously you are doing something different than just the code you posted in your question. – jfriend00 Aug 31 '15 at 17:15
  • I updated this with my full code now. It does not work for me unless I change "this" to "ez" and I'm not sure why. Here's a new fiddle https://jsfiddle.net/t61669cL/2/ – Tai Kwangi Chicken Aug 31 '15 at 17:20
  • I posted a bad link before, this is the fiddle https://jsfiddle.net/t61669cL/2/ and if you change every "this" to "ez" you'll see it works then. – Tai Kwangi Chicken Aug 31 '15 at 17:26
  • I have another interesting this. The only "this" you need to change to "ez" is the one in the "content()" method call. Here is a fixed version https://jsfiddle.net/t61669cL/3/ and you can compare it to the broken one jsfiddle.net/t61669cL/2 – Tai Kwangi Chicken Aug 31 '15 at 17:29

1 Answers1

1

The issue is in this function:

ez.isElementSet = function(execute) {
    if(this.hasOwnProperty('elementData')) {
        return execute();
    } else {
        return null;
    }
}

When you call execute(), the value of this gets reset (as it does on every function call) and will no longer be the value you want. That's why you have to use ez.elementData.innerHTML inside that callback. If you expect the value of this to be something specific in a callback function, then you have to specifically make sure the code sets it that way. There are a couple options here. The simplest is probably to use .bind() when setting the callback.

ez.content = function() {
    return this.isElementSet(function() {
        return this.elementData.innerHTML;
    }.bind(this));
}

Working demo: https://jsfiddle.net/jfriend00/ejneaa1x/

For further info on how this is set when a function is called see: When you pass 'this' as an argument

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979