Update: I re-wrote them (again). I can find the new methods here. I created a new post instead of just re-writing this for historical reasons. Sorry for the inconvinience.
I’ve just recently wrote a post called Javascript Tools Collection, where I revealed (I like this word, looks like that’s something secret
) my favourite javascript tools. Probably, the ones I use most are SACK (for ajax requests), and dom related functions. And I just started a new project heavily based on dom handling, so I decided to re-design my super ultra mega dom manipulation kit. My idea was that instead of having global functions to do the handling of the elements, I would complement the methods that are already there in the browser, prototyping some new methods, this way, I get a more elegant approach, and much more object oriented flavoured. I even made some rudimentary performance tests and found out that this way of doing things is between 5 to 10 % faster, depending on the cases. So, here’s wath I have now:
- Event attacher
1 2 3 4 5 6 7 8 9
Object.prototype.addEvent = function(evtType, func) { if (this.addEventListener) { //gecko this.addEventListener(evtType, func, true); } else if (this.attachEvent) { //ie this.attachEvent('on' + evtType, func); } else { //all the others this['on' + evtType] = func; } }
- Class handling
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
Object.prototype.hasClass = function(className) { var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)'); //use this regexp return pattern.test(this.className); //to check for the class } Object.prototype.addClass = function(className) { if (!this.hasClass(className)) { //if the class isn't there already this.className += (' ' + className); //append it to the end of the class list } } Object.prototype.removeClass = function(className) { var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)'); //use this regexp this.className = this.className.replace(pattern, ' '); //to make a search and replace by a blank space }
- GetElementsByClass
27 28 29 30 31 32 33 34 35 36 37 38 39 40
Object.prototype.getElementsByClass = function (className, tag) { var returnArray = []; tag = tag || '*'; //if tag is defined, use that for a more specific search, otherwise search in all tags var els = this.getElementsByTagName(tag); //get the elements for (var i = 0; i < els.length; i++) { //run the elements if (els[i].hasClass(className)) { //if a element implements that class returnArray.push(els[i]); //append it to the return array } } return returnArray; }
- Element attachers. Note that for simple appending there is already a function in javascript called
appendChild, that does is job and is cross browser, so there’s no need to re-invent the well here.42 43 44 45 46 47 48 49 50
Object.prototype.appendAfter = function(newElement) { //call insertBefore method on parent node to insert the new element before the element next to this this.parentNode.insertBefore(newElement, this.nextSibling); } Object.prototype.appendBefore = function(newElement) { //call insertBefore method on parent node to insert the new element before this this.parentNode.insertBefore(newElement, this); }
For element replacements there is the function
replaceChild(newElement, oldElement). - Element removal
I know that for this job there is already a function calledremoveChild, but because our little friend memory leaking bug in IE, we need a little retouching.52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
Object.prototype.removeElement = function(oldElement) { var childElements = oldElement.getElementsByTagName('*'); for (var i = 0; i < childElements.length; i++) { //purge all elements contained in the element to remove purge(childElements[i]); } purge(oldElement); //purge the element to remove this.removeChild(oldElement); //remove it //function that came from Douglas Crockford site, that removes all the event handlers from de elements function purge(d) { var a = d.attributes, i, l, n; if (a) { l = a.length; for (i = 0; i < l; i += 1) { n = a[i].name; if (typeof d[n] === 'function') { d[n] = null; } } } a = d.childNodes; if (a) { l = a.length; for (i = 0; i < l; i += 1) { purge(d.childNodes[i]); } } } }
- Element creation
For that, I still use the$newfunction I’ve showed in the other post, because unless we’re creating and appending an element at the same time, it’s not very logic to assign this task to elements (this sentence doesn’t sound very well on my head). But I had to make a small modification, because our prototype methods are going to be available in all objects, even if we do something like thisvar obj = {}, and the$newfunction has an object as an argument:84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
function $new(eltype, attributes, content) { var newElement = document.createElement(eltype); if (typeof(attributes != 'undefined')) { if (typeof(attributes) == 'object') { for (name in attributes) { if (typeof(attributes[name] == 'string') newElement.setAttribute(name, attributes[name]); } if (typeof(content != 'undefined')) newElement.innerHTML = content; } else { newElement.innerHTML = attributes; } } return newElement; }
I also still use the dollar sign ($) function to call for elements by his id.
Usually, developers tend to create functions that either accept a single element or an array of elements, or even just a element id. I think that in an extensive program this can become a bit confusing, so, if I want to remove a certain element and I only know it’s id and parent node, I use parentNode.removeElement($('elementId')), using the dollar sign function, instead of making the function check if the parameter is a string or an element and then act accordingly to that. For multi element handling, I like to use function mapping, using a function like this:
1 2 3 4 5 | //call the function having each element of the array as parameter Array.prototype.map = function(f) { for (i = 0; i < this.length; i++) f(this[i]); } |
So, if I want to remove multiple elements in an array, I use theArray.map(parentNode.removeElement). This way, every time I look to the code and I see the removeElement method, I know if I’m removing a single element, a single element based on it’s id, or multiple elements in a array.
I intend to make a post demonstrating these methods creating some kind of widget. So, stay tuned…
Cheers,
Hernâni

























































