var isIE6 = navigator.userAgent.indexOf('MSIE 6') != -1; /************************************************************************** * Useful Array methods * **************************************************************************/ Array.prototype.indexOf = function(e) { for (var i = 0; i < this.length; i++) if (this[i] == e) return i; return -1; } Array.prototype.contains = function(e) { return this.indexOf(e) != -1; } Array.prototype.remove = function(e) { var p = this.indexOf(e); if (p != -1) { for (; p < this.length - 1; p++) this[p] = this[p+1]; delete this[p]; this.length = p; } return this; } Array.prototype.add = function(e) { this[this.length] = e; } /************************************************************************** * Widget content methods: addContent, clearContent, setContent * **************************************************************************/ function addContent(element, content) { if (!content) return; var type = typeof(content); if (type == 'function') return; else if (content instanceof Array) for (var i = 0; i < content.length; i++) addContent(element, content[i]); else if (type != 'object') element.appendChild(document.createTextNode(content)); else if (content.nodeName) element.appendChild(content); else copyProperties(element, content); } function clearContent(element) { while (element.hasChildNodes()) element.removeChild(element.lastChild); } function setContent(element, content) { clearContent(element); addContent(element, content); } /************************************************************************** * element(name, { attributes | children }) * creates element with name, attributes and children specified * **************************************************************************/ function element(name) { var e = document.createElement(name); for (var i = 1; i < arguments.length; i++) { var arg = arguments[i]; if (!arg) continue; addContent(e, arguments[i]); } addContent(e, elementMethods); return e; } function copyProperties(to, from) { for (var p in from) { if (!to[p] || typeof(to[p]) != 'object' || typeof(from[p]) != 'object') { to[p] = from[p]; } else { copyProperties(to[p], from[p]); } } } /************************************************************************** * Element class methods: add and remove class names from element class attribute * **************************************************************************/ var elementMethods = { addClass : function(style) { if (!this.className || this.className.length == 0) this.className == style; else if (!this.className.split(/\s+/).contains(style)) this.className += ' ' + style; }, removeClass : function(style) { if (this.className && this.className.length > 0) this.className = this.className.split(/\s+/).remove(style).join(' '); }, show : function() { this.removeClass('hidden'); }, hide : function() { this.addClass('hidden'); }, left : function() { var left = 0; var e = this; while (e) { left += e.offsetLeft; e = e.offsetParent; } return left; }, top : function() { var top = 0; var e = this; while (e) { top += e.offsetTop; e = e.offsetParent; } return top; }, right : function() { return this.left() + this.offsetWidth; }, bottom : function() { return this.top() + this.offsetHeight; } }; /************************************************************************** * positioned(x, y, z, widget) * absolutely positions widget at x, y, z * **************************************************************************/ function positioned(x, y, widget) { return element('div', { style : { position : 'absolute', 'left' : x + 'px', top : y + 'px' }}, widget); } /************************************************************************** * multiStateImage({ srcPath }) * an img tag which can change state using img.show(n) method * **************************************************************************/ function multiStateImage() { var attrs = { states : [], setState : function(n) { this.src = this.states[n]; } }; if (isIE6) { attrs.onreadystatechange = function() { fixPNG(this); }; attrs.onload = attrs.onreadystatechange; } var img = element('img', attrs); for (var i = 0; i < arguments.length; i++) if (typeof(arguments[i]) == 'string') img.states[img.states.length] = arguments[i]; else addContent(img, arguments[i]); img.setState(0); return img; } // Utility function which runs fn(item) on all items in list function forAll(list, fn) { for (var i = 0; i < list.length; i++) fn(list[i]); } /************************************************************************** * singleActivated({ widget }) * * **************************************************************************/ function singleActivated() { var elements = []; for (var i = 0; i < arguments.length; i++) { elements[i] = arguments[i]; elements[i].deactivateableSiblings = elements; elements[i]._originalActivate = elements[i].activate; elements[i].activate = function() { forAll(this.deactivateableSiblings, function(e) { e.deactivate(); }); this._originalActivate(); }; } return elements; } function remainingArgs(a, n) { var result = new Array(); var j = 0; for (var i = n; i < a.length; i++) { result[j++] = a[i]; } return result; } function image(src) { var attrs = { src : src }; if (isIE6 && src.indexOf('.png') != -1) attrs.onload = attrs.onreadystatechange = function() { fixPNG(this); }; return element('img', attrs, remainingArgs(arguments, 1)); } function link(href) { return element('a', href ? { href : href } : false, remainingArgs(arguments,1)); }