PageRenderTime 123ms CodeModel.GetById 17ms app.highlight 84ms RepoModel.GetById 1ms app.codeStats 2ms

/public/prototype.js

http://github.com/mtravers/wuwei
JavaScript | 6081 lines | 5337 code | 718 blank | 26 comment | 763 complexity | 007ae2fe795811f80cedf92fdb591c1b MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*  Prototype JavaScript framework, version 1.7
   2 *  (c) 2005-2010 Sam Stephenson
   3 *
   4 *  Prototype is freely distributable under the terms of an MIT-style license.
   5 *  For details, see the Prototype web site: http://www.prototypejs.org/
   6 *
   7 *--------------------------------------------------------------------------*/
   8
   9var Prototype = {
  10
  11  Version: '1.7',
  12
  13  Browser: (function(){
  14    var ua = navigator.userAgent;
  15    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
  16    return {
  17      IE:             !!window.attachEvent && !isOpera,
  18      Opera:          isOpera,
  19      WebKit:         ua.indexOf('AppleWebKit/') > -1,
  20      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
  21      MobileSafari:   /Apple.*Mobile/.test(ua)
  22    }
  23  })(),
  24
  25  BrowserFeatures: {
  26    XPath: !!document.evaluate,
  27
  28    SelectorsAPI: !!document.querySelector,
  29
  30    ElementExtensions: (function() {
  31      var constructor = window.Element || window.HTMLElement;
  32      return !!(constructor && constructor.prototype);
  33    })(),
  34    SpecificElementExtensions: (function() {
  35      if (typeof window.HTMLDivElement !== 'undefined')
  36        return true;
  37
  38      var div = document.createElement('div'),
  39          form = document.createElement('form'),
  40          isSupported = false;
  41
  42      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
  43        isSupported = true;
  44      }
  45
  46      div = form = null;
  47
  48      return isSupported;
  49    })()
  50  },
  51
  52  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
  53  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
  54
  55  emptyFunction: function() { },
  56
  57  K: function(x) { return x }
  58};
  59
  60if (Prototype.Browser.MobileSafari)
  61  Prototype.BrowserFeatures.SpecificElementExtensions = false;
  62/* Based on Alex Arnell's inheritance implementation. */
  63
  64var Class = (function() {
  65
  66  var IS_DONTENUM_BUGGY = (function(){
  67    for (var p in { toString: 1 }) {
  68      if (p === 'toString') return false;
  69    }
  70    return true;
  71  })();
  72
  73  function subclass() {};
  74  function create() {
  75    var parent = null, properties = $A(arguments);
  76    if (Object.isFunction(properties[0]))
  77      parent = properties.shift();
  78
  79    function klass() {
  80      this.initialize.apply(this, arguments);
  81    }
  82
  83    Object.extend(klass, Class.Methods);
  84    klass.superclass = parent;
  85    klass.subclasses = [];
  86
  87    if (parent) {
  88      subclass.prototype = parent.prototype;
  89      klass.prototype = new subclass;
  90      parent.subclasses.push(klass);
  91    }
  92
  93    for (var i = 0, length = properties.length; i < length; i++)
  94      klass.addMethods(properties[i]);
  95
  96    if (!klass.prototype.initialize)
  97      klass.prototype.initialize = Prototype.emptyFunction;
  98
  99    klass.prototype.constructor = klass;
 100    return klass;
 101  }
 102
 103  function addMethods(source) {
 104    var ancestor   = this.superclass && this.superclass.prototype,
 105        properties = Object.keys(source);
 106
 107    if (IS_DONTENUM_BUGGY) {
 108      if (source.toString != Object.prototype.toString)
 109        properties.push("toString");
 110      if (source.valueOf != Object.prototype.valueOf)
 111        properties.push("valueOf");
 112    }
 113
 114    for (var i = 0, length = properties.length; i < length; i++) {
 115      var property = properties[i], value = source[property];
 116      if (ancestor && Object.isFunction(value) &&
 117          value.argumentNames()[0] == "$super") {
 118        var method = value;
 119        value = (function(m) {
 120          return function() { return ancestor[m].apply(this, arguments); };
 121        })(property).wrap(method);
 122
 123        value.valueOf = method.valueOf.bind(method);
 124        value.toString = method.toString.bind(method);
 125      }
 126      this.prototype[property] = value;
 127    }
 128
 129    return this;
 130  }
 131
 132  return {
 133    create: create,
 134    Methods: {
 135      addMethods: addMethods
 136    }
 137  };
 138})();
 139(function() {
 140
 141  var _toString = Object.prototype.toString,
 142      NULL_TYPE = 'Null',
 143      UNDEFINED_TYPE = 'Undefined',
 144      BOOLEAN_TYPE = 'Boolean',
 145      NUMBER_TYPE = 'Number',
 146      STRING_TYPE = 'String',
 147      OBJECT_TYPE = 'Object',
 148      FUNCTION_CLASS = '[object Function]',
 149      BOOLEAN_CLASS = '[object Boolean]',
 150      NUMBER_CLASS = '[object Number]',
 151      STRING_CLASS = '[object String]',
 152      ARRAY_CLASS = '[object Array]',
 153      DATE_CLASS = '[object Date]',
 154      NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
 155        typeof JSON.stringify === 'function' &&
 156        JSON.stringify(0) === '0' &&
 157        typeof JSON.stringify(Prototype.K) === 'undefined';
 158
 159  function Type(o) {
 160    switch(o) {
 161      case null: return NULL_TYPE;
 162      case (void 0): return UNDEFINED_TYPE;
 163    }
 164    var type = typeof o;
 165    switch(type) {
 166      case 'boolean': return BOOLEAN_TYPE;
 167      case 'number':  return NUMBER_TYPE;
 168      case 'string':  return STRING_TYPE;
 169    }
 170    return OBJECT_TYPE;
 171  }
 172
 173  function extend(destination, source) {
 174    for (var property in source)
 175      destination[property] = source[property];
 176    return destination;
 177  }
 178
 179  function inspect(object) {
 180    try {
 181      if (isUndefined(object)) return 'undefined';
 182      if (object === null) return 'null';
 183      return object.inspect ? object.inspect() : String(object);
 184    } catch (e) {
 185      if (e instanceof RangeError) return '...';
 186      throw e;
 187    }
 188  }
 189
 190  function toJSON(value) {
 191    return Str('', { '': value }, []);
 192  }
 193
 194  function Str(key, holder, stack) {
 195    var value = holder[key],
 196        type = typeof value;
 197
 198    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
 199      value = value.toJSON(key);
 200    }
 201
 202    var _class = _toString.call(value);
 203
 204    switch (_class) {
 205      case NUMBER_CLASS:
 206      case BOOLEAN_CLASS:
 207      case STRING_CLASS:
 208        value = value.valueOf();
 209    }
 210
 211    switch (value) {
 212      case null: return 'null';
 213      case true: return 'true';
 214      case false: return 'false';
 215    }
 216
 217    type = typeof value;
 218    switch (type) {
 219      case 'string':
 220        return value.inspect(true);
 221      case 'number':
 222        return isFinite(value) ? String(value) : 'null';
 223      case 'object':
 224
 225        for (var i = 0, length = stack.length; i < length; i++) {
 226          if (stack[i] === value) { throw new TypeError(); }
 227        }
 228        stack.push(value);
 229
 230        var partial = [];
 231        if (_class === ARRAY_CLASS) {
 232          for (var i = 0, length = value.length; i < length; i++) {
 233            var str = Str(i, value, stack);
 234            partial.push(typeof str === 'undefined' ? 'null' : str);
 235          }
 236          partial = '[' + partial.join(',') + ']';
 237        } else {
 238          var keys = Object.keys(value);
 239          for (var i = 0, length = keys.length; i < length; i++) {
 240            var key = keys[i], str = Str(key, value, stack);
 241            if (typeof str !== "undefined") {
 242               partial.push(key.inspect(true)+ ':' + str);
 243             }
 244          }
 245          partial = '{' + partial.join(',') + '}';
 246        }
 247        stack.pop();
 248        return partial;
 249    }
 250  }
 251
 252  function stringify(object) {
 253    return JSON.stringify(object);
 254  }
 255
 256  function toQueryString(object) {
 257    return $H(object).toQueryString();
 258  }
 259
 260  function toHTML(object) {
 261    return object && object.toHTML ? object.toHTML() : String.interpret(object);
 262  }
 263
 264  function keys(object) {
 265    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
 266    var results = [];
 267    for (var property in object) {
 268      if (object.hasOwnProperty(property)) {
 269        results.push(property);
 270      }
 271    }
 272    return results;
 273  }
 274
 275  function values(object) {
 276    var results = [];
 277    for (var property in object)
 278      results.push(object[property]);
 279    return results;
 280  }
 281
 282  function clone(object) {
 283    return extend({ }, object);
 284  }
 285
 286  function isElement(object) {
 287    return !!(object && object.nodeType == 1);
 288  }
 289
 290  function isArray(object) {
 291    return _toString.call(object) === ARRAY_CLASS;
 292  }
 293
 294  var hasNativeIsArray = (typeof Array.isArray == 'function')
 295    && Array.isArray([]) && !Array.isArray({});
 296
 297  if (hasNativeIsArray) {
 298    isArray = Array.isArray;
 299  }
 300
 301  function isHash(object) {
 302    return object instanceof Hash;
 303  }
 304
 305  function isFunction(object) {
 306    return _toString.call(object) === FUNCTION_CLASS;
 307  }
 308
 309  function isString(object) {
 310    return _toString.call(object) === STRING_CLASS;
 311  }
 312
 313  function isNumber(object) {
 314    return _toString.call(object) === NUMBER_CLASS;
 315  }
 316
 317  function isDate(object) {
 318    return _toString.call(object) === DATE_CLASS;
 319  }
 320
 321  function isUndefined(object) {
 322    return typeof object === "undefined";
 323  }
 324
 325  extend(Object, {
 326    extend:        extend,
 327    inspect:       inspect,
 328    toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
 329    toQueryString: toQueryString,
 330    toHTML:        toHTML,
 331    keys:          Object.keys || keys,
 332    values:        values,
 333    clone:         clone,
 334    isElement:     isElement,
 335    isArray:       isArray,
 336    isHash:        isHash,
 337    isFunction:    isFunction,
 338    isString:      isString,
 339    isNumber:      isNumber,
 340    isDate:        isDate,
 341    isUndefined:   isUndefined
 342  });
 343})();
 344Object.extend(Function.prototype, (function() {
 345  var slice = Array.prototype.slice;
 346
 347  function update(array, args) {
 348    var arrayLength = array.length, length = args.length;
 349    while (length--) array[arrayLength + length] = args[length];
 350    return array;
 351  }
 352
 353  function merge(array, args) {
 354    array = slice.call(array, 0);
 355    return update(array, args);
 356  }
 357
 358  function argumentNames() {
 359    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
 360      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
 361      .replace(/\s+/g, '').split(',');
 362    return names.length == 1 && !names[0] ? [] : names;
 363  }
 364
 365  function bind(context) {
 366    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
 367    var __method = this, args = slice.call(arguments, 1);
 368    return function() {
 369      var a = merge(args, arguments);
 370      return __method.apply(context, a);
 371    }
 372  }
 373
 374  function bindAsEventListener(context) {
 375    var __method = this, args = slice.call(arguments, 1);
 376    return function(event) {
 377      var a = update([event || window.event], args);
 378      return __method.apply(context, a);
 379    }
 380  }
 381
 382  function curry() {
 383    if (!arguments.length) return this;
 384    var __method = this, args = slice.call(arguments, 0);
 385    return function() {
 386      var a = merge(args, arguments);
 387      return __method.apply(this, a);
 388    }
 389  }
 390
 391  function delay(timeout) {
 392    var __method = this, args = slice.call(arguments, 1);
 393    timeout = timeout * 1000;
 394    return window.setTimeout(function() {
 395      return __method.apply(__method, args);
 396    }, timeout);
 397  }
 398
 399  function defer() {
 400    var args = update([0.01], arguments);
 401    return this.delay.apply(this, args);
 402  }
 403
 404  function wrap(wrapper) {
 405    var __method = this;
 406    return function() {
 407      var a = update([__method.bind(this)], arguments);
 408      return wrapper.apply(this, a);
 409    }
 410  }
 411
 412  function methodize() {
 413    if (this._methodized) return this._methodized;
 414    var __method = this;
 415    return this._methodized = function() {
 416      var a = update([this], arguments);
 417      return __method.apply(null, a);
 418    };
 419  }
 420
 421  return {
 422    argumentNames:       argumentNames,
 423    bind:                bind,
 424    bindAsEventListener: bindAsEventListener,
 425    curry:               curry,
 426    delay:               delay,
 427    defer:               defer,
 428    wrap:                wrap,
 429    methodize:           methodize
 430  }
 431})());
 432
 433
 434
 435(function(proto) {
 436
 437
 438  function toISOString() {
 439    return this.getUTCFullYear() + '-' +
 440      (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
 441      this.getUTCDate().toPaddedString(2) + 'T' +
 442      this.getUTCHours().toPaddedString(2) + ':' +
 443      this.getUTCMinutes().toPaddedString(2) + ':' +
 444      this.getUTCSeconds().toPaddedString(2) + 'Z';
 445  }
 446
 447
 448  function toJSON() {
 449    return this.toISOString();
 450  }
 451
 452  if (!proto.toISOString) proto.toISOString = toISOString;
 453  if (!proto.toJSON) proto.toJSON = toJSON;
 454
 455})(Date.prototype);
 456
 457
 458RegExp.prototype.match = RegExp.prototype.test;
 459
 460RegExp.escape = function(str) {
 461  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
 462};
 463var PeriodicalExecuter = Class.create({
 464  initialize: function(callback, frequency) {
 465    this.callback = callback;
 466    this.frequency = frequency;
 467    this.currentlyExecuting = false;
 468
 469    this.registerCallback();
 470  },
 471
 472  registerCallback: function() {
 473    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
 474  },
 475
 476  execute: function() {
 477    this.callback(this);
 478  },
 479
 480  stop: function() {
 481    if (!this.timer) return;
 482    clearInterval(this.timer);
 483    this.timer = null;
 484  },
 485
 486  onTimerEvent: function() {
 487    if (!this.currentlyExecuting) {
 488      try {
 489        this.currentlyExecuting = true;
 490        this.execute();
 491        this.currentlyExecuting = false;
 492      } catch(e) {
 493        this.currentlyExecuting = false;
 494        throw e;
 495      }
 496    }
 497  }
 498});
 499Object.extend(String, {
 500  interpret: function(value) {
 501    return value == null ? '' : String(value);
 502  },
 503  specialChar: {
 504    '\b': '\\b',
 505    '\t': '\\t',
 506    '\n': '\\n',
 507    '\f': '\\f',
 508    '\r': '\\r',
 509    '\\': '\\\\'
 510  }
 511});
 512
 513Object.extend(String.prototype, (function() {
 514  var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
 515    typeof JSON.parse === 'function' &&
 516    JSON.parse('{"test": true}').test;
 517
 518  function prepareReplacement(replacement) {
 519    if (Object.isFunction(replacement)) return replacement;
 520    var template = new Template(replacement);
 521    return function(match) { return template.evaluate(match) };
 522  }
 523
 524  function gsub(pattern, replacement) {
 525    var result = '', source = this, match;
 526    replacement = prepareReplacement(replacement);
 527
 528    if (Object.isString(pattern))
 529      pattern = RegExp.escape(pattern);
 530
 531    if (!(pattern.length || pattern.source)) {
 532      replacement = replacement('');
 533      return replacement + source.split('').join(replacement) + replacement;
 534    }
 535
 536    while (source.length > 0) {
 537      if (match = source.match(pattern)) {
 538        result += source.slice(0, match.index);
 539        result += String.interpret(replacement(match));
 540        source  = source.slice(match.index + match[0].length);
 541      } else {
 542        result += source, source = '';
 543      }
 544    }
 545    return result;
 546  }
 547
 548  function sub(pattern, replacement, count) {
 549    replacement = prepareReplacement(replacement);
 550    count = Object.isUndefined(count) ? 1 : count;
 551
 552    return this.gsub(pattern, function(match) {
 553      if (--count < 0) return match[0];
 554      return replacement(match);
 555    });
 556  }
 557
 558  function scan(pattern, iterator) {
 559    this.gsub(pattern, iterator);
 560    return String(this);
 561  }
 562
 563  function truncate(length, truncation) {
 564    length = length || 30;
 565    truncation = Object.isUndefined(truncation) ? '...' : truncation;
 566    return this.length > length ?
 567      this.slice(0, length - truncation.length) + truncation : String(this);
 568  }
 569
 570  function strip() {
 571    return this.replace(/^\s+/, '').replace(/\s+$/, '');
 572  }
 573
 574  function stripTags() {
 575    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
 576  }
 577
 578  function stripScripts() {
 579    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
 580  }
 581
 582  function extractScripts() {
 583    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
 584        matchOne = new RegExp(Prototype.ScriptFragment, 'im');
 585    return (this.match(matchAll) || []).map(function(scriptTag) {
 586      return (scriptTag.match(matchOne) || ['', ''])[1];
 587    });
 588  }
 589
 590  function evalScripts() {
 591    return this.extractScripts().map(function(script) { return eval(script) });
 592  }
 593
 594  function escapeHTML() {
 595    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
 596  }
 597
 598  function unescapeHTML() {
 599    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
 600  }
 601
 602
 603  function toQueryParams(separator) {
 604    var match = this.strip().match(/([^?#]*)(#.*)?$/);
 605    if (!match) return { };
 606
 607    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
 608      if ((pair = pair.split('='))[0]) {
 609        var key = decodeURIComponent(pair.shift()),
 610            value = pair.length > 1 ? pair.join('=') : pair[0];
 611
 612        if (value != undefined) value = decodeURIComponent(value);
 613
 614        if (key in hash) {
 615          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
 616          hash[key].push(value);
 617        }
 618        else hash[key] = value;
 619      }
 620      return hash;
 621    });
 622  }
 623
 624  function toArray() {
 625    return this.split('');
 626  }
 627
 628  function succ() {
 629    return this.slice(0, this.length - 1) +
 630      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
 631  }
 632
 633  function times(count) {
 634    return count < 1 ? '' : new Array(count + 1).join(this);
 635  }
 636
 637  function camelize() {
 638    return this.replace(/-+(.)?/g, function(match, chr) {
 639      return chr ? chr.toUpperCase() : '';
 640    });
 641  }
 642
 643  function capitalize() {
 644    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
 645  }
 646
 647  function underscore() {
 648    return this.replace(/::/g, '/')
 649               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
 650               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
 651               .replace(/-/g, '_')
 652               .toLowerCase();
 653  }
 654
 655  function dasherize() {
 656    return this.replace(/_/g, '-');
 657  }
 658
 659  function inspect(useDoubleQuotes) {
 660    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
 661      if (character in String.specialChar) {
 662        return String.specialChar[character];
 663      }
 664      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
 665    });
 666    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
 667    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
 668  }
 669
 670  function unfilterJSON(filter) {
 671    return this.replace(filter || Prototype.JSONFilter, '$1');
 672  }
 673
 674  function isJSON() {
 675    var str = this;
 676    if (str.blank()) return false;
 677    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
 678    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
 679    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
 680    return (/^[\],:{}\s]*$/).test(str);
 681  }
 682
 683  function evalJSON(sanitize) {
 684    var json = this.unfilterJSON(),
 685        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
 686    if (cx.test(json)) {
 687      json = json.replace(cx, function (a) {
 688        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 689      });
 690    }
 691    try {
 692      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
 693    } catch (e) { }
 694    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
 695  }
 696
 697  function parseJSON() {
 698    var json = this.unfilterJSON();
 699    return JSON.parse(json);
 700  }
 701
 702  function include(pattern) {
 703    return this.indexOf(pattern) > -1;
 704  }
 705
 706  function startsWith(pattern) {
 707    return this.lastIndexOf(pattern, 0) === 0;
 708  }
 709
 710  function endsWith(pattern) {
 711    var d = this.length - pattern.length;
 712    return d >= 0 && this.indexOf(pattern, d) === d;
 713  }
 714
 715  function empty() {
 716    return this == '';
 717  }
 718
 719  function blank() {
 720    return /^\s*$/.test(this);
 721  }
 722
 723  function interpolate(object, pattern) {
 724    return new Template(this, pattern).evaluate(object);
 725  }
 726
 727  return {
 728    gsub:           gsub,
 729    sub:            sub,
 730    scan:           scan,
 731    truncate:       truncate,
 732    strip:          String.prototype.trim || strip,
 733    stripTags:      stripTags,
 734    stripScripts:   stripScripts,
 735    extractScripts: extractScripts,
 736    evalScripts:    evalScripts,
 737    escapeHTML:     escapeHTML,
 738    unescapeHTML:   unescapeHTML,
 739    toQueryParams:  toQueryParams,
 740    parseQuery:     toQueryParams,
 741    toArray:        toArray,
 742    succ:           succ,
 743    times:          times,
 744    camelize:       camelize,
 745    capitalize:     capitalize,
 746    underscore:     underscore,
 747    dasherize:      dasherize,
 748    inspect:        inspect,
 749    unfilterJSON:   unfilterJSON,
 750    isJSON:         isJSON,
 751    evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
 752    include:        include,
 753    startsWith:     startsWith,
 754    endsWith:       endsWith,
 755    empty:          empty,
 756    blank:          blank,
 757    interpolate:    interpolate
 758  };
 759})());
 760
 761var Template = Class.create({
 762  initialize: function(template, pattern) {
 763    this.template = template.toString();
 764    this.pattern = pattern || Template.Pattern;
 765  },
 766
 767  evaluate: function(object) {
 768    if (object && Object.isFunction(object.toTemplateReplacements))
 769      object = object.toTemplateReplacements();
 770
 771    return this.template.gsub(this.pattern, function(match) {
 772      if (object == null) return (match[1] + '');
 773
 774      var before = match[1] || '';
 775      if (before == '\\') return match[2];
 776
 777      var ctx = object, expr = match[3],
 778          pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
 779
 780      match = pattern.exec(expr);
 781      if (match == null) return before;
 782
 783      while (match != null) {
 784        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
 785        ctx = ctx[comp];
 786        if (null == ctx || '' == match[3]) break;
 787        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
 788        match = pattern.exec(expr);
 789      }
 790
 791      return before + String.interpret(ctx);
 792    });
 793  }
 794});
 795Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
 796
 797var $break = { };
 798
 799var Enumerable = (function() {
 800  function each(iterator, context) {
 801    var index = 0;
 802    try {
 803      this._each(function(value) {
 804        iterator.call(context, value, index++);
 805      });
 806    } catch (e) {
 807      if (e != $break) throw e;
 808    }
 809    return this;
 810  }
 811
 812  function eachSlice(number, iterator, context) {
 813    var index = -number, slices = [], array = this.toArray();
 814    if (number < 1) return array;
 815    while ((index += number) < array.length)
 816      slices.push(array.slice(index, index+number));
 817    return slices.collect(iterator, context);
 818  }
 819
 820  function all(iterator, context) {
 821    iterator = iterator || Prototype.K;
 822    var result = true;
 823    this.each(function(value, index) {
 824      result = result && !!iterator.call(context, value, index);
 825      if (!result) throw $break;
 826    });
 827    return result;
 828  }
 829
 830  function any(iterator, context) {
 831    iterator = iterator || Prototype.K;
 832    var result = false;
 833    this.each(function(value, index) {
 834      if (result = !!iterator.call(context, value, index))
 835        throw $break;
 836    });
 837    return result;
 838  }
 839
 840  function collect(iterator, context) {
 841    iterator = iterator || Prototype.K;
 842    var results = [];
 843    this.each(function(value, index) {
 844      results.push(iterator.call(context, value, index));
 845    });
 846    return results;
 847  }
 848
 849  function detect(iterator, context) {
 850    var result;
 851    this.each(function(value, index) {
 852      if (iterator.call(context, value, index)) {
 853        result = value;
 854        throw $break;
 855      }
 856    });
 857    return result;
 858  }
 859
 860  function findAll(iterator, context) {
 861    var results = [];
 862    this.each(function(value, index) {
 863      if (iterator.call(context, value, index))
 864        results.push(value);
 865    });
 866    return results;
 867  }
 868
 869  function grep(filter, iterator, context) {
 870    iterator = iterator || Prototype.K;
 871    var results = [];
 872
 873    if (Object.isString(filter))
 874      filter = new RegExp(RegExp.escape(filter));
 875
 876    this.each(function(value, index) {
 877      if (filter.match(value))
 878        results.push(iterator.call(context, value, index));
 879    });
 880    return results;
 881  }
 882
 883  function include(object) {
 884    if (Object.isFunction(this.indexOf))
 885      if (this.indexOf(object) != -1) return true;
 886
 887    var found = false;
 888    this.each(function(value) {
 889      if (value == object) {
 890        found = true;
 891        throw $break;
 892      }
 893    });
 894    return found;
 895  }
 896
 897  function inGroupsOf(number, fillWith) {
 898    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
 899    return this.eachSlice(number, function(slice) {
 900      while(slice.length < number) slice.push(fillWith);
 901      return slice;
 902    });
 903  }
 904
 905  function inject(memo, iterator, context) {
 906    this.each(function(value, index) {
 907      memo = iterator.call(context, memo, value, index);
 908    });
 909    return memo;
 910  }
 911
 912  function invoke(method) {
 913    var args = $A(arguments).slice(1);
 914    return this.map(function(value) {
 915      return value[method].apply(value, args);
 916    });
 917  }
 918
 919  function max(iterator, context) {
 920    iterator = iterator || Prototype.K;
 921    var result;
 922    this.each(function(value, index) {
 923      value = iterator.call(context, value, index);
 924      if (result == null || value >= result)
 925        result = value;
 926    });
 927    return result;
 928  }
 929
 930  function min(iterator, context) {
 931    iterator = iterator || Prototype.K;
 932    var result;
 933    this.each(function(value, index) {
 934      value = iterator.call(context, value, index);
 935      if (result == null || value < result)
 936        result = value;
 937    });
 938    return result;
 939  }
 940
 941  function partition(iterator, context) {
 942    iterator = iterator || Prototype.K;
 943    var trues = [], falses = [];
 944    this.each(function(value, index) {
 945      (iterator.call(context, value, index) ?
 946        trues : falses).push(value);
 947    });
 948    return [trues, falses];
 949  }
 950
 951  function pluck(property) {
 952    var results = [];
 953    this.each(function(value) {
 954      results.push(value[property]);
 955    });
 956    return results;
 957  }
 958
 959  function reject(iterator, context) {
 960    var results = [];
 961    this.each(function(value, index) {
 962      if (!iterator.call(context, value, index))
 963        results.push(value);
 964    });
 965    return results;
 966  }
 967
 968  function sortBy(iterator, context) {
 969    return this.map(function(value, index) {
 970      return {
 971        value: value,
 972        criteria: iterator.call(context, value, index)
 973      };
 974    }).sort(function(left, right) {
 975      var a = left.criteria, b = right.criteria;
 976      return a < b ? -1 : a > b ? 1 : 0;
 977    }).pluck('value');
 978  }
 979
 980  function toArray() {
 981    return this.map();
 982  }
 983
 984  function zip() {
 985    var iterator = Prototype.K, args = $A(arguments);
 986    if (Object.isFunction(args.last()))
 987      iterator = args.pop();
 988
 989    var collections = [this].concat(args).map($A);
 990    return this.map(function(value, index) {
 991      return iterator(collections.pluck(index));
 992    });
 993  }
 994
 995  function size() {
 996    return this.toArray().length;
 997  }
 998
 999  function inspect() {
1000    return '#<Enumerable:' + this.toArray().inspect() + '>';
1001  }
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011  return {
1012    each:       each,
1013    eachSlice:  eachSlice,
1014    all:        all,
1015    every:      all,
1016    any:        any,
1017    some:       any,
1018    collect:    collect,
1019    map:        collect,
1020    detect:     detect,
1021    findAll:    findAll,
1022    select:     findAll,
1023    filter:     findAll,
1024    grep:       grep,
1025    include:    include,
1026    member:     include,
1027    inGroupsOf: inGroupsOf,
1028    inject:     inject,
1029    invoke:     invoke,
1030    max:        max,
1031    min:        min,
1032    partition:  partition,
1033    pluck:      pluck,
1034    reject:     reject,
1035    sortBy:     sortBy,
1036    toArray:    toArray,
1037    entries:    toArray,
1038    zip:        zip,
1039    size:       size,
1040    inspect:    inspect,
1041    find:       detect
1042  };
1043})();
1044
1045function $A(iterable) {
1046  if (!iterable) return [];
1047  if ('toArray' in Object(iterable)) return iterable.toArray();
1048  var length = iterable.length || 0, results = new Array(length);
1049  while (length--) results[length] = iterable[length];
1050  return results;
1051}
1052
1053
1054function $w(string) {
1055  if (!Object.isString(string)) return [];
1056  string = string.strip();
1057  return string ? string.split(/\s+/) : [];
1058}
1059
1060Array.from = $A;
1061
1062
1063(function() {
1064  var arrayProto = Array.prototype,
1065      slice = arrayProto.slice,
1066      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1067
1068  function each(iterator, context) {
1069    for (var i = 0, length = this.length >>> 0; i < length; i++) {
1070      if (i in this) iterator.call(context, this[i], i, this);
1071    }
1072  }
1073  if (!_each) _each = each;
1074
1075  function clear() {
1076    this.length = 0;
1077    return this;
1078  }
1079
1080  function first() {
1081    return this[0];
1082  }
1083
1084  function last() {
1085    return this[this.length - 1];
1086  }
1087
1088  function compact() {
1089    return this.select(function(value) {
1090      return value != null;
1091    });
1092  }
1093
1094  function flatten() {
1095    return this.inject([], function(array, value) {
1096      if (Object.isArray(value))
1097        return array.concat(value.flatten());
1098      array.push(value);
1099      return array;
1100    });
1101  }
1102
1103  function without() {
1104    var values = slice.call(arguments, 0);
1105    return this.select(function(value) {
1106      return !values.include(value);
1107    });
1108  }
1109
1110  function reverse(inline) {
1111    return (inline === false ? this.toArray() : this)._reverse();
1112  }
1113
1114  function uniq(sorted) {
1115    return this.inject([], function(array, value, index) {
1116      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1117        array.push(value);
1118      return array;
1119    });
1120  }
1121
1122  function intersect(array) {
1123    return this.uniq().findAll(function(item) {
1124      return array.detect(function(value) { return item === value });
1125    });
1126  }
1127
1128
1129  function clone() {
1130    return slice.call(this, 0);
1131  }
1132
1133  function size() {
1134    return this.length;
1135  }
1136
1137  function inspect() {
1138    return '[' + this.map(Object.inspect).join(', ') + ']';
1139  }
1140
1141  function indexOf(item, i) {
1142    i || (i = 0);
1143    var length = this.length;
1144    if (i < 0) i = length + i;
1145    for (; i < length; i++)
1146      if (this[i] === item) return i;
1147    return -1;
1148  }
1149
1150  function lastIndexOf(item, i) {
1151    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
1152    var n = this.slice(0, i).reverse().indexOf(item);
1153    return (n < 0) ? n : i - n - 1;
1154  }
1155
1156  function concat() {
1157    var array = slice.call(this, 0), item;
1158    for (var i = 0, length = arguments.length; i < length; i++) {
1159      item = arguments[i];
1160      if (Object.isArray(item) && !('callee' in item)) {
1161        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
1162          array.push(item[j]);
1163      } else {
1164        array.push(item);
1165      }
1166    }
1167    return array;
1168  }
1169
1170  Object.extend(arrayProto, Enumerable);
1171
1172  if (!arrayProto._reverse)
1173    arrayProto._reverse = arrayProto.reverse;
1174
1175  Object.extend(arrayProto, {
1176    _each:     _each,
1177    clear:     clear,
1178    first:     first,
1179    last:      last,
1180    compact:   compact,
1181    flatten:   flatten,
1182    without:   without,
1183    reverse:   reverse,
1184    uniq:      uniq,
1185    intersect: intersect,
1186    clone:     clone,
1187    toArray:   clone,
1188    size:      size,
1189    inspect:   inspect
1190  });
1191
1192  var CONCAT_ARGUMENTS_BUGGY = (function() {
1193    return [].concat(arguments)[0][0] !== 1;
1194  })(1,2)
1195
1196  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1197
1198  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1199  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1200})();
1201function $H(object) {
1202  return new Hash(object);
1203};
1204
1205var Hash = Class.create(Enumerable, (function() {
1206  function initialize(object) {
1207    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1208  }
1209
1210
1211  function _each(iterator) {
1212    for (var key in this._object) {
1213      var value = this._object[key], pair = [key, value];
1214      pair.key = key;
1215      pair.value = value;
1216      iterator(pair);
1217    }
1218  }
1219
1220  function set(key, value) {
1221    return this._object[key] = value;
1222  }
1223
1224  function get(key) {
1225    if (this._object[key] !== Object.prototype[key])
1226      return this._object[key];
1227  }
1228
1229  function unset(key) {
1230    var value = this._object[key];
1231    delete this._object[key];
1232    return value;
1233  }
1234
1235  function toObject() {
1236    return Object.clone(this._object);
1237  }
1238
1239
1240
1241  function keys() {
1242    return this.pluck('key');
1243  }
1244
1245  function values() {
1246    return this.pluck('value');
1247  }
1248
1249  function index(value) {
1250    var match = this.detect(function(pair) {
1251      return pair.value === value;
1252    });
1253    return match && match.key;
1254  }
1255
1256  function merge(object) {
1257    return this.clone().update(object);
1258  }
1259
1260  function update(object) {
1261    return new Hash(object).inject(this, function(result, pair) {
1262      result.set(pair.key, pair.value);
1263      return result;
1264    });
1265  }
1266
1267  function toQueryPair(key, value) {
1268    if (Object.isUndefined(value)) return key;
1269    return key + '=' + encodeURIComponent(String.interpret(value));
1270  }
1271
1272  function toQueryString() {
1273    return this.inject([], function(results, pair) {
1274      var key = encodeURIComponent(pair.key), values = pair.value;
1275
1276      if (values && typeof values == 'object') {
1277        if (Object.isArray(values)) {
1278          var queryValues = [];
1279          for (var i = 0, len = values.length, value; i < len; i++) {
1280            value = values[i];
1281            queryValues.push(toQueryPair(key, value));
1282          }
1283          return results.concat(queryValues);
1284        }
1285      } else results.push(toQueryPair(key, values));
1286      return results;
1287    }).join('&');
1288  }
1289
1290  function inspect() {
1291    return '#<Hash:{' + this.map(function(pair) {
1292      return pair.map(Object.inspect).join(': ');
1293    }).join(', ') + '}>';
1294  }
1295
1296  function clone() {
1297    return new Hash(this);
1298  }
1299
1300  return {
1301    initialize:             initialize,
1302    _each:                  _each,
1303    set:                    set,
1304    get:                    get,
1305    unset:                  unset,
1306    toObject:               toObject,
1307    toTemplateReplacements: toObject,
1308    keys:                   keys,
1309    values:                 values,
1310    index:                  index,
1311    merge:                  merge,
1312    update:                 update,
1313    toQueryString:          toQueryString,
1314    inspect:                inspect,
1315    toJSON:                 toObject,
1316    clone:                  clone
1317  };
1318})());
1319
1320Hash.from = $H;
1321Object.extend(Number.prototype, (function() {
1322  function toColorPart() {
1323    return this.toPaddedString(2, 16);
1324  }
1325
1326  function succ() {
1327    return this + 1;
1328  }
1329
1330  function times(iterator, context) {
1331    $R(0, this, true).each(iterator, context);
1332    return this;
1333  }
1334
1335  function toPaddedString(length, radix) {
1336    var string = this.toString(radix || 10);
1337    return '0'.times(length - string.length) + string;
1338  }
1339
1340  function abs() {
1341    return Math.abs(this);
1342  }
1343
1344  function round() {
1345    return Math.round(this);
1346  }
1347
1348  function ceil() {
1349    return Math.ceil(this);
1350  }
1351
1352  function floor() {
1353    return Math.floor(this);
1354  }
1355
1356  return {
1357    toColorPart:    toColorPart,
1358    succ:           succ,
1359    times:          times,
1360    toPaddedString: toPaddedString,
1361    abs:            abs,
1362    round:          round,
1363    ceil:           ceil,
1364    floor:          floor
1365  };
1366})());
1367
1368function $R(start, end, exclusive) {
1369  return new ObjectRange(start, end, exclusive);
1370}
1371
1372var ObjectRange = Class.create(Enumerable, (function() {
1373  function initialize(start, end, exclusive) {
1374    this.start = start;
1375    this.end = end;
1376    this.exclusive = exclusive;
1377  }
1378
1379  function _each(iterator) {
1380    var value = this.start;
1381    while (this.include(value)) {
1382      iterator(value);
1383      value = value.succ();
1384    }
1385  }
1386
1387  function include(value) {
1388    if (value < this.start)
1389      return false;
1390    if (this.exclusive)
1391      return value < this.end;
1392    return value <= this.end;
1393  }
1394
1395  return {
1396    initialize: initialize,
1397    _each:      _each,
1398    include:    include
1399  };
1400})());
1401
1402
1403
1404var Abstract = { };
1405
1406
1407var Try = {
1408  these: function() {
1409    var returnValue;
1410
1411    for (var i = 0, length = arguments.length; i < length; i++) {
1412      var lambda = arguments[i];
1413      try {
1414        returnValue = lambda();
1415        break;
1416      } catch (e) { }
1417    }
1418
1419    return returnValue;
1420  }
1421};
1422
1423var Ajax = {
1424  getTransport: function() {
1425    return Try.these(
1426      function() {return new XMLHttpRequest()},
1427      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1428      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1429    ) || false;
1430  },
1431
1432  activeRequestCount: 0
1433};
1434
1435Ajax.Responders = {
1436  responders: [],
1437
1438  _each: function(iterator) {
1439    this.responders._each(iterator);
1440  },
1441
1442  register: function(responder) {
1443    if (!this.include(responder))
1444      this.responders.push(responder);
1445  },
1446
1447  unregister: function(responder) {
1448    this.responders = this.responders.without(responder);
1449  },
1450
1451  dispatch: function(callback, request, transport, json) {
1452    this.each(function(responder) {
1453      if (Object.isFunction(responder[callback])) {
1454        try {
1455          responder[callback].apply(responder, [request, transport, json]);
1456        } catch (e) { }
1457      }
1458    });
1459  }
1460};
1461
1462Object.extend(Ajax.Responders, Enumerable);
1463
1464Ajax.Responders.register({
1465  onCreate:   function() { Ajax.activeRequestCount++ },
1466  onComplete: function() { Ajax.activeRequestCount-- }
1467});
1468Ajax.Base = Class.create({
1469  initialize: function(options) {
1470    this.options = {
1471      method:       'post',
1472      asynchronous: true,
1473      contentType:  'application/x-www-form-urlencoded',
1474      encoding:     'UTF-8',
1475      parameters:   '',
1476      evalJSON:     true,
1477      evalJS:       true
1478    };
1479    Object.extend(this.options, options || { });
1480
1481    this.options.method = this.options.method.toLowerCase();
1482
1483    if (Object.isHash(this.options.parameters))
1484      this.options.parameters = this.options.parameters.toObject();
1485  }
1486});
1487Ajax.Request = Class.create(Ajax.Base, {
1488  _complete: false,
1489
1490  initialize: function($super, url, options) {
1491    $super(options);
1492    this.transport = Ajax.getTransport();
1493    this.request(url);
1494  },
1495
1496  request: function(url) {
1497    this.url = url;
1498    this.method = this.options.method;
1499    var params = Object.isString(this.options.parameters) ?
1500          this.options.parameters :
1501          Object.toQueryString(this.options.parameters);
1502
1503    if (!['get', 'post'].include(this.method)) {
1504      params += (params ? '&' : '') + "_method=" + this.method;
1505      this.method = 'post';
1506    }
1507
1508    if (params && this.method === 'get') {
1509      this.url += (this.url.include('?') ? '&' : '?') + params;
1510    }
1511
1512    this.parameters = params.toQueryParams();
1513
1514    try {
1515      var response = new Ajax.Response(this);
1516      if (this.options.onCreate) this.options.onCreate(response);
1517      Ajax.Responders.dispatch('onCreate', this, response);
1518
1519      this.transport.open(this.method.toUpperCase(), this.url,
1520        this.options.asynchronous);
1521
1522      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1523
1524      this.transport.onreadystatechange = this.onStateChange.bind(this);
1525      this.setRequestHeaders();
1526
1527      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1528      this.transport.send(this.body);
1529
1530      /* Force Firefox to handle ready state 4 for synchronous requests */
1531      if (!this.options.asynchronous && this.transport.overrideMimeType)
1532        this.onStateChange();
1533
1534    }
1535    catch (e) {
1536      this.dispatchException(e);
1537    }
1538  },
1539
1540  onStateChange: function() {
1541    var readyState = this.transport.readyState;
1542    if (readyState > 1 && !((readyState == 4) && this._complete))
1543      this.respondToReadyState(this.transport.readyState);
1544  },
1545
1546  setRequestHeaders: function() {
1547    var headers = {
1548      'X-Requested-With': 'XMLHttpRequest',
1549      'X-Prototype-Version': Prototype.Version,
1550      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1551    };
1552
1553    if (this.method == 'post') {
1554      headers['Content-type'] = this.options.contentType +
1555        (this.options.encoding ? '; charset=' + this.options.encoding : '');
1556
1557      /* Force "Connection: close" for older Mozilla browsers to work
1558       * around a bug where XMLHttpRequest sends an incorrect
1559       * Content-length header. See Mozilla Bugzilla #246651.
1560       */
1561      if (this.transport.overrideMimeType &&
1562          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1563            headers['Connection'] = 'close';
1564    }
1565
1566    if (typeof this.options.requestHeaders == 'object') {
1567      var extras = this.options.requestHeaders;
1568
1569      if (Object.isFunction(extras.push))
1570        for (var i = 0, length = extras.length; i < length; i += 2)
1571          headers[extras[i]] = extras[i+1];
1572      else
1573        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1574    }
1575
1576    for (var name in headers)
1577      this.transport.setRequestHeader(name, headers[name]);
1578  },
1579
1580  success: function() {
1581    var status = this.getStatus();
1582    return !status || (status >= 200 && status < 300) || status == 304;
1583  },
1584
1585  getStatus: function() {
1586    try {
1587      if (this.transport.status === 1223) return 204;
1588      return this.transport.status || 0;
1589    } catch (e) { return 0 }
1590  },
1591
1592  respondToReadyState: function(readyState) {
1593    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1594
1595    if (state == 'Complete') {
1596      try {
1597        this._complete = true;
1598        (this.options['on' + response.status]
1599         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1600         || Prototype.emptyFunction)(response, response.headerJSON);
1601      } catch (e) {
1602        this.dispatchException(e);
1603      }
1604
1605      var contentType = response.getHeader('Content-type');
1606      if (this.options.evalJS == 'force'
1607          || (this.options.evalJS && this.isSameOrigin() && contentType
1608          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1609        this.evalResponse();
1610    }
1611
1612    try {
1613      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1614      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1615    } catch (e) {
1616      this.dispatchException(e);
1617    }
1618
1619    if (state == 'Complete') {
1620      this.transport.onreadystatechange = Prototype.emptyFunction;
1621    }
1622  },
1623
1624  isSameOrigin: function() {
1625    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1626    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1627      protocol: location.protocol,
1628      domain: document.domain,
1629      port: location.port ? ':' + location.port : ''
1630    }));
1631  },
1632
1633  getHeader: function(name) {
1634    try {
1635      return this.transport.getResponseHeader(name) || null;
1636    } catch (e) { return null; }
1637  },
1638
1639  evalResponse: function() {
1640    try {
1641      return eval((this.transport.responseText || '').unfilterJSON());
1642    } catch (e) {
1643      this.dispatchException(e);
1644    }
1645  },
1646
1647  dispatchException: function(exception) {
1648    (this.options.onException || Prototype.emptyFunction)(this, exception);
1649    Ajax.Responders.dispatch('onException', this, exception);
1650  }
1651});
1652
1653Ajax.Request.Events =
1654  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1655
1656
1657
1658
1659
1660
1661
1662
1663Ajax.Response = Class.create({
1664  initialize: function(request){
1665    this.request = request;
1666    var transport  = this.transport  = request.transport,
1667        readyState = this.readyState = transport.readyState;
1668
1669    if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1670      this.status       = this.getStatus();
1671      this.statusText   = this.getStatusText();
1672      this.responseText = String.interpret(transport.responseText);
1673      this.headerJSON   = this._getHeaderJSON();
1674    }
1675
1676    if (readyState == 4) {
1677      var xml = transport.responseXML;
1678      this.responseXML  = Object.isUndefined(xml) ? null : xml;
1679      this.responseJSON = this._getResponseJSON();
1680    }
1681  },
1682
1683  status:      0,
1684
1685  statusText: '',
1686
1687  getStatus: Ajax.Request.prototype.getStatus,
1688
1689  getStatusText: function() {
1690    try {
1691      return this.transport.statusText || '';
1692    } catch (e) { return '' }
1693  },
1694
1695  getHeader: Ajax.Request.prototype.getHeader,
1696
1697  getAllHeaders: function() {
1698    try {
1699      return this.getAllResponseHeaders();
1700    } catch (e) { return null }
1701  },
1702
1703  getResponseHeader: function(name) {
1704    return this.transport.getResponseHeader(name);
1705  },
1706
1707  getAllResponseHeaders: function() {
1708    return this.transport.getAllResponseHeaders();
1709  },
1710
1711  _getHeaderJSON: function() {
1712    var json = this.getHeader('X-JSON');
1713    if (!json) return null;
1714    json = decodeURIComponent(escape(json));
1715    try {
1716      return json.evalJSON(this.request.options.sanitizeJSON ||
1717        !this.request.isSameOrigin());
1718    } catch (e) {
1719      this.request.dispatchException(e);
1720    }
1721  },
1722
1723  _getResponseJSON: function() {
1724    var options = this.request.options;
1725    if (!options.evalJSON || (options.evalJSON != 'force' &&
1726      !(this.getHeader('Content-type') || '').include('application/json')) ||
1727        this.responseText.blank())
1728          return null;
1729    try {
1730      return this.responseText.evalJSON(options.sanitizeJSON ||
1731        !this.request.isSameOrigin());
1732    } catch (e) {
1733      this.request.dispatchException(e);
1734    }
1735  }
1736});
1737
1738Ajax.Updater = Class.create(Ajax.Request, {
1739  initialize: function($super, container, url, options) {
1740    this.container = {
1741      success: (container.success || container),
1742      failure: (container.failure || (container.success ? null : container))
1743    };
1744
1745    options = Object.clone(options);
1746    var onComplete = options.onComplete;
1747    options.onComplete = (function(response, json) {
1748      this.updateContent(response.responseText);
1749      if (Object.isFunction(onComplete)) onComplete(response, json);
1750    }).bind(this);
1751
1752    $super(url, options);
1753  },
1754
1755  updateContent: function(responseText) {
1756    var receiver = this.container[this.success() ? 'success' : 'failure'],
1757        options = this.options;
1758
1759    if (!options.evalScripts) responseText = responseText.stripScripts();
1760
1761    if (receiver = $(receiver)) {
1762      if (options.insertion) {
1763        if (Object.isString(options.insertion)) {
1764          var insertion = { }; insertion[options.insertion] = responseText;
1765          receiver.insert(insertion);
1766        }
1767        else options.insertion(receiver, responseText);
1768      }
1769      else receiver.update(responseText);
1770    }
1771  }
1772});
1773
1774Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1775  initialize: function($super, container, url, options) {
1776    $super(options);
1777    this.onComplete = this.options.onComplete;
1778
1779    this.frequency = (this.options.frequency || 2);
1780    this.decay = (this.options.decay || 1);
1781
1782    this.updater = { };
1783    this.container = container;
1784    this.url = url;
1785
1786    this.start();
1787  },
1788
1789  start: function() {
1790    this.options.onComplete = this.updateComplete.bind(this);
1791    this.onTimerEvent();
1792  },
1793
1794  stop: function() {
1795    this.updater.options.onComplete = undefined;
1796    clearTimeout(this.timer);
1797    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1798  },
1799
1800  updateComplete: function(response) {
1801    if (this.options.decay) {
1802      this.decay = (response.responseText == this.lastText ?
1803        this.decay * this.options.decay : 1);
1804
1805      this.lastText = response.responseText;
1806    }
1807    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1808  },
1809
1810  onTimerEvent: function() {
1811    this.updater = new Ajax.Updater(this.container, this.url, this.options);
1812  }
1813});
1814
1815
1816function $(element) {
1817  if (arguments.length > 1) {
1818    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1819      elements.push($(arguments[i]));
1820    return elements;
1821  }
1822  if (Object.isString(element))
1823    element = document.getElementById(element);
1824  return Element.extend(element);
1825}
1826
1827if (Prototype.BrowserFeatures.XPath) {
1828  document._getElementsByXPath = function(expression, parentElement) {
1829    var results = [];
1830    var query = document.evaluate(expression, $(parentElement) || document,
1831      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1832    for (var i = 0, length = query.snapshotLength; i < length; i++)
1833      results.push(Element.extend(query.snapshotItem(i)));
1834    return results;
1835  };
1836}
1837
1838/*--------------------------------------------------------------------------*/
1839
1840if (!Node) var Node = { };
1841
1842if (!Node.ELEMENT_NODE) {
1843  Object.extend(Node, {
1844    ELEMENT_NODE: 1,
1845    ATTRIBUTE_NODE: 2,
1846    TEXT_NODE: 3,
1847    CDATA_SECTION_NODE: 4,
1848    ENTITY_REFERENCE_NODE: 5,
1849    ENTITY_NODE: 6,
1850    PROCESSING_INSTRUCTION_NODE: 7,
1851    COMMENT_NODE: 8,
1852    DOCUMENT_NODE: 9,
1853    DOCUMENT_TYPE_NODE: 10,
1854    DOCUMENT_FRAGMENT_NODE: 11,
1855    NOTATION_NODE: 12
1856  });
1857}
1858
1859
1860
1861(function(global) {
1862  function shouldUseCache(tagName, attributes) {
1863    if (tagName === 'select') return false;
1864    if ('type' in attributes) return false;
1865    return true;
1866  }
1867
1868  var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
1869    try {
1870      var el = document.createElement('<input name="x">');
1871      return el.tagName.toLowerCase() === 'input' && el.name === 'x';
1872    }
1873    catch(err) {
1874      return false;
1875    }
1876  })();
1877
1878  var element = global.Element;
1879
1880  global.Element = function(tagName, attributes) {
1881    attributes = attributes || { };
1882    tagName = tagName.toLowerCase();
1883    var cache = Element.cache;
1884
1885    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
1886      tagName = '<' + tagName + ' name="' + attributes.name + '">';
1887      delete attributes.name;
1888      return Element.writeAttribute(document.createElement(tagName), attributes);
1889    }
1890
1891    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1892
1893    var node = shouldUseCache(tagName, attributes) ?
1894     cache[tagName].cloneNode(false) : document.createElement(tagName);
1895
1896    return Element.writeAttribute(node, attributes);
1897  };
1898
1899  Object.extend(global.Element, element || { });
1900  if (element) global.Element.prototype = element.prototype;
1901
1902})(this);
1903
1904Element.idCounter = 1;
1905Element.cache = { };
1906
1907Element._purgeElement = function(element) {
1908  var uid = element._prototypeUID;
1909  if (uid) {
1910    Element.stopObserving(element);
1911    element._prototypeUID = void 0;
1912    delete Element.Storage[uid];
1913  }
1914}
1915
1916Element.Methods = {
1917  visible: function(element) {
1918    return $(element).style.display != 'none';
1919  },
1920
1921  toggle: function(element) {
1922    element = $(element);
1923    Element[Element.visible(element) ? 'hide' : 'show'](element);
1924    return element;
1925  },
1926
1927  hide: function(element) {
1928    element = $(element);
1929    ele

Large files files are truncated, but you can click here to view the full file