tags:

views:

1193

answers:

5

In Javascript, you can extend existing classes by using its prototype object:

String.prototype.getFirstLetter = function() {
    return this[0];
};

Is it possible to use this method to extend DOM elements?

+1  A: 

I found the answer just as I was writing the question, but thought I'd post anyway to share the info.

The object you need to extend is Element.prototype.

Element.prototype.getMyId = function() {
    return this.id;
};
nickf
+7  A: 

you can extend the DOM by using the Element's prototype. However, this does not work in IE7 and earlier. You will need to extend the specific element, one at a time. The Prototype library does this. I recommend looking through the source to see exactly how it's done.

geowa4
Note that this should only be required for IE6 and IE7, as IE8 supports this. See http://msdn.microsoft.com/en-us/library/dd282900(VS.85).aspx.
Michael Madsen
ah - naturally i only tested on FFx thanks for the tip.
nickf
yeah, IE8 has made great headway with DOM manipulation, but fully supporting it isn't quite atop my priority list right now
geowa4
+1  A: 

Yes you can, but it is strongly advised not to.

If you override something another library is expecting to be the original or another library overwrote something you were expecting .. chaos!

It is best practice to keep your code in your own namespace/scope.

Chad Grant
+2  A: 

You shouldn't be directly extending anything (by "anything" I mean native DOM objects) - that will only lead to bad things. Plus re-extending every new element (something you'd have to do to support IE) adds additional overhead.

Why not take the jQuery approach and create a wrapper/constructor and extend that instead:

var myDOM = (function(){
    var myDOM = function(elems){
            return new MyDOMConstruct(elems);
        },
        MyDOMConstruct = function(elems) {
            this.collection = elems[1] ? Array.prototype.slice.call(elems) : [elems];
            return this;
        };
    myDOM.fn = MyDOMConstruct.prototype = {
        forEach : function(fn) {
            var elems = this.collection;
            for (var i = 0, l = elems.length; i < l; i++) {
                fn( elems[i], i );
            }
            return this;
        },
        addStyles : function(styles) {
            var elems = this.collection;
            for (var i = 0, l = elems.length; i < l; i++) {
                for (var prop in styles) {
                    elems[i].style[prop] = styles[prop];
                }
            }
            return this;
        }
    };
    return myDOM;
})();

Then you can add your own methods via myDOM.fn ... And you can use it like this:

myDOM(document.getElementsByTagName('*')).forEach(function(elem){
    myDOM(elem).addStyles({
        color: 'red',
        backgroundColor : 'blue'
    });
});
J-P
"You shouldn't be directly extending anything - that will only lead to bad things." It will lead to good things if you have a good reason for doing it and write your code properly. Apart from interoperability issues, there's no reason not to extend Element.prototype; for other default objects, a lot of good can be had (see adding formatting methods to Date.prototype, or escaping to RegExp.prototype). It's silly to forego perfectly useful OO practices when they're available and useful.
eyelidlessness
We're not talking about the JavaScript language and design patterns or anything like that. This is about the DOM - extending native DOM objects is not a good idea; not to mention the fact that it doesn't work properly in all browsers...
J-P
Apart from interoperability, why is it not a good idea?
eyelidlessness
A: 

yes, let's forget about cross-browser interoperability.. IE8 is out for a while now and I haven't seen any of my friends use it apart from myself..