How to create a pure JavaScript(without using any library) plugin which looks like:
document.getElementById('id').myPlugin();
like jquery ?
How to create a pure JavaScript(without using any library) plugin which looks like:
document.getElementById('id').myPlugin();
like jquery ?
Why use that format? I think
myPlugin(document.getElementById('id'))
would probably be clearer to anyone maintaining the code. I'm not a big fan of monkey patching.
I agree with spender. You should really not mess around with standard javascript elements. It's better to do a wrapper for it (ie $ as jQuery uses). If you want to make a short hand for get elements do a wrapper method and extend that one instead. This will make the code easier to maintain. Since if you modify the standard functionality in Javascript it make interfere with standard behavior. This could lead to some really hard debugging. It's better to make a wrapper function, do what ever you like with it.
But in despite of this, you want to mess around with the standard behavior you can always bind new methods to the standard objects using prototypeing. For example:
Object.prototype.myMethod = function () {}
..fredrik
I hesitate to say you can't. After all, Prototype.js did.
To be able to call getElementById('id').someNewMethod()
you would have to ‘extend’ the prototype of the type of object getElementById
returns, which is an Element
. In some browsers you can indeed do that:
Element.prototype.someNewMethod= function() {
alert('hello from a '+this.tagName);
};
document.body.someNewMethod(); // hello from a BODY
However, this is quite questionable. Prototyping onto the native JavaScript objects like Object
or String
is potentially dodgy enough, what with name clashes between browsers and libraries, but Element
and all the other DOM objects may be ‘host’ objects, which don't permit prototyping.
Even if DOM objects are implemented with a full native JavaScript interface, no specification says that Element
must expose a prototype/constructor-function under a window
property/global variable called Element
.
In reality this does work in Firefox, Webkit and Opera, and IE from version 8 onwards. However it's unstandardised, not all browsers make all the same interfaces available under all the same names, and it won't work in IE6, IE7 or many smaller browsers (eg. mobile browsers).
Prototype had a fallback for these browsers: it would try to augment every instance of an Element
with the new members when it first saw each element. But this had extremely messy side-effects and is considered by many to be a mistake; Prototype 2.0 won't try to extend DOM interfaces any more.
Maybe in the future somebody will tie this down and make it a reliable part of the browser environment. But today that's not the case, so you should continue to use other, clunkier methods such as wrapper functions.
You can create your own wrapper (similar to jQuery), and doing this will allow you to circumvent all of the discussed problems with extending the DOM directly.
myWrapper = (function(){
function NodeList(elems) {
this.length = 0;
this.merge(this, elems.nodeType ? [elems] : elems);
}
function myWrapper(elems) {
return new NodeList(elems);
}
myWrapper.NodeList = NodeList;
NodeList.prototype = {
merge: function(first, second) {
var i = first.length, j = 0;
for (var l = second.length; j < l; ++j) {
first[i++] = second[j];
}
first.length = i;
return first;
},
each: function(fn) {
for (var i = -1, l = this.length; ++i < l;) {
fn.call(this[i], this[i], i, l, this);
}
return this;
}
};
return myWrapper;
})();
And you can add your own methods like so:
myWrapper.NodeList.prototype.myPlugin = function() {
return this.each(function(){
// Do something with 'this' (the element)
});
};
Usage:
myWrapper(document.getElementById('id')).myPlugin();