DOM Extensions
Last updated: October 15th, 2008
I regularly use JavaScript to manipulate the DOM. To that end, I've written a small library which extends DOM nodes with some handy methods, such as getElementsByClassName(), hasClass(), addClass(), deleteClass() and a few others. It also has a trim() method to trim white space off strings, and an each() method that passes all items in an array to a callback function.
This library was written for a small project where something like jQuery would be too much overkill. It will not work in Internet Explorer, any version. DOM nodes are not native objects in that browser, so they cannot be prototyped.
Source code
Below is the the source code of the library.
1 /* 2 * Some extensions to the Document Object Model + Array.each() + String.trim() 3 * 4 * Copyright (c) Colin Helvensteijn 2008 5 */ 6 7 8 9 // figure out whether or not we're dealing wit IE 10 var isIE = /msie/.test(navigator.userAgent.toLowerCase()) && !/opera/.test(navigator.userAgent.toLowerCase()); 11 12 // IE doesn't understand most of what we're doing below 13 if(!isIE) 14 { 15 // get DOM constructors 16 var Document = document.constructor, HTMLElement = document.createElement("x").constructor; 17 18 // if no native getElementsByClassName exists, implement our own 19 if(!Document.prototype.getElementsByClassName) 20 { 21 /* 22 * getElementsByClassName() 23 * 24 * Returns an array with all nodes in Document or HTMLElement with class searchClass 25 */ 26 Document.prototype.getElementsByClassName = HTMLElement.prototype.getElementsByClassName = function(searchClass) 27 { 28 var elemList = this.getElementsByTagName('*'), ret = new Array(); 29 30 for(var i = 0, x = 0, len = elemList.length; i < len; i++) 31 if(elemList[i].hasClass(searchClass)) 32 ret[x++] = elemList[i]; 33 34 return ret; 35 }; 36 } 37 // if a native getElementsByClassName exits, convert its output to an array 38 else 39 { 40 // we don't want to overwrite the native implementation 41 Document.prototype._getElementsByClassName = Document.prototype.getElementsByClassName; 42 HTMLElement.prototype._getElementsByClassName = HTMLElement.prototype.getElementsByClassName; 43 44 /* 45 * getElementsByClassName() 46 * 47 * Converts the nodelist returned by the native implementation to an Array object 48 */ 49 Document.prototype.getElementsByClassName = HTMLElement.prototype.getElementsByClassName = function(searchClass) 50 { 51 var nodeList = this._getElementsByClassName(searchClass), ret = new Array(); 52 53 for(var i = 0, x = 0, len = nodeList.length; i < len; i++) 54 ret[x++] = nodeList[i]; 55 56 return ret; 57 } 58 } 59 60 if(!HTMLElement.prototype.hasClass) 61 { 62 /* 63 * hasClass() 64 * 65 * Returns true if HTMLElement has class searchClass, false if not 66 */ 67 HTMLElement.prototype.hasClass = function(searchClass) 68 { 69 if(this.className) 70 { 71 var classList = this.className.split(' '); 72 73 for(var i = 0, len = classList.length; i < len; i++) 74 if(classList[i] == searchClass) 75 return true; 76 } 77 78 return false; 79 }; 80 } 81 82 if(!HTMLElement.prototype.addClass) 83 { 84 /* 85 * addClass() 86 * 87 * Adds class newClass to HTMLElement 88 */ 89 HTMLElement.prototype.addClass = function(newClass) 90 { 91 this.className = (this.className) ? this.className + ' ' + newClass : newClass; 92 }; 93 } 94 95 if(!HTMLElement.prototype.removeClass) 96 { 97 /* 98 * removeClass() 99 * 100 * Removes class oldClass from HTMLElement 101 */ 102 HTMLElement.prototype.removeClass = function(oldClass) 103 { 104 if(this.className) 105 { 106 var classList = this.className.split(' '), newClassName = new String(); 107 108 for(var i = 0, len = classList.length; i < len; i++) 109 if(classList[i] != oldClass) 110 newClassName += classList[i] + ' '; 111 112 this.className = newClassName.trim(); 113 } 114 }; 115 } 116 117 if(!HTMLElement.prototype.toggleClass) 118 { 119 /* 120 * toggleClass() 121 * 122 * Toggles class searchClass on HTMLElement 123 */ 124 HTMLElement.prototype.toggleClass = function(searchClass) 125 { 126 this.hasClass(searchClass) ? this.removeClass(searchClass) : this.addClass(searchClass); 127 }; 128 } 129 130 if(!HTMLElement.prototype.empty) 131 { 132 /* 133 * empty() 134 * 135 * Empties the HTMLElement node 136 */ 137 HTMLElement.prototype.empty = function() 138 { 139 while(this.firstChild) 140 this.removeChild(this.firstChild); 141 }; 142 } 143 144 if(!HTMLElement.prototype.destroy) 145 { 146 /* 147 * destroy() 148 * 149 * Destroys the HTMLElement node 150 */ 151 HTMLElement.prototype.destroy = function() 152 { 153 if(this.parentNode) 154 this.parentNode.removeChild(this); 155 }; 156 } 157 158 if(!Array.prototype.each) 159 { 160 /* 161 * each() 162 * 163 * Calls function callback for each index in the array 164 */ 165 Array.prototype.each = function(callback) 166 { 167 var thisObj = arguments[1]; 168 169 if(typeof callback != "function") 170 throw new TypeError(); 171 172 for(var i = 0, len = this.length; i < len; i++) 173 if(i in this) 174 callback.call(thisObj, this[i], i, this); 175 }; 176 } 177 178 if(!String.prototype.trim) 179 { 180 /* 181 * trim() 182 * 183 * Trims any leading or trailing white space from a string 184 */ 185 String.prototype.trim = function() 186 { 187 return this.replace(/^\s+|\s+$/, ''); 188 }; 189 } 190 } 191 192 /* 193 * $() 194 * 195 * Shortcut for getElementById() 196 */ 197 if(window.$) var _$ = $; 198 var $ = function(searchId) 199 { 200 // if this is the window object, use document instead 201 return document.getElementById(searchId); 202 }; 203 204 /* 205 * $$() 206 * 207 * Shortcut for getElementsByClassName() 208 */ 209 if(window.$$) var _$$ = $$; 210 var $$ = function(searchClass) 211 { 212 // if this is the window object, use document instead 213 return document.getElementsByClassName(searchClass); 214 }; 215