Prototype’s DOM extensions set it apart from other JavaScript libraries. Prototype adds many convenience methods to elements returned by the$() function: for instance, you can write$('comments').addClassName('active').show() to get the element with the ID ‘comments’, add a class name to it and show it (if it was previously hidden). The ‘comments’ element didn’t have those methods in native JavaScript; how is this possible? This document reveals some clever hacks found in Prototype.
Most of the DOM methods are encapsulated by theElement.Methods object andthen copied over to theElement object (for convenience). They all receive theelement to operate with as the first parameter:
Element.hide('comments');vardiv_height=Element.getHeight(my_div);Element.addClassName('contactform','pending');These examples are concise and readable, but we can do better. If you have anelement to work with, you can pass it throughElement.extend() and it willcopy all those methods directly to the element. Example, to create an elementand manipulate it:
varmy_div=document.createElement('div');Element.extend(my_div);my_div.addClassName('pending').hide();// insert it in the documentdocument.body.appendChild(my_div);Our method calls just got shorter and more intuitive! As mentioned before,Element.extend() copies all the methods fromElement.Methods to our elementwhich automatically becomes the first argument for all those functions. Theextend() method is smart enough not to try to operate twice on the sameelement. What’s even better,the dollar function$() extends every elementpassed through it with this mechanism.
In addition,Element.extend() also appliesForm.Methods to FORM elementsandForm.Element.Methods to INPUT, TEXTAREA and SELECT elements:
varcontact_data=$('contactform').serialize();varsearch_terms=$('search_input').getValue();Note that not only the dollar function automatically extends elements!Element.extend() is also called indocument.getElementsByClassName,Form.getElements, on elements returned from the$$() function (elementsmatching a CSS selector) and other places - in the end, chances are you willrarely need to explicitly callElement.extend() at all.
If you have some DOM methods of your own that you’d like to add to those ofPrototype, no problem! Prototype provides a mechanism for this, too. Supposeyou have a bunch of functions encapsulated in an object, just pass the objectover toElement.addMethods():
varMyUtils={truncate:function(element,length){element=$(element);returnelement.update(element.innerHTML.truncate(length));},updateAndMark:function(element,html){return$(element).update(html).addClassName('updated');}};Element.addMethods(MyUtils);// now you can:$('explanation').truncate(100);The only thing to watch out here is to make sure the first argument of these methods is the element itself. In your methods, you can also return the element in the end to allow for chainability (or, as practiced in the example, any method which itself returns the element).
There is a secret behind all this.
In browsers that support adding methods to prototype of native objects such asHTMLElementall DOM extensions on the element are available bydefault without ever having to callElement.extend(), dollar function oranything! This will then work in those browsers:
varmy_div=document.createElement('div');my_div.addClassName('pending').hide();document.body.appendChild(my_div);Because the prototype of the native browser object is extended, all DOM elementshave Prototype extension methods built-in. This, however, isn’t true for IEwhich doesn’t let anyone touchHTMLElement.prototype. To make the previousexample work in IE you would have to extend the element withElement.extend().Don’t worry, the method is smart enough not to extend an element more than once.
Because of browsers that don’t support this you must take care to use DOMextensions only on elements that have been extended. For instance, the exampleabove works in Firefox and Opera, but addElement.extend(my_div) aftercreating the element to make the script really solid. You can use the dollarfunction as a shortcut like in the following example:
// this will error out in IE:$('someElement').parentNode.hide();// to make it cross-browser:$($('someElement').parentNode).hide();Don’t forget about this! Always test in all the browsers you plan to support.
© 2006–2023 Prototype Core Team.
Licenses:MIT License (source code) andCC-BY-SA (documentation)