PageSourceSearch

https://www.fencingandlandscapesupplies.co.uk/js/prototype/prototype.js?v=8.0.0-0-Beta18

js fencingandlandscapesupplies.co.uk collected 2026-09-29 12:10:03 UTC 165,411 bytes, 6,141 lines download raw bytes

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
60// if (Prototype.Browser.MobileSafari)
61//   Prototype.BrowserFeatures.SpecificElementExtensions = false;
62
63
64var Abstract = { };
65
66
67var Try = {
68  these: function() {
69    var returnValue;
70
71    for (var i = 0, length = arguments.length; i < length; i++) {
72      var lambda = arguments[i];
73      try {
74        returnValue = lambda();
75        break;
76      } catch (e) { }
77    }
78
79    return returnValue;
80  }
81};
82
83/* Based on Alex Arnell's inheritance implementation. */
84
85var Class = (function() {
86
87  var IS_DONTENUM_BUGGY = (function(){
88    for (var p in { toString: 1 }) {
89      if (p === 'toString') return false;
90    }
91    return true;
92  })();
93
94  function subclass() {};
95  function create() {
96    var parent = null, properties = $A(arguments);
97    if (Object.isFunction(properties[0]))
98      parent = properties.shift();
99
100    function klass() {
101      this.initialize.apply(this, arguments);
102    }
103
104    Object.extend(klass, Class.Methods);
105    klass.superclass = parent;
106    klass.subclasses = [];
107
108    if (parent) {
109      subclass.prototype = parent.prototype;
110      klass.prototype = new subclass;
111      parent.subclasses.push(klass);
112    }
113
114    for (var i = 0, length = properties.length; i < length; i++)
115      klass.addMethods(properties[i]);
116
117    if (!klass.prototype.initialize)
118      klass.prototype.initialize = Prototype.emptyFunction;
119
120    klass.prototype.constructor = klass;
121    return klass;
122  }
123
124  function addMethods(source) {
125    var ancestor   = this.superclass && this.superclass.prototype,
126        properties = Object.keys(source);
127
128    if (IS_DONTENUM_BUGGY) {
129      if (source.toString != Object.prototype.toString)
130        properties.push("toString");
131      if (source.valueOf != Object.prototype.valueOf)
132        properties.push("valueOf");
133    }
134
135    for (var i = 0, length = properties.length; i < length; i++) {
136      var property = properties[i], value = source[property];
137      if (ancestor && Object.isFunction(value) &&
138          value.argumentNames()[0] == "$super") {
139        var method = value;
140        value = (function(m) {
141          return function() { return ancestor[m].apply(this, arguments); };
142        })(property).wrap(method);
143
144        value.valueOf = method.valueOf.bind(method);
145        value.toString = method.toString.bind(method);
146      }
147      this.prototype[property] = value;
148    }
149
150    return this;
151  }
152
153  return {
154    create: create,
155    Methods: {
156      addMethods: addMethods
157    }
158  };
159})();
160(function() {
161
162  var _toString = Object.prototype.toString,
163      NULL_TYPE = 'Null',
164      UNDEFINED_TYPE = 'Undefined',
165      BOOLEAN_TYPE = 'Boolean',
166      NUMBER_TYPE = 'Number',
167      STRING_TYPE = 'String',
168      OBJECT_TYPE = 'Object',
169      FUNCTION_CLASS = '[object Function]',
170      BOOLEAN_CLASS = '[object Boolean]',
171      NUMBER_CLASS = '[object Number]',
172      STRING_CLASS = '[object String]',
173      ARRAY_CLASS = '[object Array]',
174      DATE_CLASS = '[object Date]',
175      NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
176        typeof JSON.stringify === 'function' &&
177        JSON.stringify(0) === '0' &&
178        typeof JSON.stringify(Prototype.K) === 'undefined';
179
180  function Type(o) {
181    switch(o) {
182      case null: return NULL_TYPE;
183      case (void 0): return UNDEFINED_TYPE;
184    }
185    var type = typeof o;
186    switch(type) {
187      case 'boolean': return BOOLEAN_TYPE;
188      case 'number':  return NUMBER_TYPE;
189      case 'string':  return STRING_TYPE;
190    }
191    return OBJECT_TYPE;
192  }
193
194  function extend(destination, source) {
195    for (var property in source)
196      destination[property] = source[property];
197    return destination;
198  }
199
200  function inspect(object) {
201    try {
202      if (isUndefined(object)) return 'undefined';
203      if (object === null) return 'null';
204      return object.inspect ? object.inspect() : String(object);
205    } catch (e) {
206      if (e instanceof RangeError) return '...';
207      throw e;
208    }
209  }
210
211  function toJSON(value) {
212    return Str('', { '': value }, []);
213  }
214
215  function Str(key, holder, stack) {
216    var value = holder[key],
217        type = typeof value;
218
219    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
220      value = value.toJSON(key);
221    }
222
223    var _class = _toString.call(value);
224
225    switch (_class) {
226      case NUMBER_CLASS:
227      case BOOLEAN_CLASS:
228      case STRING_CLASS:
229        value = value.valueOf();
230    }
231
232    switch (value) {
233      case null: return 'null';
234      case true: return 'true';
235      case false: return 'false';
236    }
237
238    type = typeof value;
239    switch (type) {
240      case 'string':
241        return value.inspect(true);
242      case 'number':
243        return isFinite(value) ? String(value) : 'null';
244      case 'object':
245
246        for (var i = 0, length = stack.length; i < length; i++) {
247          if (stack[i] === value) { throw new TypeError(); }
248        }
249        stack.push(value);
250
251        var partial = [];
252        if (_class === ARRAY_CLASS || value instanceof Array) {
253          for (var i = 0, length = value.length; i < length; i++) {
254            var str = Str(i, value, stack);
255            partial.push(typeof str === 'undefined' ? 'null' : str);
256          }
257          partial = '[' + partial.join(',') + ']';
258        } else {
259          var keys = Object.keys(value);
260          for (var i = 0, length = keys.length; i < length; i++) {
261            var key = keys[i], str = Str(key, value, stack);
262            if (typeof str !== "undefined") {
263               partial.push(key.inspect(true)+ ':' + str);
264             }
265          }
266          partial = '{' + partial.join(',') + '}';
267        }
268        stack.pop();
269        return partial;
270    }
271  }
272
273  function stringify(object) {
274    return JSON.stringify(object);
275  }
276
277  function toQueryString(object) {
278    return $H(object).toQueryString();
279  }
280
281  function toHTML(object) {
282    return object && object.toHTML ? object.toHTML() : String.interpret(object);
283  }
284
285  function keys(object) {
286    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
287    var results = [];
288    for (var property in object) {
289      if (object.hasOwnProperty(property)) {
290        results.push(property);
291      }
292    }
293    return results;
294  }
295
296  function values(object) {
297    var results = [];
298    for (var property in object)
299      results.push(object[property]);
300    return results;
301  }
302
303  function clone(object) {
304    return extend({ }, object);
305  }
306
307  function isElement(object) {
308    return !!(object && object.nodeType == 1);
309  }
310
311  function isArray(object) {
312    return _toString.call(object) === ARRAY_CLASS || object instanceof Array;
313  }
314
315  var hasNativeIsArray = (typeof Array.isArray == 'function')
316    && Array.isArray([]) && !Array.isArray({});
317
318  if (hasNativeIsArray) {
319    isArray = Array.isArray;
320  }
321
322  function isHash(object) {
323    return object instanceof Hash;
324  }
325
326  function isFunction(object) {
327    return _toString.call(object) === FUNCTION_CLASS;
328  }
329
330  function isString(object) {
331    return _toString.call(object) === STRING_CLASS;
332  }
333
334  function isNumber(object) {
335    return _toString.call(object) === NUMBER_CLASS;
336  }
337
338  function isDate(object) {
339    return _toString.call(object) === DATE_CLASS;
340  }
341
342  function isUndefined(object) {
343    return typeof object === "undefined";
344  }
345
346  extend(Object, {
347    extend:        extend,
348    inspect:       inspect,
349    toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
350    toQueryString: toQueryString,
351    toHTML:        toHTML,
352    keys:          Object.keys || keys,
353    values:        values,
354    clone:         clone,
355    isElement:     isElement,
356    isArray:       isArray,
357    isHash:        isHash,
358    isFunction:    isFunction,
359    isString:      isString,
360    isNumber:      isNumber,
361    isDate:        isDate,
362    isUndefined:   isUndefined
363  });
364})();
365Object.extend(Function.prototype, (function() {
366  var slice = Array.prototype.slice;
367
368  function update(array, args) {
369    var arrayLength = array.length, length = args.length;
370    while (length--) array[arrayLength + length] = args[length];
371    return array;
372  }
373
374  function merge(array, args) {
375    array = slice.call(array, 0);
376    return update(array, args);
377  }
378
379  function argumentNames() {
380    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
381      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
382      .replace(/\s+/g, '').split(',');
383    return names.length == 1 && !names[0] ? [] : names;
384  }
385
386  function bind(context) {
387    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
388    var __method = this, args = slice.call(arguments, 1);
389    return function() {
390      var a = merge(args, arguments);
391      return __method.apply(context, a);
392    }
393  }
394
395  function bindAsEventListener(context) {
396    var __method = this, args = slice.call(arguments, 1);
397    return function(event) {
398      var a = update([event || window.event], args);
399      return __method.apply(context, a);
400    }
401  }
402
403  function curry() {
404    if (!arguments.length) return this;
405    var __method = this, args = slice.call(arguments, 0);
406    return function() {
407      var a = merge(args, arguments);
408      return __method.apply(this, a);
409    }
410  }
411
412  function delay(timeout) {
413    var __method = this, args = slice.call(arguments, 1);
414    timeout = timeout * 1000;
415    return window.setTimeout(function() {
416      return __method.apply(__method, args);
417    }, timeout);
418  }
419
420  function defer() {
421    var args = update([0.01], arguments);
422    return this.delay.apply(this, args);
423  }
424
425  function wrap(wrapper) {
426    var __method = this;
427    return function() {
428      var a = update([__method.bind(this)], arguments);
429      return wrapper.apply(this, a);
430    }
431  }
432
433  function methodize() {
434    if (this._methodized) return this._methodized;
435    var __method = this;
436    return this._methodized = function() {
437      var a = update([this], arguments);
438      return __method.apply(null, a);
439    };
440  }
441
442  return {
443    argumentNames:       argumentNames,
444    // Begin modified by Zoey
445    // use native bind
446    // bind:                bind,
447    // End modified by Zoey
448    bindAsEventListener: bindAsEventListener,
449    curry:               curry,
450    delay:               delay,
451    defer:               defer,
452    wrap:                wrap,
453    methodize:           methodize
454  }
455})());
456
457
458
459(function(proto) {
460
461
462  function toISOString() {
463    return this.getUTCFullYear() + '-' +
464      (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
465      this.getUTCDate().toPaddedString(2) + 'T' +
466      this.getUTCHours().toPaddedString(2) + ':' +
467      this.getUTCMinutes().toPaddedString(2) + ':' +
468      this.getUTCSeconds().toPaddedString(2) + 'Z';
469  }
470
471
472  function toJSON() {
473    return this.toISOString();
474  }
475
476  if (!proto.toISOString) proto.toISOString = toISOString;
477  if (!proto.toJSON) proto.toJSON = toJSON;
478
479})(Date.prototype);
480
481
482RegExp.prototype.match = RegExp.prototype.test;
483
484RegExp.escape = function(str) {
485  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
486};
487var PeriodicalExecuter = Class.create({
488  initialize: function(callback, frequency) {
489    this.callback = callback;
490    this.frequency = frequency;
491    this.currentlyExecuting = false;
492
493    this.registerCallback();
494  },
495
496  registerCallback: function() {
497    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
498  },
499
500  execute: function() {
501    this.callback(this);
502  },
503
504  stop: function() {
505    if (!this.timer) return;
506    clearInterval(this.timer);
507    this.timer = null;
508  },
509
510  onTimerEvent: function() {
511    if (!this.currentlyExecuting) {
512      try {
513        this.currentlyExecuting = true;
514        this.execute();
515        this.currentlyExecuting = false;
516      } catch(e) {
517        this.currentlyExecuting = false;
518        throw e;
519      }
520    }
521  }
522});
523Object.extend(String, {
524  interpret: function(value) {
525    return value == null ? '' : String(value);
526  },
527  specialChar: {
528    '\b': '\\b',
529    '\t': '\\t',
530    '\n': '\\n',
531    '\f': '\\f',
532    '\r': '\\r',
533    '\\': '\\\\'
534  }
535});
536
537Object.extend(String.prototype, (function() {
538  var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
539    typeof JSON.parse === 'function' &&
540    JSON.parse('{"test": true}').test;
541
542  function prepareReplacement(replacement) {
543    if (Object.isFunction(replacement)) return replacement;
544    var template = new Template(replacement);
545    return function(match) { return template.evaluate(match) };
546  }
547
548  function gsub(pattern, replacement) {
549    var result = '', source = this, match;
550    replacement = prepareReplacement(replacement);
551
552    if (Object.isString(pattern))
553      pattern = RegExp.escape(pattern);
554
555    if (!(pattern.length || pattern.source)) {
556      replacement = replacement('');
557      return replacement + source.split('').join(replacement) + replacement;
558    }
559
560    while (source.length > 0) {
561      if (match = source.match(pattern)) {
562        result += source.slice(0, match.index);
563        result += String.interpret(replacement(match));
564        source  = source.slice(match.index + match[0].length);
565      } else {
566        result += source, source = '';
567      }
568    }
569    return result;
570  }
571
572  function sub(pattern, replacement, count) {
573    replacement = prepareReplacement(replacement);
574    count = Object.isUndefined(count) ? 1 : count;
575
576    return this.gsub(pattern, function(match) {
577      if (--count < 0) return match[0];
578      return replacement(match);
579    });
580  }
581
582  function scan(pattern, iterator) {
583    this.gsub(pattern, iterator);
584    return String(this);
585  }
586
587  function truncate(length, truncation) {
588    length = length || 30;
589    truncation = Object.isUndefined(truncation) ? '...' : truncation;
590    return this.length > length ?
591      this.slice(0, length - truncation.length) + truncation : String(this);
592  }
593
594  function strip() {
595    return this.replace(/^\s+/, '').replace(/\s+$/, '');
596  }
597
598  function stripTags() {
599    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
600  }
601
602  function stripScripts() {
603    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
604  }
605
606  function extractScripts() {
607    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
608        matchOne = new RegExp(Prototype.ScriptFragment, 'im');
609    return (this.match(matchAll) || []).map(function(scriptTag) {
610      return (scriptTag.match(matchOne) || ['', ''])[1];
611    });
612  }
613
614  function evalScripts() {
615    return this.extractScripts().map(function(script) { return eval(script) });
616  }
617
618  function escapeHTML() {
619    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
620  }
621
622  function unescapeHTML() {
623    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
624  }
625
626
627  function toQueryParams(separator) {
628    var match = this.strip().match(/([^?#]*)(#.*)?$/);
629    if (!match) return { };
630
631    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
632      if ((pair = pair.split('='))[0]) {
633        var key = decodeURIComponent(pair.shift()),
634            value = pair.length > 1 ? pair.join('=') : pair[0];
635
636        if (value != undefined) value = decodeURIComponent(value);
637
638        if (key in hash) {
639          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
640          hash[key].push(value);
641        }
642        else hash[key] = value;
643      }
644      return hash;
645    });
646  }
647
648  function toArray() {
649    return this.split('');
650  }
651
652  function succ() {
653    return this.slice(0, this.length - 1) +
654      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
655  }
656
657  function times(count) {
658    return count < 1 ? '' : new Array(count + 1).join(this);
659  }
660
661  function camelize() {
662    return this.replace(/-+(.)?/g, function(match, chr) {
663      return chr ? chr.toUpperCase() : '';
664    });
665  }
666
667  function capitalize() {
668    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
669  }
670
671  function underscore() {
672    return this.replace(/::/g, '/')
673               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
674               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
675               .replace(/-/g, '_')
676               .toLowerCase();
677  }
678
679  function dasherize() {
680    return this.replace(/_/g, '-');
681  }
682
683  function inspect(useDoubleQuotes) {
684    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(ch
684aracter) {
685      if (character in String.specialChar) {
686        return String.specialChar[character];
687      }
688      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
689    });
690    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
691    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
692  }
693
694  function unfilterJSON(filter) {
695    return this.replace(filter || Prototype.JSONFilter, '$1');
696  }
697
698  function isJSON() {
699    var str = this;
700    if (str.blank()) return false;
701    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
702    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
703    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
704    return (/^[\],:{}\s]*$/).test(str);
705  }
706
707  function evalJSON(sanitize) {
708    var json = this.unfilterJSON(),
709        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
710    if (cx.test(json)) {
711      json = json.replace(cx, function (a) {
712        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
713      });
714    }
715    try {
716      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
717    } catch (e) { }
718    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
719  }
720
721  function parseJSON() {
722    var json = this.unfilterJSON();
723    return JSON.parse(json);
724  }
725
726  function include(pattern) {
727    return this.indexOf(pattern) > -1;
728  }
729
730  function startsWith(pattern) {
731    return this.lastIndexOf(pattern, 0) === 0;
732  }
733
734  function endsWith(pattern) {
735    var d = this.length - pattern.length;
736    return d >= 0 && this.indexOf(pattern, d) === d;
737  }
738
739  function empty() {
740    return this == '';
741  }
742
743  function blank() {
744    return /^\s*$/.test(this);
745  }
746
747  function interpolate(object, pattern) {
748    return new Template(this, pattern).evaluate(object);
749  }
750
751  return {
752    gsub:           gsub,
753    sub:            sub,
754    scan:           scan,
755    truncate:       truncate,
756    strip:          String.prototype.trim || strip,
757    stripTags:      stripTags,
758    stripScripts:   stripScripts,
759    extractScripts: extractScripts,
760    evalScripts:    evalScripts,
761    escapeHTML:     escapeHTML,
762    unescapeHTML:   unescapeHTML,
763    toQueryParams:  toQueryParams,
764    parseQuery:     toQueryParams,
765    toArray:        toArray,
766    succ:           succ,
767    times:          times,
768    camelize:       camelize,
769    capitalize:     capitalize,
770    underscore:     underscore,
771    dasherize:      dasherize,
772    inspect:        inspect,
773    unfilterJSON:   unfilterJSON,
774    isJSON:         isJSON,
775    evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
776    include:        include,
777    startsWith:     startsWith,
778    endsWith:       endsWith,
779    empty:          empty,
780    blank:          blank,
781    interpolate:    interpolate
782  };
783})());
784
785var Template = Class.create({
786  initialize: function(template, pattern) {
787    this.template = template.toString();
788    this.pattern = pattern || Template.Pattern;
789  },
790
791  evaluate: function(object) {
792    if (object && Object.isFunction(object.toTemplateReplacements))
793      object = object.toTemplateReplacements();
794
795    return this.template.gsub(this.pattern, function(match) {
796      if (object == null) return (match[1] + '');
797
798      var before = match[1] || '';
799      if (before == '\\') return match[2];
800
801      var ctx = object, expr = match[3],
802          pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
803
804      match = pattern.exec(expr);
805      if (match == null) return before;
806
807      while (match != null) {
808        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
809        ctx = ctx[comp];
810        if (null == ctx || '' == match[3]) break;
811        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
812        match = pattern.exec(expr);
813      }
814
815      return before + String.interpret(ctx);
816    });
817  }
818});
819Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
820
821var $break = { };
822
823var Enumerable = (function() {
824  function each(iterator, context) {
825    var index = 0;
826    try {
827      this._each(function(value) {
828        iterator.call(context, value, index++);
829      });
830    } catch (e) {
831      if (e != $break) throw e;
832    }
833    return this;
834  }
835
836  function eachSlice(number, iterator, context) {
837    var index = -number, slices = [], array = this.toArray();
838    if (number < 1) return array;
839    while ((index += number) < array.length)
840      slices.push(array.slice(index, index+number));
841    return slices.collect(iterator, context);
842  }
843
844  function all(iterator, context) {
845    iterator = iterator || Prototype.K;
846    var result = true;
847    this.each(function(value, index) {
848      result = result && !!iterator.call(context, value, index);
849      if (!result) throw $break;
850    });
851    return result;
852  }
853
854  function any(iterator, context) {
855    iterator = iterator || Prototype.K;
856    var result = false;
857    this.each(function(value, index) {
858      if (result = !!iterator.call(context, value, index))
859        throw $break;
860    });
861    return result;
862  }
863
864  function collect(iterator, context) {
865    iterator = iterator || Prototype.K;
866    var results = [];
867    this.each(function(value, index) {
868      results.push(iterator.call(context, value, index));
869    });
870    return results;
871  }
872
873  function detect(iterator, context) {
874    var result;
875    this.each(function(value, index) {
876      if (iterator.call(context, value, index)) {
877        result = value;
878        throw $break;
879      }
880    });
881    return result;
882  }
883
884  function findAll(iterator, context) {
885    var results = [];
886    this.each(function(value, index) {
887      if (iterator.call(context, value, index))
888        results.push(value);
889    });
890    return results;
891  }
892
893  function grep(filter, iterator, context) {
894    iterator = iterator || Prototype.K;
895    var results = [];
896
897    if (Object.isString(filter))
898      filter = new RegExp(RegExp.escape(filter));
899
900    this.each(function(value, index) {
901      if (filter.match(value))
902        results.push(iterator.call(context, value, index));
903    });
904    return results;
905  }
906
907  function include(object) {
908    if (Object.isFunction(this.indexOf))
909      if (this.indexOf(object) != -1) return true;
910
911    var found = false;
912    this.each(function(value) {
913      if (value == object) {
914        found = true;
915        throw $break;
916      }
917    });
918    return found;
919  }
920
921  function inGroupsOf(number, fillWith) {
922    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
923    return this.eachSlice(number, function(slice) {
924      while(slice.length < number) slice.push(fillWith);
925      return slice;
926    });
927  }
928
929  function inject(memo, iterator, context) {
930    this.each(function(value, index) {
931      memo = iterator.call(context, memo, value, index);
932    });
933    return memo;
934  }
935
936  function invoke(method) {
937    var args = $A(arguments).slice(1);
938    return this.map(function(value) {
939      return value[method].apply(value, args);
940    });
941  }
942
943  function max(iterator, context) {
944    iterator = iterator || Prototype.K;
945    var result;
946    this.each(function(value, index) {
947      value = iterator.call(context, value, index);
948      if (result == null || value >= result)
949        result = value;
950    });
951    return result;
952  }
953
954  function min(iterator, context) {
955    iterator = iterator || Prototype.K;
956    var result;
957    this.each(function(value, index) {
958      value = iterator.call(context, value, index);
959      if (result == null || value < result)
960        result = value;
961    });
962    return result;
963  }
964
965  function partition(iterator, context) {
966    iterator = iterator || Prototype.K;
967    var trues = [], falses = [];
968    this.each(function(value, index) {
969      (iterator.call(context, value, index) ?
970        trues : falses).push(value);
971    });
972    return [trues, falses];
973  }
974
975  function pluck(property) {
976    var results = [];
977    this.each(function(value) {
978      results.push(value[property]);
979    });
980    return results;
981  }
982
983  function reject(iterator, context) {
984    var results = [];
985    this.each(function(value, index) {
986      if (!iterator.call(context, value, index))
987        results.push(value);
988    });
989    return results;
990  }
991
992  function sortBy(iterator, context) {
993    return this.map(function(value, index) {
994      return {
995        value: value,
996        criteria: iterator.call(context, value, index)
997      };
998    }).sort(function(left, right) {
999      var a = left.criteria, b = right.criteria;
1000      return a < b ? -1 : a > b ? 1 : 0;
1001    }).pluck('value');
1002  }
1003
1004  function toArray() {
1005    return this.collect();
1006  }
1007
1008  function zip() {
1009    var iterator = Prototype.K, args = $A(arguments);
1010    if (Object.isFunction(args.last()))
1011      iterator = args.pop();
1012
1013    var collections = [this].concat(args).map($A);
1014    return this.map(function(value, index) {
1015      return iterator(collections.pluck(index));
1016    });
1017  }
1018
1019  function size() {
1020    return this.toArray().length;
1021  }
1022
1023  function inspect() {
1024    return '#<Enumerable:' + this.toArray().inspect() + '>';
1025  }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035  return {
1036    each:       each,
1037    eachSlice:  eachSlice,
1038    all:        all,
1039    every:      all,
1040    any:        any,
1041    some:       any,
1042    collect:    collect,
1043    // map:        collect,
1044    detect:     detect,
1045    findAll:    findAll,
1046    select:     findAll,
1047    // filter:     findAll,
1048    grep:       grep,
1049    include:    include,
1050    member:     include,
1051    inGroupsOf: inGroupsOf,
1052    inject:     inject,
1053    invoke:     invoke,
1054    max:        max,
1055    min:        min,
1056    partition:  partition,
1057    pluck:      pluck,
1058    reject:     reject,
1059    sortBy:     sortBy,
1060    toArray:    toArray,
1061    entries:    toArray,
1062    zip:        zip,
1063    size:       size,
1064    inspect:    inspect,
1065    find:       detect
1066  };
1067})();
1068
1069function $A(iterable) {
1070  if (!iterable) return [];
1071  if ('toArray' in Object(iterable)) return iterable.toArray();
1072  var length = iterable.length || 0, results = new Array(length);
1073  while (length--) results[length] = iterable[length];
1074  return results;
1075}
1076
1077
1078function $w(string) {
1079  if (!Object.isString(string)) return [];
1080  string = string.strip();
1081  return string ? string.split(/\s+/) : [];
1082}
1083
1084// Begin modified by Zoey
1085// use native Array.from if available
1086if (!Array.from) {
1087  Array.from = $A;
1088}
1089// End modified by Zoey
1090
1091
1092(function() {
1093  var arrayProto = Array.prototype,
1094      slice = arrayProto.slice,
1095      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1096
1097  function each(iterator, context) {
1098    for (var i = 0, length = this.length >>> 0; i < length; i++) {
1099      if (i in this) iterator.call(context, this[i], i, this);
1100    }
1101  }
1102  if (!_each) _each = each;
1103
1104  function clear() {
1105    this.length = 0;
1106    return this;
1107  }
1108
1109  function first() {
1110    return this[0];
1111  }
1112
1113  function last() {
1114    return this[this.length - 1];
1115  }
1116
1117  function compact() {
1118    return this.select(function(value) {
1119      return value != null;
1120    });
1121  }
1122
1123  function flatten() {
1124    return this.inject([], function(array, value) {
1125      if (Object.isArray(value))
1126        return array.concat(value.flatten());
1127      array.push(value);
1128      return array;
1129    });
1130  }
1131
1132  function without() {
1133    var values = slice.call(arguments, 0);
1134    return this.select(function(value) {
1135      return !values.include(value);
1136    });
1137  }
1138
1139  function reverse(inline) {
1140    return (inline === false ? this.toArray() : this)._reverse();
1141  }
1142
1143  function uniq(sorted) {
1144    return this.inject([], function(array, value, index) {
1145      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1146        array.push(value);
1147      return array;
1148    });
1149  }
1150
1151  function intersect(array) {
1152    return this.uniq().findAll(function(item) {
1153      return array.detect(function(value) { return item === value });
1154    });
1155  }
1156
1157
1158  function clone() {
1159    return slice.call(this, 0);
1160  }
1161
1162  function size() {
1163    return this.length;
1164  }
1165
1166  function inspect() {
1167    return '[' + this.map(Object.inspect).join(', ') + ']';
1168  }
1169
1170  function indexOf(item, i) {
1171    i || (i = 0);
1172    var length = this.length;
1173    if (i < 0) i = length + i;
1174    for (; i < length; i++)
1175      if (this[i] === item) return i;
1176    return -1;
1177  }
1178
1179  function lastIndexOf(item, i) {
1180    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
1181    var n = this.slice(0, i).reverse().indexOf(item);
1182    return (n < 0) ? n : i - n - 1;
1183  }
1184
1185  function concat() {
1186    var array = slice.call(this, 0), item;
1187    for (var i = 0, length = arguments.length; i < length; i++) {
1188      item = arguments[i];
1189      if (Object.isArray(item) && !('callee' in item)) {
1190        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
1191          array.push(item[j]);
1192      } else {
1193        array.push(item);
1194      }
1195    }
1196    return array;
1197  }
1198
1199  Object.extend(arrayProto, Enumerable);
1200
1201  if (!arrayProto._reverse)
1202    arrayProto._reverse = arrayProto.reverse;
1203
1204  Object.extend(arrayProto, {
1205    _each:     _each,
1206    clear:     clear,
1207    first:     first,
1208    last:      last,
1209    compact:   compact,
1210    flatten:   flatten,
1211    without:   without,
1212    reverse:   reverse,
1213    uniq:      uniq,
1214    intersect: intersect,
1215    clone:     clone,
1216    toArray:   clone,
1217    size:      size,
1218    inspect:   inspect
1219  });
1220
1221  var CONCAT_ARGUMENTS_BUGGY = (function() {
1222    return [].concat(arguments)[0][0] !== 1;
1223  })(1,2)
1224
1225  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1226
1227  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1228  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1229})();
1230function $H(object) {
1231  return new Hash(object);
1232};
1233
1234var Hash = Class.create(Enumerable, (function() {
1235  function initialize(object) {
1236    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1237  }
1238
1239
1240  function _each(iterator) {
1241    for (var key in this._object) {
1242      var value = this._object[key], pair = [key, value];
1243      pair.key = key;
1244      pair.value = value;
1245      iterator(pair);
1246    }
1247  }
1248
1249  function set(key, value) {
1250    return this._object[key] = value;
1251  }
1252
1253  function get(key) {
1254    if (this._object[key] !== Object.prototype[key])
1255      return this._object[key];
1256  }
1257
1258  function unset(key) {
1259    var value = this._object[key];
1260    delete this._object[key];
1261    return value;
1262  }
1263
1264  function toObject() {
1265    return Object.clone(this._object);
1266  }
1267
1268
1269
1270  function keys() {
1271    return this.pluck('key');
1272  }
1273
1274  function values() {
1275    return this.pluck('value');
1276  }
1277
1278  function index(value) {
1279    var match = this.detect(function(pair) {
1280      return pair.value === value;
1281    });
1282    return match && match.key;
1283  }
1284
1285  function merge(object) {
1286    return this.clone().update(object);
1287  }
1288
1289  function update(object) {
1290    return new Hash(object).inject(this, function(result, pair) {
1291      result.set(pair.key, pair.value);
1292      return result;
1293    });
1294  }
1295
1296  function toQueryPair(key, value) {
1297    if (Object.isUndefined(value)) return key;
1298    return key + '=' + encodeURIComponent(String.interpret(value));
1299  }
1300
1301  function toQueryString() {
1302    return this.inject([], function(results, pair) {
1303      var key = encodeURIComponent(pair.key), values = pair.value;
1304
1305      if (values && typeof values == 'object') {
1306        if (Object.isArray(values)) {
1307          var queryValues = [];
1308          for (var i = 0, len = values.length, value; i < len; i++) {
1309            value = values[i];
1310            queryValues.push(toQueryPair(key, value));
1311          }
1312          return results.concat(queryValues);
1313        }
1314      } else results.push(toQueryPair(key, values));
1315      return results;
1316    }).join('&');
1317  }
1318
1319  function inspect() {
1320    return '#<Hash:{' + this.map(function(pair) {
1321      return pair.map(Object.inspect).join(': ');
1322    }).join(', ') + '}>';
1323  }
1324
1325  function clone() {
1326    return new Hash(this);
1327  }
1328
1329  return {
1330    initialize:             initialize,
1331    _each:                  _each,
1332    set:                    set,
1333    get:                    get,
1334    unset:                  unset,
1335    toObject:               toObject,
1336    toTemplateReplacements: toObject,
1337    keys:                   keys,
1338    values:                 values,
1339    index:                  index,
1340    merge:                  merge,
1341    update:                 update,
1342    toQueryString:          toQueryString,
1343    inspect:                inspect,
1344    toJSON:                 toObject,
1345    clone:                  clone
1346  };
1347})());
1348
1349Hash.from = $H;
1350Object.extend(Number.prototype, (function() {
1351  function toColorPart() {
1352    return this.toPaddedString(2, 16);
1353  }
1354
1355  function succ() {
1356    return this + 1;
1357  }
1358
1359  function times(iterator, context) {
1360    $R(0, this, true).each(iterator, context);
1361    return this;
1362  }
1363
1364  function toPaddedString(length, radix) {
1365    var string = this.toString(radix || 10);
1366    return '0'.times(length - string.length) + string;
1367  }
1368
1369  function abs() {
1370    return Math.abs(this);
1371  }
1372
1373  function round() {
1374    return Math.round(this);
1375  }
1376
1377  function ceil() {
1378    return Math.ceil(this);
1379  }
1380
1381  function floor() {
1382    return Math.floor(this);
1383  }
1384
1385  return {
1386    toColorPart:    toColorPart,
1387    succ:           succ,
1388    times:          times,
1389    toPaddedString: toPaddedString,
1390    abs:            abs,
1391    round:          round,
1392    ceil:           ceil,
1393    floor:          floor
1394  };
1395})());
1396
1397function $R(start, end, exclusive) {
1398  return new ObjectRange(start, end, exclusive);
1399}
1400
1401var ObjectRange = Class.create(Enumerable, (function() {
1402  function initialize(start, end, exclusive) {
1403    this.start = start;
1404    this.end = end;
1405    this.exclusive = exclusive;
1406  }
1407
1408  function _each(iterator) {
1409    var value = this.start;
1410    while (this.include(value)) {
1411      iterator(value);
1412      value = value.succ();
1413    }
1414  }
1415
1416  function include(value) {
1417    if (value < this.start)
1418      return false;
1419    if (this.exclusive)
1420      return value < this.end;
1421    return value <= this.end;
1422  }
1423
1424  return {
1425    initialize: initialize,
1426    _each:      _each,
1427    include:    include
1428  };
1429})());
1430
1431
1432
1433var Ajax = {
1434  getTransport: function() {
1435    return Try.these(
1436      function() {return new XMLHttpRequest()},
1437      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1438      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1439    ) || false;
1440  },
1441
1442  activeRequestCount: 0
1443};
1444
1445Ajax.Responders = {
1446  responders: [],
1447
1448  _each: function(iterator) {
1449    this.responders._each(iterator);
1450  },
1451
1452  register: function(responder) {
1453    if (!this.include(responder))
1454      this.responders.push(responder);
1455  },
1456
1457  unregister: function(responder) {
1458    this.responders = this.responders.without(responder);
1459  },
1460
1461  dispatch: function(callback, request, transport, json) {
1462    this.each(function(responder) {
1463      if (Object.isFunction(responder[callback])) {
1464        try {
1465          responder[callback].apply(responder, [request, transport, json]);
1466        } catch (e) { }
1467      }
1468    });
1469  }
1470};
1471
1472Object.extend(Ajax.Responders, Enumerable);
1473
1474Ajax.Responders.register({
1475  onCreate:   function() { Ajax.activeRequestCount++ },
1476  onComplete: function() { Ajax.activeRequestCount-- }
1477});
1478Ajax.Base = Class.create({
1479  initialize: function(options) {
1480    this.options = {
1481      method:       'post',
1482      asynchronous: true,
1483      contentType:  'application/x-www-form-urlencoded',
1484      encoding:     'UTF-8',
1485      parameters:   '',
1486      evalJSON:     true,
1487      evalJS:       true
1488    };
1489    Object.extend(this.options, options || { });
1490
1491    this.options.method = this.options.method.toLowerCase();
1492
1493    if (Object.isHash(this.options.parameters))
1494      this.options.parameters = this.options.parameters.toObject();
1495  }
1496});
1497Ajax.Request = Class.create(Ajax.Base, {
1498  _complete: false,
1499
1500  initialize: function($super, url, options) {
1501    $super(options);
1502    this.transport = Ajax.getTransport();
1503    this.request(url);
1504  },
1505
1506  request: function(url) {
1507    this.url = url;
1508    this.method = this.options.method;
1509    var params = Object.isString(this.options.parameters) ?
1510          this.options.parameters :
1511          Object.toQueryString(this.options.parameters);
1512
1513    if (!['get', 'post'].include(this.method)) {
1514      params += (params ? '&' : '') + "_method=" + this.method;
1515      this.method = 'post';
1516    }
1517
1518    if (params && this.method === 'get') {
1519      this.url += (this.url.include('?') ? '&' : '?') + params;
1520    }
1521
1522    this.parameters = params.toQueryParams();
1523
1524    try {
1525      var response = new Ajax.Response(this);
1526      if (this.options.onCreate) this.options.onCreate(response);
1527      Ajax.Responders.dispatch('onCreate', this, response);
1528
1529      this.transport.open(this.method.toUpperCase(), this.url,
1530        this.options.asynchronous);
1531
1532      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1533
1534      this.transport.onreadystatechange = this.onStateChange.bind(this);
1535      this.setRequestHeaders();
1536
1537      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1538      this.transport.send(this.body);
1539
1540      /* Force Firefox to handle ready state 4 for synchronous requests */
1541      if (!this.options.asynchronous && this.transport.overrideMimeType)
1542        this.onStateChange();
1543
1544    }
1545    catch (e) {
1546      this.dispatchException(e);
1547    }
1548  },
1549
1550  onStateChange: function() {
1551    var readyState = this.transport.readyState;
1552    if (readyState > 1 && !((readyState == 4) && this._complete))
1553      this.respondToReadyState(this.transport.readyState);
1554  },
1555
1556  setRequestHeaders: function() {
1557    var headers = {
1558      'X-Requested-With': 'XMLHttpRequest',
1559      'X-Prototype-Version': Prototype.Version,
1560      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1561    };
1562
1563    if (this.method == 'post') {
1564      // Begin modified by Zoey
1565      if (this.options.contentType) {
1566        headers['Content-type'] = this.options.contentType +
1567            (this.options.encoding ? '; charset=' + this.options.encoding : '');
1568      }
1569      // End modified by Zoey
1570
1571      /* Force "Connection: close" for older Mozilla browsers to work
1572       * around a bug where XMLHttpRequest sends an incorrect
1573       * Content-length header. See Mozilla Bugzilla #246651.
1574       */
1575      if (this.transport.overrideMimeType &&
1576          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1577            headers['Connection'] = 'close';
1578    }
1579
1580    if (typeof this.options.requestHeaders == 'object') {
1581      var extras = this.options.requestHeaders;
1582
1583      if (Object.isFunction(extras.push))
1584        for (var i = 0, length = extras.length; i < length; i += 2)
1585          headers[extras[i]] = extras[i+1];
1586      else
1587        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1588    }
1589
1590    for (var name in headers)
1591      this.transport.setRequestHeader(name, headers[name]);
1592  },
1593
1594  success: function() {
1595    var status = this.getStatus();
1596    return !status || (status >= 200 && status < 300) || status == 304;
1597  },
1598
1599  getStatus: function() {
1600    try {
1601      if (this.transport.status === 1223) return 204;
1602      return this.transport.status || 0;
1603    } catch (e) { return 0 }
1604  },
1605
1606  respondToReadyState: function(readyState) {
1607    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1608
1609    if (state == 'Complete') {
1610      try {
1611        this._complete = true;
1612        (this.options['on' + response.status]
1613         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1614         || Prototype.emptyFunction)(response, response.headerJSON);
1615      } catch (e) {
1616        this.dispatchException(e);
1617      }
1618
1619      var contentType = response.getHeader('Content-type');
1620      if (this.options.evalJS == 'force'
1621          || (this.options.evalJS && this.isSameOrigin() && contentType
1622          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1623        this.evalResponse();
1624    }
1625
1626    try {
1627      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1628      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1629    } catch (e) {
1630      this.dispatchException(e);
1631    }
1632
1633    if (state == 'Complete') {
1634      this.transport.onreadystatechange = Prototype.emptyFunction;
1635    }
1636  },
1637
1638  isSameOrigin: function() {
1639    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1640    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1641      protocol: location.protocol,
1642      domain: document.domain,
1643      port: location.port ? ':' + location.port : ''
1644    }));
1645  },
1646
1647  getHeader: function(name) {
1648    try {
1649      return this.transport.getResponseHeader(name) || null;
1650    } catch (e) { return null; }
1651  },
1652
1653  evalResponse: function() {
1654    try {
1655      return eval((this.transport.responseText || '').unfilterJSON());
1656    } catch (e) {
1657      this.dispatchException(e);
1658    }
1659  },
1660
1661  dispatchException: function(exception) {
1662    (this.options.onException || Prototype.emptyFunction)(this, exception);
1663    Ajax.Responders.dispatch('onException', this, exception);
1664  }
1665});
1666
1667Ajax.Request.Events =
1668  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1669
1670
1671
1672
1673
1674
1675
1676
1677Ajax.Response = Class.create({
1678  initialize: function(request){
1679    this.request = request;
1680    var transport  = this.transport  = request.transport,
1681        readyState = this.readyState = transport.readyState;
1682
1683    if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1684      this.status       = this.getStatus();
1685      this.statusText   = this.getStatusText();
1686      this.responseText = String.interpret(transport.responseText);
1687      this.headerJSON   = this._getHeaderJSON();
1688    }
1689
1690    if (readyState == 4) {
1691      var xml = transport.responseXML;
1692      this.responseXML  = Object.isUndefined(xml) ? null : xml;
1693      this.responseJSON = this._getResponseJSON();
1694    }
1695  },
1696
1697  status:      0,
1698
1699  statusText: '',
1700
1701  getStatus: Ajax.Request.prototype.getStatus,
1702
1703  getStatusText: function() {
1704    try {
1705      return this.transport.statusText || '';
1706    } catch (e) { return '' }
1707  },
1708
1709  getHeader: Ajax.Request.prototype.getHeader,
1710
1711  getAllHeaders: function() {
1712    try {
1713      return this.getAllResponseHeaders();
1714    } catch (e) { return null }
1715  },
1716
1717  getResponseHeader: function(name) {
1718    return this.transport.getResponseHeader(name);
1719  },
1720
1721  getAllResponseHeaders: function() {
1722    return this.transport.getAllResponseHeaders();
1723  },
1724
1725  _getHeaderJSON: function() {
1726    var json = this.getHeader('X-JSON');
1727    if (!json) return null;
1728    json = decodeURIComponent(escape(json));
1729    try {
1730      return json.evalJSON(this.request.options.sanitizeJSON ||
1731        !this.request.isSameOrigin());
1732    } catch (e) {
1733      this.request.dispatchException(e);
1734    }
1735  },
1736
1737  _getResponseJSON: function() {
1738    var options = this.request.options;
1739    if (!options.evalJSON || (options.evalJSON != 'force' &&
1740      !(this.getHeader('Content-type') || '').include('application/json')) ||
1741        this.responseText.blank())
1742          return null;
1743    try {
1744      return this.responseText.evalJSON(options.sanitizeJSON ||
1745        !this.request.isSameOrigin());
1746    } catch (e) {
1747      this.request.dispatchException(e);
1748    }
1749  }
1750});
1751
1752Ajax.Updater = Class.create(Ajax.Request, {
1753  initialize: function($super, container, url, options) {
1754    this.container = {
1755      success: (container.success || container),
1756      failure: (container.failure || (container.success ? null : container))
1757    };
1758
1759    options = Object.clone(options);
1760    var onComplete = options.onComplete;
1761    options.onComplete = (function(response, json) {
1762      this.updateContent(response.responseText);
1763      if (Object.isFunction(onComplete)) onComplete(response, json);
1764    }).bind(this);
1765
1766    $super(url, options);
1767  },
1768
1769  updateContent: function(responseText) {
1770    var receiver = this.container[this.success() ? 'success' : 'failure'],
1771        options = this.options;
1772
1773    if (!options.evalScripts) responseText = responseText.stripScripts();
1774
1775    if (receiver = $(receiver)) {
1776      if (options.insertion) {
1777        if (Object.isString(options.insertion)) {
1778          var insertion = { }; insertion[options.insertion] = responseText;
1779          receiver.insert(insertion);
1780        }
1781        else options.insertion(receiver, responseText);
1782      }
1783      else receiver.update(responseText);
1784    }
1785  }
1786});
1787
1788Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1789  initialize: function($super, container, url, options) {
1790    $super(options);
1791    this.onComplete = this.options.onComplete;
1792
1793    this.frequency = (this.options.frequency || 2);
1794    this.decay = (this.options.decay || 1);
1795
1796    this.updater = { };
1797    this.container = container;
1798    this.url = url;
1799
1800    this.start();
1801  },
1802
1803  start: function() {
1804    this.options.onComplete = this.updateComplete.bind(this);
1805    this.onTimerEvent();
1806  },
1807
1808  stop: function() {
1809    this.updater.options.onComplete = undefined;
1810    clearTimeout(this.timer);
1811    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1812  },
1813
1814  updateComplete: function(response) {
1815    if (this.options.decay) {
1816      this.decay = (response.responseText == this.lastText ?
1817        this.decay * this.options.decay : 1);
1818
1819      this.lastText = response.responseText;
1820    }
1821    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1822  },
1823
1824  onTimerEvent: function() {
1825    this.updater = new Ajax.Updater(this.container, this.url, this.options);
1826  }
1827});
1828
1829
1830function $(element) {
1831  if (arguments.length > 1) {
1832    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1833      elements.push($(arguments[i]));
1834    return elements;
1835  }
1836  if (Object.isString(element))
1837    element = document.getElementById(element);
1838  return Element.extend(element);
1839}
1840
1841if (Prototype.BrowserFeatures.XPath) {
1842  document._getElementsByXPath = function(expression, parentElement) {
1843    var results = [];
1844    var query = document.evaluate(expression, $(parentElement) || document,
1845      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1846    for (var i = 0, length = query.snapshotLength; i < length; i++)
1847      results.push(Element.extend(query.snapshotItem(i)));
1848    return results;
1849  };
1850}
1851
1852/*--------------------------------------------------------------------------*/
1853
1854if (!Node) var Node = { };
1855
1856if (!Node.ELEMENT_NODE) {
1857  Object.extend(Node, {
1858    ELEMENT_NODE: 1,
1859    ATTRIBUTE_NODE: 2,
1860    TEXT_NODE: 3,
1861    CDATA_SECTION_NODE: 4,
1862    ENTITY_REFERENCE_NODE: 5,
1863    ENTITY_NODE: 6,
1864    PROCESSING_INSTRUCTION_NODE: 7,
1865    COMMENT_NODE: 8,
1866    DOCUMENT_NODE: 9,
1867    DOCUMENT_TYPE_NODE: 10,
1868    DOCUMENT_FRAGMENT_NODE: 11,
1869    NOTATION_NODE: 12
1870  });
1871}
1872
1873
1874
1875(function(global) {
1876  function shouldUseCache(tagName, attributes) {
1877    if (tagName === 'select') return false;
1878    if ('type' in attributes) return false;
1879    return true;
1880  }
1881
1882  var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
1883    try {
1884      var el = document.createElement('<input name="x">');
1885      return el.tagName.toLowerCase() === 'input' && el.name === 'x';
1886    }
1887    catch(err) {
1888      return false;
1889    }
1890  })();
1891
1892  var element = global.Element;
1893
1894  global.Element = function(tagName, attributes) {
1895    attributes = attributes || { };
1896    tagName = tagName.toLowerCase();
1897    var cache = Element.cache;
1898
1899    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
1900      tagName = '<' + tagName + ' name="' + attributes.name + '">';
1901      delete attributes.name;
1902      return Element.writeAttribute(document.createElement(tagName), attributes);
1903    }
1904
1905    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1906
1907    var node = shouldUseCache(tagName, attributes) ?
1908     cache[tagName].cloneNode(false) : document.createElement(tagName);
1909
1910    return Element.writeAttribute(node, attributes);
1911  };
1912
1913  Object.extend(global.Element, element || { });
1914  if (element) global.Element.prototype = element.prototype;
1915
1916})(this);
1917
1918Element.idCounter = 1;
1919Element.cache = { };
1920
1921Element._purgeElement = function(element) {
1922  var uid = element._prototypeUID;
1923  if (uid) {
1924    Element.stopObserving(element);
1925    element._prototypeUID = void 0;
1926    delete Element.Storage[uid];
1927  }
1928}
1929
1930Element.Methods = {
1931  visible: function(element) {
1932    return $(element).style.display != 'none';
1933  },
1934
1935  toggle: function(element) {
1936    element = $(element);
1937    Element[Element.visible(element) ? 'hide' : 'show'](element);
1938    return element;
1939  },
1940
1941  hide: function(element) {
1942    element = $(element);
1943    element.style.display = 'none';
1944    return element;
1945  },
1946
1947  show: function(element) {
1948    element = $(element);
1949    element.style.display = '';
1950    return element;
1951  },
1952
1953  remove: function(element) {
1954    element = $(element);
1955    element.parentNode.removeChild(element);
1956    return element;
1957  },
1958
1959  update: (function(){
1960
1961    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
1962      var el = document.createElement("select"),
1963          isBuggy = true;
1964      el.innerHTML = "<option value=\"test\">test</option>";
1965      if (el.options && el.options[0]) {
1966        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
1967      }
1968      el = null;
1969      return isBuggy;
1970    })();
1971
1972    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
1973      try {
1974        var el = document.createElement("table");
1975        if (el && el.tBodies) {
1976          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
1977          var isBuggy = typeof el.tBodies[0] == "undefined";
1978          el = null;
1979          return isBuggy;
1980        }
1981      } catch (e) {
1982        return true;
1983      }
1984    })();
1985
1986    var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
1987      try {
1988        var el = document.createElement('div');
1989        el.innerHTML = "<link>";
1990        var isBuggy = (el.childNodes.length === 0);
1991        el = null;
1992        return isBuggy;
1993      } catch(e) {
1994        return true;
1995      }
1996    })();
1997
1998    var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
1999     TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
2000
2001    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
2002      var s = document.createElement("script"),
2003          isBuggy = false;
2004      try {
2005        s.appendChild(document.createTextNode(""));
2006        isBuggy = !s.firstChild ||
2007          s.firstChild && s.firstChild.nodeType !== 3;
2008      } catch (e) {
2009        isBuggy = true;
2010      }
2011      s = null;
2012      return isBuggy;
2013    })();
2014
2015
2016    function update(element, content) {
2017      element = $(element);
2018      var purgeElement = Element._purgeElement;
2019
2020      var descendants = element.getElementsByTagName('*'),
2021       i = descendants.length;
2022      while (i--) purgeElement(descendants[i]);
2023
2024      if (content && content.toElement)
2025        content = content.toElement();
2026
2027      if (Object.isElement(content))
2028        return element.update().insert(content);
2029
2030      content = Object.toHTML(content);
2031
2032      var tagName = element.tagName.toUpperCase();
2033
2034      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
2035        element.text = content;
2036        return element;
2037      }
2038
2039      if (ANY_INNERHTML_BUGGY) {
2040        if (tagName in Element._insertionTranslations.tags) {
2041          while (element.firstChild) {
2042            element.removeChild(element.firstChild);
2043          }
2044          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
2045            .each(function(node) {
2046              element.appendChild(node)
2047            });
2048        } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
2049          while (element.firstChild) {
2050            element.removeChild(element.firstChild);
2051          }
2052          var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
2053          nodes.each(function(node) { element.appendChild(node) });
2054        }
2055        else {
2056          element.innerHTML = content.stripScripts();
2057        }
2058      }
2059      else {
2060        element.innerHTML = content.stripScripts();
2061      }
2062
2063      content.evalScripts.bind(content).defer();
2064      return element;
2065    }
2066
2067    return update;
2068  })(),
2069
2070  replace: function(element, content) {
2071    element = $(element);
2072    if (content && content.toElement) content = content.toElement();
2073    else if (!Object.isElement(content)) {
2074      content = Object.toHTML(content);
2075      var range = element.ownerDocument.createRange();
2076      range.selectNode(element);
2077      content.evalScripts.bind(content).defer();
2078      content = range.createContextualFragment(content.stripScripts());
2079    }
2080    element.parentNode.replaceChild(content, element);
2081    return element;
2082  },
2083
2084  insert: function(element, insertions) {
2085    element = $(element);
2086
2087    if (Object.isString(insertions) || Object.isNumber(insertions) ||
2088        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
2089          insertions = {bottom:insertions};
2090
2091    var content, insert, tagName, childNodes;
2092
2093    for (var position in insertions) {
2094      content  = insertions[position];
2095      position = position.toLowerCase();
2096      insert = Element._insertionTranslations[position];
2097
2098      if (content && content.toElement) content = content.toElement();
2099      if (Object.isElement(content)) {
2100        insert(element, content);
2101        continue;
2102      }
2103
2104      content = Object.toHTML(content);
2105
2106      tagName = ((position == 'before' || position == 'after')
2107        ? element.parentNode : element).tagName.toUpperCase();
2108
2109      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2110
2111      if (position == 'top' || position == 'after') childNodes.reverse();
2112      childNodes.each(insert.curry(element));
2113
2114      content.evalScripts.bind(content).defer();
2115    }
2116
2117    return element;
2118  },
2119
2120  wrap: function(element, wrapper, attributes) {
2121    element = $(element);
2122    if (Object.isElement(wrapper))
2123      $(wrapper).writeAttribute(attributes || { });
2124    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
2125    else wrapper = new Element('div', wrapper);
2126    if (element.parentNode)
2127      element.parentNode.replaceChild(wrapper, element);
2128    wrapper.appendChild(element);
2129    return wrapper;
2130  },
2131
2132  inspect: function(element) {
2133    element = $(element);
2134    var result = '<' + element.tagName.toLowerCase();
2135    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
2136      var property = pair.first(),
2137          attribute = pair.last(),
2138          value = (element[property] || '').toString();
2139      if (value) result += ' ' + attribute + '=' + value.inspect(true);
2140    });
2141    return result + '>';
2142  },
2143
2144  recursivelyCollect: function(element, property, maximumLength) {
2145    element = $(element);
2146    maximumLength = maximumLength || -1;
2147    var elements = [];
2148
2149    while (element = element[property]) {
2150      if (element.nodeType == 1)
2151        elements.push(Element.extend(element));
2152      if (elements.length == maximumLength)
2153        break;
2154    }
2155
2156    return elements;
2157  },
2158
2159  ancestors: function(element) {
2160    return Element.recursivelyCollect(element, 'parentNode');
2161  },
2162
2163  descendants: function(element) {
2164    return Element.select(element, "*");
2165  },
2166
2167  firstDescendant: function(element) {
2168    element = $(element).firstChild;
2169    while (element && element.nodeType != 1) element = element.nextSibling;
2170    return $(element);
2171  },
2172
2173  immediateDescendants: function(element) {
2174    var results = [], child = $(element).firstChild;
2175    while (child) {
2176      if (child.nodeType === 1) {
2177        results.push(Element.extend(child));
2178      }
2179      child = child.nextSibling;
2180    }
2181    return results;
2182  },
2183
2184  previousSiblings: function(element, maximumLength) {
2185    return Element.recursivelyCollect(element, 'previousSibling');
2186  },
2187
2188  nextSiblings: function(element) {
2189    return Element.recursivelyCollect(element, 'nextSibling');
2190  },
2191
2192  siblings: function(element) {
2193    element = $(element);
2194    return Element.previousSiblings(element).reverse()
2195      .concat(Element.nextSiblings(element));
2196  },
2197
2198  match: function(element, selector) {
2199    element = $(element);
2200    if (Object.isString(selector))
2201      return Prototype.Selector.match(element, selector);
2202    return selector.match(element);
2203  },
2204
2205  up: function(element, expression, index) {
2206    element = $(element);
2207    if (arguments.length == 1) return $(element.parentNode);
2208    var ancestors = Element.ancestors(element);
2209    return Object.isNumber(expression) ? ancestors[expression] :
2210      Prototype.Selector.find(ancestors, expression, index);
2211  },
2212
2213  down: function(element, expression, index) {
2214    element = $(element);
2215    if (arguments.length == 1) return Element.firstDescendant(element);
2216    return Object.isNumber(expression) ? Element.descendants(element)[expression] :
2217      Element.select(element, expression)[index || 0];
2218  },
2219
2220  previous: function(element, expression, index) {
2221    element = $(element);
2222    if (Object.isNumber(expression)) index = expression, expression = false;
2223    if (!Object.isNumber(index)) index = 0;
2224
2225    if (expression) {
2226      return Prototype.Selector.find(element.previousSiblings(), expression, index);
2227    } else {
2228      return element.recursivelyCollect("previousSibling", index + 1)[index];
2229    }
2230  },
2231
2232  next: function(element, expression, index) {
2233    element = $(element);
2234    if (Object.isNumber(expression)) index = expression, expression = false;
2235    if (!Object.isNumber(index)) index = 0;
2236
2237    if (expression) {
2238      return Prototype.Selector.find(element.nextSiblings(), expression, index);
2239    } else {
2240      var maximumLength = Object.isNumber(index) ? index + 1 : 1;
2241      return element.recursivelyCollect("nextSibling", index + 1)[index];
2242    }
2243  },
2244
2245
2246  select: function(element) {
2247    element = $(element);
2248    var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
2249    return Prototype.Selector.select(expressions, element);
2250  },
2251
2252  adjacent: function(element) {
2253    element = $(element);
2254    var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
2255    return Prototype.Selector.select(expressions, element.parentNode).without(element);
2256  },
2257
2258  identify: function(element) {
2259    element = $(element);
2260    var id = Element.readAttribute(element, 'id');
2261    if (id) return id;
2262    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
2263    Element.writeAttribute(element, 'id', id);
2264    return id;
2265  },
2266
2267  readAttribute: function(element, name) {
2268    element = $(element);
2269    if (Prototype.Browser.IE) {
2270      var t = Element._attributeTranslations.read;
2271      if (t.values[name]) return t.values[name](element, name);
2272      if (t.names[name]) name = t.names[name];
2273      if (name.include(':')) {
2274        return (!element.attributes || !element.attributes[name]) ? null :
2275         element.attributes[name].value;
2276      }
2277    }
2278    return element.getAttribute(name);
2279  },
2280
2281  writeAttribute: function(element, name, value) {
2282    element = $(element);
2283    var attributes = { }, t = Element._attributeTranslations.write;
2284
2285    if (typeof name == 'object') attributes = name;
2286    else attributes[name] = Object.isUndefined(value) ? true : value;
2287
2288    for (var attr in attributes) {
2289      name = t.names[attr] || attr;
2290      value = attributes[attr];
2291      if (t.values[attr]) name = t.values[attr](element, value);
2292      if (value === false || value === null)
2293        element.removeAttribute(name);
2294      else if (value === true)
2295        element.setAttribute(name, name);
2296      else element.setAttribute(name, value);
2297    }
2298    return element;
2299  },
2300
2301  getHeight: function(element) {
2302    return Element.getDimensions(element).height;
2303  },
2304
2305  getWidth: function(element) {
2306    return Element.getDimensions(element).width;
2307  },
2308
2309  classNames: function(element) {
2310    return new Element.ClassNames(element);
2311  },
2312
2313  hasClassName: function(element, className) {
2314    if (!(element = $(element))) return;
2315    var elementClassName = element.className;
2316    return (elementClassName.length > 0 && (elementClassName == className ||
2317      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
2318  },
2319
2320  addClassName: function(element, className) {
2321    if (!(element = $(element))) return;
2322    if (!Element.hasClassName(element, className))
2323      element.className += (element.className ? ' ' : '') + className;
2324    return element;
2325  },
2326
2327  removeClassName: function(element, className) {
2328    if (!(element = $(element))) return;
2329    element.className = element.className.replace(
2330      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
2331    return element;
2332  },
2333
2334  toggleClassName: function(element, className) {
2335    if (!(element = $(element))) return;
2336    return Element[Element.hasClassName(element, className) ?
2337      'removeClassName' : 'addClassName'](element, className);
2338  },
2339
2340  cleanWhitespace: function(element) {
2341    element = $(element);
2342    var node = element.firstChild;
2343    while (node) {
2344      var nextNode = node.nextSibling;
2345      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
2346        element.removeChild(node);
2347      node = nextNode;
2348    }
2349    return element;
2350  },
2351
2352  empty: function(element) {
2353    return $(element).innerHTML.blank();
2354  },
2355
2356  descendantOf: function(element, ancestor) {
2357    element = $(element), ancestor = $(ancestor);
2358
2359    if (element.compareDocumentPosition)
2360      return (element.compareDocumentPosition(ancestor) & 8) === 8;
2361
2362    if (ancestor.contains)
2363      return ancestor.contains(element) && ancestor !== element;
2364
2365    while (element = element.parentNode)
2366      if (element == ancestor) return true;
2367
2368    return false;
2369  },
2370
2371  scrollTo: function(element) {
2372    element = $(element);
2373    var pos = Element.cumulativeOffset(element);
2374    window.scrollTo(pos[0], pos[1]);
2375    return element;
2376  },
2377
2378  getStyle: function(element, style) {
2379    element = $(element);
2380    style = style == 'float' ? 'cssFloat' : style.camelize();
2381    var value = element.style[style];
2382    if (!value || value == 'auto') {
2383      var css = document.defaultView.getComputedStyle(element, null);
2384      value = css ? css[style] : null;
2385    }
2386    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
2387    return value == 'auto' ? null : value;
2388  },
2389
2390  getOpacity: function(element) {
2391    return $(element).getStyle('opacity');
2392  },
2393
2394  setStyle: function(element, styles) {
2395    element = $(element);
2396    var elementStyle = element.style, match;
2397    if (Object.isString(styles)) {
2398      element.style.cssText += ';' + styles;
2399      return styles.include('opacity') ?
2400        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
2401    }
2402    for (var property in styles)
2403      if (property == 'opacity') element.setOpacity(styles[property]);
2404      else
2405        elementStyle[(property == 'float' || property == 'cssFloat') ?
2406          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
2407            property] = styles[property];
2408
2409    return element;
2410  },
2411
2412  setOpacity: function(element, value) {
2413    element = $(element);
2414    element.style.opacity = (value == 1 || value === '') ? '' :
2415      (value < 0.00001) ? 0 : value;
2416    return element;
2417  },
2418
2419  makePositioned: function(element) {
2420    element = $(element);
2421    var pos = Element.getStyle(element, 'position');
2422    if (pos == 'static' || !pos) {
2423      element._madePositioned = true;
2424      element.style.position = 'relative';
2425      if (Prototype.Browser.Opera) {
2426        element.style.top = 0;
2427        element.style.left = 0;
2428      }
2429    }
2430    return element;
2431  },
2432
2433  undoPositioned: function(element) {
2434    element = $(element);
2435    if (element._madePositioned) {
2436      element._madePositioned = undefined;
2437      element.style.position =
2438        element.style.top =
2439        element.style.left =
2440        element.style.bottom =
2441        element.style.right = '';
2442    }
2443    return element;
2444  },
2445
2446  makeClipping: function(element) {
2447    element = $(element);
2448    if (element._overflow) return element;
2449    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
2450    if (element._overflow !== 'hidden')
2451      element.style.overflow = 'hidden';
2452    return element;
2453  },
2454
2455  undoClipping: function(element) {
2456    element = $(element);
2457    if (!element._overflow) return element;
2458    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
2459    element._overflow = null;
2460    return element;
2461  },
2462
2463  clonePosition: function(element, source) {
2464    var options = Object.extend({
2465      setLeft:    true,
2466      setTop:     true,
2467      setWidth:   true,
2468      setHeight:  true,
2469      offsetTop:  0,
2470      offsetLeft: 0
2471    }, arguments[2] || { });
2472
2473    source = $(source);
2474    var p = Element.viewportOffset(source), delta = [0, 0], parent = null;
2475
2476    element = $(element);
2477
2478    if (Element.getStyle(element, 'position') == 'absolute') {
2479      parent = Element.getOffsetParent(element);
2480      delta = Element.viewportOffset(parent);
2481    }
2482
2483    if (parent == document.body) {
2484      delta[0] -= document.body.offsetLeft;
2485      delta[1] -= document.body.offsetTop;
2486    }
2487
2488    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
2489    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
2490    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
2491    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
2492    return element;
2493  }
2494};
2495
2496Object.extend(Element.Methods, {
2497  getElementsBySelector: Element.Methods.select,
2498
2499  childElements: Element.Methods.immediateDescendants
2500});
2501
2502Element._attributeTranslations = {
2503  write: {
2504    names: {
2505      className: 'class',
2506      htmlFor:   'for'
2507    },
2508    values: { }
2509  }
2510};
2511
2512if (Prototype.Browser.Opera) {
2513  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2514    function(proceed, element, style) {
2515      switch (style) {
2516        case 'height': case 'width':
2517          if (!Element.visible(element)) return null;
2518
2519          var dim = parseInt(proceed(element, style), 10);
2520
2521          if (dim !== element['offset' + style.capitalize()])
2522            return dim + 'px';
2523
2524          var properties;
2525          if (style === 'height') {
2526            properties = ['border-top-width', 'padding-top',
2527             'padding-bottom', 'border-bottom-width'];
2528          }
2529          else {
2530            properties = ['border-left-width', 'padding-left',
2531             'padding-right', 'border-right-width'];
2532          }
2533          return properties.inject(dim, function(memo, property) {
2534            var val = proceed(element, property);
2535            return val === null ? memo : memo - parseInt(val, 10);
2536          }) + 'px';
2537        default: return proceed(element, style);
2538      }
2539    }
2540  );
2541
2542  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2543    function(proceed, element, attribute) {
2544      if (attribute === 'title') return element.title;
2545      return proceed(element, attribute);
2546    }
2547  );
2548}
2549
2550else if (Prototype.Browser.IE) {
2551  Element.Methods.getStyle = function(element, style) {
2552    element = $(element);
2553    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
2554    var value = element.style[style];
2555    if (!value && element.currentStyle) value = element.currentStyle[style];
2556
2557    if (style == 'opacity') {
2558      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
2559        if (value[1]) return parseFloat(value[1]) / 100;
2560      return 1.0;
2561    }
2562
2563    if (value == 'auto') {
2564      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
2565        return element['offset' + style.capitalize()] + 'px';
2566      return null;
2567    }
2568    return value;
2569  };
2570
2571  Element.Methods.setOpacity = function(element, value) {
2572    function stripAlpha(filter){
2573      return filter.replace(/alpha\([^\)]*\)/gi,'');
2574    }
2575    element = $(element);
2576    var currentStyle = element.currentStyle;
2577    if ((currentStyle && !currentStyle.hasLayout) ||
2578      (!currentStyle && element.style.zoom == 'normal'))
2579        element.style.zoom = 1;
2580
2581    var filter = element.getStyle('filter'), style = element.style;
2582    if (value == 1 || value === '') {
2583      (filter = stripAlpha(filter)) ?
2584        style.filter = filter : style.removeAttribute('filter');
2585      return element;
2586    } else if (value < 0.00001) value = 0;
2587    style.filter = stripAlpha(filter) +
2588      'alpha(opacity=' + (value * 100) + ')';
2589    return element;
2590  };
2591
2592  Element._attributeTranslations = (function(){
2593
2594    var classProp = 'className',
2595        forProp = 'for',
2596        el = document.createElement('div');
2597
2598    el.setAttribute(classProp, 'x');
2599
2600    if (el.className !== 'x') {
2601      el.setAttribute('class', 'x');
2602      if (el.className === 'x') {
2603        classProp = 'class';
2604      }
2605    }
2606    el = null;
2607
2608    el = document.createElement('label');
2609    el.setAttribute(forProp, 'x');
2610    if (el.htmlFor !== 'x') {
2611      el.setAttribute('htmlFor', 'x');
2612      if (el.htmlFor === 'x') {
2613        forProp = 'htmlFor';
2614      }
2615    }
2616    el = null;
2617
2618    return {
2619      read: {
2620        names: {
2621          'class':      classProp,
2622          'className':  classProp,
2623          'for':        forProp,
2624          'htmlFor':    forProp
2625        },
2626        values: {
2627          _getAttr: function(element, attribute) {
2628            return element.getAttribute(attribute);
2629          },
2630          _getAttr2: function(element, attribute) {
2631            return element.getAttribute(attribute, 2);
2632          },
2633          _getAttrNode: function(element, attribute) {
2634            var node = element.getAttributeNode(attribute);
2635            return node ? node.value : "";
2636          },
2637          _getEv: (function(){
2638
2639            var el = document.createElement('div'), f;
2640            el.onclick = Prototype.emptyFunction;
2641            var value = el.getAttribute('onclick');
2642
2643            if (String(value).indexOf('{') > -1) {
2644              f = function(element, attribute) {
2645                attribute = element.getAttribute(attribute);
2646                if (!attribute) return null;
2647                attribute = attribute.toString();
2648                attribute = attribute.split('{')[1];
2649                attribute = attribute.split('}')[0];
2650                return attribute.strip();
2651              };
2652            }
2653            else if (value === '') {
2654              f = function(element, attribute) {
2655                attribute = element.getAttribute(attribute);
2656                if (!attribute) return null;
2657                return attribute.strip();
2658              };
2659            }
2660            el = null;
2661            return f;
2662          })(),
2663          _flag: function(element, attribute) {
2664            return $(element).hasAttribute(attribute) ? attribute : null;
2665          },
2666          style: function(element) {
2667            return element.style.cssText.toLowerCase();
2668          },
2669          title: function(element) {
2670            return element.title;
2671          }
2672        }
2673      }
2674    }
2675  })();
2676
2677  Element._attributeTranslations.write = {
2678    names: Object.extend({
2679      cellpadding: 'cellPadding',
2680      cellspacing: 'cellSpacing'
2681    }, Element._attributeTranslations.read.names),
2682    values: {
2683      checked: function(element, value) {
2684        element.checked = !!value;
2685      },
2686
2687      style: function(element, value) {
2688        element.style.cssText = value ? value : '';
2689      }
2690    }
2691  };
2692
2693  Element._attributeTranslations.has = {};
2694
2695  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
2696      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
2697    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
2698    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
2699  });
2700
2701  (function(v) {
2702    Object.extend(v, {
2703      href:        v._getAttr2,
2704      src:         v._getAttr2,
2705      type:        v._getAttr,
2706      action:      v._getAttrNode,
2707      disabled:    v._flag,
2708      checked:     v._flag,
2709      readonly:    v._flag,
2710      multiple:    v._flag,
2711      onload:      v._getEv,
2712      onunload:    v._getEv,
2713      onclick:     v._getEv,
2714      ondblclick:  v._getEv,
2715      onmousedown: v._getEv,
2716      onmouseup:   v._getEv,
2717      onmouseover: v._getEv,
2718      onmousemove: v._getEv,
2719      onmouseout:  v._getEv,
2720      onfocus:     v._getEv,
2721      onblur:      v._getEv,
2722      onkeypress:  v._getEv,
2723      onkeydown:   v._getEv,
2724      onkeyup:     v._getEv,
2725      onsubmit:    v._getEv,
2726      onreset:     v._getEv,
2727      onselect:    v._getEv,
2728      onchange:    v._getEv
2729    });
2730  })(Element._attributeTranslations.read.values);
2731
2732  if (Prototype.BrowserFeatures.ElementExtensions) {
2733    (function() {
2734      function _descendants(element) {
2735        var nodes = element.getElementsByTagName('*'), results = [];
2736        for (var i = 0, node; node = nodes[i]; i++)
2737          if (node.tagName !== "!") // Filter out comment nodes.
2738            results.push(node);
2739        return results;
2740      }
2741
2742      Element.Methods.down = function(element, expression, index) {
2743        element = $(element);
2744        if (arguments.length == 1) return element.firstDescendant();
2745        return Object.isNumber(expression) ? _descendants(element)[expression] :
2746          Element.select(element, expression)[index || 0];
2747      }
2748    })();
2749  }
2750
2751}
2752
2753else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
2754  Element.Methods.setOpacity = function(element, value) {
2755    element = $(element);
2756    element.style.opacity = (value == 1) ? 0.999999 :
2757      (value === '') ? '' : (value < 0.00001) ? 0 : value;
2758    return element;
2759  };
2760}
2761
2762else if (Prototype.Browser.WebKit) {
2763  Element.Methods.setOpacity = function(element, value) {
2764    element = $(element);
2765    element.style.opacity = (value == 1 || value === '') ? '' :
2766      (value < 0.00001) ? 0 : value;
2767
2768    if (value == 1)
2769      if (element.tagName.toUpperCase() == 'IMG' && element.width) {
2770        element.width++; element.width--;
2771      } else try {
2772        var n = document.createTextNode(' ');
2773        element.appendChild(n);
2774        element.removeChild(n);
2775      } catch (e) { }
2776
2777    return element;
2778  };
2779}
2780
2781if ('outerHTML' in document.documentElement) {
2782  Element.Methods.replace = function(element, content) {
2783    element = $(element);
2784
2785    if (content && content.toElement) content = content.toElement();
2786    if (Object.isElement(content)) {
2787      element.parentNode.replaceChild(content, element);
2788      return element;
2789    }
2790
2791    content = Object.toHTML(content);
2792    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2793
2794    if (Element._insertionTranslations.tags[tagName]) {
2795      var nextSibling = element.next(),
2796          fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2797      parent.removeChild(element);
2798      if (nextSibling)
2799        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
2800      else
2801        fragments.each(function(node) { parent.appendChild(node) });
2802    }
2803    else element.outerHTML = content.stripScripts();
2804
2805    content.evalScripts.bind(content).defer();
2806    return element;
2807  };
2808}
2809
2810Element._returnOffset = function(l, t) {
2811  var result = [l, t];
2812  result.left = l;
2813  result.top = t;
2814  return result;
2815};
2816
2817Element._getContentFromAnonymousElement = function(tagName, html, force) {
2818  var div = new Element('div'),
2819      t = Element._insertionTranslations.tags[tagName];
2820
2821  var workaround = false;
2822  if (t) workaround = true;
2823  else if (force) {
2824    workaround = true;
2825    t = ['', '', 0];
2826  }
2827
2828  if (workaround) {
2829    div.innerHTML = '&nbsp;' + t[0] + html + t[1];
2830    div.removeChild(div.firstChild);
2831    for (var i = t[2]; i--; ) {
2832      div = div.firstChild;
2833    }
2834  }
2835  else {
2836    div.innerHTML = html;
2837  }
2838  return $A(div.childNodes);
2839};
2840
2841Element._insertionTranslations = {
2842  before: function(element, node) {
2843    element.parentNode.insertBefore(node, element);
2844  },
2845  top: function(element, node) {
2846    element.insertBefore(node, element.firstChild);
2847  },
2848  bottom: function(element, node) {
2849    element.appendChild(node);
2850  },
2851  after: function(element, node) {
2852    element.parentNode.insertBefore(node, element.nextSibling);
2853  },
2854  tags: {
2855    TABLE:  ['<table>',                '</table>',                   1],
2856    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
2857    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
2858    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2859    SELECT: ['<select>',               '</select>',                  1]
2860  }
2861};
2862
2863(function() {
2864  var tags = Element._insertionTranslations.tags;
2865  Object.extend(tags, {
2866    THEAD: tags.TBODY,
2867    TFOOT: tags.TBODY,
2868    TH:    tags.TD
2869  });
2870})();
2871
2872Element.Methods.Simulated = {
2873  hasAttribute: function(element, attribute) {
2874    attribute = Element._attributeTranslations.has[attribute] || attribute;
2875    var node = $(element).getAttributeNode(attribute);
2876    return !!(node && node.specified);
2877  }
2878};
2879
2880Element.Methods.ByTag = { };
2881
2882Object.extend(Element, Element.Methods);
2883
2884(function(div) {
2885
2886  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
2887    window.HTMLElement = { };
2888    window.HTMLElement.prototype = div['__proto__'];
2889    Prototype.BrowserFeatures.ElementExtensions = true;
2890  }
2891
2892  div = null;
2893
2894})(document.createElement('div'));
2895
2896Element.extend = (function() {
2897
2898  function checkDeficiency(tagName) {
2899    if (typeof window.Element != 'undefined') {
2900      var proto = window.Element.prototype;
2901      if (proto) {
2902        var id = '_' + (Math.random()+'').slice(2),
2903            el = document.createElement(tagName);
2904        proto[id] = 'x';
2905        var isBuggy = (el[id] !== 'x');
2906        delete proto[id];
2907        el = null;
2908        return isBuggy;
2909      }
2910    }
2911    return false;
2912  }
2913
2914  function extendElementWith(element, methods) {
2915    for (var property in methods) {
2916      var value = methods[property];
2917      if (Object.isFunction(value) && !(property in element))
2918        element[property] = value.methodize();
2919    }
2920  }
2921
2922  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
2923
2924  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
2925    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
2926      return function(element) {
2927        if (element && typeof element._extendedByPrototype == 'undefined') {
2928          var t = element.tagName;
2929          if (t && (/^(?:object|applet|embed)$/i.test(t))) {
2930            extendElementWith(element, Element.Methods);
2931            extendElementWith(element, Element.Methods.Simulated);
2932            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
2933          }
2934        }
2935        return element;
2936      }
2937    }
2938    return Prototype.K;
2939  }
2940
2941  var Methods = { }, ByTag = Element.Methods.ByTag;
2942
2943  var extend = Object.extend(function(element) {
2944    if (!element || typeof element._extendedByPrototype != 'undefined' ||
2945        element.nodeType != 1 || element == window) return element;
2946
2947    var methods = Object.clone(Methods),
2948        tagName = element.tagName.toUpperCase();
2949
2950    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2951
2952    extendElementWith(element, methods);
2953
2954    element._extendedByPrototype = Prototype.emptyFunction;
2955    return element;
2956
2957  }, {
2958    refresh: function() {
2959      if (!Prototype.BrowserFeatures.ElementExtensions) {
2960        Object.extend(Methods, Element.Methods);
2961        Object.extend(Methods, Element.Methods.Simulated);
2962      }
2963    }
2964  });
2965
2966  extend.refresh();
2967  return extend;
2968})();
2969
2970if (document.documentElement.hasAttribute) {
2971  Element.hasAttribute = function(element, attribute) {
2972    return element.hasAttribute(attribute);
2973  };
2974}
2975else {
2976  Element.hasAttribute = Element.Methods.Simulated.hasAttribute;
2977}
2978
2979Element.addMethods = function(methods) {
2980  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
2981
2982  if (!methods) {
2983    Object.extend(Form, Form.Methods);
2984    Object.extend(Form.Element, Form.Element.Methods);
2985    Object.extend(Element.Methods.ByTag, {
2986      "FORM":     Object.clone(Form.Methods),
2987      "INPUT":    Object.clone(Form.Element.Methods),
2988      "SELECT":   Object.clone(Form.Element.Methods),
2989      "TEXTAREA": Object.clone(Form.Element.Methods),
2990      "BUTTON":   Object.clone(Form.Element.Methods)
2991    });
2992  }
2993
2994  if (arguments.length == 2) {
2995    var tagName = methods;
2996    methods = arguments[1];
2997  }
2998
2999  if (!tagName) Object.extend(Element.Methods, methods || { });
3000  else {
3001    if (Object.isArray(tagName)) tagName.each(extend);
3002    else extend(tagName);
3003  }
3004
3005  function extend(tagName) {
3006    tagName = tagName.toUpperCase();
3007    if (!Element.Methods.ByTag[tagName])
3008      Element.Methods.ByTag[tagName] = { };
3009    Object.extend(Element.Methods.ByTag[tagName], methods);
3010  }
3011
3012  function copy(methods, destination, onlyIfAbsent) {
3013    onlyIfAbsent = onlyIfAbsent || false;
3014    for (var property in methods) {
3015      var value = methods[property];
3016      if (!Object.isFunction(value)) continue;
3017      if (!onlyIfAbsent || !(property in destination))
3018        destination[property] = value.methodize();
3019    }
3020  }
3021
3022  function findDOMClass(tagName) {
3023    var klass;
3024    var trans = {
3025      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3026      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3027      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3028      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3029      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3030      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3031      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3032      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3033      "FrameSet", "IFRAME": "IFrame"
3034    };
3035    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3036    if (window[klass]) return window[klass];
3037    klass = 'HTML' + tagName + 'Element';
3038    if (window[klass]) return window[klass];
3039    klass = 'HTML' + tagName.capitalize() + 'Element';
3040    if (window[klass]) return window[klass];
3041
3042    var element = document.createElement(tagName),
3043        proto = element['__proto__'] || element.constructor.prototype;
3044
3045    element = null;
3046    return proto;
3047  }
3048
3049  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
3050   Element.prototype;
3051
3052  if (F.ElementExtensions) {
3053    copy(Element.Methods, elementPrototype);
3054    copy(Element.Methods.Simulated, elementPrototype, true);
3055  }
3056
3057  if (F.SpecificElementExtensions) {
3058    for (var tag in Element.Methods.ByTag) {
3059      var klass = findDOMClass(tag);
3060      if (Object.isUndefined(klass)) continue;
3061      copy(T[tag], klass.prototype);
3062    }
3063  }
3064
3065  Object.extend(Element, Element.Methods);
3066  delete Element.ByTag;
3067
3068  if (Element.extend.refresh) Element.extend.refresh();
3069  Element.cache = { };
3070};
3071
3072
3073document.viewport = {
3074
3075  getDimensions: function() {
3076    return { width: this.getWidth(), height: this.getHeight() };
3077  },
3078
3079  getScrollOffsets: function() {
3080    return Element._returnOffset(
3081      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
3082      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
3083  }
3084};
3085
3086(function(viewport) {
3087  var B = Prototype.Browser, doc = document, element, property = {};
3088
3089  function getRootElement() {
3090    if (B.WebKit && !doc.evaluate)
3091      return document;
3092
3093    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
3094      return document.body;
3095
3096    return document.documentElement;
3097  }
3098
3099  function define(D) {
3100    if (!element) element = getRootElement();
3101
3102    property[D] = 'client' + D;
3103
3104    viewport['get' + D] = function() { return element[property[D]] };
3105    return viewport['get' + D]();
3106  }
3107
3108  viewport.getWidth  = define.curry('Width');
3109
3110  viewport.getHeight = define.curry('Height');
3111})(document.viewport);
3112
3113
3114Element.Storage = {
3115  UID: 1
3116};
3117
3118Element.addMethods({
3119  getStorage: function(element) {
3120    if (!(element = $(element))) return;
3121
3122    var uid;
3123    if (element === window) {
3124      uid = 0;
3125    } else {
3126      if (typeof element._prototypeUID === "undefined")
3127        element._prototypeUID = Element.Storage.UID++;
3128      uid = element._prototypeUID;
3129    }
3130
3131    if (!Element.Storage[uid])
3132      Element.Storage[uid] = $H();
3133
3134    return Element.Storage[uid];
3135  },
3136
3137  store: function(element, key, value) {
3138    if (!(element = $(element))) return;
3139
3140    if (arguments.length === 2) {
3141      Element.getStorage(element).update(key);
3142    } else {
3143      Element.getStorage(element).set(key, value);
3144    }
3145
3146    return element;
3147  },
3148
3149  retrieve: function(element, key, defaultValue) {
3150    if (!(element = $(element))) return;
3151    var hash = Element.getStorage(element), value = hash.get(key);
3152
3153    if (Object.isUndefined(value)) {
3154      hash.set(key, defaultValue);
3155      value = defaultValue;
3156    }
3157
3158    return value;
3159  },
3160
3161  clone: function(element, deep) {
3162    if (!(element = $(element))) return;
3163    var clone = element.cloneNode(deep);
3164    clone._prototypeUID = void 0;
3165    if (deep) {
3166      var descendants = Element.select(clone, '*'),
3167          i = descendants.length;
3168      while (i--) {
3169        descendants[i]._prototypeUID = void 0;
3170      }
3171    }
3172    return Element.extend(clone);
3173  },
3174
3175  purge: function(element) {
3176    if (!(element = $(element))) return;
3177    var purgeElement = Element._purgeElement;
3178
3179    purgeElement(element);
3180
3181    var descendants = element.getElementsByTagName('*'),
3182     i = descendants.length;
3183
3184    while (i--) purgeElement(descendants[i]);
3185
3186    return null;
3187  }
3188});
3189
3190(function() {
3191
3192  function toDecimal(pctString) {
3193    var match = pctString.match(/^(\d+)%?$/i);
3194    if (!match) return null;
3195    return (Number(match[1]) / 100);
3196  }
3197
3198  function getPixelValue(value, property, context) {
3199    var element = null;
3200    if (Object.isElement(value)) {
3201      element = value;
3202      value = element.getStyle(property);
3203    }
3204
3205    if (value === null) {
3206      return null;
3207    }
3208
3209    if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
3210      return window.parseFloat(value);
3211    }
3212
3213    var isPercentage = value.include('%'), isViewport = (context === document.viewport);
3214
3215    if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
3216      var style = element.style.left, rStyle = element.runtimeStyle.left;
3217      element.runtimeStyle.left = element.currentStyle.left;
3218      element.style.left = value || 0;
3219      value = element.style.pixelLeft;
3220      element.style.left = style;
3221      element.runtimeStyle.left = rStyle;
3222
3223      return value;
3224    }
3225
3226    if (element && isPercentage) {
3227      context = context || element.parentNode;
3228      var decimal = toDecimal(value);
3229      var whole = null;
3230      var position = element.getStyle('position');
3231
3232      var isHorizontal = property.include('left') || property.include('right') ||
3233       property.include('width');
3234
3235      var isVertical =  property.include('top') || property.include('bottom') ||
3236        property.include('height');
3237
3238      if (context === document.viewport) {
3239        if (isHorizontal) {
3240          whole = document.viewport.getWidth();
3241        } else if (isVertical) {
3242          whole = document.viewport.getHeight();
3243        }
3244      } else {
3245        if (isHorizontal) {
3246          whole = $(context).measure('width');
3247        } else if (isVertical) {
3248          whole = $(context).measure('height');
3249        }
3250      }
3251
3252      return (whole === null) ? 0 : whole * decimal;
3253    }
3254
3255    return 0;
3256  }
3257
3258  function toCSSPixels(number) {
3259    if (Object.isString(number) && number.endsWith('px')) {
3260      return number;
3261    }
3262    return number + 'px';
3263  }
3264
3265  function isDisplayed(element) {
3266    var originalElement = element;
3267    while (element && element.parentNode) {
3268      var display = element.getStyle('display');
3269      if (display === 'none') {
3270        return false;
3271      }
3272      element = $(element.parentNode);
3273    }
3274    return true;
3275  }
3276
3277  var hasLayout = Prototype.K;
3278  if ('currentStyle' in document.documentElement) {
3279    hasLayout = function(element) {
3280      if (!element.currentStyle.hasLayout) {
3281        element.style.zoom = 1;
3282      }
3283      return element;
3284    };
3285  }
3286
3287  function cssNameFor(key) {
3288    if (key.include('border')) key = key + '-width';
3289    return key.camelize();
3290  }
3291
3292  Element.Layout = Class.create(Hash, {
3293    initialize: function($super, element, preCompute) {
3294      $super();
3295      this.element = $(element);
3296
3297      Element.Layout.PROPERTIES.each( function(property) {
3298        this._set(property, null);
3299      }, this);
3300
3301      if (preCompute) {
3302        this._preComputing = true;
3303        this._begin();
3304        Element.Layout.PROPERTIES.each( this._compute, this );
3305        this._end();
3306        this._preComputing = false;
3307      }
3308    },
3309
3310    _set: function(property, value) {
3311      return Hash.prototype.set.call(this, property, value);
3312    },
3313
3314    set: function(property, value) {
3315      throw "Properties of Element.Layout are read-only.";
3316    },
3317
3318    get: function($super, property) {
3319      var value = $super(property);
3320      return value === null ? this._compute(property) : value;
3321    },
3322
3323    _begin: function() {
3324      if (this._prepared) return;
3325
3326      var element = this.element;
3327      if (isDisplayed(element)) {
3328        this._prepared = true;
3329        return;
3330      }
3331
3332      var originalStyles = {
3333        position:   element.style.position   || '',
3334        width:      element.style.width      || '',
3335        visibility: element.style.visibility || '',
3336        display:    element.style.display    || ''
3337      };
3338
3339      element.store('prototype_original_styles', originalStyles);
3340
3341      var position = element.getStyle('position'),
3342       width = element.getStyle('width');
3343
3344      if (width === "0px" || width === null) {
3345        element.style.display = 'block';
3346        width = element.getStyle('width');
3347      }
3348
3349      var context = (position === 'fixed') ? document.viewport :
3350       element.parentNode;
3351
3352      element.setStyle({
3353        position:   'absolute',
3354        visibility: 'hidden',
3355        display:    'block'
3356      });
3357
3358      var positionedWidth = element.getStyle('width');
3359
3360      var newWidth;
3361      if (width && (positionedWidth === width)) {
3362        newWidth = getPixelValue(element, 'width', context);
3363      } else if (position === 'absolute' || position === 'fixed') {
3364        newWidth = getPixelValue(element, 'width', context);
3365      } else {
3366        var parent = element.parentNode, pLayout = $(parent).getLayout();
3367
3368        newWidth = pLayout.get('width') -
3369         this.get('margin-left') -
3370         this.get('border-left') -
3371         this.get('padding-left') -
3372         this.get('padding-right') -
3373         this.get('border-right') -
3374         this.get('margin-right');
3375      }
3376
3377      element.setStyle({ width: newWidth + 'px' });
3378
3379      this._prepared = true;
3380    },
3381
3382    _end: function() {
3383      var element = this.element;
3384      var originalStyles = element.retrieve('prototype_original_styles');
3385      element.store('prototype_original_styles', null);
3386      element.setStyle(originalStyles);
3387      this._prepared = false;
3388    },
3389
3390    _compute: function(property) {
3391      var COMPUTATIONS = Element.Layout.COMPUTATIONS;
3392      if (!(property in COMPUTATIONS)) {
3393        throw "Property not found.";
3394      }
3395
3396      return this._set(property, COMPUTATIONS[property].call(this, this.element));
3397    },
3398
3399    toObject: function() {
3400      var args = $A(arguments);
3401      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3402       args.join(' ').split(' ');
3403      var obj = {};
3404      keys.each( function(key) {
3405        if (!Element.Layout.PROPERTIES.include(key)) return;
3406        var value = this.get(key);
3407        if (value != null) obj[key] = value;
3408      }, this);
3409      return obj;
3410    },
3411
3412    toHash: function() {
3413      var obj = this.toObject.apply(this, arguments);
3414      return new Hash(obj);
3415    },
3416
3417    toCSS: function() {
3418      var args = $A(arguments);
3419      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3420       args.join(' ').split(' ');
3421      var css = {};
3422
3423      keys.each( function(key) {
3424        if (!Element.Layout.PROPERTIES.include(key)) return;
3425        if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
3426
3427        var value = this.get(key);
3428        if (value != null) css[cssNameFor(key)] = value + 'px';
3429      }, this);
3430      return css;
3431    },
3432
3433    inspect: function() {
3434      return "#<Element.Layout>";
3435    }
3436  });
3437
3438  Object.extend(Element.Layout, {
3439    PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
3440
3441    COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
3442
3443    COMPUTATIONS: {
3444      'height': function(element) {
3445        if (!this._preComputing) this._begin();
3446
3447        var bHeight = this.get('border-box-height');
3448        if (bHeight <= 0) {
3449          if (!this._preComputing) this._end();
3450          return 0;
3451        }
3452
3453        var bTop = this.get('border-top'),
3454         bBottom = this.get('border-bottom');
3455
3456        var pTop = this.get('padding-top'),
3457         pBottom = this.get('padding-bottom');
3458
3459        if (!this._preComputing) this._end();
3460
3461        return bHeight - bTop - bBottom - pTop - pBottom;
3462      },
3463
3464      'width': function(element) {
3465        if (!this._preComputing) this._begin();
3466
3467        var bWidth = this.get('border-box-width');
3468        if (bWidth <= 0) {
3469          if (!this._preComputing) this._end();
3470          return 0;
3471        }
3472
3473        var bLeft = this.get('border-left'),
3474         bRight = this.get('border-right');
3475
3476        var pLeft = this.get('padding-left'),
3477         pRight = this.get('padding-right');
3478
3479        if (!this._preComputing) this._end();
3480
3481        return bWidth - bLeft - bRight - pLeft - pRight;
3482      },
3483
3484      'padding-box-height': function(element) {
3485        var height = this.get('height'),
3486         pTop = this.get('padding-top'),
3487         pBottom = this.get('padding-bottom');
3488
3489        return height + pTop + pBottom;
3490      },
3491
3492      'padding-box-width': function(element) {
3493        var width = this.get('width'),
3494         pLeft = this.get('padding-left'),
3495         pRight = this.get('padding-right');
3496
3497        return width + pLeft + pRight;
3498      },
3499
3500      'border-box-height': function(element) {
3501        if (!this._preComputing) this._begin();
3502        var height = element.offsetHeight;
3503        if (!this._preComputing) this._end();
3504        return height;
3505      },
3506
3507      'border-box-width': function(element) {
3508        if (!this._preComputing) this._begin();
3509        var width = element.offsetWidth;
3510        if (!this._preComputing) this._end();
3511        return width;
3512      },
3513
3514      'margin-box-height': function(element) {
3515        var bHeight = this.get('border-box-height'),
3516         mTop = this.get('margin-top'),
3517         mBottom = this.get('margin-bottom');
3518
3519        if (bHeight <= 0) return 0;
3520
3521        return bHeight + mTop + mBottom;
3522      },
3523
3524      'margin-box-width': function(element) {
3525        var bWidth = this.get('border-box-width'),
3526         mLeft = this.get('margin-left'),
3527         mRight = this.get('margin-right');
3528
3529        if (bWidth <= 0) return 0;
3530
3531        return bWidth + mLeft + mRight;
3532      },
3533
3534      'top': function(element) {
3535        var offset = element.positionedOffset();
3536        return offset.top;
3537      },
3538
3539      'bottom': function(element) {
3540        var offset = element.positionedOffset(),
3541         parent = element.getOffsetParent(),
3542         pHeight = parent.measure('height');
3543
3544        var mHeight = this.get('border-box-height');
3545
3546        return pHeight - mHeight - offset.top;
3547      },
3548
3549      'left': function(element) {
3550        var offset = element.positionedOffset();
3551        return offset.left;
3552      },
3553
3554      'right': function(element) {
3555        var offset = element.positionedOffset(),
3556         parent = element.getOffsetParent(),
3557         pWidth = parent.measure('width');
3558
3559        var mWidth = this.get('border-box-width');
3560
3561        return pWidth - mWidth - offset.left;
3562      },
3563
3564      'padding-top': function(element) {
3565        return getPixelValue(element, 'paddingTop');
3566      },
3567
3568      'padding-bottom': function(element) {
3569        return getPixelValue(element, 'paddingBottom');
3570      },
3571
3572      'padding-left': function(element) {
3573        return getPixelValue(element, 'paddingLeft');
3574      },
3575
3576      'padding-right': function(element) {
3577        return getPixelValue(element, 'paddingRight');
3578      },
3579
3580      'border-top': function(element) {
3581        return getPixelValue(element, 'borderTopWidth');
3582      },
3583
3584      'border-bottom': function(element) {
3585        return getPixelValue(element, 'borderBottomWidth');
3586      },
3587
3588      'border-left': function(element) {
3589        return getPixelValue(element, 'borderLeftWidth');
3590      },
3591
3592      'border-right': function(element) {
3593        return getPixelValue(element, 'borderRightWidth');
3594      },
3595
3596      'margin-top': function(element) {
3597        return getPixelValue(element, 'marginTop');
3598      },
3599
3600      'margin-bottom': function(element) {
3601        return getPixelValue(element, 'marginBottom');
3602      },
3603
3604      'margin-left': function(element) {
3605        return getPixelValue(element, 'marginLeft');
3606      },
3607
3608      'margin-right': function(element) {
3609        return getPixelValue(element, 'marginRight');
3610      }
3611    }
3612  });
3613
3614  if ('getBoundingClientRect' in document.documentElement) {
3615    Object.extend(Element.Layout.COMPUTATIONS, {
3616      'right': function(element) {
3617        var parent = hasLayout(element.getOffsetParent());
3618        var rect = element.getBoundingClientRect(),
3619         pRect = parent.getBoundingClientRect();
3620
3621        return (pRect.right - rect.right).round();
3622      },
3623
3624      'bottom': function(element) {
3625        var parent = hasLayout(element.getOffsetParent());
3626        var rect = element.getBoundingClientRect(),
3627         pRect = parent.getBoundingClientRect();
3628
3629        return (pRect.bottom - rect.bottom).round();
3630      }
3631    });
3632  }
3633
3634  Element.Offset = Class.create({
3635    initialize: function(left, top) {
3636      this.left = left.round();
3637      this.top  = top.round();
3638
3639      this[0] = this.left;
3640      this[1] = this.top;
3641    },
3642
3643    relativeTo: function(offset) {
3644      return new Element.Offset(
3645        this.left - offset.left,
3646        this.top  - offset.top
3647      );
3648    },
3649
3650    inspect: function() {
3651      return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
3652    },
3653
3654    toString: function() {
3655      return "[#{left}, #{top}]".interpolate(this);
3656    },
3657
3658    toArray: function() {
3659      return [this.left, this.top];
3660    }
3661  });
3662
3663  function getLayout(element, preCompute) {
3664    return new Element.Layout(element, preCompute);
3665  }
3666
3667  function measure(element, property) {
3668    return $(element).getLayout().get(property);
3669  }
3670
3671  function getDimensions(element) {
3672    element = $(element);
3673    var display = Element.getStyle(element, 'display');
3674
3675    if (display && display !== 'none') {
3676      return { width: element.offsetWidth, height: element.offsetHeight };
3677    }
3678
3679    var style = element.style;
3680    var originalStyles = {
3681      visibility: style.visibility,
3682      position:   style.position,
3683      display:    style.display
3684    };
3685
3686    var newStyles = {
3687      visibility: 'hidden',
3688      display:    'block'
3689    };
3690
3691    if (originalStyles.position !== 'fixed')
3692      newStyles.position = 'absolute';
3693
3694    Element.setStyle(element, newStyles);
3695
3696    var dimensions = {
3697      width:  element.offsetWidth,
3698      height: element.offsetHeight
3699    };
3700
3701    Element.setStyle(element, originalStyles);
3702
3703    return dimensions;
3704  }
3705
3706  function getOffsetParent(element) {
3707    element = $(element);
3708
3709    if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
3710      return $(document.body);
3711
3712    var isInline = (Element.getStyle(element, 'display') === 'inline');
3713    if (!isInline && element.offsetParent) return $(element.offsetParent);
3714
3715    while ((element = element.parentNode) && element !== document.body) {
3716      if (Element.getStyle(element, 'position') !== 'static') {
3717        return isHtml(element) ? $(document.body) : $(element);
3718      }
3719    }
3720
3721    return $(document.body);
3722  }
3723
3724
3725  function cumulativeOffset(element) {
3726    element = $(element);
3727    var valueT = 0, valueL = 0;
3728    if (element.parentNode) {
3729      do {
3730        valueT += element.offsetTop  || 0;
3731        valueL += element.offsetLeft || 0;
3732        element = element.offsetParent;
3733      } while (element);
3734    }
3735    return new Element.Offset(valueL, valueT);
3736  }
3737
3738  function positionedOffset(element) {
3739    element = $(element);
3740
3741    var layout = element.getLayout();
3742
3743    var valueT = 0, valueL = 0;
3744    do {
3745      valueT += element.offsetTop  || 0;
3746      valueL += element.offsetLeft || 0;
3747      element = element.offsetParent;
3748      if (element) {
3749        if (isBody(element)) break;
3750        var p = Element.getStyle(element, 'position');
3751        if (p !== 'static') break;
3752      }
3753    } while (element);
3754
3755    valueL -= layout.get('margin-top');
3756    valueT -= layout.get('margin-left');
3757
3758    return new Element.Offset(valueL, valueT);
3759  }
3760
3761  function cumulativeScrollOffset(element) {
3762    var valueT = 0, valueL = 0;
3763    do {
3764      valueT += element.scrollTop  || 0;
3765      valueL += element.scrollLeft || 0;
3766      element = element.parentNode;
3767    } while (element);
3768    return new Element.Offset(valueL, valueT);
3769  }
3770
3771  function viewportOffset(forElement) {
3772    element = $(element);
3773    var valueT = 0, valueL = 0, docBody = document.body;
3774
3775    var element = forElement;
3776    do {
3777      valueT += element.offsetTop  || 0;
3778      valueL += element.offsetLeft || 0;
3779      if (element.offsetParent == docBody &&
3780        Element.getStyle(element, 'position') == 'absolute') break;
3781    } while (element = element.offsetParent);
3782
3783    element = forElement;
3784    do {
3785      if (element != docBody) {
3786        valueT -= element.scrollTop  || 0;
3787        valueL -= element.scrollLeft || 0;
3788      }
3789    } while (element = element.parentNode);
3790    return new Element.Offset(valueL, valueT);
3791  }
3792
3793  function absolutize(element) {
3794    element = $(element);
3795
3796    if (Element.getStyle(element, 'position') === 'absolute') {
3797      return element;
3798    }
3799
3800    var offsetParent = getOffsetParent(element);
3801    var eOffset = element.viewportOffset(),
3802     pOffset = offsetParent.viewportOffset();
3803
3804    var offset = eOffset.relativeTo(pOffset);
3805    var layout = element.getLayout();
3806
3807    element.store('prototype_absolutize_original_styles', {
3808      left:   element.getStyle('left'),
3809      top:    element.getStyle('top'),
3810      width:  element.getStyle('width'),
3811      height: element.getStyle('height')
3812    });
3813
3814    element.setStyle({
3815      position: 'absolute',
3816      top:    offset.top + 'px',
3817      left:   offset.left + 'px',
3818      width:  layout.get('width') + 'px',
3819      height: layout.get('height') + 'px'
3820    });
3821
3822    return element;
3823  }
3824
3825  function relativize(element) {
3826    element = $(element);
3827    if (Element.getStyle(element, 'position') === 'relative') {
3828      return element;
3829    }
3830
3831    var originalStyles =
3832     element.retrieve('prototype_absolutize_original_styles');
3833
3834    if (originalStyles) element.setStyle(originalStyles);
3835    return element;
3836  }
3837
3838  if (Prototype.Browser.IE) {
3839    getOffsetParent = getOffsetParent.wrap(
3840      function(proceed, element) {
3841        element = $(element);
3842
3843        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
3844          return $(document.body);
3845
3846        var position = element.getStyle('position');
3847        if (position !== 'static') return proceed(element);
3848
3849        element.setStyle({ position: 'relative' });
3850        var value = proceed(element);
3851        element.setStyle({ position: position });
3852        return value;
3853      }
3854    );
3855
3856    positionedOffset = positionedOffset.wrap(function(proceed, element) {
3857      element = $(element);
3858      if (!element.parentNode) return new Element.Offset(0, 0);
3859      var position = element.getStyle('position');
3860      if (position !== 'static') return proceed(element);
3861
3862      var offsetParent = element.getOffsetParent();
3863      if (offsetParent && offsetParent.getStyle('position') === 'fixed')
3864        hasLayout(offsetParent);
3865
3866      element.setStyle({ position: 'relative' });
3867      var value = proceed(element);
3868      element.setStyle({ position: position });
3869      return value;
3870    });
3871  } else if (Prototype.Browser.Webkit) {
3872    cumulativeOffset = function(element) {
3873      element = $(element);
3874      var valueT = 0, valueL = 0;
3875      do {
3876        valueT += element.offsetTop  || 0;
3877        valueL += element.offsetLeft || 0;
3878        if (element.offsetParent == document.body)
3879          if (Element.getStyle(element, 'position') == 'absolute') break;
3880
3881        element = element.offsetParent;
3882      } while (element);
3883
3884      return new Element.Offset(valueL, valueT);
3885    };
3886  }
3887
3888
3889  Element.addMethods({
3890    getLayout:              getLayout,
3891    measure:                measure,
3892    getDimensions:          getDimensions,
3893    getOffsetParent:        getOffsetParent,
3894    cumulativeOffset:       cumulativeOffset,
3895    positionedOffset:       positionedOffset,
3896    cumulativeScrollOffset: cumulativeScrollOffset,
3897    viewportOffset:         viewportOffset,
3898    absolutize:             absolutize,
3899    relativize:             relativize
3900  });
3901
3902  function isBody(element) {
3903    return element.nodeName.toUpperCase() === 'BODY';
3904  }
3905
3906  function isHtml(element) {
3907    return element.nodeName.toUpperCase() === 'HTML';
3908  }
3909
3910  function isDocument(element) {
3911    return element.nodeType === Node.DOCUMENT_NODE;
3912  }
3913
3914  function isDetached(element) {
3915    return element !== document.body &&
3916     !Element.descendantOf(element, document.body);
3917  }
3918
3919  if ('getBoundingClientRect' in document.documentElement) {
3920    Element.addMethods({
3921      viewportOffset: function(element) {
3922        element = $(element);
3923        if (isDetached(element)) return new Element.Offset(0, 0);
3924
3925        var rect = element.getBoundingClientRect(),
3926         docEl = document.documentElement;
3927        return new Element.Offset(rect.left - docEl.clientLeft,
3928         rect.top - docEl.clientTop);
3929      }
3930    });
3931  }
3932})();
3933window.$$ = function() {
3934  var expression = $A(arguments).join(', ');
3935  return Prototype.Selector.select(expression, document);
3936};
3937
3938Prototype.Selector = (function() {
3939
3940  function select() {
3941    throw new Error('Method "Prototype.Selector.select" must be defined.');
3942  }
3943
3944  function match() {
3945    throw new Error('Method "Prototype.Selector.match" must be defined.');
3946  }
3947
3948  function find(elements, expression, index) {
3949    index = index || 0;
3950    var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
3951
3952    for (i = 0; i < length; i++) {
3953      if (match(elements[i], expression) && index == matchIndex++) {
3954        return Element.extend(elements[i]);
3955      }
3956    }
3957  }
3958
3959  function extendElements(elements) {
3960    for (var i = 0, length = elements.length; i < length; i++) {
3961      Element.extend(elements[i]);
3962    }
3963    return elements;
3964  }
3965
3966
3967  var K = Prototype.K;
3968
3969  return {
3970    select: select,
3971    match: match,
3972    find: find,
3973    extendElements: (Element.extend === K) ? K : extendElements,
3974    extendElement: Element.extend
3975  };
3976})();
3977Prototype._original_property = window.Sizzle;
3978/*!
3979 * Sizzle CSS Selector Engine - v1.0
3980 *  Copyright 2009, The Dojo Foundation
3981 *  Released under the MIT, BSD, and GPL Licenses.
3982 *  More information: http://sizzlejs.com/
3983 */
3984(function(){
3985
3986var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3987	done = 0,
3988	toString = Object.prototype.toString,
3989	hasDuplicate = false,
3990	baseHasDuplicate = true;
3991
3992[0, 0].sort(function(){
3993	baseHasDuplicate = false;
vendor: 5,902 bytes, lines 3994-4250
3994	return 0;
3995});
3996
3997var Sizzle = function(selector, context, results, seed) {
3998	results = results || [];
3999	var origContext = context = context || document;
4000
4001	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
4002		return [];
4003	}
4004
4005	if ( !selector || typeof selector !== "string" ) {
4006		return results;
4007	}
4008
4009	var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
4010		soFar = selector;
4011
4012	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
4013		soFar = m[3];
4014
4015		parts.push( m[1] );
4016
4017		if ( m[2] ) {
4018			extra = m[3];
4019			break;
4020		}
4021	}
4022
4023	if ( parts.length > 1 && origPOS.exec( selector ) ) {
4024		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
4025			set = posProcess( parts[0] + parts[1], context );
4026		} else {
4027			set = Expr.relative[ parts[0] ] ?
4028				[ context ] :
4029				Sizzle( parts.shift(), context );
4030
4031			while ( parts.length ) {
4032				selector = parts.shift();
4033
4034				if ( Expr.relative[ selector ] )
4035					selector += parts.shift();
4036
4037				set = posProcess( selector, set );
4038			}
4039		}
4040	} else {
4041		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
4042				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
4043			var ret = Sizzle.find( parts.shift(), context, contextXML );
4044			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
4045		}
4046
4047		if ( context ) {
4048			var ret = seed ?
4049				{ expr: parts.pop(), set: makeArray(seed) } :
4050				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
4051			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
4052
4053			if ( parts.length > 0 ) {
4054				checkSet = makeArray(set);
4055			} else {
4056				prune = false;
4057			}
4058
4059			while ( parts.length ) {
4060				var cur = parts.pop(), pop = cur;
4061
4062				if ( !Expr.relative[ cur ] ) {
4063					cur = "";
4064				} else {
4065					pop = parts.pop();
4066				}
4067
4068				if ( pop == null ) {
4069					pop = context;
4070				}
4071
4072				Expr.relative[ cur ]( checkSet, pop, contextXML );
4073			}
4074		} else {
4075			checkSet = parts = [];
4076		}
4077	}
4078
4079	if ( !checkSet ) {
4080		checkSet = set;
4081	}
4082
4083	if ( !checkSet ) {
4084		throw "Syntax error, unrecognized expression: " + (cur || selector);
4085	}
4086
4087	if ( toString.call(checkSet) === "[object Array]" || checkSet instanceof Array) {
4088		if ( !prune ) {
4089			results.push.apply( results, checkSet );
4090		} else if ( context && context.nodeType === 1 ) {
4091			for ( var i = 0; checkSet[i] != null; i++ ) {
4092				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
4093					results.push( set[i] );
4094				}
4095			}
4096		} else {
4097			for ( var i = 0; checkSet[i] != null; i++ ) {
4098				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4099					results.push( set[i] );
4100				}
4101			}
4102		}
4103	} else {
4104		makeArray( checkSet, results );
4105	}
4106
4107	if ( extra ) {
4108		Sizzle( extra, origContext, results, seed );
4109		Sizzle.uniqueSort( results );
4110	}
4111
4112	return results;
4113};
4114
4115Sizzle.uniqueSort = function(results){
4116	if ( sortOrder ) {
4117		hasDuplicate = baseHasDuplicate;
4118		results.sort(sortOrder);
4119
4120		if ( hasDuplicate ) {
4121			for ( var i = 1; i < results.length; i++ ) {
4122				if ( results[i] === results[i-1] ) {
4123					results.splice(i--, 1);
4124				}
4125			}
4126		}
4127	}
4128
4129	return results;
4130};
4131
4132Sizzle.matches = function(expr, set){
4133	return Sizzle(expr, null, null, set);
4134};
4135
4136Sizzle.find = function(expr, context, isXML){
4137	var set, match;
4138
4139	if ( !expr ) {
4140		return [];
4141	}
4142
4143	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
4144		var type = Expr.order[i], match;
4145
4146		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4147			var left = match[1];
4148			match.splice(1,1);
4149
4150			if ( left.substr( left.length - 1 ) !== "\\" ) {
4151				match[1] = (match[1] || "").replace(/\\/g, "");
4152				set = Expr.find[ type ]( match, context, isXML );
4153				if ( set != null ) {
4154					expr = expr.replace( Expr.match[ type ], "" );
4155					break;
4156				}
4157			}
4158		}
4159	}
4160
4161	if ( !set ) {
4162		set = context.getElementsByTagName("*");
4163	}
4164
4165	return {set: set, expr: expr};
4166};
4167
4168Sizzle.filter = function(expr, set, inplace, not){
4169	var old = expr, result = [], curLoop = set, match, anyFound,
4170		isXMLFilter = set && set[0] && isXML(set[0]);
4171
4172	while ( expr && set.length ) {
4173		for ( var type in Expr.filter ) {
4174			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
4175				var filter = Expr.filter[ type ], found, item;
4176				anyFound = false;
4177
4178				if ( curLoop == result ) {
4179					result = [];
4180				}
4181
4182				if ( Expr.preFilter[ type ] ) {
4183					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4184
4185					if ( !match ) {
4186						anyFound = found = true;
4187					} else if ( match === true ) {
4188						continue;
4189					}
4190				}
4191
4192				if ( match ) {
4193					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
4194						if ( item ) {
4195							found = filter( item, match, i, curLoop );
4196							var pass = not ^ !!found;
4197
4198							if ( inplace && found != null ) {
4199								if ( pass ) {
4200									anyFound = true;
4201								} else {
4202									curLoop[i] = false;
4203								}
4204							} else if ( pass ) {
4205								result.push( item );
4206								anyFound = true;
4207							}
4208						}
4209					}
4210				}
4211
4212				if ( found !== undefined ) {
4213					if ( !inplace ) {
4214						curLoop = result;
4215					}
4216
4217					expr = expr.replace( Expr.match[ type ], "" );
4218
4219					if ( !anyFound ) {
4220						return [];
4221					}
4222
4223					break;
4224				}
4225			}
4226		}
4227
4228		if ( expr == old ) {
4229			if ( anyFound == null ) {
4230				throw "Syntax error, unrecognized expression: " + expr;
4231			} else {
4232				break;
4233			}
4234		}
4235
4236		old = expr;
4237	}
4238
4239	return curLoop;
4240};
4241
4242var Expr = Sizzle.selectors = {
4243	order: [ "ID", "NAME", "TAG" ],
4244	match: {
4245		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
4246		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
4247		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
4248		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
4249		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
4250		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
4251		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
4252		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
4253	},
4254	leftMatch: {},
4255	attrMap: {
4256		"class": "className",
4257		"for": "htmlFor"
4258	},
4259	attrHandle: {
4260		href: function(elem){
4261			return elem.getAttribute("href");
4262		}
4263	},
4264	relative: {
4265		"+": function(checkSet, part, isXML){
4266			var isPartStr = typeof part === "string",
4267				isTag = isPartStr && !/\W/.test(part),
4268				isPartStrNotTag = isPartStr && !isTag;
4269
4270			if ( isTag && !isXML ) {
4271				part = part.toUpperCase();
4272			}
4273
4274			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4275				if ( (elem = checkSet[i]) ) {
4276					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4277
4278					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
4279						elem || false :
4280						elem === part;
4281				}
4282			}
4283
4284			if ( isPartStrNotTag ) {
4285				Sizzle.filter( part, checkSet, true );
4286			}
4287		},
4288		">": function(checkSet, part, isXML){
4289			var isPartStr = typeof part === "string";
4290
4291			if ( isPartStr && !/\W/.test(part) ) {
4292				part = isXML ? part : part.toUpperCase();
4293
4294				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4295					var elem = checkSet[i];
4296					if ( elem ) {
4297						var parent = elem.parentNode;
4298						checkSet[i] = parent.nodeName === part ? parent : false;
4299					}
4300				}
4301			} else {
4302				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4303					var elem = checkSet[i];
4304					if ( elem ) {
4305						checkSet[i] = isPartStr ?
4306							elem.parentNode :
4307							elem.parentNode === part;
4308					}
4309				}
4310
4311				if ( isPartStr ) {
4312					Sizzle.filter( part, checkSet, true );
4313				}
4314			}
4315		},
4316		"": function(checkSet, part, isXML){
4317			var doneName = done++, checkFn = dirCheck;
4318
4319			if ( !/\W/.test(part) ) {
4320				var nodeCheck = part = isXML ? part : part.toUpperCase();
4321				checkFn = dirNodeCheck;
4322			}
4323
4324			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
4325		},
4326		"~": function(checkSet, part, isXML){
4327			var doneName = done++, checkFn = dirCheck;
4328
4329			if ( typeof part === "string" && !/\W/.test(part) ) {
4330				var nodeCheck = part = isXML ? part : part.toUpperCase();
4331				checkFn = dirNodeCheck;
4332			}
4333
4334			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
4335		}
4336	},
4337	find: {
4338		ID: function(match, context, isXML){
4339			if ( typeof context.getElementById !== "undefined" && !isXML ) {
4340				var m = context.getElementById(match[1]);
4341				return m ? [m] : [];
4342			}
4343		},
4344		NAME: function(match, context, isXML){
4345			if ( typeof context.getElementsByName !== "undefined" ) {
4346				var ret = [], results = context.getElementsByName(match[1]);
4347
4348				for ( var i = 0, l = results.length; i < l; i++ ) {
4349					if ( results[i].getAttribute("name") === match[1] ) {
4350						ret.push( results[i] );
4351					}
4352				}
4353
4354				return ret.length === 0 ? null : ret;
4355			}
4356		},
4357		TAG: function(match, context){
4358			return context.getElementsByTagName(match[1]);
4359		}
4360	},
4361	preFilter: {
4362		CLASS: function(match, curLoop, inplace, result, not, isXML){
4363			match = " " + match[1].replace(/\\/g, "") + " ";
4364
4365			if ( isXML ) {
4366				return match;
4367			}
4368
4369			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
4370				if ( elem ) {
4371					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
4372						if ( !inplace )
4373							result.push( elem );
4374					} else if ( inplace ) {
4375						curLoop[i] = false;
4376					}
4377				}
4378			}
4379
4380			return false;
4381		},
4382		ID: function(match){
4383			return match[1].replace(/\\/g, "");
4384		},
4385		TAG: function(match, curLoop){
4386			for ( var i = 0; curLoop[i] === false; i++ ){}
4387			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
4388		},
4389		CHILD: function(match){
4390			if ( match[1] == "nth" ) {
4391				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
4392					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
4393					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
4394
4395				match[2] = (test[1] + (test[2] || 1)) - 0;
4396				match[3] = test[3] - 0;
4397			}
4398
4399			match[0] = done++;
4400
4401			return match;
4402		},
4403		ATTR: function(match, curLoop, inplace, result, not, isXML){
4404			var name = match[1].replace(/\\/g, "");
4405
4406			if ( !isXML && Expr.attrMap[name] ) {
4407				match[1] = Expr.attrMap[name];
4408			}
4409
4410			if ( match[2] === "~=" ) {
4411				match[4] = " " + match[4] + " ";
4412			}
4413
4414			return match;
4415		},
4416		PSEUDO: function(match, curLoop, inplace, result, not){
vendor: 10,107 bytes, lines 4417-4827
4417			if ( match[1] === "not" ) {
4418				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
4419					match[3] = Sizzle(match[3], null, null, curLoop);
4420				} else {
4421					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
4422					if ( !inplace ) {
4423						result.push.apply( result, ret );
4424					}
4425					return false;
4426				}
4427			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
4428				return true;
4429			}
4430
4431			return match;
4432		},
4433		POS: function(match){
4434			match.unshift( true );
4435			return match;
4436		}
4437	},
4438	filters: {
4439		enabled: function(elem){
4440			return elem.disabled === false && elem.type !== "hidden";
4441		},
4442		disabled: function(elem){
4443			return elem.disabled === true;
4444		},
4445		checked: function(elem){
4446			return elem.checked === true;
4447		},
4448		selected: function(elem){
4449			elem.parentNode.selectedIndex;
4450			return elem.selected === true;
4451		},
4452		parent: function(elem){
4453			return !!elem.firstChild;
4454		},
4455		empty: function(elem){
4456			return !elem.firstChild;
4457		},
4458		has: function(elem, i, match){
4459			return !!Sizzle( match[3], elem ).length;
4460		},
4461		header: function(elem){
4462			return /h\d/i.test( elem.nodeName );
4463		},
4464		text: function(elem){
4465			return "text" === elem.type;
4466		},
4467		radio: function(elem){
4468			return "radio" === elem.type;
4469		},
4470		checkbox: function(elem){
4471			return "checkbox" === elem.type;
4472		},
4473		file: function(elem){
4474			return "file" === elem.type;
4475		},
4476		password: function(elem){
4477			return "password" === elem.type;
4478		},
4479		submit: function(elem){
4480			return "submit" === elem.type;
4481		},
4482		image: function(elem){
4483			return "image" === elem.type;
4484		},
4485		reset: function(elem){
4486			return "reset" === elem.type;
4487		},
4488		button: function(elem){
4489			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
4490		},
4491		input: function(elem){
4492			return /input|select|textarea|button/i.test(elem.nodeName);
4493		}
4494	},
4495	setFilters: {
4496		first: function(elem, i){
4497			return i === 0;
4498		},
4499		last: function(elem, i, match, array){
4500			return i === array.length - 1;
4501		},
4502		even: function(elem, i){
4503			return i % 2 === 0;
4504		},
4505		odd: function(elem, i){
4506			return i % 2 === 1;
4507		},
4508		lt: function(elem, i, match){
4509			return i < match[3] - 0;
4510		},
4511		gt: function(elem, i, match){
4512			return i > match[3] - 0;
4513		},
4514		nth: function(elem, i, match){
4515			return match[3] - 0 == i;
4516		},
4517		eq: function(elem, i, match){
4518			return match[3] - 0 == i;
4519		}
4520	},
4521	filter: {
4522		PSEUDO: function(elem, match, i, array){
4523			var name = match[1], filter = Expr.filters[ name ];
4524
4525			if ( filter ) {
4526				return filter( elem, i, match, array );
4527			} else if ( name === "contains" ) {
4528				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
4529			} else if ( name === "not" ) {
4530				var not = match[3];
4531
4532				for ( var i = 0, l = not.length; i < l; i++ ) {
4533					if ( not[i] === elem ) {
4534						return false;
4535					}
4536				}
4537
4538				return true;
4539			}
4540		},
4541		CHILD: function(elem, match){
4542			var type = match[1], node = elem;
4543			switch (type) {
4544				case 'only':
4545				case 'first':
4546					while ( (node = node.previousSibling) )  {
4547						if ( node.nodeType === 1 ) return false;
4548					}
4549					if ( type == 'first') return true;
4550					node = elem;
4551				case 'last':
4552					while ( (node = node.nextSibling) )  {
4553						if ( node.nodeType === 1 ) return false;
4554					}
4555					return true;
4556				case 'nth':
4557					var first = match[2], last = match[3];
4558
4559					if ( first == 1 && last == 0 ) {
4560						return true;
4561					}
4562
4563					var doneName = match[0],
4564						parent = elem.parentNode;
4565
4566					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
4567						var count = 0;
4568						for ( node = parent.firstChild; node; node = node.nextSibling ) {
4569							if ( node.nodeType === 1 ) {
4570								node.nodeIndex = ++count;
4571							}
4572						}
4573						parent.sizcache = doneName;
4574					}
4575
4576					var diff = elem.nodeIndex - last;
4577					if ( first == 0 ) {
4578						return diff == 0;
4579					} else {
4580						return ( diff % first == 0 && diff / first >= 0 );
4581					}
4582			}
4583		},
4584		ID: function(elem, match){
4585			return elem.nodeType === 1 && elem.getAttribute("id") === match;
4586		},
4587		TAG: function(elem, match){
4588			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
4589		},
4590		CLASS: function(elem, match){
4591			return (" " + (elem.className || elem.getAttribute("class")) + " ")
4592				.indexOf( match ) > -1;
4593		},
4594		ATTR: function(elem, match){
4595			var name = match[1],
4596				result = Expr.attrHandle[ name ] ?
4597					Expr.attrHandle[ name ]( elem ) :
4598					elem[ name ] != null ?
4599						elem[ name ] :
4600						elem.getAttribute( name ),
4601				value = result + "",
4602				type = match[2],
4603				check = match[4];
4604
4605			return result == null ?
4606				type === "!=" :
4607				type === "=" ?
4608				value === check :
4609				type === "*=" ?
4610				value.indexOf(check) >= 0 :
4611				type === "~=" ?
4612				(" " + value + " ").indexOf(check) >= 0 :
4613				!check ?
4614				value && result !== false :
4615				type === "!=" ?
4616				value != check :
4617				type === "^=" ?
4618				value.indexOf(check) === 0 :
4619				type === "$=" ?
4620				value.substr(value.length - check.length) === check :
4621				type === "|=" ?
4622				value === check || value.substr(0, check.length + 1) === check + "-" :
4623				false;
4624		},
4625		POS: function(elem, match, i, array){
4626			var name = match[2], filter = Expr.setFilters[ name ];
4627
4628			if ( filter ) {
4629				return filter( elem, i, match, array );
4630			}
4631		}
4632	}
4633};
4634
4635var origPOS = Expr.match.POS;
4636
4637for ( var type in Expr.match ) {
4638	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
4639	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
4640}
4641
4642var makeArray = function(array, results) {
4643	array = Array.prototype.slice.call( array, 0 );
4644
4645	if ( results ) {
4646		results.push.apply( results, array );
4647		return results;
4648	}
4649
4650	return array;
4651};
4652
4653try {
4654	Array.prototype.slice.call( document.documentElement.childNodes, 0 );
4655
4656} catch(e){
4657	makeArray = function(array, results) {
4658		var ret = results || [];
4659
4660		if ( toString.call(array) === "[object Array]" || array instanceof Array ) {
4661			Array.prototype.push.apply( ret, array );
4662		} else {
4663			if ( typeof array.length === "number" ) {
4664				for ( var i = 0, l = array.length; i < l; i++ ) {
4665					ret.push( array[i] );
4666				}
4667			} else {
4668				for ( var i = 0; array[i]; i++ ) {
4669					ret.push( array[i] );
4670				}
4671			}
4672		}
4673
4674		return ret;
4675	};
4676}
4677
4678var sortOrder;
4679
4680if ( document.documentElement.compareDocumentPosition ) {
4681	sortOrder = function( a, b ) {
4682		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
4683			if ( a == b ) {
4684				hasDuplicate = true;
4685			}
4686			return 0;
4687		}
4688
4689		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
4690		if ( ret === 0 ) {
4691			hasDuplicate = true;
4692		}
4693		return ret;
4694	};
4695} else if ( "sourceIndex" in document.documentElement ) {
4696	sortOrder = function( a, b ) {
4697		if ( !a.sourceIndex || !b.sourceIndex ) {
4698			if ( a == b ) {
4699				hasDuplicate = true;
4700			}
4701			return 0;
4702		}
4703
4704		var ret = a.sourceIndex - b.sourceIndex;
4705		if ( ret === 0 ) {
4706			hasDuplicate = true;
4707		}
4708		return ret;
4709	};
4710} else if ( document.createRange ) {
4711	sortOrder = function( a, b ) {
4712		if ( !a.ownerDocument || !b.ownerDocument ) {
4713			if ( a == b ) {
4714				hasDuplicate = true;
4715			}
4716			return 0;
4717		}
4718
4719		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
4720		aRange.setStart(a, 0);
4721		aRange.setEnd(a, 0);
4722		bRange.setStart(b, 0);
4723		bRange.setEnd(b, 0);
4724		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
4725		if ( ret === 0 ) {
4726			hasDuplicate = true;
4727		}
4728		return ret;
4729	};
4730}
4731
4732(function(){
4733	var form = document.createElement("div"),
4734		id = "script" + (new Date).getTime();
4735	form.innerHTML = "<a name='" + id + "'/>";
4736
4737	var root = document.documentElement;
4738	root.insertBefore( form, root.firstChild );
4739
4740	if ( !!document.getElementById( id ) ) {
4741		Expr.find.ID = function(match, context, isXML){
4742			if ( typeof context.getElementById !== "undefined" && !isXML ) {
4743				var m = context.getElementById(match[1]);
4744				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
4745			}
4746		};
4747
4748		Expr.filter.ID = function(elem, match){
4749			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4750			return elem.nodeType === 1 && node && node.nodeValue === match;
4751		};
4752	}
4753
4754	root.removeChild( form );
4755	root = form = null; // release memory in IE
4756})();
4757
4758(function(){
4759
4760	var div = document.createElement("div");
4761	div.appendChild( document.createComment("") );
4762
4763	if ( div.getElementsByTagName("*").length > 0 ) {
4764		Expr.find.TAG = function(match, context){
4765			var results = context.getElementsByTagName(match[1]);
4766
4767			if ( match[1] === "*" ) {
4768				var tmp = [];
4769
4770				for ( var i = 0; results[i]; i++ ) {
4771					if ( results[i].nodeType === 1 ) {
4772						tmp.push( results[i] );
4773					}
4774				}
4775
4776				results = tmp;
4777			}
4778
4779			return results;
4780		};
4781	}
4782
4783	div.innerHTML = "<a href='#'></a>";
4784	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
4785			div.firstChild.getAttribute("href") !== "#" ) {
4786		Expr.attrHandle.href = function(elem){
4787			return elem.getAttribute("href", 2);
4788		};
4789	}
4790
4791	div = null; // release memory in IE
4792})();
4793
4794if ( document.querySelectorAll ) (function(){
4795	var oldSizzle = Sizzle, div = document.createElement("div");
4796	div.innerHTML = "<p class='TEST'></p>";
4797
4798	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
4799		return;
4800	}
4801
4802	Sizzle = function(query, context, extra, seed){
4803		context = context || document;
4804
4805		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
4806			try {
4807				return makeArray( context.querySelectorAll(query), extra );
4808			} catch(e){}
4809		}
4810
4811		return oldSizzle(query, context, extra, seed);
4812	};
4813
4814	for ( var prop in oldSizzle ) {
4815		Sizzle[ prop ] = oldSizzle[ prop ];
4816	}
4817
4818	div = null; // release memory in IE
4819})();
4820
4821if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
4822	var div = document.createElement("div");
4823	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
4824
4825	if ( div.getElementsByClassName("e").length === 0 )
4826		return;
4827
4828	div.lastChild.className = "e";
4829
4830	if ( div.getElementsByClassName("e").length === 1 )
4831		return;
4832
4833	Expr.order.splice(1, 0, "CLASS");
4834	Expr.find.CLASS = function(match, context, isXML) {
4835		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
4836			return context.getElementsByClassName(match[1]);
4837		}
4838	};
4839
4840	div = null; // release memory in IE
4841})();
4842
4843function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4844	var sibDir = dir == "previousSibling" && !isXML;
4845	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4846		var elem = checkSet[i];
4847		if ( elem ) {
4848			if ( sibDir && elem.nodeType === 1 ){
4849				elem.sizcache = doneName;
4850				elem.sizset = i;
4851			}
4852			elem = elem[dir];
4853			var match = false;
4854
4855			while ( elem ) {
4856				if ( elem.sizcache === doneName ) {
4857					match = checkSet[elem.sizset];
4858					break;
4859				}
4860
4861				if ( elem.nodeType === 1 && !isXML ){
4862					elem.sizcache = doneName;
4863					elem.sizset = i;
4864				}
4865
4866				if ( elem.nodeName === cur ) {
4867					match = elem;
4868					break;
4869				}
4870
4871				elem = elem[dir];
4872			}
4873
4874			checkSet[i] = match;
4875		}
4876	}
4877}
4878
4879function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4880	var sibDir = dir == "previousSibling" && !isXML;
4881	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4882		var elem = checkSet[i];
4883		if ( elem ) {
4884			if ( sibDir && elem.nodeType === 1 ) {
4885				elem.sizcache = doneName;
4886				elem.sizset = i;
4887			}
4888			elem = elem[dir];
4889			var match = false;
4890
4891			while ( elem ) {
4892				if ( elem.sizcache === doneName ) {
4893					match = checkSet[elem.sizset];
4894					break;
4895				}
4896
4897				if ( elem.nodeType === 1 ) {
4898					if ( !isXML ) {
4899						elem.sizcache = doneName;
4900						elem.sizset = i;
4901					}
4902					if ( typeof cur !== "string" ) {
4903						if ( elem === cur ) {
4904							match = true;
4905							break;
4906						}
4907
4908					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
4909						match = elem;
4910						break;
4911					}
4912				}
4913
4914				elem = elem[dir];
4915			}
4916
4917			checkSet[i] = match;
4918		}
4919	}
4920}
4921
4922var contains = document.compareDocumentPosition ?  function(a, b){
4923	return a.compareDocumentPosition(b) & 16;
4924} : function(a, b){
4925	return a !== b && (a.contains ? a.contains(b) : true);
4926};
4927
4928var isXML = function(elem){
4929	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
4930		!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
4931};
4932
4933var posProcess = function(selector, context){
4934	var tmpSet = [], later = "", match,
4935		root = context.nodeType ? [context] : context;
4936
4937	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
4938		later += match[0];
4939		selector = selector.replace( Expr.match.PSEUDO, "" );
4940	}
4941
4942	selector = Expr.relative[selector] ? selector + "*" : selector;
4943
4944	for ( var i = 0, l = root.length; i < l; i++ ) {
4945		Sizzle( selector, root[i], tmpSet );
4946	}
4947
4948	return Sizzle.filter( later, tmpSet );
4949};
4950
4951
4952window.Sizzle = Sizzle;
4953
4954})();
4955
4956;(function(engine) {
4957  var extendElements = Prototype.Selector.extendElements;
4958
4959  function select(selector, scope) {
4960    return extendElements(engine(selector, scope || document));
4961  }
4962
4963  function match(element, selector) {
4964    return engine.matches(selector, [element]).length == 1;
4965  }
4966
4967  Prototype.Selector.engine = engine;
4968  Prototype.Selector.select = select;
4969  Prototype.Selector.match = match;
4970})(Sizzle);
4971
4972window.Sizzle = Prototype._original_property;
4973delete Prototype._original_property;
4974
4975var Form = {
4976  reset: function(form) {
4977    form = $(form);
4978    form.reset();
4979    return form;
4980  },
4981
4982  serializeElements: function(elements, options) {
4983    if (typeof options != 'object') options = { hash: !!options };
4984    else if (Object.isUndefined(options.hash)) options.hash = true;
4985    var key, value, submitted = false, submit = options.submit, accumulator, initial;
4986
4987    if (options.hash) {
4988      initial = {};
4989      accumulator = function(result, key, value) {
4990        if (key in result) {
4991          if (!Object.isArray(result[key])) result[key] = [result[key]];
4992          result[key].push(value);
4993        } else result[key] = value;
4994        return result;
4995      };
4996    } else {
4997      initial = '';
4998      accumulator = function(result, key, value) {
4999        return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value);
5000      }
5001    }
5002
5003    return elements.inject(initial, function(result, element) {
5004      if (!element.disabled && element.name) {
5005        key = element.name; value = $(element).getValue();
5006        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
5007            submit !== false && (!submit || key == submit) && (submitted = true)))) {
5008          result = accumulator(result, key, value);
5009        }
5010      }
5011      return result;
5012    });
5013  },
5014
5015  // Begin modified by Zoey
5016  elementsToFormData: function(elements, options) {
5017    if (typeof options != 'object') options = {};
5018    // else if (Object.isUndefined(options.hash)) options.hash = true;
5019    var key, value, submitted = false, submit = options.submit, accumulator, initial;
5020
5021    initial = new FormData();
5022    accumulator = function(result, key, value) {
5023      if (key.substring(key.length-2) === '[]') {
5024        result.append(key, value);
5025      } else {
5026        result.set(key, value);
5027      }
5028      return result;
5029    };
5030
5031    return elements.inject(initial, function(result, element) {
5032      if (!element.disabled && element.name) {
5033        key = element.name;
5034        value = element.type !== 'file' ? $(element).getValue() : ((element.files && element.files[0]) || null);
5035        if (value != null && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) {
5036          result = accumulator(result, key, value);
5037        }
5038      }
5039      return result;
5040    });
5041  }
5042  // End modified by Zoey
5043};
5044
5045Form.Methods = {
5046  serialize: function(form, options) {
5047    return Form.serializeElements(Form.getElements(form), options);
5048  },
5049
5050  // Begin modified by Zoey
5051  toFormData: function(form, options) {
5052    return Form.elementsToFormData(Form.getElements(form), options);
5053  },
5054  // End modified by Zoey
5055
5056  getElements: function(form) {
5057    var elements = $(form).getElementsByTagName('*'),
5058        element,
5059        arr = [ ],
5060        serializers = Form.Element.Serializers;
5061    for (var i = 0; element = elements[i]; i++) {
5062      arr.push(element);
5063    }
5064    return arr.inject([], function(elements, child) {
5065      if (serializers[child.tagName.toLowerCase()])
5066        elements.push(Element.extend(child));
5067      return elements;
5068    })
5069  },
5070
5071  getInputs: function(form, typeName, name) {
5072    form = $(form);
5073    var inputs = form.getElementsByTagName('input');
5074
5075    if (!typeName && !name) return $A(inputs).map(Element.extend);
5076
5077    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
5078      var input = inputs[i];
5079      if ((typeName && input.type != typeName) || (name && input.name != name))
5080        continue;
5081      matchingInputs.push(Element.extend(input));
5082    }
5083
5084    return matchingInputs;
5085  },
5086
5087  disable: function(form) {
5088    form = $(form);
5089    Form.getElements(form).invoke('disable');
5090    return form;
5091  },
5092
5093  enable: function(form) {
5094    form = $(form);
5095    Form.getElements(form).invoke('enable');
5096    return form;
5097  },
5098
5099  findFirstElement: function(form) {
5100    var elements = $(form).getElements().findAll(function(element) {
5101      return 'hidden' != element.type && !element.disabled;
5102    });
5103    var firstByIndex = elements.findAll(function(element) {
5104      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
5105    }).sortBy(function(element) { return element.tabIndex }).first();
5106
5107    return firstByIndex ? firstByIndex : elements.find(function(element) {
5108      return /^(?:input|select|textarea)$/i.test(element.tagName);
5109    });
5110  },
5111
5112  focusFirstElement: function(form) {
5113    form = $(form);
5114    var element = form.findFirstElement();
5115    if (element) element.activate();
5116    return form;
5117  },
5118
5119  request: function(form, options) {
5120    form = $(form), options = Object.clone(options || { });
5121
5122    var params = options.parameters, action = form.readAttribute('action') || '';
5123    if (action.blank()) action = window.location.href;
5124    options.parameters = form.serialize(true);
5125
5126    if (params) {
5127      if (Object.isString(params)) params = params.toQueryParams();
5128      Object.extend(options.parameters, params);
5129    }
5130
5131    if (form.hasAttribute('method') && !options.method)
5132      options.method = form.method;
5133
5134    return new Ajax.Request(action, options);
5135  }
5136};
5137
5138/*--------------------------------------------------------------------------*/
5139
5140
5141Form.Element = {
5142  focus: function(element) {
5143    $(element).focus();
5144    return element;
5145  },
5146
5147  select: function(element) {
5148    $(element).select();
5149    return element;
5150  }
5151};
5152
5153Form.Element.Methods = {
5154
5155  serialize: function(element) {
5156    element = $(element);
5157    if (!element.disabled && element.name) {
5158      var value = element.getValue();
5159      if (value != undefined) {
5160        var pair = { };
5161        pair[element.name] = value;
5162        return Object.toQueryString(pair);
5163      }
5164    }
5165    return '';
5166  },
5167
5168  getValue: function(element) {
5169    element = $(element);
5170    var method = element.tagName.toLowerCase();
5171    return Form.Element.Serializers[method](element);
5172  },
5173
5174  setValue: function(element, value) {
5175    element = $(element);
5176    var method = element.tagName.toLowerCase();
5177    Form.Element.Serializers[method](element, value);
5178    return element;
5179  },
5180
5181  clear: function(element) {
5182    $(element).value = '';
5183    return element;
5184  },
5185
5186  present: function(element) {
5187    return $(element).value != '';
5188  },
5189
5190  activate: function(element) {
5191    element = $(element);
5192    try {
5193      element.focus();
5194      if (element.select && (element.tagName.toLowerCase() != 'input' ||
5195          !(/^(?:button|reset|submit)$/i.test(element.type))))
5196        element.select();
5197    } catch (e) { }
5198    return element;
5199  },
5200
5201  disable: function(element) {
5202    element = $(element);
5203    element.disabled = true;
5204    return element;
5205  },
5206
5207  enable: function(element) {
5208    element = $(element);
5209    element.disabled = false;
5210    return element;
5211  }
5212};
5213
5214/*--------------------------------------------------------------------------*/
5215
5216var Field = Form.Element;
5217
5218var $F = Form.Element.Methods.getValue;
5219
5220/*--------------------------------------------------------------------------*/
5221
5222Form.Element.Serializers = (function() {
5223  function input(element, value) {
5224    switch (element.type.toLowerCase()) {
5225      case 'checkbox':
5226      case 'radio':
5227        return inputSelector(element, value);
5228      default:
5229        return valueSelector(element, value);
5230    }
5231  }
5232
5233  function inputSelector(element, value) {
5234    if (Object.isUndefined(value))
5235      return element.checked ? element.value : null;
5236    else element.checked = !!value;
5237  }
5238
5239  function valueSelector(element, value) {
5240    if (Object.isUndefined(value)) return element.value;
5241    else element.value = value;
5242  }
5243
5244  function select(element, value) {
5245    if (Object.isUndefined(value))
5246      return (element.type === 'select-one' ? selectOne : selectMany)(element);
5247
5248    var opt, currentValue, single = !Object.isArray(value);
5249    for (var i = 0, length = element.length; i < length; i++) {
5250      opt = element.options[i];
5251      currentValue = this.optionValue(opt);
5252      if (single) {
5253        if (currentValue == value) {
5254          opt.selected = true;
5255          return;
5256        }
5257      }
5258      else opt.selected = value.include(currentValue);
5259    }
5260  }
5261
5262  function selectOne(element) {
5263    var index = element.selectedIndex;
5264    return index >= 0 ? optionValue(element.options[index]) : null;
5265  }
5266
5267  function selectMany(element) {
5268    var values, length = element.length;
5269    if (!length) return null;
5270
5271    for (var i = 0, values = []; i < length; i++) {
5272      var opt = element.options[i];
5273      if (opt.selected) values.push(optionValue(opt));
5274    }
5275    return values;
5276  }
5277
5278  function optionValue(opt) {
5279    return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
5280  }
5281
5282  return {
5283    input:         input,
5284    inputSelector: inputSelector,
5285    textarea:      valueSelector,
5286    select:        select,
5287    selectOne:     selectOne,
5288    selectMany:    selectMany,
5289    optionValue:   optionValue,
5290    button:        valueSelector
5291  };
5292})();
5293
5294/*--------------------------------------------------------------------------*/
5295
5296
5297Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
5298  initialize: function($super, element, frequency, callback) {
5299    $super(callback, frequency);
5300    this.element   = $(element);
5301    this.lastValue = this.getValue();
5302  },
5303
5304  execute: function() {
5305    var value = this.getValue();
5306    if (Object.isString(this.lastValue) && Object.isString(value) ?
5307        this.lastValue != value : String(this.lastValue) != String(value)) {
5308      this.callback(this.element, value);
5309      this.lastValue = value;
5310    }
5311  }
5312});
5313
5314Form.Element.Observer = Class.create(Abstract.TimedObserver, {
5315  getValue: function() {
5316    return Form.Element.getValue(this.element);
5317  }
5318});
5319
5320Form.Observer = Class.create(Abstract.TimedObserver, {
5321  getValue: function() {
5322    return Form.serialize(this.element);
5323  }
5324});
5325
5326/*--------------------------------------------------------------------------*/
5327
5328Abstract.EventObserver = Class.create({
5329  initialize: function(element, callback) {
5330    this.element  = $(element);
5331    this.callback = callback;
5332
5333    this.lastValue = this.getValue();
5334    if (this.element.tagName.toLowerCase() == 'form')
5335      this.registerFormCallbacks();
5336    else
5337      this.registerCallback(this.element);
5338  },
5339
5340  onElementEvent: function() {
5341    var value = this.getValue();
5342    if (this.lastValue != value) {
5343      this.callback(this.element, value);
5344      this.lastValue = value;
5345    }
5346  },
5347
5348  registerFormCallbacks: function() {
5349    Form.getElements(this.element).each(this.registerCallback, this);
5350  },
5351
5352  registerCallback: function(element) {
5353    if (element.type) {
5354      switch (element.type.toLowerCase()) {
5355        case 'checkbox':
5356        case 'radio':
5357          Event.observe(element, 'click', this.onElementEvent.bind(this));
5358          break;
5359        default:
5360          Event.observe(element, 'change', this.onElementEvent.bind(this));
5361          break;
5362      }
5363    }
5364  }
5365});
5366
5367Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
5368  getValue: function() {
5369    return Form.Element.getValue(this.element);
5370  }
5371});
5372
5373Form.EventObserver = Class.create(Abstract.EventObserver, {
5374  getValue: function() {
5375    return Form.serialize(this.element);
5376  }
5377});
5378(function() {
5379
5380  var Event = {
5381    KEY_BACKSPACE: 8,
5382    KEY_TAB:       9,
5383    KEY_RETURN:   13,
5384    KEY_ESC:      27,
5385    KEY_LEFT:     37,
5386    KEY_UP:       38,
5387    KEY_RIGHT:    39,
5388    KEY_DOWN:     40,
5389    KEY_DELETE:   46,
5390    KEY_HOME:     36,
5391    KEY_END:      35,
5392    KEY_PAGEUP:   33,
5393    KEY_PAGEDOWN: 34,
5394    KEY_INSERT:   45,
5395
5396    cache: {}
5397  };
5398
5399  var docEl = document.documentElement;
5400  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
5401    && 'onmouseleave' in docEl;
5402
5403
5404
5405  var isIELegacyEvent = function(event) { return false; };
5406
5407  if (window.attachEvent) {
5408    if (window.addEventListener) {
5409      isIELegacyEvent = function(event) {
5410        return !(event instanceof window.Event);
5411      };
5412    } else {
5413      isIELegacyEvent = function(event) { return true; };
5414    }
5415  }
5416
5417  var _isButton;
5418
5419  function _isButtonForDOMEvents(event, code) {
5420    return event.which ? (event.which === code + 1) : (event.button === code);
5421  }
5422
5423  var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
5424  function _isButtonForLegacyEvents(event, code) {
5425    return event.button === legacyButtonMap[code];
5426  }
5427
5428  function _isButtonForWebKit(event, code) {
5429    switch (code) {
5430      case 0: return event.which == 1 && !event.metaKey;
5431      case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
5432      case 2: return event.which == 3;
5433      default: return false;
5434    }
5435  }
5436
5437  if (window.attachEvent) {
5438    if (!window.addEventListener) {
5439      _isButton = _isButtonForLegacyEvents;
5440    } else {
5441      _isButton = function(event, code) {
5442        return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
5443         _isButtonForDOMEvents(event, code);
5444      }
5445    }
5446  } else if (Prototype.Browser.WebKit) {
5447    _isButton = _isButtonForWebKit;
5448  } else {
5449    _isButton = _isButtonForDOMEvents;
5450  }
5451
5452  function isLeftClick(event)   { return _isButton(event, 0) }
5453
5454  function isMiddleClick(event) { return _isButton(event, 1) }
5455
5456  function isRightClick(event)  { return _isButton(event, 2) }
5457
5458  function element(event) {
5459    event = Event.extend(event);
5460
5461    var node = event.target, type = event.type,
5462     currentTarget = event.currentTarget;
5463
5464    if (currentTarget && currentTarget.tagName) {
5465      if (type === 'load' || type === 'error' ||
5466        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
5467          && currentTarget.type === 'radio'))
5468            node = currentTarget;
5469    }
5470
5471    if (node.nodeType == Node.TEXT_NODE)
5472      node = node.parentNode;
5473
5474    return Element.extend(node);
5475  }
5476
5477  function findElement(event, expression) {
5478    var element = Event.element(event);
5479
5480    if (!expression) return element;
5481    while (element) {
5482      if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
5483        return Element.extend(element);
5484      }
5485      element = element.parentNode;
5486    }
5487  }
5488
5489  function pointer(event) {
5490    return { x: pointerX(event), y: pointerY(event) };
5491  }
5492
5493  function pointerX(event) {
5494    var docElement = document.documentElement,
5495     body = document.body || { scrollLeft: 0 };
5496
5497    return event.pageX || (event.clientX +
5498      (docElement.scrollLeft || body.scrollLeft) -
5499      (docElement.clientLeft || 0));
5500  }
5501
5502  function pointerY(event) {
5503    var docElement = document.documentElement,
5504     body = document.body || { scrollTop: 0 };
5505
5506    return  event.pageY || (event.clientY +
5507       (docElement.scrollTop || body.scrollTop) -
5508       (docElement.clientTop || 0));
5509  }
5510
5511
5512  function stop(event) {
5513    Event.extend(event);
5514    event.preventDefault();
5515    event.stopPropagation();
5516
5517    event.stopped = true;
5518  }
5519
5520
5521  Event.Methods = {
5522    isLeftClick:   isLeftClick,
5523    isMiddleClick: isMiddleClick,
5524    isRightClick:  isRightClick,
5525
5526    element:     element,
5527    findElement: findElement,
5528
5529    pointer:  pointer,
5530    pointerX: pointerX,
5531    pointerY: pointerY,
5532
5533    stop: stop
5534  };
5535
5536  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
5537    m[name] = Event.Methods[name].methodize();
5538    return m;
5539  });
5540
5541  if (window.attachEvent) {
5542    function _relatedTarget(event) {
5543      var element;
5544      switch (event.type) {
5545        case 'mouseover':
5546        case 'mouseenter':
5547          element = event.fromElement;
5548          break;
5549        case 'mouseout':
5550        case 'mouseleave':
5551          element = event.toElement;
5552          break;
5553        default:
5554          return null;
5555      }
5556      return Element.extend(element);
5557    }
5558
5559    var additionalMethods = {
5560      stopPropagation: function() { this.cancelBubble = true },
5561      preventDefault:  function() { this.returnValue = false },
5562      inspect: function() { return '[object Event]' }
5563    };
5564
5565    Event.extend = function(event, element) {
5566      if (!event) return false;
5567
5568      if (!isIELegacyEvent(event)) return event;
5569
5570      if (event._extendedByPrototype) return event;
5571      event._extendedByPrototype = Prototype.emptyFunction;
5572
5573      var pointer = Event.pointer(event);
5574
5575      Object.extend(event, {
5576        target: event.srcElement || element,
5577        relatedTarget: _relatedTarget(event),
5578        pageX:  pointer.x,
5579        pageY:  pointer.y
5580      });
5581
5582      Object.extend(event, methods);
5583      Object.extend(event, additionalMethods);
5584
5585      return event;
5586    };
5587  } else {
5588    Event.extend = Prototype.K;
5589  }
5590
5591  if (window.addEventListener) {
5592    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
5593    Object.extend(Event.prototype, methods);
5594  }
5595
5596  function _createResponder(element, eventName, handler) {
5597    var registry = Element.retrieve(element, 'prototype_event_registry');
5598
5599    if (Object.isUndefined(registry)) {
5600      CACHE.push(element);
5601      registry = Element.retrieve(element, 'prototype_event_registry', $H());
5602    }
5603
5604    var respondersForEvent = registry.get(eventName);
5605    if (Object.isUndefined(respondersForEvent)) {
5606      respondersForEvent = [];
5607      registry.set(eventName, respondersForEvent);
5608    }
5609
5610    if (respondersForEvent.pluck('handler').include(handler)) return false;
5611
5612    var responder;
5613    if (eventName.include(":")) {
5614      responder = function(event) {
5615        if (Object.isUndefined(event.eventName))
5616          return false;
5617
5618        if (event.eventName !== eventName)
5619          return false;
5620
5621        Event.extend(event, element);
5622        handler.call(element, event);
5623      };
5624    } else {
5625      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
5626       (eventName === "mouseenter" || eventName === "mouseleave")) {
5627        if (eventName === "mouseenter" || eventName === "mouseleave") {
5628          responder = function(event) {
5629            Event.extend(event, element);
5630
5631            var parent = event.relatedTarget;
5632            while (parent && parent !== element) {
5633              try { parent = parent.parentNode; }
5634              catch(e) { parent = element; }
5635            }
5636
5637            if (parent === element) return;
5638
5639            handler.call(element, event);
5640          };
5641        }
5642      } else {
5643        responder = function(event) {
5644          Event.extend(event, element);
5645          handler.call(element, event);
5646        };
5647      }
5648    }
5649
5650    responder.handler = handler;
5651    respondersForEvent.push(responder);
5652    return responder;
5653  }
5654
5655  function _destroyCache() {
5656    for (var i = 0, length = CACHE.length; i < length; i++) {
5657      Event.stopObserving(CACHE[i]);
5658      CACHE[i] = null;
5659    }
5660  }
5661
5662  var CACHE = [];
5663
5664  if (Prototype.Browser.IE)
5665    window.attachEvent('onunload', _destroyCache);
5666
5667  if (Prototype.Browser.WebKit)
5668    window.addEventListener('unload', Prototype.emptyFunction, false);
5669
5670
5671  var _getDOMEventName = Prototype.K,
5672      translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
5673
5674  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
5675    _getDOMEventName = function(eventName) {
5676      return (translations[eventName] || eventName);
5677    };
5678  }
5679
5680  function observe(element, eventName, handler) {
5681    element = $(element);
5682
5683    // Zoey Edit Start
5684    if(document.loaded && element === window && eventName === 'load' && typeof handler === 'function'){
5685      handler();
5686      return element;
5687    } else if(document.readyState === 'complete' && element === "dom:loaded" && typeof eventName === 'function') {
5688      eventName();
5689      return element;
5690    }
5691    // Zoey Edit End
5692
5693    var responder = _createResponder(element, eventName, handler);
5694
5695    if (!responder) return element;
5696
5697    if (eventName.include(':')) {
5698      if (element.addEventListener)
5699        element.addEventListener("dataavailable", responder, false);
5700      else if(element.attachEvent) {
5701        element.attachEvent("ondataavailable", responder);
5702        element.attachEvent("onlosecapture", responder);
5703      }
5704    } else {
5705      var actualEventName = _getDOMEventName(eventName);
5706
5707      if (element.addEventListener)
5708        element.addEventListener(actualEventName, responder, false);
5709      else if(element.attachEvent)
5710        element.attachEvent("on" + actualEventName, responder);
5711    }
5712
5713    return element;
5714  }
5715
5716  function stopObserving(element, eventName, handler) {
5717    element = $(element);
5718
5719    var registry = Element.retrieve(element, 'prototype_event_registry');
5720    if (!registry) return element;
5721
5722    if (!eventName) {
5723      registry.each( function(pair) {
5724        var eventName = pair.key;
5725        stopObserving(element, eventName);
5726      });
5727      return element;
5728    }
5729
5730    var responders = registry.get(eventName);
5731    if (!responders) return element;
5732
5733    if (!handler) {
5734      responders.each(function(r) {
5735        stopObserving(element, eventName, r.handler);
5736      });
5737      return element;
5738    }
5739
5740    var i = responders.length, responder;
5741    while (i--) {
5742      if (responders[i].handler === handler) {
5743        responder = responders[i];
5744        break;
5745      }
5746    }
5747    if (!responder) return element;
5748
5749    if (eventName.include(':')) {
5750      if (element.removeEventListener)
5751        element.removeEventListener("dataavailable", responder, false);
5752      else {
5753        element.detachEvent("ondataavailable", responder);
5754        element.detachEvent("onlosecapture", responder);
5755      }
5756    } else {
5757      var actualEventName = _getDOMEventName(eventName);
5758      if (element.removeEventListener)
5759        element.removeEventListener(actualEventName, responder, false);
5760      else
5761        element.detachEvent('on' + actualEventName, responder);
5762    }
5763
5764    registry.set(eventName, responders.without(responder));
5765
5766    return element;
5767  }
5768
5769  function fire(element, eventName, memo, bubble) {
5770    element = $(element);
5771
5772    if (Object.isUndefined(bubble))
5773      bubble = true;
5774
5775    if (element == document && document.createEvent && !element.dispatchEvent)
5776      element = document.documentElement;
5777
5778    var event;
5779    if (document.createEvent) {
5780      event = document.createEvent('HTMLEvents');
5781      event.initEvent('dataavailable', bubble, true);
5782    } else {
5783      event = document.createEventObject();
5784      event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
5785    }
5786
5787    event.eventName = eventName;
5788    event.memo = memo || { };
5789
5790    if (document.createEvent)
5791      element.dispatchEvent(event);
5792    else
5793      element.fireEvent(event.eventType, event);
5794
5795    return Event.extend(event);
5796  }
5797
5798  Event.Handler = Class.create({
5799    initialize: function(element, eventName, selector, callback) {
5800      this.element   = $(element);
5801      this.eventName = eventName;
5802      this.selector  = selector;
5803      this.callback  = callback;
5804      this.handler   = this.handleEvent.bind(this);
5805    },
5806
5807    start: function() {
5808      Event.observe(this.element, this.eventName, this.handler);
5809      return this;
5810    },
5811
5812    stop: function() {
5813      Event.stopObserving(this.element, this.eventName, this.handler);
5814      return this;
5815    },
5816
5817    handleEvent: function(event) {
5818      var element = Event.findElement(event, this.selector);
5819      if (element) this.callback.call(this.element, event, element);
5820    }
5821  });
5822
5823  function on(element, eventName, selector, callback) {
5824    element = $(element);
5825    if (Object.isFunction(selector) && Object.isUndefined(callback)) {
5826      callback = selector, selector = null;
5827    }
5828
5829    return new Event.Handler(element, eventName, selector, callback).start();
5830  }
5831
5832  Object.extend(Event, Event.Methods);
5833
5834  Object.extend(Event, {
5835    fire:          fire,
5836    observe:       observe,
5837    stopObserving: stopObserving,
5838    on:            on
5839  });
5840
5841  Element.addMethods({
5842    fire:          fire,
5843
5844    observe:       observe,
5845
5846    stopObserving: stopObserving,
5847
5848    on:            on
5849  });
5850
5851  Object.extend(document, {
5852    fire:          fire.methodize(),
5853
5854    observe:       observe.methodize(),
5855
5856    stopObserving: stopObserving.methodize(),
5857
5858    on:            on.methodize(),
5859
5860    loaded:        false
5861  });
5862
5863  if (window.Event) Object.extend(window.Event, Event);
5864  else window.Event = Event;
5865})();
5866
5867(function() {
5868  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
5869     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
5870
5871  var timer;
5872
5873  function fireContentLoadedEvent() {
5874    if (document.loaded) return;
5875    if (timer) window.clearTimeout(timer);
5876    document.loaded = true;
5877    document.fire('dom:loaded');
5878  }
5879
5880  function checkReadyState() {
5881    if (document.readyState === 'complete') {
5882      document.stopObserving('readystatechange', checkReadyState);
5883      fireContentLoadedEvent();
5884    }
5885  }
5886
5887  function pollDoScroll() {
5888    try { document.documentElement.doScroll('left'); }
5889    catch(e) {
5890      timer = pollDoScroll.defer();
5891      return;
5892    }
5893    fireContentLoadedEvent();
5894  }
5895
5896  if (document.addEventListener) {
5897    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
5898  } else {
5899    document.observe('readystatechange', checkReadyState);
5900    if (window == top)
5901      timer = pollDoScroll.defer();
5902  }
5903
5904  Event.observe(window, 'load', fireContentLoadedEvent);
5905})();
5906
5907Element.addMethods();
5908
5909/*------------------------------- DEPRECATED -------------------------------*/
5910
5911Hash.toQueryString = Object.toQueryString;
5912
5913var Toggle = { display: Element.toggle };
5914
5915Element.Methods.childOf = Element.Methods.descendantOf;
5916
5917var Insertion = {
5918  Before: function(element, content) {
5919    return Element.insert(element, {before:content});
5920  },
5921
5922  Top: function(element, content) {
5923    return Element.insert(element, {top:content});
5924  },
5925
5926  Bottom: function(element, content) {
5927    return Element.insert(element, {bottom:content});
5928  },
5929
5930  After: function(element, content) {
5931    return Element.insert(element, {after:content});
5932  }
5933};
5934
5935var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
5936
5937var Position = {
5938  includeScrollOffsets: false,
5939
5940  prepare: function() {
5941    this.deltaX =  window.pageXOffset
5942                || document.documentElement.scrollLeft
5943                || document.body.scrollLeft
5944                || 0;
5945    this.deltaY =  window.pageYOffset
5946                || document.documentElement.scrollTop
5947                || document.body.scrollTop
5948                || 0;
5949  },
5950
5951  within: function(element, x, y) {
5952    if (this.includeScrollOffsets)
5953      return this.withinIncludingScrolloffsets(element, x, y);
5954    this.xcomp = x;
5955    this.ycomp = y;
5956    this.offset = Element.cumulativeOffset(element);
5957
5958    return (y >= this.offset[1] &&
5959            y <  this.offset[1] + element.offsetHeight &&
5960            x >= this.offset[0] &&
5961            x <  this.offset[0] + element.offsetWidth);
5962  },
5963
5964  withinIncludingScrolloffsets: function(element, x, y) {
5965    var offsetcache = Element.cumulativeScrollOffset(element);
5966
5967    this.xcomp = x + offsetcache[0] - this.deltaX;
5968    this.ycomp = y + offsetcache[1] - this.deltaY;
5969    this.offset = Element.cumulativeOffset(element);
5970
5971    return (this.ycomp >= this.offset[1] &&
5972            this.ycomp <  this.offset[1] + element.offsetHeight &&
5973            this.xcomp >= this.offset[0] &&
5974            this.xcomp <  this.offset[0] + element.offsetWidth);
5975  },
5976
5977  overlap: function(mode, element) {
5978    if (!mode) return 0;
5979    if (mode == 'vertical')
5980      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
5981        element.offsetHeight;
5982    if (mode == 'horizontal')
5983      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
5984        element.offsetWidth;
5985  },
5986
5987
5988  cumulativeOffset: Element.Methods.cumulativeOffset,
5989
5990  positionedOffset: Element.Methods.positionedOffset,
5991
5992  absolutize: function(element) {
5993    Position.prepare();
5994    return Element.absolutize(element);
5995  },
5996
5997  relativize: function(element) {
5998    Position.prepare();
5999    return Element.relativize(element);
6000  },
6001
6002  realOffset: Element.Methods.cumulativeScrollOffset,
6003
6004  offsetParent: Element.Methods.getOffsetParent,
6005
6006  page: Element.Methods.viewportOffset,
6007
6008  clone: function(source, target, options) {
6009    options = options || { };
6010    return Element.clonePosition(target, source, options);
6011  }
6012};
6013
6014/*--------------------------------------------------------------------------*/
6015
6016if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
6017  function iter(name) {
6018    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
6019  }
6020
6021  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
6022  function(element, className) {
6023    className = className.toString().strip();
6024    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
6025    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
6026  } : function(element, className) {
6027    className = className.toString().strip();
6028    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
6029    if (!classNames && !className) return elements;
6030
6031    var nodes = $(element).getElementsByTagName('*');
6032    className = ' ' + className + ' ';
6033
6034    for (var i = 0, child, cn; child = nodes[i]; i++) {
6035      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
6036          (classNames && classNames.all(function(name) {
6037            return !name.toString().blank() && cn.include(' ' + name + ' ');
6038          }))))
6039        elements.push(Element.extend(child));
6040    }
6041    return elements;
6042  };
6043
6044  return function(className, parentElement) {
6045    return $(parentElement || document.body).getElementsByClassName(className);
6046  };
6047}(Element.Methods);
6048
6049/*--------------------------------------------------------------------------*/
6050
6051Element.ClassNames = Class.create();
6052Element.ClassNames.prototype = {
6053  initialize: function(element) {
6054    this.element = $(element);
6055  },
6056
6057  _each: function(iterator) {
6058    this.element.className.split(/\s+/).select(function(name) {
6059      return name.length > 0;
6060    })._each(iterator);
6061  },
6062
6063  set: function(className) {
6064    this.element.className = className;
6065  },
6066
6067  add: function(classNameToAdd) {
6068    if (this.include(classNameToAdd)) return;
6069    this.set($A(this).concat(classNameToAdd).join(' '));
6070  },
6071
6072  remove: function(classNameToRemove) {
6073    if (!this.include(classNameToRemove)) return;
6074    this.set($A(this).without(classNameToRemove).join(' '));
6075  },
6076
6077  toString: function() {
6078    return $A(this).join(' ');
6079  }
6080};
6081
6082Object.extend(Element.ClassNames.prototype, Enumerable);
6083
6084/*--------------------------------------------------------------------------*/
6085
6086(function() {
6087  window.Selector = Class.create({
6088    initialize: function(expression) {
6089      this.expression = expression.strip();
6090    },
6091
6092    findElements: function(rootElement) {
6093      return Prototype.Selector.select(this.expression, rootElement);
6094    },
6095
6096    match: function(element) {
6097      return Prototype.Selector.match(element, this.expression);
6098    },
6099
6100    toString: function() {
6101      return this.expression;
6102    },
6103
6104    inspect: function() {
6105      return "#<Selector: " + this.expression + ">";
6106    }
6107  });
6108
6109  Object.extend(Selector, {
6110    matchElements: function(elements, expression) {
6111      var match = Prototype.Selector.match,
6112          results = [];
6113
6114      for (var i = 0, length = elements.length; i < length; i++) {
6115        var element = elements[i];
6116        if (match(element, expression)) {
6117          results.push(Element.extend(element));
6118        }
6119      }
6120      return results;
6121    },
6122
6123    findElement: function(elements, expression, index) {
6124      index = index || 0;
6125      var matchIndex = 0, element;
6126      for (var i = 0, length = elements.length; i < length; i++) {
6127        element = elements[i];
6128        if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
6129          return Element.extend(element);
6130        }
6131      }
6132    },
6133
6134    findChildElements: function(element, expressions) {
6135      var selector = expressions.toArray().join(', ');
6136      return Prototype.Selector.select(selector, element || document);
6137    }
6138  });
6139})();
6140
6141window.Zoey.export('Prototype');

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.