1 /** 2 * Nornix common JavaScript routines. 3 * 4 * @version @version@ 5 */ 6 7 /** 8 * The root namespace for all Nornix JavaScript. 9 */ 10 if (!Nornix) var Nornix = { 11 /** 12 * @namespace Namespace for Event functions 13 */ 14 events:{}, 15 /** 16 * @namespace Namespace for Cookie functions 17 */ 18 cookies:{}, 19 /** 20 * @namespace Namespace for CSS functions. 21 */ 22 css:{}, 23 /** 24 * @namespace Namespace for DOM functions. 25 */ 26 dom:{}, 27 /** 28 * @namespace Namespace for Utility functions. 29 */ 30 util:{}}; 31 32 if (document.addEventListener) 33 { 34 /** 35 * Function to add events to objects. 36 * @see http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html 37 * @see http://ejohn.org/projects/flexible-javascript-events/ 38 * @see http://dean.edwards.name/weblog/2005/12/js-tip1 39 * @param {Object} obj object to add the event to 40 * @param {String} type event type, like "load", "click" 41 * @param {Function} fn the function that should be run when the event fires 42 * @param {boolean} capture if true, indicates that the user wishes to initiate capture 43 */ 44 Nornix.events.add = function ( obj, type, fn, capture ) 45 { 46 obj.addEventListener( type, fn, capture ); 47 }; 48 /** 49 * Function to remove events from objects. 50 * You should use the same parameters as in {@link event#addEvent} to remove the same event listener. 51 * @see http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html 52 * @see http://ejohn.org/projects/flexible-javascript-events/ 53 * @see http://dean.edwards.name/weblog/2005/12/js-tip1 54 * @param {Object} obj object to add the event to 55 * @param {String} type event type, like "load", "click" 56 * @param {Function} fn the function that should be run when the event fires 57 * @param {boolean} capture if true, indicates that the user wishes to initiate capture 58 */ 59 Nornix.events.remove = function ( obj, type, fn, capture ) 60 { 61 obj.removeEventListener( type, fn, capture ); 62 }; 63 } 64 else if (document.attachEvent) 65 { 66 /** 67 * @ignore 68 */ 69 Nornix.events.add = function( obj, type, fn ) 70 { 71 obj["e"+type+fn] = fn; 72 obj[type+fn] = function() 73 { 74 var e = window.event; 75 e.target = window.event.srcElement; 76 obj["e"+type+fn]( e ); 77 }; 78 obj.attachEvent( "on"+type, obj[type+fn] ); 79 }; 80 /** 81 * @ignore 82 */ 83 Nornix.events.remove = function( obj, type, fn ) 84 { 85 obj.detachEvent( "on"+type, obj[type+fn] ); 86 obj[type+fn] = null; 87 obj["e"+type+fn] = null; 88 }; 89 } 90 else 91 { 92 // sorry, no support! 93 Nornix.events.add = Function; 94 Nornix.events.remove = Function; 95 } 96 97 /** 98 * Function to stop normal browser action on events. 99 * Function you can call within your event handlers to stop them performing 100 * the normal browser action or kill the event entirely. 101 * @see http://www.twinhelix.com 102 * @param {Event} e the event object 103 * @param {boolean} c set to true to cancel event bubbling 104 */ 105 Nornix.events.cancel = function(e, c) 106 { 107 e.returnValue = false; 108 if (e.preventDefault) e.preventDefault(); 109 if (c) 110 { 111 e.cancelBubble = true; 112 if (e.stopPropagation) e.stopPropagation(); 113 } 114 }; 115 116 /** 117 * Function to run an initialization after an element 118 * has became available in the DOM. 119 * 120 * The element will be sent to the initializing function as an object. 121 * @param {String} id ID of element to wait for 122 * @param {Function} initFunc the function that should be run when the element is available 123 * @param {number} interval time in milliseconds 124 */ 125 Nornix.events.delayedInit = function (id, initFunc, interval) 126 { 127 var el; 128 if (interval === undefined) interval = 10; 129 var intervalId = window.setInterval( function () 130 { 131 if (el = document.getElementById(id)) 132 { 133 window.clearInterval(intervalId); 134 initFunc(el); 135 } 136 }, 137 interval 138 ); 139 }; 140 141 /** 142 * Function to create a browser cookie. 143 * @param {String} name name of cookie 144 * @param {String} value value of cookie 145 * @param {Number} days number of days browser should save the cookie 146 */ 147 Nornix.cookies.create = function (name, value, days) 148 { 149 var expire; 150 if (days) 151 { 152 var date = new Date(); 153 date.setTime(date.getTime()+(days*24*60*60*1000)); 154 expire = "; expires="+date.toGMTString(); 155 } 156 else 157 { 158 expire = ""; 159 } 160 document.cookie = name+"="+value+expire+"; path=/"; 161 }; 162 163 /** 164 * Function to read a browser cookie. 165 * @param {String} name name of cookie 166 * @return value of cookie 167 * @type String 168 */ 169 Nornix.cookies.read = function (name) 170 { 171 var nameEQ = name + "="; 172 var ca = document.cookie.split(';'), i = 0, c; 173 while (c = ca[i++]) 174 { 175 c = Nornix.util.trim(c); 176 if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); 177 } 178 return ''; 179 }; 180 181 /** 182 * Function to erase a browser cookie. 183 * @param {String} name name of cookie 184 */ 185 Nornix.cookies.erase = function (name) 186 { 187 createCookie(name, "", -1); 188 }; 189 190 /** 191 * Function to swap, remove or add a class name on an object. 192 * @param {HTMLElement} el the object to work on 193 * @param {String} oldstr the old class -- set to null to add class 194 * @param {String} newstr the new class -- leave empty to remove class 195 */ 196 Nornix.css.swap = function (el, oldstr, newstr) 197 { 198 if (!el) return; 199 if (!el.className || el.className.length === 0) 200 { 201 el.className = newstr ? newstr : ""; 202 return; 203 } 204 var arr = el.className.split(" "), i = 0, t; 205 while (t = arr[i++]) 206 { 207 if (t === oldstr) 208 { 209 if (newstr) 210 { 211 arr[i-1] = newstr; 212 el.className = arr.join(" "); 213 return; 214 } 215 else 216 { 217 delete arr[i-1]; 218 el.className = arr.join(" "); 219 return; 220 } 221 } 222 else if (t === newstr) 223 { 224 el.className = arr.join(" "); 225 return; 226 } 227 } 228 if (newstr) arr[arr.length] = newstr; 229 el.className = arr.join(" "); 230 }; 231 232 /** 233 * Function to add a class name on an object. 234 * @param {HTMLElement} el the object to work on 235 * @param {String} className the new class 236 */ 237 Nornix.css.add = function (el, className) 238 { 239 return Nornix.css.swap(el, null, className); 240 }; 241 242 /** 243 * Function to remove a class name from an object. 244 * @function 245 * @param {HTMLElement} el the object to work on 246 * @param {String} className class to remove 247 */ 248 Nornix.css.remove = function (el, className) 249 { 250 return Nornix.css.swap; 251 }(); // create alias for swapClasses() 252 253 /** 254 * Check if class exists on element. 255 * @param {HTMLElement} el the object to work on 256 * @param {String} s class name 257 * @return true if the class exists 258 */ 259 Nornix.css.contains = function (el, s) 260 { 261 if (!el || !el.className) return false; 262 var arr = el.className.split(" "), i = 0, t; 263 while (t = arr[i++]) 264 { 265 if (t === s) return true; 266 } 267 return false; 268 }; 269 270 /** 271 * Get position of node. 272 * @param {HTMLElement} obj the object to work on 273 * @return absolute position as .x and .y of return value. 274 */ 275 Nornix.css.getPos = function (obj) 276 { 277 var pos = {x: obj.offsetLeft || 0, y: obj.offsetTop || 0}; 278 while (obj = obj.offsetParent) 279 { 280 pos.x += obj.offsetLeft || 0; 281 pos.y += obj.offsetTop || 0; 282 } 283 return pos; 284 }; 285 286 /** 287 * Get current style of element. 288 * @function 289 * @param {HTMLElement} el element to get the style from 290 * @param {String} styleProp CSS style propterty to fetch 291 * @return current setting of style property 292 */ 293 Nornix.css.getProperty = function (el, styleProp) 294 { 295 if (window.getComputedStyle) 296 { 297 return function (el, styleProp) 298 { 299 return window.getComputedStyle(el, "").getPropertyValue(styleProp); 300 }; 301 } 302 return function (el, styleProp) 303 { 304 return el.currentStyle ? el.currentStyle[Nornix.css.prop2Js(styleProp)] : null; 305 }; 306 }(); 307 308 /** 309 * Convert CSS property to JS equivalent. 310 * @param {String} p property to convert 311 * @return JS property 312 */ 313 Nornix.css.prop2Js = function (p) 314 { 315 var arr = p.split("-"); 316 if (arr.length > 1) 317 { 318 var sum = arr[0], i = 1, part; 319 while (part = arr[i++]) 320 { 321 sum += part.charAt(0).toUpperCase() + part.substr(1); 322 } 323 return sum; 324 } 325 return p; 326 }; 327 328 329 /** 330 * Create static copy of a live collection. 331 * This makes it much faster to work with the elements. 332 * @param {HTMLCollection} collection a live collection 333 * @return static copy of the live collection 334 */ 335 Nornix.dom.live2copy = function (collection) 336 { 337 var elements = [], i = 0, el; 338 while (el = collection[i++]) 339 { 340 elements[elements.length] = el; 341 } 342 return elements; 343 } 344 345 /** 346 * Function that reads the text content of a DOM node. 347 * IE FIX for .textContent 348 * @param {Node} node DOM node to get text content from 349 * @return text content of node 350 * @type String 351 */ 352 Nornix.dom.getTextContent = function (node) 353 { 354 if (typeof node.textContent != "undefined") 355 { 356 return node.textContent; 357 } 358 else 359 { 360 return node.innerText; 361 } 362 }; 363 364 /** 365 * Preload image files for faster rendering. 366 * @param {Array} imgs array of images 367 * @param {String} path path to images 368 */ 369 Nornix.dom.imagePreload = function (imgs, path, extension) 370 { 371 if (Nornix.cookies.read("preImg")) return; 372 var i = 0, img, loadedImgs = [], loadedImgsCount = 0, imgsCount = imgs.length, imgO; 373 function checkFinished () 374 { 375 loadedImgsCount++; 376 if (loadedImgsCount === imgsCount) 377 { 378 loadedImgs = null; 379 Nornix.cookies.create("preImg", "x"); 380 } 381 } 382 while (img = imgs[i++]) 383 { 384 imgO = new Image(); 385 imgO.onload = checkFinished; 386 imgO.src = path + img + extension; 387 loadedImgs[i] = imgO; 388 } 389 }; 390 391 /** 392 * Find first or last children of element type. 393 * @param {HTMLElement} nodes node, which children nodes will be searched 394 * @param {String} nodeName type of HTML element we are looking for 395 * @param {Function} nodeAction closure for action to execute 396 * @param {boolean} backwards search from the end of the child list when true 397 * @return value of action closure. 398 */ 399 Nornix.dom.findChildOfType = function (nodes, nodeName, nodeAction, backwards) 400 { 401 var e; 402 if (!backwards) 403 { 404 var i = 0; 405 while (e = nodes.childNodes[i++]) 406 { 407 if (Nornix.dom.eqNodeName(e, nodeName)) 408 { 409 return nodeAction(e); 410 } 411 } 412 } 413 else 414 { 415 var i = nodes.childNodes.length - 1; 416 while (e = nodes.childNodes[i--]) 417 { 418 if (Nornix.dom.eqNodeName(e, nodeName)) 419 { 420 return nodeAction(e); 421 } 422 } 423 } 424 }; 425 426 /** 427 * Check if node name of element is equal to a string. 428 * @param {HTMLElement} el the object to work on 429 * @param {String} nodeName 430 * @return true if the node name is equivalent 431 */ 432 Nornix.dom.eqNodeName = function (el, nodeName) 433 { 434 if (el && el.nodeName && el.nodeName.toLowerCase() === nodeName) 435 { 436 return true; 437 } 438 return false; 439 }; 440 441 /** 442 * String function that removes whitespace from the start and end of a string. 443 * @param {String} s the string to use 444 * @return {String} the string with whitespace removed 445 * @type String 446 */ 447 Nornix.util.trim = function (s) 448 { 449 return s.replace(/^\s*|\s*$/g, ""); 450 }; 451 452 /** 453 * True when browser is Internet Exlorer. 454 * @type boolean 455 */ 456 Nornix.util.isIe = document.all && window.opera === undefined; 457