javascriptchainingmodule-pattern

Is document.getElementById a method that can be chained?


If I have this module pattern:

var MODULE = (function(window){
    var myPublicStuff = {};

    myPublicStuff.myPublicMethod = function(e){
        return e;
    };
    return myPublicStuff;

})(window);  //edit:  forgot to put I have this

This works: (edited for clarity)

v = document.getElementById('some-element'); //works as expected
MODULE.myPublicMethod(v);  //works.

But this does not work,

MODULE.myPublicMethod().document.getElementById('some-element');

or

document.getElementById('some-element').MODULE.myPublicMethod().

I thought that if the preceding member in the jail returned a value, you could chain it to the next link up? That does not work here, but I do not know why.

Edit: Thanks for all the answers. All I'm trying to do is get the element and have that method print it back out via chaining. That's all. if I put in 'btnPrint' I want it to give me <button type="button" id="btnPrint" class="btn">...</button> If I do getElementById at the console, that is what I get if I use a variable for my module first (which makes sense.) I only wanted to do the same thing with a chained method.

Edit: For completeness this is What Travis put on JSFiddle (thanks):

<button type="button" id="btnPrint" class="btn">...</button>

Element.prototype.myPublicMethod = function(){
 //in the prototype scheme that JavaScript uses,
 //the current instance of the Element is *this*,
 //so returning this will return the current Element
 //that we started with.
 return this;

}

console.log(document.getElementById("btnPrint").myPublicMethod());

I agree. This looks bad unless absolutely necessary.


Solution

  • Is document.getElementById a method that can be chained?

    Yes. It returns an Element (or undefined if there is no match). The Element exposes a generic set of functions, and if the element is a specific type (for example a form) then it may also have a specific set of functions exposed.

    Read more on the generic Element type at https://developer.mozilla.org/en-US/docs/Web/API/Element

    I want to do this:

    v = document.getElementById('some-element'); //works as expected
    MODULE.myPublicMethod(v);
    

    Here, v is straightforward, right? It just gets the element with id="some-element". Okay, from there you pass it into the myPublicMethod(v). When you do that, all you are doing is calling a function that returns the same value that is passed in. And nothing else, there is no assignment or storing taking place in the code you show above.

    What you could have done here, if you wanted to take advantage of the chaining setup, would be to then access the v element from the returned value like this:

    v = document.getElementById('some-element');
    var vId = MODULE.myPublicMethod(v).id;
    console.log(vId);// this will log "some-element" to the console
    

    But this does not work,

     MODULE.myPublicMethod().document.getElementById('some-element');
    

    So above I explained that you are "calling a function that returns the same value that is passed in", remember that myPublicMethod just has return e; in it? Well that means that you are using undefined as the result since nothing was passed in using this line of code. In other words, your code above can be examined as undefined.document.getElementById('some-element') which is hopefully clearly problematic.

    if I put in 'btnPrint' I want it to give me <button type="button" id="btnPrint" class="btn">...</button>

    For example, your code as written would accomplish this as such:

    var MODULE = (function(window){
        var myPublicStuff = {};
    
        myPublicStuff.myPublicMethod = function(e){
            return e;
        };
        return myPublicStuff;
    })(window);
    
    console.log(MODULE.myPublicMethod(document.getElementById('btnPrint')));
    <button type="button" id="btnPrint" class="btn">...</button>