PageSourceSearch

https://www.visegradgroup.eu/js/scriptaculous/prototype.js?ts=1610540218

js visegradgroup.eu collected 2026-09-24 18:15:15 UTC 140,919 bytes, 4,905 lines download raw bytes

1/*  Prototype JavaScript framework, version 1.6.1
2 *  (c) 2005-2009 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
9// -- START -- WEBRA módosítások: 2014.08.05. BalintZ.
10// A bootstrap dropdown menu nem jo enelkul
11var isBootstrapEvent = false;
12if (window.jQuery) {  
13  jQuery('*').on('hide.bs.dropdown', function( event ) {
14    isBootstrapEvent = true;
15  });
16  jQuery('*').on('hide.bs.collapse', function( event ) {
17    isBootstrapEvent = true;
18  });
19  jQuery('*').on('hide.bs.modal', function( event ) {
20    isBootstrapEvent = true;
21  });
22  jQuery('*').on('hide.bs.tooltip', function( event ) {
23    isBootstrapEvent = true;
24  });
25  jQuery('*').on('hide.bs.popover', function( event ) {
26    isBootstrapEvent = true;
27  });
28}
29// -- END -- WEBRA módosítások: 2014.08.05. BalintZ.
30
31var Prototype = {
32  Version: '1.6.1',
33
34  Browser: (function(){
35    var ua = navigator.userAgent;
36    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
37    return {
38      IE:             !!window.attachEvent && !isOpera,
39      Opera:          isOpera,
40      WebKit:         ua.indexOf('AppleWebKit/') > -1,
41      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
42      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
43    }
44  })(),
45
46  BrowserFeatures: {
47    XPath: !!document.evaluate,
48    SelectorsAPI: !!document.querySelector,
49    ElementExtensions: (function() {
50      var constructor = window.Element || window.HTMLElement;
51      return !!(constructor && constructor.prototype);
52    })(),
53    SpecificElementExtensions: (function() {
54      if (typeof window.HTMLDivElement !== 'undefined')
55        return true;
56
57      var div = document.createElement('div');
58      var form = document.createElement('form');
59      var isSupported = false;
60
61      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
62        isSupported = true;
63      }
64
65      div = form = null;
66
67      return isSupported;
68    })()
69  },
70
71  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
72  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
73
74  emptyFunction: function() { },
75  K: function(x) { return x }
76};
77
78if (Prototype.Browser.MobileSafari)
79  Prototype.BrowserFeatures.SpecificElementExtensions = false;
80
81
82var Abstract = { };
83
84
85var Try = {
86  these: function() {
87    var returnValue;
88
89    for (var i = 0, length = arguments.length; i < length; i++) {
90      var lambda = arguments[i];
91      try {
92        returnValue = lambda();
93        break;
94      } catch (e) { }
95    }
96
97    return returnValue;
98  }
99};
100
101/* Based on Alex Arnell's inheritance implementation. */
102
103var Class = (function() {
104  function subclass() {};
105  function create() {
106    var parent = null, properties = $A(arguments);
107    if (Object.isFunction(properties[0]))
108      parent = properties.shift();
109
110    function klass() {
111      this.initialize.apply(this, arguments);
112    }
113
114    Object.extend(klass, Class.Methods);
115    klass.superclass = parent;
116    klass.subclasses = [];
117
118    if (parent) {
119      subclass.prototype = parent.prototype;
120      klass.prototype = new subclass;
121      parent.subclasses.push(klass);
122    }
123
124    for (var i = 0; i < properties.length; i++)
125      klass.addMethods(properties[i]);
126
127    if (!klass.prototype.initialize)
128      klass.prototype.initialize = Prototype.emptyFunction;
129
130    klass.prototype.constructor = klass;
131    return klass;
132  }
133
134  function addMethods(source) {
135    var ancestor   = this.superclass && this.superclass.prototype;
136    var properties = Object.keys(source);
137
138    if (!Object.keys({ toString: true }).length) {
139      if (source.toString != Object.prototype.toString)
140        properties.push("toString");
141      if (source.valueOf != Object.prototype.valueOf)
142        properties.push("valueOf");
143    }
144
145    for (var i = 0, length = properties.length; i < length; i++) {
146      var property = properties[i], value = source[property];
147      if (ancestor && Object.isFunction(value) &&
148          value.argumentNames().first() == "$super") {
149        var method = value;
150        value = (function(m) {
151          return function() { return ancestor[m].apply(this, arguments); };
152        })(property).wrap(method);
153
154        value.valueOf = method.valueOf.bind(method);
155        value.toString = method.toString.bind(method);
156      }
157      this.prototype[property] = value;
158    }
159
160    return this;
161  }
162
163  return {
164    create: create,
165    Methods: {
166      addMethods: addMethods
167    }
168  };
169})();
170(function() {
171
172  var _toString = Object.prototype.toString;
173
174  function extend(destination, source) {
175    for (var property in source)
176      destination[property] = source[property];
177    return destination;
178  }
179
180  function inspect(object) {
181    try {
182      if (isUndefined(object)) return 'undefined';
183      if (object === null) return 'null';
184      return object.inspect ? object.inspect() : String(object);
185    } catch (e) {
186      if (e instanceof RangeError) return '...';
187      throw e;
188    }
189  }
190
191  function toJSON(object) {
192    var type = typeof object;
193    switch (type) {
194      case 'undefined':
195      case 'function':
196      case 'unknown': return;
197      case 'boolean': return object.toString();
198    }
199
200    if (object === null) return 'null';
201    if (object.toJSON) return object.toJSON();
202    if (isElement(object)) return;
203
204    var results = [];
205    for (var property in object) {
206      var value = toJSON(object[property]);
207      if (!isUndefined(value))
208        results.push(property.toJSON() + ': ' + value);
209    }
210
211    return '{' + results.join(', ') + '}';
212  }
213
214  function toQueryString(object) {
215    return $H(object).toQueryString();
216  }
217
218  function toHTML(object) {
219    return object && object.toHTML ? object.toHTML() : String.interpret(object);
220  }
221
222  function keys(object) {
223    var results = [];
224    for (var property in object)
225      results.push(property);
226    return results;
227  }
228
229  function values(object) {
230    var results = [];
231    for (var property in object)
232      results.push(object[property]);
233    return results;
234  }
235
236  function clone(object) {
237    return extend({ }, object);
238  }
239
240  function isElement(object) {
241    return !!(object && object.nodeType == 1);
242  }
243
244  function isArray(object) {
245    return _toString.call(object) == "[object Array]";
246  }
247
248
249  function isHash(object) {
250    return object instanceof Hash;
251  }
252
253  function isFunction(object) {
254    return typeof object === "function";
255  }
256
257  function isString(object) {
258    return _toString.call(object) == "[object String]";
259  }
260
261  function isNumber(object) {
262    return _toString.call(object) == "[object Number]";
263  }
264
265  function isUndefined(object) {
266    return typeof object === "undefined";
267  }
268
269  extend(Object, {
270    extend:        extend,
271    inspect:       inspect,
272    toJSON:        toJSON,
273    toQueryString: toQueryString,
274    toHTML:        toHTML,
275    keys:          keys,
276    values:        values,
277    clone:         clone,
278    isElement:     isElement,
279    isArray:       isArray,
280    isHash:        isHash,
281    isFunction:    isFunction,
282    isString:      isString,
283    isNumber:      isNumber,
284    isUndefined:   isUndefined
285  });
286})();
287Object.extend(Function.prototype, (function() {
288  var slice = Array.prototype.slice;
289
290  function update(array, args) {
291    var arrayLength = array.length, length = args.length;
292    while (length--) array[arrayLength + length] = args[length];
293    return array;
294  }
295
296  function merge(array, args) {
297    array = slice.call(array, 0);
298    return update(array, args);
299  }
300
301  function argumentNames() {
302    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
303      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
304      .replace(/\s+/g, '').split(',');
305    return names.length == 1 && !names[0] ? [] : names;
306  }
307
308  function bind(context) {
309    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
310    var __method = this, args = slice.call(arguments, 1);
311    return function() {
312      var a = merge(args, arguments);
313      return __method.apply(context, a);
314    }
315  }
316
317  function bindAsEventListener(context) {
318    var __method = this, args = slice.call(arguments, 1);
319    return function(event) {
320      var a = update([event || window.event], args);
321      return __method.apply(context, a);
322    }
323  }
324
325  function curry() {
326    if (!arguments.length) return this;
327    var __method = this, args = slice.call(arguments, 0);
328    return function() {
329      var a = merge(args, arguments);
330      return __method.apply(this, a);
331    }
332  }
333
334  function delay(timeout) {
335    var __method = this, args = slice.call(arguments, 1);
336    timeout = timeout * 1000
337    return window.setTimeout(function() {
338      return __method.apply(__method, args);
339    }, timeout);
340  }
341
342  function defer() {
343    var args = update([0.01], arguments);
344    return this.delay.apply(this, args);
345  }
346
347  function wrap(wrapper) {
348    var __method = this;
349    return function() {
350      var a = update([__method.bind(this)], arguments);
351      return wrapper.apply(this, a);
352    }
353  }
354
355  function methodize() {
356    if (this._methodized) return this._methodized;
357    var __method = this;
358    return this._methodized = function() {
359      var a = update([this], arguments);
360      return __method.apply(null, a);
361    };
362  }
363
364  return {
365    argumentNames:       argumentNames,
366    bind:                bind,
367    bindAsEventListener: bindAsEventListener,
368    curry:               curry,
369    delay:               delay,
370    defer:               defer,
371    wrap:                wrap,
372    methodize:           methodize
373  }
374})());
375
376
377Date.prototype.toJSON = function() {
378  return '"' + this.getUTCFullYear() + '-' +
379    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
380    this.getUTCDate().toPaddedString(2) + 'T' +
381    this.getUTCHours().toPaddedString(2) + ':' +
382    this.getUTCMinutes().toPaddedString(2) + ':' +
383    this.getUTCSeconds().toPaddedString(2) + 'Z"';
384};
385
386
387RegExp.prototype.match = RegExp.prototype.test;
388
389RegExp.escape = function(str) {
390  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
391};
392var PeriodicalExecuter = Class.create({
393  initialize: function(callback, frequency) {
394    this.callback = callback;
395    this.frequency = frequency;
396    this.currentlyExecuting = false;
397
398    this.registerCallback();
399  },
400
401  registerCallback: function() {
402    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
403  },
404
405  execute: function() {
406    this.callback(this);
407  },
408
409  stop: function() {
410    if (!this.timer) return;
411    clearInterval(this.timer);
412    this.timer = null;
413  },
414
415  onTimerEvent: function() {
416    if (!this.currentlyExecuting) {
417      try {
418        this.currentlyExecuting = true;
419        this.execute();
420        this.currentlyExecuting = false;
421      } catch(e) {
422        this.currentlyExecuting = false;
423        throw e;
424      }
425    }
426  }
427});
428Object.extend(String, {
429  interpret: function(value) {
430    return value == null ? '' : String(value);
431  },
432  specialChar: {
433    '\b': '\\b',
434    '\t': '\\t',
435    '\n': '\\n',
436    '\f': '\\f',
437    '\r': '\\r',
438    '\\': '\\\\'
439  }
440});
441
442Object.extend(String.prototype, (function() {
443
444  function prepareReplacement(replacement) {
445    if (Object.isFunction(replacement)) return replacement;
446    var template = new Template(replacement);
447    return function(match) { return template.evaluate(match) };
448  }
449
450  function gsub(pattern, replacement) {
451    var result = '', source = this, match;
452    replacement = prepareReplacement(replacement);
453
454    if (Object.isString(pattern))
455      pattern = RegExp.escape(pattern);
456
457    if (!(pattern.length || pattern.source)) {
458      replacement = replacement('');
459      return replacement + source.split('').join(replacement) + replacement;
460    }
461
462    while (source.length > 0) {
463      if (match = source.match(pattern)) {
464        result += source.slice(0, match.index);
465        result += String.interpret(replacement(match));
466        source  = source.slice(match.index + match[0].length);
467      } else {
468        result += source, source = '';
469      }
470    }
471    return result;
472  }
473
474  function sub(pattern, replacement, count) {
475    replacement = prepareReplacement(replacement);
476    count = Object.isUndefined(count) ? 1 : count;
477
478    return this.gsub(pattern, function(match) {
479      if (--count < 0) return match[0];
480      return replacement(match);
481    });
482  }
483
484  function scan(pattern, iterator) {
485    this.gsub(pattern, iterator);
486    return String(this);
487  }
488
489  function truncate(length, truncation) {
490    length = length || 30;
491    truncation = Object.isUndefined(truncation) ? '...' : truncation;
492    return this.length > length ?
493      this.slice(0, length - truncation.length) + truncation : String(this);
494  }
495
496  function strip() {
497    return this.replace(/^\s+/, '').replace(/\s+$/, '');
498  }
499
500  function stripTags() {
501    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
502  }
503
504  function stripScripts() {
505    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
506  }
507
508  function extractScripts() {
509    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
510    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
511    return (this.match(matchAll) || []).map(function(scriptTag) {
512      return (scriptTag.match(matchOne) || ['', ''])[1];
513    });
514  }
515
516  function evalScripts() {
517    return this.extractScripts().map(function(script) { return eval(script) });
518  }
519
520  function escapeHTML() {
521    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
522  }
523
524  function unescapeHTML() {
525    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
526  }
527
528
529  function toQueryParams(separator) {
530    var match = this.strip().match(/([^?#]*)(#.*)?$/);
531    if (!match) return { };
532
533    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
534      if ((pair = pair.split('='))[0]) {
535        var key = decodeURIComponent(pair.shift());
536        var value = pair.length > 1 ? pair.join('=') : pair[0];
537        if (value != undefined) value = decodeURIComponent(value);
538
539        if (key in hash) {
540          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
541          hash[key].push(value);
542        }
543        else hash[key] = value;
544      }
545      return hash;
546    });
547  }
548
549  function toArray() {
550    return this.split('');
551  }
552
553  function succ() {
554    return this.slice(0, this.length - 1) +
555      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
556  }
557
558  function times(count) {
559    return count < 1 ? '' : new Array(count + 1).join(this);
560  }
561
562  function camelize() {
563    var parts = this.split('-'), len = parts.length;
564    if (len == 1) return parts[0];
565
566    var camelized = this.charAt(0) == '-'
567      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
568      : parts[0];
569
570    for (var i = 1; i < len; i++)
571      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
572
573    return camelized;
574  }
575
576  function capitalize() {
577    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
578  }
579
580  function underscore() {
581    return this.replace(/::/g, '/')
582               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
583               .replace(/([a-z\d])([A-Z])/g, '$1_$2')
584               .replace(/-/g, '_')
585               .toLowerCase();
586  }
587
588  function dasherize() {
589    return this.replace(/_/g, '-');
590  }
591
592  function inspect(useDoubleQuotes) {
593    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(ch
593aracter) {
594      if (character in String.specialChar) {
595        return String.specialChar[character];
596      }
597      return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
598    });
599    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
600    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
601  }
602
603  function toJSON() {
604    return this.inspect(true);
605  }
606
607  function unfilterJSON(filter) {
608    return this.replace(filter || Prototype.JSONFilter, '$1');
609  }
610
611  function isJSON() {
612    var str = this;
613    if (str.blank()) return false;
614    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
615    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
616  }
617
618  function evalJSON(sanitize) {
619    var json = this.unfilterJSON();
620    try {
621      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
622    } catch (e) { }
623    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
624  }
625
626  function include(pattern) {
627    return this.indexOf(pattern) > -1;
628  }
629
630  function startsWith(pattern) {
631    return this.indexOf(pattern) === 0;
632  }
633
634  function endsWith(pattern) {
635    var d = this.length - pattern.length;
636    return d >= 0 && this.lastIndexOf(pattern) === d;
637  }
638
639  function empty() {
640    return this == '';
641  }
642
643  function blank() {
644    return /^\s*$/.test(this);
645  }
646
647  function interpolate(object, pattern) {
648    return new Template(this, pattern).evaluate(object);
649  }
650
651  return {
652    gsub:           gsub,
653    sub:            sub,
654    scan:           scan,
655    truncate:       truncate,
656    strip:          String.prototype.trim ? String.prototype.trim : strip,
657    stripTags:      stripTags,
658    stripScripts:   stripScripts,
659    extractScripts: extractScripts,
660    evalScripts:    evalScripts,
661    escapeHTML:     escapeHTML,
662    unescapeHTML:   unescapeHTML,
663    toQueryParams:  toQueryParams,
664    parseQuery:     toQueryParams,
665    toArray:        toArray,
666    succ:           succ,
667    times:          times,
668    camelize:       camelize,
669    capitalize:     capitalize,
670    underscore:     underscore,
671    dasherize:      dasherize,
672    inspect:        inspect,
673    toJSON:         toJSON,
674    unfilterJSON:   unfilterJSON,
675    isJSON:         isJSON,
676    evalJSON:       evalJSON,
677    include:        include,
678    startsWith:     startsWith,
679    endsWith:       endsWith,
680    empty:          empty,
681    blank:          blank,
682    interpolate:    interpolate
683  };
684})());
685
686var Template = Class.create({
687  initialize: function(template, pattern) {
688    this.template = template.toString();
689    this.pattern = pattern || Template.Pattern;
690  },
691
692  evaluate: function(object) {
693    if (object && Object.isFunction(object.toTemplateReplacements))
694      object = object.toTemplateReplacements();
695
696    return this.template.gsub(this.pattern, function(match) {
697      if (object == null) return (match[1] + '');
698
699      var before = match[1] || '';
700      if (before == '\\') return match[2];
701
702      var ctx = object, expr = match[3];
703      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
704      match = pattern.exec(expr);
705      if (match == null) return before;
706
707      while (match != null) {
708        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
709        ctx = ctx[comp];
710        if (null == ctx || '' == match[3]) break;
711        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
712        match = pattern.exec(expr);
713      }
714
715      return before + String.interpret(ctx);
716    });
717  }
718});
719Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
720
721var $break = { };
722
723var Enumerable = (function() {
724  function each(iterator, context) {
725    var index = 0;
726    try {
727      this._each(function(value) {
728        iterator.call(context, value, index++);
729      });
730    } catch (e) {
731      if (e != $break) throw e;
732    }
733    return this;
734  }
735
736  function eachSlice(number, iterator, context) {
737    var index = -number, slices = [], array = this.toArray();
738    if (number < 1) return array;
739    while ((index += number) < array.length)
740      slices.push(array.slice(index, index+number));
741    return slices.collect(iterator, context);
742  }
743
744  function all(iterator, context) {
745    iterator = iterator || Prototype.K;
746    var result = true;
747    this.each(function(value, index) {
748      result = result && !!iterator.call(context, value, index);
749      if (!result) throw $break;
750    });
751    return result;
752  }
753
754  function any(iterator, context) {
755    iterator = iterator || Prototype.K;
756    var result = false;
757    this.each(function(value, index) {
758      if (result = !!iterator.call(context, value, index))
759        throw $break;
760    });
761    return result;
762  }
763
764  function collect(iterator, context) {
765    iterator = iterator || Prototype.K;
766    var results = [];
767    this.each(function(value, index) {
768      results.push(iterator.call(context, value, index));
769    });
770    return results;
771  }
772
773  function detect(iterator, context) {
774    var result;
775    this.each(function(value, index) {
776      if (iterator.call(context, value, index)) {
777        result = value;
778        throw $break;
779      }
780    });
781    return result;
782  }
783
784  function findAll(iterator, context) {
785    var results = [];
786    this.each(function(value, index) {
787      if (iterator.call(context, value, index))
788        results.push(value);
789    });
790    return results;
791  }
792
793  function grep(filter, iterator, context) {
794    iterator = iterator || Prototype.K;
795    var results = [];
796
797    if (Object.isString(filter))
798      filter = new RegExp(RegExp.escape(filter));
799
800    this.each(function(value, index) {
801      if (filter.match(value))
802        results.push(iterator.call(context, value, index));
803    });
804    return results;
805  }
806
807  function include(object) {
808    if (Object.isFunction(this.indexOf))
809      if (this.indexOf(object) != -1) return true;
810
811    var found = false;
812    this.each(function(value) {
813      if (value == object) {
814        found = true;
815        throw $break;
816      }
817    });
818    return found;
819  }
820
821  function inGroupsOf(number, fillWith) {
822    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
823    return this.eachSlice(number, function(slice) {
824      while(slice.length < number) slice.push(fillWith);
825      return slice;
826    });
827  }
828
829  function inject(memo, iterator, context) {
830    this.each(function(value, index) {
831      memo = iterator.call(context, memo, value, index);
832    });
833    return memo;
834  }
835
836  function invoke(method) {
837    var args = $A(arguments).slice(1);
838    return this.map(function(value) {
839      return value[method].apply(value, args);
840    });
841  }
842
843  function max(iterator, context) {
844    iterator = iterator || Prototype.K;
845    var result;
846    this.each(function(value, index) {
847      value = iterator.call(context, value, index);
848      if (result == null || value >= result)
849        result = value;
850    });
851    return result;
852  }
853
854  function min(iterator, context) {
855    iterator = iterator || Prototype.K;
856    var result;
857    this.each(function(value, index) {
858      value = iterator.call(context, value, index);
859      if (result == null || value < result)
860        result = value;
861    });
862    return result;
863  }
864
865  function partition(iterator, context) {
866    iterator = iterator || Prototype.K;
867    var trues = [], falses = [];
868    this.each(function(value, index) {
869      (iterator.call(context, value, index) ?
870        trues : falses).push(value);
871    });
872    return [trues, falses];
873  }
874
875  function pluck(property) {
876    var results = [];
877    this.each(function(value) {
878      results.push(value[property]);
879    });
880    return results;
881  }
882
883  function reject(iterator, context) {
884    var results = [];
885    this.each(function(value, index) {
886      if (!iterator.call(context, value, index))
887        results.push(value);
888    });
889    return results;
890  }
891
892  function sortBy(iterator, context) {
893    return this.map(function(value, index) {
894      return {
895        value: value,
896        criteria: iterator.call(context, value, index)
897      };
898    }).sort(function(left, right) {
899      var a = left.criteria, b = right.criteria;
900      return a < b ? -1 : a > b ? 1 : 0;
901    }).pluck('value');
902  }
903
904  function toArray() {
905    return this.map();
906  }
907
908  function zip() {
909    var iterator = Prototype.K, args = $A(arguments);
910    if (Object.isFunction(args.last()))
911      iterator = args.pop();
912
913    var collections = [this].concat(args).map($A);
914    return this.map(function(value, index) {
915      return iterator(collections.pluck(index));
916    });
917  }
918
919  function size() {
920    return this.toArray().length;
921  }
922
923  function inspect() {
924    return '#<Enumerable:' + this.toArray().inspect() + '>';
925  }
926
927
928
929
930
931
932
933
934
935  return {
936    each:       each,
937    eachSlice:  eachSlice,
938    all:        all,
939    every:      all,
940    any:        any,
941    some:       any,
942    collect:    collect,
943    map:        collect,
944    detect:     detect,
945    findAll:    findAll,
946    select:     findAll,
947    filter:     findAll,
948    grep:       grep,
949    include:    include,
950    member:     include,
951    inGroupsOf: inGroupsOf,
952    inject:     inject,
953    invoke:     invoke,
954    max:        max,
955    min:        min,
956    partition:  partition,
957    pluck:      pluck,
958    reject:     reject,
959    sortBy:     sortBy,
960    toArray:    toArray,
961    entries:    toArray,
962    zip:        zip,
963    size:       size,
964    inspect:    inspect,
965    find:       detect
966  };
967})();
968function $A(iterable) {
969  if (!iterable) return [];
970  if ('toArray' in Object(iterable)) return iterable.toArray();
971  var length = iterable.length || 0, results = new Array(length);
972  while (length--) results[length] = iterable[length];
973  return results;
974}
975
976function $w(string) {
977  if (!Object.isString(string)) return [];
978  string = string.strip();
979  return string ? string.split(/\s+/) : [];
980}
981
982Array.from = $A;
983
984
985(function() {
986  var arrayProto = Array.prototype,
987      slice = arrayProto.slice,
988      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
989
990  function each(iterator) {
991    for (var i = 0, length = this.length; i < length; i++)
992      iterator(this[i]);
993  }
994  if (!_each) _each = each;
995
996  function clear() {
997    this.length = 0;
998    return this;
999  }
1000
1001  function first() {
1002    return this[0];
1003  }
1004
1005  function last() {
1006    return this[this.length - 1];
1007  }
1008
1009  function compact() {
1010    return this.select(function(value) {
1011      return value != null;
1012    });
1013  }
1014
1015  function flatten() {
1016    return this.inject([], function(array, value) {
1017      if (Object.isArray(value))
1018        return array.concat(value.flatten());
1019      array.push(value);
1020      return array;
1021    });
1022  }
1023
1024  function without() {
1025    var values = slice.call(arguments, 0);
1026    return this.select(function(value) {
1027      return !values.include(value);
1028    });
1029  }
1030
1031  function reverse(inline) {
1032    return (inline !== false ? this : this.toArray())._reverse();
1033  }
1034
1035  function uniq(sorted) {
1036    return this.inject([], function(array, value, index) {
1037      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1038        array.push(value);
1039      return array;
1040    });
1041  }
1042
1043  function intersect(array) {
1044    return this.uniq().findAll(function(item) {
1045      return array.detect(function(value) { return item === value });
1046    });
1047  }
1048
1049
1050  function clone() {
1051    return slice.call(this, 0);
1052  }
1053
1054  function size() {
1055    return this.length;
1056  }
1057
1058  function inspect() {
1059    return '[' + this.map(Object.inspect).join(', ') + ']';
1060  }
1061
1062  function toJSON() {
1063    var results = [];
1064    this.each(function(object) {
1065      var value = Object.toJSON(object);
1066      if (!Object.isUndefined(value)) results.push(value);
1067    });
1068    return '[' + results.join(', ') + ']';
1069  }
1070
1071  function indexOf(item, i) {
1072    i || (i = 0);
1073    var length = this.length;
1074    if (i < 0) i = length + i;
1075    for (; i < length; i++)
1076      if (this[i] === item) return i;
1077    return -1;
1078  }
1079
1080  function lastIndexOf(item, i) {
1081    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
1082    var n = this.slice(0, i).reverse().indexOf(item);
1083    return (n < 0) ? n : i - n - 1;
1084  }
1085
1086  function concat() {
1087    var array = slice.call(this, 0), item;
1088    for (var i = 0, length = arguments.length; i < length; i++) {
1089      item = arguments[i];
1090      if (Object.isArray(item) && !('callee' in item)) {
1091        for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
1092          array.push(item[j]);
1093      } else {
1094        array.push(item);
1095      }
1096    }
1097    return array;
1098  }
1099
1100  Object.extend(arrayProto, Enumerable);
1101
1102  if (!arrayProto._reverse)
1103    arrayProto._reverse = arrayProto.reverse;
1104
1105  Object.extend(arrayProto, {
1106    _each:     _each,
1107    clear:     clear,
1108    first:     first,
1109    last:      last,
1110    compact:   compact,
1111    flatten:   flatten,
1112    without:   without,
1113    reverse:   reverse,
1114    uniq:      uniq,
1115    intersect: intersect,
1116    clone:     clone,
1117    toArray:   clone,
1118    size:      size,
1119    inspect:   inspect,
1120    toJSON:    toJSON
1121  });
1122
1123  var CONCAT_ARGUMENTS_BUGGY = (function() {
1124    return [].concat(arguments)[0][0] !== 1;
1125  })(1,2)
1126
1127  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1128
1129  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1130  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1131})();
1132function $H(object) {
1133  return new Hash(object);
1134};
1135
1136var Hash = Class.create(Enumerable, (function() {
1137  function initialize(object) {
1138    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1139  }
1140
1141  function _each(iterator) {
1142    for (var key in this._object) {
1143      var value = this._object[key], pair = [key, value];
1144      pair.key = key;
1145      pair.value = value;
1146      iterator(pair);
1147    }
1148  }
1149
1150  function set(key, value) {
1151    return this._object[key] = value;
1152  }
1153
1154  function get(key) {
1155    if (this._object[key] !== Object.prototype[key])
1156      return this._object[key];
1157  }
1158
1159  function unset(key) {
1160    var value = this._object[key];
1161    delete this._object[key];
1162    return value;
1163  }
1164
1165  function toObject() {
1166    return Object.clone(this._object);
1167  }
1168
1169  function keys() {
1170    return this.pluck('key');
1171  }
1172
1173  function values() {
1174    return this.pluck('value');
1175  }
1176
1177  function index(value) {
1178    var match = this.detect(function(pair) {
1179      return pair.value === value;
1180    });
1181    return match && match.key;
1182  }
1183
1184  function merge(object) {
1185    return this.clone().update(object);
1186  }
1187
1188  function update(object) {
1189    return new Hash(object).inject(this, function(result, pair) {
1190      result.set(pair.key, pair.value);
1191      return result;
1192    });
1193  }
1194
1195  function toQueryPair(key, value) {
1196    if (Object.isUndefined(value)) return key;
1197    return key + '=' + encodeURIComponent(String.interpret(value));
1198  }
1199
1200  function toQueryString() {
1201    return this.inject([], function(results, pair) {
1202      var key = encodeURIComponent(pair.key), values = pair.value;
1203
1204      if (values && typeof values == 'object') {
1205        if (Object.isArray(values))
1206          return results.concat(values.map(toQueryPair.curry(key)));
1207      } else results.push(toQueryPair(key, values));
1208      return results;
1209    }).join('&');
1210  }
1211
1212  function inspect() {
1213    return '#<Hash:{' + this.map(function(pair) {
1214      return pair.map(Object.inspect).join(': ');
1215    }).join(', ') + '}>';
1216  }
1217
1218  function toJSON() {
1219    return Object.toJSON(this.toObject());
1220  }
1221
1222  function clone() {
1223    return new Hash(this);
1224  }
1225
1226  return {
1227    initialize:             initialize,
1228    _each:                  _each,
1229    set:                    set,
1230    get:                    get,
1231    unset:                  unset,
1232    toObject:               toObject,
1233    toTemplateReplacements: toObject,
1234    keys:                   keys,
1235    values:                 values,
1236    index:                  index,
1237    merge:                  merge,
1238    update:                 update,
1239    toQueryString:          toQueryString,
1240    inspect:                inspect,
1241    toJSON:                 toJSON,
1242    clone:                  clone
1243  };
1244})());
1245
1246Hash.from = $H;
1247Object.extend(Number.prototype, (function() {
1248  function toColorPart() {
1249    return this.toPaddedString(2, 16);
1250  }
1251
1252  function succ() {
1253    return this + 1;
1254  }
1255
1256  function times(iterator, context) {
1257    $R(0, this, true).each(iterator, context);
1258    return this;
1259  }
1260
1261  function toPaddedString(length, radix) {
1262    var string = this.toString(radix || 10);
1263    return '0'.times(length - string.length) + string;
1264  }
1265
1266  function toJSON() {
1267    return isFinite(this) ? this.toString() : 'null';
1268  }
1269
1270  function abs() {
1271    return Math.abs(this);
1272  }
1273
1274  function round() {
1275    return Math.round(this);
1276  }
1277
1278  function ceil() {
1279    return Math.ceil(this);
1280  }
1281
1282  function floor() {
1283    return Math.floor(this);
1284  }
1285
1286  return {
1287    toColorPart:    toColorPart,
1288    succ:           succ,
1289    times:          times,
1290    toPaddedString: toPaddedString,
1291    toJSON:         toJSON,
1292    abs:            abs,
1293    round:          round,
1294    ceil:           ceil,
1295    floor:          floor
1296  };
1297})());
1298
1299function $R(start, end, exclusive) {
1300  return new ObjectRange(start, end, exclusive);
1301}
1302
1303var ObjectRange = Class.create(Enumerable, (function() {
1304  function initialize(start, end, exclusive) {
1305    this.start = start;
1306    this.end = end;
1307    this.exclusive = exclusive;
1308  }
1309
1310  function _each(iterator) {
1311    var value = this.start;
1312    while (this.include(value)) {
1313      iterator(value);
1314      value = value.succ();
1315    }
1316  }
1317
1318  function include(value) {
1319    if (value < this.start)
1320      return false;
1321    if (this.exclusive)
1322      return value < this.end;
1323    return value <= this.end;
1324  }
1325
1326  return {
1327    initialize: initialize,
1328    _each:      _each,
1329    include:    include
1330  };
1331})());
1332
1333
1334
1335var Ajax = {
1336  getTransport: function() {
1337    return Try.these(
1338      function() {return new XMLHttpRequest()},
1339      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1340      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1341    ) || false;
1342  },
1343
1344  activeRequestCount: 0
1345};
1346
1347Ajax.Responders = {
1348  responders: [],
1349
1350  _each: function(iterator) {
1351    this.responders._each(iterator);
1352  },
1353
1354  register: function(responder) {
1355    if (!this.include(responder))
1356      this.responders.push(responder);
1357  },
1358
1359  unregister: function(responder) {
1360    this.responders = this.responders.without(responder);
1361  },
1362
1363  dispatch: function(callback, request, transport, json) {
1364    this.each(function(responder) {
1365      if (Object.isFunction(responder[callback])) {
1366        try {
1367          responder[callback].apply(responder, [request, transport, json]);
1368        } catch (e) { }
1369      }
1370    });
1371  }
1372};
1373
1374Object.extend(Ajax.Responders, Enumerable);
1375
1376Ajax.Responders.register({
1377  onCreate:   function() { Ajax.activeRequestCount++ },
1378  onComplete: function() { Ajax.activeRequestCount-- }
1379});
1380Ajax.Base = Class.create({
1381  initialize: function(options) {
1382    this.options = {
1383      method:       'post',
1384      asynchronous: true,
1385      contentType:  'application/x-www-form-urlencoded',
1386      encoding:     'UTF-8',
1387      parameters:   '',
1388      evalJSON:     true,
1389      evalJS:       true
1390    };
1391    Object.extend(this.options, options || { });
1392
1393    this.options.method = this.options.method.toLowerCase();
1394
1395    if (Object.isString(this.options.parameters))
1396      this.options.parameters = this.options.parameters.toQueryParams();
1397    else if (Object.isHash(this.options.parameters))
1398      this.options.parameters = this.options.parameters.toObject();
1399  }
1400});
1401Ajax.Request = Class.create(Ajax.Base, {
1402  _complete: false,
1403
1404  initialize: function($super, url, options) {
1405    $super(options);
1406    this.transport = Ajax.getTransport();
1407    this.request(url);
1408  },
1409
1410  request: function(url) {
1411    this.url = url;
1412    this.method = this.options.method;
1413    var params = Object.clone(this.options.parameters);
1414
1415    if (!['get', 'post'].include(this.method)) {
1416      params['_method'] = this.method;
1417      this.method = 'post';
1418    }
1419
1420    this.parameters = params;
1421
1422    if (params = Object.toQueryString(params)) {
1423      if (this.method == 'get')
1424        this.url += (this.url.include('?') ? '&' : '?') + params;
1425      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1426        params += '&_=';
1427    }
1428
1429    try {
1430      var response = new Ajax.Response(this);
1431      if (this.options.onCreate) this.options.onCreate(response);
1432      Ajax.Responders.dispatch('onCreate', this, response);
1433
1434      this.transport.open(this.method.toUpperCase(), this.url,
1435        this.options.asynchronous);
1436
1437      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1438
1439      this.transport.onreadystatechange = this.onStateChange.bind(this);
1440      this.setRequestHeaders();
1441
1442      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1443      this.transport.send(this.body);
1444
1445      /* Force Firefox to handle ready state 4 for synchronous requests */
1446      if (!this.options.asynchronous && this.transport.overrideMimeType)
1447        this.onStateChange();
1448
1449    }
1450    catch (e) {
1451      this.dispatchException(e);
1452    }
1453  },
1454
1455  onStateChange: function() {
1456    var readyState = this.transport.readyState;
1457    if (readyState > 1 && !((readyState == 4) && this._complete))
1458      this.respondToReadyState(this.transport.readyState);
1459  },
1460
1461  setRequestHeaders: function() {
1462    var headers = {
1463      'X-Requested-With': 'XMLHttpRequest',
1464      'X-Prototype-Version': Prototype.Version,
1465      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1466    };
1467
1468    if (this.method == 'post') {
1469      headers['Content-type'] = this.options.contentType +
1470        (this.options.encoding ? '; charset=' + this.options.encoding : '');
1471
1472      /* Force "Connection: close" for older Mozilla browsers to work
1473       * around a bug where XMLHttpRequest sends an incorrect
1474       * Content-length header. See Mozilla Bugzilla #246651.
1475       */
1476      if (this.transport.overrideMimeType &&
1477          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1478            headers['Connection'] = 'close';
1479    }
1480
1481    if (typeof this.options.requestHeaders == 'object') {
1482      var extras = this.options.requestHeaders;
1483
1484      if (Object.isFunction(extras.push))
1485        for (var i = 0, length = extras.length; i < length; i += 2)
1486          headers[extras[i]] = extras[i+1];
1487      else
1488        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1489    }
1490
1491    for (var name in headers)
1492      this.transport.setRequestHeader(name, headers[name]);
1493  },
1494
1495  success: function() {
1496    var status = this.getStatus();
1497    return !status || (status >= 200 && status < 300);
1498  },
1499
1500  getStatus: function() {
1501    try {
1502      return this.transport.status || 0;
1503    } catch (e) { return 0 }
1504  },
1505
1506  respondToReadyState: function(readyState) {
1507    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1508
1509    if (state == 'Complete') {
1510      try {
1511        this._complete = true;
1512        (this.options['on' + response.status]
1513         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1514         || Prototype.emptyFunction)(response, response.headerJSON);
1515      } catch (e) {
1516        this.dispatchException(e);
1517      }
1518
1519      var contentType = response.getHeader('Content-type');
1520      if (this.options.evalJS == 'force'
1521          || (this.options.evalJS && this.isSameOrigin() && contentType
1522          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1523        this.evalResponse();
1524    }
1525
1526    try {
1527      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1528      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1529    } catch (e) {
1530      this.dispatchException(e);
1531    }
1532
1533    if (state == 'Complete') {
1534      this.transport.onreadystatechange = Prototype.emptyFunction;
1535    }
1536  },
1537
1538  isSameOrigin: function() {
1539    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1540    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1541      protocol: location.protocol,
1542      domain: document.domain,
1543      port: location.port ? ':' + location.port : ''
1544    }));
1545  },
1546
1547  getHeader: function(name) {
1548    try {
1549      return this.transport.getResponseHeader(name) || null;
1550    } catch (e) { return null; }
1551  },
1552
1553  evalResponse: function() {
1554    try {
1555      return eval((this.transport.responseText || '').unfilterJSON());
1556    } catch (e) {
1557      this.dispatchException(e);
1558    }
1559  },
1560
1561  dispatchException: function(exception) {
1562    (this.options.onException || Prototype.emptyFunction)(this, exception);
1563    Ajax.Responders.dispatch('onException', this, exception);
1564  }
1565});
1566
1567Ajax.Request.Events =
1568  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1569
1570
1571
1572
1573
1574
1575
1576
1577Ajax.Response = Class.create({
1578  initialize: function(request){
1579    this.request = request;
1580    var transport  = this.transport  = request.transport,
1581        readyState = this.readyState = transport.readyState;
1582
1583    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1584      this.status       = this.getStatus();
1585      this.statusText   = this.getStatusText();
1586      this.responseText = String.interpret(transport.responseText);
1587      this.headerJSON   = this._getHeaderJSON();
1588    }
1589
1590    if(readyState == 4) {
1591      var xml = transport.responseXML;
1592      this.responseXML  = Object.isUndefined(xml) ? null : xml;
1593      this.responseJSON = this._getResponseJSON();
1594    }
1595  },
1596
1597  status:      0,
1598
1599  statusText: '',
1600
1601  getStatus: Ajax.Request.prototype.getStatus,
1602
1603  getStatusText: function() {
1604    try {
1605      return this.transport.statusText || '';
1606    } catch (e) { return '' }
1607  },
1608
1609  getHeader: Ajax.Request.prototype.getHeader,
1610
1611  getAllHeaders: function() {
1612    try {
1613      return this.getAllResponseHeaders();
1614    } catch (e) { return null }
1615  },
1616
1617  getResponseHeader: function(name) {
1618    return this.transport.getResponseHeader(name);
1619  },
1620
1621  getAllResponseHeaders: function() {
1622    return this.transport.getAllResponseHeaders();
1623  },
1624
1625  _getHeaderJSON: function() {
1626    var json = this.getHeader('X-JSON');
1627    if (!json) return null;
1628    json = decodeURIComponent(escape(json));
1629    try {
1630      return json.evalJSON(this.request.options.sanitizeJSON ||
1631        !this.request.isSameOrigin());
1632    } catch (e) {
1633      this.request.dispatchException(e);
1634    }
1635  },
1636
1637  _getResponseJSON: function() {
1638    var options = this.request.options;
1639    if (!options.evalJSON || (options.evalJSON != 'force' &&
1640      !(this.getHeader('Content-type') || '').include('application/json')) ||
1641        this.responseText.blank())
1642          return null;
1643    try {
1644      return this.responseText.evalJSON(options.sanitizeJSON ||
1645        !this.request.isSameOrigin());
1646    } catch (e) {
1647      this.request.dispatchException(e);
1648    }
1649  }
1650});
1651
1652Ajax.Updater = Class.create(Ajax.Request, {
1653  initialize: function($super, container, url, options) {
1654    this.container = {
1655      success: (container.success || container),
1656      failure: (container.failure || (container.success ? null : container))
1657    };
1658
1659    options = Object.clone(options);
1660    var onComplete = options.onComplete;
1661    options.onComplete = (function(response, json) {
1662      this.updateContent(response.responseText);
1663      if (Object.isFunction(onComplete)) onComplete(response, json);
1664    }).bind(this);
1665
1666    $super(url, options);
1667  },
1668
1669  updateContent: function(responseText) {
1670    var receiver = this.container[this.success() ? 'success' : 'failure'],
1671        options = this.options;
1672
1673    if (!options.evalScripts) responseText = responseText.stripScripts();
1674
1675    if (receiver = $(receiver)) {
1676      if (options.insertion) {
1677        if (Object.isString(options.insertion)) {
1678          var insertion = { }; insertion[options.insertion] = responseText;
1679          receiver.insert(insertion);
1680        }
1681        else options.insertion(receiver, responseText);
1682      }
1683      else receiver.update(responseText);
1684    }
1685  }
1686});
1687
1688Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1689  initialize: function($super, container, url, options) {
1690    $super(options);
1691    this.onComplete = this.options.onComplete;
1692
1693    this.frequency = (this.options.frequency || 2);
1694    this.decay = (this.options.decay || 1);
1695
1696    this.updater = { };
1697    this.container = container;
1698    this.url = url;
1699
1700    this.start();
1701  },
1702
1703  start: function() {
1704    this.options.onComplete = this.updateComplete.bind(this);
1705    this.onTimerEvent();
1706  },
1707
1708  stop: function() {
1709    this.updater.options.onComplete = undefined;
1710    clearTimeout(this.timer);
1711    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1712  },
1713
1714  updateComplete: function(response) {
1715    if (this.options.decay) {
1716      this.decay = (response.responseText == this.lastText ?
1717        this.decay * this.options.decay : 1);
1718
1719      this.lastText = response.responseText;
1720    }
1721    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1722  },
1723
1724  onTimerEvent: function() {
1725    this.updater = new Ajax.Updater(this.container, this.url, this.options);
1726  }
1727});
1728
1729
1730
1731function $(element) {
1732  if (arguments.length > 1) {
1733    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1734      elements.push($(arguments[i]));
1735    return elements;
1736  }
1737  if (Object.isString(element))
1738    element = document.getElementById(element);
1739  return Element.extend(element);
1740}
1741
1742if (Prototype.BrowserFeatures.XPath) {
1743  document._getElementsByXPath = function(expression, parentElement) {
1744    var results = [];
1745    var query = document.evaluate(expression, $(parentElement) || document,
1746      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1747    for (var i = 0, length = query.snapshotLength; i < length; i++)
1748      results.push(Element.extend(query.snapshotItem(i)));
1749    return results;
1750  };
1751}
1752
1753/*--------------------------------------------------------------------------*/
1754
1755if (!window.Node) var Node = { };
1756
1757if (!Node.ELEMENT_NODE) {
1758  Object.extend(Node, {
1759    ELEMENT_NODE: 1,
1760    ATTRIBUTE_NODE: 2,
1761    TEXT_NODE: 3,
1762    CDATA_SECTION_NODE: 4,
1763    ENTITY_REFERENCE_NODE: 5,
1764    ENTITY_NODE: 6,
1765    PROCESSING_INSTRUCTION_NODE: 7,
1766    COMMENT_NODE: 8,
1767    DOCUMENT_NODE: 9,
1768    DOCUMENT_TYPE_NODE: 10,
1769    DOCUMENT_FRAGMENT_NODE: 11,
1770    NOTATION_NODE: 12
1771  });
1772}
1773
1774
1775(function(global) {
1776
1777  var SETATTRIBUTE_IGNORES_NAME = (function(){
1778    var elForm = document.createElement("form");
1779    var elInput = document.createElement("input");
1780    var root = document.documentElement;
1781    elInput.setAttribute("name", "test");
1782    elForm.appendChild(elInput);
1783    root.appendChild(elForm);
1784    var isBuggy = elForm.elements
1785      ? (typeof elForm.elements.test == "undefined")
1786      : null;
1787    root.removeChild(elForm);
1788    elForm = elInput = null;
1789    return isBuggy;
1790  })();
1791
1792  var element = global.Element;
1793  global.Element = function(tagName, attributes) {
1794    attributes = attributes || { };
1795    tagName = tagName.toLowerCase();
1796    var cache = Element.cache;
1797    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
1798      tagName = '<' + tagName + ' name="' + attributes.name + '">';
1799      delete attributes.name;
1800      return Element.writeAttribute(document.createElement(tagName), attributes);
1801    }
1802    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1803    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
1804  };
1805  Object.extend(global.Element, element || { });
1806  if (element) global.Element.prototype = element.prototype;
1807})(this);
1808
1809Element.cache = { };
1810Element.idCounter = 1;
1811
1812Element.Methods = {
1813  visible: function(element) {
1814    return $(element).style.display != 'none';
1815  },
1816
1817  toggle: function(element) {
1818    element = $(element);
1819    Element[Element.visible(element) ? 'hide' : 'show'](element);
1820    return element;
1821  },
1822
1823
1824  hide: function(element) {
1825		// -- START -- WEBRA módosítások: 2014.08.05. BalintZ.
1826		if (isBootstrapEvent) {
1827			isBootstrapEvent = false;
1828			return;
1829		}
1830		// -- END -- WEBRA módosítások: 2014.08.05. BalintZ.
1831
1832		element = $(element);
1833    element.style.display = 'none';
1834    return element;
1835  },
1836
1837  show: function(element) {
1838    element = $(element);
1839    element.style.display = '';
1840    return element;
1841  },
1842
1843  remove: function(element) {
1844    element = $(element);
1845    element.parentNode.removeChild(element);
1846    return element;
1847  },
1848
1849  update: (function(){
1850
1851    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
1852      var el = document.createElement("select"),
1853          isBuggy = true;
1854      el.innerHTML = "<option value=\"test\">test</option>";
1855      if (el.options && el.options[0]) {
1856        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
1857      }
1858      el = null;
1859      return isBuggy;
1860    })();
1861
1862    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
1863      try {
1864        var el = document.createElement("table");
1865        if (el && el.tBodies) {
1866          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
1867          var isBuggy = typeof el.tBodies[0] == "undefined";
1868          el = null;
1869          return isBuggy;
1870        }
1871      } catch (e) {
1872        return true;
1873      }
1874    })();
1875
1876    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
1877      var s = document.createElement("script"),
1878          isBuggy = false;
1879      try {
1880        s.appendChild(document.createTextNode(""));
1881        isBuggy = !s.firstChild ||
1882          s.firstChild && s.firstChild.nodeType !== 3;
1883      } catch (e) {
1884        isBuggy = true;
1885      }
1886      s = null;
1887      return isBuggy;
1888    })();
1889
1890    function update(element, content) {
1891      element = $(element);
1892
1893      if (content && content.toElement)
1894        content = content.toElement();
1895
1896      if (Object.isElement(content))
1897        return element.update().insert(content);
1898
1899      content = Object.toHTML(content);
1900
1901      var tagName = element.tagName.toUpperCase();
1902
1903      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
1904        element.text = content;
1905        return element;
1906      }
1907
1908      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
1909        if (tagName in Element._insertionTranslations.tags) {
1910          while (element.firstChild) {
1911            element.removeChild(element.firstChild);
1912          }
1913          Element._getContentFromAnonymousElement(tagName, content.stripScripts())
1914            .each(function(node) {
1915              element.appendChild(node)
1916            });
1917        }
1918        else {
1919          element.innerHTML = content.stripScripts();
1920        }
1921      }
1922      else {
1923        element.innerHTML = content.stripScripts();
1924      }
1925
1926      content.evalScripts.bind(content).defer();
1927      return element;
1928    }
1929
1930    return update;
1931  })(),
1932
1933  replace: function(element, content) {
1934    element = $(element);
1935    if (content && content.toElement) content = content.toElement();
1936    else if (!Object.isElement(content)) {
1937      content = Object.toHTML(content);
1938      var range = element.ownerDocument.createRange();
1939      range.selectNode(element);
1940      content.evalScripts.bind(content).defer();
1941      content = range.createContextualFragment(content.stripScripts());
1942    }
1943    element.parentNode.replaceChild(content, element);
1944    return element;
1945  },
1946
1947  insert: function(element, insertions) {
1948    element = $(element);
1949
1950    if (Object.isString(insertions) || Object.isNumber(insertions) ||
1951        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
1952          insertions = {bottom:insertions};
1953
1954    var content, insert, tagName, childNodes;
1955
1956    for (var position in insertions) {
1957      content  = insertions[position];
1958      position = position.toLowerCase();
1959      insert = Element._insertionTranslations[position];
1960
1961      if (content && content.toElement) content = content.toElement();
1962      if (Object.isElement(content)) {
1963        insert(element, content);
1964        continue;
1965      }
1966
1967      content = Object.toHTML(content);
1968
1969      tagName = ((position == 'before' || position == 'after')
1970        ? element.parentNode : element).tagName.toUpperCase();
1971
1972      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
1973
1974      if (position == 'top' || position == 'after') childNodes.reverse();
1975      childNodes.each(insert.curry(element));
1976
1977      content.evalScripts.bind(content).defer();
1978    }
1979
1980    return element;
1981  },
1982
1983  wrap: function(element, wrapper, attributes) {
1984    element = $(element);
1985    if (Object.isElement(wrapper))
1986      $(wrapper).writeAttribute(attributes || { });
1987    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
1988    else wrapper = new Element('div', wrapper);
1989    if (element.parentNode)
1990      element.parentNode.replaceChild(wrapper, element);
1991    wrapper.appendChild(element);
1992    return wrapper;
1993  },
1994
1995  inspect: function(element) {
1996    element = $(element);
1997    var result = '<' + element.tagName.toLowerCase();
1998    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1999      var property = pair.first(), attribute = pair.last();
2000      var value = (element[property] || '').toString();
2001      if (value) result += ' ' + attribute + '=' + value.inspect(true);
2002    });
2003    return result + '>';
2004  },
2005
2006  recursivelyCollect: function(element, property) {
2007    element = $(element);
2008    var elements = [];
2009    while (element = element[property])
2010      if (element.nodeType == 1)
2011        elements.push(Element.extend(element));
2012    return elements;
2013  },
2014
2015  ancestors: function(element) {
2016    return Element.recursivelyCollect(element, 'parentNode');
2017  },
2018
2019  descendants: function(element) {
2020    return Element.select(element, "*");
2021  },
2022
2023  firstDescendant: function(element) {
2024    element = $(element).firstChild;
2025    while (element && element.nodeType != 1) element = element.nextSibling;
2026    return $(element);
2027  },
2028
2029  immediateDescendants: function(element) {
2030    if (!(element = $(element).firstChild)) return [];
2031    while (element && element.nodeType != 1) element = element.nextSibling;
2032    if (element) return [element].concat($(element).nextSiblings());
2033    return [];
2034  },
2035
2036  previousSiblings: function(element) {
2037    return Element.recursivelyCollect(element, 'previousSibling');
2038  },
2039
2040  nextSiblings: function(element) {
2041    return Element.recursivelyCollect(element, 'nextSibling');
2042  },
2043
2044  siblings: function(element) {
2045    element = $(element);
2046    return Element.previousSiblings(element).reverse()
2047      .concat(Element.nextSiblings(element));
2048  },
2049
2050  match: function(element, selector) {
2051    if (Object.isString(selector))
2052      selector = new Selector(selector);
2053    return selector.match($(element));
2054  },
2055
2056  up: function(element, expression, index) {
2057    element = $(element);
2058    if (arguments.length == 1) return $(element.parentNode);
2059    var ancestors = Element.ancestors(element);
2060    return Object.isNumber(expression) ? ancestors[expression] :
2061      Selector.findElement(ancestors, expression, index);
2062  },
2063
2064  down: function(element, expression, index) {
2065    element = $(element);
2066    if (arguments.length == 1) return Element.firstDescendant(element);
2067    return Object.isNumber(expression) ? Element.descendants(element)[expression] :
2068      Element.select(element, expression)[index || 0];
2069  },
2070
2071  previous: function(element, expression, index) {
2072    element = $(element);
2073    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
2074    var previousSiblings = Element.previousSiblings(element);
2075    return Object.isNumber(expression) ? previousSiblings[expression] :
2076      Selector.findElement(previousSiblings, expression, index);
2077  },
2078
2079  next: function(element, expression, index) {
2080    element = $(element);
2081    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
2082    var nextSiblings = Element.nextSiblings(element);
2083    return Object.isNumber(expression) ? nextSiblings[expression] :
2084      Selector.findElement(nextSiblings, expression, index);
2085  },
2086
2087
2088  select: function(element) {
2089    var args = Array.prototype.slice.call(arguments, 1);
2090    return Selector.findChildElements(element, args);
2091  },
2092
2093  adjacent: function(element) {
2094    var args = Array.prototype.slice.call(arguments, 1);
2095    return Selector.findChildElements(element.parentNode, args).without(element);
2096  },
2097
2098  identify: function(element) {
2099    element = $(element);
2100    var id = Element.readAttribute(element, 'id');
2101    if (id) return id;
2102    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
2103    Element.writeAttribute(element, 'id', id);
2104    return id;
2105  },
2106
2107  readAttribute: function(element, name) {
2108    element = $(element);
2109    if (Prototype.Browser.IE) {
2110      var t = Element._attributeTranslations.read;
2111      if (t.values[name]) return t.values[name](element, name);
2112      if (t.names[name]) name = t.names[name];
2113      if (name.include(':')) {
2114        return (!element.attributes || !element.attributes[name]) ? null :
2115         element.attributes[name].value;
2116      }
2117    }
2118    return element.getAttribute(name);
2119  },
2120
2121  writeAttribute: function(element, name, value) {
2122    element = $(element);
2123    var attributes = { }, t = Element._attributeTranslations.write;
2124
2125    if (typeof name == 'object') attributes = name;
2126    else attributes[name] = Object.isUndefined(value) ? true : value;
2127
2128    for (var attr in attributes) {
2129      name = t.names[attr] || attr;
2130      value = attributes[attr];
2131      if (t.values[attr]) name = t.values[attr](element, value);
2132      if (value === false || value === null)
2133        element.removeAttribute(name);
2134      else if (value === true)
2135        element.setAttribute(name, name);
2136      else element.setAttribute(name, value);
2137    }
2138    return element;
2139  },
2140
2141  getHeight: function(element) {
2142    return Element.getDimensions(element).height;
2143  },
2144
2145  getWidth: function(element) {
2146    return Element.getDimensions(element).width;
2147  },
2148
2149  classNames: function(element) {
2150    return new Element.ClassNames(element);
2151  },
2152
2153  hasClassName: function(element, className) {
2154    if (!(element = $(element))) return;
2155    var elementClassName = element.className;
2156    return (elementClassName.length > 0 && (elementClassName == className ||
2157      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
2158  },
2159
2160  addClassName: function(element, className) {
2161    if (!(element = $(element))) return;
2162    if (!Element.hasClassName(element, className))
2163      element.className += (element.className ? ' ' : '') + className;
2164    return element;
2165  },
2166
2167  removeClassName: function(element, className) {
2168    if (!(element = $(element))) return;
2169    element.className = element.className.replace(
2170      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
2171    return element;
2172  },
2173
2174  toggleClassName: function(element, className) {
2175    if (!(element = $(element))) return;
2176    return Element[Element.hasClassName(element, className) ?
2177      'removeClassName' : 'addClassName'](element, className);
2178  },
2179
2180  cleanWhitespace: function(element) {
2181    element = $(element);
2182    var node = element.firstChild;
2183    while (node) {
2184      var nextNode = node.nextSibling;
2185      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
2186        element.removeChild(node);
2187      node = nextNode;
2188    }
2189    return element;
2190  },
2191
2192  empty: function(element) {
2193    return $(element).innerHTML.blank();
2194  },
2195
2196  descendantOf: function(element, ancestor) {
2197    element = $(element), ancestor = $(ancestor);
2198
2199    if (element.compareDocumentPosition)
2200      return (element.compareDocumentPosition(ancestor) & 8) === 8;
2201
2202    if (ancestor.contains)
2203      return ancestor.contains(element) && ancestor !== element;
2204
2205    while (element = element.parentNode)
2206      if (element == ancestor) return true;
2207
2208    return false;
2209  },
2210
2211  scrollTo: function(element) {
2212    element = $(element);
2213    var pos = Element.cumulativeOffset(element);
2214    window.scrollTo(pos[0], pos[1]);
2215    return element;
2216  },
2217
2218  getStyle: function(element, style) {
2219    element = $(element);
2220    style = style == 'float' ? 'cssFloat' : style.camelize();
2221    var value = element.style[style];
2222    if (!value || value == 'auto') {
2223      var css = document.defaultView.getComputedStyle(element, null);
2224      value = css ? css[style] : null;
2225    }
2226    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
2227    return value == 'auto' ? null : value;
2228  },
2229
2230  getOpacity: function(element) {
2231    return $(element).getStyle('opacity');
2232  },
2233
2234  setStyle: function(element, styles) {
2235    element = $(element);
2236    var elementStyle = element.style, match;
2237    if (Object.isString(styles)) {
2238      element.style.cssText += ';' + styles;
2239      return styles.include('opacity') ?
2240        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
2241    }
2242    for (var property in styles)
2243      if (property == 'opacity') element.setOpacity(styles[property]);
2244      else
2245        elementStyle[(property == 'float' || property == 'cssFloat') ?
2246          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
2247            property] = styles[property];
2248
2249    return element;
2250  },
2251
2252  setOpacity: function(element, value) {
2253    element = $(element);
2254    element.style.opacity = (value == 1 || value === '') ? '' :
2255      (value < 0.00001) ? 0 : value;
2256    return element;
2257  },
2258
2259  getDimensions: function(element) {
2260    element = $(element);
2261    var display = Element.getStyle(element, 'display');
2262    if (display != 'none' && display != null) // Safari bug
2263      return {width: element.offsetWidth, height: element.offsetHeight};
2264
2265    var els = element.style;
2266    var originalVisibility = els.visibility;
2267    var originalPosition = els.position;
2268    var originalDisplay = els.display;
2269    els.visibility = 'hidden';
2270    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
2271      els.position = 'absolute';
2272    els.display = 'block';
2273    var originalWidth = element.clientWidth;
2274    var originalHeight = element.clientHeight;
2275    els.display = originalDisplay;
2276    els.position = originalPosition;
2277    els.visibility = originalVisibility;
2278    return {width: originalWidth, height: originalHeight};
2279  },
2280
2281  makePositioned: function(element) {
2282    element = $(element);
2283    var pos = Element.getStyle(element, 'position');
2284    if (pos == 'static' || !pos) {
2285      element._madePositioned = true;
2286      element.style.position = 'relative';
2287      if (Prototype.Browser.Opera) {
2288        element.style.top = 0;
2289        element.style.left = 0;
2290      }
2291    }
2292    return element;
2293  },
2294
2295  undoPositioned: function(element) {
2296    element = $(element);
2297    if (element._madePositioned) {
2298      element._madePositioned = undefined;
2299      element.style.position =
2300        element.style.top =
2301        element.style.left =
2302        element.style.bottom =
2303        element.style.right = '';
2304    }
2305    return element;
2306  },
2307
2308  makeClipping: function(element) {
2309    element = $(element);
2310    if (element._overflow) return element;
2311    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
2312    if (element._overflow !== 'hidden')
2313      element.style.overflow = 'hidden';
2314    return element;
2315  },
2316
2317  undoClipping: function(element) {
2318    element = $(element);
2319    if (!element._overflow) return element;
2320    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
2321    element._overflow = null;
2322    return element;
2323  },
2324
2325  cumulativeOffset: function(element) {
2326    var valueT = 0, valueL = 0;
2327    do {
2328      valueT += element.offsetTop  || 0;
2329      valueL += element.offsetLeft || 0;
2330      element = element.offsetParent;
2331    } while (element);
2332    return Element._returnOffset(valueL, valueT);
2333  },
2334
2335  positionedOffset: function(element) {
2336    var valueT = 0, valueL = 0;
2337    do {
2338      valueT += element.offsetTop  || 0;
2339      valueL += element.offsetLeft || 0;
2340      element = element.offsetParent;
2341      if (element) {
2342        if (element.tagName.toUpperCase() == 'BODY') break;
2343        var p = Element.getStyle(element, 'position');
2344        if (p !== 'static') break;
2345      }
2346    } while (element);
2347    return Element._returnOffset(valueL, valueT);
2348  },
2349
2350  absolutize: function(element) {
2351    element = $(element);
2352    if (Element.getStyle(element, 'position') == 'absolute') return element;
2353
2354    var offsets = Element.positionedOffset(element);
2355    var top     = offsets[1];
2356    var left    = offsets[0];
2357    var width   = element.clientWidth;
2358    var height  = element.clientHeight;
2359
2360    element._originalLeft   = left - parseFloat(element.style.left  || 0);
2361    element._originalTop    = top  - parseFloat(element.style.top || 0);
2362    element._originalWidth  = element.style.width;
2363    element._originalHeight = element.style.height;
2364
2365    element.style.position = 'absolute';
2366    element.style.top    = top + 'px';
2367    element.style.left   = left + 'px';
2368    element.style.width  = width + 'px';
2369    element.style.height = height + 'px';
2370    return element;
2371  },
2372
2373  relativize: function(element) {
2374    element = $(element);
2375    if (Element.getStyle(element, 'position') == 'relative') return element;
2376
2377    element.style.position = 'relative';
2378    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
2379    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
2380
2381    element.style.top    = top + 'px';
2382    element.style.left   = left + 'px';
2383    element.style.height = element._originalHeight;
2384    element.style.width  = element._originalWidth;
2385    return element;
2386  },
2387
2388  cumulativeScrollOffset: function(element) {
2389    var valueT = 0, valueL = 0;
2390    do {
2391      valueT += element.scrollTop  || 0;
2392      valueL += element.scrollLeft || 0;
2393      element = element.parentNode;
2394    } while (element);
2395    return Element._returnOffset(valueL, valueT);
2396  },
2397
2398  getOffsetParent: function(element) {
2399	//if (element.offsetParent) return $(element.offsetParent);
2400	// WEBRA - IE8 bugfix - nem lathato elemnel az offsetParent értéke a document.body null helyett. 
2401	if (element.offsetParent && Element.visible(element)) return $(element.offsetParent); // IE8 bugfix - AITIA
2402    if (element == document.body) return $(element);
2403
2404    while ((element = element.parentNode) && element != document.body)
2405      if (Element.getStyle(element, 'position') != 'static')
2406        return $(element);
2407
2408    return $(document.body);
2409  },
2410
2411  viewportOffset: function(forElement) {
2412    var valueT = 0, valueL = 0;
2413
2414    var element = forElement;
2415    do {
2416      valueT += element.offsetTop  || 0;
2417      valueL += element.offsetLeft || 0;
2418
2419      if (element.offsetParent == document.body &&
2420        Element.getStyle(element, 'position') == 'absolute') break;
2421
2422    } while (element = element.offsetParent);
2423
2424    element = forElement;
2425    do {
2426      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
2427        valueT -= element.scrollTop  || 0;
2428        valueL -= element.scrollLeft || 0;
2429      }
2430    } while (element = element.parentNode);
2431
2432    return Element._returnOffset(valueL, valueT);
2433  },
2434
2435  clonePosition: function(element, source) {
2436    var options = Object.extend({
2437      setLeft:    true,
2438      setTop:     true,
2439      setWidth:   true,
2440      setHeight:  true,
2441      offsetTop:  0,
2442      offsetLeft: 0
2443    }, arguments[2] || { });
2444
2445    source = $(source);
2446    var p = Element.viewportOffset(source);
2447
2448    element = $(element);
2449    var delta = [0, 0];
2450    var parent = null;
2451    if (Element.getStyle(element, 'position') == 'absolute') {
2452      parent = Element.getOffsetParent(element);
2453      delta = Element.viewportOffset(parent);
2454    }
2455
2456    if (parent == document.body) {
2457      delta[0] -= document.body.offsetLeft;
2458      delta[1] -= document.body.offsetTop;
2459    }
2460
2461    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
2462    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
2463    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
2464    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
2465    return element;
2466  }
2467};
2468
2469Object.extend(Element.Methods, {
2470  getElementsBySelector: Element.Methods.select,
2471
2472  childElements: Element.Methods.immediateDescendants
2473});
2474
2475Element._attributeTranslations = {
2476  write: {
2477    names: {
2478      className: 'class',
2479      htmlFor:   'for'
2480    },
2481    values: { }
2482  }
2483};
2484
2485if (Prototype.Browser.Opera) {
2486  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2487    function(proceed, element, style) {
2488      switch (style) {
2489        case 'left': case 'top': case 'right': case 'bottom':
2490          if (proceed(element, 'position') === 'static') return null;
2491        case 'height': case 'width':
2492          if (!Element.visible(element)) return null;
2493
2494          var dim = parseInt(proceed(element, style), 10);
2495
2496          if (dim !== element['offset' + style.capitalize()])
2497            return dim + 'px';
2498
2499          var properties;
2500          if (style === 'height') {
2501            properties = ['border-top-width', 'padding-top',
2502             'padding-bottom', 'border-bottom-width'];
2503          }
2504          else {
2505            properties = ['border-left-width', 'padding-left',
2506             'padding-right', 'border-right-width'];
2507          }
2508          return properties.inject(dim, function(memo, property) {
2509            var val = proceed(element, property);
2510            return val === null ? memo : memo - parseInt(val, 10);
2511          }) + 'px';
2512        default: return proceed(element, style);
2513      }
2514    }
2515  );
2516
2517  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2518    function(proceed, element, attribute) {
2519      if (attribute === 'title') return element.title;
2520      return proceed(element, attribute);
2521    }
2522  );
2523}
2524
2525else if (Prototype.Browser.IE) {
2526  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
2527    function(proceed, element) {
2528      element = $(element);
2529      try { element.offsetParent }
2530      catch(e) { return $(document.body) }
2531      var position = element.getStyle('position');
2532      if (position !== 'static') return proceed(element);
2533      element.setStyle({ position: 'relative' });
2534      var value = proceed(element);
2535      element.setStyle({ position: position });
2536      return value;
2537    }
2538  );
2539
2540  $w('positionedOffset viewportOffset').each(function(method) {
2541    Element.Methods[method] = Element.Methods[method].wrap(
2542      function(proceed, element) {
2543        element = $(element);
2544        try { element.offsetParent }
2545        catch(e) { return Element._returnOffset(0,0) }
2546        var position = element.getStyle('position');
2547        if (position !== 'static') return proceed(element);
2548        var offsetParent = element.getOffsetParent();
2549        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
2550          offsetParent.setStyle({ zoom: 1 });
2551        element.setStyle({ position: 'relative' });
2552        var value = proceed(element);
2553        element.setStyle({ position: position });
2554        return value;
2555      }
2556    );
2557  });
2558
2559  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
2560    function(proceed, element) {
2561      try { element.offsetParent }
2562      catch(e) { return Element._returnOffset(0,0) }
2563      return proceed(element);
2564    }
2565  );
2566
2567  Element.Methods.getStyle = function(element, style) {
2568    element = $(element);
2569    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
2570    var value = element.style[style];
2571    if (!value && element.currentStyle) value = element.currentStyle[style];
2572
2573    if (style == 'opacity') {
2574      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
2575        if (value[1]) return parseFloat(value[1]) / 100;
2576      return 1.0;
2577    }
2578
2579    if (value == 'auto') {
2580      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
2581        return element['offset' + style.capitalize()] + 'px';
2582      return null;
2583    }
2584    return value;
2585  };
2586
2587  Element.Methods.setOpacity = function(element, value) {
2588    function stripAlpha(filter){
2589      return filter.replace(/alpha\([^\)]*\)/gi,'');
2590    }
2591    element = $(element);
2592    var currentStyle = element.currentStyle;
2593    if ((currentStyle && !currentStyle.hasLayout) ||
2594      (!currentStyle && element.style.zoom == 'normal'))
2595        element.style.zoom = 1;
2596
2597    var filter = element.getStyle('filter'), style = element.style;
2598    if (value == 1 || value === '') {
2599      (filter = stripAlpha(filter)) ?
2600        style.filter = filter : style.removeAttribute('filter');
2601      return element;
2602    } else if (value < 0.00001) value = 0;
2603    style.filter = stripAlpha(filter) +
2604      'alpha(opacity=' + (value * 100) + ')';
2605    return element;
2606  };
2607
2608  Element._attributeTranslations = (function(){
2609
2610    var classProp = 'className';
2611    var forProp = 'for';
2612
2613    var el = document.createElement('div');
2614
2615    el.setAttribute(classProp, 'x');
2616
2617    if (el.className !== 'x') {
2618      el.setAttribute('class', 'x');
2619      if (el.className === 'x') {
2620        classProp = 'class';
2621      }
2622    }
2623    el = null;
2624
2625    el = document.createElement('label');
2626    el.setAttribute(forProp, 'x');
2627    if (el.htmlFor !== 'x') {
2628      el.setAttribute('htmlFor', 'x');
2629      if (el.htmlFor === 'x') {
2630        forProp = 'htmlFor';
2631      }
2632    }
2633    el = null;
2634
2635    return {
2636      read: {
2637        names: {
2638          'class':      classProp,
2639          'className':  classProp,
2640          'for':        forProp,
2641          'htmlFor':    forProp
2642        },
2643        values: {
2644          _getAttr: function(element, attribute) {
2645            return element.getAttribute(attribute);
2646          },
2647          _getAttr2: function(element, attribute) {
2648            return element.getAttribute(attribute, 2);
2649          },
2650          _getAttrNode: function(element, attribute) {
2651            var node = element.getAttributeNode(attribute);
2652            return node ? node.value : "";
2653          },
2654          _getEv: (function(){
2655
2656            var el = document.createElement('div');
2657            el.onclick = Prototype.emptyFunction;
2658            var value = el.getAttribute('onclick');
2659            var f;
2660
2661            if (String(value).indexOf('{') > -1) {
2662              f = function(element, attribute) {
2663                attribute = element.getAttribute(attribute);
2664                if (!attribute) return null;
2665                attribute = attribute.toString();
2666                attribute = attribute.split('{')[1];
2667                attribute = attribute.split('}')[0];
2668                return attribute.strip();
2669              };
2670            }
2671            else if (value === '') {
2672              f = function(element, attribute) {
2673                attribute = element.getAttribute(attribute);
2674                if (!attribute) return null;
2675                return attribute.strip();
2676              };
2677            }
2678            el = null;
2679            return f;
2680          })(),
2681          _flag: function(element, attribute) {
2682            return $(element).hasAttribute(attribute) ? attribute : null;
2683          },
2684          style: function(element) {
2685            return element.style.cssText.toLowerCase();
2686          },
2687          title: function(element) {
2688            return element.title;
2689          }
2690        }
2691      }
2692    }
2693  })();
2694
2695  Element._attributeTranslations.write = {
2696    names: Object.extend({
2697      cellpadding: 'cellPadding',
2698      cellspacing: 'cellSpacing'
2699    }, Element._attributeTranslations.read.names),
2700    values: {
2701      checked: function(element, value) {
2702        element.checked = !!value;
2703      },
2704
2705      style: function(element, value) {
2706        element.style.cssText = value ? value : '';
2707      }
2708    }
2709  };
2710
2711  Element._attributeTranslations.has = {};
2712
2713  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
2714      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
2715    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
2716    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
2717  });
2718
2719  (function(v) {
2720    Object.extend(v, {
2721      href:        v._getAttr2,
2722      src:         v._getAttr2,
2723      type:        v._getAttr,
2724      action:      v._getAttrNode,
2725      disabled:    v._flag,
2726      checked:     v._flag,
2727      readonly:    v._flag,
2728      multiple:    v._flag,
2729      onload:      v._getEv,
2730      onunload:    v._getEv,
2731      onclick:     v._getEv,
2732      ondblclick:  v._getEv,
2733      onmousedown: v._getEv,
2734      onmouseup:   v._getEv,
2735      onmouseover: v._getEv,
2736      onmousemove: v._getEv,
2737      onmouseout:  v._getEv,
2738      onfocus:     v._getEv,
2739      onblur:      v._getEv,
2740      onkeypress:  v._getEv,
2741      onkeydown:   v._getEv,
2742      onkeyup:     v._getEv,
2743      onsubmit:    v._getEv,
2744      onreset:     v._getEv,
2745      onselect:    v._getEv,
2746      onchange:    v._getEv
2747    });
2748  })(Element._attributeTranslations.read.values);
2749
2750  if (Prototype.BrowserFeatures.ElementExtensions) {
2751    (function() {
2752      function _descendants(element) {
2753        var nodes = element.getElementsByTagName('*'), results = [];
2754        for (var i = 0, node; node = nodes[i]; i++)
2755          if (node.tagName !== "!") // Filter out comment nodes.
2756            results.push(node);
2757        return results;
2758      }
2759
2760      Element.Methods.down = function(element, expression, index) {
2761        element = $(element);
2762        if (arguments.length == 1) return element.firstDescendant();
2763        return Object.isNumber(expression) ? _descendants(element)[expression] :
2764          Element.select(element, expression)[index || 0];
2765      }
2766    })();
2767  }
2768
2769}
2770
2771else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
2772  Element.Methods.setOpacity = function(element, value) {
2773    element = $(element);
2774    element.style.opacity = (value == 1) ? 0.999999 :
2775      (value === '') ? '' : (value < 0.00001) ? 0 : value;
2776    return element;
2777  };
2778}
2779
2780else if (Prototype.Browser.WebKit) {
2781  Element.Methods.setOpacity = function(element, value) {
2782    element = $(element);
2783    element.style.opacity = (value == 1 || value === '') ? '' :
2784      (value < 0.00001) ? 0 : value;
2785
2786    if (value == 1)
2787      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
2788        element.width++; element.width--;
2789      } else try {
2790        var n = document.createTextNode(' ');
2791        element.appendChild(n);
2792        element.removeChild(n);
2793      } catch (e) { }
2794
2795    return element;
2796  };
2797
2798  Element.Methods.cumulativeOffset = function(element) {
2799    var valueT = 0, valueL = 0;
2800    do {
2801      valueT += element.offsetTop  || 0;
2802      valueL += element.offsetLeft || 0;
2803      if (element.offsetParent == document.body)
2804        if (Element.getStyle(element, 'position') == 'absolute') break;
2805
2806      element = element.offsetParent;
2807    } while (element);
2808
2809    return Element._returnOffset(valueL, valueT);
2810  };
2811}
2812
2813if ('outerHTML' in document.documentElement) {
2814  Element.Methods.replace = function(element, content) {
2815    element = $(element);
2816
2817    if (content && content.toElement) content = content.toElement();
2818    if (Object.isElement(content)) {
2819      element.parentNode.replaceChild(content, element);
2820      return element;
2821    }
2822
2823    content = Object.toHTML(content);
2824    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2825
2826    if (Element._insertionTranslations.tags[tagName]) {
2827      var nextSibling = element.next();
2828      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2829      parent.removeChild(element);
2830      if (nextSibling)
2831        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
2832      else
2833        fragments.each(function(node) { parent.appendChild(node) });
2834    }
2835    else element.outerHTML = content.stripScripts();
2836
2837    content.evalScripts.bind(content).defer();
2838    return element;
2839  };
2840}
2841
2842Element._returnOffset = function(l, t) {
2843  var result = [l, t];
2844  result.left = l;
2845  result.top = t;
2846  return result;
2847};
2848
2849Element._getContentFromAnonymousElement = function(tagName, html) {
2850  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
2851  if (t) {
2852    div.innerHTML = t[0] + html + t[1];
2853    t[2].times(function() { div = div.firstChild });
2854  } else div.innerHTML = html;
2855  return $A(div.childNodes);
2856};
2857
2858Element._insertionTranslations = {
2859  before: function(element, node) {
2860    element.parentNode.insertBefore(node, element);
2861  },
2862  top: function(element, node) {
2863    element.insertBefore(node, element.firstChild);
2864  },
2865  bottom: function(element, node) {
2866    element.appendChild(node);
2867  },
2868  after: function(element, node) {
2869    element.parentNode.insertBefore(node, element.nextSibling);
2870  },
2871  tags: {
2872    TABLE:  ['<table>',                '</table>',                   1],
2873    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
2874    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
2875    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2876    SELECT: ['<select>',               '</select>',                  1]
2877  }
2878};
2879
2880(function() {
2881  var tags = Element._insertionTranslations.tags;
2882  Object.extend(tags, {
2883    THEAD: tags.TBODY,
2884    TFOOT: tags.TBODY,
2885    TH:    tags.TD
2886  });
2887})();
2888
2889Element.Methods.Simulated = {
2890  hasAttribute: function(element, attribute) {
2891    attribute = Element._attributeTranslations.has[attribute] || attribute;
2892    var node = $(element).getAttributeNode(attribute);
2893    return !!(node && node.specified);
2894  }
2895};
2896
2897Element.Methods.ByTag = { };
2898
2899Object.extend(Element, Element.Methods);
2900
2901(function(div) {
2902
2903  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
2904    window.HTMLElement = { };
2905    window.HTMLElement.prototype = div['__proto__'];
2906    Prototype.BrowserFeatures.ElementExtensions = true;
2907  }
2908
2909  div = null;
2910
2911})(document.createElement('div'))
2912
2913Element.extend = (function() {
2914
2915  function checkDeficiency(tagName) {
2916    if (typeof window.Element != 'undefined') {
2917      var proto = window.Element.prototype;
2918      if (proto) {
2919        var id = '_' + (Math.random()+'').slice(2);
2920        var el = document.createElement(tagName);
2921        proto[id] = 'x';
2922        var isBuggy = (el[id] !== 'x');
2923        delete proto[id];
2924        el = null;
2925        return isBuggy;
2926      }
2927    }
2928    return false;
2929  }
2930
2931  function extendElementWith(element, methods) {
2932    for (var property in methods) {
2933      var value = methods[property];
2934      if (Object.isFunction(value) && !(property in element))
2935        element[property] = value.methodize();
2936    }
2937  }
2938
2939  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
2940
2941  if (Prototype.BrowserFeatures.SpecificElementExtensions) {
2942    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
2943      return function(element) {
2944        if (element && typeof element._extendedByPrototype == 'undefined') {
2945          var t = element.tagName;
2946          if (t && (/^(?:object|applet|embed)$/i.test(t))) {
2947            extendElementWith(element, Element.Methods);
2948            extendElementWith(element, Element.Methods.Simulated);
2949            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
2950          }
2951        }
2952        return element;
2953      }
2954    }
2955    return Prototype.K;
2956  }
2957
2958  var Methods = { }, ByTag = Element.Methods.ByTag;
2959
2960  var extend = Object.extend(function(element) {
2961    if (!element || typeof element._extendedByPrototype != 'undefined' ||
2962        element.nodeType != 1 || element == window) return element;
2963
2964    var methods = Object.clone(Methods),
2965        tagName = element.tagName.toUpperCase();
2966
2967    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2968
2969    extendElementWith(element, methods);
2970
2971    element._extendedByPrototype = Prototype.emptyFunction;
2972    return element;
2973
2974  }, {
2975    refresh: function() {
2976      if (!Prototype.BrowserFeatures.ElementExtensions) {
2977        Object.extend(Methods, Element.Methods);
2978        Object.extend(Methods, Element.Methods.Simulated);
2979      }
2980    }
2981  });
2982
2983  extend.refresh();
2984  return extend;
2985})();
2986
2987Element.hasAttribute = function(element, attribute) {
2988  if (element.hasAttribute) return element.hasAttribute(attribute);
2989  return Element.Methods.Simulated.hasAttribute(element, attribute);
2990};
2991
2992Element.addMethods = function(methods) {
2993  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
2994
2995  if (!methods) {
2996    Object.extend(Form, Form.Methods);
2997    Object.extend(Form.Element, Form.Element.Methods);
2998    Object.extend(Element.Methods.ByTag, {
2999      "FORM":     Object.clone(Form.Methods),
3000      "INPUT":    Object.clone(Form.Element.Methods),
3001      "SELECT":   Object.clone(Form.Element.Methods),
3002      "TEXTAREA": Object.clone(Form.Element.Methods)
3003    });
3004  }
3005
3006  if (arguments.length == 2) {
3007    var tagName = methods;
3008    methods = arguments[1];
3009  }
3010
3011  if (!tagName) Object.extend(Element.Methods, methods || { });
3012  else {
3013    if (Object.isArray(tagName)) tagName.each(extend);
3014    else extend(tagName);
3015  }
3016
3017  function extend(tagName) {
3018    tagName = tagName.toUpperCase();
3019    if (!Element.Methods.ByTag[tagName])
3020      Element.Methods.ByTag[tagName] = { };
3021    Object.extend(Element.Methods.ByTag[tagName], methods);
3022  }
3023
3024  function copy(methods, destination, onlyIfAbsent) {
3025    onlyIfAbsent = onlyIfAbsent || false;
3026    for (var property in methods) {
3027      var value = methods[property];
3028      if (!Object.isFunction(value)) continue;
3029      if (!onlyIfAbsent || !(property in destination))
3030        destination[property] = value.methodize();
3031    }
3032  }
3033
3034  function findDOMClass(tagName) {
3035    var klass;
3036    var trans = {
3037      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3038      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3039      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3040      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3041      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3042      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3043      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3044      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3045      "FrameSet", "IFRAME": "IFrame"
3046    };
3047    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3048    if (window[klass]) return window[klass];
3049    klass = 'HTML' + tagName + 'Element';
3050    if (window[klass]) return window[klass];
3051    klass = 'HTML' + tagName.capitalize() + 'Element';
3052    if (window[klass]) return window[klass];
3053
3054    var element = document.createElement(tagName);
3055    var proto = element['__proto__'] || element.constructor.prototype;
3056    element = null;
3057    return proto;
3058  }
3059
3060  var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
3061   Element.prototype;
3062
3063  if (F.ElementExtensions) {
3064    copy(Element.Methods, elementPrototype);
3065    copy(Element.Methods.Simulated, elementPrototype, true);
3066  }
3067
3068  if (F.SpecificElementExtensions) {
3069    for (var tag in Element.Methods.ByTag) {
3070      var klass = findDOMClass(tag);
3071      if (Object.isUndefined(klass)) continue;
3072      copy(T[tag], klass.prototype);
3073    }
3074  }
3075
3076  Object.extend(Element, Element.Methods);
3077  delete Element.ByTag;
3078
3079  if (Element.extend.refresh) Element.extend.refresh();
3080  Element.cache = { };
3081};
3082
3083
3084document.viewport = {
3085
3086  getDimensions: function() {
3087    return { width: this.getWidth(), height: this.getHeight() };
3088  },
3089
3090  getScrollOffsets: function() {
3091    return Element._returnOffset(
3092      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
3093      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop);
3094  }
3095};
3096
3097(function(viewport) {
3098  var B = Prototype.Browser, doc = document, element, property = {};
3099
3100  function getRootElement() {
3101    if (B.WebKit && !doc.evaluate)
3102      return document;
3103
3104    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
3105      return document.body;
3106
3107    return document.documentElement;
3108  }
3109
3110  function define(D) {
3111    if (!element) element = getRootElement();
3112
3113    property[D] = 'client' + D;
3114
3115    viewport['get' + D] = function() { return element[property[D]] };
3116    return viewport['get' + D]();
3117  }
3118
3119  viewport.getWidth  = define.curry('Width');
3120
3121  viewport.getHeight = define.curry('Height');
3122})(document.viewport);
3123
3124
3125Element.Storage = {
3126  UID: 1
3127};
3128
3129Element.addMethods({
3130  getStorage: function(element) {
3131    if (!(element = $(element))) return;
3132
3133    var uid;
3134    if (element === window) {
3135      uid = 0;
3136    } else {
3137      if (typeof element._prototypeUID === "undefined")
3138        element._prototypeUID = [Element.Storage.UID++];
3139      uid = element._prototypeUID[0];
3140    }
3141
3142    if (!Element.Storage[uid])
3143      Element.Storage[uid] = $H();
3144
3145    return Element.Storage[uid];
3146  },
3147
3148  store: function(element, key, value) {
3149    if (!(element = $(element))) return;
3150
3151    if (arguments.length === 2) {
3152      Element.getStorage(element).update(key);
3153    } else {
3154      Element.getStorage(element).set(key, value);
3155    }
3156
3157    return element;
3158  },
3159
3160  retrieve: function(element, key, defaultValue) {
3161    if (!(element = $(element))) return;
3162    var hash = Element.getStorage(element), value = hash.get(key);
3163
3164    if (Object.isUndefined(value)) {
3165      hash.set(key, defaultValue);
3166      value = defaultValue;
3167    }
3168
3169    return value;
3170  },
3171
3172  clone: function(element, deep) {
3173    if (!(element = $(element))) return;
3174    var clone = element.cloneNode(deep);
3175    clone._prototypeUID = void 0;
3176    if (deep) {
3177      var descendants = Element.select(clone, '*'),
3178          i = descendants.length;
3179      while (i--) {
3180        descendants[i]._prototypeUID = void 0;
3181      }
3182    }
3183    return Element.extend(clone);
3184  }
3185});
3186/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
3187 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
3188 * license.  Please see http://www.yui-ext.com/ for more information. */
3189
3190var Selector = Class.create({
3191  initialize: function(expression) {
3192    this.expression = expression.strip();
3193
3194    if (this.shouldUseSelectorsAPI()) {
3195      this.mode = 'selectorsAPI';
3196    } else if (this.shouldUseXPath()) {
3197      this.mode = 'xpath';
3198      this.compileXPathMatcher();
3199    } else {
3200      this.mode = "normal";
3201      this.compileMatcher();
3202    }
3203
3204  },
3205
3206  shouldUseXPath: (function() {
3207
3208    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
3209      var isBuggy = false;
3210      if (document.evaluate && window.XPathResult) {
3211        var el = document.createElement('div');
3212        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';
3213
3214        var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
3215          "//*[local-name()='li' or local-name()='LI']";
3216
3217        var result = document.evaluate(xpath, el, null,
3218          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
3219
3220        isBuggy = (result.snapshotLength !== 2);
3221        el = null;
3222      }
3223      return isBuggy;
3224    })();
3225
3226    return function() {
3227      if (!Prototype.BrowserFeatures.XPath) return false;
3228
3229      var e = this.expression;
3230
3231      if (Prototype.Browser.WebKit &&
3232       (e.include("-of-type") || e.include(":empty")))
3233        return false;
3234
3235      if ((/(\[[\w-]*?:|:checked)/).test(e))
3236        return false;
3237
3238      if (IS_DESCENDANT_SELECTOR_BUGGY) return false;
3239
3240      return true;
3241    }
3242
3243  })(),
3244
3245  shouldUseSelectorsAPI: function() {
3246    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
3247
3248    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;
3249
3250    if (!Selector._div) Selector._div = new Element('div');
3251
3252    try {
3253      Selector._div.querySelector(this.expression);
3254    } catch(e) {
3255      return false;
3256    }
3257
3258    return true;
3259  },
3260
3261  compileMatcher: function() {
3262    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
3263        c = Selector.criteria, le, p, m, len = ps.length, name;
3264
3265    if (Selector._cache[e]) {
3266      this.matcher = Selector._cache[e];
3267      return;
3268    }
3269
3270    this.matcher = ["this.matcher = function(root) {",
3271                    "var r = root, h = Selector.handlers, c = false, n;"];
3272
3273    while (e && le != e && (/\S/).test(e)) {
3274      le = e;
3275      for (var i = 0; i<len; i++) {
3276        p = ps[i].re;
3277        name = ps[i].name;
3278        if (m = e.match(p)) {
3279          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
3280            new Template(c[name]).evaluate(m));
3281          e = e.replace(m[0], '');
3282          break;
3283        }
3284      }
3285    }
3286
3287    this.matcher.push("return h.unique(n);\n}");
3288    eval(this.matcher.join('\n'));
3289    Selector._cache[this.expression] = this.matcher;
3290  },
3291
3292  compileXPathMatcher: function() {
3293    var e = this.expression, ps = Selector.patterns,
3294        x = Selector.xpath, le, m, len = ps.length, name;
3295
3296    if (Selector._cache[e]) {
3297      this.xpath = Selector._cache[e]; return;
3298    }
3299
3300    this.matcher = ['.//*'];
3301    while (e && le != e && (/\S/).test(e)) {
3302      le = e;
3303      for (var i = 0; i<len; i++) {
3304        name = ps[i].name;
3305        if (m = e.match(ps[i].re)) {
3306          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
3307            new Template(x[name]).evaluate(m));
3308          e = e.replace(m[0], '');
3309          break;
3310        }
3311      }
3312    }
3313
3314    this.xpath = this.matcher.join('');
3315    Selector._cache[this.expression] = this.xpath;
3316  },
3317
3318  findElements: function(root) {
3319    root = root || document;
3320    var e = this.expression, results;
3321
3322    switch (this.mode) {
3323      case 'selectorsAPI':
3324        if (root !== document) {
3325          var oldId = root.id, id = $(root).identify();
3326          id = id.replace(/([\.:])/g, "\\$1");
3327          e = "#" + id + " " + e;
3328        }
3329
3330        results = $A(root.querySelectorAll(e)).map(Element.extend);
3331        root.id = oldId;
3332
3333        return results;
3334      case 'xpath':
3335        return document._getElementsByXPath(this.xpath, root);
3336      default:
3337       return this.matcher(root);
3338    }
3339  },
3340
3341  match: function(element) {
3342    this.tokens = [];
3343
3344    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
3345    var le, p, m, len = ps.length, name;
3346
3347    while (e && le !== e && (/\S/).test(e)) {
3348      le = e;
3349      for (var i = 0; i<len; i++) {
3350        p = ps[i].re;
3351        name = ps[i].name;
3352        if (m = e.match(p)) {
3353          if (as[name]) {
3354            this.tokens.push([name, Object.clone(m)]);
3355            e = e.replace(m[0], '');
3356          } else {
3357            return this.findElements(document).include(element);
3358          }
3359        }
3360      }
3361    }
3362
3363    var match = true, name, matches;
3364    for (var i = 0, token; token = this.tokens[i]; i++) {
3365      name = token[0], matches = token[1];
3366      if (!Selector.assertions[name](element, matches)) {
3367        match = false; break;
3368      }
3369    }
3370
3371    return match;
3372  },
3373
3374  toString: function() {
3375    return this.expression;
3376  },
3377
3378  inspect: function() {
3379    return "#<Selector:" + this.expression.inspect() + ">";
3380  }
3381});
3382
3383if (Prototype.BrowserFeatures.SelectorsAPI &&
3384 document.compatMode === 'BackCompat') {
3385  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
3386    var div = document.createElement('div'),
3387     span = document.createElement('span');
3388
3389    div.id = "prototype_test_id";
3390    span.className = 'Test';
3391    div.appendChild(span);
3392    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
3393    div = span = null;
3394    return isIgnored;
3395  })();
3396}
3397
3398Object.extend(Selector, {
3399  _cache: { },
3400
3401  xpath: {
3402    descendant:   "//*",
3403    child:        "/*",
3404    adjacent:     "/following-sibling::*[1]",
3405    laterSibling: '/following-sibling::*',
3406    tagName:      function(m) {
3407      if (m[1] == '*') return '';
3408      return "[local-name()='" + m[1].toLowerCase() +
3409             "' or local-name()='" + m[1].toUpperCase() + "']";
3410    },
3411    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
3412    id:           "[@id='#{1}']",
3413    attrPresence: function(m) {
3414      m[1] = m[1].toLowerCase();
3415      return new Template("[@#{1}]").evaluate(m);
3416    },
3417    attr: function(m) {
3418      m[1] = m[1].toLowerCase();
3419      m[3] = m[5] || m[6];
3420      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
3421    },
3422    pseudo: function(m) {
3423      var h = Selector.xpath.pseudos[m[1]];
3424      if (!h) return '';
3425      if (Object.isFunction(h)) return h(m);
3426      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
3427    },
3428    operators: {
3429      '=':  "[@#{1}='#{3}']",
3430      '!=': "[@#{1}!='#{3}']",
3431      '^=': "[starts-with(@#{1}, '#{3}')]",
3432      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
3433      '*=': "[contains(@#{1}, '#{3}')]",
3434      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
3435      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
3436    },
3437    pseudos: {
3438      'first-child': '[not(preceding-sibling::*)]',
3439      'last-child':  '[not(following-sibling::*)]',
3440      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
3441      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
3442      'checked':     "[@checked]",
3443      'disabled':    "[(@disabled) and (@type!='hidden')]",
3444      'enabled':     "[not(@disabled) and (@type!='hidden')]",
3445      'not': function(m) {
3446        var e = m[6], p = Selector.patterns,
3447            x = Selector.xpath, le, v, len = p.length, name;
3448
3449        var exclusion = [];
3450        while (e && le != e && (/\S/).test(e)) {
3451          le = e;
3452          for (var i = 0; i<len; i++) {
3453            name = p[i].name
3454            if (m = e.match(p[i].re)) {
3455              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
3456              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
3457              e = e.replace(m[0], '');
3458              break;
3459            }
3460          }
3461        }
3462        return "[not(" + exclusion.join(" and ") + ")]";
3463      },
3464      'nth-child':      function(m) {
3465        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
3466      },
3467      'nth-last-child': function(m) {
3468        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
3469      },
3470      'nth-of-type':    function(m) {
3471        return Selector.xpath.pseudos.nth("position() ", m);
3472      },
3473      'nth-last-of-type': function(m) {
3474        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
3475      },
3476      'first-of-type':  function(m) {
3477        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
3478      },
3479      'last-of-type':   function(m) {
3480        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
3481      },
3482      'only-of-type':   function(m) {
3483        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
3484      },
3485      nth: function(fragment, m) {
3486        var mm, formula = m[6], predicate;
3487        if (formula == 'even') formula = '2n+0';
3488        if (formula == 'odd')  formula = '2n+1';
3489        if (mm = formula.match(/^(\d+)$/)) // digit only
3490          return '[' + fragment + "= " + mm[1] + ']';
3491        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
3492          if (mm[1] == "-") mm[1] = -1;
3493          var a = mm[1] ? Number(mm[1]) : 1;
3494          var b = mm[2] ? Number(mm[2]) : 0;
3495          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
3496          "((#{fragment} - #{b}) div #{a} >= 0)]";
3497          return new Template(predicate).evaluate({
3498            fragment: fragment, a: a, b: b });
3499        }
3500      }
3501    }
3502  },
3503
3504  criteria: {
3505    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
3506    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
3507    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
3508    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
3509    attr: function(m) {
3510      m[3] = (m[5] || m[6]);
3511      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
3512    },
3513    pseudo: function(m) {
3514      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
3515      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
3516    },
3517    descendant:   'c = "descendant";',
3518    child:        'c = "child";',
3519    adjacent:     'c = "adjacent";',
3520    laterSibling: 'c = "laterSibling";'
3521  },
3522
3523  patterns: [
3524    { name: 'laterSibling', re: /^\s*~\s*/ },
3525    { name: 'child',        re: /^\s*>\s*/ },
3526    { name: 'adjacent',     re: /^\s*\+\s*/ },
3527    { name: 'descendant',   re: /^\s/ },
3528
3529    { name: 'tagName',      re: /^\s*(\*|[\w\-]+)(\b|$)?/ },
3530    { name: 'id',           re: /^#([\w\-\*]+)(\b|$)/ },
3531    { name: 'className',    re: /^\.([\w\-\*]+)(\b|$)/ },
3532    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ },
3533    { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ },
3534    { name: 'attr',         re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }
3535  ],
3536
3537  assertions: {
3538    tagName: function(element, matches) {
3539      return matches[1].toUpperCase() == element.tagName.toUpperCase();
3540    },
3541
3542    className: function(element, matches) {
3543      return Element.hasClassName(element, matches[1]);
3544    },
3545
3546    id: function(element, matches) {
3547      return element.id === matches[1];
3548    },
3549
3550    attrPresence: function(element, matches) {
3551      return Element.hasAttribute(element, matches[1]);
3552    },
3553
3554    attr: function(element, matches) {
3555      var nodeValue = Element.readAttribute(element, matches[1]);
3556      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
3557    }
3558  },
3559
3560  handlers: {
3561    concat: function(a, b) {
3562      for (var i = 0, node; node = b[i]; i++)
3563        a.push(node);
3564      return a;
3565    },
3566
3567    mark: function(nodes) {
3568      var _true = Prototype.emptyFunction;
3569      for (var i = 0, node; node = nodes[i]; i++)
3570        node._countedByPrototype = _true;
3571      return nodes;
3572    },
3573
3574    unmark: (function(){
3575
3576      var PROPERTIES_ATTRIBUTES_MAP = (function(){
3577        var el = document.createElement('div'),
3578            isBuggy = false,
3579            propName = '_countedByPrototype',
3580            value = 'x'
3581        el[propName] = value;
3582        isBuggy = (el.getAttribute(propName) === value);
3583        el = null;
3584        return isBuggy;
3585      })();
3586
3587      return PROPERTIES_ATTRIBUTES_MAP ?
3588        function(nodes) {
3589          for (var i = 0, node; node = nodes[i]; i++)
3590            node.removeAttribute('_countedByPrototype');
3591          return nodes;
3592        } :
3593        function(nodes) {
3594          for (var i = 0, node; node = nodes[i]; i++)
3595            node._countedByPrototype = void 0;
3596          return nodes;
3597        }
3598    })(),
3599
3600    index: function(parentNode, reverse, ofType) {
3601      parentNode._countedByPrototype = Prototype.emptyFunction;
3602      if (reverse) {
3603        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
3604          var node = nodes[i];
3605          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3606        }
3607      } else {
3608        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
3609          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3610      }
3611    },
3612
3613    unique: function(nodes) {
3614      if (nodes.length == 0) return nodes;
3615      var results = [], n;
3616      for (var i = 0, l = nodes.length; i < l; i++)
3617        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') {
3618          n._countedByPrototype = Prototype.emptyFunction;
3619          results.push(Element.extend(n));
3620        }
3621      return Selector.handlers.unmark(results);
3622    },
3623
3624    descendant: function(nodes) {
3625      var h = Selector.handlers;
3626      for (var i = 0, results = [], node; node = nodes[i]; i++)
3627        h.concat(results, node.getElementsByTagName('*'));
3628      return results;
3629    },
3630
3631    child: function(nodes) {
3632      var h = Selector.handlers;
3633      for (var i = 0, results = [], node; node = nodes[i]; i++) {
3634        for (var j = 0, child; child = node.childNodes[j]; j++)
3635          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
3636      }
3637      return results;
3638    },
3639
3640    adjacent: function(nodes) {
3641      for (var i = 0, results = [], node; node = nodes[i]; i++) {
3642        var next = this.nextElementSibling(node);
3643        if (next) results.push(next);
3644      }
3645      return results;
3646    },
3647
3648    laterSibling: function(nodes) {
3649      var h = Selector.handlers;
3650      for (var i = 0, results = [], node; node = nodes[i]; i++)
3651        h.concat(results, Element.nextSiblings(node));
3652      return results;
3653    },
3654
3655    nextElementSibling: function(node) {
3656      while (node = node.nextSibling)
3657        if (node.nodeType == 1) return node;
3658      return null;
3659    },
3660
3661    previousElementSibling: function(node) {
3662      while (node = node.previousSibling)
3663        if (node.nodeType == 1) return node;
3664      return null;
3665    },
3666
3667    tagName: function(nodes, root, tagName, combinator) {
3668      var uTagName = tagName.toUpperCase();
3669      var results = [], h = Selector.handlers;
3670      if (nodes) {
3671        if (combinator) {
3672          if (combinator == "descendant") {
3673            for (var i = 0, node; node = nodes[i]; i++)
3674              h.concat(results, node.getElementsByTagName(tagName));
3675            return results;
3676          } else nodes = this[combinator](nodes);
3677          if (tagName == "*") return nodes;
3678        }
3679        for (var i = 0, node; node = nodes[i]; i++)
3680          if (node.tagName.toUpperCase() === uTagName) results.push(node);
3681        return results;
3682      } else return root.getElementsByTagName(tagName);
3683    },
3684
3685    id: function(nodes, root, id, combinator) {
3686      var targetNode = $(id), h = Selector.handlers;
3687
3688      if (root == document) {
3689        if (!targetNode) return [];
3690        if (!nodes) return [targetNode];
3691      } else {
3692        if (!root.sourceIndex || root.sourceIndex < 1) {
3693          var nodes = root.getElementsByTagName('*');
3694          for (var j = 0, node; node = nodes[j]; j++) {
3695            if (node.id === id) return [node];
3696          }
3697        }
3698      }
3699
3700      if (nodes) {
3701        if (combinator) {
3702          if (combinator == 'child') {
3703            for (var i = 0, node; node = nodes[i]; i++)
3704              if (targetNode.parentNode == node) return [targetNode];
3705          } else if (combinator == 'descendant') {
3706            for (var i = 0, node; node = nodes[i]; i++)
3707              if (Element.descendantOf(targetNode, node)) return [targetNode];
3708          } else if (combinator == 'adjacent') {
3709            for (var i = 0, node; node = nodes[i]; i++)
3710              if (Selector.handlers.previousElementSibling(targetNode) == node)
3711                return [targetNode];
3712          } else nodes = h[combinator](nodes);
3713        }
3714        for (var i = 0, node; node = nodes[i]; i++)
3715          if (node == targetNode) return [targetNode];
3716        return [];
3717      }
3718      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
3719    },
3720
3721    className: function(nodes, root, className, combinator) {
3722      if (nodes && combinator) nodes = this[combinator](nodes);
3723      return Selector.handlers.byClassName(nodes, root, className);
3724    },
3725
3726    byClassName: function(nodes, root, className) {
3727      if (!nodes) nodes = Selector.handlers.descendant([root]);
3728      var needle = ' ' + className + ' ';
3729      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
3730        nodeClassName = node.className;
3731        if (nodeClassName.length == 0) continue;
3732        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
3733          results.push(node);
3734      }
3735      return results;
3736    },
3737
3738    attrPresence: function(nodes, root, attr, combinator) {
3739      if (!nodes) nodes = root.getElementsByTagName("*");
3740      if (nodes && combinator) nodes = this[combinator](nodes);
3741      var results = [];
3742      for (var i = 0, node; node = nodes[i]; i++)
3743        if (Element.hasAttribute(node, attr)) results.push(node);
3744      return results;
3745    },
3746
3747    attr: function(nodes, root, attr, value, operator, combinator) {
3748      if (!nodes) nodes = root.getElementsByTagName("*");
3749      if (nodes && combinator) nodes = this[combinator](nodes);
3750      var handler = Selector.operators[operator], results = [];
3751      for (var i = 0, node; node = nodes[i]; i++) {
3752        var nodeValue = Element.readAttribute(node, attr);
3753        if (nodeValue === null) continue;
3754        if (handler(nodeValue, value)) results.push(node);
3755      }
3756      return results;
3757    },
3758
3759    pseudo: function(nodes, name, value, root, combinator) {
3760      if (nodes && combinator) nodes = this[combinator](nodes);
3761      if (!nodes) nodes = root.getElementsByTagName("*");
3762      return Selector.pseudos[name](nodes, value, root);
3763    }
3764  },
3765
3766  pseudos: {
3767    'first-child': function(nodes, value, root) {
3768      for (var i = 0, results = [], node; node = nodes[i]; i++) {
3769        if (Selector.handlers.previousElementSibling(node)) continue;
3770          results.push(node);
3771      }
3772      return results;
3773    },
3774    'last-child': function(nodes, value, root) {
3775      for (var i = 0, results = [], node; node = nodes[i]; i++) {
3776        if (Selector.handlers.nextElementSibling(node)) continue;
3777          results.push(node);
3778      }
3779      return results;
3780    },
3781    'only-child': function(nodes, value, root) {
3782      var h = Selector.handlers;
3783      for (var i = 0, results = [], node; node = nodes[i]; i++)
3784        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
3785          results.push(node);
3786      return results;
3787    },
3788    'nth-child':        function(nodes, formula, root) {
3789      return Selector.pseudos.nth(nodes, formula, root);
3790    },
3791    'nth-last-child':   function(nodes, formula, root) {
3792      return Selector.pseudos.nth(nodes, formula, root, true);
3793    },
3794    'nth-of-type':      function(nodes, formula, root) {
3795      return Selector.pseudos.nth(nodes, formula, root, false, true);
3796    },
3797    'nth-last-of-type': function(nodes, formula, root) {
3798      return Selector.pseudos.nth(nodes, formula, root, true, true);
3799    },
3800    'first-of-type':    function(nodes, formula, root) {
3801      return Selector.pseudos.nth(nodes, "1", root, false, true);
3802    },
3803    'last-of-type':     function(nodes, formula, root) {
3804      return Selector.pseudos.nth(nodes, "1", root, true, true);
3805    },
3806    'only-of-type':     function(nodes, formula, root) {
3807      var p = Selector.pseudos;
3808      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
3809    },
3810
3811    getIndices: function(a, b, total) {
3812      if (a == 0) return b > 0 ? [b] : [];
3813      return $R(1, total).inject([], function(memo, i) {
3814        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
3815        return memo;
3816      });
3817    },
3818
3819    nth: function(nodes, formula, root, reverse, ofType) {
3820      if (nodes.length == 0) return [];
3821      if (formula == 'even') formula = '2n+0';
3822      if (formula == 'odd')  formula = '2n+1';
3823      var h = Selector.handlers, results = [], indexed = [], m;
3824      h.mark(nodes);
3825      for (var i = 0, node; node = nodes[i]; i++) {
3826        if (!node.parentNode._countedByPrototype) {
3827          h.index(node.parentNode, reverse, ofType);
3828          indexed.push(node.parentNode);
3829        }
3830      }
3831      if (formula.match(/^\d+$/)) { // just a number
3832        formula = Number(formula);
3833        for (var i = 0, node; node = nodes[i]; i++)
3834          if (node.nodeIndex == formula) results.push(node);
3835      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
3836        if (m[1] == "-") m[1] = -1;
3837        var a = m[1] ? Number(m[1]) : 1;
3838        var b = m[2] ? Number(m[2]) : 0;
3839        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
3840        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
3841          for (var j = 0; j < l; j++)
3842            if (node.nodeIndex == indices[j]) results.push(node);
3843        }
3844      }
3845      h.unmark(nodes);
3846      h.unmark(indexed);
3847      return results;
3848    },
3849
3850    'empty': function(nodes, value, root) {
3851      for (var i = 0, results = [], node; node = nodes[i]; i++) {
3852        if (node.tagName == '!' || node.firstChild) continue;
3853        results.push(node);
3854      }
3855      return results;
3856    },
3857
3858    'not': function(nodes, selector, root) {
3859      var h = Selector.handlers, selectorType, m;
3860      var exclusions = new Selector(selector).findElements(root);
3861      h.mark(exclusions);
3862      for (var i = 0, results = [], node; node = nodes[i]; i++)
3863        if (!node._countedByPrototype) results.push(node);
3864      h.unmark(exclusions);
3865      return results;
3866    },
3867
3868    'enabled': function(nodes, value, root) {
3869      for (var i = 0, results = [], node; node = nodes[i]; i++)
3870        if (!node.disabled && (!node.type || node.type !== 'hidden'))
3871          results.push(node);
3872      return results;
3873    },
3874
3875    'disabled': function(nodes, value, root) {
3876      for (var i = 0, results = [], node; node = nodes[i]; i++)
3877        if (node.disabled) results.push(node);
3878      return results;
3879    },
3880
3881    'checked': function(nodes, value, root) {
3882      for (var i = 0, results = [], node; node = nodes[i]; i++)
3883        if (node.checked) results.push(node);
3884      return results;
3885    }
3886  },
3887
3888  operators: {
3889    '=':  function(nv, v) { return nv == v; },
3890    '!=': function(nv, v) { return nv != v; },
3891    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
3892    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
3893    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
3894    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
3895    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
3896     '-').include('-' + (v || "").toUpperCase() + '-'); }
3897  },
3898
3899  split: function(expression) {
3900    var expressions = [];
3901    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
3902      expressions.push(m[1].strip());
3903    });
3904    return expressions;
3905  },
3906
3907  matchElements: function(elements, expression) {
3908    var matches = $$(expression), h = Selector.handlers;
3909    h.mark(matches);
3910    for (var i = 0, results = [], element; element = elements[i]; i++)
3911      if (element._countedByPrototype) results.push(element);
3912    h.unmark(matches);
3913    return results;
3914  },
3915
3916  findElement: function(elements, expression, index) {
3917    if (Object.isNumber(expression)) {
3918      index = expression; expression = false;
3919    }
3920    return Selector.matchElements(elements, expression || '*')[index || 0];
3921  },
3922
3923  findChildElements: function(element, expressions) {
3924    expressions = Selector.split(expressions.join(','));
3925    var results = [], h = Selector.handlers;
3926    for (var i = 0, l = expressions.length, selector; i < l; i++) {
3927      selector = new Selector(expressions[i].strip());
3928      h.concat(results, selector.findElements(element));
3929    }
3930    return (l > 1) ? h.unique(results) : results;
3931  }
3932});
3933
3934if (Prototype.Browser.IE) {
3935  Object.extend(Selector.handlers, {
3936    concat: function(a, b) {
3937      for (var i = 0, node; node = b[i]; i++)
3938        if (node.tagName !== "!") a.push(node);
3939      return a;
3940    }
3941  });
3942}
3943
3944function $$() {
3945  return Selector.findChildElements(document, $A(arguments));
3946}
3947
3948var Form = {
3949  reset: function(form) {
3950    form = $(form);
3951    form.reset();
3952    return form;
3953  },
3954
3955  serializeElements: function(elements, options) {
3956    if (typeof options != 'object') options = { hash: !!options };
3957    else if (Object.isUndefined(options.hash)) options.hash = true;
3958    var key, value, submitted = false, submit = options.submit;
3959
3960    var data = elements.inject({ }, function(result, element) {
3961      if (!element.disabled && element.name) {
3962        key = element.name; value = $(element).getValue();
3963        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
3964            submit !== false && (!submit || key == submit) && (submitted = true)))) {
3965          if (key in result) {
3966            if (!Object.isArray(result[key])) result[key] = [result[key]];
3967            result[key].push(value);
3968          }
3969          else result[key] = value;
3970        }
3971      }
3972      return result;
3973    });
3974
3975    return options.hash ? data : Object.toQueryString(data);
3976  }
3977};
3978
3979Form.Methods = {
3980  serialize: function(form, options) {
3981    return Form.serializeElements(Form.getElements(form), options);
3982  },
3983
3984  getElements: function(form) {
3985    var elements = $(form).getElementsByTagName('*'),
3986        element,
3987        arr = [ ],
3988        serializers = Form.Element.Serializers;
3989    for (var i = 0; element = elements[i]; i++) {
3990      arr.push(element);
3991    }
3992    return arr.inject([], function(elements, child) {
3993      if (serializers[child.tagName.toLowerCase()])
3994        elements.push(Element.extend(child));
3995      return elements;
3996    })
3997  },
3998
3999  getInputs: function(form, typeName, name) {
4000    form = $(form);
4001    var inputs = form.getElementsByTagName('input');
4002
4003    if (!typeName && !name) return $A(inputs).map(Element.extend);
4004
4005    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
4006      var input = inputs[i];
4007      if ((typeName && input.type != typeName) || (name && input.name != name))
4008        continue;
4009      matchingInputs.push(Element.extend(input));
4010    }
4011
4012    return matchingInputs;
4013  },
4014
4015  disable: function(form) {
4016    form = $(form);
4017    Form.getElements(form).invoke('disable');
4018    return form;
4019  },
4020
4021  enable: function(form) {
4022    form = $(form);
4023    Form.getElements(form).invoke('enable');
4024    return form;
4025  },
4026
4027  findFirstElement: function(form) {
4028    var elements = $(form).getElements().findAll(function(element) {
4029      return 'hidden' != element.type && !element.disabled;
4030    });
4031    var firstByIndex = elements.findAll(function(element) {
4032      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
4033    }).sortBy(function(element) { return element.tabIndex }).first();
4034
4035    return firstByIndex ? firstByIndex : elements.find(function(element) {
4036      return /^(?:input|select|textarea)$/i.test(element.tagName);
4037    });
4038  },
4039
4040  focusFirstElement: function(form) {
4041    form = $(form);
4042    form.findFirstElement().activate();
4043    return form;
4044  },
4045
4046  request: function(form, options) {
4047    form = $(form), options = Object.clone(options || { });
4048
4049    var params = options.parameters, action = form.readAttribute('action') || '';
4050    if (action.blank()) action = window.location.href;
4051    options.parameters = form.serialize(true);
4052
4053    if (params) {
4054      if (Object.isString(params)) params = params.toQueryParams();
4055      Object.extend(options.parameters, params);
4056    }
4057
4058    if (form.hasAttribute('method') && !options.method)
4059      options.method = form.method;
4060
4061    return new Ajax.Request(action, options);
4062  }
4063};
4064
4065/*--------------------------------------------------------------------------*/
4066
4067
4068Form.Element = {
4069  focus: function(element) {
4070    $(element).focus();
4071    return element;
4072  },
4073
4074  select: function(element) {
4075    $(element).select();
4076    return element;
4077  }
4078};
4079
4080Form.Element.Methods = {
4081
4082  serialize: function(element) {
4083    element = $(element);
4084    if (!element.disabled && element.name) {
4085      var value = element.getValue();
4086      if (value != undefined) {
4087        var pair = { };
4088        pair[element.name] = value;
4089        return Object.toQueryString(pair);
4090      }
4091    }
4092    return '';
4093  },
4094
4095  getValue: function(element) {
4096    element = $(element);
4097    var method = element.tagName.toLowerCase();
4098    return Form.Element.Serializers[method](element);
4099  },
4100
4101  setValue: function(element, value) {
4102    element = $(element);
4103    var method = element.tagName.toLowerCase();
4104    Form.Element.Serializers[method](element, value);
4105    return element;
4106  },
4107
4108  clear: function(element) {
4109    $(element).value = '';
4110    return element;
4111  },
4112
4113  present: function(element) {
4114    return $(element).value != '';
4115  },
4116
4117  activate: function(element) {
4118    element = $(element);
4119    try {
4120      element.focus();
4121      if (element.select && (element.tagName.toLowerCase() != 'input' ||
4122          !(/^(?:button|reset|submit)$/i.test(element.type))))
4123        element.select();
4124    } catch (e) { }
4125    return element;
4126  },
4127
4128  disable: function(element) {
4129    element = $(element);
4130    element.disabled = true;
4131    return element;
4132  },
4133
4134  enable: function(element) {
4135    element = $(element);
4136    element.disabled = false;
4137    return element;
4138  }
4139};
4140
4141/*--------------------------------------------------------------------------*/
4142
4143var Field = Form.Element;
4144
4145var $F = Form.Element.Methods.getValue;
4146
4147/*--------------------------------------------------------------------------*/
4148
4149Form.Element.Serializers = {
4150  input: function(element, value) {
4151    switch (element.type.toLowerCase()) {
4152      case 'checkbox':
4153      case 'radio':
4154        return Form.Element.Serializers.inputSelector(element, value);
4155      default:
4156        return Form.Element.Serializers.textarea(element, value);
4157    }
4158  },
4159
4160  inputSelector: function(element, value) {
4161    if (Object.isUndefined(value)) return element.checked ? element.value : null;
4162    else element.checked = !!value;
4163  },
4164
4165  textarea: function(element, value) {
4166    if (Object.isUndefined(value)) return element.value;
4167    else element.value = value;
4168  },
4169
4170  select: function(element, value) {
4171    if (Object.isUndefined(value))
4172      return this[element.type == 'select-one' ?
4173        'selectOne' : 'selectMany'](element);
4174    else {
4175      var opt, currentValue, single = !Object.isArray(value);
4176      for (var i = 0, length = element.length; i < length; i++) {
4177        opt = element.options[i];
4178        currentValue = this.optionValue(opt);
4179        if (single) {
4180          if (currentValue == value) {
4181            opt.selected = true;
4182            return;
4183          }
4184        }
4185        else opt.selected = value.include(currentValue);
4186      }
4187    }
4188  },
4189
4190  selectOne: function(element) {
4191    var index = element.selectedIndex;
4192    return index >= 0 ? this.optionValue(element.options[index]) : null;
4193  },
4194
4195  selectMany: function(element) {
4196    var values, length = element.length;
4197    if (!length) return null;
4198
4199    for (var i = 0, values = []; i < length; i++) {
4200      var opt = element.options[i];
4201      if (opt.selected) values.push(this.optionValue(opt));
4202    }
4203    return values;
4204  },
4205
4206  optionValue: function(opt) {
4207    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
4208  }
4209};
4210
4211/*--------------------------------------------------------------------------*/
4212
4213
4214Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
4215  initialize: function($super, element, frequency, callback) {
4216    $super(callback, frequency);
4217    this.element   = $(element);
4218    this.lastValue = this.getValue();
4219  },
4220
4221  execute: function() {
4222    var value = this.getValue();
4223    if (Object.isString(this.lastValue) && Object.isString(value) ?
4224        this.lastValue != value : String(this.lastValue) != String(value)) {
4225      this.callback(this.element, value);
4226      this.lastValue = value;
4227    }
4228  }
4229});
4230
4231Form.Element.Observer = Class.create(Abstract.TimedObserver, {
4232  getValue: function() {
4233    return Form.Element.getValue(this.element);
4234  }
4235});
4236
4237Form.Observer = Class.create(Abstract.TimedObserver, {
4238  getValue: function() {
4239    return Form.serialize(this.element);
4240  }
4241});
4242
4243/*--------------------------------------------------------------------------*/
4244
4245Abstract.EventObserver = Class.create({
4246  initialize: function(element, callback) {
4247    this.element  = $(element);
4248    this.callback = callback;
4249
4250    this.lastValue = this.getValue();
4251    if (this.element.tagName.toLowerCase() == 'form')
4252      this.registerFormCallbacks();
4253    else
4254      this.registerCallback(this.element);
4255  },
4256
4257  onElementEvent: function() {
4258    var value = this.getValue();
4259    if (this.lastValue != value) {
4260      this.callback(this.element, value);
4261      this.lastValue = value;
4262    }
4263  },
4264
4265  registerFormCallbacks: function() {
4266    Form.getElements(this.element).each(this.registerCallback, this);
4267  },
4268
4269  registerCallback: function(element) {
4270    if (element.type) {
4271      switch (element.type.toLowerCase()) {
4272        case 'checkbox':
4273        case 'radio':
4274          Event.observe(element, 'click', this.onElementEvent.bind(this));
4275          break;
4276        default:
4277          Event.observe(element, 'change', this.onElementEvent.bind(this));
4278          break;
4279      }
4280    }
4281  }
4282});
4283
4284Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
4285  getValue: function() {
4286    return Form.Element.getValue(this.element);
4287  }
4288});
4289
4290Form.EventObserver = Class.create(Abstract.EventObserver, {
4291  getValue: function() {
4292    return Form.serialize(this.element);
4293  }
4294});
4295(function() {
4296
4297  var Event = {
4298    KEY_BACKSPACE: 8,
4299    KEY_TAB:       9,
4300    KEY_RETURN:   13,
4301    KEY_ESC:      27,
4302    KEY_LEFT:     37,
4303    KEY_UP:       38,
4304    KEY_RIGHT:    39,
4305    KEY_DOWN:     40,
4306    KEY_DELETE:   46,
4307    KEY_HOME:     36,
4308    KEY_END:      35,
4309    KEY_PAGEUP:   33,
4310    KEY_PAGEDOWN: 34,
4311    KEY_INSERT:   45,
4312
4313    cache: {}
4314  };
4315
4316  var docEl = document.documentElement;
4317  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
4318    && 'onmouseleave' in docEl;
4319
4320  var _isButton;
4321  if (Prototype.Browser.IE) {
4322    var buttonMap = { 0: 1, 1: 4, 2: 2 };
4323    _isButton = function(event, code) {
4324      return event.button === buttonMap[code];
4325    };
4326  } else if (Prototype.Browser.WebKit) {
4327    _isButton = function(event, code) {
4328      switch (code) {
4329        case 0: return event.which == 1 && !event.metaKey;
4330        case 1: return event.which == 1 && event.metaKey;
4331        default: return false;
4332      }
4333    };
4334  } else {
4335    _isButton = function(event, code) {
4336      return event.which ? (event.which === code + 1) : (event.button === code);
4337    };
4338  }
4339
4340  function isLeftClick(event)   { return _isButton(event, 0) }
4341
4342  function isMiddleClick(event) { return _isButton(event, 1) }
4343
4344  function isRightClick(event)  { return _isButton(event, 2) }
4345
4346  function element(event) {
4347    event = Event.extend(event);
4348
4349    var node = event.target, type = event.type,
4350     currentTarget = event.currentTarget;
4351
4352    if (currentTarget && currentTarget.tagName) {
4353      if (type === 'load' || type === 'error' ||
4354        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
4355          && currentTarget.type === 'radio'))
4356            node = currentTarget;
4357    }
4358
4359    if (node.nodeType == Node.TEXT_NODE)
4360      node = node.parentNode;
4361
4362    return Element.extend(node);
4363  }
4364
4365  function findElement(event, expression) {
4366    var element = Event.element(event);
4367    if (!expression) return element;
4368    var elements = [element].concat(element.ancestors());
4369    return Selector.findElement(elements, expression, 0);
4370  }
4371
4372  function pointer(event) {
4373    return { x: pointerX(event), y: pointerY(event) };
4374  }
4375
4376  function pointerX(event) {
4377    var docElement = document.documentElement,
4378     body = document.body || { scrollLeft: 0 };
4379
4380    return event.pageX || (event.clientX +
4381      (docElement.scrollLeft || body.scrollLeft) -
4382      (docElement.clientLeft || 0));
4383  }
4384
4385  function pointerY(event) {
4386    var docElement = document.documentElement,
4387     body = document.body || { scrollTop: 0 };
4388
4389    return  event.pageY || (event.clientY +
4390       (docElement.scrollTop || body.scrollTop) -
4391       (docElement.clientTop || 0));
4392  }
4393
4394
4395  function stop(event) {
4396    Event.extend(event);
4397    event.preventDefault();
4398    event.stopPropagation();
4399
4400    event.stopped = true;
4401  }
4402
4403  Event.Methods = {
4404    isLeftClick: isLeftClick,
4405    isMiddleClick: isMiddleClick,
4406    isRightClick: isRightClick,
4407
4408    element: element,
4409    findElement: findElement,
4410
4411    pointer: pointer,
4412    pointerX: pointerX,
4413    pointerY: pointerY,
4414
4415    stop: stop
4416  };
4417
4418
4419  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
4420    m[name] = Event.Methods[name].methodize();
4421    return m;
4422  });
4423
4424  if (Prototype.Browser.IE) {
4425    function _relatedTarget(event) {
4426      var element;
4427      switch (event.type) {
4428        case 'mouseover': element = event.fromElement; break;
4429        case 'mouseout':  element = event.toElement;   break;
4430        default: return null;
4431      }
4432      return Element.extend(element);
4433    }
4434
4435    Object.extend(methods, {
4436      stopPropagation: function() { this.cancelBubble = true },
4437      preventDefault:  function() { this.returnValue = false },
4438      inspect: function() { return '[object Event]' }
4439    });
4440
4441    Event.extend = function(event, element) {
4442      if (!event) return false;
4443      if (event._extendedByPrototype) return event;
4444
4445      event._extendedByPrototype = Prototype.emptyFunction;
4446      var pointer = Event.pointer(event);
4447
4448      Object.extend(event, {
4449        target: event.srcElement || element,
4450        relatedTarget: _relatedTarget(event),
4451        pageX:  pointer.x,
4452        pageY:  pointer.y
4453      });
4454
4455      return Object.extend(event, methods);
4456    };
4457  } else {
4458    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
4459    Object.extend(Event.prototype, methods);
4460    Event.extend = Prototype.K;
4461  }
4462
4463  function _createResponder(element, eventName, handler) {
4464    var registry = Element.retrieve(element, 'prototype_event_registry');
4465
4466    if (Object.isUndefined(registry)) {
4467      CACHE.push(element);
4468      registry = Element.retrieve(element, 'prototype_event_registry', $H());
4469    }
4470
4471    var respondersForEvent = registry.get(eventName);
4472    if (Object.isUndefined(respondersForEvent)) {
4473      respondersForEvent = [];
4474      registry.set(eventName, respondersForEvent);
4475    }
4476
4477    if (respondersForEvent.pluck('handler').include(handler)) return false;
4478
4479    var responder;
4480    if (eventName.include(":")) {
4481      responder = function(event) {
4482        if (Object.isUndefined(event.eventName))
4483          return false;
4484
4485        if (event.eventName !== eventName)
4486          return false;
4487
4488        Event.extend(event, element);
4489        handler.call(element, event);
4490      };
4491    } else {
4492      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
4493       (eventName === "mouseenter" || eventName === "mouseleave")) {
4494        if (eventName === "mouseenter" || eventName === "mouseleave") {
4495          responder = function(event) {
4496            Event.extend(event, element);
4497
4498            var parent = event.relatedTarget;
4499            while (parent && parent !== element) {
4500              try { parent = parent.parentNode; }
4501              catch(e) { parent = element; }
4502            }
4503
4504            if (parent === element) return;
4505
4506            handler.call(element, event);
4507          };
4508        }
4509      } else {
4510        responder = function(event) {
4511          Event.extend(event, element);
4512          handler.call(element, event);
4513        };
4514      }
4515    }
4516
4517    responder.handler = handler;
4518    respondersForEvent.push(responder);
4519    return responder;
4520  }
4521
4522  function _destroyCache() {
4523    for (var i = 0, length = CACHE.length; i < length; i++) {
4524      Event.stopObserving(CACHE[i]);
4525      CACHE[i] = null;
4526    }
4527  }
4528
4529  var CACHE = [];
4530
4531  if (Prototype.Browser.IE)
4532    window.attachEvent('onunload', _destroyCache);
4533
4534  if (Prototype.Browser.WebKit)
4535    window.addEventListener('unload', Prototype.emptyFunction, false);
4536
4537
4538  var _getDOMEventName = Prototype.K;
4539
4540  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
4541    _getDOMEventName = function(eventName) {
4542      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
4543      return eventName in translations ? translations[eventName] : eventName;
4544    };
4545  }
4546
4547  function observe(element, eventName, handler) {
4548    element = $(element);
4549
4550    var responder = _createResponder(element, eventName, handler);
4551
4552    if (!responder) return element;
4553
4554    if (eventName.include(':')) {
4555      if (element.addEventListener)
4556        element.addEventListener("dataavailable", responder, false);
4557      else {
4558        element.attachEvent("ondataavailable", responder);
4559        element.attachEvent("onfilterchange", responder);
4560      }
4561    } else {
4562      var actualEventName = _getDOMEventName(eventName);
4563
4564      if (element.addEventListener)
4565        element.addEventListener(actualEventName, responder, false);
4566      else
4567        element.attachEvent("on" + actualEventName, responder);
4568    }
4569
4570    return element;
4571  }
4572
4573  function stopObserving(element, eventName, handler) {
4574    element = $(element);
4575
4576    var registry = Element.retrieve(element, 'prototype_event_registry');
4577
4578    if (Object.isUndefined(registry)) return element;
4579
4580    if (eventName && !handler) {
4581      var responders = registry.get(eventName);
4582
4583      if (Object.isUndefined(responders)) return element;
4584
4585      responders.each( function(r) {
4586        Element.stopObserving(element, eventName, r.handler);
4587      });
4588      return element;
4589    } else if (!eventName) {
4590      registry.each( function(pair) {
4591        var eventName = pair.key, responders = pair.value;
4592
4593        responders.each( function(r) {
4594          Element.stopObserving(element, eventName, r.handler);
4595        });
4596      });
4597      return element;
4598    }
4599
4600    var responders = registry.get(eventName);
4601
4602    if (!responders) return;
4603
4604    var responder = responders.find( function(r) { return r.handler === handler; });
4605    if (!responder) return element;
4606
4607    var actualEventName = _getDOMEventName(eventName);
4608
4609    if (eventName.include(':')) {
4610      if (element.removeEventListener)
4611        element.removeEventListener("dataavailable", responder, false);
4612      else {
4613        element.detachEvent("ondataavailable", responder);
4614        element.detachEvent("onfilterchange",  responder);
4615      }
4616    } else {
4617      if (element.removeEventListener)
4618        element.removeEventListener(actualEventName, responder, false);
4619      else
4620        element.detachEvent('on' + actualEventName, responder);
4621    }
4622
4623    registry.set(eventName, responders.without(responder));
4624
4625    return element;
4626  }
4627
4628  function fire(element, eventName, memo, bubble) {
4629    element = $(element);
4630
4631    if (Object.isUndefined(bubble))
4632      bubble = true;
4633
4634    if (element == document && document.createEvent && !element.dispatchEvent)
4635      element = document.documentElement;
4636
4637    var event;
4638    if (document.createEvent) {
4639      event = document.createEvent('HTMLEvents');
4640      event.initEvent('dataavailable', true, true);
4641    } else {
4642      event = document.createEventObject();
4643      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
4644    }
4645
4646    event.eventName = eventName;
4647    event.memo = memo || { };
4648
4649    if (document.createEvent)
4650      element.dispatchEvent(event);
4651    else
4652      element.fireEvent(event.eventType, event);
4653
4654    return Event.extend(event);
4655  }
4656
4657
4658  Object.extend(Event, Event.Methods);
4659
4660  Object.extend(Event, {
4661    fire:          fire,
4662    observe:       observe,
4663    stopObserving: stopObserving
4664  });
4665
4666  Element.addMethods({
4667    fire:          fire,
4668
4669    observe:       observe,
4670
4671    stopObserving: stopObserving
4672  });
4673
4674  Object.extend(document, {
4675    fire:          fire.methodize(),
4676
4677    observe:       observe.methodize(),
4678
4679    stopObserving: stopObserving.methodize(),
4680
4681    loaded:        false
4682  });
4683
4684  if (window.Event) Object.extend(window.Event, Event);
4685  else window.Event = Event;
4686})();
4687
4688(function() {
4689  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
4690     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
4691
4692  var timer;
4693
4694  function fireContentLoadedEvent() {
4695    if (document.loaded) return;
4696    if (timer) window.clearTimeout(timer);
4697    document.loaded = true;
4698    document.fire('dom:loaded');
4699  }
4700
4701  function checkReadyState() {
4702    if (document.readyState === 'complete') {
4703      document.stopObserving('readystatechange', checkReadyState);
4704      fireContentLoadedEvent();
4705    }
4706  }
4707
4708  function pollDoScroll() {
4709    try { document.documentElement.doScroll('left'); }
4710    catch(e) {
4711      timer = pollDoScroll.defer();
4712      return;
4713    }
4714    fireContentLoadedEvent();
4715  }
4716
4717  if (document.addEventListener) {
4718    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
4719  } else {
4720    document.observe('readystatechange', checkReadyState);
4721    if (window == top)
4722      timer = pollDoScroll.defer();
4723  }
4724
4725  Event.observe(window, 'load', fireContentLoadedEvent);
4726})();
4727
4728Element.addMethods();
4729
4730/*------------------------------- DEPRECATED -------------------------------*/
4731
4732Hash.toQueryString = Object.toQueryString;
4733
4734var Toggle = { display: Element.toggle };
4735
4736Element.Methods.childOf = Element.Methods.descendantOf;
4737
4738var Insertion = {
4739  Before: function(element, content) {
4740    return Element.insert(element, {before:content});
4741  },
4742
4743  Top: function(element, content) {
4744    return Element.insert(element, {top:content});
4745  },
4746
4747  Bottom: function(element, content) {
4748    return Element.insert(element, {bottom:content});
4749  },
4750
4751  After: function(element, content) {
4752    return Element.insert(element, {after:content});
4753  }
4754};
4755
4756var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
4757
4758var Position = {
4759  includeScrollOffsets: false,
4760
4761  prepare: function() {
4762    this.deltaX =  window.pageXOffset
4763                || document.documentElement.scrollLeft
4764                || document.body.scrollLeft
4765                || 0;
4766    this.deltaY =  window.pageYOffset
4767                || document.documentElement.scrollTop
4768                || document.body.scrollTop
4769                || 0;
4770  },
4771
4772  within: function(element, x, y) {
4773    if (this.includeScrollOffsets)
4774      return this.withinIncludingScrolloffsets(element, x, y);
4775    this.xcomp = x;
4776    this.ycomp = y;
4777    this.offset = Element.cumulativeOffset(element);
4778
4779    return (y >= this.offset[1] &&
4780            y <  this.offset[1] + element.offsetHeight &&
4781            x >= this.offset[0] &&
4782            x <  this.offset[0] + element.offsetWidth);
4783  },
4784
4785  withinIncludingScrolloffsets: function(element, x, y) {
4786    var offsetcache = Element.cumulativeScrollOffset(element);
4787
4788    this.xcomp = x + offsetcache[0] - this.deltaX;
4789    this.ycomp = y + offsetcache[1] - this.deltaY;
4790    this.offset = Element.cumulativeOffset(element);
4791
4792    return (this.ycomp >= this.offset[1] &&
4793            this.ycomp <  this.offset[1] + element.offsetHeight &&
4794            this.xcomp >= this.offset[0] &&
4795            this.xcomp <  this.offset[0] + element.offsetWidth);
4796  },
4797
4798  overlap: function(mode, element) {
4799    if (!mode) return 0;
4800    if (mode == 'vertical')
4801      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
4802        element.offsetHeight;
4803    if (mode == 'horizontal')
4804      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
4805        element.offsetWidth;
4806  },
4807
4808
4809  cumulativeOffset: Element.Methods.cumulativeOffset,
4810
4811  positionedOffset: Element.Methods.positionedOffset,
4812
4813  absolutize: function(element) {
4814    Position.prepare();
4815    return Element.absolutize(element);
4816  },
4817
4818  relativize: function(element) {
4819    Position.prepare();
4820    return Element.relativize(element);
4821  },
4822
4823  realOffset: Element.Methods.cumulativeScrollOffset,
4824
4825  offsetParent: Element.Methods.getOffsetParent,
4826
4827  page: Element.Methods.viewportOffset,
4828
4829  clone: function(source, target, options) {
4830    options = options || { };
4831    return Element.clonePosition(target, source, options);
4832  }
4833};
4834
4835/*--------------------------------------------------------------------------*/
4836
4837if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
4838  function iter(name) {
4839    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
4840  }
4841
4842  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
4843  function(element, className) {
4844    className = className.toString().strip();
4845    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
4846    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
4847  } : function(element, className) {
4848    className = className.toString().strip();
4849    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
4850    if (!classNames && !className) return elements;
4851
4852    var nodes = $(element).getElementsByTagName('*');
4853    className = ' ' + className + ' ';
4854
4855    for (var i = 0, child, cn; child = nodes[i]; i++) {
4856      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
4857          (classNames && classNames.all(function(name) {
4858            return !name.toString().blank() && cn.include(' ' + name + ' ');
4859          }))))
4860        elements.push(Element.extend(child));
4861    }
4862    return elements;
4863  };
4864
4865  return function(className, parentElement) {
4866    return $(parentElement || document.body).getElementsByClassName(className);
4867  };
4868}(Element.Methods);
4869
4870/*--------------------------------------------------------------------------*/
4871
4872Element.ClassNames = Class.create();
4873Element.ClassNames.prototype = {
4874  initialize: function(element) {
4875    this.element = $(element);
4876  },
4877
4878  _each: function(iterator) {
4879    this.element.className.split(/\s+/).select(function(name) {
4880      return name.length > 0;
4881    })._each(iterator);
4882  },
4883
4884  set: function(className) {
4885    this.element.className = className;
4886  },
4887
4888  add: function(classNameToAdd) {
4889    if (this.include(classNameToAdd)) return;
4890    this.set($A(this).concat(classNameToAdd).join(' '));
4891  },
4892
4893  remove: function(classNameToRemove) {
4894    if (!this.include(classNameToRemove)) return;
4895    this.set($A(this).without(classNameToRemove).join(' '));
4896  },
4897
4898  toString: function() {
4899    return $A(this).join(' ');
4900  }
4901};
4902
4903Object.extend(Element.ClassNames.prototype, Enumerable);
4904
4905/*--------------------------------------------------------------------------*/

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.