/* Prototype JavaScript framework, version 1.4.0                                           
 * (c) 2005 Sam Stephenson <sam@conio.net>                                                
 *                                                                                        
 * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff                
 * against the source tree, available from the Prototype darcs repository.                
 *                                                                                        
 * 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];                                                              
 }                                                                                     
}                                                                                 