PageSourceSearch

http://www.famouswhy.ro/ddd/inc/js/prototype-1.6.0.3.js

js famouswhy.ro collected 2026-09-25 00:23:09 UTC 136,117 bytes, 3,601 lines download raw bytes

1var Prototype = {
2    Version: '1.6.0.3',
3    Browser: {
4        IE: !! (window.attachEvent && navigator.userAgent.indexOf('Opera') === -1),
5        Opera: navigator.userAgent.indexOf('Opera') > -1,
6        WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
7        Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') === -1,
8        MobileSafari: !! navigator.userAgent.match(/Apple.*Mobile.*Safari/)
9    },
10    BrowserFeatures: {
11        XPath: !! document.evaluate,
12        SelectorsAPI: !! document.querySelector,
13        ElementExtensions: !! window.HTMLElement,
14        SpecificElementExtensions: document.createElement('div')['__proto__'] && document.createElement('div')['__proto__'] !== document.createElement('form')['__proto__']
15    },
16    ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
17    JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
18    emptyFunction: function() {},
19    K: function(x) {
20        return x
21    }
22};
23if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false;
24var Class = {
25    create: function() {
26        var parent = null,
27            properties = $A(arguments);
28        if (Object.isFunction(properties[0])) parent = properties.shift();
29
30        function klass() {
31            this.initialize.apply(this, arguments);
32        }
33        Object.extend(klass, Class.Methods);
34        klass.superclass = parent;
35        klass.subclasses = [];
36        if (parent) {
37            var subclass = function() {};
38            subclass.prototype = parent.prototype;
39            klass.prototype = new subclass;
40            parent.subclasses.push(klass);
41        }
42        for (var i = 0; i < properties.length; i++)
43        klass.addMethods(properties[i]);
44        if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction;
45        klass.prototype.constructor = klass;
46        return klass;
47    }
48};
49Class.Methods = {
50    addMethods: function(source) {
51        var ancestor = this.superclass && this.superclass.prototype;
52        var properties = Object.keys(source);
53        if (!Object.keys({
54            toString: true
55        }).length) properties.push("toString", "valueOf");
56        for (var i = 0, length = properties.length; i < length; i++) {
57            var property = properties[i],
58                value = source[property];
59            if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") {
60                var method = value;
61                value = (function(m) {
62                    return function() {
63                        return ancestor[m].apply(this, arguments)
64                    };
65                })(property).wrap(method);
66                value.valueOf = method.valueOf.bind(method);
67                value.toString = method.toString.bind(method);
68            }
69            this.prototype[property] = value;
70        }
71        return this;
72    }
73};
74var Abstract = {};
75Object.extend = function(destination, source) {
76    for (var property in source)
77    destination[property] = source[property];
78    return destination;
79};
80Object.extend(Object, {
81    inspect: function(object) {
82        try {
83            if (Object.isUndefined(object)) return 'undefined';
84            if (object === null) return 'null';
85            return object.inspect ? object.inspect() : String(object);
86        } catch (e) {
87            if (e instanceof RangeError) return '...';
88            throw e;
89        }
90    },
91    toJSON: function(object) {
92        var type = typeof object;
93        switch (type) {
94        case 'undefined':
95        case 'function':
96        case 'unknown':
97            return;
98        case 'boolean':
99            return object.toString();
100        }
101        if (object === null) return 'null';
102        if (object.toJSON) return object.toJSON();
103        if (Object.isElement(object)) return;
104        var results = [];
105        for (var property in object) {
106            var value = Object.toJSON(object[property]);
107            if (!Object.isUndefined(value)) results.push(property.toJSON() + ': ' + value);
108        }
109        return '{' + results.join(', ') + '}';
110    },
111    toQueryString: function(object) {
112        return $H(object).toQueryString();
113    },
114    toHTML: function(object) {
115        return object && object.toHTML ? object.toHTML() : String.interpret(object);
116    },
117    keys: function(object) {
118        var keys = [];
119        for (var property in object)
120        keys.push(property);
121        return keys;
122    },
123    values: function(object) {
124        var values = [];
125        for (var property in object)
126        values.push(object[property]);
127        return values;
128    },
129    clone: function(object) {
130        return Object.extend({}, object);
131    },
132    isElement: function(object) {
133        return !!(object && object.nodeType == 1);
134    },
135    isArray: function(object) {
136        return object != null && typeof object == "object" && 'splice' in object && 'join' in object;
137    },
138    isHash: function(object) {
139        return object instanceof Hash;
140    },
141    isFunction: function(object) {
142        return typeof object == "function";
143    },
144    isString: function(object) {
145        return typeof object == "string";
146    },
147    isNumber: function(object) {
148        return typeof object == "number";
149    },
150    isUndefined: function(object) {
151        return typeof object == "undefined";
152    }
153});
154Object.extend(Function.prototype, {
155    argumentNames: function() {
156        var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1].replace(/\s+/g, '').split(',');
157        return names.length == 1 && !names[0] ? [] : names;
158    },
159    bind: function() {
160        if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
161        var __method = this,
162            args = $A(arguments),
163            object = args.shift();
164        return function() {
165            return __method.apply(object, args.concat($A(arguments)));
166        }
167    },
168    bindAsEventListener: function() {
169        var __method = this,
170            args = $A(arguments),
171            object = args.shift();
172        return function(event) {
173            return __method.apply(object, [event || window.event].concat(args));
174        }
175    },
176    curry: function() {
177        if (!arguments.length) return this;
178        var __method = this,
179            args = $A(arguments);
180        return function() {
181            return __method.apply(this, args.concat($A(arguments)));
182        }
183    },
184    delay: function() {
185        var __method = this,
186            args = $A(arguments),
187            timeout = args.shift() * 1000;
188        return window.setTimeout(function() {
189            return __method.apply(__method, args);
190        }, timeout);
191    },
192    defer: function() {
193        var args = [0.01].concat($A(arguments));
194        return this.delay.apply(this, args);
195    },
196    wrap: function(wrapper) {
197        var __method = this;
198        return function() {
199            return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
200        }
201    },
202    methodize: function() {
203        if (this._methodized) return this._methodized;
204        var __method = this;
205        return this._methodized = function() {
206            return __method.apply(null, [this].concat($A(arguments)));
207        };
208    }
209});
210Date.prototype.toJSON = function() {
211    return '"' + this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z"';
212};
213var Try = {
214    these: function() {
215        var returnValue;
216        for (var i = 0, length = arguments.length; i < length; i++) {
217            var lambda = arguments[i];
218            try {
219                returnValue = lambda();
220                break;
221            } catch (e) {}
222        }
223        return returnValue;
224    }
225};
226RegExp.prototype.match = RegExp.prototype.test;
227RegExp.escape = function(str) {
228    return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
229};
230var PeriodicalExecuter = Class.create({
231    initialize: function(callback, frequency) {
232        this.callback = callback;
233        this.frequency = frequency;
234        this.currentlyExecuting = false;
235        this.registerCallback();
236    },
237    registerCallback: function() {
238        this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
239    },
240    execute: function() {
241        this.callback(this);
242    },
243    stop: function() {
244        if (!this.timer) return;
245        clearInterval(this.timer);
246        this.timer = null;
247    },
248    onTimerEvent: function() {
249        if (!this.currentlyExecuting) {
250            try {
251                this.currentlyExecuting = true;
252                this.execute();
253            } finally {
254                this.currentlyExecuting = false;
255            }
256        }
257    }
258});
259Object.extend(String, {
260    interpret: function(value) {
261        return value == null ? '' : String(value);
262    },
263    specialChar: {
264        '\b': '\\b',
265        '\t': '\\t',
266        '\n': '\\n',
267        '\f': '\\f',
268        '\r': '\\r',
269        '\\': '\\\\'
270    }
271});
272Object.extend(String.prototype, {
273    gsub: function(pattern, replacement) {
274        var result = '',
275            source = this,
276            match;
277        replacement = arguments.callee.prepareReplacement(replacement);
278        while (source.length > 0) {
279            if (match = source.match(pattern)) {
280                result += source.slice(0, match.index);
281                result += String.interpret(replacement(match));
282                source = source.slice(match.index + match[0].length);
283            } else {
284                result += source, source = '';
285            }
286        }
287        return result;
288    },
289    sub: function(pattern, replacement, count) {
290        replacement = this.gsub.prepareReplacement(replacement);
291        count = Object.isUndefined(count) ? 1 : count;
292        return this.gsub(pattern, function(match) {
293            if (--count < 0) return match[0];
294            return replacement(match);
295        });
296    },
297    scan: function(pattern, iterator) {
298        this.gsub(pattern, iterator);
299        return String(this);
300    },
301    truncate: function(length, truncation) {
302        length = length || 30;
303        truncation = Object.isUndefined(truncation) ? '...' : truncation;
304        return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this);
305    },
306    strip: function() {
307        return this.replace(/^\s+/, '').replace(/\s+$/, '');
308    },
309    stripTags: function() {
310        return this.replace(/<\/?[^>]+>/gi, '');
311    },
312    stripScripts: function() {
313        return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
314    },
315    extractScripts: function() {
316        var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
317        var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
318        return (this.match(matchAll) || []).map(function(scriptTag) {
319            return (scriptTag.match(matchOne) || ['', ''])[1];
320        });
321    },
322    evalScripts: function() {
323        return this.extractScripts().map(function(script) {
324            return eval(script)
325        });
326    },
327    escapeHTML: function() {
328        var self = arguments.callee;
329        self.text.data = this;
330        return self.div.innerHTML;
331    },
332    unescapeHTML: function() {
333        var div = new Element('div');
334        div.innerHTML = this.stripTags();
335        return div.childNodes[0] ? (div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) {
336            return memo + node.nodeValue
337        }) : div.childNodes[0].nodeValue) : '';
338    },
339    toQueryParams: function(separator) {
340        var match = this.strip().match(/([^?#]*)(#.*)?$/);
341        if (!match) return {};
342        return match[1].split(separator || '&').inject({}, function(hash, pair) {
343            if ((pair = pair.split('='))[0]) {
344                var key = decodeURIComponent(pair.shift());
345                var value = pair.length > 1 ? pair.join('=') : pair[0];
346                if (value != undefined) value = decodeURIComponent(value);
347                if (key in hash) {
348                    if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
349                    hash[key].push(value);
350                }
351                else hash[key] = value;
352            }
353            return hash;
354        });
355    },
356    toArray: function() {
357        return this.split('');
358    },
359    succ: function() {
360        return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
361    },
362    times: function(count) {
363        return count < 1 ? '' : new Array(count + 1).join(this);
364    },
365    camelize: function() {
366        var parts = this.split('-'),
367            len = parts.length;
368        if (len == 1) return parts[0];
369        var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0];
370        for (var i = 1; i < len; i++)
371        camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
372        return camelized;
373    },
374    capitalize: function() {
375        return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
376    },
377    underscore: function() {
378        return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '#{1}_#{2}').gsub(/([a-z\d])([A-Z])/, '#{1}_#{2}').gsub(/-/, '_').toLowerCase();
379    },
380    dasherize: function() {
381        return this.gsub(/_/, '-');
382    },
383    inspect: function(useDoubleQuotes) {
384        var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
385            var character = String.specialChar[match[0]];
386            return character ? character : '\\u00' + match[0].charCo
386deAt().toPaddedString(2, 16);
387        });
388        if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
389        return "'" + escapedString.replace(/'/g, '\\\'') + "'";
390    },
391    toJSON: function() {
392        return this.inspect(true);
393    },
394    unfilterJSON: function(filter) {
395        return this.sub(filter || Prototype.JSONFilter, '#{1}');
396    },
397    isJSON: function() {
398        var str = this;
399        if (str.blank()) return false;
400        str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
401        return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
402    },
403    evalJSON: function(sanitize) {
404        var json = this.unfilterJSON();
405        try {
406            if (!sanitize || json.isJSON()) return eval('(' + json + ')');
407        } catch (e) {}
408        throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
409    },
410    include: function(pattern) {
411        return this.indexOf(pattern) > -1;
412    },
413    startsWith: function(pattern) {
414        return this.indexOf(pattern) === 0;
415    },
416    endsWith: function(pattern) {
417        var d = this.length - pattern.length;
418        return d >= 0 && this.lastIndexOf(pattern) === d;
419    },
420    empty: function() {
421        return this == '';
422    },
423    blank: function() {
424        return /^\s*$/.test(this);
425    },
426    interpolate: function(object, pattern) {
427        return new Template(this, pattern).evaluate(object);
428    }
429});
430if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
431    escapeHTML: function() {
432        return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
433    },
434    unescapeHTML: function() {
435        return this.stripTags().replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
436    }
437});
438String.prototype.gsub.prepareReplacement = function(replacement) {
439    if (Object.isFunction(replacement)) return replacement;
440    var template = new Template(replacement);
441    return function(match) {
442        return template.evaluate(match)
443    };
444};
445String.prototype.parseQuery = String.prototype.toQueryParams;
446Object.extend(String.prototype.escapeHTML, {
447    div: document.createElement('div'),
448    text: document.createTextNode('')
449});
450String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
451var Template = Class.create({
452    initialize: function(template, pattern) {
453        this.template = template.toString();
454        this.pattern = pattern || Template.Pattern;
455    },
456    evaluate: function(object) {
457        if (Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements();
458        return this.template.gsub(this.pattern, function(match) {
459            if (object == null) return '';
460            var before = match[1] || '';
461            if (before == '\\') return match[2];
462            var ctx = object,
463                expr = match[3];
464            var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
465            match = pattern.exec(expr);
466            if (match == null) return before;
467            while (match != null) {
468                var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
469                ctx = ctx[comp];
470                if (null == ctx || '' == match[3]) break;
471                expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
472                match = pattern.exec(expr);
473            }
474            return before + String.interpret(ctx);
475        });
476    }
477});
478Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
479var $break = {};
480var Enumerable = {
481    each: function(iterator, context) {
482        var index = 0;
483        try {
484            this._each(function(value) {
485                iterator.call(context, value, index++);
486            });
487        } catch (e) {
488            if (e != $break) throw e;
489        }
490        return this;
491    },
492    eachSlice: function(number, iterator, context) {
493        var index = -number,
494            slices = [],
495            array = this.toArray();
496        if (number < 1) return array;
497        while ((index += number) < array.length)
498        slices.push(array.slice(index, index + number));
499        return slices.collect(iterator, context);
500    },
501    all: function(iterator, context) {
502        iterator = iterator || Prototype.K;
503        var result = true;
504        this.each(function(value, index) {
505            result = result && !! iterator.call(context, value, index);
506            if (!result) throw $break;
507        });
508        return result;
509    },
510    any: function(iterator, context) {
511        iterator = iterator || Prototype.K;
512        var result = false;
513        this.each(function(value, index) {
514            if (result = !! iterator.call(context, value, index)) throw $break;
515        });
516        return result;
517    },
518    collect: function(iterator, context) {
519        iterator = iterator || Prototype.K;
520        var results = [];
521        this.each(function(value, index) {
522            results.push(iterator.call(context, value, index));
523        });
524        return results;
525    },
526    detect: function(iterator, context) {
527        var result;
528        this.each(function(value, index) {
529            if (iterator.call(context, value, index)) {
530                result = value;
531                throw $break;
532            }
533        });
534        return result;
535    },
536    findAll: function(iterator, context) {
537        var results = [];
538        this.each(function(value, index) {
539            if (iterator.call(context, value, index)) results.push(value);
540        });
541        return results;
542    },
543    grep: function(filter, iterator, context) {
544        iterator = iterator || Prototype.K;
545        var results = [];
546        if (Object.isString(filter)) filter = new RegExp(filter);
547        this.each(function(value, index) {
548            if (filter.match(value)) results.push(iterator.call(context, value, index));
549        });
550        return results;
551    },
552    include: function(object) {
553        if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true;
554        var found = false;
555        this.each(function(value) {
556            if (value == object) {
557                found = true;
558                throw $break;
559            }
560        });
561        return found;
562    },
563    inGroupsOf: function(number, fillWith) {
564        fillWith = Object.isUndefined(fillWith) ? null : fillWith;
565        return this.eachSlice(number, function(slice) {
566            while (slice.length < number) slice.push(fillWith);
567            return slice;
568        });
569    },
570    inject: function(memo, iterator, context) {
571        this.each(function(value, index) {
572            memo = iterator.call(context, memo, value, index);
573        });
574        return memo;
575    },
576    invoke: function(method) {
577        var args = $A(arguments).slice(1);
578        return this.map(function(value) {
579            return value[method].apply(value, args);
580        });
581    },
582    max: function(iterator, context) {
583        iterator = iterator || Prototype.K;
584        var result;
585        this.each(function(value, index) {
586            value = iterator.call(context, value, index);
587            if (result == null || value >= result) result = value;
588        });
589        return result;
590    },
591    min: function(iterator, context) {
592        iterator = iterator || Prototype.K;
593        var result;
594        this.each(function(value, index) {
595            value = iterator.call(context, value, index);
596            if (result == null || value < result) result = value;
597        });
598        return result;
599    },
600    partition: function(iterator, context) {
601        iterator = iterator || Prototype.K;
602        var trues = [],
603            falses = [];
604        this.each(function(value, index) {
605            (iterator.call(context, value, index) ? trues : falses).push(value);
606        });
607        return [trues, falses];
608    },
609    pluck: function(property) {
610        var results = [];
611        this.each(function(value) {
612            results.push(value[property]);
613        });
614        return results;
615    },
616    reject: function(iterator, context) {
617        var results = [];
618        this.each(function(value, index) {
619            if (!iterator.call(context, value, index)) results.push(value);
620        });
621        return results;
622    },
623    sortBy: function(iterator, context) {
624        return this.map(function(value, index) {
625            return {
626                value: value,
627                criteria: iterator.call(context, value, index)
628            };
629        }).sort(function(left, right) {
630            var a = left.criteria,
631                b = right.criteria;
632            return a < b ? -1 : a > b ? 1 : 0;
633        }).pluck('value');
634    },
635    toArray: function() {
636        return this.map();
637    },
638    zip: function() {
639        var iterator = Prototype.K,
640            args = $A(arguments);
641        if (Object.isFunction(args.last())) iterator = args.pop();
642        var collections = [this].concat(args).map($A);
643        return this.map(function(value, index) {
644            return iterator(collections.pluck(index));
645        });
646    },
647    size: function() {
648        return this.toArray().length;
649    },
650    inspect: function() {
651        return '#<Enumerable:' + this.toArray().inspect() + '>';
652    }
653};
654Object.extend(Enumerable, {
655    map: Enumerable.collect,
656    find: Enumerable.detect,
657    select: Enumerable.findAll,
658    filter: Enumerable.findAll,
659    member: Enumerable.include,
660    entries: Enumerable.toArray,
661    every: Enumerable.all,
662    some: Enumerable.any
663});
664
665function $A(iterable) {
666    if (!iterable) return [];
667    if (iterable.toArray) return iterable.toArray();
668    var length = iterable.length || 0,
669        results = new Array(length);
670    while (length--) results[length] = iterable[length];
671    return results;
672}
673if (Prototype.Browser.WebKit) {
674    $A = function(iterable) {
675        if (!iterable) return [];
676        if (!(typeof iterable === 'function' && typeof iterable.length === 'number' && typeof iterable.item === 'function') && iterable.toArray) return iterable.toArray();
677        var length = iterable.length || 0,
678            results = new Array(length);
679        while (length--) results[length] = iterable[length];
680        return results;
681    };
682}
683Array.from = $A;
684Object.extend(Array.prototype, Enumerable);
685if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
686Object.extend(Array.prototype, {
687    _each: function(iterator) {
688        for (var i = 0, length = this.length; i < length; i++)
689        iterator(this[i]);
690    },
691    clear: function() {
692        this.length = 0;
693        return this;
694    },
695    first: function() {
696        return this[0];
697    },
698    last: function() {
699        return this[this.length - 1];
700    },
701    compact: function() {
702        return this.select(function(value) {
703            return value != null;
704        });
705    },
706    flatten: function() {
707        return this.inject([], function(array, value) {
708            return array.concat(Object.isArray(value) ? value.flatten() : [value]);
709        });
710    },
711    without: function() {
712        var values = $A(arguments);
713        return this.select(function(value) {
714            return !values.include(value);
715        });
716    },
717    reverse: function(inline) {
718        return (inline !== false ? this : this.toArray())._reverse();
719    },
720    reduce: function() {
721        return this.length >
721 1 ? this : this[0];
722    },
723    uniq: function(sorted) {
724        return this.inject([], function(array, value, index) {
725            if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value);
726            return array;
727        });
728    },
729    intersect: function(array) {
730        return this.uniq().findAll(function(item) {
731            return array.detect(function(value) {
732                return item === value
733            });
734        });
735    },
736    clone: function() {
737        return [].concat(this);
738    },
739    size: function() {
740        return this.length;
741    },
742    inspect: function() {
743        return '[' + this.map(Object.inspect).join(', ') + ']';
744    },
745    toJSON: function() {
746        var results = [];
747        this.each(function(object) {
748            var value = Object.toJSON(object);
749            if (!Object.isUndefined(value)) results.push(value);
750        });
751        return '[' + results.join(', ') + ']';
752    }
753});
754if (Object.isFunction(Array.prototype.forEach)) Array.prototype._each = Array.prototype.forEach;
755if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
756    i || (i = 0);
757    var length = this.length;
758    if (i < 0) i = length + i;
759    for (; i < length; i++)
760    if (this[i] === item) return i;
761    return -1;
762};
763if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
764    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
765    var n = this.slice(0, i).reverse().indexOf(item);
766    return (n < 0) ? n : i - n - 1;
767};
768Array.prototype.toArray = Array.prototype.clone;
769
770function $w(string) {
771    if (!Object.isString(string)) return [];
772    string = string.strip();
773    return string ? string.split(/\s+/) : [];
774}
775if (Prototype.Browser.Opera) {
776    Array.prototype.concat = function() {
777        var array = [];
778        for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
779        for (var i = 0, length = arguments.length; i < length; i++) {
780            if (Object.isArray(arguments[i])) {
781                for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
782                array.push(arguments[i][j]);
783            } else {
784                array.push(arguments[i]);
785            }
786        }
787        return array;
788    };
789}
790Object.extend(Number.prototype, {
791    toColorPart: function() {
792        return this.toPaddedString(2, 16);
793    },
794    succ: function() {
795        return this + 1;
796    },
797    times: function(iterator, context) {
798        $R(0, this, true).each(iterator, context);
799        return this;
800    },
801    toPaddedString: function(length, radix) {
802        var string = this.toString(radix || 10);
803        return '0'.times(length - string.length) + string;
804    },
805    toJSON: function() {
806        return isFinite(this) ? this.toString() : 'null';
807    }
808});
809$w('abs round ceil floor').each(function(method) {
810    Number.prototype[method] = Math[method].methodize();
811});
812
813function $H(object) {
814    return new Hash(object);
815};
816var Hash = Class.create(Enumerable, (function() {
817    function toQueryPair(key, value) {
818        if (Object.isUndefined(value)) return key;
819        return key + '=' + encodeURIComponent(String.interpret(value));
820    }
821    return {
822        initialize: function(object) {
823            this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
824        },
825        _each: function(iterator) {
826            for (var key in this._object) {
827                var value = this._object[key],
828                    pair = [key, value];
829                pair.key = key;
830                pair.value = value;
831                iterator(pair);
832            }
833        },
834        set: function(key, value) {
835            return this._object[key] = value;
836        },
837        get: function(key) {
838            if (this._object[key] !== Object.prototype[key]) return this._object[key];
839        },
840        unset: function(key) {
841            var value = this._object[key];
842            delete this._object[key];
843            return value;
844        },
845        toObject: function() {
846            return Object.clone(this._object);
847        },
848        keys: function() {
849            return this.pluck('key');
850        },
851        values: function() {
852            return this.pluck('value');
853        },
854        index: function(value) {
855            var match = this.detect(function(pair) {
856                return pair.value === value;
857            });
858            return match && match.key;
859        },
860        merge: function(object) {
861            return this.clone().update(object);
862        },
863        update: function(object) {
864            return new Hash(object).inject(this, function(result, pair) {
865                result.set(pair.key, pair.value);
866                return result;
867            });
868        },
869        toQueryString: function() {
870            return this.inject([], function(results, pair) {
871                var key = encodeURIComponent(pair.key),
872                    values = pair.value;
873                if (values && typeof values == 'object') {
874                    if (Object.isArray(values)) return results.concat(values.map(toQueryPair.curry(key)));
875                } else results.push(toQueryPair(key, values));
876                return results;
877            }).join('&');
878        },
879        inspect: function() {
880            return '#<Hash:{' + this.map(function(pair) {
881                return pair.map(Object.inspect).join(': ');
882            }).join(', ') + '}>';
883        },
884        toJSON: function() {
885            return Object.toJSON(this.toObject());
886        },
887        clone: function() {
888            return new Hash(this);
889        }
890    }
891})());
892Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
893Hash.from = $H;
894var ObjectRange = Class.create(Enumerable, {
895    initialize: function(start, end, exclusive) {
896        this.start = start;
897        this.end = end;
898        this.exclusive = exclusive;
899    },
900    _each: function(iterator) {
901        var value = this.start;
902        while (this.include(value)) {
903            iterator(value);
904            value = value.succ();
905        }
906    },
907    include: function(value) {
908        if (value < this.start) return false;
909        if (this.exclusive) return value < this.end;
910        return value <= this.end;
911    }
912});
913var $R = function(start, end, exclusive) {
914    return new ObjectRange(start, end, exclusive);
915};
916var Ajax = {
917    getTransport: function() {
918        return Try.these(function() {
919            return new XMLHttpRequest()
920        }, function() {
921            return new ActiveXObject('Msxml2.XMLHTTP')
922        }, function() {
923            return new ActiveXObject('Microsoft.XMLHTTP')
924        }) || false;
925    },
926    activeRequestCount: 0
927};
928Ajax.Responders = {
929    responders: [],
930    _each: function(iterator) {
931        this.responders._each(iterator);
932    },
933    register: function(responder) {
934        if (!this.include(responder)) this.responders.push(responder);
935    },
936    unregister: function(responder) {
937        this.responders = this.responders.without(responder);
938    },
939    dispatch: function(callback, request, transport, json) {
940        this.each(function(responder) {
941            if (Object.isFunction(responder[callback])) {
942                try {
943                    responder[callback].apply(responder, [request, transport, json]);
944                } catch (e) {}
945            }
946        });
947    }
948};
949Object.extend(Ajax.Responders, Enumerable);
950Ajax.Responders.register({
951    onCreate: function() {
952        Ajax.activeRequestCount++
953    },
954    onComplete: function() {
955        Ajax.activeRequestCount--
956    }
957});
958Ajax.Base = Class.create({
959    initialize: function(options) {
960        this.options = {
961            method: 'post',
962            asynchronous: true,
963            contentType: 'application/x-www-form-urlencoded',
964            encoding: 'UTF-8',
965            parameters: '',
966            evalJSON: true,
967            evalJS: true
968        };
969        Object.extend(this.options, options || {});
970        this.options.method = this.options.method.toLowerCase();
971        if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams();
972        else if (Object.isHash(this.options.parameters)) this.options.parameters = this.options.parameters.toObject();
973    }
974});
975Ajax.Request = Class.create(Ajax.Base, {
976    _complete: false,
977    initialize: function($super, url, options) {
978        $super(options);
979        this.transport = Ajax.getTransport();
980        this.request(url);
981    },
982    request: function(url) {
983        this.url = url;
984        this.method = this.options.method;
985        var params = Object.clone(this.options.parameters);
986        if (!['get', 'post'].include(this.method)) {
987            params['_method'] = this.method;
988            this.method = 'post';
989        }
990        this.parameters = params;
991        if (params = Object.toQueryString(params)) {
992            if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params;
993            else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=';
994        }
995        try {
996            var response = new Ajax.Response(this);
997            if (this.options.onCreate) this.options.onCreate(response);
998            Ajax.Responders.dispatch('onCreate', this, response);
999            this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous);
1000            if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1001            this.transport.onreadystatechange = this.onStateChange.bind(this);
1002            this.setRequestHeaders();
1003            this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1004            this.transport.send(this.body);
1005            if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange();
1006        }
1007        catch (e) {
1008            this.dispatchException(e);
1009        }
1010    },
1011    onStateChange: function() {
1012        var readyState = this.transport.readyState;
1013        if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState);
1014    },
1015    setRequestHeaders: function() {
1016        var headers = {
1017            'X-Requested-With': 'XMLHttpRequest',
1018            'X-Prototype-Version': Prototype.Version,
1019            'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1020        };
1021        if (this.method == 'post') {
1022            headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : '');
1023            if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1] < 2005) headers['Connection'] = 'close';
1024        }
1025        if (typeof this.options.requestHeaders == 'object') {
1026            var extras = this.options.requestHeaders;
1027            if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i + 1];
1028            else $H(extras).each(function(pair) {
1029                headers[pair.key] = pair.value
1030            });
1031        }
1032        for (var name in headers)
1033        this.transport.setRequestHeader(name, headers[name]);
1034    },
1035    success: function() {
1036        var status = this.getStatus();
1037        return !status || (status >= 200 && status < 300);
1038    },
1039    getStatus: function() {
1040        try {
1041            return this.transport.status || 0;
1042        } catch (e) {
1043            return 0
1044        }
1045    },
1046    respondToReadyState: function(readyState) {
1047        var state = Ajax.Request.Events[readyState],
1048            response = new Ajax.Response(this);
1049        if (state == 'Complete') {
1050            try {
1051                this._complete = true;
1052                (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON);
1053            } catch (e) {
1054                this.dispatchException(e);
1055            }
1056            var contentType = response.getHeader('Content-type');
1057            if (this.options.evalJS == 'force' || (this.options.evalJS && this.isSameOrigin() && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse();
1058        }
1059        try {
1060            (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1061            Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1062        } catch (e) {
1063            this.dispatchException(e);
1064        }
1065        if (state == 'Complete') {
1066            this.transport.onreadystatechange = Prototype.emptyFunction;
1067        }
1068    },
1069    isSameOrigin: function() {
1070        var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1071        return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1072            protocol: location.protocol,
1073            domain: document.domain,
1074            port: location.port ? ':' + location.port : ''
1075        }));
1076    },
1077    getHeader: function(name) {
1078        try {
1079            return this.transport.getResponseHeader(name) || null;
1080        } catch (e) {
1081            return null
1082        }
1083    },
1084    evalResponse: function() {
1085        try {
1086            return eval((this.transport.responseText || '').unfilterJSON());
1087        } catch (e) {
1088            this.dispatchException(e);
1089        }
1090    },
1091    dispatchException: function(exception) {
1092        (this.options.onException || Prototype.emptyFunction)(this, exception);
1093        Ajax.Responders.dispatch('onException', this, exception);
1094    }
1095});
1096Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1097Ajax.Response = Class.create({
1098    initialize: function(request) {
1099        this.request = request;
1100        var transport = this.transport = request.transport,
1101            readyState = this.readyState = transport.readyState;
1102        if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1103            this.status = this.getStatus();
1104            this.statusText = this.getStatusText();
1105            this.responseText = String.interpret(transport.responseText);
1106            this.headerJSON = this._getHeaderJSON();
1107        }
1108        if (readyState == 4) {
1109            var xml = transport.responseXML;
1110            this.responseXML = Object.isUndefined(xml) ? null : xml;
1111            this.responseJSON = this._getResponseJSON();
1112        }
1113    },
1114    status: 0,
1115    statusText: '',
1116    getStatus: Ajax.Request.prototype.getStatus,
1117    getStatusText: function() {
1118        try {
1119            return this.transport.statusText || '';
1120        } catch (e) {
1121            return ''
1122        }
1123    },
1124    getHeader: Ajax.Request.prototype.getHeader,
1125    getAllHeaders: function() {
1126        try {
1127            return this.getAllResponseHeaders();
1128        } catch (e) {
1129            return null
1130        }
1131    },
1132    getResponseHeader: function(name) {
1133        return this.transport.getResponseHeader(name);
1134    },
1135    getAllResponseHeaders: function() {
1136        return this.transport.getAllResponseHeaders();
1137    },
1138    _getHeaderJSON: function() {
1139        var json = this.getHeader('X-JSON');
1140        if (!json) return null;
1141        json = decodeURIComponent(escape(json));
1142        try {
1143            return json.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin());
1144        } catch (e) {
1145            this.request.dispatchException(e);
1146        }
1147    },
1148    _getResponseJSON: function() {
1149        var options = this.request.options;
1150        if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json')) || this.responseText.blank()) return null;
1151        try {
1152            return this.responseText.evalJSON(options.sanitizeJSON || !this.request.isSameOrigin());
1153        } catch (e) {
1154            this.request.dispatchException(e);
1155        }
1156    }
1157});
1158Ajax.Updater = Class.create(Ajax.Request, {
1159    initialize: function($super, container, url, options) {
1160        this.container = {
1161            success: (container.success || container),
1162            failure: (container.failure || (container.success ? null : container))
1163        };
1164        options = Object.clone(options);
1165        var onComplete = options.onComplete;
1166        options.onComplete = (function(response, json) {
1167            this.updateContent(response.responseText);
1168            if (Object.isFunction(onComplete)) onComplete(response, json);
1169        }).bind(this);
1170        $super(url, options);
1171    },
1172    updateContent: function(responseText) {
1173        var receiver = this.container[this.success() ? 'success' : 'failure'],
1174            options = this.options;
1175        if (!options.evalScripts) responseText = responseText.stripScripts();
1176        if (receiver = $(receiver)) {
1177            if (options.insertion) {
1178                if (Object.isString(options.insertion)) {
1179                    var insertion = {};
1180                    insertion[options.insertion] = responseText;
1181                    receiver.insert(insertion);
1182                }
1183                else options.insertion(receiver, responseText);
1184            }
1185            else receiver.update(responseText);
1186        }
1187    }
1188});
1189Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1190    initialize: function($super, container, url, options) {
1191        $super(options);
1192        this.onComplete = this.options.onComplete;
1193        this.frequency = (this.options.frequency || 2);
1194        this.decay = (this.options.decay || 1);
1195        this.updater = {};
1196        this.container = container;
1197        this.url = url;
1198        this.start();
1199    },
1200    start: function() {
1201        this.options.onComplete = this.updateComplete.bind(this);
1202        this.onTimerEvent();
1203    },
1204    stop: function() {
1205        this.updater.options.onComplete = undefined;
1206        clearTimeout(this.timer);
1207        (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1208    },
1209    updateComplete: function(response) {
1210        if (this.options.decay) {
1211            this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1);
1212            this.lastText = response.responseText;
1213        }
1214        this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1215    },
1216    onTimerEvent: function() {
1217        this.updater = new Ajax.Updater(this.container, this.url, this.options);
1218    }
1219});
1220
1221function $(element) {
1222    if (arguments.length > 1) {
1223        for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1224        elements.push($(arguments[i]));
1225        return elements;
1226    }
1227    if (Object.isString(element)) element = document.getElementById(element);
1228    return Element.extend(element);
1229}
1230if (Prototype.BrowserFeatures.XPath) {
1231    document._getElementsByXPath = function(expression, parentElement) {
1232        var results = [];
1233        var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1234        for (var i = 0, length = query.snapshotLength; i < length; i++)
1235        results.push(Element.extend(query.snapshotItem(i)));
1236        return results;
1237    };
1238}
1239if (!window.Node) var Node = {};
1240if (!Node.ELEMENT_NODE) {
1241    Object.extend(Node, {
1242        ELEMENT_NODE: 1,
1243        ATTRIBUTE_NODE: 2,
1244        TEXT_NODE: 3,
1245        CDATA_SECTION_NODE: 4,
1246        ENTITY_REFERENCE_NODE: 5,
1247        ENTITY_NODE: 6,
1248        PROCESSING_INSTRUCTION_NODE: 7,
1249        COMMENT_NODE: 8,
1250        DOCUMENT_NODE: 9,
1251        DOCUMENT_TYPE_NODE: 10,
1252        DOCUMENT_FRAGMENT_NODE: 11,
1253        NOTATION_NODE: 12
1254    });
1255}(function() {
1256    var element = this.Element;
1257    this.Element = function(tagName, attributes) {
1258        attributes = attributes || {};
1259        tagName = tagName.toLowerCase();
1260        var cache = Element.cache;
1261        if (Prototype.Browser.IE && attributes.name) {
1262            tagName = '<' + tagName + ' name="' + attributes.name + '">';
1263            delete attributes.name;
1264            return Element.writeAttribute(document.createElement(tagName), attributes);
1265        }
1266        if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1267        return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
1268    };
1269    Object.extend(this.Element, element || {});
1270    if (element) this.Element.prototype = element.prototype;
1271}).call(window);
1272Element.cache = {};
1273Element.Methods = {
1274    visible: function(element) {
1275        return $(element).style.display != 'none';
1276    },
1277    toggle: function(element) {
1278        element = $(element);
1279        Element[Element.visible(element) ? 'hide' : 'show'](element);
1280        return element;
1281    },
1282    hide: function(element) {
1283        element = $(element);
1284        element.style.display = 'none';
1285        return element;
1286    },
1287    show: function(element) {
1288        element = $(element);
1289        element.style.display = '';
1290        return element;
1291    },
1292    remove: function(element) {
1293        element = $(element);
1294        element.parentNode.removeChild(element);
1295        return element;
1296    },
1297    update: function(element, content) {
1298        element = $(element);
1299        if (content && content.toElement) content = content.toElement();
1300        if (Object.isElement(content)) return element.update().insert(content);
1301        content = Object.toHTML(content);
1302        element.innerHTML = content.stripScripts();
1303        content.evalScripts.bind(content).defer();
1304        return element;
1305    },
1306    replace: function(element, content) {
1307        element = $(element);
1308        if (content && content.toElement) content = content.toElement();
1309        else if (!Object.isElement(content)) {
1310            content = Object.toHTML(content);
1311            var range = element.ownerDocument.createRange();
1312            range.selectNode(element);
1313            content.evalScripts.bind(content).defer();
1314            content = range.createContextualFragment(content.stripScripts());
1315        }
1316        element.parentNode.replaceChild(content, element);
1317        return element;
1318    },
1319    insert: function(element, insertions) {
1320        element = $(element);
1321        if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {
1322            bottom: insertions
1323        };
1324        var content, insert, tagName, childNodes;
1325        for (var position in insertions) {
1326            content = insertions[position];
1327            position = position.toLowerCase();
1328            insert = Element._insertionTranslations[position];
1329            if (content && content.toElement) content = content.toElement();
1330            if (Object.isElement(content)) {
1331                insert(element, content);
1332                continue;
1333            }
1334            content = Object.toHTML(content);
1335            tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase();
1336            childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
1337            if (position == 'top' || position == 'after') childNodes.reverse();
1338            childNodes.each(insert.curry(element));
1339            content.evalScripts.bind(content).defer();
1340        }
1341        return element;
1342    },
1343    wrap: function(element, wrapper, attributes) {
1344        element = $(element);
1345        if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || {});
1346        else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
1347        else wrapper = new Element('div', wrapper);
1348        if (element.parentNode) element.parentNode.replaceChild(wrapper, element);
1349        wrapper.appendChild(element);
1350        return wrapper;
1351    },
1352    inspect: function(element) {
1353        element = $(element);
1354        var result = '<' + element.tagName.toLowerCase();
1355        $H({
1356            'id': 'id',
1357            'className': 'class'
1358        }).each(function(pair) {
1359            var property = pair.first(),
1360                attribute = pair.last();
1361            var value = (element[property] || '').toString();
1362            if (value) result += ' ' + attribute + '=' + value.inspect(true);
1363        });
1364        return result + '>';
1365    },
1366    recursivelyCollect: function(element, property) {
1367        element = $(element);
1368        var elements = [];
1369        while (element = element[property])
1370        if (element.nodeType == 1) elements.push(Element.extend(element));
1371        return elements;
1372    },
1373    ancestors: function(element) {
1374        return $(element).recursivelyCollect('parentNode');
1375    },
1376    descendants: function(element) {
1377        return $(element).select("*");
1378    },
1379    firstDescendant: function(element) {
1380        element = $(element).firstChild;
1381        while (element && element.nodeType != 1) element = element.nextSibling;
1382        return $(element);
1383    },
1384    immediateDescendants: function(element) {
1385        if (!(element = $(element).firstChild)) return [];
1386        while (element && element.nodeType != 1) element = element.nextSibling;
1387        if (element) return [element].concat($(element).nextSiblings());
1388        return [];
1389    },
1390    previousSiblings: function(element) {
1391        return $(element).recursivelyCollect('previousSibling');
1392    },
1393    nextSiblings: function(element) {
1394        return $(element).recursivelyCollect('nextSibling');
1395    },
1396    siblings: function(element) {
1397        element = $(element);
1398        return element.previousSiblings().reverse().concat(element.nextSiblings());
1399    },
1400    match: function(element, selector) {
1401        if (Object.isString(selector)) selector = new Selector(selector);
1402        return selector.match($(element));
1403    },
1404    up: function(element, expression, index) {
1405        element = $(element);
1406        if (arguments.length == 1) return $(element.parentNode);
1407        var ancestors = element.ancestors();
1408        return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index);
1409    },
1410    down: function(element, expression, index) {
1411        element = $(element);
1412        if (arguments.length == 1) return element.firstDescendant();
1413        return Object.isNumber(expression) ? element.descendants()[expression] : Element.select(element, expression)[index || 0];
1414    },
1415    previous: function(element, expression, index) {
1416        element = $(element);
1417        if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1418        var previousSiblings = element.previousSiblings();
1419        return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index);
1420    },
1421    next: function(element, expression, index) {
1422        element = $(element);
1423        if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1424        var nextSiblings = element.nextSiblings();
1425        return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index);
1426    },
1427    select: function() {
1428        var args = $A(arguments),
1429            element = $(args.shift());
1430        return Selector.findChildElements(element, args);
1431    },
1432    adjacent: function() {
1433        var args = $A(arguments),
1434            element = $(args.shift());
1435        return Selector.findChildElements(element.parentNode, args).without(element);
1436    },
1437    identify: function(element) {
1438        element = $(element);
1439        var id = element.readAttribute('id'),
1440            self = arguments.callee;
1441        if (id) return id;
1442        do {
1443            id = 'anonymous_element_' + self.counter++
1444        } while ($(id));
1445        element.writeAttribute('id', id);
1446        return id;
1447    },
1448    readAttribute: function(element, name) {
1449        element = $(element);
1450        if (Prototype.Browser.IE) {
1451            var t = Element._attributeTranslations.read;
1452            if (t.values[name]) return t.values[name](element, name);
1453            if (t.names[name]) name = t.names[name];
1454            if (name.include(':')) {
1455                return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value;
1456            }
1457        }
1458        return element.getAttribute(name);
1459    },
1460    writeAttribute: function(element, name, value) {
1461        element = $(element);
1462        var attributes = {},
1463            t = Element._attributeTranslations.write;
1464        if (typeof name == 'object') attributes = name;
1465        else attributes[name] = Object.isUndefined(value) ? true : value;
1466        for (var attr in attributes) {
1467            name = t.names[attr] || attr;
1468            value = attributes[attr];
1469            if (t.values[attr]) name = t.values[attr](element, value);
1470            if (value === false || value === null) element.removeAttribute(name);
1471            else if (value === true) element.setAttribute(name, name);
1472            else element.setAttribute(name, value);
1473        }
1474        return element;
1475    },
1476    getHeight: function(element) {
1477        return $(element).getDimensions().height;
1478    },
1479    getWidth: function(element) {
1480        return $(element).getDimensions().width;
1481    },
1482    classNames: function(element) {
1483        return new Element.ClassNames(element);
1484    },
1485    hasClassName: function(element, className) {
1486        if (!(element = $(element))) return;
1487        var elementClassName = element.className;
1488        return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
1489    },
1490    addClassName: function(element, className) {
1491        if (!(element = $(element))) return;
1492        if (!element.hasClassName(className)) element.className += (element.className ? ' ' : '') + className;
1493        return element;
1494    },
1495    removeClassName: function(element, className) {
1496        if (!(element = $(element))) return;
1497        element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
1498        return element;
1499    },
1500    toggleClassName: function(element, className) {
1501        if (!(element = $(element))) return;
1502        return element[element.hasClassName(className) ? 'removeClassName' : 'addClassName'](className);
1503    },
1504    cleanWhitespace: function(element) {
1505        element = $(element);
1506        var node = element.firstChild;
1507        while (node) {
1508            var nextNode = node.nextSibling;
1509            if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node);
1510            node = nextNode;
1511        }
1512        return element;
1513    },
1514    empty: function(element) {
1515        return $(element).innerHTML.blank();
1516    },
1517    descendantOf: function(element, ancestor) {
1518        element = $(element), ancestor = $(ancestor);
1519        if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8;
1520        if (ancestor.contains) return ancestor.contains(element) && ancestor !== element;
1521        while (element = element.parentNode)
1522        if (element == ancestor) return true;
1523        return false;
1524    },
1525    scrollTo: function(element) {
1526        element = $(element);
1527        var pos = element.cumulativeOffset();
1528        window.scrollTo(pos[0], pos[1]);
1529        return element;
1530    },
1531    getStyle: function(element, style) {
1532        element = $(element);
1533        style = style == 'float' ? 'cssFloat' : style.camelize();
1534        var value = element.style[style];
1535        if (!value || value == 'auto') {
1536            var css = document.defaultView.getComputedStyle(element, null);
1537            value = css ? css[style] : null;
1538        }
1539        if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1540        return value == 'auto' ? null : value;
1541    },
1542    getOpacity: function(element) {
1543        return $(element).getStyle('opacity');
1544    },
1545    setStyle: function(element, styles) {
1546        element = $(element);
1547        var elementStyle = element.style,
1548            match;
1549        if (Object.isString(styles)) {
1550            element.style.cssText += ';' + styles;
1551            return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
1552        }
1553        for (var property in styles)
1554        if (property == 'opacity') element.setOpacity(styles[property]);
1555        else elementStyle[(property == 'float' || property == 'cssFloat') ? (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : property] = styles[property];
1556        return element;
1557    },
1558    setOpacity: function(element, value) {
1559        element = $(element);
1560        element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value;
1561        return element;
1562    },
1563    getDimensions: function(element) {
1564        element = $(element);
1565        var display = element.getStyle('display');
1566        if (display != 'none' && display != null) return {
1567            width: element.offsetWidth,
1568            height: element.offsetHeight
1569        };
1570        var els = element.style;
1571        var originalVisibility = els.visibility;
1572        var originalPosition = els.position;
1573        var originalDisplay = els.display;
1574        els.visibility = 'hidden';
1575        els.position = 'absolute';
1576        els.display = 'block';
1577        var originalWidth = element.clientWidth;
1578        var originalHeight = element.clientHeight;
1579        els.display = originalDisplay;
1580        els.position = originalPosition;
1581        els.visibility = originalVisibility;
1582        return {
1583            width: originalWidth,
1584            height: originalHeight
1585        };
1586    },
1587    makePositioned: function(element) {
1588        element = $(element);
1589        var pos = Element.getStyle(element, 'position');
1590        if (pos == 'static' || !pos) {
1591            element._madePositioned = true;
1592            element.style.position = 'relative';
1593            if (Prototype.Browser.Opera) {
1594                element.style.top = 0;
1595                element.style.left = 0;
1596            }
1597        }
1598        return element;
1599    },
1600    undoPositioned: function(element) {
1601        element = $(element);
1602        if (element._madePositioned) {
1603            element._madePositioned = undefined;
1604            element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
1605        }
1606        return element;
1607    },
1608    makeClipping: function(element) {
1609        element = $(element);
1610        if (element._overflow) return element;
1611        element._overflow = Element.getStyle(element, 'overflow') || 'auto';
1612        if (element._overflow !== 'hidden') element.style.overflow = 'hidden';
1613        return element;
1614    },
1615    undoClipping: function(element) {
1616        element = $(element);
1617        if (!element._overflow) return element;
1618        element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1619        element._overflow = null;
1620        return element;
1621    },
1622    cumulativeOffset: function(element) {
1623        var valueT = 0,
1624            valueL = 0;
1625        do {
1626            valueT += element.offsetTop || 0;
1627            valueL += element.offsetLeft || 0;
1628            element = element.offsetParent;
1629        } while (element);
1630        return Element._returnOffset(valueL, valueT);
1631    },
1632    positionedOffset: function(element) {
1633        var valueT = 0,
1634            valueL = 0;
1635        do {
1636            valueT += element.offsetTop || 0;
1637            valueL += element.offsetLeft || 0;
1638            element = element.offsetParent;
1639            if (element) {
1640                if (element.tagName.toUpperCase() == 'BODY') break;
1641                var p = Element.getStyle(element, 'position');
1642                if (p !== 'static') break;
1643            }
1644        } while (element);
1645        return Element._returnOffset(valueL, valueT);
1646    },
1647    absolutize: function(element) {
1648        element = $(element);
1649        if (element.getStyle('position') == 'absolute') return element;
1650        var offsets = element.positionedOffset();
1651        var top = offsets[1];
1652        var left = offsets[0];
1653        var width = element.clientWidth;
1654        var height = element.clientHeight;
1655        element._originalLeft = left - parseFloat(element.style.left || 0);
1656        element._originalTop = top - parseFloat(element.style.top || 0);
1657        element._originalWidth = element.style.width;
1658        element._originalHeight = element.style.height;
1659        element.style.position = 'absolute';
1660        element.style.top = top + 'px';
1661        element.style.left = left + 'px';
1662        element.style.width = width + 'px';
1663        element.style.height = height + 'px';
1664        return element;
1665    },
1666    relativize: function(element) {
1667        element = $(element);
1668        if (element.getStyle('position') == 'relative') return element;
1669        element.style.position = 'relative';
1670        var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
1671        var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1672        element.style.top = top + 'px';
1673        element.style.left = left + 'px';
1674        element.style.height = element._originalHeight;
1675        element.style.width = element._originalWidth;
1676        return element;
1677    },
1678    cumulativeScrollOffset: function(element) {
1679        var valueT = 0,
1680            valueL = 0;
1681        do {
1682            valueT += element.scrollTop || 0;
1683            valueL += element.scrollLeft || 0;
1684            element = element.parentNode;
1685        } while (element);
1686        return Element._returnOffset(valueL, valueT);
1687    },
1688    getOffsetParent: function(element) {
1689        if (element.offsetParent) return $(element.offsetParent);
1690        if (element == document.body) return $(element);
1691        while ((element = element.parentNode) && element != document.body)
1692        if (Element.getStyle(element, 'position') != 'static') return $(element);
1693        return $(document.body);
1694    },
1695    viewportOffset: function(forElement) {
1696        var valueT = 0,
1697            valueL = 0;
1698        var element = forElement;
1699        do {
1700            valueT += element.offsetTop || 0;
1701            valueL += element.offsetLeft || 0;
1702            if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break;
1703        } while (element = element.offsetParent);
1704        element = forElement;
1705        do {
1706            if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
1707                valueT -= element.scrollTop || 0;
1708                valueL -= element.scrollLeft || 0;
1709            }
1710        } while (element = element.parentNode);
1711        return Element._returnOffset(valueL, valueT);
1712    },
1713    clonePosition: function(element, source) {
1714        var options = Object.extend({
1715            setLeft: true,
1716            setTop: true,
1717            setWidth: true,
1718            setHeight: true,
1719            offsetTop: 0,
1720            offsetLeft: 0
1721        }, arguments[2] || {});
1722        source = $(source);
1723        var p = source.viewportOffset();
1724        element = $(element);
1725        var delta = [0, 0];
1726        var parent = null;
1727        if (Element.getStyle(element, 'position') == 'absolute') {
1728            parent = element.getOffsetParent();
1729            delta = parent.viewportOffset();
1730        }
1731        if (parent == document.body) {
1732            delta[0] -= document.body.offsetLeft;
1733            delta[1] -= document.body.offsetTop;
1734        }
1735        if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
1736        if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
1737        if (options.setWidth) element.style.width = source.offsetWidth + 'px';
1738        if (options.setHeight) element.style.height = source.offsetHeight + 'px';
1739        return element;
1740    }
1741};
1742Element.Methods.identify.counter = 1;
1743Object.extend(Element.Methods, {
1744    getElementsBySelector: Element.Methods.select,
1745    childElements: Element.Methods.immediateDescendants
1746});
1747Element._attributeTranslations = {
1748    write: {
1749        names: {
1750            className: 'class',
1751            htmlFor: 'for'
1752        },
1753        values: {}
1754    }
1755};
1756if (Prototype.Browser.Opera) {
1757    Element.Methods.getStyle = Element.Methods.getStyle.wrap(function(proceed, element, style) {
1758        switch (style) {
1759        case 'left':
1760        case 'top':
1761        case 'right':
1762        case 'bottom':
1763            if (proceed(element, 'position') === 'static') return null;
1764        case 'height':
1765        case 'width':
1766            if (!Element.visible(element)) return null;
1767            var dim = parseInt(proceed(element, style), 10);
1768            if (dim !== element['offset' + style.capitalize()]) return dim + 'px';
1769            var properties;
1770            if (style === 'height') {
1771                properties = ['border-top-width', 'padding-top', 'padding-bottom', 'border-bottom-width'];
1772            }
1773            else {
1774                properties = ['border-left-width', 'padding-left', 'padding-right', 'border-right-width'];
1775            }
1776            return properties.inject(dim, function(memo, property) {
1777                var val = proceed(element, property);
1778                return val === null ? memo : memo - parseInt(val, 10);
1779            }) + 'px';
1780        default:
1781            return proceed(element, style);
1782        }
1783    });
1784    Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(function(proceed, element, attribute) {
1785        if (attribute === 'title') return element.title;
1786        return proceed(element, attribute);
1787    });
1788}
1789else if (Prototype.Browser.IE) {
1790    Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(function(proceed, element) {
1791        element = $(element);
1792        try {
1793            element.offsetParent
1794        }
1795        catch (e) {
1796            return $(document.body)
1797        }
1798        var position = element.getStyle('position');
1799        if (position !== 'static') return proceed(element);
1800        element.setStyle({
1801            position: 'relative'
1802        });
1803        var value = proceed(element);
1804        element.setStyle({
1805            position: position
1806        });
1807        return value;
1808    });
1809    $w('positionedOffset viewportOffset').each(function(method) {
1810        Element.Methods[method] = Element.Methods[method].wrap(function(proceed, element) {
1811            element = $(element);
1812            try {
1813                element.offsetParent
1814            }
1815            catch (e) {
1816                return Element._returnOffset(0, 0)
1817            }
1818            var position = element.getStyle('position');
1819            if (position !== 'static') return proceed(element);
1820            var offsetParent = element.getOffsetParent();
1821            if (offsetParent && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({
1822                zoom: 1
1823            });
1824            element.setStyle({
1825                position: 'relative'
1826            });
1827            var value = proceed(element);
1828            element.setStyle({
1829                position: position
1830            });
1831            return value;
1832        });
1833    });
1834    Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(function(proceed, element) {
1835        try {
1836            element.offsetParent
1837        }
1838        catch (e) {
1839            return Element._returnOffset(0, 0)
1840        }
1841        return proceed(element);
1842    });
1843    Element.Methods.getStyle = function(element, style) {
1844        element = $(element);
1845        style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
1846        var value = element.style[style];
1847        if (!value && element.currentStyle) value = element.currentStyle[style];
1848        if (style == 'opacity') {
1849            if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100;
1850            return 1.0;
1851        }
1852        if (value == 'auto') {
1853            if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px';
1854            return null;
1855        }
1856        return value;
1857    };
1858    Element.Methods.setOpacity = function(element, value) {
1859        function stripAlpha(filter) {
1860            return filter.replace(/alpha\([^\)]*\)/gi, '');
1861        }
1862        element = $(element);
1863        var currentStyle = element.currentStyle;
1864        if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1;
1865        var filter = element.getStyle('filter'),
1866            style = element.style;
1867        if (value == 1 || value === '') {
1868            (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter');
1869            return element;
1870        } else if (value < 0.00001) value = 0;
1871        style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')';
1872        return element;
1873    };
1874    Element._attributeTranslations = {
1875        read: {
1876            names: {
1877                'class': 'className',
1878                'for': 'htmlFor'
1879            },
1880            values: {
1881                _getAttr: function(element, attribute) {
1882                    return element.getAttribute(attribute, 2);
1883                },
1884                _getAttrNode: function(element, attribute) {
1885                    var node = element.getAttributeNode(attribute);
1886                    return node ? node.value : "";
1887                },
1888                _getEv: function(element, attribute) {
1889                    attribute = element.getAttribute(attribute);
1890                    return attribute ? attribute.toString().slice(23, -2) : null;
1891                },
1892                _flag: function(element, attribute) {
1893                    return $(element).hasAttribute(attribute) ? attribute : null;
1894                },
1895                style: function(element) {
1896                    return element.style.cssText.toLowerCase();
1897                },
1898                title: function(element) {
1899                    return element.title;
1900                }
1901            }
1902        }
1903    };
1904    Element._attributeTranslations.write = {
1905        names: Object.extend({
1906            cellpadding: 'cellPadding',
1907            cellspacing: 'cellSpacing'
1908        }, Element._attributeTranslations.read.names),
1909        values: {
1910            checked: function(element, value) {
1911                element.checked = !! value;
1912            },
1913            style: function(element, value) {
1914                element.style.cssText = value ? value : '';
1915            }
1916        }
1917    };
1918    Element._attributeTranslations.has = {};
1919    $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
1920        Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
1921        Element._attributeTranslations.has[attr.toLowerCase()] = attr;
1922    });
1923    (function(v) {
1924        Object.extend(v, {
1925            href: v._getAttr,
1926            src: v._getAttr,
1927            type: v._getAttr,
1928            action: v._getAttrNode,
1929            disabled: v._flag,
1930            checked: v._flag,
1931            readonly: v._flag,
1932            multiple: v._flag,
1933            onload: v._getEv,
1934            onunload: v._getEv,
1935            onclick: v._getEv,
1936            ondblclick: v._getEv,
1937            onmousedown: v._getEv,
1938            onmouseup: v._getEv,
1939            onmouseover: v._getEv,
1940            onmousemove: v._getEv,
1941            onmouseout: v._getEv,
1942            onfocus: v._getEv,
1943            onblur: v._getEv,
1944            onkeypress: v._getEv,
1945            onkeydown: v._getEv,
1946            onkeyup: v._getEv,
1947            onsubmit: v._getEv,
1948            onreset: v._getEv,
1949            onselect: v._getEv,
1950            onchange: v._getEv
1951        });
1952    })(Element._attributeTranslations.read.values);
1953}
1954else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
1955    Element.Methods.setOpacity = function(element, value) {
1956        element = $(element);
1957        element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value;
1958        return element;
1959    };
1960}
1961else if (Prototype.Browser.WebKit) {
1962    Element.Methods.setOpacity = function(element, value) {
1963        element = $(element);
1964        element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value;
1965        if (value == 1) if (element.tagName.toUpperCase() == 'IMG' && element.width) {
1966            element.width++;
1967            element.width--;
1968        } else try {
1969            var n = document.createTextNode(' ');
1970            element.appendChild(n);
1971            element.removeChild(n);
1972        } catch (e) {}
1973        return element;
1974    };
1975    Element.Methods.cumulativeOffset = function(element) {
1976        var valueT = 0,
1977            valueL = 0;
1978        do {
1979            valueT += element.offsetTop || 0;
1980            valueL += element.offsetLeft || 0;
1981            if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break;
1982            element = element.offsetParent;
1983        } while (element);
1984        return Element._returnOffset(valueL, valueT);
1985    };
1986}
1987if (Prototype.Browser.IE || Prototype.Browser.Opera) {
1988    Element.Methods.update = function(element, content) {
1989        element = $(element);
1990        if (content && content.toElement) content = content.toElement();
1991        if (Object.isElement(content)) return element.update().insert(content);
1992        content = Object.toHTML(content);
1993        var tagName = element.tagName.toUpperCase();
1994        if (tagName in Element._insertionTranslations.tags) {
1995            $A(element.childNodes).each(function(node) {
1996                element.removeChild(node)
1997            });
1998            Element._getContentFromAnonymousElement(tagName, content.stripScripts()).each(function(node) {
1999                element.appendChild(node)
2000            });
2001        }
2002        else element.innerHTML = content.stripScripts();
2003        content.evalScripts.bind(content).defer();
2004        return element;
2005    };
2006}
2007if ('outerHTML' in document.createElement('div')) {
2008    Element.Methods.replace = function(element, content) {
2009        element = $(element);
2010        if (content && content.toElement) content = content.toElement();
2011        if (Object.isElement(content)) {
2012            element.parentNode.replaceChild(content, element);
2013            return element;
2014        }
2015        content = Object.toHTML(content);
2016        var parent = element.parentNode,
2017            tagName = parent.tagName.toUpperCase();
2018        if (Element._insertionTranslations.tags[tagName]) {
2019            var nextSibling = element.next();
2020            var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2021            parent.removeChild(element);
2022            if (nextSibling) fragments.each(function(node) {
2023                parent.insertBefore(node, nextSibling)
2024            });
2025            else fragments.each(function(node) {
2026                parent.appendChild(node)
2027            });
2028        }
2029        else element.outerHTML = content.stripScripts();
2030        content.evalScripts.bind(content).defer();
2031        return element;
2032    };
2033}
2034Element._returnOffset = function(l, t) {
2035    var result = [l, t];
2036    result.left = l;
2037    result.top = t;
2038    return result;
2039};
2040Element._getContentFromAnonymousElement = function(tagName, html) {
2041    var div = new Element('div'),
2042        t = Element._insertionTranslations.tags[tagName];
2043    if (t) {
2044        div.innerHTML = t[0] + html + t[1];
2045        t[2].times(function() {
2046            div = div.firstChild
2047        });
2048    } else div.innerHTML = html;
2049    return $A(div.childNodes);
2050};
2051Element._insertionTranslations = {
2052    before: function(element, node) {
2053        element.parentNode.insertBefore(node, element);
2054    },
2055    top: function(element, node) {
2056        element.insertBefore(node, element.firstChild);
2057    },
2058    bottom: function(element, node) {
2059        element.appendChild(node);
2060    },
2061    after: function(element, node) {
2062        element.parentNode.insertBefore(node, element.nextSibling);
2063    },
2064    tags: {
2065        TABLE: ['<table>', '</table>', 1],
2066        TBODY: ['<table><tbody>', '</tbody></table>', 2],
2067        TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2068        TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2069        SELECT: ['<select>', '</select>', 1]
2070    }
2071};
2072(function() {
2073    Object.extend(this.tags, {
2074        THEAD: this.tags.TBODY,
2075        TFOOT: this.tags.TBODY,
2076        TH: this.tags.TD
2077    });
2078}).call(Element._insertionTranslations);
2079Element.Methods.Simulated = {
2080    hasAttribute: function(element, attribute) {
2081        attribute = Element._attributeTranslations.has[attribute] || attribute;
2082        var node = $(element).getAttributeNode(attribute);
2083        return !!(node && node.specified);
2084    }
2085};
2086Element.Methods.ByTag = {};
2087Object.extend(Element, Element.Methods);
2088if (!Prototype.BrowserFeatures.ElementExtensions && document.createElement('div')['__proto__']) {
2089    window.HTMLElement = {};
2090    window.HTMLElement.prototype = document.createElement('div')['__proto__'];
2091    Prototype.BrowserFeatures.ElementExtensions = true;
2092}
2093Element.extend = (function() {
2094    if (Prototype.BrowserFeatures.SpecificElementExtensions) return Prototype.K;
2095    var Methods = {},
2096        ByTag = Element.Methods.ByTag;
2097    var extend = Object.extend(function(element) {
2098        if (!element || element._extendedByPrototype || element.nodeType != 1 || element == window) return element;
2099        var methods = Object.clone(Methods),
2100            tagName = element.tagName.toUpperCase(),
2101            property, value;
2102        if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2103        for (property in methods) {
2104            value = methods[property];
2105            if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize();
2106        }
2107        element._extendedByPrototype = Prototype.emptyFunction;
2108        return element;
2109    }, {
2110        refresh: function() {
2111            if (!Prototype.BrowserFeatures.ElementExtensions) {
2112                Object.extend(Methods, Element.Methods);
2113                Object.extend(Methods, Element.Methods.Simulated);
2114            }
2115        }
2116    });
2117    extend.refresh();
2118    return extend;
2119})();
2120Element.hasAttribute = function(element, attribute) {
2121    if (element.hasAttribute) return element.hasAttribute(attribute);
2122    return Element.Methods.Simulated.hasAttribute(element, attribute);
2123};
2124Element.addMethods = function(methods) {
2125    var F = Prototype.BrowserFeatures,
2126        T = Element.Methods.ByTag;
2127    if (!methods) {
2128        Object.extend(Form, Form.Methods);
2129        Object.extend(Form.Element, Form.Element.Methods);
2130        Object.extend(Element.Methods.ByTag, {
2131            "FORM": Object.clone(Form.Methods),
2132            "INPUT": Object.clone(Form.Element.Methods),
2133            "SELECT": Object.clone(Form.Element.Methods),
2134            "TEXTAREA": Object.clone(Form.Element.Methods)
2135        });
2136    }
2137    if (arguments.length == 2) {
2138        var tagName = methods;
2139        methods = arguments[1];
2140    }
2141    if (!tagName) Object.extend(Element.Methods, methods || {});
2142    else {
2143        if (Object.isArray(tagName)) tagName.each(extend);
2144        else extend(tagName);
2145    }
2146
2147    function extend(tagName) {
2148        tagName = tagName.toUpperCase();
2149        if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = {};
2150        Object.extend(Element.Methods.ByTag[tagName], methods);
2151    }
2152
2153    function copy(methods, destination, onlyIfAbsent) {
2154        onlyIfAbsent = onlyIfAbsent || false;
2155        for (var property in methods) {
2156            var value = methods[property];
2157            if (!Object.isFunction(value)) continue;
2158            if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize();
2159        }
2160    }
2161
2162    function findDOMClass(tagName) {
2163        var klass;
2164        var trans = {
2165            "OPTGROUP": "OptGroup",
2166            "TEXTAREA": "TextArea",
2167            "P": "Paragraph",
2168            "FIELDSET": "FieldSet",
2169            "UL": "UList",
2170            "OL": "OList",
2171            "DL": "DList",
2172            "DIR": "Directory",
2173            "H1": "Heading",
2174            "H2": "Heading",
2175            "H3": "Heading",
2176            "H4": "Heading",
2177            "H5": "Heading",
2178            "H6": "Heading",
2179            "Q": "Quote",
2180            "INS": "Mod",
2181            "DEL": "Mod",
2182            "A": "Anchor",
2183            "IMG": "Image",
2184            "CAPTION": "TableCaption",
2185            "COL": "TableCol",
2186            "COLGROUP": "TableCol",
2187            "THEAD": "TableSection",
2188            "TFOOT": "TableSection",
2189            "TBODY": "TableSection",
2190            "TR": "TableRow",
2191            "TH": "TableCell",
2192            "TD": "TableCell",
2193            "FRAMESET": "FrameSet",
2194            "IFRAME": "IFrame"
2195        };
2196        if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
2197        if (window[klass]) return window[klass];
2198        klass = 'HTML' + tagName + 'Element';
2199        if (window[klass]) return window[klass];
2200        klass = 'HTML' + tagName.capitalize() + 'Element';
2201        if (window[klass]) return window[klass];
2202        window[klass] = {};
2203        window[klass].prototype = document.createElement(tagName)['__proto__'];
2204        return window[klass];
2205    }
2206    if (F.ElementExtensions) {
2207        copy(Element.Methods, HTMLElement.prototype);
2208        copy(Element.Methods.Simulated, HTMLElement.prototype, true);
2209    }
2210    if (F.SpecificElementExtensions) {
2211        for (var tag in Element.Methods.ByTag) {
2212            var klass = findDOMClass(tag);
2213            if (Object.isUndefined(klass)) continue;
2214            copy(T[tag], klass.prototype);
2215        }
2216    }
2217    Object.extend(Element, Element.Methods);
2218    delete Element.ByTag;
2219    if (Element.extend.refresh) Element.extend.refresh();
2220    Element.cache = {};
2221};
2222document.viewport = {
2223    getDimensions: function() {
2224        var dimensions = {},
2225            B = Prototype.Browser;
2226        $w('width height').each(function(d) {
2227            var D = d.capitalize();
2228            if (B.WebKit && !document.evaluate) {
2229                dimensions[d] = self['inner' + D];
2230            } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
2231                dimensions[d] = document.body['client' + D]
2232            } else {
2233                dimensions[d] = document.documentElement['client' + D];
2234            }
2235        });
2236        return dimensions;
2237    },
2238    getWidth: function() {
2239        return this.getDimensions().width;
2240    },
2241    getHeight: function() {
2242        return this.getDimensions().height;
2243    },
2244    getScrollOffsets: function() {
2245        return Element._returnOffset(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
2246    }
2247};
2248var Selector = Class.create({
2249    initialize: function(expression) {
2250        this.expression = expression.strip();
2251        if (this.shouldUseSelectorsAPI()) {
2252            this.mode = 'selectorsAPI';
2253        } else if (this.shouldUseXPath()) {
2254            this.mode = 'xpath';
2255            this.compileXPathMatcher();
2256        } else {
2257            this.mode = "normal";
2258            this.compileMatcher();
2259        }
2260    },
2261    shouldUseXPath: function() {
2262        if (!Prototype.BrowserFeatures.XPath) return false;
2263        var e = this.expression;
2264        if (Prototype.Browser.WebKit && (e.include("-of-type") || e.include(":empty"))) return false;
2265        if ((/(\[[\w-]*?:|:checked)/).test(e)) return false;
2266        return true;
2267    },
2268    shouldUseSelectorsAPI: function() {
2269        if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
2270        if (!Selector._div) Selector._div = new Element('div');
2271        try {
2272            Selector._div.querySelector(this.expression);
2273        } catch (e) {
2274            return false;
2275        }
2276        return true;
2277    },
2278    compileMatcher: function() {
2279        var e = this.expression,
2280            ps = Selector.patterns,
2281            h = Selector.handlers,
2282            c = Selector.criteria,
2283            le, p, m;
2284        if (Selector._cache[e]) {
2285            this.matcher = Selector._cache[e];
2286            return;
2287        }
2288        this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"];
2289        while (e && le != e && (/\S/).test(e)) {
2290            le = e;
2291            for (var i in ps) {
2292                p = ps[i];
2293                if (m = e.match(p)) {
2294                    this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m));
2295                    e = e.replace(m[0], '');
2296                    break;
2297                }
2298            }
2299        }
2300        this.matcher.push("return h.unique(n);\n}");
2301        eval(this.matcher.join('\n'));
2302        Selector._cache[this.expression] = this.matcher;
2303    },
2304    compileXPathMatcher: function() {
2305        var e = this.expression,
2306            ps = Selector.patterns,
2307            x = Selector.xpath,
2308            le, m;
2309        if (Selector._cache[e]) {
2310            this.xpath = Selector._cache[e];
2311            return;
2312        }
2313        this.matcher = ['.//*'];
2314        while (e && le != e && (/\S/).test(e)) {
2315            le = e;
2316            for (var i in ps) {
2317                if (m = e.match(ps[i])) {
2318                    this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m));
2319                    e = e.replace(m[0], '');
2320                    break;
2321                }
2322            }
2323        }
2324        this.xpath = this.matcher.join('');
2325        Selector._cache[this.expression] = this.xpath;
2326    },
2327    findElements: function(root) {
2328        root = root || document;
2329        var e = this.expression,
2330            results;
2331        switch (this.mode) {
2332        case 'selectorsAPI':
2333            if (root !== document) {
2334                var oldId = root.id,
2335                    id = $(root).identify();
2336                e = "#" + id + " " + e;
2337            }
2338            results = $A(root.querySelectorAll(e)).map(Element.extend);
2339            root.id = oldId;
2340            return results;
2341        case 'xpath':
2342            return document._getElementsByXPath(this.xpath, root);
2343        default:
2344            return this.matcher(root);
2345        }
2346    },
2347    match: function(element) {
2348        this.tokens = [];
2349        var e = this.expression,
2350            ps = Selector.patterns,
2351            as = Selector.assertions;
2352        var le, p, m;
2353        while (e && le !== e && (/\S/).test(e)) {
2354            le = e;
2355            for (var i in ps) {
2356                p = ps[i];
2357                if (m = e.match(p)) {
2358                    if (as[i]) {
2359                        this.tokens.push([i, Object.clone(m)]);
2360                        e = e.replace(m[0], '');
2361                    } else {
2362                        return this.findElements(document).include(element);
2363                    }
2364                }
2365            }
2366        }
2367        var match = true,
2368            name, matches;
2369        for (var i = 0, token; token = this.tokens[i]; i++) {
2370            name = token[0], matches = token[1];
2371            if (!Selector.assertions[name](element, matches)) {
2372                match = false;
2373                break;
2374            }
2375        }
2376        return match;
2377    },
2378    toString: function() {
2379        return this.expression;
2380    },
2381    inspect: function() {
2382        return "#<Selector:" + this.expression.inspect() + ">";
2383    }
2384});
2385Object.extend(Selector, {
2386    _cache: {},
2387    xpath: {
2388        descendant: "//*",
2389        child: "/*",
2390        adjacent: "/following-sibling::*[1]",
2391        laterSibling: '/following-sibling::*',
2392        tagName: function(m) {
2393            if (m[1] == '*') return '';
2394            return "[local-name()='" + m[1].toLowerCase() + "' or local-name()='" + m[1].toUpperCase() + "']";
2395        },
2396        className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2397        id: "[@id='#{1}']",
2398        attrPresence: function(m) {
2399            m[1] = m[1].toLowerCase();
2400            return new Template("[@#{1}]").evaluate(m);
2401        },
2402        attr: function(m) {
2403            m[1] = m[1].toLowerCase();
2404            m[3] = m[5] || m[6];
2405            return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2406        },
2407        pseudo: function(m) {
2408            var h = Selector.xpath.pseudos[m[1]];
2409            if (!h) return '';
2410            if (Object.isFunction(h)) return h(m);
2411            return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
2412        },
2413        operators: {
2414            '=': "[@#{1}='#{3}']",
2415            '!=': "[@#{1}!='#{3}']",
2416            '^=': "[starts-with(@#{1}, '#{3}')]",
2417            '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
2418            '*=': "[contains(@#{1}, '#{3}')]",
2419            '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
2420            '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
2421        },
2422        pseudos: {
2423            'first-child': '[not(preceding-sibling::*)]',
2424            'last-child': '[not(following-sibling::*)]',
2425            'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
2426            'empty': "[count(*) = 0 and (count(text()) = 0)]",
2427            'checked': "[@checked]",
2428            'disabled': "[(@disabled) and (@type!='hidden')]",
2429            'enabled': "[not(@disabled) and (@type!='hidden')]",
2430            'not': function(m) {
2431                var e = m[6],
2432                    p = Selector.patterns,
2433                    x = Selector.xpath,
2434                    le, v;
2435                var exclusion = [];
2436                while (e && le != e && (/\S/).test(e)) {
2437                    le = e;
2438                    for (var i in p) {
2439                        if (m = e.match(p[i])) {
2440                            v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
2441                            exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2442                            e = e.replace(m[0], '');
2443                            break;
2444                        }
2445                    }
2446                }
2447                return "[not(" + exclusion.join(" and ") + ")]";
2448            },
2449            'nth-child': function(m) {
2450                return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
2451            },
2452            'nth-last-child': function(m) {
2453                return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
2454            },
2455            'nth-of-type': function(m) {
2456                return Selector.xpath.pseudos.nth("position() ", m);
2457            },
2458            'nth-last-of-type': function(m) {
2459                return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
2460            },
2461            'first-of-type': function(m) {
2462                m[6] = "1";
2463                return Selector.xpath.pseudos['nth-of-type'](m);
2464            },
2465            'last-of-type': function(m) {
2466                m[6] = "1";
2467                return Selector.xpath.pseudos['nth-last-of-type'](m);
2468            },
2469            'only-of-type': function(m) {
2470                var p = Selector.xpath.pseudos;
2471                return p['first-of-type'](m) + p['last-of-type'](m);
2472            },
2473            nth: function(fragment, m) {
2474                var mm, formula = m[6],
2475                    predicate;
2476                if (formula == 'even') formula = '2n+0';
2477                if (formula == 'odd') formula = '2n+1';
2478                if (mm = formula.match(/^(\d+)$/)) return '[' + fragment + "= " + mm[1] + ']';
2479                if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) {
2480                    if (mm[1] == "-") mm[1] = -1;
2481                    var a = mm[1] ? Number(mm[1]) : 1;
2482                    var b = mm[2] ? Number(mm[2]) : 0;
2483                    predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + "((#{fragment} - #{b}) div #{a} >= 0)]";
2484                    return new Template(predicate).evaluate({
2485                        fragment: fragment,
2486                        a: a,
2487                        b: b
2488                    });
2489                }
2490            }
2491        }
2492    },
2493    criteria: {
2494        tagName: 'n = h.tagName(n, r, "#{1}", c);      c = false;',
2495        className: 'n = h.className(n, r, "#{1}", c);    c = false;',
2496        id: 'n = h.id(n, r, "#{1}", c);           c = false;',
2497        attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
2498        attr: function(m) {
2499            m[3] = (m[5] || m[6]);
2500            return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
2501        },
2502        pseudo: function(m) {
2503            if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
2504            return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
2505        },
2506        descendant: 'c = "descendant";',
2507        child: 'c = "child";',
2508        adjacent: 'c = "adjacent";',
2509        laterSibling: 'c = "laterSibling";'
2510    },
2511    patterns: {
2512        laterSibling: /^\s*~\s*/,
2513        child: /^\s*>\s*/,
2514        adjacent: /^\s*\+\s*/,
2515        descendant: /^\s/,
2516        tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
2517        id: /^#([\w\-\*]+)(\b|$)/,
2518        className: /^\.([\w\-\*]+)(\b|$)/,
2519        pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
2520        attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
2521        attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
2522    },
2523    assertions: {
2524        tagName: function(element, matches) {
2525            return matches[1].toUpperCase() == element.tagName.toUpperCase();
2526        },
2527        className: function(element, matches) {
2528            return Element.hasClassName(element, matches[1]);
2529        },
2530        id: function(element, matches) {
2531            return element.id === matches[1];
2532        },
2533        attrPresence: function(element, matches) {
2534            return Element.hasAttribute(element, matches[1]);
2535        },
2536        attr: function(element, matches) {
2537            var nodeValue = Element.readAttribute(element, matches[1]);
2538            return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
2539        }
2540    },
2541    handlers: {
2542        concat: function(a, b) {
2543            for (var i = 0, node; node = b[i]; i++)
2544            a.push(node);
2545            return a;
2546        },
2547        mark: function(nodes) {
2548            var _true = Prototype.emptyFunction;
2549            for (var i = 0, node; node = nodes[i]; i++)
2550            node._countedByPrototype = _true;
2551            return nodes;
2552        },
2553        unmark: function(nodes) {
2554            for (var i = 0, node; node = nodes[i]; i++)
2555            node._countedByPrototype = undefined;
2556            return nodes;
2557        },
2558        index: function(parentNode, reverse, ofType) {
2559            parentNode._countedByPrototype = Prototype.emptyFunction;
2560            if (reverse) {
2561                for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
2562                    var node = nodes[i];
2563                    if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
2564                }
2565            } else {
2566                for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
2567                if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
2568            }
2569        },
2570        unique: function(nodes) {
2571            if (nodes.length == 0) return nodes;
2572            var results = [],
2573                n;
2574            for (var i = 0, l = nodes.length; i < l; i++)
2575            if (!(n = nodes[i])._countedByPrototype) {
2576                n._countedByPrototype = Prototype.emptyFunction;
2577                results.push(Element.extend(n));
2578            }
2579            return Selector.handlers.unmark(results);
2580        },
2581        descendant: function(nodes) {
2582            var h = Selector.handlers;
2583            for (var i = 0, results = [], node; node = nodes[i]; i++)
2584            h.concat(results, node.getElementsByTagName('*'));
2585            return results;
2586        },
2587        child: function(nodes) {
2588            var h = Selector.handlers;
2589            for (var i = 0, results = [], node; node = nodes[i]; i++) {
2590                for (var j = 0, child; child = node.childNodes[j]; j++)
2591                if (child.nodeType == 1 && child.tagName != '!') results.push(child);
2592            }
2593            return results;
2594        },
2595        adjacent: function(nodes) {
2596            for (var i = 0, results = [], node; node = nodes[i]; i++) {
2597                var next = this.nextElementSibling(node);
2598                if (next) results.push(next);
2599            }
2600            return results;
2601        },
2602        laterSibling: function(nodes) {
2603            var h = Selector.handlers;
2604            for (var i = 0, results = [], node; node = nodes[i]; i++)
2605            h.concat(results, Element.nextSiblings(node));
2606            return results;
2607        },
2608        nextElementSibling: function(node) {
2609            while (node = node.nextSibling)
2610            if (node.nodeType == 1) return node;
2611            return null;
2612        },
2613        previousElementSibling: function(node) {
2614            while (node = node.previousSibling)
2615            if (node.nodeType == 1) return node;
2616            return null;
2617        },
2618        tagName: function(nodes, root, tagName, combinator) {
2619            var uTagName = tagName.toUpperCase();
2620            var results = [],
2621                h = Selector.handlers;
2622            if (nodes) {
2623                if (combinator) {
2624                    if (combinator == "descendant") {
2625                        for (var i = 0, node; node = nodes[i]; i++)
2626                        h.concat(results, node.getElementsByTagName(tagName));
2627                        return results;
2628                    } else nodes = this[combinator](nodes);
2629                    if (tagName == "*") return nodes;
2630                }
2631                for (var i = 0, node; node = nodes[i]; i++)
2632                if (node.tagName.toUpperCase() === uTagName) results.push(node);
2633                return results;
2634            } else return root.getElementsByTagName(tagName);
2635        },
2636        id: function(nodes, root, id, combinator) {
2637            var targetNode = $(id),
2638                h = Selector.handlers;
2639            if (!targetNode) return [];
2640            if (!nodes && root == document) return [targetNode];
2641            if (nodes) {
2642                if (combinator) {
2643                    if (combinator == 'child') {
2644                        for (var i = 0, node; node = nodes[i]; i++)
2645                        if (targetNode.parentNode == node) return [targetNode];
2646                    } else if (combinator == 'descendant') {
2647                        for (var i = 0, node; node = nodes[i]; i++)
2648                        if (Element.descendantOf(targetNode, node)) return [targetNode];
2649                    } else if (combinator == 'adjacent') {
2650                        for (var i = 0, node; node = nodes[i]; i++)
2651                        if (Selector.handlers.previousElementSibling(targetNode) == node) return [targetNode];
2652                    } else nodes = h[combinator](nodes);
2653                }
2654                for (var i = 0, node; node = nodes[i]; i++)
2655                if (node == targetNode) return [targetNode];
2656                return [];
2657            }
2658            return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
2659        },
2660        className: function(nodes, root, className, combinator) {
2661            if (nodes && combinator) nodes = this[combinator](nodes);
2662            return Selector.handlers.byClassName(nodes, root, className);
2663        },
2664        byClassName: function(nodes, root, className) {
2665            if (!nodes) nodes = Selector.handlers.descendant([root]);
2666            var needle = ' ' + className + ' ';
2667            for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
2668                nodeClassName = node.className;
2669                if (nodeClassName.length == 0) continue;
2670                if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) results.push(node);
2671            }
2672            return results;
2673        },
2674        attrPresence: function(nodes, root, attr, combinator) {
2675            if (!nodes) nodes = root.getElementsByTagName("*");
2676            if (nodes && combinator) nodes = this[combinator](nodes);
2677            var results = [];
2678            for (var i = 0, node; node = nodes[i]; i++)
2679            if (Element.hasAttribute(node, attr)) results.push(node);
2680            return results;
2681        },
2682        attr: function(nodes, root, attr, value, operator, combinator) {
2683            if (!nodes) nodes = root.getElementsByTagName("*");
2684            if (nodes && combinator) nodes = this[combinator](nodes);
2685            var handler = Selector.operators[operator],
2686                results = [];
2687            for (var i = 0, node; node = nodes[i]; i++) {
2688                var nodeValue = Element.readAttribute(node, attr);
2689                if (nodeValue === null) continue;
2690                if (handler(nodeValue, value)) results.push(node);
2691            }
2692            return results;
2693        },
2694        pseudo: function(nodes, name, value, root, combinator) {
2695            if (nodes && combinator) nodes = this[combinator](nodes);
2696            if (!nodes) nodes = root.getElementsByTagName("*");
2697            return Selector.pseudos[name](nodes, value, root);
2698        }
2699    },
2700    pseudos: {
2701        'first-child': function(nodes, value, root) {
2702            for (var i = 0, results = [], node; node = nodes[i]; i++) {
2703                if (Selector.handlers.previousElementSibling(node)) continue;
2704                results.push(node);
2705            }
2706            return results;
2707        },
2708        'last-child': function(nodes, value, root) {
2709            for (var i = 0, results = [], node; node = nodes[i]; i++) {
2710                if (Selector.handlers.nextElementSibling(node)) continue;
2711                results.push(node);
2712            }
2713            return results;
2714        },
2715        'only-child': function(nodes, value, root) {
2716            var h = Selector.handlers;
2717            for (var i = 0, results = [], node; node = nodes[i]; i++)
2718            if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) results.push(node);
2719            return results;
2720        },
2721        'nth-child': function(nodes, formula, root) {
2722            return Selector.pseudos.nth(nodes, formula, root);
2723        },
2724        'nth-last-child': function(nodes, formula, root) {
2725            return Selector.pseudos.nth(nodes, formula, root, true);
2726        },
2727        'nth-of-type': function(nodes, formula, root) {
2728            return Selector.pseudos.nth(nodes, formula, root, false, true);
2729        },
2730        'nth-last-of-type': function(nodes, formula, root) {
2731            return Selector.pseudos.nth(nodes, formula, root, true, true);
2732        },
2733        'first-of-type': function(nodes, formula, root) {
2734            return Selector.pseudos.nth(nodes, "1", root, false, true);
2735        },
2736        'last-of-type': function(nodes, formula, root) {
2737            return Selector.pseudos.nth(nodes, "1", root, true, true);
2738        },
2739        'only-of-type': function(nodes, formula, root) {
2740            var p = Selector.pseudos;
2741            return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
2742        },
2743        getIndices: function(a, b, total) {
2744            if (a == 0) return b > 0 ? [b] : [];
2745            return $R(1, total).inject([], function(memo, i) {
2746                if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
2747                return memo;
2748            });
2749        },
2750        nth: function(nodes, formula, root, reverse, ofType) {
2751            if (nodes.length == 0) return [];
2752            if (formula == 'even') formula = '2n+0';
2753            if (formula == 'odd') formula = '2n+1';
2754            var h = Selector.handlers,
2755                results = [],
2756                indexed = [],
2757                m;
2758            h.mark(nodes);
2759            for (var i = 0, node; node = nodes[i]; i++) {
2760                if (!node.parentNode._countedByPrototype) {
2761                    h.index(node.parentNode, reverse, ofType);
2762                    indexed.push(node.parentNode);
2763                }
2764            }
2765            if (formula.match(/^\d+$/)) {
2766                formula = Number(formula);
2767                for (var i = 0, node; node = nodes[i]; i++)
2768                if (node.nodeIndex == formula) results.push(node);
2769            } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) {
2770                if (m[1] == "-") m[1] = -1;
2771                var a = m[1] ? Number(m[1]) : 1;
2772                var b = m[2] ? Number(m[2]) : 0;
2773                var indices = Selector.pseudos.getIndices(a, b, nodes.length);
2774                for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
2775                    for (var j = 0; j < l; j++)
2776                    if (node.nodeIndex == indices[j]) results.push(node);
2777                }
2778            }
2779            h.unmark(nodes);
2780            h.unmark(indexed);
2781            return results;
2782        },
2783        'empty': function(nodes, value, root) {
2784            for (var i = 0, results = [], node; node = nodes[i]; i++) {
2785                if (node.tagName == '!' || node.firstChild) continue;
2786                results.push(node);
2787            }
2788            return results;
2789        },
2790        'not': function(nodes, selector, root) {
2791            var h = Selector.handlers,
2792                selectorType, m;
2793            var exclusions = new Selector(selector).findElements(root);
2794            h.mark(exclusions);
2795            for (var i = 0, results = [], node; node = nodes[i]; i++)
2796            if (!node._countedByPrototype) results.push(node);
2797            h.unmark(exclusions);
2798            return results;
2799        },
2800        'enabled': function(nodes, value, root) {
2801            for (var i = 0, results = [], node; node = nodes[i]; i++)
2802            if (!node.disabled && (!node.type || node.type !== 'hidden')) results.push(node);
2803            return results;
2804        },
2805        'disabled': function(nodes, value, root) {
2806            for (var i = 0, results = [], node; node = nodes[i]; i++)
2807            if (node.disabled) results.push(node);
2808            return results;
2809        },
2810        'checked': function(nodes, value, root) {
2811            for (var i = 0, results = [], node; node = nodes[i]; i++)
2812            if (node.checked) results.push(node);
2813            return results;
2814        }
2815    },
2816    operators: {
2817        '=': function(nv, v) {
2818            return nv == v;
2819        },
2820        '!=': function(nv, v) {
2821            return nv != v;
2822        },
2823        '^=': function(nv, v) {
2824            return nv == v || nv && nv.startsWith(v);
2825        },
2826        '$=': function(nv, v) {
2827            return nv == v || nv && nv.endsWith(v);
2828        },
2829        '*=': function(nv, v) {
2830            return nv == v || nv && nv.include(v);
2831        },
2832        '$=': function(nv, v) {
2833            return nv.endsWith(v);
2834        },
2835        '*=': function(nv, v) {
2836            return nv.include(v);
2837        },
2838        '~=': function(nv, v) {
2839            return (' ' + nv + ' ').include(' ' + v + ' ');
2840        },
2841        '|=': function(nv, v) {
2842            return ('-' + (nv || "").toUpperCase() + '-').include('-' + (v || "").toUpperCase() + '-');
2843        }
2844    },
2845    split: function(expression) {
2846        var expressions = [];
2847        expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
2848            expressions.push(m[1].strip());
2849        });
2850        return expressions;
2851    },
2852    matchElements: function(elements, expression) {
2853        var matches = $$(expression),
2854            h = Selector.handlers;
2855        h.mark(matches);
2856        for (var i = 0, results = [], element; element = elements[i]; i++)
2857        if (element._countedByPrototype) results.push(element);
2858        h.unmark(matches);
2859        return results;
2860    },
2861    findElement: function(elements, expression, index) {
2862        if (Object.isNumber(expression)) {
2863            index = expression;
2864            expression = false;
2865        }
2866        return Selector.matchElements(elements, expression || '*')[index || 0];
2867    },
2868    findChildElements: function(element, expressions) {
2869        expressions = Selector.split(expressions.join(','));
2870        var results = [],
2871            h = Selector.handlers;
2872        for (var i = 0, l = expressions.length, selector; i < l; i++) {
2873            selector = new Selector(expressions[i].strip());
2874            h.concat(results, selector.findElements(element));
2875        }
2876        return (l > 1) ? h.unique(results) : results;
2877    }
2878});
2879if (Prototype.Browser.IE) {
2880    Object.extend(Selector.handlers, {
2881        concat: function(a, b) {
2882            for (var i = 0, node; node = b[i]; i++)
2883            if (node.tagName !== "!") a.push(node);
2884            return a;
2885        },
2886        unmark: function(nodes) {
2887            for (var i = 0, node; node = nodes[i]; i++)
2888            node.removeAttribute('_countedByPrototype');
2889            return nodes;
2890        }
2891    });
2892}
2893
2894function $$() {
2895    return Selector.findChildElements(document, $A(arguments));
2896}
2897var Form = {
2898    reset: function(form) {
2899        $(form).reset();
2900        return form;
2901    },
2902    serializeElements: function(elements, options) {
2903        if (typeof options != 'object') options = {
2904            hash: !! options
2905        };
2906        else if (Object.isUndefined(options.hash)) options.hash = true;
2907        var key, value, submitted = false,
2908            submit = options.submit;
2909        var data = elements.inject({}, function(result, element) {
2910            if (!element.disabled && element.name) {
2911                key = element.name;
2912                value = $(element).getValue();
2913                if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) {
2914                    if (key in result) {
2915                        if (!Object.isArray(result[key])) result[key] = [result[key]];
2916                        result[key].push(value);
2917                    }
2918                    else result[key] = value;
2919                }
2920            }
2921            return result;
2922        });
2923        return options.hash ? data : Object.toQueryString(data);
2924    }
2925};
2926Form.Methods = {
2927    serialize: function(form, options) {
2928        return Form.serializeElements(Form.getElements(form), options);
2929    },
2930    getElements: function(form) {
2931        return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) {
2932            if (Form.Element.Serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child));
2933            return elements;
2934        });
2935    },
2936    getInputs: function(form, typeName, name) {
2937        form = $(form);
2938        var inputs = form.getElementsByTagName('input');
2939        if (!typeName && !name) return $A(inputs).map(Element.extend);
2940        for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
2941            var input = inputs[i];
2942            if ((typeName && input.type != typeName) || (name && input.name != name)) continue;
2943            matchingInputs.push(Element.extend(input));
2944        }
2945        return matchingInputs;
2946    },
2947    disable: function(form) {
2948        form = $(form);
2949        Form.getElements(form).invoke('disable');
2950        return form;
2951    },
2952    enable: function(form) {
2953        form = $(form);
2954        Form.getElements(form).invoke('enable');
2955        return form;
2956    },
2957    findFirstElement: function(form) {
2958        var elements = $(form).getElements().findAll(function(element) {
2959            return 'hidden' != element.type && !element.disabled;
2960        });
2961        var firstByIndex = elements.findAll(function(element) {
2962            return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
2963        }).sortBy(function(element) {
2964            return element.tabIndex
2965        }).first();
2966        return firstByIndex ? firstByIndex : elements.find(function(element) {
2967            return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
2968        });
2969    },
2970    focusFirstElement: function(form) {
2971        form = $(form);
2972        form.findFirstElement().activate();
2973        return form;
2974    },
2975    request: function(form, options) {
2976        form = $(form), options = Object.clone(options || {});
2977        var params = options.parameters,
2978            action = form.readAttribute('action') || '';
2979        if (action.blank()) action = window.location.href;
2980        options.parameters = form.serialize(true);
2981        if (params) {
2982            if (Object.isString(params)) params = params.toQueryParams();
2983            Object.extend(options.parameters, params);
2984        }
2985        if (form.hasAttribute('method') && !options.method) options.method = form.method;
2986        return new Ajax.Request(action, options);
2987    }
2988};
2989Form.Element = {
2990    focus: function(element) {
2991        $(element).focus();
2992        return element;
2993    },
2994    select: function(element) {
2995        $(element).select();
2996        return element;
2997    }
2998};
2999Form.Element.Methods = {
3000    serialize: function(element) {
3001        element = $(element);
3002        if (!element.disabled && element.name) {
3003            var value = element.getValue();
3004            if (value != undefined) {
3005                var pair = {};
3006                pair[element.name] = value;
3007                return Object.toQueryString(pair);
3008            }
3009        }
3010        return '';
3011    },
3012    getValue: function(element) {
3013        element = $(element);
3014        var method = element.tagName.toLowerCase();
3015        return Form.Element.Serializers[method](element);
3016    },
3017    setValue: function(element, value) {
3018        element = $(element);
3019        var method = element.tagName.toLowerCase();
3020        Form.Element.Serializers[method](element, value);
3021        return element;
3022    },
3023    clear: function(element) {
3024        $(element).value = '';
3025        return element;
3026    },
3027    present: function(element) {
3028        return $(element).value != '';
3029    },
3030    activate: function(element) {
3031        element = $(element);
3032        try {
3033            element.focus();
3034            if (element.select && (element.tagName.toLowerCase() != 'input' || !['button', 'reset', 'submit'].include(element.type))) element.select();
3035        } catch (e) {}
3036        return element;
3037    },
3038    disable: function(element) {
3039        element = $(element);
3040        element.disabled = true;
3041        return element;
3042    },
3043    enable: function(element) {
3044        element = $(element);
3045        element.disabled = false;
3046        return element;
3047    }
3048};
3049var Field = Form.Element;
3050var $F = Form.Element.Methods.getValue;
3051Form.Element.Serializers = {
3052    input: function(element, value) {
3053        switch (element.type.toLowerCase()) {
3054        case 'checkbox':
3055        case 'radio':
3056            return Form.Element.Serializers.inputSelector(element, value);
3057        default:
3058            return Form.Element.Serializers.textarea(element, value);
3059        }
3060    },
3061    inputSelector: function(element, value) {
3062        if (Object.isUndefined(value)) return element.checked ? element.value : null;
3063        else element.checked = !! value;
3064    },
3065    textarea: function(element, value) {
3066        if (Object.isUndefined(value)) return element.value;
3067        else element.value = value;
3068    },
3069    select: function(element, value) {
3070        if (Object.isUndefined(value)) return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element);
3071        else {
3072            var opt, currentValue, single = !Object.isArray(value);
3073            for (var i = 0, length = element.length; i < length; i++) {
3074                opt = element.options[i];
3075                currentValue = this.optionValue(opt);
3076                if (single) {
3077                    if (currentValue == value) {
3078                        opt.selected = true;
3079                        return;
3080                    }
3081                }
3082                else opt.selected = value.include(currentValue);
3083            }
3084        }
3085    },
3086    selectOne: function(element) {
3087        var index = element.selectedIndex;
3088        return index >= 0 ? this.optionValue(element.options[index]) : null;
3089    },
3090    selectMany: function(element) {
3091        var values, length = element.length;
3092        if (!length) return null;
3093        for (var i = 0, values = []; i < length; i++) {
3094            var opt = element.options[i];
3095            if (opt.selected) values.push(this.optionValue(opt));
3096        }
3097        return values;
3098    },
3099    optionValue: function(opt) {
3100        return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
3101    }
3102};
3103Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
3104    initialize: function($super, element, frequency, callback) {
3105        $super(callback, frequency);
3106        this.element = $(element);
3107        this.lastValue = this.getValue();
3108    },
3109    execute: function() {
3110        var value = this.getValue();
3111        if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) {
3112            this.callback(this.element, value);
3113            this.lastValue = value;
3114        }
3115    }
3116});
3117Form.Element.Observer = Class.create(Abstract.TimedObserver, {
3118    getValue: function() {
3119        return Form.Element.getValue(this.element);
3120    }
3121});
3122Form.Observer = Class.create(Abstract.TimedObserver, {
3123    getValue: function() {
3124        return Form.serialize(this.element);
3125    }
3126});
3127Abstract.EventObserver = Class.create({
3128    initialize: function(element, callback) {
3129        this.element = $(element);
3130        this.callback = callback;
3131        this.lastValue = this.getValue();
3132        if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks();
3133        else this.registerCallback(this.element);
3134    },
3135    onElementEvent: function() {
3136        var value = this.getValue();
3137        if (this.lastValue != value) {
3138            this.callback(this.element, value);
3139            this.lastValue = value;
3140        }
3141    },
3142    registerFormCallbacks: function() {
3143        Form.getElements(this.element).each(this.registerCallback, this);
3144    },
3145    registerCallback: function(element) {
3146        if (element.type) {
3147            switch (element.type.toLowerCase()) {
3148            case 'checkbox':
3149            case 'radio':
3150                Event.observe(element, 'click', this.onElementEvent.bind(this));
3151                break;
3152            default:
3153                Event.observe(element, 'change', this.onElementEvent.bind(this));
3154                break;
3155            }
3156        }
3157    }
3158});
3159Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
3160    getValue: function() {
3161        return Form.Element.getValue(this.element);
3162    }
3163});
3164Form.EventObserver = Class.create(Abstract.EventObserver, {
3165    getValue: function() {
3166        return Form.serialize(this.element);
3167    }
3168});
3169if (!window.Event) var Event = {};
3170Object.extend(Event, {
3171    KEY_BACKSPACE: 8,
3172    KEY_TAB: 9,
3173    KEY_RETURN: 13,
3174    KEY_ESC: 27,
3175    KEY_LEFT: 37,
3176    KEY_UP: 38,
3177    KEY_RIGHT: 39,
3178    KEY_DOWN: 40,
3179    KEY_DELETE: 46,
3180    KEY_HOME: 36,
3181    KEY_END: 35,
3182    KEY_PAGEUP: 33,
3183    KEY_PAGEDOWN: 34,
3184    KEY_INSERT: 45,
3185    cache: {},
3186    relatedTarget: function(event) {
3187        var element;
3188        switch (event.type) {
3189        case 'mouseover':
3190            element = event.fromElement;
3191            break;
3192        case 'mouseout':
3193            element = event.toElement;
3194            break;
3195        default:
3196            return null;
3197        }
3198        return Element.extend(element);
3199    }
3200});
3201Event.Methods = (function() {
3202    var isButton;
3203    if (Prototype.Browser.IE) {
3204        var buttonMap = {
3205            0: 1,
3206            1: 4,
3207            2: 2
3208        };
3209        isButton = function(event, code) {
3210            return event.button == buttonMap[code];
3211        };
3212    } else if (Prototype.Browser.WebKit) {
3213        isButton = function(event, code) {
3214            switch (code) {
3215            case 0:
3216                return event.which == 1 && !event.metaKey;
3217            case 1:
3218                return event.which == 1 && event.metaKey;
3219            default:
3220                return false;
3221            }
3222        };
3223    } else {
3224        isButton = function(event, code) {
3225            return event.which ? (event.which === code + 1) : (event.button === code);
3226        };
3227    }
3228    return {
3229        isLeftClick: function(event) {
3230            return isButton(event, 0)
3231        },
3232        isMiddleClick: function(event) {
3233            return isButton(event, 1)
3234        },
3235        isRightClick: function(event) {
3236            return isButton(event, 2)
3237        },
3238        element: function(event) {
3239            event = Event.extend(event);
3240            var node = event.target,
3241                type = event.type,
3242                currentTarget = event.currentTarget;
3243            if (currentTarget && currentTarget.tagName) {
3244                if (type === 'load' || type === 'error' || (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' && currentTarget.type === 'radio')) node = currentTarget;
3245            }
3246            if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
3247            return Element.extend(node);
3248        },
3249        findElement: function(event, expression) {
3250            var element = Event.element(event);
3251            if (!expression) return element;
3252            var elements = [element].concat(element.ancestors());
3253            return Selector.findElement(elements, expression, 0);
3254        },
3255        pointer: function(event) {
3256            var docElement = document.documentElement,
3257                body = document.body || {
3258                    scrollLeft: 0,
3259                    scrollTop: 0
3260                };
3261            return {
3262                x: event.pageX || (event.clientX + (docElement.scrollLeft || body.scrollLeft) - (docElement.clientLeft || 0)),
3263                y: event.pageY || (event.clientY + (docElement.scrollTop || body.scrollTop) - (docElement.clientTop || 0))
3264            };
3265        },
3266        pointerX: function(event) {
3267            return Event.pointer(event).x
3268        },
3269        pointerY: function(event) {
3270            return Event.pointer(event).y
3271        },
3272        stop: function(event) {
3273            Event.extend(event);
3274            event.preventDefault();
3275            event.stopPropagation();
3276            event.stopped = true;
3277        }
3278    };
3279})();
3280Event.extend = (function() {
3281    var methods = Object.keys(Event.Methods).inject({}, function(m, name) {
3282        m[name] = Event.Methods[name].methodize();
3283        return m;
3284    });
3285    if (Prototype.Browser.IE) {
3286        Object.extend(methods, {
3287            stopPropagation: function() {
3288                this.cancelBubble = true
3289            },
3290            preventDefault: function() {
3291                this.returnValue = false
3292            },
3293            inspect: function() {
3294                return "[object Event]"
3295            }
3296        });
3297        return function(event) {
3298            if (!event) return false;
3299            if (event._extendedByPrototype) return event;
3300            event._extendedByPrototype = Prototype.emptyFunction;
3301            var pointer = Event.pointer(event);
3302            Object.extend(event, {
3303                target: event.srcElement,
3304                relatedTarget: Event.relatedTarget(event),
3305                pageX: pointer.x,
3306                pageY: pointer.y
3307            });
3308            return Object.extend(event, methods);
3309        };
3310    } else {
3311        Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
3312        Object.extend(Event.prototype, methods);
3313        return Prototype.K;
3314    }
3315})();
3316Object.extend(Event, (function() {
3317    var cache = Event.cache;
3318
3319    function getEventID(element) {
3320        if (element._prototypeEventID) return element._prototypeEventID[0];
3321        arguments.callee.id = arguments.callee.id || 1;
3322        return element._prototypeEventID = [++arguments.callee.id];
3323    }
3324
3325    function getDOMEventName(eventName) {
3326        if (eventName && eventName.include(':')) return "dataavailable";
3327        return eventName;
3328    }
3329
3330    function getCacheForID(id) {
3331        return cache[id] = cache[id] || {};
3332    }
3333
3334    function getWrappersForEventName(id, eventName) {
3335        var c = getCacheForID(id);
3336        return c[eventName] = c[eventName] || [];
3337    }
3338
3339    function createWrapper(element, eventName, handler) {
3340        var id = getEventID(element);
3341        var c = getWrappersForEventName(id, eventName);
3342        if (c.pluck("handler").include(handler)) return false;
3343        var wrapper = function(event) {
3344            if (!Event || !Event.extend || (event.eventName && event.eventName != eventName)) return false;
3345            Event.extend(event);
3346            handler.call(element, event);
3347        };
3348        wrapper.handler = handler;
3349        c.push(wrapper);
3350        return wrapper;
3351    }
3352
3353    function findWrapper(id, eventName, handler) {
3354        var c = getWrappersForEventName(id, eventName);
3355        return c.find(function(wrapper) {
3356            return wrapper.handler == handler
3357        });
3358    }
3359
3360    function destroyWrapper(id, eventName, handler) {
3361        var c = getCacheForID(id);
3362        if (!c[eventName]) return false;
3363        c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
3364    }
3365
3366    function destroyCache() {
3367        for (var id in cache)
3368        for (var eventName in cache[id])
3369        cache[id][eventName] = null;
3370    }
3371    if (window.attachEvent) {
3372        window.attachEvent("onunload", destroyCache);
3373    }
3374    if (Prototype.Browser.WebKit) {
3375        window.addEventListener('unload', Prototype.emptyFunction, false);
3376    }
3377    return {
3378        observe: function(element, eventName, handler) {
3379            element = $(element);
3380            var name = getDOMEventName(eventName);
3381            var wrapper = createWrapper(element, eventName, handler);
3382            if (!wrapper) return element;
3383            if (element.addEventListener) {
3384                element.addEventListener(name, wrapper, false);
3385            } else {
3386                element.attachEvent("on" + name, wrapper);
3387            }
3388            return element;
3389        },
3390        stopObserving: function(element, eventName, handler) {
3391            element = $(element);
3392            var id = getEventID(element),
3393                name = getDOMEventName(eventName);
3394            if (!handler && eventName) {
3395                getWrappersForEventName(id, eventName).each(function(wrapper) {
3396                    element.stopObserving(eventName, wrapper.handler);
3397                });
3398                return element;
3399            } else if (!eventName) {
3400                Object.keys(getCacheForID(id)).each(function(eventName) {
3401                    element.stopObserving(eventName);
3402                });
3403                return element;
3404            }
3405            var wrapper = findWrapper(id, eventName, handler);
3406            if (!wrapper) return element;
3407            if (element.removeEventListener) {
3408                element.removeEventListener(name, wrapper, false);
3409            } else {
3410                element.detachEvent("on" + name, wrapper);
3411            }
3412            destroyWrapper(id, eventName, handler);
3413            return element;
3414        },
3415        fire: function(element, eventName, memo) {
3416            element = $(element);
3417            if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement;
3418            var event;
3419            if (document.createEvent) {
3420                event = document.createEvent("HTMLEvents");
3421                event.initEvent("dataavailable", true, true);
3422            } else {
3423                event = document.createEventObject();
3424                event.eventType = "ondataavailable";
3425            }
3426            event.eventName = eventName;
3427            event.memo = memo || {};
3428            if (document.createEvent) {
3429                element.dispatchEvent(event);
3430            } else {
3431                element.fireEvent(event.eventType, event);
3432            }
3433            return Event.extend(event);
3434        }
3435    };
3436})());
3437Object.extend(Event, Event.Methods);
3438Element.addMethods({
3439    fire: Event.fire,
3440    observe: Event.observe,
3441    stopObserving: Event.stopObserving
3442});
3443Object.extend(document, {
3444    fire: Element.Methods.fire.methodize(),
3445    observe: Element.Methods.observe.methodize(),
3446    stopObserving: Element.Methods.stopObserving.methodize(),
3447    loaded: false
3448});
3449(function() {
3450    var timer;
3451
3452    function fireContentLoadedEvent() {
3453        if (document.loaded) return;
3454        if (timer) window.clearInterval(timer);
3455        document.fire("dom:loaded");
3456        document.loaded = true;
3457    }
3458    if (document.addEventListener) {
3459        if (Prototype.Browser.WebKit) {
3460            timer = window.setInterval(function() {
3461                if (/loaded|complete/.test(document.readyState)) fireContentLoadedEvent();
3462            }, 0);
3463            Event.observe(window, "load", fireContentLoadedEvent);
3464        } else {
3465            document.addEventListener("DOMContentLoaded", fireContentLoadedEvent, false);
3466        }
3467    } else {
3468        document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
3469        $("__onDOMContentLoaded").onreadystatechange = function() {
3470            if (this.readyState == "complete") {
3471                this.onreadystatechange = null;
3472                fireContentLoadedEvent();
3473            }
3474        };
3475    }
3476})();
3477Hash.toQueryString = Object.toQueryString;
3478var Toggle = {
3479    display: Element.toggle
3480};
3481Element.Methods.childOf = Element.Methods.descendantOf;
3482var Insertion = {
3483    Before: function(element, content) {
3484        return Element.insert(element, {
3485            before: content
3486        });
3487    },
3488    Top: function(element, content) {
3489        return Element.insert(element, {
3490            top: content
3491        });
3492    },
3493    Bottom: function(element, content) {
3494        return Element.insert(element, {
3495            bottom: content
3496        });
3497    },
3498    After: function(element, content) {
3499        return Element.insert(element, {
3500            after: content
3501        });
3502    }
3503};
3504var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
3505var Position = {
3506    includeScrollOffsets: false,
3507    prepare: function() {
3508        this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
3509        this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
3510    },
3511    within: function(element, x, y) {
3512        if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y);
3513        this.xcomp = x;
3514        this.ycomp = y;
3515        this.offset = Element.cumulativeOffset(element);
3516        return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth);
3517    },
3518    withinIncludingScrolloffsets: function(element, x, y) {
3519        var offsetcache = Element.cumulativeScrollOffset(element);
3520        this.xcomp = x + offsetcache[0] - this.deltaX;
3521        this.ycomp = y + offsetcache[1] - this.deltaY;
3522        this.offset = Element.cumulativeOffset(element);
3523        return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth);
3524    },
3525    overlap: function(mode, element) {
3526        if (!mode) return 0;
3527        if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight;
3528        if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth;
3529    },
3530    cumulativeOffset: Element.Methods.cumulativeOffset,
3531    positionedOffset: Element.Methods.positionedOffset,
3532    absolutize: function(element) {
3533        Position.prepare();
3534        return Element.absolutize(element);
3535    },
3536    relativize: function(element) {
3537        Position.prepare();
3538        return Element.relativize(element);
3539    },
3540    realOffset: Element.Methods.cumulativeScrollOffset,
3541    offsetParent: Element.Methods.getOffsetParent,
3542    page: Element.Methods.viewportOffset,
3543    clone: function(source, target, options) {
3544        options = options || {};
3545        return Element.clonePosition(target, source, options);
3546    }
3547};
3548if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods) {
3549    function iter(name) {
3550        return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
3551    }
3552    instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
3553    function(element, className) {
3554        className = className.toString().strip();
3555        var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
3556        return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
3557    } : function(element, className) {
3558        className = className.toString().strip();
3559        var elements = [],
3560            classNames = (/\s/.test(className) ? $w(className) : null);
3561        if (!classNames && !className) return elements;
3562        var nodes = $(element).getElementsByTagName('*');
3563        className = ' ' + className + ' ';
3564        for (var i = 0, child, cn; child = nodes[i]; i++) {
3565            if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || (classNames && classNames.all(function(name) {
3566                return !name.toString().blank() && cn.include(' ' + name + ' ');
3567            })))) elements.push(Element.extend(child));
3568        }
3569        return elements;
3570    };
3571    return function(className, parentElement) {
3572        return $(parentElement || document.body).getElementsByClassName(className);
3573    };
3574}(Element.Methods);
3575Element.ClassNames = Class.create();
3576Element.ClassNames.prototype = {
3577    initialize: function(element) {
3578        this.element = $(element);
3579    },
3580    _each: function(iterator) {
3581        this.element.className.split(/\s+/).select(function(name) {
3582            return name.length > 0;
3583        })._each(iterator);
3584    },
3585    set: function(className) {
3586        this.element.className = className;
3587    },
3588    add: function(classNameToAdd) {
3589        if (this.include(classNameToAdd)) return;
3590        this.set($A(this).concat(classNameToAdd).join(' '));
3591    },
3592    remove: function(classNameToRemove) {
3593        if (!this.include(classNameToRemove)) return;
3594        this.set($A(this).without(classNameToRemove).join(' '));
3595    },
3596    toString: function() {
3597        return $A(this).join(' ');
3598    }
3599};
3600Object.extend(Element.ClassNames.prototype, Enumerable);
3601Element.addMethods();

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.