var Class = function(properties){ var klass = function(){ if (this.initialize && $type(this.initialize) == 'function') return this.initialize.apply(this, arguments); else return this; }; $extend(klass, this); klass.prototype = properties; return klass; }; Class.empty = function(){}; Class.prototype = { extend: function(properties){ var proto = $merge(this.prototype); for (var property in properties){ var pp = proto[property]; proto[property] = $mergeClass(pp, properties[property]); } return new Class(proto); }, implement: function(properties){ $extend(this.prototype, properties); } }; function $type(obj){ if (obj === null || obj === undefined) return false; var type = typeof obj; if (type == 'object'){ if (obj.htmlElement) return 'element'; if (obj.push) return 'array'; if (obj.nodeName){ switch(obj.nodeType){ case 1: return 'element'; case 3: return obj.nodeValue.test(/\S/) ? 'textnode' : 'whitespace'; } } } return type; }; function $merge(){ var mix = {}; for (var i = 0; i < arguments.length; i++){ for (var property in arguments[i]){ var ap = arguments[i][property]; var mp = mix[property]; if (mp && $type(ap) == 'object' && $type(mp) == 'object') mix[property] = $merge(mp, ap); else mix[property] = ap; } } return mix; }; //internal function $mergeClass(previous, current){ if (previous && previous != current){ var ptype = $type(previous); var ctype = $type(current); if (ptype == 'function' && ctype == 'function'){ var merged = function(){ this.parent = arguments.callee.parent; return current.apply(this, arguments); }; merged.parent = previous; return merged; } else if (ptype == 'object' && ctype == 'object'){ return $merge(previous, current); } } return current; }; var $extend = Object.extend = function(){ var args = arguments; if (!args[1]) args = [this, args[0]]; for (var property in args[1]) args[0][property] = args[1][property]; return args[0]; }; var $native = Object.Native = function(){ for (var i = 0; i < arguments.length; i++) arguments[i].extend = $native.extend; }; $native.extend = function(props){ for (var prop in props){ if (!this.prototype[prop]) this.prototype[prop] = props[prop]; } }; $native(Function, Array, String, Number, Class); //window, document window.extend = document.extend = $extend; var Window = window; function $chk(obj){ return !!(obj || obj === 0); }; function $pick(obj, picked){ return (obj !== null && obj !== undefined) ? obj : picked; }; function $random(min, max){ return Math.floor(Math.random() * (max - min + 1) + min); }; function $time(){ return new Date().getTime(); }; function $duration(data, ms){ if ($type(data) != 'object') return parseInt(data); this.units = this.units || {years: 'FullYear', months: 'Month', days: 'Date', hours: 'Hours', minutes: 'Minutes', seconds: 'Seconds', milliseconds: 'Milliseconds'}; var date = new Date(); for (var unit in data){ var fn = this.units[unit]; if (fn) date['set' + fn](date['get' + fn]() + $pick(data[unit], 0)); } return parseInt((date.getTime() - $time()) / (ms ? 1 : 1000)); } function $clear(timer){ clearTimeout(timer); clearInterval(timer); return null; }; if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true; else if (document.childNodes && !document.all && !navigator.taintEnabled) window.khtml = true; else if (document.getBoxObjectFor != null) window.gecko = true; //htmlelement if (typeof HTMLElement == 'undefined'){ var HTMLElement = Class.empty; if (window.khtml) document.createElement("iframe"); //fixes safari HTMLElement.prototype = (window.khtml) ? window["[[DOMElement.prototype]]"] : {}; } HTMLElement.prototype.htmlElement = true; //enables background image cache for internet explorer 6 if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){}; var Chain = new Class({ chain: function(fn){ this.chains = this.chains || []; this.chains.push(fn); return this; }, callChain: function(){ if (this.chains && this.chains.length) this.chains.shift().delay(10, this); }, clearChain: function(){ this.chains = []; } }); var Events = new Class({ addEvent: function(type, fn){ if (fn != Class.empty){ this.events = this.events || {}; this.events[type] = this.events[type] || []; this.events[type].include(fn); } return this; }, fireEvent: function(type, args, delay){ if (this.events && this.events[type]){ this.events[type].each(function(fn){ fn.create({'bind': this, 'delay': delay, 'arguments': args})(); }, this); } return this; }, removeEvent: function(type, fn){ if (this.events && this.events[type]) this.events[type].remove(fn); return this; } }); var Options = new Class({ setOptions: function(){ var args = (arguments.length == 1) ? [this.options, arguments[0]] : arguments; this.options = $merge.apply(this, args); if (this.addEvent){ for (var option in this.options){ if (($type(this.options[option]) == 'function') && option.test(/^on[A-Z]/)) this.addEvent(option, this.options[option]); } } return this; } }); var Group = new Class({ initialize: function(){ this.instances = $A(arguments); this.events = {}; this.checker = {}; }, addEvent: function(type, fn){ this.checker[type] = this.checker[type] || {}; this.events[type] = this.events[type] || []; if (this.events[type].test(fn)) return false; else this.events[type].push(fn); this.instances.each(function(instance, i){ instance.addEvent(type, this.check.bind(this, [type, instance, i])); }, this); return this; }, check: function(type, instance, i){ this.checker[type][i] = true; var every = this.instances.every(function(current, j){ return this.checker[type][j] || false; }, this); if (!every) return; this.instances.each(function(current, j){ this.checker[type][j] = false; }, this); this.events[type].each(function(event){ event.call(this, this.instances, instance); }, this); } }); //custom methods Array.extend({ forEach: function(fn, bind){ for (var i = 0, j = this.length; i < j; i++) fn.call(bind, this[i], i, this); }, filter: function(fn, bind){ var results = []; for (var i = 0, j = this.length; i < j; i++){ if (fn.call(bind, this[i], i, this)) results.push(this[i]); } return results; }, map: function(fn, bind){ var results = []; for (var i = 0, j = this.length; i < j; i++) results[i] = fn.call(bind, this[i], i, this); return results; }, every: function(fn, bind){ for (var i = 0, j = this.length; i < j; i++){ if (!fn.call(bind, this[i], i, this)) return false; } return true; }, some: function(fn, bind){ for (var i = 0, j = this.length; i < j; i++){ if (fn.call(bind, this[i], i, this)) return true; } return false; }, indexOf: function(item, from){ from = from || 0; var len = this.length; if (from < 0) from = Math.max(0, len + from); while (from < len){ if (this[from] === item) return from; from++; } return -1; }, copy: function(start, length){ start = start || 0; if (start < 0) start = this.length + start; length = length || (this.length - start); var newArray = []; for (var i = 0; i < length; i++) newArray[i] = this[start++]; return newArray; }, remove: function(item){ var i = 0; var len = this.length; while (i < len){ if (this[i] && this[i] === item) this.splice(i, 1); else i++; } return this; }, test: function(item, from){ return this.indexOf(item, from) != -1; }, extend: function(newArray){ for (var i = 0, j = newArray.length; i < j; i++) this.push(newArray[i]); return this; }, implement: function(array){ for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); return this; }, associate: function(keys){ var obj = {}, length = Math.min(this.length, keys.length); for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; return obj; }, include: function(item){ if (!this.test(item)) this.push(item); return this; } }); Array.prototype.each = Array.prototype.forEach; function $A(array, start, length){ return Array.prototype.copy.call(array, start, length); }; function $each(iterable, fn, bind){ if ($chk(iterable.length)) Array.prototype.forEach.call(iterable, fn, bind); else for (var name in iterable) fn.call(bind, iterable[name], name); }; String.extend({ test: function(regex, params){ return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this); }, toInt: function(){ return parseInt(this); }, toFloat: function(){ return parseFloat(this); }, camelCase: function(){ return this.replace(/-\D/g, function(match){ return match.charAt(1).toUpperCase(); }); }, hyphenate: function(){ return this.replace(/\w[A-Z]/g, function(match){ return (match.charAt(0)+'-'+match.charAt(1).toLowerCase()); }); }, capitalize: function(){ return this.toLowerCase().replace(/\b[a-z]/g, function(match){ return match.toUpperCase(); }); }, trim: function(){ return this.replace(/^\s+|\s+$/g, ''); }, clean: function(){ return this.replace(/\s{2,}/g, ' ').trim(); }, rgbToHex: function(array){ var rgb = this.match(/\d{1,3}/g); return (rgb) ? rgb.rgbToHex(array) : false; }, hexToRgb: function(array){ var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); return (hex) ? hex.slice(1).hexToRgb(array) : false; } }); Array.extend({ rgbToHex: function(array){ if (this.length < 3) return false; if (this[3] && (this[3] == 0) && !array) return 'transparent'; var hex = []; for (var i = 0; i < 3; i++){ var bit = (this[i]-0).toString(16); hex.push((bit.length == 1) ? '0'+bit : bit); } return array ? hex : '#'+hex.join(''); }, hexToRgb: function(array){ if (this.length != 3) return false; var rgb = []; for (var i = 0; i < 3; i++){ rgb.push(parseInt((this[i].length == 1) ? this[i]+this[i] : this[i], 16)); } return array ? rgb : 'rgb('+rgb.join(',')+')'; } }); Number.extend({ toInt: function(){ return parseInt(this); }, toFloat: function(){ return parseFloat(this); } }); Function.extend({ create: function(options){ var fn = this; options = $merge({ 'bind': fn, 'event': false, 'arguments': null, 'delay': false, 'periodical': false, 'attempt': false }, options); if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments]; return function(event){ var args; if (options.event){ event = event || window.event; args = [(options.event === true) ? event : new options.event(event)]; if (options.arguments) args = args.concat(options.arguments); } else args = options.arguments || arguments; var returns = function(){ return fn.apply(options.bind, args); }; if (options.delay) return setTimeout(returns, $duration(options.delay)); if (options.periodical) return setInterval(returns, $duration(options.periodical)); if (options.attempt){ try { return returns(); } catch(err){ return err; } } return returns(); }; }, pass: function(args, bind){ return this.create({'arguments': args, 'bind': bind}); }, attempt: function(args, bind){ return this.create({'arguments': args, 'bind': bind, 'attempt': true})(); }, bind: function(bind, args){ return this.create({'bind': bind, 'arguments': args}); }, bindAsEventListener: function(bind, args){ return this.create({'bind': bind, 'event': true, 'arguments': args}); }, delay: function(delay, bind, args){ return this.create({'delay': delay, 'bind': bind, 'arguments': args})(); }, periodical: function(interval, bind, args){ return this.create({'periodical': interval, 'bind': bind, 'arguments': args})(); } }); var Element = new Class({ initialize: function(el, props){ if ($type(el) == 'string') el = document.createElement(el); el = $(el); if (!props || !el) return el; for (var prop in props){ switch(prop){ case 'styles': el.setStyles(props[prop]); break; case 'events': el.addEvents(props[prop]); break; case 'properties': el.setProperties(props[prop]); break; default: el.setProperty(prop, props[prop]); } } return el; } }); function $(el){ if (!el) return false; if (el.htmlElement) return Garbage.collect(el); if ([window, document].test(el)) return el; var type = $type(el); if (type == 'string'){ el = document.getElementById(el); type = (el) ? 'element' : false; } if (type != 'element') return false; if (['object', 'embed'].test(el.tagName.toLowerCase())) return el; $extend(el, Element.prototype); el.htmlElement = true; return Garbage.collect(el); }; //elements class var Elements = new Class({}); Elements.extend = Class.prototype.implement; document.getElementsBySelector = document.getElementsByTagName; function $$(){ if (!arguments) return false; if (arguments.length == 1 && typeof arguments[0] == 'string') return document.getElementsBySelector(arguments[0]); var elements = []; for (var i = 0, j = arguments.length; i < j; i++){ var selector = arguments[i]; switch($type(selector)){ case 'element': if (i == 0) elements = element; else elements.include(element); break; case 'string': var temp = document.getElementsBySelector(selector, true); if (i == 0) elements = temp; else elements.implement(temp); break; case 'object': if (i == 0) elements = selector; else elements.implement(selector); break; case 'array': elements.implement(selector); } var returned = []; for (var k = 0, l = elements.length; k < l; k++){ var element = $(elements[k]); if (element) returned.push(element); } } return $extend(returned, new Elements); }; Elements.Multi = function(property){ return function(){ var args = arguments; var items = []; var elements = true; for (var i = 0, j = this.length, returns; i < j; i++){ returns = this[i][property].apply(this[i], args); if ($type(returns) != 'element') elements = false; items.push(returns); }; return (elements) ? $$(items) : items; }; }; Element.extend = function(properties){ for (var property in properties){ HTMLElement.prototype[property] = properties[property]; Element.prototype[property] = properties[property]; Elements.prototype[property] = Elements.Multi(property); } }; Element.extend({ inject: function(el, where){ el = $(el); switch(where){ case "before": el.parentNode.insertBefore(this, el); break; case "after": var next = el.getNext(); if (!next) el.parentNode.appendChild(this); else el.parentNode.insertBefore(this, next); break; case "inside": el.appendChild(this); } return this; }, injectBefore: function(el){ return this.inject(el, 'before'); }, injectAfter: function(el){ return this.inject(el, 'after'); }, injectInside: function(el){ return this.inject(el, 'inside'); }, adopt: function(){ $each(arguments, function(el){ this.appendChild($(el)); }, this); return this; }, remove: function(){ this.parentNode.removeChild(this); return this; }, clone: function(contents){ return $(this.cloneNode(contents !== false)); }, replaceWith: function(el){ this.parentNode.replaceChild(el, this); return $(el); }, appendText: function(text){ if (window.ie){ switch(this.getTag()){ case 'style': this.styleSheet.cssText = text; return this; case 'script': this.setProperty('text', text); return this; } } this.appendChild(document.createTextNode(text)); return this; }, hasClass: function(className){ return this.className.test('(?:^|\\s)'+className+'(?:\\s|$)'); }, addClass: function(className){ if (!this.hasClass(className)) this.className = (this.className+' '+className).clean(); return this; }, removeClass: function(className){ this.className = this.className.replace(new RegExp('(^|\\s)'+className+'(?:\\s|$)'), '$1').clean(); return this; }, toggleClass: function(className){ return this.hasClass(className) ? this.removeClass(className) : this.addClass(className); }, setStyle: function(property, value){ switch(property){ case 'opacity': return this.setOpacity(parseFloat(value)); case 'float': property = (window.ie) ? 'styleFloat' : 'cssFloat'; } property = property.camelCase(); switch($type(value)){ case 'number': if (!['zIndex', 'zoom'].test(property)) value += 'px'; break; case 'array': value = 'rgb(' + value.join(',') + ')'; } this.style[property] = value; return this; }, setStyles: function(source){ switch($type(source)){ case 'object': for (var property in source) this.setStyle(property, source[property]); break; case 'string': this.style.cssText = source; } return this; }, setOpacity: function(opacity){ if (opacity == 0){ if (this.style.visibility != "hidden") this.style.visibility = "hidden"; } else { if (this.style.visibility != "visible") this.style.visibility = "visible"; } if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1; if (window.ie) this.style.filter = "alpha(opacity=" + opacity * 100 + ")"; this.style.opacity = this.opacity = opacity; return this; }, getStyle: function(property){ property = property.camelCase(); var style = this.style[property]; if (!$chk(style)){ if (property == 'opacity') return $chk(this.opacity) ? this.opacity : 1; if (['margin', 'padding'].test(property)){ var result = []; ['top', 'right', 'bottom', 'left'].each(function(prop){ result.push(this.getStyle(property + '-' + prop) || '0'); }, this); var every = result.every(function(val){ return val == result[0]; }); return (every) ? result[0] : result; } if (document.defaultView) style = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate()); else if (this.currentStyle) style = this.currentStyle[property]; } if (style == 'auto' && ['height', 'width'].test(property)) return this['offset'+property.capitalize()] + 'px'; return (style && property.test(/color/i) && style.test(/rgb/)) ? style.rgbToHex() : style; }, getStyles: function(){ var result = {}; $each(arguments, function(argument){ result[argument] = this.getStyle(argument); }, this); return result; }, walk: function(brother, start){ brother += 'Sibling'; var el = (start) ? this[start] : this[brother]; while (el && $type(el) != 'element') el = el[brother]; return $(el); }, getPrevious: function(){ return this.walk('previous'); }, getNext: function(){ return this.walk('next'); }, getFirst: function(){ return this.walk('next', 'firstChild'); }, getLast: function(){ return this.walk('previous', 'lastChild'); }, getParent: function(){ return $(this.parentNode); }, getChildren: function(){ return $$(this.childNodes); }, hasChild: function(el) { return ($A(this.getElementsByTagName('*')).test(el)) ? true : false; }, setProperty: function(property, value){ switch(property){ case 'class': this.className = value; break; case 'style': this.setStyles(value); break; case 'name': if (window.ie6){ var el = new Element('<' + this.getTag() + ' name="' + value + '" />'); ['value', 'id', 'className', 'style'].each(function(attribute){ el[attribute] = this[attribute]; }); if (this.parentNode) this.replaceWith(el); return el; } default: this.setAttribute(property, value); } return this; }, setProperties: function(source){ for (var property in source) this.setProperty(property, source[property]); return this; }, setHTML: function(){ this.innerHTML = $A(arguments).join(''); return this; }, getProperty: function(property){ return (property == 'class') ? this.className : this.getAttribute(property); }, getTag: function(){ return this.tagName.toLowerCase(); } }); Element.eventMethods = { addEvent: function(type, fn){ this.events = this.events || {}; this.events[type] = this.events[type] || {'keys': [], 'values': []}; if (!this.events[type].keys.test(fn)){ this.events[type].keys.push(fn); if (this.addEventListener){ this.addEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, fn, false); } else { fn = fn.bind(this); this.attachEvent('on'+type, fn); this.events[type].values.push(fn); } } return this; }, addEvents: function(source){ for (var type in source) this.addEvent(type, source[type]); return this; }, removeEvent: function(type, fn){ if (this.events && this.events[type]){ var pos = this.events[type].keys.indexOf(fn); if (pos == -1) return this; var key = this.events[type].keys.splice(pos,1)[0]; if (this.removeEventListener){ this.removeEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, key, false); } else { this.detachEvent('on'+type, this.events[type].values.splice(pos,1)[0]); } } return this; }, removeEvents: function(type){ if (this.events){ if (type){ if (this.events[type]){ this.events[type].keys.each(function(fn){ this.removeEvent(type, fn); }, this); this.events[type] = null; } } else { for (var evType in this.events) this.removeEvents(evType); this.events = null; } } return this; }, fireEvent: function(type, args){ if (this.events && this.events[type]){ this.events[type].keys.each(function(fn){ fn.bind(this, args)(); }, this); } } }; window.extend(Element.eventMethods); document.extend(Element.eventMethods); Element.extend(Element.eventMethods); var Garbage = { elements: [], collect: function(el){ if (!el.collected){ Garbage.elements.push(el); el.collected = true; } return el; }, trash: function(elements){ for (var i = 0, j = elements.length, el; i < j; i++){ if (!(el = elements[i]) || !el.collected) return; el.removeEvents(); for (var p in Element.prototype) el[p] = null; el.htmlElement = el.collected = null; } }, empty: function(){ Garbage.collect(window); Garbage.collect(document); Garbage.trash(Garbage.elements); Garbage.elements = []; } }; window.addEvent('unload', Garbage.empty); var Event = new Class({ initialize: function(event){ this.event = event || window.event; this.type = this.event.type; this.target = this.event.target || this.event.srcElement; if (this.target.nodeType == 3) this.target = this.target.parentNode; // Safari this.shift = this.event.shiftKey; this.control = this.event.ctrlKey; this.alt = this.event.altKey; this.meta = this.event.metaKey; if (['DOMMouseScroll', 'mousewheel'].test(this.type)){ this.wheel = this.event.wheelDelta ? (this.event.wheelDelta / (window.opera ? -120 : 120)) : -(this.event.detail || 0) / 3; } else if (this.type.test(/key/)){ this.code = this.event.which || this.event.keyCode; for (var name in Event.keys){ if (Event.keys[name] == this.code){ this.key = name; break; } } var fKey = this.code - 111; if (fKey > 0 && fKey < 13) this.key = 'f' + fKey; this.key = this.key || String.fromCharCode(this.code).toLowerCase(); } else if (this.type.test(/mouse/) || (this.type == 'click')){ this.page = { 'x': this.event.pageX || this.event.clientX + document.documentElement.scrollLeft, 'y': this.event.pageY || this.event.clientY + document.documentElement.scrollTop }; this.client = { 'x': this.event.pageX ? this.event.pageX - window.pageXOffset : this.event.clientX, 'y': this.event.pageY ? this.event.pageY - window.pageYOffset : this.event.clientY }; this.rightClick = (this.event.which == 3) || (this.event.button == 2); switch(this.type){ case 'mouseover': this.relatedTarget = this.event.relatedTarget || this.event.fromElement; break; case 'mouseout': this.relatedTarget = this.event.relatedTarget || this.event.toElement; } } }, stop: function() { this.stopPropagation(); this.preventDefault(); return this; }, stopPropagation: function(){ if (this.event.stopPropagation) this.event.stopPropagation(); else this.event.cancelBubble = true; return this; }, preventDefault: function(){ if (this.event.preventDefault) this.event.preventDefault(); else this.event.returnValue = false; return this; } }); Event.keys = { 'enter': 13, 'up': 38, 'down': 40, 'left': 37, 'right': 39, 'esc': 27, 'space': 32, 'backspace': 8, 'delete': 46 }; Function.extend({ bindWithEvent: function(bind, args){ return this.create({'bind': bind, 'arguments': args, 'event': Event}); } }); function $E(selector, filter){ return ($(filter) || document).getElement(selector); }; function $ES(selector, filter){ return ($(filter) || document).getElementsBySelector(selector); }; Element.domMethods = { getElements: function(selector, nocash){ var items = []; var xpath = (document.evaluate) ? true : false; selector = selector.clean().split(' '); for (var i = 0, j = selector.length; i < j; i++){ var sel = selector[i]; var param = sel.match(/^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/); if (!param) break; param[1] = (param[1]) ? param[1] : '*'; if (xpath){ var temp = this.namespaceURI ? ['xhtml:'] : []; temp.push(param[1]); if (param[2]) temp.push('[@id="', param[2], '"]'); if (param[3]) temp.push('[contains(concat(" ", @class, " "), " ', param[3], ' ")]'); if (param[4]){ if (param[5] && param[6]){ switch(param[5]){ case '*=': temp.push('[contains(@', param[4], ', "', param[6], '")]'); break; case '^=': temp.push('[starts-with(@', param[4], ', "', param[6], '")]'); break; case '$=': temp.push('[substring(@', param[4], ', string-length(@', param[4], ') - ', param[6].length, ' + 1) = "', param[6], '"]'); break; case '=': temp.push('[@', param[4], '="', param[6], '"]'); break; case '!=': temp.push('[@', param[4], '!="', param[6], '"]'); } } else temp.push('[@', param[4], ']'); } items.push(temp.join('')); continue; } Filters.selector = param; if (i == 0){ if (param[2]){ var el = this.getElementById(param[2]); if (!el || ((param[1] != '*') && (Element.prototype.getTag.call(el) != param[1]))) break; items = [el]; } else { items = $A(this.getElementsByTagName(param[1])); } } else { items = Elements.prototype.getElementsByTagName.call(items, param[1], true); if (param[2]) items = items.filter(Filters.id); } if (param[3]) items = items.filter(Filters.className); if (param[4]) items = items.filter(Filters.attribute); } if (xpath) items = this.getElementsByXpath(items.join('//')); return (nocash) ? items : $extend(items.map($), new Elements); }, getElementsByXpath: function(xp){ var result = []; var resolver = function(prefix){ return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false; }; var xpath = document.evaluate('.//' + xp, this, resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, j = xpath.snapshotLength; i < j; i++) result.push(xpath.snapshotItem(i)); return result; }, getElement: function(selector){ return this.getElementsBySelector(selector)[0]; }, getElementsBySelector: function(selector, nocash){ var elements = []; selector = selector.split(','); if (selector.length == 1) return this.getElements(selector[0], nocash); for (var i = 0, j = selector.length; i < j; i++){ var temp = this.getElements(selector[i], true); if (i == 0) elements = temp; else elements.implement(temp); } return (nocash) ? elements : $extend(elements.map($), new Elements); }, getElementsByClassName: function(className){ return this.getElements('.' + className); } }; Element.extend({ getElementById: function(id){ var el = document.getElementById(id); if (!el) return false; for (var parent = el.parentNode; parent != this; parent = parent.parentNode){ if (!parent) return false; } return el; } }); document.extend(Element.domMethods); Element.extend(Element.domMethods); //dom filters, internal methods. var Filters = { selector: [], id: function(el){ return (el.id == Filters.selector[2]); }, className: function(el){ return (Element.prototype.hasClass.call(el, Filters.selector[3])); }, attribute: function(el){ var current = Element.prototype.getProperty.call(el, Filters.selector[4]); if (!current) return false; var operator = Filters.selector[5]; if (!operator) return true; var value = Filters.selector[6]; switch(operator){ case '=': return (current == value); case '*=': return (current.test(value)); case '^=': return (current.test('^' + value)); case '$=': return (current.test(value + '$')); case '!=': return (current != value); } return false; } }; Elements.extend({ getElementsByTagName: function(tagName){ var found = []; for (var i = 0, j = this.length; i < j; i++) found.extend(this[i].getElementsByTagName(tagName)); return found; } }); Element.extend({ getValue: function(){ switch(this.getTag()){ case 'select': var values = []; $each(this.options, function(opt){ if (opt.selected) values.push($pick(opt.value, opt.text)); }); return (this.multiple) ? values : values[0]; case 'input': if (!(this.checked && ['checkbox', 'radio'].test(this.type)) && !['hidden', 'text', 'password'].test(this.type)) break; case 'textarea': return this.value; } return false; }, getFormElements: function(){ return $$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea')); }, toQueryString: function(){ var queryString = []; this.getFormElements().each(function(el){ var name = $(el).name; var value = el.getValue(); if (!el.disabled && $chk(value)){ var qs = function(val){ queryString.push(name + '=' + encodeURIComponent(val)); }; if ($type(value) == 'array') value.each(qs); else qs(value); } }); return queryString.join('&'); } }); Element.extend({ scrollTo: function(x, y){ this.scrollLeft = x; this.scrollTop = y; }, getSize: function(){ return { 'scroll': {'x': this.scrollLeft, 'y': this.scrollTop}, 'size': {'x': this.offsetWidth, 'y': this.offsetHeight}, 'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight} }; }, getPosition: function(overflown){ overflown = overflown || []; var el = this, left = 0, top = 0; do { left += el.offsetLeft || 0; top += el.offsetTop || 0; el = el.offsetParent; } while (el); overflown.each(function(element){ left -= element.scrollLeft || 0; top -= element.scrollTop || 0; }); return {'x': left, 'y': top}; }, getTop: function(){ return this.getPosition().y; }, getLeft: function(){ return this.getPosition().x; }, getCoordinates: function(overflown){ var position = this.getPosition(overflown); var obj = { 'width': this.offsetWidth, 'height': this.offsetHeight, 'left': position.x, 'top': position.y }; obj.right = obj.left + obj.width; obj.bottom = obj.top + obj.height; return obj; } }); window.extend({ addEvent: function(type, fn){ if (type == 'domready'){ if (this.loaded) fn(); else if (!this.events || !this.events.domready){ var domReady = function(){ if (this.loaded) return; this.loaded = true; if (this.timer) this.timer = $clear(this.timer); Element.prototype.fireEvent.call(this, 'domready'); this.events.domready = null; }.bind(this); if (document.readyState && this.khtml){ //safari and konqueror this.timer = function(){ if (['loaded','complete'].test(document.readyState)) domReady(); }.periodical(50); } else if (document.readyState && this.ie){ //ie document.write("