SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Addict miggl's Avatar
    Join Date
    Feb 2007
    Location
    Los Angeles, CA
    Posts
    286
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    How to extend HTMLObject

    I would like to extend any HTMLObject with additional functions, such as the following:
    Code:
    HTMLCollection.prototype.getElementByID = function(s_name)
    {
    	alert(s_name);
    	
    	return null;
    }
    Unfortunately this doesn't work. However, this one does:
    Code:
    Array.prototype.getElementsByName = function(s_name)
    {
    	alert(s_name);
    	
    	return null;
    }
    Is there a way to do what I'm looking for, perhaps using other techniques?
    Celebrate Liberty, Freedom, and Rights at The Constitutionalist.

  2. #2
    SitePoint Addict miggl's Avatar
    Join Date
    Feb 2007
    Location
    Los Angeles, CA
    Posts
    286
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I figured it out:
    Code:
    Object.prototype.getElementByID = function(s_name)
    {
    	alert(s_name);
    	
    	return null;
    }
    Celebrate Liberty, Freedom, and Rights at The Constitutionalist.

  3. #3
    SitePoint Guru Ize's Avatar
    Join Date
    Nov 2005
    Location
    The Netherlands
    Posts
    808
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Do note that your solution adds the getElementByID function to every object you create. It's IMHO not a good idea to extend the Object class.
    For instance, your solution allows this:
    Code Javascript:
    var x = { };
    var y = x.getElementByID('foo'); // <-- this will probably throw an error

    You can extend the HTMLElement prototype in some browsers, but not all (Safari, for instance, does not support this). This is why the popular frameworks use some sort of extending function that assigns these functions to an element.

    For instance:

    Code Javascript:
     
    function $ ( elm ) {
     
      if (typeof elm == 'string') {
        var e = document.getElementById(elm);
      } else {
        var e = elm;
      }
      return extend (elm);
    }
     
    function extend (obj){
      // loop through functions you want to support "natively"
      // add them to obj
      return obj;
    }

    I hope that makes sense

  4. #4
    SitePoint Addict miggl's Avatar
    Join Date
    Feb 2007
    Location
    Los Angeles, CA
    Posts
    286
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Arrow

    Thanks for your thoughts on this!

    The drawback with your approach for me is that this would introduce non-native function calls, and would further complicate actual usage. My main goal here was ease of use.

    Now, if certain browsers do not support extending HTMLObjects, then they also won't support it in your version, as I would be doing the same thing, just in a more round-about way, no?

    I tried following your code, but it didn't completely make sense to me. What I get from it is that I would need to create a function $, then call it using the element I am trying to query, as a parameter, like so:
    Code:
    $(document.getElementById("test"));
    I would much rather do something like:
    Code:
    document.getElementById("test").$("look_for_value");
    Regarding the other concern of overloading all object types: I have found that it only extends the non-specific object types. It hasn't extended Array, and the others. At least not in FireFox.
    Celebrate Liberty, Freedom, and Rights at The Constitutionalist.

  5. #5
    SitePoint Guru Ize's Avatar
    Join Date
    Nov 2005
    Location
    The Netherlands
    Posts
    808
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would also much rather do something like that, but alas; it's hard to accomplish cross-browser compatible.

    Regarding the other concern of overloading all object types: I have found that it only extends the non-specific object types. It hasn't extended Array, and the others. At least not in FireFox.
    This surprises me, since every class in Javascript extends from the Object prototype.
    For instance, this:

    Code Javascript:
    alert (typeof new Array == 'object')

    ...evaluates to true.

    But hey, if you got it working, you've got it working, no?
    Be sure to test it in different browsers though!

  6. #6
    SitePoint Addict miggl's Avatar
    Join Date
    Feb 2007
    Location
    Los Angeles, CA
    Posts
    286
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yea, I'm not 100% sure though, precisely because of the concern you raised (all items are based off the object class). However, I believe that because I am "overloading" objects with the same function (getElementById for example) my "overloaded" one gets nullified as the more specific objects are created, i.e. Array().
    This would hold true if the order of events is the following:

    1. Instantiation of Object.
    2. I add custom functions to Object on page load.
    2. All native specific objects get instantiated (like Array()) and implement their own functions, wiping out my functions.

    Or alternatively:

    1. Instantiation of Object.
    2. All native specific objects get instantiated (like Array()).
    3. I add custom functions to Object on page load.

    Since the specific object classes are based on the original Object class, they would not know of the new Object methods I have created after the fact.

    If I know more about the internals of how these things work I could probably speak more intelligently on this, however, these are just suspicions that I have, nothing more.
    Celebrate Liberty, Freedom, and Rights at The Constitutionalist.

  7. #7
    SitePoint Guru Ize's Avatar
    Join Date
    Nov 2005
    Location
    The Netherlands
    Posts
    808
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, you might be right, but try this:

    Code Javascript:
    Object.prototype.doSomething = function(){
    }
    alert (typeof new Array().doSomething == 'function');

    This alerts "true"...

  8. #8
    SitePoint Addict miggl's Avatar
    Join Date
    Feb 2007
    Location
    Los Angeles, CA
    Posts
    286
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Good point! But try this:
    Code:
    alert (typeof new Array().doSomething == 'function');
    Object.prototype.doSomething = function(){}
    alert (typeof new Array().doSomething == 'function');
    This is probably very obvious, when you look at the code. But I believe it represents what's happening in the page: The page loads its objects without any of my prototyping. Only object instantiated after the prototyping has been defined actually have the extended functionality.

    To get around the issue of of not being able to access this extended functionality when in an HTMLCollection, for example, I have created new functions called getItemsBy*(). These work just like the getElement(s)By*() functions, but instead they return a real array of objects, instead of a collection. All I have to do then is extend the Array() object and the Object() object to include my custom functions, so that I can use them on anything on the page.

    Now, your point above leads me to believe that I can also achieve this by only extending the Object() object, and wouldn't need to extend the Array() object. *testing now* This worked, just like you said. Unfortunately the Object() extension doesn't appear to effect the Document() object. I'll have to manually extend that as well.

    Thanks for your insightful and thought-provoking discussion!
    Celebrate Liberty, Freedom, and Rights at The Constitutionalist.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •