mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	
		
			
	
	
		
			1781 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			1781 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | /*  Prototype JavaScript framework, version 1.4.0 | ||
|  |  *  (c) 2005 Sam Stephenson <sam@conio.net> | ||
|  |  * | ||
|  |  *  Prototype is freely distributable under the terms of an MIT-style license. | ||
|  |  *  For details, see the Prototype web site: http://prototype.conio.net/
 | ||
|  |  * | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | var Prototype = { | ||
|  |   Version: '1.4.0', | ||
|  |   ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', | ||
|  | 
 | ||
|  |   emptyFunction: function() {}, | ||
|  |   K: function(x) {return x} | ||
|  | } | ||
|  | 
 | ||
|  | var Class = { | ||
|  |   create: function() { | ||
|  |     return function() { | ||
|  |       this.initialize.apply(this, arguments); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | var Abstract = new Object(); | ||
|  | 
 | ||
|  | Object.extend = function(destination, source) { | ||
|  |   for (property in source) { | ||
|  |     destination[property] = source[property]; | ||
|  |   } | ||
|  |   return destination; | ||
|  | } | ||
|  | 
 | ||
|  | Object.inspect = function(object) { | ||
|  |   try { | ||
|  |     if (object == undefined) return 'undefined'; | ||
|  |     if (object == null) return 'null'; | ||
|  |     return object.inspect ? object.inspect() : object.toString(); | ||
|  |   } catch (e) { | ||
|  |     if (e instanceof RangeError) return '...'; | ||
|  |     throw e; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Function.prototype.bind = function() { | ||
|  |   var __method = this, args = $A(arguments), object = args.shift(); | ||
|  |   return function() { | ||
|  |     return __method.apply(object, args.concat($A(arguments))); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Function.prototype.bindAsEventListener = function(object) { | ||
|  |   var __method = this; | ||
|  |   return function(event) { | ||
|  |     return __method.call(object, event || window.event); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Number.prototype, { | ||
|  |   toColorPart: function() { | ||
|  |     var digits = this.toString(16); | ||
|  |     if (this < 16) return '0' + digits; | ||
|  |     return digits; | ||
|  |   }, | ||
|  | 
 | ||
|  |   succ: function() { | ||
|  |     return this + 1; | ||
|  |   }, | ||
|  | 
 | ||
|  |   times: function(iterator) { | ||
|  |     $R(0, this, true).each(iterator); | ||
|  |     return this; | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | var Try = { | ||
|  |   these: function() { | ||
|  |     var returnValue; | ||
|  | 
 | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |       var lambda = arguments[i]; | ||
|  |       try { | ||
|  |         returnValue = lambda(); | ||
|  |         break; | ||
|  |       } catch (e) {} | ||
|  |     } | ||
|  | 
 | ||
|  |     return returnValue; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | var PeriodicalExecuter = Class.create(); | ||
|  | PeriodicalExecuter.prototype = { | ||
|  |   initialize: function(callback, frequency) { | ||
|  |     this.callback = callback; | ||
|  |     this.frequency = frequency; | ||
|  |     this.currentlyExecuting = false; | ||
|  | 
 | ||
|  |     this.registerCallback(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   registerCallback: function() { | ||
|  |     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); | ||
|  |   }, | ||
|  | 
 | ||
|  |   onTimerEvent: function() { | ||
|  |     if (!this.currentlyExecuting) { | ||
|  |       try { | ||
|  |         this.currentlyExecuting = true; | ||
|  |         this.callback(); | ||
|  |       } finally { | ||
|  |         this.currentlyExecuting = false; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | function $() { | ||
|  |   var elements = new Array(); | ||
|  | 
 | ||
|  |   for (var i = 0; i < arguments.length; i++) { | ||
|  |     var element = arguments[i]; | ||
|  |     if (typeof element == 'string') | ||
|  |       element = document.getElementById(element); | ||
|  | 
 | ||
|  |     if (arguments.length == 1) | ||
|  |       return element; | ||
|  | 
 | ||
|  |     elements.push(element); | ||
|  |   } | ||
|  | 
 | ||
|  |   return elements; | ||
|  | } | ||
|  | Object.extend(String.prototype, { | ||
|  |   stripTags: function() { | ||
|  |     return this.replace(/<\/?[^>]+>/gi, ''); | ||
|  |   }, | ||
|  | 
 | ||
|  |   stripScripts: function() { | ||
|  |     return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); | ||
|  |   }, | ||
|  | 
 | ||
|  |   extractScripts: function() { | ||
|  |     var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); | ||
|  |     var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); | ||
|  |     return (this.match(matchAll) || []).map(function(scriptTag) { | ||
|  |       return (scriptTag.match(matchOne) || ['', ''])[1]; | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   evalScripts: function() { | ||
|  |     return this.extractScripts().map(eval); | ||
|  |   }, | ||
|  | 
 | ||
|  |   escapeHTML: function() { | ||
|  |     var div = document.createElement('div'); | ||
|  |     var text = document.createTextNode(this); | ||
|  |     div.appendChild(text); | ||
|  |     return div.innerHTML; | ||
|  |   }, | ||
|  | 
 | ||
|  |   unescapeHTML: function() { | ||
|  |     var div = document.createElement('div'); | ||
|  |     div.innerHTML = this.stripTags(); | ||
|  |     return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; | ||
|  |   }, | ||
|  | 
 | ||
|  |   toQueryParams: function() { | ||
|  |     var pairs = this.match(/^\??(.*)$/)[1].split('&'); | ||
|  |     return pairs.inject({}, function(params, pairString) { | ||
|  |       var pair = pairString.split('='); | ||
|  |       params[pair[0]] = pair[1]; | ||
|  |       return params; | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   toArray: function() { | ||
|  |     return this.split(''); | ||
|  |   }, | ||
|  | 
 | ||
|  |   camelize: function() { | ||
|  |     var oStringList = this.split('-'); | ||
|  |     if (oStringList.length == 1) return oStringList[0]; | ||
|  | 
 | ||
|  |     var camelizedString = this.indexOf('-') == 0 | ||
|  |       ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) | ||
|  |       : oStringList[0]; | ||
|  | 
 | ||
|  |     for (var i = 1, len = oStringList.length; i < len; i++) { | ||
|  |       var s = oStringList[i]; | ||
|  |       camelizedString += s.charAt(0).toUpperCase() + s.substring(1); | ||
|  |     } | ||
|  | 
 | ||
|  |     return camelizedString; | ||
|  |   }, | ||
|  | 
 | ||
|  |   inspect: function() { | ||
|  |     return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | String.prototype.parseQuery = String.prototype.toQueryParams; | ||
|  | 
 | ||
|  | var $break    = new Object(); | ||
|  | var $continue = new Object(); | ||
|  | 
 | ||
|  | var Enumerable = { | ||
|  |   each: function(iterator) { | ||
|  |     var index = 0; | ||
|  |     try { | ||
|  |       this._each(function(value) { | ||
|  |         try { | ||
|  |           iterator(value, index++); | ||
|  |         } catch (e) { | ||
|  |           if (e != $continue) throw e; | ||
|  |         } | ||
|  |       }); | ||
|  |     } catch (e) { | ||
|  |       if (e != $break) throw e; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   all: function(iterator) { | ||
|  |     var result = true; | ||
|  |     this.each(function(value, index) { | ||
|  |       result = result && !!(iterator || Prototype.K)(value, index); | ||
|  |       if (!result) throw $break; | ||
|  |     }); | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   any: function(iterator) { | ||
|  |     var result = true; | ||
|  |     this.each(function(value, index) { | ||
|  |       if (result = !!(iterator || Prototype.K)(value, index)) | ||
|  |         throw $break; | ||
|  |     }); | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   collect: function(iterator) { | ||
|  |     var results = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       results.push(iterator(value, index)); | ||
|  |     }); | ||
|  |     return results; | ||
|  |   }, | ||
|  | 
 | ||
|  |   detect: function (iterator) { | ||
|  |     var result; | ||
|  |     this.each(function(value, index) { | ||
|  |       if (iterator(value, index)) { | ||
|  |         result = value; | ||
|  |         throw $break; | ||
|  |       } | ||
|  |     }); | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   findAll: function(iterator) { | ||
|  |     var results = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       if (iterator(value, index)) | ||
|  |         results.push(value); | ||
|  |     }); | ||
|  |     return results; | ||
|  |   }, | ||
|  | 
 | ||
|  |   grep: function(pattern, iterator) { | ||
|  |     var results = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       var stringValue = value.toString(); | ||
|  |       if (stringValue.match(pattern)) | ||
|  |         results.push((iterator || Prototype.K)(value, index)); | ||
|  |     }) | ||
|  |     return results; | ||
|  |   }, | ||
|  | 
 | ||
|  |   include: function(object) { | ||
|  |     var found = false; | ||
|  |     this.each(function(value) { | ||
|  |       if (value == object) { | ||
|  |         found = true; | ||
|  |         throw $break; | ||
|  |       } | ||
|  |     }); | ||
|  |     return found; | ||
|  |   }, | ||
|  | 
 | ||
|  |   inject: function(memo, iterator) { | ||
|  |     this.each(function(value, index) { | ||
|  |       memo = iterator(memo, value, index); | ||
|  |     }); | ||
|  |     return memo; | ||
|  |   }, | ||
|  | 
 | ||
|  |   invoke: function(method) { | ||
|  |     var args = $A(arguments).slice(1); | ||
|  |     return this.collect(function(value) { | ||
|  |       return value[method].apply(value, args); | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   max: function(iterator) { | ||
|  |     var result; | ||
|  |     this.each(function(value, index) { | ||
|  |       value = (iterator || Prototype.K)(value, index); | ||
|  |       if (value >= (result || value)) | ||
|  |         result = value; | ||
|  |     }); | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   min: function(iterator) { | ||
|  |     var result; | ||
|  |     this.each(function(value, index) { | ||
|  |       value = (iterator || Prototype.K)(value, index); | ||
|  |       if (value <= (result || value)) | ||
|  |         result = value; | ||
|  |     }); | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   partition: function(iterator) { | ||
|  |     var trues = [], falses = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       ((iterator || Prototype.K)(value, index) ? | ||
|  |         trues : falses).push(value); | ||
|  |     }); | ||
|  |     return [trues, falses]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   pluck: function(property) { | ||
|  |     var results = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       results.push(value[property]); | ||
|  |     }); | ||
|  |     return results; | ||
|  |   }, | ||
|  | 
 | ||
|  |   reject: function(iterator) { | ||
|  |     var results = []; | ||
|  |     this.each(function(value, index) { | ||
|  |       if (!iterator(value, index)) | ||
|  |         results.push(value); | ||
|  |     }); | ||
|  |     return results; | ||
|  |   }, | ||
|  | 
 | ||
|  |   sortBy: function(iterator) { | ||
|  |     return this.collect(function(value, index) { | ||
|  |       return {value: value, criteria: iterator(value, index)}; | ||
|  |     }).sort(function(left, right) { | ||
|  |       var a = left.criteria, b = right.criteria; | ||
|  |       return a < b ? -1 : a > b ? 1 : 0; | ||
|  |     }).pluck('value'); | ||
|  |   }, | ||
|  | 
 | ||
|  |   toArray: function() { | ||
|  |     return this.collect(Prototype.K); | ||
|  |   }, | ||
|  | 
 | ||
|  |   zip: function() { | ||
|  |     var iterator = Prototype.K, args = $A(arguments); | ||
|  |     if (typeof args.last() == 'function') | ||
|  |       iterator = args.pop(); | ||
|  | 
 | ||
|  |     var collections = [this].concat(args).map($A); | ||
|  |     return this.map(function(value, index) { | ||
|  |       iterator(value = collections.pluck(index)); | ||
|  |       return value; | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   inspect: function() { | ||
|  |     return '#<Enumerable:' + this.toArray().inspect() + '>'; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Enumerable, { | ||
|  |   map:     Enumerable.collect, | ||
|  |   find:    Enumerable.detect, | ||
|  |   select:  Enumerable.findAll, | ||
|  |   member:  Enumerable.include, | ||
|  |   entries: Enumerable.toArray | ||
|  | }); | ||
|  | var $A = Array.from = function(iterable) { | ||
|  |   if (!iterable) return []; | ||
|  |   if (iterable.toArray) { | ||
|  |     return iterable.toArray(); | ||
|  |   } else { | ||
|  |     var results = []; | ||
|  |     for (var i = 0; i < iterable.length; i++) | ||
|  |       results.push(iterable[i]); | ||
|  |     return results; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Array.prototype, Enumerable); | ||
|  | 
 | ||
|  | Array.prototype._reverse = Array.prototype.reverse; | ||
|  | 
 | ||
|  | Object.extend(Array.prototype, { | ||
|  |   _each: function(iterator) { | ||
|  |     for (var i = 0; i < this.length; i++) | ||
|  |       iterator(this[i]); | ||
|  |   }, | ||
|  | 
 | ||
|  |   clear: function() { | ||
|  |     this.length = 0; | ||
|  |     return this; | ||
|  |   }, | ||
|  | 
 | ||
|  |   first: function() { | ||
|  |     return this[0]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   last: function() { | ||
|  |     return this[this.length - 1]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   compact: function() { | ||
|  |     return this.select(function(value) { | ||
|  |       return value != undefined || value != null; | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   flatten: function() { | ||
|  |     return this.inject([], function(array, value) { | ||
|  |       return array.concat(value.constructor == Array ? | ||
|  |         value.flatten() : [value]); | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   without: function() { | ||
|  |     var values = $A(arguments); | ||
|  |     return this.select(function(value) { | ||
|  |       return !values.include(value); | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   indexOf: function(object) { | ||
|  |     for (var i = 0; i < this.length; i++) | ||
|  |       if (this[i] == object) return i; | ||
|  |     return -1; | ||
|  |   }, | ||
|  | 
 | ||
|  |   reverse: function(inline) { | ||
|  |     return (inline !== false ? this : this.toArray())._reverse(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   shift: function() { | ||
|  |     var result = this[0]; | ||
|  |     for (var i = 0; i < this.length - 1; i++) | ||
|  |       this[i] = this[i + 1]; | ||
|  |     this.length--; | ||
|  |     return result; | ||
|  |   }, | ||
|  | 
 | ||
|  |   inspect: function() { | ||
|  |     return '[' + this.map(Object.inspect).join(', ') + ']'; | ||
|  |   } | ||
|  | }); | ||
|  | var Hash = { | ||
|  |   _each: function(iterator) { | ||
|  |     for (key in this) { | ||
|  |       var value = this[key]; | ||
|  |       if (typeof value == 'function') continue; | ||
|  | 
 | ||
|  |       var pair = [key, value]; | ||
|  |       pair.key = key; | ||
|  |       pair.value = value; | ||
|  |       iterator(pair); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   keys: function() { | ||
|  |     return this.pluck('key'); | ||
|  |   }, | ||
|  | 
 | ||
|  |   values: function() { | ||
|  |     return this.pluck('value'); | ||
|  |   }, | ||
|  | 
 | ||
|  |   merge: function(hash) { | ||
|  |     return $H(hash).inject($H(this), function(mergedHash, pair) { | ||
|  |       mergedHash[pair.key] = pair.value; | ||
|  |       return mergedHash; | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   toQueryString: function() { | ||
|  |     return this.map(function(pair) { | ||
|  |       return pair.map(encodeURIComponent).join('='); | ||
|  |     }).join('&'); | ||
|  |   }, | ||
|  | 
 | ||
|  |   inspect: function() { | ||
|  |     return '#<Hash:{' + this.map(function(pair) { | ||
|  |       return pair.map(Object.inspect).join(': '); | ||
|  |     }).join(', ') + '}>'; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function $H(object) { | ||
|  |   var hash = Object.extend({}, object || {}); | ||
|  |   Object.extend(hash, Enumerable); | ||
|  |   Object.extend(hash, Hash); | ||
|  |   return hash; | ||
|  | } | ||
|  | ObjectRange = Class.create(); | ||
|  | Object.extend(ObjectRange.prototype, Enumerable); | ||
|  | Object.extend(ObjectRange.prototype, { | ||
|  |   initialize: function(start, end, exclusive) { | ||
|  |     this.start = start; | ||
|  |     this.end = end; | ||
|  |     this.exclusive = exclusive; | ||
|  |   }, | ||
|  | 
 | ||
|  |   _each: function(iterator) { | ||
|  |     var value = this.start; | ||
|  |     do { | ||
|  |       iterator(value); | ||
|  |       value = value.succ(); | ||
|  |     } while (this.include(value)); | ||
|  |   }, | ||
|  | 
 | ||
|  |   include: function(value) { | ||
|  |     if (value < this.start) | ||
|  |       return false; | ||
|  |     if (this.exclusive) | ||
|  |       return value < this.end; | ||
|  |     return value <= this.end; | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | var $R = function(start, end, exclusive) { | ||
|  |   return new ObjectRange(start, end, exclusive); | ||
|  | } | ||
|  | 
 | ||
|  | var Ajax = { | ||
|  |   getTransport: function() { | ||
|  |     return Try.these( | ||
|  |       function() {return new ActiveXObject('Msxml2.XMLHTTP')}, | ||
|  |       function() {return new ActiveXObject('Microsoft.XMLHTTP')}, | ||
|  |       function() {return new XMLHttpRequest()} | ||
|  |     ) || false; | ||
|  |   }, | ||
|  | 
 | ||
|  |   activeRequestCount: 0 | ||
|  | } | ||
|  | 
 | ||
|  | Ajax.Responders = { | ||
|  |   responders: [], | ||
|  | 
 | ||
|  |   _each: function(iterator) { | ||
|  |     this.responders._each(iterator); | ||
|  |   }, | ||
|  | 
 | ||
|  |   register: function(responderToAdd) { | ||
|  |     if (!this.include(responderToAdd)) | ||
|  |       this.responders.push(responderToAdd); | ||
|  |   }, | ||
|  | 
 | ||
|  |   unregister: function(responderToRemove) { | ||
|  |     this.responders = this.responders.without(responderToRemove); | ||
|  |   }, | ||
|  | 
 | ||
|  |   dispatch: function(callback, request, transport, json) { | ||
|  |     this.each(function(responder) { | ||
|  |       if (responder[callback] && typeof responder[callback] == 'function') { | ||
|  |         try { | ||
|  |           responder[callback].apply(responder, [request, transport, json]); | ||
|  |         } catch (e) {} | ||
|  |       } | ||
|  |     }); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | Object.extend(Ajax.Responders, Enumerable); | ||
|  | 
 | ||
|  | Ajax.Responders.register({ | ||
|  |   onCreate: function() { | ||
|  |     Ajax.activeRequestCount++; | ||
|  |   }, | ||
|  | 
 | ||
|  |   onComplete: function() { | ||
|  |     Ajax.activeRequestCount--; | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Ajax.Base = function() {}; | ||
|  | Ajax.Base.prototype = { | ||
|  |   setOptions: function(options) { | ||
|  |     this.options = { | ||
|  |       method:       'post', | ||
|  |       asynchronous: true, | ||
|  |       parameters:   '' | ||
|  |     } | ||
|  |     Object.extend(this.options, options || {}); | ||
|  |   }, | ||
|  | 
 | ||
|  |   responseIsSuccess: function() { | ||
|  |     return this.transport.status == undefined | ||
|  |         || this.transport.status == 0 | ||
|  |         || (this.transport.status >= 200 && this.transport.status < 300); | ||
|  |   }, | ||
|  | 
 | ||
|  |   responseIsFailure: function() { | ||
|  |     return !this.responseIsSuccess(); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Ajax.Request = Class.create(); | ||
|  | Ajax.Request.Events = | ||
|  |   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; | ||
|  | 
 | ||
|  | Ajax.Request.prototype = Object.extend(new Ajax.Base(), { | ||
|  |   initialize: function(url, options) { | ||
|  |     this.transport = Ajax.getTransport(); | ||
|  |     this.setOptions(options); | ||
|  |     this.request(url); | ||
|  |   }, | ||
|  | 
 | ||
|  |   request: function(url) { | ||
|  |     var parameters = this.options.parameters || ''; | ||
|  |     if (parameters.length > 0) parameters += '&_='; | ||
|  | 
 | ||
|  |     try { | ||
|  |       this.url = url; | ||
|  |       if (this.options.method == 'get' && parameters.length > 0) | ||
|  |         this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; | ||
|  | 
 | ||
|  |       Ajax.Responders.dispatch('onCreate', this, this.transport); | ||
|  | 
 | ||
|  |       this.transport.open(this.options.method, this.url, | ||
|  |         this.options.asynchronous); | ||
|  | 
 | ||
|  |       if (this.options.asynchronous) { | ||
|  |         this.transport.onreadystatechange = this.onStateChange.bind(this); | ||
|  |         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); | ||
|  |       } | ||
|  | 
 | ||
|  |       this.setRequestHeaders(); | ||
|  | 
 | ||
|  |       var body = this.options.postBody ? this.options.postBody : parameters; | ||
|  |       this.transport.send(this.options.method == 'post' ? body : null); | ||
|  | 
 | ||
|  |     } catch (e) { | ||
|  |       this.dispatchException(e); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   setRequestHeaders: function() { | ||
|  |     var requestHeaders = | ||
|  |       ['X-Requested-With', 'XMLHttpRequest', | ||
|  |        'X-Prototype-Version', Prototype.Version]; | ||
|  | 
 | ||
|  |     if (this.options.method == 'post') { | ||
|  |       requestHeaders.push('Content-type', | ||
|  |         'application/x-www-form-urlencoded'); | ||
|  | 
 | ||
|  |       /* Force "Connection: close" for Mozilla browsers to work around | ||
|  |        * a bug where XMLHttpReqeuest sends an incorrect Content-length | ||
|  |        * header. See Mozilla Bugzilla #246651. | ||
|  |        */ | ||
|  |       if (this.transport.overrideMimeType) | ||
|  |         requestHeaders.push('Connection', 'close'); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.options.requestHeaders) | ||
|  |       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); | ||
|  | 
 | ||
|  |     for (var i = 0; i < requestHeaders.length; i += 2) | ||
|  |       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); | ||
|  |   }, | ||
|  | 
 | ||
|  |   onStateChange: function() { | ||
|  |     var readyState = this.transport.readyState; | ||
|  |     if (readyState != 1) | ||
|  |       this.respondToReadyState(this.transport.readyState); | ||
|  |   }, | ||
|  | 
 | ||
|  |   header: function(name) { | ||
|  |     try { | ||
|  |       return this.transport.getResponseHeader(name); | ||
|  |     } catch (e) {} | ||
|  |   }, | ||
|  | 
 | ||
|  |   evalJSON: function() { | ||
|  |     try { | ||
|  |       return eval(this.header('X-JSON')); | ||
|  |     } catch (e) {} | ||
|  |   }, | ||
|  | 
 | ||
|  |   evalResponse: function() { | ||
|  |     try { | ||
|  |       return eval(this.transport.responseText); | ||
|  |     } catch (e) { | ||
|  |       this.dispatchException(e); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   respondToReadyState: function(readyState) { | ||
|  |     var event = Ajax.Request.Events[readyState]; | ||
|  |     var transport = this.transport, json = this.evalJSON(); | ||
|  | 
 | ||
|  |     if (event == 'Complete') { | ||
|  |       try { | ||
|  |         (this.options['on' + this.transport.status] | ||
|  |          || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] | ||
|  |          || Prototype.emptyFunction)(transport, json); | ||
|  |       } catch (e) { | ||
|  |         this.dispatchException(e); | ||
|  |       } | ||
|  | 
 | ||
|  |       if ((this.header('Content-type') || '').match(/^text\/javascript/i)) | ||
|  |         this.evalResponse(); | ||
|  |     } | ||
|  | 
 | ||
|  |     try { | ||
|  |       (this.options['on' + event] || Prototype.emptyFunction)(transport, json); | ||
|  |       Ajax.Responders.dispatch('on' + event, this, transport, json); | ||
|  |     } catch (e) { | ||
|  |       this.dispatchException(e); | ||
|  |     } | ||
|  | 
 | ||
|  |     /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ | ||
|  |     if (event == 'Complete') | ||
|  |       this.transport.onreadystatechange = Prototype.emptyFunction; | ||
|  |   }, | ||
|  | 
 | ||
|  |   dispatchException: function(exception) { | ||
|  |     (this.options.onException || Prototype.emptyFunction)(this, exception); | ||
|  |     Ajax.Responders.dispatch('onException', this, exception); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Ajax.Updater = Class.create(); | ||
|  | 
 | ||
|  | Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { | ||
|  |   initialize: function(container, url, options) { | ||
|  |     this.containers = { | ||
|  |       success: container.success ? $(container.success) : $(container), | ||
|  |       failure: container.failure ? $(container.failure) : | ||
|  |         (container.success ? null : $(container)) | ||
|  |     } | ||
|  | 
 | ||
|  |     this.transport = Ajax.getTransport(); | ||
|  |     this.setOptions(options); | ||
|  | 
 | ||
|  |     var onComplete = this.options.onComplete || Prototype.emptyFunction; | ||
|  |     this.options.onComplete = (function(transport, object) { | ||
|  |       this.updateContent(); | ||
|  |       onComplete(transport, object); | ||
|  |     }).bind(this); | ||
|  | 
 | ||
|  |     this.request(url); | ||
|  |   }, | ||
|  | 
 | ||
|  |   updateContent: function() { | ||
|  |     var receiver = this.responseIsSuccess() ? | ||
|  |       this.containers.success : this.containers.failure; | ||
|  |     var response = this.transport.responseText; | ||
|  | 
 | ||
|  |     if (!this.options.evalScripts) | ||
|  |       response = response.stripScripts(); | ||
|  | 
 | ||
|  |     if (receiver) { | ||
|  |       if (this.options.insertion) { | ||
|  |         new this.options.insertion(receiver, response); | ||
|  |       } else { | ||
|  |         Element.update(receiver, response); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (this.responseIsSuccess()) { | ||
|  |       if (this.onComplete) | ||
|  |         setTimeout(this.onComplete.bind(this), 10); | ||
|  |     } | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Ajax.PeriodicalUpdater = Class.create(); | ||
|  | Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { | ||
|  |   initialize: function(container, url, options) { | ||
|  |     this.setOptions(options); | ||
|  |     this.onComplete = this.options.onComplete; | ||
|  | 
 | ||
|  |     this.frequency = (this.options.frequency || 2); | ||
|  |     this.decay = (this.options.decay || 1); | ||
|  | 
 | ||
|  |     this.updater = {}; | ||
|  |     this.container = container; | ||
|  |     this.url = url; | ||
|  | 
 | ||
|  |     this.start(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   start: function() { | ||
|  |     this.options.onComplete = this.updateComplete.bind(this); | ||
|  |     this.onTimerEvent(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   stop: function() { | ||
|  |     this.updater.onComplete = undefined; | ||
|  |     clearTimeout(this.timer); | ||
|  |     (this.onComplete || Prototype.emptyFunction).apply(this, arguments); | ||
|  |   }, | ||
|  | 
 | ||
|  |   updateComplete: function(request) { | ||
|  |     if (this.options.decay) { | ||
|  |       this.decay = (request.responseText == this.lastText ? | ||
|  |         this.decay * this.options.decay : 1); | ||
|  | 
 | ||
|  |       this.lastText = request.responseText; | ||
|  |     } | ||
|  |     this.timer = setTimeout(this.onTimerEvent.bind(this), | ||
|  |       this.decay * this.frequency * 1000); | ||
|  |   }, | ||
|  | 
 | ||
|  |   onTimerEvent: function() { | ||
|  |     this.updater = new Ajax.Updater(this.container, this.url, this.options); | ||
|  |   } | ||
|  | }); | ||
|  | document.getElementsByClassName = function(className, parentElement) { | ||
|  |   var children = ($(parentElement) || document.body).getElementsByTagName('*'); | ||
|  |   return $A(children).inject([], function(elements, child) { | ||
|  |     if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) | ||
|  |       elements.push(child); | ||
|  |     return elements; | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | if (!window.Element) { | ||
|  |   var Element = new Object(); | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Element, { | ||
|  |   visible: function(element) { | ||
|  |     return $(element).style.display != 'none'; | ||
|  |   }, | ||
|  | 
 | ||
|  |   toggle: function() { | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |       var element = $(arguments[i]); | ||
|  |       Element[Element.visible(element) ? 'hide' : 'show'](element); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   hide: function() { | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |       var element = $(arguments[i]); | ||
|  |       element.style.display = 'none'; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   show: function() { | ||
|  |     for (var i = 0; i < arguments.length; i++) { | ||
|  |       var element = $(arguments[i]); | ||
|  |       element.style.display = ''; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   remove: function(element) { | ||
|  |     element = $(element); | ||
|  |     element.parentNode.removeChild(element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   update: function(element, html) { | ||
|  |     $(element).innerHTML = html.stripScripts(); | ||
|  |     setTimeout(function() {html.evalScripts()}, 10); | ||
|  |   }, | ||
|  | 
 | ||
|  |   getHeight: function(element) { | ||
|  |     element = $(element); | ||
|  |     return element.offsetHeight; | ||
|  |   }, | ||
|  | 
 | ||
|  |   classNames: function(element) { | ||
|  |     return new Element.ClassNames(element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   hasClassName: function(element, className) { | ||
|  |     if (!(element = $(element))) return; | ||
|  |     return Element.classNames(element).include(className); | ||
|  |   }, | ||
|  | 
 | ||
|  |   addClassName: function(element, className) { | ||
|  |     if (!(element = $(element))) return; | ||
|  |     return Element.classNames(element).add(className); | ||
|  |   }, | ||
|  | 
 | ||
|  |   removeClassName: function(element, className) { | ||
|  |     if (!(element = $(element))) return; | ||
|  |     return Element.classNames(element).remove(className); | ||
|  |   }, | ||
|  | 
 | ||
|  |   // removes whitespace-only text node children
 | ||
|  |   cleanWhitespace: function(element) { | ||
|  |     element = $(element); | ||
|  |     for (var i = 0; i < element.childNodes.length; i++) { | ||
|  |       var node = element.childNodes[i]; | ||
|  |       if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) | ||
|  |         Element.remove(node); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   empty: function(element) { | ||
|  |     return $(element).innerHTML.match(/^\s*$/); | ||
|  |   }, | ||
|  | 
 | ||
|  |   scrollTo: function(element) { | ||
|  |     element = $(element); | ||
|  |     var x = element.x ? element.x : element.offsetLeft, | ||
|  |         y = element.y ? element.y : element.offsetTop; | ||
|  |     window.scrollTo(x, y); | ||
|  |   }, | ||
|  | 
 | ||
|  |   getStyle: function(element, style) { | ||
|  |     element = $(element); | ||
|  |     var value = element.style[style.camelize()]; | ||
|  |     if (!value) { | ||
|  |       if (document.defaultView && document.defaultView.getComputedStyle) { | ||
|  |         var css = document.defaultView.getComputedStyle(element, null); | ||
|  |         value = css ? css.getPropertyValue(style) : null; | ||
|  |       } else if (element.currentStyle) { | ||
|  |         value = element.currentStyle[style.camelize()]; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) | ||
|  |       if (Element.getStyle(element, 'position') == 'static') value = 'auto'; | ||
|  | 
 | ||
|  |     return value == 'auto' ? null : value; | ||
|  |   }, | ||
|  | 
 | ||
|  |   setStyle: function(element, style) { | ||
|  |     element = $(element); | ||
|  |     for (name in style) | ||
|  |       element.style[name.camelize()] = style[name]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   getDimensions: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (Element.getStyle(element, 'display') != 'none') | ||
|  |       return {width: element.offsetWidth, height: element.offsetHeight}; | ||
|  | 
 | ||
|  |     // All *Width and *Height properties give 0 on elements with display none,
 | ||
|  |     // so enable the element temporarily
 | ||
|  |     var els = element.style; | ||
|  |     var originalVisibility = els.visibility; | ||
|  |     var originalPosition = els.position; | ||
|  |     els.visibility = 'hidden'; | ||
|  |     els.position = 'absolute'; | ||
|  |     els.display = ''; | ||
|  |     var originalWidth = element.clientWidth; | ||
|  |     var originalHeight = element.clientHeight; | ||
|  |     els.display = 'none'; | ||
|  |     els.position = originalPosition; | ||
|  |     els.visibility = originalVisibility; | ||
|  |     return {width: originalWidth, height: originalHeight}; | ||
|  |   }, | ||
|  | 
 | ||
|  |   makePositioned: function(element) { | ||
|  |     element = $(element); | ||
|  |     var pos = Element.getStyle(element, 'position'); | ||
|  |     if (pos == 'static' || !pos) { | ||
|  |       element._madePositioned = true; | ||
|  |       element.style.position = 'relative'; | ||
|  |       // Opera returns the offset relative to the positioning context, when an
 | ||
|  |       // element is position relative but top and left have not been defined
 | ||
|  |       if (window.opera) { | ||
|  |         element.style.top = 0; | ||
|  |         element.style.left = 0; | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   undoPositioned: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (element._madePositioned) { | ||
|  |       element._madePositioned = undefined; | ||
|  |       element.style.position = | ||
|  |         element.style.top = | ||
|  |         element.style.left = | ||
|  |         element.style.bottom = | ||
|  |         element.style.right = ''; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   makeClipping: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (element._overflow) return; | ||
|  |     element._overflow = element.style.overflow; | ||
|  |     if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') | ||
|  |       element.style.overflow = 'hidden'; | ||
|  |   }, | ||
|  | 
 | ||
|  |   undoClipping: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (element._overflow) return; | ||
|  |     element.style.overflow = element._overflow; | ||
|  |     element._overflow = undefined; | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | var Toggle = new Object(); | ||
|  | Toggle.display = Element.toggle; | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | Abstract.Insertion = function(adjacency) { | ||
|  |   this.adjacency = adjacency; | ||
|  | } | ||
|  | 
 | ||
|  | Abstract.Insertion.prototype = { | ||
|  |   initialize: function(element, content) { | ||
|  |     this.element = $(element); | ||
|  |     this.content = content.stripScripts(); | ||
|  | 
 | ||
|  |     if (this.adjacency && this.element.insertAdjacentHTML) { | ||
|  |       try { | ||
|  |         this.element.insertAdjacentHTML(this.adjacency, this.content); | ||
|  |       } catch (e) { | ||
|  |         if (this.element.tagName.toLowerCase() == 'tbody') { | ||
|  |           this.insertContent(this.contentFromAnonymousTable()); | ||
|  |         } else { | ||
|  |           throw e; | ||
|  |         } | ||
|  |       } | ||
|  |     } else { | ||
|  |       this.range = this.element.ownerDocument.createRange(); | ||
|  |       if (this.initializeRange) this.initializeRange(); | ||
|  |       this.insertContent([this.range.createContextualFragment(this.content)]); | ||
|  |     } | ||
|  | 
 | ||
|  |     setTimeout(function() {content.evalScripts()}, 10); | ||
|  |   }, | ||
|  | 
 | ||
|  |   contentFromAnonymousTable: function() { | ||
|  |     var div = document.createElement('div'); | ||
|  |     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; | ||
|  |     return $A(div.childNodes[0].childNodes[0].childNodes); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | var Insertion = new Object(); | ||
|  | 
 | ||
|  | Insertion.Before = Class.create(); | ||
|  | Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { | ||
|  |   initializeRange: function() { | ||
|  |     this.range.setStartBefore(this.element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   insertContent: function(fragments) { | ||
|  |     fragments.each((function(fragment) { | ||
|  |       this.element.parentNode.insertBefore(fragment, this.element); | ||
|  |     }).bind(this)); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Insertion.Top = Class.create(); | ||
|  | Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { | ||
|  |   initializeRange: function() { | ||
|  |     this.range.selectNodeContents(this.element); | ||
|  |     this.range.collapse(true); | ||
|  |   }, | ||
|  | 
 | ||
|  |   insertContent: function(fragments) { | ||
|  |     fragments.reverse(false).each((function(fragment) { | ||
|  |       this.element.insertBefore(fragment, this.element.firstChild); | ||
|  |     }).bind(this)); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Insertion.Bottom = Class.create(); | ||
|  | Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { | ||
|  |   initializeRange: function() { | ||
|  |     this.range.selectNodeContents(this.element); | ||
|  |     this.range.collapse(this.element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   insertContent: function(fragments) { | ||
|  |     fragments.each((function(fragment) { | ||
|  |       this.element.appendChild(fragment); | ||
|  |     }).bind(this)); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Insertion.After = Class.create(); | ||
|  | Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { | ||
|  |   initializeRange: function() { | ||
|  |     this.range.setStartAfter(this.element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   insertContent: function(fragments) { | ||
|  |     fragments.each((function(fragment) { | ||
|  |       this.element.parentNode.insertBefore(fragment, | ||
|  |         this.element.nextSibling); | ||
|  |     }).bind(this)); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | Element.ClassNames = Class.create(); | ||
|  | Element.ClassNames.prototype = { | ||
|  |   initialize: function(element) { | ||
|  |     this.element = $(element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   _each: function(iterator) { | ||
|  |     this.element.className.split(/\s+/).select(function(name) { | ||
|  |       return name.length > 0; | ||
|  |     })._each(iterator); | ||
|  |   }, | ||
|  | 
 | ||
|  |   set: function(className) { | ||
|  |     this.element.className = className; | ||
|  |   }, | ||
|  | 
 | ||
|  |   add: function(classNameToAdd) { | ||
|  |     if (this.include(classNameToAdd)) return; | ||
|  |     this.set(this.toArray().concat(classNameToAdd).join(' ')); | ||
|  |   }, | ||
|  | 
 | ||
|  |   remove: function(classNameToRemove) { | ||
|  |     if (!this.include(classNameToRemove)) return; | ||
|  |     this.set(this.select(function(className) { | ||
|  |       return className != classNameToRemove; | ||
|  |     }).join(' ')); | ||
|  |   }, | ||
|  | 
 | ||
|  |   toString: function() { | ||
|  |     return this.toArray().join(' '); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Element.ClassNames.prototype, Enumerable); | ||
|  | var Field = { | ||
|  |   clear: function() { | ||
|  |     for (var i = 0; i < arguments.length; i++) | ||
|  |       $(arguments[i]).value = ''; | ||
|  |   }, | ||
|  | 
 | ||
|  |   focus: function(element) { | ||
|  |     $(element).focus(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   present: function() { | ||
|  |     for (var i = 0; i < arguments.length; i++) | ||
|  |       if ($(arguments[i]).value == '') return false; | ||
|  |     return true; | ||
|  |   }, | ||
|  | 
 | ||
|  |   select: function(element) { | ||
|  |     $(element).select(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   activate: function(element) { | ||
|  |     element = $(element); | ||
|  |     element.focus(); | ||
|  |     if (element.select) | ||
|  |       element.select(); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | var Form = { | ||
|  |   serialize: function(form) { | ||
|  |     var elements = Form.getElements($(form)); | ||
|  |     var queryComponents = new Array(); | ||
|  | 
 | ||
|  |     for (var i = 0; i < elements.length; i++) { | ||
|  |       var queryComponent = Form.Element.serialize(elements[i]); | ||
|  |       if (queryComponent) | ||
|  |         queryComponents.push(queryComponent); | ||
|  |     } | ||
|  | 
 | ||
|  |     return queryComponents.join('&'); | ||
|  |   }, | ||
|  | 
 | ||
|  |   getElements: function(form) { | ||
|  |     form = $(form); | ||
|  |     var elements = new Array(); | ||
|  | 
 | ||
|  |     for (tagName in Form.Element.Serializers) { | ||
|  |       var tagElements = form.getElementsByTagName(tagName); | ||
|  |       for (var j = 0; j < tagElements.length; j++) | ||
|  |         elements.push(tagElements[j]); | ||
|  |     } | ||
|  |     return elements; | ||
|  |   }, | ||
|  | 
 | ||
|  |   getInputs: function(form, typeName, name) { | ||
|  |     form = $(form); | ||
|  |     var inputs = form.getElementsByTagName('input'); | ||
|  | 
 | ||
|  |     if (!typeName && !name) | ||
|  |       return inputs; | ||
|  | 
 | ||
|  |     var matchingInputs = new Array(); | ||
|  |     for (var i = 0; i < inputs.length; i++) { | ||
|  |       var input = inputs[i]; | ||
|  |       if ((typeName && input.type != typeName) || | ||
|  |           (name && input.name != name)) | ||
|  |         continue; | ||
|  |       matchingInputs.push(input); | ||
|  |     } | ||
|  | 
 | ||
|  |     return matchingInputs; | ||
|  |   }, | ||
|  | 
 | ||
|  |   disable: function(form) { | ||
|  |     var elements = Form.getElements(form); | ||
|  |     for (var i = 0; i < elements.length; i++) { | ||
|  |       var element = elements[i]; | ||
|  |       element.blur(); | ||
|  |       element.disabled = 'true'; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   enable: function(form) { | ||
|  |     var elements = Form.getElements(form); | ||
|  |     for (var i = 0; i < elements.length; i++) { | ||
|  |       var element = elements[i]; | ||
|  |       element.disabled = ''; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   findFirstElement: function(form) { | ||
|  |     return Form.getElements(form).find(function(element) { | ||
|  |       return element.type != 'hidden' && !element.disabled && | ||
|  |         ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); | ||
|  |     }); | ||
|  |   }, | ||
|  | 
 | ||
|  |   focusFirstElement: function(form) { | ||
|  |     Field.activate(Form.findFirstElement(form)); | ||
|  |   }, | ||
|  | 
 | ||
|  |   reset: function(form) { | ||
|  |     $(form).reset(); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Form.Element = { | ||
|  |   serialize: function(element) { | ||
|  |     element = $(element); | ||
|  |     var method = element.tagName.toLowerCase(); | ||
|  |     var parameter = Form.Element.Serializers[method](element); | ||
|  | 
 | ||
|  |     if (parameter) { | ||
|  |       var key = encodeURIComponent(parameter[0]); | ||
|  |       if (key.length == 0) return; | ||
|  | 
 | ||
|  |       if (parameter[1].constructor != Array) | ||
|  |         parameter[1] = [parameter[1]]; | ||
|  | 
 | ||
|  |       return parameter[1].map(function(value) { | ||
|  |         return key + '=' + encodeURIComponent(value); | ||
|  |       }).join('&'); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   getValue: function(element) { | ||
|  |     element = $(element); | ||
|  |     var method = element.tagName.toLowerCase(); | ||
|  |     var parameter = Form.Element.Serializers[method](element); | ||
|  | 
 | ||
|  |     if (parameter) | ||
|  |       return parameter[1]; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Form.Element.Serializers = { | ||
|  |   input: function(element) { | ||
|  |     switch (element.type.toLowerCase()) { | ||
|  |       case 'submit': | ||
|  |       case 'hidden': | ||
|  |       case 'password': | ||
|  |       case 'text': | ||
|  |         return Form.Element.Serializers.textarea(element); | ||
|  |       case 'checkbox': | ||
|  |       case 'radio': | ||
|  |         return Form.Element.Serializers.inputSelector(element); | ||
|  |     } | ||
|  |     return false; | ||
|  |   }, | ||
|  | 
 | ||
|  |   inputSelector: function(element) { | ||
|  |     if (element.checked) | ||
|  |       return [element.name, element.value]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   textarea: function(element) { | ||
|  |     return [element.name, element.value]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   select: function(element) { | ||
|  |     return Form.Element.Serializers[element.type == 'select-one' ? | ||
|  |       'selectOne' : 'selectMany'](element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   selectOne: function(element) { | ||
|  |     var value = '', opt, index = element.selectedIndex; | ||
|  |     if (index >= 0) { | ||
|  |       opt = element.options[index]; | ||
|  |       value = opt.value; | ||
|  |       if (!value && !('value' in opt)) | ||
|  |         value = opt.text; | ||
|  |     } | ||
|  |     return [element.name, value]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   selectMany: function(element) { | ||
|  |     var value = new Array(); | ||
|  |     for (var i = 0; i < element.length; i++) { | ||
|  |       var opt = element.options[i]; | ||
|  |       if (opt.selected) { | ||
|  |         var optValue = opt.value; | ||
|  |         if (!optValue && !('value' in opt)) | ||
|  |           optValue = opt.text; | ||
|  |         value.push(optValue); | ||
|  |       } | ||
|  |     } | ||
|  |     return [element.name, value]; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | var $F = Form.Element.getValue; | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | Abstract.TimedObserver = function() {} | ||
|  | Abstract.TimedObserver.prototype = { | ||
|  |   initialize: function(element, frequency, callback) { | ||
|  |     this.frequency = frequency; | ||
|  |     this.element   = $(element); | ||
|  |     this.callback  = callback; | ||
|  | 
 | ||
|  |     this.lastValue = this.getValue(); | ||
|  |     this.registerCallback(); | ||
|  |   }, | ||
|  | 
 | ||
|  |   registerCallback: function() { | ||
|  |     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); | ||
|  |   }, | ||
|  | 
 | ||
|  |   onTimerEvent: function() { | ||
|  |     var value = this.getValue(); | ||
|  |     if (this.lastValue != value) { | ||
|  |       this.callback(this.element, value); | ||
|  |       this.lastValue = value; | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Form.Element.Observer = Class.create(); | ||
|  | Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | ||
|  |   getValue: function() { | ||
|  |     return Form.Element.getValue(this.element); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Form.Observer = Class.create(); | ||
|  | Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | ||
|  |   getValue: function() { | ||
|  |     return Form.serialize(this.element); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | /*--------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | Abstract.EventObserver = function() {} | ||
|  | Abstract.EventObserver.prototype = { | ||
|  |   initialize: function(element, callback) { | ||
|  |     this.element  = $(element); | ||
|  |     this.callback = callback; | ||
|  | 
 | ||
|  |     this.lastValue = this.getValue(); | ||
|  |     if (this.element.tagName.toLowerCase() == 'form') | ||
|  |       this.registerFormCallbacks(); | ||
|  |     else | ||
|  |       this.registerCallback(this.element); | ||
|  |   }, | ||
|  | 
 | ||
|  |   onElementEvent: function() { | ||
|  |     var value = this.getValue(); | ||
|  |     if (this.lastValue != value) { | ||
|  |       this.callback(this.element, value); | ||
|  |       this.lastValue = value; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   registerFormCallbacks: function() { | ||
|  |     var elements = Form.getElements(this.element); | ||
|  |     for (var i = 0; i < elements.length; i++) | ||
|  |       this.registerCallback(elements[i]); | ||
|  |   }, | ||
|  | 
 | ||
|  |   registerCallback: function(element) { | ||
|  |     if (element.type) { | ||
|  |       switch (element.type.toLowerCase()) { | ||
|  |         case 'checkbox': | ||
|  |         case 'radio': | ||
|  |           Event.observe(element, 'click', this.onElementEvent.bind(this)); | ||
|  |           break; | ||
|  |         case 'password': | ||
|  |         case 'text': | ||
|  |         case 'textarea': | ||
|  |         case 'select-one': | ||
|  |         case 'select-multiple': | ||
|  |           Event.observe(element, 'change', this.onElementEvent.bind(this)); | ||
|  |           break; | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | Form.Element.EventObserver = Class.create(); | ||
|  | Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | ||
|  |   getValue: function() { | ||
|  |     return Form.Element.getValue(this.element); | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | Form.EventObserver = Class.create(); | ||
|  | Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | ||
|  |   getValue: function() { | ||
|  |     return Form.serialize(this.element); | ||
|  |   } | ||
|  | }); | ||
|  | if (!window.Event) { | ||
|  |   var Event = new Object(); | ||
|  | } | ||
|  | 
 | ||
|  | Object.extend(Event, { | ||
|  |   KEY_BACKSPACE: 8, | ||
|  |   KEY_TAB:       9, | ||
|  |   KEY_RETURN:   13, | ||
|  |   KEY_ESC:      27, | ||
|  |   KEY_LEFT:     37, | ||
|  |   KEY_UP:       38, | ||
|  |   KEY_RIGHT:    39, | ||
|  |   KEY_DOWN:     40, | ||
|  |   KEY_DELETE:   46, | ||
|  | 
 | ||
|  |   element: function(event) { | ||
|  |     return event.target || event.srcElement; | ||
|  |   }, | ||
|  | 
 | ||
|  |   isLeftClick: function(event) { | ||
|  |     return (((event.which) && (event.which == 1)) || | ||
|  |             ((event.button) && (event.button == 1))); | ||
|  |   }, | ||
|  | 
 | ||
|  |   pointerX: function(event) { | ||
|  |     return event.pageX || (event.clientX + | ||
|  |       (document.documentElement.scrollLeft || document.body.scrollLeft)); | ||
|  |   }, | ||
|  | 
 | ||
|  |   pointerY: function(event) { | ||
|  |     return event.pageY || (event.clientY + | ||
|  |       (document.documentElement.scrollTop || document.body.scrollTop)); | ||
|  |   }, | ||
|  | 
 | ||
|  |   stop: function(event) { | ||
|  |     if (event.preventDefault) { | ||
|  |       event.preventDefault(); | ||
|  |       event.stopPropagation(); | ||
|  |     } else { | ||
|  |       event.returnValue = false; | ||
|  |       event.cancelBubble = true; | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   // find the first node with the given tagName, starting from the
 | ||
|  |   // node the event was triggered on; traverses the DOM upwards
 | ||
|  |   findElement: function(event, tagName) { | ||
|  |     var element = Event.element(event); | ||
|  |     while (element.parentNode && (!element.tagName || | ||
|  |         (element.tagName.toUpperCase() != tagName.toUpperCase()))) | ||
|  |       element = element.parentNode; | ||
|  |     return element; | ||
|  |   }, | ||
|  | 
 | ||
|  |   observers: false, | ||
|  | 
 | ||
|  |   _observeAndCache: function(element, name, observer, useCapture) { | ||
|  |     if (!this.observers) this.observers = []; | ||
|  |     if (element.addEventListener) { | ||
|  |       this.observers.push([element, name, observer, useCapture]); | ||
|  |       element.addEventListener(name, observer, useCapture); | ||
|  |     } else if (element.attachEvent) { | ||
|  |       this.observers.push([element, name, observer, useCapture]); | ||
|  |       element.attachEvent('on' + name, observer); | ||
|  |     } | ||
|  |   }, | ||
|  | 
 | ||
|  |   unloadCache: function() { | ||
|  |     if (!Event.observers) return; | ||
|  |     for (var i = 0; i < Event.observers.length; i++) { | ||
|  |       Event.stopObserving.apply(this, Event.observers[i]); | ||
|  |       Event.observers[i][0] = null; | ||
|  |     } | ||
|  |     Event.observers = false; | ||
|  |   }, | ||
|  | 
 | ||
|  |   observe: function(element, name, observer, useCapture) { | ||
|  |     var element = $(element); | ||
|  |     useCapture = useCapture || false; | ||
|  | 
 | ||
|  |     if (name == 'keypress' && | ||
|  |         (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | ||
|  |         || element.attachEvent)) | ||
|  |       name = 'keydown'; | ||
|  | 
 | ||
|  |     this._observeAndCache(element, name, observer, useCapture); | ||
|  |   }, | ||
|  | 
 | ||
|  |   stopObserving: function(element, name, observer, useCapture) { | ||
|  |     var element = $(element); | ||
|  |     useCapture = useCapture || false; | ||
|  | 
 | ||
|  |     if (name == 'keypress' && | ||
|  |         (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | ||
|  |         || element.detachEvent)) | ||
|  |       name = 'keydown'; | ||
|  | 
 | ||
|  |     if (element.removeEventListener) { | ||
|  |       element.removeEventListener(name, observer, useCapture); | ||
|  |     } else if (element.detachEvent) { | ||
|  |       element.detachEvent('on' + name, observer); | ||
|  |     } | ||
|  |   } | ||
|  | }); | ||
|  | 
 | ||
|  | /* prevent memory leaks in IE */ | ||
|  | Event.observe(window, 'unload', Event.unloadCache, false); | ||
|  | var Position = { | ||
|  |   // set to true if needed, warning: firefox performance problems
 | ||
|  |   // NOT neeeded for page scrolling, only if draggable contained in
 | ||
|  |   // scrollable elements
 | ||
|  |   includeScrollOffsets: false, | ||
|  | 
 | ||
|  |   // must be called before calling withinIncludingScrolloffset, every time the
 | ||
|  |   // page is scrolled
 | ||
|  |   prepare: function() { | ||
|  |     this.deltaX =  window.pageXOffset | ||
|  |                 || document.documentElement.scrollLeft | ||
|  |                 || document.body.scrollLeft | ||
|  |                 || 0; | ||
|  |     this.deltaY =  window.pageYOffset | ||
|  |                 || document.documentElement.scrollTop | ||
|  |                 || document.body.scrollTop | ||
|  |                 || 0; | ||
|  |   }, | ||
|  | 
 | ||
|  |   realOffset: function(element) { | ||
|  |     var valueT = 0, valueL = 0; | ||
|  |     do { | ||
|  |       valueT += element.scrollTop  || 0; | ||
|  |       valueL += element.scrollLeft || 0; | ||
|  |       element = element.parentNode; | ||
|  |     } while (element); | ||
|  |     return [valueL, valueT]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   cumulativeOffset: function(element) { | ||
|  |     var valueT = 0, valueL = 0; | ||
|  |     do { | ||
|  |       valueT += element.offsetTop  || 0; | ||
|  |       valueL += element.offsetLeft || 0; | ||
|  |       element = element.offsetParent; | ||
|  |     } while (element); | ||
|  |     return [valueL, valueT]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   positionedOffset: function(element) { | ||
|  |     var valueT = 0, valueL = 0; | ||
|  |     do { | ||
|  |       valueT += element.offsetTop  || 0; | ||
|  |       valueL += element.offsetLeft || 0; | ||
|  |       element = element.offsetParent; | ||
|  |       if (element) { | ||
|  |         p = Element.getStyle(element, 'position'); | ||
|  |         if (p == 'relative' || p == 'absolute') break; | ||
|  |       } | ||
|  |     } while (element); | ||
|  |     return [valueL, valueT]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   offsetParent: function(element) { | ||
|  |     if (element.offsetParent) return element.offsetParent; | ||
|  |     if (element == document.body) return element; | ||
|  | 
 | ||
|  |     while ((element = element.parentNode) && element != document.body) | ||
|  |       if (Element.getStyle(element, 'position') != 'static') | ||
|  |         return element; | ||
|  | 
 | ||
|  |     return document.body; | ||
|  |   }, | ||
|  | 
 | ||
|  |   // caches x/y coordinate pair to use with overlap
 | ||
|  |   within: function(element, x, y) { | ||
|  |     if (this.includeScrollOffsets) | ||
|  |       return this.withinIncludingScrolloffsets(element, x, y); | ||
|  |     this.xcomp = x; | ||
|  |     this.ycomp = y; | ||
|  |     this.offset = this.cumulativeOffset(element); | ||
|  | 
 | ||
|  |     return (y >= this.offset[1] && | ||
|  |             y <  this.offset[1] + element.offsetHeight && | ||
|  |             x >= this.offset[0] && | ||
|  |             x <  this.offset[0] + element.offsetWidth); | ||
|  |   }, | ||
|  | 
 | ||
|  |   withinIncludingScrolloffsets: function(element, x, y) { | ||
|  |     var offsetcache = this.realOffset(element); | ||
|  | 
 | ||
|  |     this.xcomp = x + offsetcache[0] - this.deltaX; | ||
|  |     this.ycomp = y + offsetcache[1] - this.deltaY; | ||
|  |     this.offset = this.cumulativeOffset(element); | ||
|  | 
 | ||
|  |     return (this.ycomp >= this.offset[1] && | ||
|  |             this.ycomp <  this.offset[1] + element.offsetHeight && | ||
|  |             this.xcomp >= this.offset[0] && | ||
|  |             this.xcomp <  this.offset[0] + element.offsetWidth); | ||
|  |   }, | ||
|  | 
 | ||
|  |   // within must be called directly before
 | ||
|  |   overlap: function(mode, element) { | ||
|  |     if (!mode) return 0; | ||
|  |     if (mode == 'vertical') | ||
|  |       return ((this.offset[1] + element.offsetHeight) - this.ycomp) / | ||
|  |         element.offsetHeight; | ||
|  |     if (mode == 'horizontal') | ||
|  |       return ((this.offset[0] + element.offsetWidth) - this.xcomp) / | ||
|  |         element.offsetWidth; | ||
|  |   }, | ||
|  | 
 | ||
|  |   clone: function(source, target) { | ||
|  |     source = $(source); | ||
|  |     target = $(target); | ||
|  |     target.style.position = 'absolute'; | ||
|  |     var offsets = this.cumulativeOffset(source); | ||
|  |     target.style.top    = offsets[1] + 'px'; | ||
|  |     target.style.left   = offsets[0] + 'px'; | ||
|  |     target.style.width  = source.offsetWidth + 'px'; | ||
|  |     target.style.height = source.offsetHeight + 'px'; | ||
|  |   }, | ||
|  | 
 | ||
|  |   page: function(forElement) { | ||
|  |     var valueT = 0, valueL = 0; | ||
|  | 
 | ||
|  |     var element = forElement; | ||
|  |     do { | ||
|  |       valueT += element.offsetTop  || 0; | ||
|  |       valueL += element.offsetLeft || 0; | ||
|  | 
 | ||
|  |       // Safari fix
 | ||
|  |       if (element.offsetParent==document.body) | ||
|  |         if (Element.getStyle(element,'position')=='absolute') break; | ||
|  | 
 | ||
|  |     } while (element = element.offsetParent); | ||
|  | 
 | ||
|  |     element = forElement; | ||
|  |     do { | ||
|  |       valueT -= element.scrollTop  || 0; | ||
|  |       valueL -= element.scrollLeft || 0; | ||
|  |     } while (element = element.parentNode); | ||
|  | 
 | ||
|  |     return [valueL, valueT]; | ||
|  |   }, | ||
|  | 
 | ||
|  |   clone: function(source, target) { | ||
|  |     var options = Object.extend({ | ||
|  |       setLeft:    true, | ||
|  |       setTop:     true, | ||
|  |       setWidth:   true, | ||
|  |       setHeight:  true, | ||
|  |       offsetTop:  0, | ||
|  |       offsetLeft: 0 | ||
|  |     }, arguments[2] || {}) | ||
|  | 
 | ||
|  |     // find page position of source
 | ||
|  |     source = $(source); | ||
|  |     var p = Position.page(source); | ||
|  | 
 | ||
|  |     // find coordinate system to use
 | ||
|  |     target = $(target); | ||
|  |     var delta = [0, 0]; | ||
|  |     var parent = null; | ||
|  |     // delta [0,0] will do fine with position: fixed elements,
 | ||
|  |     // position:absolute needs offsetParent deltas
 | ||
|  |     if (Element.getStyle(target,'position') == 'absolute') { | ||
|  |       parent = Position.offsetParent(target); | ||
|  |       delta = Position.page(parent); | ||
|  |     } | ||
|  | 
 | ||
|  |     // correct by body offsets (fixes Safari)
 | ||
|  |     if (parent == document.body) { | ||
|  |       delta[0] -= document.body.offsetLeft; | ||
|  |       delta[1] -= document.body.offsetTop; | ||
|  |     } | ||
|  | 
 | ||
|  |     // set position
 | ||
|  |     if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px'; | ||
|  |     if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px'; | ||
|  |     if(options.setWidth)  target.style.width = source.offsetWidth + 'px'; | ||
|  |     if(options.setHeight) target.style.height = source.offsetHeight + 'px'; | ||
|  |   }, | ||
|  | 
 | ||
|  |   absolutize: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (element.style.position == 'absolute') return; | ||
|  |     Position.prepare(); | ||
|  | 
 | ||
|  |     var offsets = Position.positionedOffset(element); | ||
|  |     var top     = offsets[1]; | ||
|  |     var left    = offsets[0]; | ||
|  |     var width   = element.clientWidth; | ||
|  |     var height  = element.clientHeight; | ||
|  | 
 | ||
|  |     element._originalLeft   = left - parseFloat(element.style.left  || 0); | ||
|  |     element._originalTop    = top  - parseFloat(element.style.top || 0); | ||
|  |     element._originalWidth  = element.style.width; | ||
|  |     element._originalHeight = element.style.height; | ||
|  | 
 | ||
|  |     element.style.position = 'absolute'; | ||
|  |     element.style.top    = top + 'px';; | ||
|  |     element.style.left   = left + 'px';; | ||
|  |     element.style.width  = width + 'px';; | ||
|  |     element.style.height = height + 'px';; | ||
|  |   }, | ||
|  | 
 | ||
|  |   relativize: function(element) { | ||
|  |     element = $(element); | ||
|  |     if (element.style.position == 'relative') return; | ||
|  |     Position.prepare(); | ||
|  | 
 | ||
|  |     element.style.position = 'relative'; | ||
|  |     var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0); | ||
|  |     var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); | ||
|  | 
 | ||
|  |     element.style.top    = top + 'px'; | ||
|  |     element.style.left   = left + 'px'; | ||
|  |     element.style.height = element._originalHeight; | ||
|  |     element.style.width  = element._originalWidth; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // Safari returns margins on body which is incorrect if the child is absolutely
 | ||
|  | // positioned.  For performance reasons, redefine Position.cumulativeOffset for
 | ||
|  | // KHTML/WebKit only.
 | ||
|  | if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { | ||
|  |   Position.cumulativeOffset = function(element) { | ||
|  |     var valueT = 0, valueL = 0; | ||
|  |     do { | ||
|  |       valueT += element.offsetTop  || 0; | ||
|  |       valueL += element.offsetLeft || 0; | ||
|  |       if (element.offsetParent == document.body) | ||
|  |         if (Element.getStyle(element, 'position') == 'absolute') break; | ||
|  | 
 | ||
|  |       element = element.offsetParent; | ||
|  |     } while (element); | ||
|  | 
 | ||
|  |     return [valueL, valueT]; | ||
|  |   } | ||
|  | } |