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>
6
  • It seems to work as expected here: jsfiddle.net/jfriend00/t61669cL Commented Aug 31, 2015 at 17:08
  • Hmm. What I did to fix it was changed all instances of "this" to "ez" and then it worked. Commented Aug 31, 2015 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. Commented Aug 31, 2015 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 jsfiddle.net/t61669cL/2 Commented Aug 31, 2015 at 17:20
  • I posted a bad link before, this is the fiddle jsfiddle.net/t61669cL/2 and if you change every "this" to "ez" you'll see it works then. Commented Aug 31, 2015 at 17:26

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

2 Comments

So what bind() does is basically attatches "this" to that function?
Pretty much. .bind() returns a new function that calls the original with a specific value of this.

Your Answer

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.