You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/11/12 23:23:28 UTC

svn commit: r594319 [25/40] - in /tapestry/tapestry5/trunk: ./ tapestry-annotations/ tapestry-annotations/src/main/java/org/apache/tapestry/beaneditor/ tapestry-annotations/src/site/ tapestry-component-report/ tapestry-component-report/src/main/java/or...

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/prototype.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/prototype.js?rev=594319&r1=594318&r2=594319&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/prototype.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/scriptaculous_1_8/prototype.js Mon Nov 12 14:22:31 2007
@@ -7,2539 +7,3067 @@
  *--------------------------------------------------------------------------*/
 
 var Prototype = {
-  Version: '1.6.0',
+    Version: '1.6.0',
 
-  Browser: {
-    IE:     !!(window.attachEvent && !window.opera),
-    Opera:  !!window.opera,
-    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
-    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
-    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
-  },
-
-  BrowserFeatures: {
-    XPath: !!document.evaluate,
-    ElementExtensions: !!window.HTMLElement,
-    SpecificElementExtensions:
-      document.createElement('div').__proto__ &&
-      document.createElement('div').__proto__ !==
-        document.createElement('form').__proto__
-  },
-
-  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
-  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
-
-  emptyFunction: function() { },
-  K: function(x) { return x }
+    Browser: {
+        IE:     !!(window.attachEvent && !window.opera),
+        Opera:  !!window.opera,
+        WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+        Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+        MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+    },
+
+    BrowserFeatures: {
+        XPath: !!document.evaluate,
+        ElementExtensions: !!window.HTMLElement,
+        SpecificElementExtensions:
+                document.createElement('div').__proto__ &&
+                document.createElement('div').__proto__ !==
+                document.createElement('form').__proto__
+    },
+
+    ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+    JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+    emptyFunction: function()
+    {
+    },
+    K: function(x)
+    {
+        return x
+    }
 };
 
 if (Prototype.Browser.MobileSafari)
-  Prototype.BrowserFeatures.SpecificElementExtensions = false;
+    Prototype.BrowserFeatures.SpecificElementExtensions = false;
 
 if (Prototype.Browser.WebKit)
-  Prototype.BrowserFeatures.XPath = false;
+    Prototype.BrowserFeatures.XPath = false;
 
 /* Based on Alex Arnell's inheritance implementation. */
 var Class = {
-  create: function() {
-    var parent = null, properties = $A(arguments);
-    if (Object.isFunction(properties[0]))
-      parent = properties.shift();
-
-    function klass() {
-      this.initialize.apply(this, arguments);
-    }
-
-    Object.extend(klass, Class.Methods);
-    klass.superclass = parent;
-    klass.subclasses = [];
+    create: function()
+    {
+        var parent = null, properties = $A(arguments);
+        if (Object.isFunction(properties[0]))
+            parent = properties.shift();
+
+        function klass()
+        {
+            this.initialize.apply(this, arguments);
+        }
 
-    if (parent) {
-      var subclass = function() { };
-      subclass.prototype = parent.prototype;
-      klass.prototype = new subclass;
-      parent.subclasses.push(klass);
-    }
+        Object.extend(klass, Class.Methods);
+        klass.superclass = parent;
+        klass.subclasses = [];
+
+        if (parent)
+        {
+            var subclass = function()
+            {
+            };
+            subclass.prototype = parent.prototype;
+            klass.prototype = new subclass;
+            parent.subclasses.push(klass);
+        }
 
-    for (var i = 0; i < properties.length; i++)
-      klass.addMethods(properties[i]);
+        for (var i = 0; i < properties.length; i++)
+            klass.addMethods(properties[i]);
 
-    if (!klass.prototype.initialize)
-      klass.prototype.initialize = Prototype.emptyFunction;
+        if (!klass.prototype.initialize)
+            klass.prototype.initialize = Prototype.emptyFunction;
 
-    klass.prototype.constructor = klass;
+        klass.prototype.constructor = klass;
 
-    return klass;
-  }
+        return klass;
+    }
 };
 
 Class.Methods = {
-  addMethods: function(source) {
-    var ancestor   = this.superclass && this.superclass.prototype;
-    var properties = Object.keys(source);
-
-    if (!Object.keys({ toString: true }).length)
-      properties.push("toString", "valueOf");
-
-    for (var i = 0, length = properties.length; i < length; i++) {
-      var property = properties[i], value = source[property];
-      if (ancestor && Object.isFunction(value) &&
-          value.argumentNames().first() == "$super") {
-        var method = value, value = Object.extend((function(m) {
-          return function() { return ancestor[m].apply(this, arguments) };
-        })(property).wrap(method), {
-          valueOf:  function() { return method },
-          toString: function() { return method.toString() }
-        });
-      }
-      this.prototype[property] = value;
-    }
+    addMethods: function(source)
+    {
+        var ancestor = this.superclass && this.superclass.prototype;
+        var properties = Object.keys(source);
+
+        if (!Object.keys({ toString: true }).length)
+            properties.push("toString", "valueOf");
+
+        for (var i = 0, length = properties.length; i < length; i++)
+        {
+            var property = properties[i], value = source[property];
+            if (ancestor && Object.isFunction(value) &&
+                value.argumentNames().first() == "$super")
+            {
+                var method = value, value = Object.extend((function(m)
+                {
+                    return function()
+                    {
+                        return ancestor[m].apply(this, arguments)
+                    };
+                })(property).wrap(method), {
+                    valueOf:  function()
+                    {
+                        return method
+                    },
+                    toString: function()
+                    {
+                        return method.toString()
+                    }
+                });
+            }
+            this.prototype[property] = value;
+        }
 
-    return this;
-  }
+        return this;
+    }
 };
 
 var Abstract = { };
 
-Object.extend = function(destination, source) {
-  for (var property in source)
-    destination[property] = source[property];
-  return destination;
+Object.extend = function(destination, source)
+{
+    for (var property in source)
+        destination[property] = source[property];
+    return destination;
 };
 
 Object.extend(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;
-    }
-  },
-
-  toJSON: function(object) {
-    var type = typeof object;
-    switch (type) {
-      case 'undefined':
-      case 'function':
-      case 'unknown': return;
-      case 'boolean': return object.toString();
-    }
-
-    if (object === null) return 'null';
-    if (object.toJSON) return object.toJSON();
-    if (Object.isElement(object)) return;
-
-    var results = [];
-    for (var property in object) {
-      var value = Object.toJSON(object[property]);
-      if (value !== undefined)
-        results.push(property.toJSON() + ': ' + value);
-    }
-
-    return '{' + results.join(', ') + '}';
-  },
-
-  toQueryString: function(object) {
-    return $H(object).toQueryString();
-  },
-
-  toHTML: function(object) {
-    return object && object.toHTML ? object.toHTML() : String.interpret(object);
-  },
-
-  keys: function(object) {
-    var keys = [];
-    for (var property in object)
-      keys.push(property);
-    return keys;
-  },
-
-  values: function(object) {
-    var values = [];
-    for (var property in object)
-      values.push(object[property]);
-    return values;
-  },
-
-  clone: function(object) {
-    return Object.extend({ }, object);
-  },
-
-  isElement: function(object) {
-    return object && object.nodeType == 1;
-  },
-
-  isArray: function(object) {
-    return object && object.constructor === Array;
-  },
-
-  isHash: function(object) {
-    return object instanceof Hash;
-  },
-
-  isFunction: function(object) {
-    return typeof object == "function";
-  },
-
-  isString: function(object) {
-    return typeof object == "string";
-  },
-
-  isNumber: function(object) {
-    return typeof object == "number";
-  },
-
-  isUndefined: function(object) {
-    return typeof object == "undefined";
-  }
+    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;
+        }
+    },
+
+    toJSON: function(object)
+    {
+        var type = typeof object;
+        switch (type)
+                {
+            case 'undefined':
+            case 'function':
+            case 'unknown': return;
+            case 'boolean': return object.toString();
+        }
+
+        if (object === null) return 'null';
+        if (object.toJSON) return object.toJSON();
+        if (Object.isElement(object)) return;
+
+        var results = [];
+        for (var property in object)
+        {
+            var value = Object.toJSON(object[property]);
+            if (value !== undefined)
+                results.push(property.toJSON() + ': ' + value);
+        }
+
+        return '{' + results.join(', ') + '}';
+    },
+
+    toQueryString: function(object)
+    {
+        return $H(object).toQueryString();
+    },
+
+    toHTML: function(object)
+    {
+        return object && object.toHTML ? object.toHTML() : String.interpret(object);
+    },
+
+    keys: function(object)
+    {
+        var keys = [];
+        for (var property in object)
+            keys.push(property);
+        return keys;
+    },
+
+    values: function(object)
+    {
+        var values = [];
+        for (var property in object)
+            values.push(object[property]);
+        return values;
+    },
+
+    clone: function(object)
+    {
+        return Object.extend({ }, object);
+    },
+
+    isElement: function(object)
+    {
+        return object && object.nodeType == 1;
+    },
+
+    isArray: function(object)
+    {
+        return object && object.constructor === Array;
+    },
+
+    isHash: function(object)
+    {
+        return object instanceof Hash;
+    },
+
+    isFunction: function(object)
+    {
+        return typeof object == "function";
+    },
+
+    isString: function(object)
+    {
+        return typeof object == "string";
+    },
+
+    isNumber: function(object)
+    {
+        return typeof object == "number";
+    },
+
+    isUndefined: function(object)
+    {
+        return typeof object == "undefined";
+    }
 });
 
 Object.extend(Function.prototype, {
-  argumentNames: function() {
-    var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
-    return names.length == 1 && !names[0] ? [] : names;
-  },
-
-  bind: function() {
-    if (arguments.length < 2 && arguments[0] === undefined) return this;
-    var __method = this, args = $A(arguments), object = args.shift();
-    return function() {
-      return __method.apply(object, args.concat($A(arguments)));
-    }
-  },
-
-  bindAsEventListener: function() {
-    var __method = this, args = $A(arguments), object = args.shift();
-    return function(event) {
-      return __method.apply(object, [event || window.event].concat(args));
-    }
-  },
-
-  curry: function() {
-    if (!arguments.length) return this;
-    var __method = this, args = $A(arguments);
-    return function() {
-      return __method.apply(this, args.concat($A(arguments)));
-    }
-  },
-
-  delay: function() {
-    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
-    return window.setTimeout(function() {
-      return __method.apply(__method, args);
-    }, timeout);
-  },
-
-  wrap: function(wrapper) {
-    var __method = this;
-    return function() {
-      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
-    }
-  },
-
-  methodize: function() {
-    if (this._methodized) return this._methodized;
-    var __method = this;
-    return this._methodized = function() {
-      return __method.apply(null, [this].concat($A(arguments)));
-    };
-  }
+    argumentNames: function()
+    {
+        var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+        return names.length == 1 && !names[0] ? [] : names;
+    },
+
+    bind: function()
+    {
+        if (arguments.length < 2 && arguments[0] === undefined) return this;
+        var __method = this, args = $A(arguments), object = args.shift();
+        return function()
+        {
+            return __method.apply(object, args.concat($A(arguments)));
+        }
+    },
+
+    bindAsEventListener: function()
+    {
+        var __method = this, args = $A(arguments), object = args.shift();
+        return function(event)
+        {
+            return __method.apply(object, [event || window.event].concat(args));
+        }
+    },
+
+    curry: function()
+    {
+        if (!arguments.length) return this;
+        var __method = this, args = $A(arguments);
+        return function()
+        {
+            return __method.apply(this, args.concat($A(arguments)));
+        }
+    },
+
+    delay: function()
+    {
+        var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+        return window.setTimeout(function()
+        {
+            return __method.apply(__method, args);
+        }, timeout);
+    },
+
+    wrap: function(wrapper)
+    {
+        var __method = this;
+        return function()
+        {
+            return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+        }
+    },
+
+    methodize: function()
+    {
+        if (this._methodized) return this._methodized;
+        var __method = this;
+        return this._methodized = function()
+        {
+            return __method.apply(null, [this].concat($A(arguments)));
+        };
+    }
 });
 
 Function.prototype.defer = Function.prototype.delay.curry(0.01);
 
-Date.prototype.toJSON = function() {
-  return '"' + this.getUTCFullYear() + '-' +
-    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
-    this.getUTCDate().toPaddedString(2) + 'T' +
-    this.getUTCHours().toPaddedString(2) + ':' +
-    this.getUTCMinutes().toPaddedString(2) + ':' +
-    this.getUTCSeconds().toPaddedString(2) + 'Z"';
+Date.prototype.toJSON = function()
+{
+    return '"' + this.getUTCFullYear() + '-' +
+           (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+           this.getUTCDate().toPaddedString(2) + 'T' +
+           this.getUTCHours().toPaddedString(2) + ':' +
+           this.getUTCMinutes().toPaddedString(2) + ':' +
+           this.getUTCSeconds().toPaddedString(2) + 'Z"';
 };
 
 var Try = {
-  these: function() {
-    var returnValue;
+    these: function()
+    {
+        var returnValue;
+
+        for (var i = 0, length = arguments.length; i < length; i++)
+        {
+            var lambda = arguments[i];
+            try
+            {
+                returnValue = lambda();
+                break;
+            }
+            catch (e)
+            {
+            }
+        }
 
-    for (var i = 0, length = arguments.length; i < length; i++) {
-      var lambda = arguments[i];
-      try {
-        returnValue = lambda();
-        break;
-      } catch (e) { }
+        return returnValue;
     }
-
-    return returnValue;
-  }
 };
 
 RegExp.prototype.match = RegExp.prototype.test;
 
-RegExp.escape = function(str) {
-  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+RegExp.escape = function(str)
+{
+    return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
 };
 
 /*--------------------------------------------------------------------------*/
 
 var PeriodicalExecuter = Class.create({
-  initialize: function(callback, frequency) {
-    this.callback = callback;
-    this.frequency = frequency;
-    this.currentlyExecuting = false;
-
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  execute: function() {
-    this.callback(this);
-  },
-
-  stop: function() {
-    if (!this.timer) return;
-    clearInterval(this.timer);
-    this.timer = null;
-  },
-
-  onTimerEvent: function() {
-    if (!this.currentlyExecuting) {
-      try {
-        this.currentlyExecuting = true;
-        this.execute();
-      } finally {
+    initialize: function(callback, frequency)
+    {
+        this.callback = callback;
+        this.frequency = frequency;
         this.currentlyExecuting = false;
-      }
-    }
-  }
-});
-Object.extend(String, {
-  interpret: function(value) {
-    return value == null ? '' : String(value);
-  },
-  specialChar: {
-    '\b': '\\b',
-    '\t': '\\t',
-    '\n': '\\n',
-    '\f': '\\f',
-    '\r': '\\r',
-    '\\': '\\\\'
-  }
-});
-
-Object.extend(String.prototype, {
-  gsub: function(pattern, replacement) {
-    var result = '', source = this, match;
-    replacement = arguments.callee.prepareReplacement(replacement);
-
-    while (source.length > 0) {
-      if (match = source.match(pattern)) {
-        result += source.slice(0, match.index);
-        result += String.interpret(replacement(match));
-        source  = source.slice(match.index + match[0].length);
-      } else {
-        result += source, source = '';
-      }
-    }
-    return result;
-  },
 
-  sub: function(pattern, replacement, count) {
-    replacement = this.gsub.prepareReplacement(replacement);
-    count = count === undefined ? 1 : count;
-
-    return this.gsub(pattern, function(match) {
-      if (--count < 0) return match[0];
-      return replacement(match);
-    });
-  },
+        this.registerCallback();
+    },
 
-  scan: function(pattern, iterator) {
-    this.gsub(pattern, iterator);
-    return String(this);
-  },
-
-  truncate: function(length, truncation) {
-    length = length || 30;
-    truncation = truncation === undefined ? '...' : truncation;
-    return this.length > length ?
-      this.slice(0, length - truncation.length) + truncation : String(this);
-  },
-
-  strip: function() {
-    return this.replace(/^\s+/, '').replace(/\s+$/, '');
-  },
-
-  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];
-    });
-  },
+    registerCallback: function()
+    {
+        this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+    },
 
-  evalScripts: function() {
-    return this.extractScripts().map(function(script) { return eval(script) });
-  },
-
-  escapeHTML: function() {
-    var self = arguments.callee;
-    self.text.data = this;
-    return self.div.innerHTML;
-  },
-
-  unescapeHTML: function() {
-    var div = new Element('div');
-    div.innerHTML = this.stripTags();
-    return div.childNodes[0] ? (div.childNodes.length > 1 ?
-      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
-      div.childNodes[0].nodeValue) : '';
-  },
-
-  toQueryParams: function(separator) {
-    var match = this.strip().match(/([^?#]*)(#.*)?$/);
-    if (!match) return { };
-
-    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
-      if ((pair = pair.split('='))[0]) {
-        var key = decodeURIComponent(pair.shift());
-        var value = pair.length > 1 ? pair.join('=') : pair[0];
-        if (value != undefined) value = decodeURIComponent(value);
-
-        if (key in hash) {
-          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
-          hash[key].push(value);
-        }
-        else hash[key] = value;
-      }
-      return hash;
-    });
-  },
+    execute: function()
+    {
+        this.callback(this);
+    },
 
-  toArray: function() {
-    return this.split('');
-  },
-
-  succ: function() {
-    return this.slice(0, this.length - 1) +
-      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
-  },
-
-  times: function(count) {
-    return count < 1 ? '' : new Array(count + 1).join(this);
-  },
-
-  camelize: function() {
-    var parts = this.split('-'), len = parts.length;
-    if (len == 1) return parts[0];
-
-    var camelized = this.charAt(0) == '-'
-      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
-      : parts[0];
-
-    for (var i = 1; i < len; i++)
-      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
-
-    return camelized;
-  },
-
-  capitalize: function() {
-    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
-  },
-
-  underscore: function() {
-    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
-  },
-
-  dasherize: function() {
-    return this.gsub(/_/,'-');
-  },
-
-  inspect: function(useDoubleQuotes) {
-    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
-      var character = String.specialChar[match[0]];
-      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
-    });
-    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
-    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
-  },
-
-  toJSON: function() {
-    return this.inspect(true);
-  },
-
-  unfilterJSON: function(filter) {
-    return this.sub(filter || Prototype.JSONFilter, '#{1}');
-  },
-
-  isJSON: function() {
-    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
-    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
-  },
-
-  evalJSON: function(sanitize) {
-    var json = this.unfilterJSON();
-    try {
-      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
-    } catch (e) { }
-    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
-  },
-
-  include: function(pattern) {
-    return this.indexOf(pattern) > -1;
-  },
-
-  startsWith: function(pattern) {
-    return this.indexOf(pattern) === 0;
-  },
-
-  endsWith: function(pattern) {
-    var d = this.length - pattern.length;
-    return d >= 0 && this.lastIndexOf(pattern) === d;
-  },
-
-  empty: function() {
-    return this == '';
-  },
-
-  blank: function() {
-    return /^\s*$/.test(this);
-  },
-
-  interpolate: function(object, pattern) {
-    return new Template(this, pattern).evaluate(object);
-  }
-});
+    stop: function()
+    {
+        if (!this.timer) return;
+        clearInterval(this.timer);
+        this.timer = null;
+    },
 
-if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
-  escapeHTML: function() {
-    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
-  },
-  unescapeHTML: function() {
-    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
-  }
+    onTimerEvent: function()
+    {
+        if (!this.currentlyExecuting)
+        {
+            try
+            {
+                this.currentlyExecuting = true;
+                this.execute();
+            }
+            finally
+            {
+                this.currentlyExecuting = false;
+            }
+        }
+    }
 });
-
-String.prototype.gsub.prepareReplacement = function(replacement) {
-  if (Object.isFunction(replacement)) return replacement;
-  var template = new Template(replacement);
-  return function(match) { return template.evaluate(match) };
-};
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-Object.extend(String.prototype.escapeHTML, {
-  div:  document.createElement('div'),
-  text: document.createTextNode('')
+Object.extend(String, {
+    interpret: function(value)
+    {
+        return value == null ? '' : String(value);
+    },
+    specialChar: {
+        '\b': '\\b',
+        '\t': '\\t',
+        '\n': '\\n',
+        '\f': '\\f',
+        '\r': '\\r',
+        '\\': '\\\\'
+    }
 });
 
-with (String.prototype.escapeHTML) div.appendChild(text);
+Object.extend(String.prototype, {
+    gsub: function(pattern, replacement)
+    {
+        var result = '', source = this, match;
+        replacement = arguments.callee.prepareReplacement(replacement);
+
+        while (source.length > 0)
+        {
+            if (match = source.match(pattern))
+            {
+                result += source.slice(0, match.index);
+                result += String.interpret(replacement(match));
+                source = source.slice(match.index + match[0].length);
+            }
+            else
+            {
+                result += source,source = '';
+            }
+        }
+        return result;
+    },
 
-var Template = Class.create({
-  initialize: function(template, pattern) {
-    this.template = template.toString();
-    this.pattern = pattern || Template.Pattern;
-  },
-
-  evaluate: function(object) {
-    if (Object.isFunction(object.toTemplateReplacements))
-      object = object.toTemplateReplacements();
-
-    return this.template.gsub(this.pattern, function(match) {
-      if (object == null) return '';
-
-      var before = match[1] || '';
-      if (before == '\\') return match[2];
-
-      var ctx = object, expr = match[3];
-      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
-      if (match == null) return before;
-
-      while (match != null) {
-        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
-        ctx = ctx[comp];
-        if (null == ctx || '' == match[3]) break;
-        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
-        match = pattern.exec(expr);
-      }
-
-      return before + String.interpret(ctx);
-    }.bind(this));
-  }
-});
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+    sub: function(pattern, replacement, count)
+    {
+        replacement = this.gsub.prepareReplacement(replacement);
+        count = count === undefined ? 1 : count;
+
+        return this.gsub(pattern, function(match)
+        {
+            if (--count < 0) return match[0];
+            return replacement(match);
+        });
+    },
 
-var $break = { };
+    scan: function(pattern, iterator)
+    {
+        this.gsub(pattern, iterator);
+        return String(this);
+    },
 
-var Enumerable = {
-  each: function(iterator, context) {
-    var index = 0;
-    iterator = iterator.bind(context);
-    try {
-      this._each(function(value) {
-        iterator(value, index++);
-      });
-    } catch (e) {
-      if (e != $break) throw e;
-    }
-    return this;
-  },
-
-  eachSlice: function(number, iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var index = -number, slices = [], array = this.toArray();
-    while ((index += number) < array.length)
-      slices.push(array.slice(index, index+number));
-    return slices.collect(iterator, context);
-  },
-
-  all: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var result = true;
-    this.each(function(value, index) {
-      result = result && !!iterator(value, index);
-      if (!result) throw $break;
-    });
-    return result;
-  },
+    truncate: function(length, truncation)
+    {
+        length = length || 30;
+        truncation = truncation === undefined ? '...' : truncation;
+        return this.length > length ?
+               this.slice(0, length - truncation.length) + truncation : String(this);
+    },
 
-  any: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var result = false;
-    this.each(function(value, index) {
-      if (result = !!iterator(value, index))
-        throw $break;
-    });
-    return result;
-  },
+    strip: function()
+    {
+        return this.replace(/^\s+/, '').replace(/\s+$/, '');
+    },
 
-  collect: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var results = [];
-    this.each(function(value, index) {
-      results.push(iterator(value, index));
-    });
-    return results;
-  },
+    stripTags: function()
+    {
+        return this.replace(/<\/?[^>]+>/gi, '');
+    },
 
-  detect: function(iterator, context) {
-    iterator = iterator.bind(context);
-    var result;
-    this.each(function(value, index) {
-      if (iterator(value, index)) {
-        result = value;
-        throw $break;
-      }
-    });
-    return result;
-  },
+    stripScripts: function()
+    {
+        return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+    },
 
-  findAll: function(iterator, context) {
-    iterator = iterator.bind(context);
-    var results = [];
-    this.each(function(value, index) {
-      if (iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
+    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];
+        });
+    },
 
-  grep: function(filter, iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var results = [];
-
-    if (Object.isString(filter))
-      filter = new RegExp(filter);
-
-    this.each(function(value, index) {
-      if (filter.match(value))
-        results.push(iterator(value, index));
-    });
-    return results;
-  },
+    evalScripts: function()
+    {
+        return this.extractScripts().map(function(script)
+        {
+            return eval(script)
+        });
+    },
 
-  include: function(object) {
-    if (Object.isFunction(this.indexOf))
-      if (this.indexOf(object) != -1) return true;
-
-    var found = false;
-    this.each(function(value) {
-      if (value == object) {
-        found = true;
-        throw $break;
-      }
-    });
-    return found;
-  },
+    escapeHTML: function()
+    {
+        var self = arguments.callee;
+        self.text.data = this;
+        return self.div.innerHTML;
+    },
+
+    unescapeHTML: function()
+    {
+        var div = new Element('div');
+        div.innerHTML = this.stripTags();
+        return div.childNodes[0] ? (div.childNodes.length > 1 ?
+                                    $A(div.childNodes).inject('', function(memo, node)
+                                    {
+                                        return memo + node.nodeValue
+                                    }) :
+                                    div.childNodes[0].nodeValue) : '';
+    },
+
+    toQueryParams: function(separator)
+    {
+        var match = this.strip().match(/([^?#]*)(#.*)?$/);
+        if (!match) return { };
+
+        return match[1].split(separator || '&').inject({ }, function(hash, pair)
+        {
+            if ((pair = pair.split('='))[0])
+            {
+                var key = decodeURIComponent(pair.shift());
+                var value = pair.length > 1 ? pair.join('=') : pair[0];
+                if (value != undefined) value = decodeURIComponent(value);
+
+                if (key in hash)
+                {
+                    if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+                    hash[key].push(value);
+                }
+                else hash[key] = value;
+            }
+            return hash;
+        });
+    },
 
-  inGroupsOf: function(number, fillWith) {
-    fillWith = fillWith === undefined ? null : fillWith;
-    return this.eachSlice(number, function(slice) {
-      while(slice.length < number) slice.push(fillWith);
-      return slice;
-    });
-  },
+    toArray: function()
+    {
+        return this.split('');
+    },
 
-  inject: function(memo, iterator, context) {
-    iterator = iterator.bind(context);
-    this.each(function(value, index) {
-      memo = iterator(memo, value, index);
-    });
-    return memo;
-  },
+    succ: function()
+    {
+        return this.slice(0, this.length - 1) +
+               String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+    },
 
-  invoke: function(method) {
-    var args = $A(arguments).slice(1);
-    return this.map(function(value) {
-      return value[method].apply(value, args);
-    });
-  },
+    times: function(count)
+    {
+        return count < 1 ? '' : new Array(count + 1).join(this);
+    },
 
-  max: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var result;
-    this.each(function(value, index) {
-      value = iterator(value, index);
-      if (result == undefined || value >= result)
-        result = value;
-    });
-    return result;
-  },
+    camelize: function()
+    {
+        var parts = this.split('-'), len = parts.length;
+        if (len == 1) return parts[0];
 
-  min: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var result;
-    this.each(function(value, index) {
-      value = iterator(value, index);
-      if (result == undefined || value < result)
-        result = value;
-    });
-    return result;
-  },
+        var camelized = this.charAt(0) == '-'
+                ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+                : parts[0];
 
-  partition: function(iterator, context) {
-    iterator = iterator ? iterator.bind(context) : Prototype.K;
-    var trues = [], falses = [];
-    this.each(function(value, index) {
-      (iterator(value, index) ?
-        trues : falses).push(value);
-    });
-    return [trues, falses];
-  },
+        for (var i = 1; i < len; i++)
+            camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
 
-  pluck: function(property) {
-    var results = [];
-    this.each(function(value) {
-      results.push(value[property]);
-    });
-    return results;
-  },
+        return camelized;
+    },
 
-  reject: function(iterator, context) {
-    iterator = iterator.bind(context);
-    var results = [];
-    this.each(function(value, index) {
-      if (!iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
+    capitalize: function()
+    {
+        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+    },
 
-  sortBy: function(iterator, context) {
-    iterator = iterator.bind(context);
-    return this.map(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.map();
-  },
-
-  zip: function() {
-    var iterator = Prototype.K, args = $A(arguments);
-    if (Object.isFunction(args.last()))
-      iterator = args.pop();
-
-    var collections = [this].concat(args).map($A);
-    return this.map(function(value, index) {
-      return iterator(collections.pluck(index));
-    });
-  },
+    underscore: function()
+    {
+        return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '#{1}_#{2}').gsub(/([a-z\d])([A-Z])/, '#{1}_#{2}').gsub(/-/, '_').toLowerCase();
+    },
 
-  size: function() {
-    return this.toArray().length;
-  },
-
-  inspect: function() {
-    return '#<Enumerable:' + this.toArray().inspect() + '>';
-  }
-};
+    dasherize: function()
+    {
+        return this.gsub(/_/, '-');
+    },
 
-Object.extend(Enumerable, {
-  map:     Enumerable.collect,
-  find:    Enumerable.detect,
-  select:  Enumerable.findAll,
-  filter:  Enumerable.findAll,
-  member:  Enumerable.include,
-  entries: Enumerable.toArray,
-  every:   Enumerable.all,
-  some:    Enumerable.any
-});
-function $A(iterable) {
-  if (!iterable) return [];
-  if (iterable.toArray) return iterable.toArray();
-  var length = iterable.length, results = new Array(length);
-  while (length--) results[length] = iterable[length];
-  return results;
-}
+    inspect: function(useDoubleQuotes)
+    {
+        var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match)
+        {
+            var character = String.specialChar[match[0]];
+            return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+        });
+        if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+        return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+    },
 
-if (Prototype.Browser.WebKit) {
-  function $A(iterable) {
-    if (!iterable) return [];
-    if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
-        iterable.toArray) return iterable.toArray();
-    var length = iterable.length, results = new Array(length);
-    while (length--) results[length] = iterable[length];
-    return results;
-  }
-}
+    toJSON: function()
+    {
+        return this.inspect(true);
+    },
 
-Array.from = $A;
+    unfilterJSON: function(filter)
+    {
+        return this.sub(filter || Prototype.JSONFilter, '#{1}');
+    },
 
-Object.extend(Array.prototype, Enumerable);
+    isJSON: function()
+    {
+        var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+        return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+    },
 
-if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+    evalJSON: function(sanitize)
+    {
+        var json = this.unfilterJSON();
+        try
+        {
+            if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+        }
+        catch (e)
+        {
+        }
+        throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+    },
 
-Object.extend(Array.prototype, {
-  _each: function(iterator) {
-    for (var i = 0, length = this.length; i < 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 != null;
-    });
-  },
+    include: function(pattern)
+    {
+        return this.indexOf(pattern) > -1;
+    },
 
-  flatten: function() {
-    return this.inject([], function(array, value) {
-      return array.concat(Object.isArray(value) ?
-        value.flatten() : [value]);
-    });
-  },
+    startsWith: function(pattern)
+    {
+        return this.indexOf(pattern) === 0;
+    },
 
-  without: function() {
-    var values = $A(arguments);
-    return this.select(function(value) {
-      return !values.include(value);
-    });
-  },
+    endsWith: function(pattern)
+    {
+        var d = this.length - pattern.length;
+        return d >= 0 && this.lastIndexOf(pattern) === d;
+    },
 
-  reverse: function(inline) {
-    return (inline !== false ? this : this.toArray())._reverse();
-  },
-
-  reduce: function() {
-    return this.length > 1 ? this : this[0];
-  },
-
-  uniq: function(sorted) {
-    return this.inject([], function(array, value, index) {
-      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
-        array.push(value);
-      return array;
-    });
-  },
+    empty: function()
+    {
+        return this == '';
+    },
 
-  intersect: function(array) {
-    return this.uniq().findAll(function(item) {
-      return array.detect(function(value) { return item === value });
-    });
-  },
+    blank: function()
+    {
+        return /^\s*$/.test(this);
+    },
 
-  clone: function() {
-    return [].concat(this);
-  },
-
-  size: function() {
-    return this.length;
-  },
-
-  inspect: function() {
-    return '[' + this.map(Object.inspect).join(', ') + ']';
-  },
-
-  toJSON: function() {
-    var results = [];
-    this.each(function(object) {
-      var value = Object.toJSON(object);
-      if (value !== undefined) results.push(value);
-    });
-    return '[' + results.join(', ') + ']';
-  }
+    interpolate: function(object, pattern)
+    {
+        return new Template(this, pattern).evaluate(object);
+    }
 });
 
-// use native browser JS 1.6 implementation if available
-if (Object.isFunction(Array.prototype.forEach))
-  Array.prototype._each = Array.prototype.forEach;
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+    escapeHTML: function()
+    {
+        return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+    },
+    unescapeHTML: function()
+    {
+        return this.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
+    }
+});
 
-if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
-  i || (i = 0);
-  var length = this.length;
-  if (i < 0) i = length + i;
-  for (; i < length; i++)
-    if (this[i] === item) return i;
-  return -1;
+String.prototype.gsub.prepareReplacement = function(replacement)
+{
+    if (Object.isFunction(replacement)) return replacement;
+    var template = new Template(replacement);
+    return function(match)
+    {
+        return template.evaluate(match)
+    };
 };
 
-if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
-  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
-  var n = this.slice(0, i).reverse().indexOf(item);
-  return (n < 0) ? n : i - n - 1;
-};
+String.prototype.parseQuery = String.prototype.toQueryParams;
 
-Array.prototype.toArray = Array.prototype.clone;
+Object.extend(String.prototype.escapeHTML, {
+    div:  document.createElement('div'),
+    text: document.createTextNode('')
+});
 
-function $w(string) {
-  if (!Object.isString(string)) return [];
-  string = string.strip();
-  return string ? string.split(/\s+/) : [];
-}
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+    initialize: function(template, pattern)
+    {
+        this.template = template.toString();
+        this.pattern = pattern || Template.Pattern;
+    },
+
+    evaluate: function(object)
+    {
+        if (Object.isFunction(object.toTemplateReplacements))
+            object = object.toTemplateReplacements();
+
+        return this.template.gsub(this.pattern, function(match)
+        {
+            if (object == null) return '';
+
+            var before = match[1] || '';
+            if (before == '\\') return match[2];
+
+            var ctx = object, expr = match[3];
+            var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
+            if (match == null) return before;
+
+            while (match != null)
+            {
+                var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+                ctx = ctx[comp];
+                if (null == ctx || '' == match[3]) break;
+                expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+                match = pattern.exec(expr);
+            }
 
-if (Prototype.Browser.Opera){
-  Array.prototype.concat = function() {
-    var array = [];
-    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
-    for (var i = 0, length = arguments.length; i < length; i++) {
-      if (Object.isArray(arguments[i])) {
-        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
-          array.push(arguments[i][j]);
-      } else {
-        array.push(arguments[i]);
-      }
+            return before + String.interpret(ctx);
+        }.bind(this));
     }
-    return array;
-  };
-}
-Object.extend(Number.prototype, {
-  toColorPart: function() {
-    return this.toPaddedString(2, 16);
-  },
-
-  succ: function() {
-    return this + 1;
-  },
-
-  times: function(iterator) {
-    $R(0, this, true).each(iterator);
-    return this;
-  },
-
-  toPaddedString: function(length, radix) {
-    var string = this.toString(radix || 10);
-    return '0'.times(length - string.length) + string;
-  },
-
-  toJSON: function() {
-    return isFinite(this) ? this.toString() : 'null';
-  }
 });
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
 
-$w('abs round ceil floor').each(function(method){
-  Number.prototype[method] = Math[method].methodize();
-});
-function $H(object) {
-  return new Hash(object);
-};
+var $break = { };
 
-var Hash = Class.create(Enumerable, (function() {
-  if (function() {
-    var i = 0, Test = function(value) { this.key = value };
-    Test.prototype.key = 'foo';
-    for (var property in new Test('bar')) i++;
-    return i > 1;
-  }()) {
-    function each(iterator) {
-      var cache = [];
-      for (var key in this._object) {
-        var value = this._object[key];
-        if (cache.include(key)) continue;
-        cache.push(key);
-        var pair = [key, value];
-        pair.key = key;
-        pair.value = value;
-        iterator(pair);
-      }
-    }
-  } else {
-    function each(iterator) {
-      for (var key in this._object) {
-        var value = this._object[key], pair = [key, value];
-        pair.key = key;
-        pair.value = value;
-        iterator(pair);
-      }
-    }
-  }
+var Enumerable = {
+    each: function(iterator, context)
+    {
+        var index = 0;
+        iterator = iterator.bind(context);
+        try
+        {
+            this._each(function(value)
+            {
+                iterator(value, index++);
+            });
+        }
+        catch (e)
+        {
+            if (e != $break) throw e;
+        }
+        return this;
+    },
 
-  function toQueryPair(key, value) {
-    if (Object.isUndefined(value)) return key;
-    return key + '=' + encodeURIComponent(String.interpret(value));
-  }
+    eachSlice: function(number, iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var index = -number, slices = [], array = this.toArray();
+        while ((index += number) < array.length)
+            slices.push(array.slice(index, index + number));
+        return slices.collect(iterator, context);
+    },
+
+    all: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var result = true;
+        this.each(function(value, index)
+        {
+            result = result && !!iterator(value, index);
+            if (!result) throw $break;
+        });
+        return result;
+    },
 
-  return {
-    initialize: function(object) {
-      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+    any: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var result = false;
+        this.each(function(value, index)
+        {
+            if (result = !!iterator(value, index))
+                throw $break;
+        });
+        return result;
     },
 
-    _each: each,
+    collect: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var results = [];
+        this.each(function(value, index)
+        {
+            results.push(iterator(value, index));
+        });
+        return results;
+    },
 
-    set: function(key, value) {
-      return this._object[key] = value;
+    detect: function(iterator, context)
+    {
+        iterator = iterator.bind(context);
+        var result;
+        this.each(function(value, index)
+        {
+            if (iterator(value, index))
+            {
+                result = value;
+                throw $break;
+            }
+        });
+        return result;
     },
 
-    get: function(key) {
-      return this._object[key];
+    findAll: function(iterator, context)
+    {
+        iterator = iterator.bind(context);
+        var results = [];
+        this.each(function(value, index)
+        {
+            if (iterator(value, index))
+                results.push(value);
+        });
+        return results;
     },
 
-    unset: function(key) {
-      var value = this._object[key];
-      delete this._object[key];
-      return value;
+    grep: function(filter, iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var results = [];
+
+        if (Object.isString(filter))
+            filter = new RegExp(filter);
+
+        this.each(function(value, index)
+        {
+            if (filter.match(value))
+                results.push(iterator(value, index));
+        });
+        return results;
     },
 
-    toObject: function() {
-      return Object.clone(this._object);
+    include: function(object)
+    {
+        if (Object.isFunction(this.indexOf))
+            if (this.indexOf(object) != -1) return true;
+
+        var found = false;
+        this.each(function(value)
+        {
+            if (value == object)
+            {
+                found = true;
+                throw $break;
+            }
+        });
+        return found;
     },
 
-    keys: function() {
-      return this.pluck('key');
+    inGroupsOf: function(number, fillWith)
+    {
+        fillWith = fillWith === undefined ? null : fillWith;
+        return this.eachSlice(number, function(slice)
+        {
+            while (slice.length < number) slice.push(fillWith);
+            return slice;
+        });
     },
 
-    values: function() {
-      return this.pluck('value');
+    inject: function(memo, iterator, context)
+    {
+        iterator = iterator.bind(context);
+        this.each(function(value, index)
+        {
+            memo = iterator(memo, value, index);
+        });
+        return memo;
     },
 
-    index: function(value) {
-      var match = this.detect(function(pair) {
-        return pair.value === value;
-      });
-      return match && match.key;
+    invoke: function(method)
+    {
+        var args = $A(arguments).slice(1);
+        return this.map(function(value)
+        {
+            return value[method].apply(value, args);
+        });
     },
 
-    merge: function(object) {
-      return this.clone().update(object);
+    max: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var result;
+        this.each(function(value, index)
+        {
+            value = iterator(value, index);
+            if (result == undefined || value >= result)
+                result = value;
+        });
+        return result;
     },
 
-    update: function(object) {
-      return new Hash(object).inject(this, function(result, pair) {
-        result.set(pair.key, pair.value);
+    min: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var result;
+        this.each(function(value, index)
+        {
+            value = iterator(value, index);
+            if (result == undefined || value < result)
+                result = value;
+        });
         return result;
-      });
     },
 
-    toQueryString: function() {
-      return this.map(function(pair) {
-        var key = encodeURIComponent(pair.key), values = pair.value;
+    partition: function(iterator, context)
+    {
+        iterator = iterator ? iterator.bind(context) : Prototype.K;
+        var trues = [], falses = [];
+        this.each(function(value, index)
+        {
+            (iterator(value, index) ?
+             trues : falses).push(value);
+        });
+        return [trues, falses];
+    },
 
-        if (values && typeof values == 'object') {
-          if (Object.isArray(values))
-            return values.map(toQueryPair.curry(key)).join('&');
-        }
-        return toQueryPair(key, values);
-      }).join('&');
+    pluck: function(property)
+    {
+        var results = [];
+        this.each(function(value)
+        {
+            results.push(value[property]);
+        });
+        return results;
+    },
+
+    reject: function(iterator, context)
+    {
+        iterator = iterator.bind(context);
+        var results = [];
+        this.each(function(value, index)
+        {
+            if (!iterator(value, index))
+                results.push(value);
+        });
+        return results;
     },
 
-    inspect: function() {
-      return '#<Hash:{' + this.map(function(pair) {
-        return pair.map(Object.inspect).join(': ');
-      }).join(', ') + '}>';
+    sortBy: function(iterator, context)
+    {
+        iterator = iterator.bind(context);
+        return this.map(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.map();
+    },
+
+    zip: function()
+    {
+        var iterator = Prototype.K, args = $A(arguments);
+        if (Object.isFunction(args.last()))
+            iterator = args.pop();
+
+        var collections = [this].concat(args).map($A);
+        return this.map(function(value, index)
+        {
+            return iterator(collections.pluck(index));
+        });
     },
 
-    toJSON: function() {
-      return Object.toJSON(this.toObject());
+    size: function()
+    {
+        return this.toArray().length;
     },
 
-    clone: function() {
-      return new Hash(this);
+    inspect: function()
+    {
+        return '#<Enumerable:' + this.toArray().inspect() + '>';
     }
-  }
-})());
+};
+
+Object.extend(Enumerable, {
+    map:     Enumerable.collect,
+    find:    Enumerable.detect,
+    select:  Enumerable.findAll,
+    filter:  Enumerable.findAll,
+    member:  Enumerable.include,
+    entries: Enumerable.toArray,
+    every:   Enumerable.all,
+    some:    Enumerable.any
+});
+function $A(iterable)
+{
+    if (!iterable) return [];
+    if (iterable.toArray) return iterable.toArray();
+    var length = iterable.length, results = new Array(length);
+    while (length--) results[length] = iterable[length];
+    return results;
+}
+
+if (Prototype.Browser.WebKit)
+{
+    function $A(iterable)
+    {
+        if (!iterable) return [];
+        if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+            iterable.toArray) return iterable.toArray();
+        var length = iterable.length, results = new Array(length);
+        while (length--) results[length] = iterable[length];
+        return results;
+    }
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+    _each: function(iterator)
+    {
+        for (var i = 0, length = this.length; i < 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 != null;
+        });
+    },
+
+    flatten: function()
+    {
+        return this.inject([], function(array, value)
+        {
+            return array.concat(Object.isArray(value) ?
+                                value.flatten() : [value]);
+        });
+    },
+
+    without: function()
+    {
+        var values = $A(arguments);
+        return this.select(function(value)
+        {
+            return !values.include(value);
+        });
+    },
+
+    reverse: function(inline)
+    {
+        return (inline !== false ? this : this.toArray())._reverse();
+    },
+
+    reduce: function()
+    {
+        return this.length > 1 ? this : this[0];
+    },
+
+    uniq: function(sorted)
+    {
+        return this.inject([], function(array, value, index)
+        {
+            if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+                array.push(value);
+            return array;
+        });
+    },
+
+    intersect: function(array)
+    {
+        return this.uniq().findAll(function(item)
+        {
+            return array.detect(function(value)
+            {
+                return item === value
+            });
+        });
+    },
+
+    clone: function()
+    {
+        return [].concat(this);
+    },
+
+    size: function()
+    {
+        return this.length;
+    },
+
+    inspect: function()
+    {
+        return '[' + this.map(Object.inspect).join(', ') + ']';
+    },
+
+    toJSON: function()
+    {
+        var results = [];
+        this.each(function(object)
+        {
+            var value = Object.toJSON(object);
+            if (value !== undefined) results.push(value);
+        });
+        return '[' + results.join(', ') + ']';
+    }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+    Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i)
+{
+    i || (i = 0);
+    var length = this.length;
+    if (i < 0) i = length + i;
+    for (; i < length; i++)
+        if (this[i] === item) return i;
+    return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i)
+{
+    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+    var n = this.slice(0, i).reverse().indexOf(item);
+    return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string)
+{
+    if (!Object.isString(string)) return [];
+    string = string.strip();
+    return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera)
+{
+    Array.prototype.concat = function()
+    {
+        var array = [];
+        for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+        for (var i = 0, length = arguments.length; i < length; i++)
+        {
+            if (Object.isArray(arguments[i]))
+            {
+                for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+                    array.push(arguments[i][j]);
+            }
+            else
+            {
+                array.push(arguments[i]);
+            }
+        }
+        return array;
+    };
+}
+Object.extend(Number.prototype, {
+    toColorPart: function()
+    {
+        return this.toPaddedString(2, 16);
+    },
+
+    succ: function()
+    {
+        return this + 1;
+    },
+
+    times: function(iterator)
+    {
+        $R(0, this, true).each(iterator);
+        return this;
+    },
+
+    toPaddedString: function(length, radix)
+    {
+        var string = this.toString(radix || 10);
+        return '0'.times(length - string.length) + string;
+    },
+
+    toJSON: function()
+    {
+        return isFinite(this) ? this.toString() : 'null';
+    }
+});
+
+$w('abs round ceil floor').each(function(method)
+{
+    Number.prototype[method] = Math[method].methodize();
+});
+function $H(object)
+{
+    return new Hash(object);
+}
+;
+
+var Hash = Class.create(Enumerable, (function()
+{
+    if (function()
+    {
+        var i = 0, Test = function(value)
+        {
+            this.key = value
+        };
+        Test.prototype.key = 'foo';
+        for (var property in new Test('bar')) i++;
+        return i > 1;
+    }())
+    {
+        function each(iterator)
+        {
+            var cache = [];
+            for (var key in this._object)
+            {
+                var value = this._object[key];
+                if (cache.include(key)) continue;
+                cache.push(key);
+                var pair = [key, value];
+                pair.key = key;
+                pair.value = value;
+                iterator(pair);
+            }
+        }
+    }
+    else
+    {
+        function each(iterator)
+        {
+            for (var key in this._object)
+            {
+                var value = this._object[key], pair = [key, value];
+                pair.key = key;
+                pair.value = value;
+                iterator(pair);
+            }
+        }
+    }
+
+    function toQueryPair(key, value)
+    {
+        if (Object.isUndefined(value)) return key;
+        return key + '=' + encodeURIComponent(String.interpret(value));
+    }
+
+    return {
+        initialize: function(object)
+        {
+            this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+        },
+
+        _each: each,
+
+        set: function(key, value)
+        {
+            return this._object[key] = value;
+        },
+
+        get: function(key)
+        {
+            return this._object[key];
+        },
+
+        unset: function(key)
+        {
+            var value = this._object[key];
+            delete this._object[key];
+            return value;
+        },
+
+        toObject: function()
+        {
+            return Object.clone(this._object);
+        },
+
+        keys: function()
+        {
+            return this.pluck('key');
+        },
+
+        values: function()
+        {
+            return this.pluck('value');
+        },
+
+        index: function(value)
+        {
+            var match = this.detect(function(pair)
+            {
+                return pair.value === value;
+            });
+            return match && match.key;
+        },
+
+        merge: function(object)
+        {
+            return this.clone().update(object);
+        },
+
+        update: function(object)
+        {
+            return new Hash(object).inject(this, function(result, pair)
+            {
+                result.set(pair.key, pair.value);
+                return result;
+            });
+        },
+
+        toQueryString: function()
+        {
+            return this.map(function(pair)
+            {
+                var key = encodeURIComponent(pair.key), values = pair.value;
+
+                if (values && typeof values == 'object')
+                {
+                    if (Object.isArray(values))
+                        return values.map(toQueryPair.curry(key)).join('&');
+                }
+                return toQueryPair(key, values);
+            }).join('&');
+        },
+
+        inspect: function()
+        {
+            return '#<Hash:{' + this.map(function(pair)
+            {
+                return pair.map(Object.inspect).join(': ');
+            }).join(', ') + '}>';
+        },
+
+        toJSON: function()
+        {
+            return Object.toJSON(this.toObject());
+        },
+
+        clone: function()
+        {
+            return new Hash(this);
+        }
+    }
+})());
 
 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
 Hash.from = $H;
 var ObjectRange = Class.create(Enumerable, {
-  initialize: function(start, end, exclusive) {
-    this.start = start;
-    this.end = end;
-    this.exclusive = exclusive;
-  },
-
-  _each: function(iterator) {
-    var value = this.start;
-    while (this.include(value)) {
-      iterator(value);
-      value = value.succ();
-    }
-  },
-
-  include: function(value) {
-    if (value < this.start)
-      return false;
-    if (this.exclusive)
-      return value < this.end;
-    return value <= this.end;
-  }
+    initialize: function(start, end, exclusive)
+    {
+        this.start = start;
+        this.end = end;
+        this.exclusive = exclusive;
+    },
+
+    _each: function(iterator)
+    {
+        var value = this.start;
+        while (this.include(value))
+        {
+            iterator(value);
+            value = value.succ();
+        }
+    },
+
+    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 $R = function(start, end, exclusive)
+{
+    return new ObjectRange(start, end, exclusive);
 };
 
 var Ajax = {
-  getTransport: function() {
-    return Try.these(
-      function() {return new XMLHttpRequest()},
-      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
-      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
-    ) || false;
-  },
+    getTransport: function()
+    {
+        return Try.these(
+                function()
+                {
+                    return new XMLHttpRequest()
+                },
+                function()
+                {
+                    return new ActiveXObject('Msxml2.XMLHTTP')
+                },
+                function()
+                {
+                    return new ActiveXObject('Microsoft.XMLHTTP')
+                }
+                ) || false;
+    },
 
-  activeRequestCount: 0
+    activeRequestCount: 0
 };
 
 Ajax.Responders = {
-  responders: [],
+    responders: [],
 
-  _each: function(iterator) {
-    this.responders._each(iterator);
-  },
-
-  register: function(responder) {
-    if (!this.include(responder))
-      this.responders.push(responder);
-  },
-
-  unregister: function(responder) {
-    this.responders = this.responders.without(responder);
-  },
-
-  dispatch: function(callback, request, transport, json) {
-    this.each(function(responder) {
-      if (Object.isFunction(responder[callback])) {
-        try {
-          responder[callback].apply(responder, [request, transport, json]);
-        } catch (e) { }
-      }
-    });
-  }
+    _each: function(iterator)
+    {
+        this.responders._each(iterator);
+    },
+
+    register: function(responder)
+    {
+        if (!this.include(responder))
+            this.responders.push(responder);
+    },
+
+    unregister: function(responder)
+    {
+        this.responders = this.responders.without(responder);
+    },
+
+    dispatch: function(callback, request, transport, json)
+    {
+        this.each(function(responder)
+        {
+            if (Object.isFunction(responder[callback]))
+            {
+                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-- }
+    onCreate:   function()
+    {
+        Ajax.activeRequestCount++
+    },
+    onComplete: function()
+    {
+        Ajax.activeRequestCount--
+    }
 });
 
 Ajax.Base = Class.create({
-  initialize: function(options) {
-    this.options = {
-      method:       'post',
-      asynchronous: true,
-      contentType:  'application/x-www-form-urlencoded',
-      encoding:     'UTF-8',
-      parameters:   '',
-      evalJSON:     true,
-      evalJS:       true
-    };
-    Object.extend(this.options, options || { });
-
-    this.options.method = this.options.method.toLowerCase();
-    if (Object.isString(this.options.parameters))
-      this.options.parameters = this.options.parameters.toQueryParams();
-  }
+    initialize: function(options)
+    {
+        this.options = {
+            method:       'post',
+            asynchronous: true,
+            contentType:  'application/x-www-form-urlencoded',
+            encoding:     'UTF-8',
+            parameters:   '',
+            evalJSON:     true,
+            evalJS:       true
+        };
+        Object.extend(this.options, options || { });
+
+        this.options.method = this.options.method.toLowerCase();
+        if (Object.isString(this.options.parameters))
+            this.options.parameters = this.options.parameters.toQueryParams();
+    }
 });
 
 Ajax.Request = Class.create(Ajax.Base, {
-  _complete: false,
+    _complete: false,
 
-  initialize: function($super, url, options) {
-    $super(options);
-    this.transport = Ajax.getTransport();
-    this.request(url);
-  },
+    initialize: function($super, url, options)
+    {
+        $super(options);
+        this.transport = Ajax.getTransport();
+        this.request(url);
+    },
+
+    request: function(url)
+    {
+        this.url = url;
+        this.method = this.options.method;
+        var params = Object.clone(this.options.parameters);
+
+        if (!['get', 'post'].include(this.method))
+        {
+            // simulate other verbs over post
+            params['_method'] = this.method;
+            this.method = 'post';
+        }
 
-  request: function(url) {
-    this.url = url;
-    this.method = this.options.method;
-    var params = Object.clone(this.options.parameters);
+        this.parameters = params;
 
-    if (!['get', 'post'].include(this.method)) {
-      // simulate other verbs over post
-      params['_method'] = this.method;
-      this.method = 'post';
-    }
+        if (params = Object.toQueryString(params))
+        {
+            // when GET, append parameters to URL
+            if (this.method == 'get')
+                this.url += (this.url.include('?') ? '&' : '?') + params;
+            else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+                params += '&_=';
+        }
 
-    this.parameters = params;
+        try
+        {
+            var response = new Ajax.Response(this);
+            if (this.options.onCreate) this.options.onCreate(response);
+            Ajax.Responders.dispatch('onCreate', this, response);
+
+            this.transport.open(this.method.toUpperCase(), this.url,
+                    this.options.asynchronous);
+
+            if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+            this.transport.onreadystatechange = this.onStateChange.bind(this);
+            this.setRequestHeaders();
+
+            this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+            this.transport.send(this.body);
+
+            /* Force Firefox to handle ready state 4 for synchronous requests */
+            if (!this.options.asynchronous && this.transport.overrideMimeType)
+                this.onStateChange();
 
-    if (params = Object.toQueryString(params)) {
-      // when GET, append parameters to URL
-      if (this.method == 'get')
-        this.url += (this.url.include('?') ? '&' : '?') + params;
-      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
-        params += '&_=';
-    }
+        }
+        catch (e)
+        {
+            this.dispatchException(e);
+        }
+    },
 
-    try {
-      var response = new Ajax.Response(this);
-      if (this.options.onCreate) this.options.onCreate(response);
-      Ajax.Responders.dispatch('onCreate', this, response);
+    onStateChange: function()
+    {
+        var readyState = this.transport.readyState;
+        if (readyState > 1 && !((readyState == 4) && this._complete))
+            this.respondToReadyState(this.transport.readyState);
+    },
+
+    setRequestHeaders: function()
+    {
+        var headers = {
+            'X-Requested-With': 'XMLHttpRequest',
+            'X-Prototype-Version': Prototype.Version,
+            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+        };
+
+        if (this.method == 'post')
+        {
+            headers['Content-type'] = this.options.contentType +
+                                      (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+            /* Force "Connection: close" for older Mozilla browsers to work
+            * around a bug where XMLHttpRequest sends an incorrect
+            * Content-length header. See Mozilla Bugzilla #246651.
+            */
+            if (this.transport.overrideMimeType &&
+                (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+                headers['Connection'] = 'close';
+        }
 
-      this.transport.open(this.method.toUpperCase(), this.url,
-        this.options.asynchronous);
+    // user-defined headers
+        if (typeof this.options.requestHeaders == 'object')
+        {
+            var extras = this.options.requestHeaders;
+
+            if (Object.isFunction(extras.push))
+                for (var i = 0, length = extras.length; i < length; i += 2)
+                    headers[extras[i]] = extras[i + 1];
+            else
+                $H(extras).each(function(pair)
+                {
+                    headers[pair.key] = pair.value
+                });
+        }
 
-      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+        for (var name in headers)
+            this.transport.setRequestHeader(name, headers[name]);
+    },
 
-      this.transport.onreadystatechange = this.onStateChange.bind(this);
-      this.setRequestHeaders();
+    success: function()
+    {
+        var status = this.getStatus();
+        return !status || (status >= 200 && status < 300);
+    },
 
-      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
-      this.transport.send(this.body);
+    getStatus: function()
+    {
+        try
+        {
+            return this.transport.status || 0;
+        }
+        catch (e)
+        {
+            return 0
+        }
+    },
 
-      /* Force Firefox to handle ready state 4 for synchronous requests */
-      if (!this.options.asynchronous && this.transport.overrideMimeType)
-        this.onStateChange();
+    respondToReadyState: function(readyState)
+    {
+        var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+        if (state == 'Complete')
+        {
+            try
+            {
+                this._complete = true;
+                (this.options['on' + response.status]
+                        || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+                        || Prototype.emptyFunction)(response, response.headerJSON);
+            }
+            catch (e)
+            {
+                this.dispatchException(e);
+            }
 
-    }
-    catch (e) {
-      this.dispatchException(e);
-    }
-  },
+            var contentType = response.getHeader('Content-type');
+            if (this.options.evalJS == 'force'
+                    || (this.options.evalJS && contentType
+                    && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+                this.evalResponse();
+        }
 
-  onStateChange: function() {
-    var readyState = this.transport.readyState;
-    if (readyState > 1 && !((readyState == 4) && this._complete))
-      this.respondToReadyState(this.transport.readyState);
-  },
+        try
+        {
+            (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+            Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+        }
+        catch (e)
+        {
+            this.dispatchException(e);
+        }
 
-  setRequestHeaders: function() {
-    var headers = {
-      'X-Requested-With': 'XMLHttpRequest',
-      'X-Prototype-Version': Prototype.Version,
-      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
-    };
+        if (state == 'Complete')
+        {
+            // avoid memory leak in MSIE: clean up
+            this.transport.onreadystatechange = Prototype.emptyFunction;
+        }
+    },
 
-    if (this.method == 'post') {
-      headers['Content-type'] = this.options.contentType +
-        (this.options.encoding ? '; charset=' + this.options.encoding : '');
-
-      /* Force "Connection: close" for older Mozilla browsers to work
-       * around a bug where XMLHttpRequest sends an incorrect
-       * Content-length header. See Mozilla Bugzilla #246651.
-       */
-      if (this.transport.overrideMimeType &&
-          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
-            headers['Connection'] = 'close';
-    }
+    getHeader: function(name)
+    {
+        try
+        {
+            return this.transport.getResponseHeader(name);
+        }
+        catch (e)
+        {
+            return null
+        }
+    },
 
-    // user-defined headers
-    if (typeof this.options.requestHeaders == 'object') {
-      var extras = this.options.requestHeaders;
+    evalResponse: function()
+    {
+        try
+        {
+            return eval((this.transport.responseText || '').unfilterJSON());
+        }
+        catch (e)
+        {
+            this.dispatchException(e);
+        }
+    },
 
-      if (Object.isFunction(extras.push))
-        for (var i = 0, length = extras.length; i < length; i += 2)
-          headers[extras[i]] = extras[i+1];
-      else
-        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
-    }
-
-    for (var name in headers)
-      this.transport.setRequestHeader(name, headers[name]);
-  },
-
-  success: function() {
-    var status = this.getStatus();
-    return !status || (status >= 200 && status < 300);
-  },
-
-  getStatus: function() {
-    try {
-      return this.transport.status || 0;
-    } catch (e) { return 0 }
-  },
-
-  respondToReadyState: function(readyState) {
-    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
-
-    if (state == 'Complete') {
-      try {
-        this._complete = true;
-        (this.options['on' + response.status]
-         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
-         || Prototype.emptyFunction)(response, response.headerJSON);
-      } catch (e) {
-        this.dispatchException(e);
-      }
-
-      var contentType = response.getHeader('Content-type');
-      if (this.options.evalJS == 'force'
-          || (this.options.evalJS && contentType
-          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
-        this.evalResponse();
-    }
-
-    try {
-      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
-      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-
-    if (state == 'Complete') {
-      // avoid memory leak in MSIE: clean up
-      this.transport.onreadystatechange = Prototype.emptyFunction;
-    }
-  },
-
-  getHeader: function(name) {
-    try {
-      return this.transport.getResponseHeader(name);
-    } catch (e) { return null }
-  },
-
-  evalResponse: function() {
-    try {
-      return eval((this.transport.responseText || '').unfilterJSON());
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  dispatchException: function(exception) {
-    (this.options.onException || Prototype.emptyFunction)(this, exception);
-    Ajax.Responders.dispatch('onException', this, exception);
-  }
+    dispatchException: function(exception)
+    {
+        (this.options.onException || Prototype.emptyFunction)(this, exception);
+        Ajax.Responders.dispatch('onException', this, exception);
+    }
 });
 
 Ajax.Request.Events =
-  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
 
 Ajax.Response = Class.create({
-  initialize: function(request){
-    this.request = request;
-    var transport  = this.transport  = request.transport,
-        readyState = this.readyState = transport.readyState;
-
-    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
-      this.status       = this.getStatus();
-      this.statusText   = this.getStatusText();
-      this.responseText = String.interpret(transport.responseText);
-      this.headerJSON   = this._getHeaderJSON();
-    }
-
-    if(readyState == 4) {
-      var xml = transport.responseXML;
-      this.responseXML  = xml === undefined ? null : xml;
-      this.responseJSON = this._getResponseJSON();
-    }
-  },
-
-  status:      0,
-  statusText: '',
-
-  getStatus: Ajax.Request.prototype.getStatus,
-
-  getStatusText: function() {
-    try {
-      return this.transport.statusText || '';
-    } catch (e) { return '' }
-  },
-
-  getHeader: Ajax.Request.prototype.getHeader,
-
-  getAllHeaders: function() {
-    try {
-      return this.getAllResponseHeaders();
-    } catch (e) { return null }
-  },
-
-  getResponseHeader: function(name) {
-    return this.transport.getResponseHeader(name);
-  },
-
-  getAllResponseHeaders: function() {
-    return this.transport.getAllResponseHeaders();
-  },
-
-  _getHeaderJSON: function() {
-    var json = this.getHeader('X-JSON');
-    if (!json) return null;
-    json = decodeURIComponent(escape(json));
-    try {
-      return json.evalJSON(this.request.options.sanitizeJSON);
-    } catch (e) {
-      this.request.dispatchException(e);
-    }
-  },
-
-  _getResponseJSON: function() {
-    var options = this.request.options;
-    if (!options.evalJSON || (options.evalJSON != 'force' &&
-      !(this.getHeader('Content-type') || '').include('application/json')))
-        return null;
-    try {
-      return this.transport.responseText.evalJSON(options.sanitizeJSON);
-    } catch (e) {
-      this.request.dispatchException(e);
-    }
-  }
-});
+    initialize: function(request)
+    {
+        this.request = request;
+        var transport = this.transport = request.transport,
+                readyState = this.readyState = transport.readyState;
+
+        if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4)
+        {
+            this.status = this.getStatus();
+            this.statusText = this.getStatusText();
+            this.responseText = String.interpret(transport.responseText);
+            this.headerJSON = this._getHeaderJSON();
+        }
 
-Ajax.Updater = Class.create(Ajax.Request, {
-  initialize: function($super, container, url, options) {
-    this.container = {
-      success: (container.success || container),
-      failure: (container.failure || (container.success ? null : container))
-    };
+        if (readyState == 4)
+        {
+            var xml = transport.responseXML;
+            this.responseXML = xml === undefined ? null : xml;
+            this.responseJSON = this._getResponseJSON();
+        }
+    },
+
+    status:      0,
+    statusText: '',
 
-    options = options || { };
-    var onComplete = options.onComplete;
-    options.onComplete = (function(response, param) {
-      this.updateContent(response.responseText);
-      if (Object.isFunction(onComplete)) onComplete(response, param);
-    }).bind(this);
+    getStatus: Ajax.Request.prototype.getStatus,
+
+    getStatusText: function()
+    {
+        try
+        {
+            return this.transport.statusText || '';
+        }
+        catch (e)
+        {
+            return ''
+        }
+    },
 
-    $super(url, options);
-  },
+    getHeader: Ajax.Request.prototype.getHeader,
 
-  updateContent: function(responseText) {
-    var receiver = this.container[this.success() ? 'success' : 'failure'],
-        options = this.options;
+    getAllHeaders: function()
+    {
+        try
+        {
+            return this.getAllResponseHeaders();
+        }
+        catch (e)
+        {
+            return null
+        }
+    },
 
-    if (!options.evalScripts) responseText = responseText.stripScripts();
+    getResponseHeader: function(name)
+    {
+        return this.transport.getResponseHeader(name);
+    },
+
+    getAllResponseHeaders: function()
+    {
+        return this.transport.getAllResponseHeaders();
+    },
+
+    _getHeaderJSON: function()
+    {
+        var json = this.getHeader('X-JSON');
+        if (!json) return null;
+        json = decodeURIComponent(escape(json));
+        try
+        {
+            return json.evalJSON(this.request.options.sanitizeJSON);
+        }
+        catch (e)
+        {
+            this.request.dispatchException(e);
+        }
+    },
 
-    if (receiver = $(receiver)) {
-      if (options.insertion) {
-        if (Object.isString(options.insertion)) {
-          var insertion = { }; insertion[options.insertion] = responseText;
-          receiver.insert(insertion);
+    _getResponseJSON: function()
+    {
+        var options = this.request.options;
+        if (!options.evalJSON || (options.evalJSON != 'force' &&
+                                  !(this.getHeader('Content-type') || '').include('application/json')))
+            return null;
+        try
+        {
+            return this.transport.responseText.evalJSON(options.sanitizeJSON);
+        }
+        catch (e)
+        {
+            this.request.dispatchException(e);
         }
-        else options.insertion(receiver, responseText);
-      }
-      else receiver.update(responseText);
     }
+});
 
-    if (this.success()) {
-      if (this.onComplete) this.onComplete.bind(this).defer();
+Ajax.Updater = Class.create(Ajax.Request, {
+    initialize: function($super, container, url, options)
+    {
+        this.container = {
+            success: (container.success || container),
+            failure: (container.failure || (container.success ? null : container))
+        };
+
+        options = options || { };
+        var onComplete = options.onComplete;
+        options.onComplete = (function(response, param)
+        {
+            this.updateContent(response.responseText);
+            if (Object.isFunction(onComplete)) onComplete(response, param);
+        }).bind(this);
+
+        $super(url, options);
+    },
+
+    updateContent: function(responseText)
+    {
+        var receiver = this.container[this.success() ? 'success' : 'failure'],
+                options = this.options;
+
+        if (!options.evalScripts) responseText = responseText.stripScripts();
+
+        if (receiver = $(receiver))
+        {
+            if (options.insertion)
+            {
+                if (Object.isString(options.insertion))
+                {
+                    var insertion = { };
+                    insertion[options.insertion] = responseText;
+                    receiver.insert(insertion);
+                }
+                else options.insertion(receiver, responseText);
+            }
+            else receiver.update(responseText);
+        }
+
+        if (this.success())
+        {
+            if (this.onComplete) this.onComplete.bind(this).defer();
+        }
     }
-  }
 });
 
 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
-  initialize: function($super, container, url, options) {
-    $super(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.options.onComplete = undefined;
-    clearTimeout(this.timer);
-    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
-  },
-
-  updateComplete: function(response) {
-    if (this.options.decay) {
-      this.decay = (response.responseText == this.lastText ?
-        this.decay * this.options.decay : 1);
-
-      this.lastText = response.responseText;
-    }
-    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
-  },
-
-  onTimerEvent: function() {
-    this.updater = new Ajax.Updater(this.container, this.url, this.options);
-  }
+    initialize: function($super, container, url, options)
+    {
+        $super(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.options.onComplete = undefined;
+        clearTimeout(this.timer);
+        (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+    },
+
+    updateComplete: function(response)
+    {
+        if (this.options.decay)
+        {
+            this.decay = (response.responseText == this.lastText ?

[... 5562 lines stripped ...]