]> git.wh0rd.org - tt-rss.git/blob - lib/prototype.js
pngcrush.sh
[tt-rss.git] / lib / prototype.js
1 // Modified document.on() to modified.p_on() to fix compatibility with Dojo -fox
2
3 /* Prototype JavaScript framework, version 1.7.3
4 * (c) 2005-2010 Sam Stephenson
5 *
6 * Prototype is freely distributable under the terms of an MIT-style license.
7 * For details, see the Prototype web site: http://www.prototypejs.org/
8 *
9 *--------------------------------------------------------------------------*/
10
11 var Prototype = {
12
13 Version: '1.7.3',
14
15 Browser: (function(){
16 var ua = navigator.userAgent;
17 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
18 return {
19 IE: !!window.attachEvent && !isOpera,
20 Opera: isOpera,
21 WebKit: ua.indexOf('AppleWebKit/') > -1,
22 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
23 MobileSafari: /Apple.*Mobile/.test(ua)
24 }
25 })(),
26
27 BrowserFeatures: {
28 XPath: !!document.evaluate,
29
30 SelectorsAPI: !!document.querySelector,
31
32 ElementExtensions: (function() {
33 var constructor = window.Element || window.HTMLElement;
34 return !!(constructor && constructor.prototype);
35 })(),
36 SpecificElementExtensions: (function() {
37 if (typeof window.HTMLDivElement !== 'undefined')
38 return true;
39
40 var div = document.createElement('div'),
41 form = document.createElement('form'),
42 isSupported = false;
43
44 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
45 isSupported = true;
46 }
47
48 div = form = null;
49
50 return isSupported;
51 })()
52 },
53
54 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
55 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
56
57 emptyFunction: function() { },
58
59 K: function(x) { return x }
60 };
61
62 if (Prototype.Browser.MobileSafari)
63 Prototype.BrowserFeatures.SpecificElementExtensions = false;
64 /* Based on Alex Arnell's inheritance implementation. */
65
66 var Class = (function() {
67
68 var IS_DONTENUM_BUGGY = (function(){
69 for (var p in { toString: 1 }) {
70 if (p === 'toString') return false;
71 }
72 return true;
73 })();
74
75 function subclass() {};
76 function create() {
77 var parent = null, properties = $A(arguments);
78 if (Object.isFunction(properties[0]))
79 parent = properties.shift();
80
81 function klass() {
82 this.initialize.apply(this, arguments);
83 }
84
85 Object.extend(klass, Class.Methods);
86 klass.superclass = parent;
87 klass.subclasses = [];
88
89 if (parent) {
90 subclass.prototype = parent.prototype;
91 klass.prototype = new subclass;
92 parent.subclasses.push(klass);
93 }
94
95 for (var i = 0, length = properties.length; i < length; i++)
96 klass.addMethods(properties[i]);
97
98 if (!klass.prototype.initialize)
99 klass.prototype.initialize = Prototype.emptyFunction;
100
101 klass.prototype.constructor = klass;
102 return klass;
103 }
104
105 function addMethods(source) {
106 var ancestor = this.superclass && this.superclass.prototype,
107 properties = Object.keys(source);
108
109 if (IS_DONTENUM_BUGGY) {
110 if (source.toString != Object.prototype.toString)
111 properties.push("toString");
112 if (source.valueOf != Object.prototype.valueOf)
113 properties.push("valueOf");
114 }
115
116 for (var i = 0, length = properties.length; i < length; i++) {
117 var property = properties[i], value = source[property];
118 if (ancestor && Object.isFunction(value) &&
119 value.argumentNames()[0] == "$super") {
120 var method = value;
121 value = (function(m) {
122 return function() { return ancestor[m].apply(this, arguments); };
123 })(property).wrap(method);
124
125 value.valueOf = (function(method) {
126 return function() { return method.valueOf.call(method); };
127 })(method);
128
129 value.toString = (function(method) {
130 return function() { return method.toString.call(method); };
131 })(method);
132 }
133 this.prototype[property] = value;
134 }
135
136 return this;
137 }
138
139 return {
140 create: create,
141 Methods: {
142 addMethods: addMethods
143 }
144 };
145 })();
146 (function() {
147
148 var _toString = Object.prototype.toString,
149 _hasOwnProperty = Object.prototype.hasOwnProperty,
150 NULL_TYPE = 'Null',
151 UNDEFINED_TYPE = 'Undefined',
152 BOOLEAN_TYPE = 'Boolean',
153 NUMBER_TYPE = 'Number',
154 STRING_TYPE = 'String',
155 OBJECT_TYPE = 'Object',
156 FUNCTION_CLASS = '[object Function]',
157 BOOLEAN_CLASS = '[object Boolean]',
158 NUMBER_CLASS = '[object Number]',
159 STRING_CLASS = '[object String]',
160 ARRAY_CLASS = '[object Array]',
161 DATE_CLASS = '[object Date]',
162 NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
163 typeof JSON.stringify === 'function' &&
164 JSON.stringify(0) === '0' &&
165 typeof JSON.stringify(Prototype.K) === 'undefined';
166
167
168
169 var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',
170 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
171
172 var IS_DONTENUM_BUGGY = (function(){
173 for (var p in { toString: 1 }) {
174 if (p === 'toString') return false;
175 }
176 return true;
177 })();
178
179 function Type(o) {
180 switch(o) {
181 case null: return NULL_TYPE;
182 case (void 0): return UNDEFINED_TYPE;
183 }
184 var type = typeof o;
185 switch(type) {
186 case 'boolean': return BOOLEAN_TYPE;
187 case 'number': return NUMBER_TYPE;
188 case 'string': return STRING_TYPE;
189 }
190 return OBJECT_TYPE;
191 }
192
193 function extend(destination, source) {
194 for (var property in source)
195 destination[property] = source[property];
196 return destination;
197 }
198
199 function inspect(object) {
200 try {
201 if (isUndefined(object)) return 'undefined';
202 if (object === null) return 'null';
203 return object.inspect ? object.inspect() : String(object);
204 } catch (e) {
205 if (e instanceof RangeError) return '...';
206 throw e;
207 }
208 }
209
210 function toJSON(value) {
211 return Str('', { '': value }, []);
212 }
213
214 function Str(key, holder, stack) {
215 var value = holder[key];
216 if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
217 value = value.toJSON(key);
218 }
219
220 var _class = _toString.call(value);
221
222 switch (_class) {
223 case NUMBER_CLASS:
224 case BOOLEAN_CLASS:
225 case STRING_CLASS:
226 value = value.valueOf();
227 }
228
229 switch (value) {
230 case null: return 'null';
231 case true: return 'true';
232 case false: return 'false';
233 }
234
235 var type = typeof value;
236 switch (type) {
237 case 'string':
238 return value.inspect(true);
239 case 'number':
240 return isFinite(value) ? String(value) : 'null';
241 case 'object':
242
243 for (var i = 0, length = stack.length; i < length; i++) {
244 if (stack[i] === value) {
245 throw new TypeError("Cyclic reference to '" + value + "' in object");
246 }
247 }
248 stack.push(value);
249
250 var partial = [];
251 if (_class === ARRAY_CLASS) {
252 for (var i = 0, length = value.length; i < length; i++) {
253 var str = Str(i, value, stack);
254 partial.push(typeof str === 'undefined' ? 'null' : str);
255 }
256 partial = '[' + partial.join(',') + ']';
257 } else {
258 var keys = Object.keys(value);
259 for (var i = 0, length = keys.length; i < length; i++) {
260 var key = keys[i], str = Str(key, value, stack);
261 if (typeof str !== "undefined") {
262 partial.push(key.inspect(true)+ ':' + str);
263 }
264 }
265 partial = '{' + partial.join(',') + '}';
266 }
267 stack.pop();
268 return partial;
269 }
270 }
271
272 function stringify(object) {
273 return JSON.stringify(object);
274 }
275
276 function toQueryString(object) {
277 return $H(object).toQueryString();
278 }
279
280 function toHTML(object) {
281 return object && object.toHTML ? object.toHTML() : String.interpret(object);
282 }
283
284 function keys(object) {
285 if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
286 var results = [];
287 for (var property in object) {
288 if (_hasOwnProperty.call(object, property))
289 results.push(property);
290 }
291
292 if (IS_DONTENUM_BUGGY) {
293 for (var i = 0; property = DONT_ENUMS[i]; i++) {
294 if (_hasOwnProperty.call(object, property))
295 results.push(property);
296 }
297 }
298
299 return results;
300 }
301
302 function values(object) {
303 var results = [];
304 for (var property in object)
305 results.push(object[property]);
306 return results;
307 }
308
309 function clone(object) {
310 return extend({ }, object);
311 }
312
313 function isElement(object) {
314 return !!(object && object.nodeType == 1);
315 }
316
317 function isArray(object) {
318 return _toString.call(object) === ARRAY_CLASS;
319 }
320
321 var hasNativeIsArray = (typeof Array.isArray == 'function')
322 && Array.isArray([]) && !Array.isArray({});
323
324 if (hasNativeIsArray) {
325 isArray = Array.isArray;
326 }
327
328 function isHash(object) {
329 return object instanceof Hash;
330 }
331
332 function isFunction(object) {
333 return _toString.call(object) === FUNCTION_CLASS;
334 }
335
336 function isString(object) {
337 return _toString.call(object) === STRING_CLASS;
338 }
339
340 function isNumber(object) {
341 return _toString.call(object) === NUMBER_CLASS;
342 }
343
344 function isDate(object) {
345 return _toString.call(object) === DATE_CLASS;
346 }
347
348 function isUndefined(object) {
349 return typeof object === "undefined";
350 }
351
352 extend(Object, {
353 extend: extend,
354 inspect: inspect,
355 toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
356 toQueryString: toQueryString,
357 toHTML: toHTML,
358 keys: Object.keys || keys,
359 values: values,
360 clone: clone,
361 isElement: isElement,
362 isArray: isArray,
363 isHash: isHash,
364 isFunction: isFunction,
365 isString: isString,
366 isNumber: isNumber,
367 isDate: isDate,
368 isUndefined: isUndefined
369 });
370 })();
371 Object.extend(Function.prototype, (function() {
372 var slice = Array.prototype.slice;
373
374 function update(array, args) {
375 var arrayLength = array.length, length = args.length;
376 while (length--) array[arrayLength + length] = args[length];
377 return array;
378 }
379
380 function merge(array, args) {
381 array = slice.call(array, 0);
382 return update(array, args);
383 }
384
385 function argumentNames() {
386 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
387 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
388 .replace(/\s+/g, '').split(',');
389 return names.length == 1 && !names[0] ? [] : names;
390 }
391
392
393 function bind(context) {
394 if (arguments.length < 2 && Object.isUndefined(arguments[0]))
395 return this;
396
397 if (!Object.isFunction(this))
398 throw new TypeError("The object is not callable.");
399
400 var nop = function() {};
401 var __method = this, args = slice.call(arguments, 1);
402
403 var bound = function() {
404 var a = merge(args, arguments);
405 var c = this instanceof bound ? this : context;
406 return __method.apply(c, a);
407 };
408
409 nop.prototype = this.prototype;
410 bound.prototype = new nop();
411
412 return bound;
413 }
414
415 function bindAsEventListener(context) {
416 var __method = this, args = slice.call(arguments, 1);
417 return function(event) {
418 var a = update([event || window.event], args);
419 return __method.apply(context, a);
420 }
421 }
422
423 function curry() {
424 if (!arguments.length) return this;
425 var __method = this, args = slice.call(arguments, 0);
426 return function() {
427 var a = merge(args, arguments);
428 return __method.apply(this, a);
429 }
430 }
431
432 function delay(timeout) {
433 var __method = this, args = slice.call(arguments, 1);
434 timeout = timeout * 1000;
435 return window.setTimeout(function() {
436 return __method.apply(__method, args);
437 }, timeout);
438 }
439
440 function defer() {
441 var args = update([0.01], arguments);
442 return this.delay.apply(this, args);
443 }
444
445 function wrap(wrapper) {
446 var __method = this;
447 return function() {
448 var a = update([__method.bind(this)], arguments);
449 return wrapper.apply(this, a);
450 }
451 }
452
453 function methodize() {
454 if (this._methodized) return this._methodized;
455 var __method = this;
456 return this._methodized = function() {
457 var a = update([this], arguments);
458 return __method.apply(null, a);
459 };
460 }
461
462 var extensions = {
463 argumentNames: argumentNames,
464 bindAsEventListener: bindAsEventListener,
465 curry: curry,
466 delay: delay,
467 defer: defer,
468 wrap: wrap,
469 methodize: methodize
470 };
471
472 if (!Function.prototype.bind)
473 extensions.bind = bind;
474
475 return extensions;
476 })());
477
478
479
480 (function(proto) {
481
482
483 function toISOString() {
484 return this.getUTCFullYear() + '-' +
485 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
486 this.getUTCDate().toPaddedString(2) + 'T' +
487 this.getUTCHours().toPaddedString(2) + ':' +
488 this.getUTCMinutes().toPaddedString(2) + ':' +
489 this.getUTCSeconds().toPaddedString(2) + 'Z';
490 }
491
492
493 function toJSON() {
494 return this.toISOString();
495 }
496
497 if (!proto.toISOString) proto.toISOString = toISOString;
498 if (!proto.toJSON) proto.toJSON = toJSON;
499
500 })(Date.prototype);
501
502
503 RegExp.prototype.match = RegExp.prototype.test;
504
505 RegExp.escape = function(str) {
506 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
507 };
508 var PeriodicalExecuter = Class.create({
509 initialize: function(callback, frequency) {
510 this.callback = callback;
511 this.frequency = frequency;
512 this.currentlyExecuting = false;
513
514 this.registerCallback();
515 },
516
517 registerCallback: function() {
518 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
519 },
520
521 execute: function() {
522 this.callback(this);
523 },
524
525 stop: function() {
526 if (!this.timer) return;
527 clearInterval(this.timer);
528 this.timer = null;
529 },
530
531 onTimerEvent: function() {
532 if (!this.currentlyExecuting) {
533 try {
534 this.currentlyExecuting = true;
535 this.execute();
536 this.currentlyExecuting = false;
537 } catch(e) {
538 this.currentlyExecuting = false;
539 throw e;
540 }
541 }
542 }
543 });
544 Object.extend(String, {
545 interpret: function(value) {
546 return value == null ? '' : String(value);
547 },
548 specialChar: {
549 '\b': '\\b',
550 '\t': '\\t',
551 '\n': '\\n',
552 '\f': '\\f',
553 '\r': '\\r',
554 '\\': '\\\\'
555 }
556 });
557
558 Object.extend(String.prototype, (function() {
559 var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
560 typeof JSON.parse === 'function' &&
561 JSON.parse('{"test": true}').test;
562
563 function prepareReplacement(replacement) {
564 if (Object.isFunction(replacement)) return replacement;
565 var template = new Template(replacement);
566 return function(match) { return template.evaluate(match) };
567 }
568
569 function isNonEmptyRegExp(regexp) {
570 return regexp.source && regexp.source !== '(?:)';
571 }
572
573
574 function gsub(pattern, replacement) {
575 var result = '', source = this, match;
576 replacement = prepareReplacement(replacement);
577
578 if (Object.isString(pattern))
579 pattern = RegExp.escape(pattern);
580
581 if (!(pattern.length || isNonEmptyRegExp(pattern))) {
582 replacement = replacement('');
583 return replacement + source.split('').join(replacement) + replacement;
584 }
585
586 while (source.length > 0) {
587 match = source.match(pattern)
588 if (match && match[0].length > 0) {
589 result += source.slice(0, match.index);
590 result += String.interpret(replacement(match));
591 source = source.slice(match.index + match[0].length);
592 } else {
593 result += source, source = '';
594 }
595 }
596 return result;
597 }
598
599 function sub(pattern, replacement, count) {
600 replacement = prepareReplacement(replacement);
601 count = Object.isUndefined(count) ? 1 : count;
602
603 return this.gsub(pattern, function(match) {
604 if (--count < 0) return match[0];
605 return replacement(match);
606 });
607 }
608
609 function scan(pattern, iterator) {
610 this.gsub(pattern, iterator);
611 return String(this);
612 }
613
614 function truncate(length, truncation) {
615 length = length || 30;
616 truncation = Object.isUndefined(truncation) ? '...' : truncation;
617 return this.length > length ?
618 this.slice(0, length - truncation.length) + truncation : String(this);
619 }
620
621 function strip() {
622 return this.replace(/^\s+/, '').replace(/\s+$/, '');
623 }
624
625 function stripTags() {
626 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, '');
627 }
628
629 function stripScripts() {
630 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
631 }
632
633 function extractScripts() {
634 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
635 matchOne = new RegExp(Prototype.ScriptFragment, 'im');
636 return (this.match(matchAll) || []).map(function(scriptTag) {
637 return (scriptTag.match(matchOne) || ['', ''])[1];
638 });
639 }
640
641 function evalScripts() {
642 return this.extractScripts().map(function(script) { return eval(script); });
643 }
644
645 function escapeHTML() {
646 return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
647 }
648
649 function unescapeHTML() {
650 return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
651 }
652
653
654 function toQueryParams(separator) {
655 var match = this.strip().match(/([^?#]*)(#.*)?$/);
656 if (!match) return { };
657
658 return match[1].split(separator || '&').inject({ }, function(hash, pair) {
659 if ((pair = pair.split('='))[0]) {
660 var key = decodeURIComponent(pair.shift()),
661 value = pair.length > 1 ? pair.join('=') : pair[0];
662
663 if (value != undefined) {
664 value = value.gsub('+', ' ');
665 value = decodeURIComponent(value);
666 }
667
668 if (key in hash) {
669 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
670 hash[key].push(value);
671 }
672 else hash[key] = value;
673 }
674 return hash;
675 });
676 }
677
678 function toArray() {
679 return this.split('');
680 }
681
682 function succ() {
683 return this.slice(0, this.length - 1) +
684 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
685 }
686
687 function times(count) {
688 return count < 1 ? '' : new Array(count + 1).join(this);
689 }
690
691 function camelize() {
692 return this.replace(/-+(.)?/g, function(match, chr) {
693 return chr ? chr.toUpperCase() : '';
694 });
695 }
696
697 function capitalize() {
698 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
699 }
700
701 function underscore() {
702 return this.replace(/::/g, '/')
703 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
704 .replace(/([a-z\d])([A-Z])/g, '$1_$2')
705 .replace(/-/g, '_')
706 .toLowerCase();
707 }
708
709 function dasherize() {
710 return this.replace(/_/g, '-');
711 }
712
713 function inspect(useDoubleQuotes) {
714 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
715 if (character in String.specialChar) {
716 return String.specialChar[character];
717 }
718 return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
719 });
720 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
721 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
722 }
723
724 function unfilterJSON(filter) {
725 return this.replace(filter || Prototype.JSONFilter, '$1');
726 }
727
728 function isJSON() {
729 var str = this;
730 if (str.blank()) return false;
731 str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
732 str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
733 str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
734 return (/^[\],:{}\s]*$/).test(str);
735 }
736
737 function evalJSON(sanitize) {
738 var json = this.unfilterJSON(),
739 cx = /[\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\u0000]/g;
740 if (cx.test(json)) {
741 json = json.replace(cx, function (a) {
742 return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
743 });
744 }
745 try {
746 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
747 } catch (e) { }
748 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
749 }
750
751 function parseJSON() {
752 var json = this.unfilterJSON();
753 return JSON.parse(json);
754 }
755
756 function include(pattern) {
757 return this.indexOf(pattern) > -1;
758 }
759
760 function startsWith(pattern, position) {
761 position = Object.isNumber(position) ? position : 0;
762 return this.lastIndexOf(pattern, position) === position;
763 }
764
765 function endsWith(pattern, position) {
766 pattern = String(pattern);
767 position = Object.isNumber(position) ? position : this.length;
768 if (position < 0) position = 0;
769 if (position > this.length) position = this.length;
770 var d = position - pattern.length;
771 return d >= 0 && this.indexOf(pattern, d) === d;
772 }
773
774 function empty() {
775 return this == '';
776 }
777
778 function blank() {
779 return /^\s*$/.test(this);
780 }
781
782 function interpolate(object, pattern) {
783 return new Template(this, pattern).evaluate(object);
784 }
785
786 return {
787 gsub: gsub,
788 sub: sub,
789 scan: scan,
790 truncate: truncate,
791 strip: String.prototype.trim || strip,
792 stripTags: stripTags,
793 stripScripts: stripScripts,
794 extractScripts: extractScripts,
795 evalScripts: evalScripts,
796 escapeHTML: escapeHTML,
797 unescapeHTML: unescapeHTML,
798 toQueryParams: toQueryParams,
799 parseQuery: toQueryParams,
800 toArray: toArray,
801 succ: succ,
802 times: times,
803 camelize: camelize,
804 capitalize: capitalize,
805 underscore: underscore,
806 dasherize: dasherize,
807 inspect: inspect,
808 unfilterJSON: unfilterJSON,
809 isJSON: isJSON,
810 evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
811 include: include,
812 startsWith: String.prototype.startsWith || startsWith,
813 endsWith: String.prototype.endsWith || endsWith,
814 empty: empty,
815 blank: blank,
816 interpolate: interpolate
817 };
818 })());
819
820 var Template = Class.create({
821 initialize: function(template, pattern) {
822 this.template = template.toString();
823 this.pattern = pattern || Template.Pattern;
824 },
825
826 evaluate: function(object) {
827 if (object && Object.isFunction(object.toTemplateReplacements))
828 object = object.toTemplateReplacements();
829
830 return this.template.gsub(this.pattern, function(match) {
831 if (object == null) return (match[1] + '');
832
833 var before = match[1] || '';
834 if (before == '\\') return match[2];
835
836 var ctx = object, expr = match[3],
837 pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
838
839 match = pattern.exec(expr);
840 if (match == null) return before;
841
842 while (match != null) {
843 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
844 ctx = ctx[comp];
845 if (null == ctx || '' == match[3]) break;
846 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
847 match = pattern.exec(expr);
848 }
849
850 return before + String.interpret(ctx);
851 });
852 }
853 });
854 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
855
856 var $break = { };
857
858 var Enumerable = (function() {
859 function each(iterator, context) {
860 try {
861 this._each(iterator, context);
862 } catch (e) {
863 if (e != $break) throw e;
864 }
865 return this;
866 }
867
868 function eachSlice(number, iterator, context) {
869 var index = -number, slices = [], array = this.toArray();
870 if (number < 1) return array;
871 while ((index += number) < array.length)
872 slices.push(array.slice(index, index+number));
873 return slices.collect(iterator, context);
874 }
875
876 function all(iterator, context) {
877 iterator = iterator || Prototype.K;
878 var result = true;
879 this.each(function(value, index) {
880 result = result && !!iterator.call(context, value, index, this);
881 if (!result) throw $break;
882 }, this);
883 return result;
884 }
885
886 function any(iterator, context) {
887 iterator = iterator || Prototype.K;
888 var result = false;
889 this.each(function(value, index) {
890 if (result = !!iterator.call(context, value, index, this))
891 throw $break;
892 }, this);
893 return result;
894 }
895
896 function collect(iterator, context) {
897 iterator = iterator || Prototype.K;
898 var results = [];
899 this.each(function(value, index) {
900 results.push(iterator.call(context, value, index, this));
901 }, this);
902 return results;
903 }
904
905 function detect(iterator, context) {
906 var result;
907 this.each(function(value, index) {
908 if (iterator.call(context, value, index, this)) {
909 result = value;
910 throw $break;
911 }
912 }, this);
913 return result;
914 }
915
916 function findAll(iterator, context) {
917 var results = [];
918 this.each(function(value, index) {
919 if (iterator.call(context, value, index, this))
920 results.push(value);
921 }, this);
922 return results;
923 }
924
925 function grep(filter, iterator, context) {
926 iterator = iterator || Prototype.K;
927 var results = [];
928
929 if (Object.isString(filter))
930 filter = new RegExp(RegExp.escape(filter));
931
932 this.each(function(value, index) {
933 if (filter.match(value))
934 results.push(iterator.call(context, value, index, this));
935 }, this);
936 return results;
937 }
938
939 function include(object) {
940 if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)
941 return true;
942
943 var found = false;
944 this.each(function(value) {
945 if (value == object) {
946 found = true;
947 throw $break;
948 }
949 });
950 return found;
951 }
952
953 function inGroupsOf(number, fillWith) {
954 fillWith = Object.isUndefined(fillWith) ? null : fillWith;
955 return this.eachSlice(number, function(slice) {
956 while(slice.length < number) slice.push(fillWith);
957 return slice;
958 });
959 }
960
961 function inject(memo, iterator, context) {
962 this.each(function(value, index) {
963 memo = iterator.call(context, memo, value, index, this);
964 }, this);
965 return memo;
966 }
967
968 function invoke(method) {
969 var args = $A(arguments).slice(1);
970 return this.map(function(value) {
971 return value[method].apply(value, args);
972 });
973 }
974
975 function max(iterator, context) {
976 iterator = iterator || Prototype.K;
977 var result;
978 this.each(function(value, index) {
979 value = iterator.call(context, value, index, this);
980 if (result == null || value >= result)
981 result = value;
982 }, this);
983 return result;
984 }
985
986 function min(iterator, context) {
987 iterator = iterator || Prototype.K;
988 var result;
989 this.each(function(value, index) {
990 value = iterator.call(context, value, index, this);
991 if (result == null || value < result)
992 result = value;
993 }, this);
994 return result;
995 }
996
997 function partition(iterator, context) {
998 iterator = iterator || Prototype.K;
999 var trues = [], falses = [];
1000 this.each(function(value, index) {
1001 (iterator.call(context, value, index, this) ?
1002 trues : falses).push(value);
1003 }, this);
1004 return [trues, falses];
1005 }
1006
1007 function pluck(property) {
1008 var results = [];
1009 this.each(function(value) {
1010 results.push(value[property]);
1011 });
1012 return results;
1013 }
1014
1015 function reject(iterator, context) {
1016 var results = [];
1017 this.each(function(value, index) {
1018 if (!iterator.call(context, value, index, this))
1019 results.push(value);
1020 }, this);
1021 return results;
1022 }
1023
1024 function sortBy(iterator, context) {
1025 return this.map(function(value, index) {
1026 return {
1027 value: value,
1028 criteria: iterator.call(context, value, index, this)
1029 };
1030 }, this).sort(function(left, right) {
1031 var a = left.criteria, b = right.criteria;
1032 return a < b ? -1 : a > b ? 1 : 0;
1033 }).pluck('value');
1034 }
1035
1036 function toArray() {
1037 return this.map();
1038 }
1039
1040 function zip() {
1041 var iterator = Prototype.K, args = $A(arguments);
1042 if (Object.isFunction(args.last()))
1043 iterator = args.pop();
1044
1045 var collections = [this].concat(args).map($A);
1046 return this.map(function(value, index) {
1047 return iterator(collections.pluck(index));
1048 });
1049 }
1050
1051 function size() {
1052 return this.toArray().length;
1053 }
1054
1055 function inspect() {
1056 return '#<Enumerable:' + this.toArray().inspect() + '>';
1057 }
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 return {
1068 each: each,
1069 eachSlice: eachSlice,
1070 all: all,
1071 every: all,
1072 any: any,
1073 some: any,
1074 collect: collect,
1075 map: collect,
1076 detect: detect,
1077 findAll: findAll,
1078 select: findAll,
1079 filter: findAll,
1080 grep: grep,
1081 include: include,
1082 member: include,
1083 inGroupsOf: inGroupsOf,
1084 inject: inject,
1085 invoke: invoke,
1086 max: max,
1087 min: min,
1088 partition: partition,
1089 pluck: pluck,
1090 reject: reject,
1091 sortBy: sortBy,
1092 toArray: toArray,
1093 entries: toArray,
1094 zip: zip,
1095 size: size,
1096 inspect: inspect,
1097 find: detect
1098 };
1099 })();
1100
1101 function $A(iterable) {
1102 if (!iterable) return [];
1103 if ('toArray' in Object(iterable)) return iterable.toArray();
1104 var length = iterable.length || 0, results = new Array(length);
1105 while (length--) results[length] = iterable[length];
1106 return results;
1107 }
1108
1109
1110 function $w(string) {
1111 if (!Object.isString(string)) return [];
1112 string = string.strip();
1113 return string ? string.split(/\s+/) : [];
1114 }
1115
1116 Array.from = $A;
1117
1118
1119 (function() {
1120 var arrayProto = Array.prototype,
1121 slice = arrayProto.slice,
1122 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1123
1124 function each(iterator, context) {
1125 for (var i = 0, length = this.length >>> 0; i < length; i++) {
1126 if (i in this) iterator.call(context, this[i], i, this);
1127 }
1128 }
1129 if (!_each) _each = each;
1130
1131 function clear() {
1132 this.length = 0;
1133 return this;
1134 }
1135
1136 function first() {
1137 return this[0];
1138 }
1139
1140 function last() {
1141 return this[this.length - 1];
1142 }
1143
1144 function compact() {
1145 return this.select(function(value) {
1146 return value != null;
1147 });
1148 }
1149
1150 function flatten() {
1151 return this.inject([], function(array, value) {
1152 if (Object.isArray(value))
1153 return array.concat(value.flatten());
1154 array.push(value);
1155 return array;
1156 });
1157 }
1158
1159 function without() {
1160 var values = slice.call(arguments, 0);
1161 return this.select(function(value) {
1162 return !values.include(value);
1163 });
1164 }
1165
1166 function reverse(inline) {
1167 return (inline === false ? this.toArray() : this)._reverse();
1168 }
1169
1170 function uniq(sorted) {
1171 return this.inject([], function(array, value, index) {
1172 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1173 array.push(value);
1174 return array;
1175 });
1176 }
1177
1178 function intersect(array) {
1179 return this.uniq().findAll(function(item) {
1180 return array.indexOf(item) !== -1;
1181 });
1182 }
1183
1184
1185 function clone() {
1186 return slice.call(this, 0);
1187 }
1188
1189 function size() {
1190 return this.length;
1191 }
1192
1193 function inspect() {
1194 return '[' + this.map(Object.inspect).join(', ') + ']';
1195 }
1196
1197 function indexOf(item, i) {
1198 if (this == null) throw new TypeError();
1199
1200 var array = Object(this), length = array.length >>> 0;
1201 if (length === 0) return -1;
1202
1203 i = Number(i);
1204 if (isNaN(i)) {
1205 i = 0;
1206 } else if (i !== 0 && isFinite(i)) {
1207 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1208 }
1209
1210 if (i > length) return -1;
1211
1212 var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);
1213 for (; k < length; k++)
1214 if (k in array && array[k] === item) return k;
1215 return -1;
1216 }
1217
1218
1219 function lastIndexOf(item, i) {
1220 if (this == null) throw new TypeError();
1221
1222 var array = Object(this), length = array.length >>> 0;
1223 if (length === 0) return -1;
1224
1225 if (!Object.isUndefined(i)) {
1226 i = Number(i);
1227 if (isNaN(i)) {
1228 i = 0;
1229 } else if (i !== 0 && isFinite(i)) {
1230 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1231 }
1232 } else {
1233 i = length;
1234 }
1235
1236 var k = i >= 0 ? Math.min(i, length - 1) :
1237 length - Math.abs(i);
1238
1239 for (; k >= 0; k--)
1240 if (k in array && array[k] === item) return k;
1241 return -1;
1242 }
1243
1244 function concat(_) {
1245 var array = [], items = slice.call(arguments, 0), item, n = 0;
1246 items.unshift(this);
1247 for (var i = 0, length = items.length; i < length; i++) {
1248 item = items[i];
1249 if (Object.isArray(item) && !('callee' in item)) {
1250 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
1251 if (j in item) array[n] = item[j];
1252 n++;
1253 }
1254 } else {
1255 array[n++] = item;
1256 }
1257 }
1258 array.length = n;
1259 return array;
1260 }
1261
1262
1263 function wrapNative(method) {
1264 return function() {
1265 if (arguments.length === 0) {
1266 return method.call(this, Prototype.K);
1267 } else if (arguments[0] === undefined) {
1268 var args = slice.call(arguments, 1);
1269 args.unshift(Prototype.K);
1270 return method.apply(this, args);
1271 } else {
1272 return method.apply(this, arguments);
1273 }
1274 };
1275 }
1276
1277
1278 function map(iterator) {
1279 if (this == null) throw new TypeError();
1280 iterator = iterator || Prototype.K;
1281
1282 var object = Object(this);
1283 var results = [], context = arguments[1], n = 0;
1284
1285 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1286 if (i in object) {
1287 results[n] = iterator.call(context, object[i], i, object);
1288 }
1289 n++;
1290 }
1291 results.length = n;
1292 return results;
1293 }
1294
1295 if (arrayProto.map) {
1296 map = wrapNative(Array.prototype.map);
1297 }
1298
1299 function filter(iterator) {
1300 if (this == null || !Object.isFunction(iterator))
1301 throw new TypeError();
1302
1303 var object = Object(this);
1304 var results = [], context = arguments[1], value;
1305
1306 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1307 if (i in object) {
1308 value = object[i];
1309 if (iterator.call(context, value, i, object)) {
1310 results.push(value);
1311 }
1312 }
1313 }
1314 return results;
1315 }
1316
1317 if (arrayProto.filter) {
1318 filter = Array.prototype.filter;
1319 }
1320
1321 function some(iterator) {
1322 if (this == null) throw new TypeError();
1323 iterator = iterator || Prototype.K;
1324 var context = arguments[1];
1325
1326 var object = Object(this);
1327 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1328 if (i in object && iterator.call(context, object[i], i, object)) {
1329 return true;
1330 }
1331 }
1332
1333 return false;
1334 }
1335
1336 if (arrayProto.some) {
1337 some = wrapNative(Array.prototype.some);
1338 }
1339
1340 function every(iterator) {
1341 if (this == null) throw new TypeError();
1342 iterator = iterator || Prototype.K;
1343 var context = arguments[1];
1344
1345 var object = Object(this);
1346 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1347 if (i in object && !iterator.call(context, object[i], i, object)) {
1348 return false;
1349 }
1350 }
1351
1352 return true;
1353 }
1354
1355 if (arrayProto.every) {
1356 every = wrapNative(Array.prototype.every);
1357 }
1358
1359
1360 Object.extend(arrayProto, Enumerable);
1361
1362 if (arrayProto.entries === Enumerable.entries) {
1363 delete arrayProto.entries;
1364 }
1365
1366 if (!arrayProto._reverse)
1367 arrayProto._reverse = arrayProto.reverse;
1368
1369 Object.extend(arrayProto, {
1370 _each: _each,
1371
1372 map: map,
1373 collect: map,
1374 select: filter,
1375 filter: filter,
1376 findAll: filter,
1377 some: some,
1378 any: some,
1379 every: every,
1380 all: every,
1381
1382 clear: clear,
1383 first: first,
1384 last: last,
1385 compact: compact,
1386 flatten: flatten,
1387 without: without,
1388 reverse: reverse,
1389 uniq: uniq,
1390 intersect: intersect,
1391 clone: clone,
1392 toArray: clone,
1393 size: size,
1394 inspect: inspect
1395 });
1396
1397 var CONCAT_ARGUMENTS_BUGGY = (function() {
1398 return [].concat(arguments)[0][0] !== 1;
1399 })(1,2);
1400
1401 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1402
1403 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1404 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1405 })();
1406 function $H(object) {
1407 return new Hash(object);
1408 };
1409
1410 var Hash = Class.create(Enumerable, (function() {
1411 function initialize(object) {
1412 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1413 }
1414
1415
1416 function _each(iterator, context) {
1417 var i = 0;
1418 for (var key in this._object) {
1419 var value = this._object[key], pair = [key, value];
1420 pair.key = key;
1421 pair.value = value;
1422 iterator.call(context, pair, i);
1423 i++;
1424 }
1425 }
1426
1427 function set(key, value) {
1428 return this._object[key] = value;
1429 }
1430
1431 function get(key) {
1432 if (this._object[key] !== Object.prototype[key])
1433 return this._object[key];
1434 }
1435
1436 function unset(key) {
1437 var value = this._object[key];
1438 delete this._object[key];
1439 return value;
1440 }
1441
1442 function toObject() {
1443 return Object.clone(this._object);
1444 }
1445
1446
1447
1448 function keys() {
1449 return this.pluck('key');
1450 }
1451
1452 function values() {
1453 return this.pluck('value');
1454 }
1455
1456 function index(value) {
1457 var match = this.detect(function(pair) {
1458 return pair.value === value;
1459 });
1460 return match && match.key;
1461 }
1462
1463 function merge(object) {
1464 return this.clone().update(object);
1465 }
1466
1467 function update(object) {
1468 return new Hash(object).inject(this, function(result, pair) {
1469 result.set(pair.key, pair.value);
1470 return result;
1471 });
1472 }
1473
1474 function toQueryPair(key, value) {
1475 if (Object.isUndefined(value)) return key;
1476
1477 value = String.interpret(value);
1478
1479 value = value.gsub(/(\r)?\n/, '\r\n');
1480 value = encodeURIComponent(value);
1481 value = value.gsub(/%20/, '+');
1482 return key + '=' + value;
1483 }
1484
1485 function toQueryString() {
1486 return this.inject([], function(results, pair) {
1487 var key = encodeURIComponent(pair.key), values = pair.value;
1488
1489 if (values && typeof values == 'object') {
1490 if (Object.isArray(values)) {
1491 var queryValues = [];
1492 for (var i = 0, len = values.length, value; i < len; i++) {
1493 value = values[i];
1494 queryValues.push(toQueryPair(key, value));
1495 }
1496 return results.concat(queryValues);
1497 }
1498 } else results.push(toQueryPair(key, values));
1499 return results;
1500 }).join('&');
1501 }
1502
1503 function inspect() {
1504 return '#<Hash:{' + this.map(function(pair) {
1505 return pair.map(Object.inspect).join(': ');
1506 }).join(', ') + '}>';
1507 }
1508
1509 function clone() {
1510 return new Hash(this);
1511 }
1512
1513 return {
1514 initialize: initialize,
1515 _each: _each,
1516 set: set,
1517 get: get,
1518 unset: unset,
1519 toObject: toObject,
1520 toTemplateReplacements: toObject,
1521 keys: keys,
1522 values: values,
1523 index: index,
1524 merge: merge,
1525 update: update,
1526 toQueryString: toQueryString,
1527 inspect: inspect,
1528 toJSON: toObject,
1529 clone: clone
1530 };
1531 })());
1532
1533 Hash.from = $H;
1534 Object.extend(Number.prototype, (function() {
1535 function toColorPart() {
1536 return this.toPaddedString(2, 16);
1537 }
1538
1539 function succ() {
1540 return this + 1;
1541 }
1542
1543 function times(iterator, context) {
1544 $R(0, this, true).each(iterator, context);
1545 return this;
1546 }
1547
1548 function toPaddedString(length, radix) {
1549 var string = this.toString(radix || 10);
1550 return '0'.times(length - string.length) + string;
1551 }
1552
1553 function abs() {
1554 return Math.abs(this);
1555 }
1556
1557 function round() {
1558 return Math.round(this);
1559 }
1560
1561 function ceil() {
1562 return Math.ceil(this);
1563 }
1564
1565 function floor() {
1566 return Math.floor(this);
1567 }
1568
1569 return {
1570 toColorPart: toColorPart,
1571 succ: succ,
1572 times: times,
1573 toPaddedString: toPaddedString,
1574 abs: abs,
1575 round: round,
1576 ceil: ceil,
1577 floor: floor
1578 };
1579 })());
1580
1581 function $R(start, end, exclusive) {
1582 return new ObjectRange(start, end, exclusive);
1583 }
1584
1585 var ObjectRange = Class.create(Enumerable, (function() {
1586 function initialize(start, end, exclusive) {
1587 this.start = start;
1588 this.end = end;
1589 this.exclusive = exclusive;
1590 }
1591
1592 function _each(iterator, context) {
1593 var value = this.start, i;
1594 for (i = 0; this.include(value); i++) {
1595 iterator.call(context, value, i);
1596 value = value.succ();
1597 }
1598 }
1599
1600 function include(value) {
1601 if (value < this.start)
1602 return false;
1603 if (this.exclusive)
1604 return value < this.end;
1605 return value <= this.end;
1606 }
1607
1608 return {
1609 initialize: initialize,
1610 _each: _each,
1611 include: include
1612 };
1613 })());
1614
1615
1616
1617 var Abstract = { };
1618
1619
1620 var Try = {
1621 these: function() {
1622 var returnValue;
1623
1624 for (var i = 0, length = arguments.length; i < length; i++) {
1625 var lambda = arguments[i];
1626 try {
1627 returnValue = lambda();
1628 break;
1629 } catch (e) { }
1630 }
1631
1632 return returnValue;
1633 }
1634 };
1635
1636 var Ajax = {
1637 getTransport: function() {
1638 return Try.these(
1639 function() {return new XMLHttpRequest()},
1640 function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1641 function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1642 ) || false;
1643 },
1644
1645 activeRequestCount: 0
1646 };
1647
1648 Ajax.Responders = {
1649 responders: [],
1650
1651 _each: function(iterator, context) {
1652 this.responders._each(iterator, context);
1653 },
1654
1655 register: function(responder) {
1656 if (!this.include(responder))
1657 this.responders.push(responder);
1658 },
1659
1660 unregister: function(responder) {
1661 this.responders = this.responders.without(responder);
1662 },
1663
1664 dispatch: function(callback, request, transport, json) {
1665 this.each(function(responder) {
1666 if (Object.isFunction(responder[callback])) {
1667 try {
1668 responder[callback].apply(responder, [request, transport, json]);
1669 } catch (e) { }
1670 }
1671 });
1672 }
1673 };
1674
1675 Object.extend(Ajax.Responders, Enumerable);
1676
1677 Ajax.Responders.register({
1678 onCreate: function() { Ajax.activeRequestCount++ },
1679 onComplete: function() { Ajax.activeRequestCount-- }
1680 });
1681 Ajax.Base = Class.create({
1682 initialize: function(options) {
1683 this.options = {
1684 method: 'post',
1685 asynchronous: true,
1686 contentType: 'application/x-www-form-urlencoded',
1687 encoding: 'UTF-8',
1688 parameters: '',
1689 evalJSON: true,
1690 evalJS: true
1691 };
1692 Object.extend(this.options, options || { });
1693
1694 this.options.method = this.options.method.toLowerCase();
1695
1696 if (Object.isHash(this.options.parameters))
1697 this.options.parameters = this.options.parameters.toObject();
1698 }
1699 });
1700 Ajax.Request = Class.create(Ajax.Base, {
1701 _complete: false,
1702
1703 initialize: function($super, url, options) {
1704 $super(options);
1705 this.transport = Ajax.getTransport();
1706 this.request(url);
1707 },
1708
1709 request: function(url) {
1710 this.url = url;
1711 this.method = this.options.method;
1712 var params = Object.isString(this.options.parameters) ?
1713 this.options.parameters :
1714 Object.toQueryString(this.options.parameters);
1715
1716 if (!['get', 'post'].include(this.method)) {
1717 params += (params ? '&' : '') + "_method=" + this.method;
1718 this.method = 'post';
1719 }
1720
1721 if (params && this.method === 'get') {
1722 this.url += (this.url.include('?') ? '&' : '?') + params;
1723 }
1724
1725 this.parameters = params.toQueryParams();
1726
1727 try {
1728 var response = new Ajax.Response(this);
1729 if (this.options.onCreate) this.options.onCreate(response);
1730 Ajax.Responders.dispatch('onCreate', this, response);
1731
1732 this.transport.open(this.method.toUpperCase(), this.url,
1733 this.options.asynchronous);
1734
1735 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1736
1737 this.transport.onreadystatechange = this.onStateChange.bind(this);
1738 this.setRequestHeaders();
1739
1740 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1741 this.transport.send(this.body);
1742
1743 /* Force Firefox to handle ready state 4 for synchronous requests */
1744 if (!this.options.asynchronous && this.transport.overrideMimeType)
1745 this.onStateChange();
1746
1747 }
1748 catch (e) {
1749 this.dispatchException(e);
1750 }
1751 },
1752
1753 onStateChange: function() {
1754 var readyState = this.transport.readyState;
1755 if (readyState > 1 && !((readyState == 4) && this._complete))
1756 this.respondToReadyState(this.transport.readyState);
1757 },
1758
1759 setRequestHeaders: function() {
1760 var headers = {
1761 'X-Requested-With': 'XMLHttpRequest',
1762 'X-Prototype-Version': Prototype.Version,
1763 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1764 };
1765
1766 if (this.method == 'post') {
1767 headers['Content-type'] = this.options.contentType +
1768 (this.options.encoding ? '; charset=' + this.options.encoding : '');
1769
1770 /* Force "Connection: close" for older Mozilla browsers to work
1771 * around a bug where XMLHttpRequest sends an incorrect
1772 * Content-length header. See Mozilla Bugzilla #246651.
1773 */
1774 if (this.transport.overrideMimeType &&
1775 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1776 headers['Connection'] = 'close';
1777 }
1778
1779 if (typeof this.options.requestHeaders == 'object') {
1780 var extras = this.options.requestHeaders;
1781
1782 if (Object.isFunction(extras.push))
1783 for (var i = 0, length = extras.length; i < length; i += 2)
1784 headers[extras[i]] = extras[i+1];
1785 else
1786 $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1787 }
1788
1789 for (var name in headers)
1790 if (headers[name] != null)
1791 this.transport.setRequestHeader(name, headers[name]);
1792 },
1793
1794 success: function() {
1795 var status = this.getStatus();
1796 return !status || (status >= 200 && status < 300) || status == 304;
1797 },
1798
1799 getStatus: function() {
1800 try {
1801 if (this.transport.status === 1223) return 204;
1802 return this.transport.status || 0;
1803 } catch (e) { return 0 }
1804 },
1805
1806 respondToReadyState: function(readyState) {
1807 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1808
1809 if (state == 'Complete') {
1810 try {
1811 this._complete = true;
1812 (this.options['on' + response.status]
1813 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1814 || Prototype.emptyFunction)(response, response.headerJSON);
1815 } catch (e) {
1816 this.dispatchException(e);
1817 }
1818
1819 var contentType = response.getHeader('Content-type');
1820 if (this.options.evalJS == 'force'
1821 || (this.options.evalJS && this.isSameOrigin() && contentType
1822 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1823 this.evalResponse();
1824 }
1825
1826 try {
1827 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1828 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1829 } catch (e) {
1830 this.dispatchException(e);
1831 }
1832
1833 if (state == 'Complete') {
1834 this.transport.onreadystatechange = Prototype.emptyFunction;
1835 }
1836 },
1837
1838 isSameOrigin: function() {
1839 var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1840 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1841 protocol: location.protocol,
1842 domain: document.domain,
1843 port: location.port ? ':' + location.port : ''
1844 }));
1845 },
1846
1847 getHeader: function(name) {
1848 try {
1849 return this.transport.getResponseHeader(name) || null;
1850 } catch (e) { return null; }
1851 },
1852
1853 evalResponse: function() {
1854 try {
1855 return eval((this.transport.responseText || '').unfilterJSON());
1856 } catch (e) {
1857 this.dispatchException(e);
1858 }
1859 },
1860
1861 dispatchException: function(exception) {
1862 (this.options.onException || Prototype.emptyFunction)(this, exception);
1863 Ajax.Responders.dispatch('onException', this, exception);
1864 }
1865 });
1866
1867 Ajax.Request.Events =
1868 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1869
1870
1871
1872
1873
1874
1875
1876
1877 Ajax.Response = Class.create({
1878 initialize: function(request){
1879 this.request = request;
1880 var transport = this.transport = request.transport,
1881 readyState = this.readyState = transport.readyState;
1882
1883 if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1884 this.status = this.getStatus();
1885 this.statusText = this.getStatusText();
1886 this.responseText = String.interpret(transport.responseText);
1887 this.headerJSON = this._getHeaderJSON();
1888 }
1889
1890 if (readyState == 4) {
1891 var xml = transport.responseXML;
1892 this.responseXML = Object.isUndefined(xml) ? null : xml;
1893 this.responseJSON = this._getResponseJSON();
1894 }
1895 },
1896
1897 status: 0,
1898
1899 statusText: '',
1900
1901 getStatus: Ajax.Request.prototype.getStatus,
1902
1903 getStatusText: function() {
1904 try {
1905 return this.transport.statusText || '';
1906 } catch (e) { return '' }
1907 },
1908
1909 getHeader: Ajax.Request.prototype.getHeader,
1910
1911 getAllHeaders: function() {
1912 try {
1913 return this.getAllResponseHeaders();
1914 } catch (e) { return null }
1915 },
1916
1917 getResponseHeader: function(name) {
1918 return this.transport.getResponseHeader(name);
1919 },
1920
1921 getAllResponseHeaders: function() {
1922 return this.transport.getAllResponseHeaders();
1923 },
1924
1925 _getHeaderJSON: function() {
1926 var json = this.getHeader('X-JSON');
1927 if (!json) return null;
1928
1929 try {
1930 json = decodeURIComponent(escape(json));
1931 } catch(e) {
1932 }
1933
1934 try {
1935 return json.evalJSON(this.request.options.sanitizeJSON ||
1936 !this.request.isSameOrigin());
1937 } catch (e) {
1938 this.request.dispatchException(e);
1939 }
1940 },
1941
1942 _getResponseJSON: function() {
1943 var options = this.request.options;
1944 if (!options.evalJSON || (options.evalJSON != 'force' &&
1945 !(this.getHeader('Content-type') || '').include('application/json')) ||
1946 this.responseText.blank())
1947 return null;
1948 try {
1949 return this.responseText.evalJSON(options.sanitizeJSON ||
1950 !this.request.isSameOrigin());
1951 } catch (e) {
1952 this.request.dispatchException(e);
1953 }
1954 }
1955 });
1956
1957 Ajax.Updater = Class.create(Ajax.Request, {
1958 initialize: function($super, container, url, options) {
1959 this.container = {
1960 success: (container.success || container),
1961 failure: (container.failure || (container.success ? null : container))
1962 };
1963
1964 options = Object.clone(options);
1965 var onComplete = options.onComplete;
1966 options.onComplete = (function(response, json) {
1967 this.updateContent(response.responseText);
1968 if (Object.isFunction(onComplete)) onComplete(response, json);
1969 }).bind(this);
1970
1971 $super(url, options);
1972 },
1973
1974 updateContent: function(responseText) {
1975 var receiver = this.container[this.success() ? 'success' : 'failure'],
1976 options = this.options;
1977
1978 if (!options.evalScripts) responseText = responseText.stripScripts();
1979
1980 if (receiver = $(receiver)) {
1981 if (options.insertion) {
1982 if (Object.isString(options.insertion)) {
1983 var insertion = { }; insertion[options.insertion] = responseText;
1984 receiver.insert(insertion);
1985 }
1986 else options.insertion(receiver, responseText);
1987 }
1988 else receiver.update(responseText);
1989 }
1990 }
1991 });
1992
1993 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1994 initialize: function($super, container, url, options) {
1995 $super(options);
1996 this.onComplete = this.options.onComplete;
1997
1998 this.frequency = (this.options.frequency || 2);
1999 this.decay = (this.options.decay || 1);
2000
2001 this.updater = { };
2002 this.container = container;
2003 this.url = url;
2004
2005 this.start();
2006 },
2007
2008 start: function() {
2009 this.options.onComplete = this.updateComplete.bind(this);
2010 this.onTimerEvent();
2011 },
2012
2013 stop: function() {
2014 this.updater.options.onComplete = undefined;
2015 clearTimeout(this.timer);
2016 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
2017 },
2018
2019 updateComplete: function(response) {
2020 if (this.options.decay) {
2021 this.decay = (response.responseText == this.lastText ?
2022 this.decay * this.options.decay : 1);
2023
2024 this.lastText = response.responseText;
2025 }
2026 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
2027 },
2028
2029 onTimerEvent: function() {
2030 this.updater = new Ajax.Updater(this.container, this.url, this.options);
2031 }
2032 });
2033
2034 (function(GLOBAL) {
2035
2036 var UNDEFINED;
2037 var SLICE = Array.prototype.slice;
2038
2039 var DIV = document.createElement('div');
2040
2041
2042 function $(element) {
2043 if (arguments.length > 1) {
2044 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
2045 elements.push($(arguments[i]));
2046 return elements;
2047 }
2048
2049 if (Object.isString(element))
2050 element = document.getElementById(element);
2051 return Element.extend(element);
2052 }
2053
2054 GLOBAL.$ = $;
2055
2056
2057 if (!GLOBAL.Node) GLOBAL.Node = {};
2058
2059 if (!GLOBAL.Node.ELEMENT_NODE) {
2060 Object.extend(GLOBAL.Node, {
2061 ELEMENT_NODE: 1,
2062 ATTRIBUTE_NODE: 2,
2063 TEXT_NODE: 3,
2064 CDATA_SECTION_NODE: 4,
2065 ENTITY_REFERENCE_NODE: 5,
2066 ENTITY_NODE: 6,
2067 PROCESSING_INSTRUCTION_NODE: 7,
2068 COMMENT_NODE: 8,
2069 DOCUMENT_NODE: 9,
2070 DOCUMENT_TYPE_NODE: 10,
2071 DOCUMENT_FRAGMENT_NODE: 11,
2072 NOTATION_NODE: 12
2073 });
2074 }
2075
2076 var ELEMENT_CACHE = {};
2077
2078 function shouldUseCreationCache(tagName, attributes) {
2079 if (tagName === 'select') return false;
2080 if ('type' in attributes) return false;
2081 return true;
2082 }
2083
2084 var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
2085 try {
2086 var el = document.createElement('<input name="x">');
2087 return el.tagName.toLowerCase() === 'input' && el.name === 'x';
2088 }
2089 catch(err) {
2090 return false;
2091 }
2092 })();
2093
2094
2095 var oldElement = GLOBAL.Element;
2096 function Element(tagName, attributes) {
2097 attributes = attributes || {};
2098 tagName = tagName.toLowerCase();
2099
2100 if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
2101 tagName = '<' + tagName + ' name="' + attributes.name + '">';
2102 delete attributes.name;
2103 return Element.writeAttribute(document.createElement(tagName), attributes);
2104 }
2105
2106 if (!ELEMENT_CACHE[tagName])
2107 ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));
2108
2109 var node = shouldUseCreationCache(tagName, attributes) ?
2110 ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);
2111
2112 return Element.writeAttribute(node, attributes);
2113 }
2114
2115 GLOBAL.Element = Element;
2116
2117 Object.extend(GLOBAL.Element, oldElement || {});
2118 if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;
2119
2120 Element.Methods = { ByTag: {}, Simulated: {} };
2121
2122 var methods = {};
2123
2124 var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };
2125 function inspect(element) {
2126 element = $(element);
2127 var result = '<' + element.tagName.toLowerCase();
2128
2129 var attribute, value;
2130 for (var property in INSPECT_ATTRIBUTES) {
2131 attribute = INSPECT_ATTRIBUTES[property];
2132 value = (element[property] || '').toString();
2133 if (value) result += ' ' + attribute + '=' + value.inspect(true);
2134 }
2135
2136 return result + '>';
2137 }
2138
2139 methods.inspect = inspect;
2140
2141
2142 function visible(element) {
2143 return $(element).getStyle('display') !== 'none';
2144 }
2145
2146 function toggle(element, bool) {
2147 element = $(element);
2148 if (typeof bool !== 'boolean')
2149 bool = !Element.visible(element);
2150 Element[bool ? 'show' : 'hide'](element);
2151
2152 return element;
2153 }
2154
2155 function hide(element) {
2156 element = $(element);
2157 element.style.display = 'none';
2158 return element;
2159 }
2160
2161 function show(element) {
2162 element = $(element);
2163 element.style.display = '';
2164 return element;
2165 }
2166
2167
2168 Object.extend(methods, {
2169 visible: visible,
2170 toggle: toggle,
2171 hide: hide,
2172 show: show
2173 });
2174
2175
2176 function remove(element) {
2177 element = $(element);
2178 element.parentNode.removeChild(element);
2179 return element;
2180 }
2181
2182 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
2183 var el = document.createElement("select"),
2184 isBuggy = true;
2185 el.innerHTML = "<option value=\"test\">test</option>";
2186 if (el.options && el.options[0]) {
2187 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
2188 }
2189 el = null;
2190 return isBuggy;
2191 })();
2192
2193 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
2194 try {
2195 var el = document.createElement("table");
2196 if (el && el.tBodies) {
2197 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
2198 var isBuggy = typeof el.tBodies[0] == "undefined";
2199 el = null;
2200 return isBuggy;
2201 }
2202 } catch (e) {
2203 return true;
2204 }
2205 })();
2206
2207 var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
2208 try {
2209 var el = document.createElement('div');
2210 el.innerHTML = "<link />";
2211 var isBuggy = (el.childNodes.length === 0);
2212 el = null;
2213 return isBuggy;
2214 } catch(e) {
2215 return true;
2216 }
2217 })();
2218
2219 var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
2220 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
2221
2222 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
2223 var s = document.createElement("script"),
2224 isBuggy = false;
2225 try {
2226 s.appendChild(document.createTextNode(""));
2227 isBuggy = !s.firstChild ||
2228 s.firstChild && s.firstChild.nodeType !== 3;
2229 } catch (e) {
2230 isBuggy = true;
2231 }
2232 s = null;
2233 return isBuggy;
2234 })();
2235
2236 function update(element, content) {
2237 element = $(element);
2238
2239 var descendants = element.getElementsByTagName('*'),
2240 i = descendants.length;
2241 while (i--) purgeElement(descendants[i]);
2242
2243 if (content && content.toElement)
2244 content = content.toElement();
2245
2246 if (Object.isElement(content))
2247 return element.update().insert(content);
2248
2249
2250 content = Object.toHTML(content);
2251 var tagName = element.tagName.toUpperCase();
2252
2253 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
2254 element.text = content;
2255 return element;
2256 }
2257
2258 if (ANY_INNERHTML_BUGGY) {
2259 if (tagName in INSERTION_TRANSLATIONS.tags) {
2260 while (element.firstChild)
2261 element.removeChild(element.firstChild);
2262
2263 var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2264 for (var i = 0, node; node = nodes[i]; i++)
2265 element.appendChild(node);
2266
2267 } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
2268 while (element.firstChild)
2269 element.removeChild(element.firstChild);
2270
2271 var nodes = getContentFromAnonymousElement(tagName,
2272 content.stripScripts(), true);
2273
2274 for (var i = 0, node; node = nodes[i]; i++)
2275 element.appendChild(node);
2276 } else {
2277 element.innerHTML = content.stripScripts();
2278 }
2279 } else {
2280 element.innerHTML = content.stripScripts();
2281 }
2282
2283 content.evalScripts.bind(content).defer();
2284 return element;
2285 }
2286
2287 function replace(element, content) {
2288 element = $(element);
2289
2290 if (content && content.toElement) {
2291 content = content.toElement();
2292 } else if (!Object.isElement(content)) {
2293 content = Object.toHTML(content);
2294 var range = element.ownerDocument.createRange();
2295 range.selectNode(element);
2296 content.evalScripts.bind(content).defer();
2297 content = range.createContextualFragment(content.stripScripts());
2298 }
2299
2300 element.parentNode.replaceChild(content, element);
2301 return element;
2302 }
2303
2304 var INSERTION_TRANSLATIONS = {
2305 before: function(element, node) {
2306 element.parentNode.insertBefore(node, element);
2307 },
2308 top: function(element, node) {
2309 element.insertBefore(node, element.firstChild);
2310 },
2311 bottom: function(element, node) {
2312 element.appendChild(node);
2313 },
2314 after: function(element, node) {
2315 element.parentNode.insertBefore(node, element.nextSibling);
2316 },
2317
2318 tags: {
2319 TABLE: ['<table>', '</table>', 1],
2320 TBODY: ['<table><tbody>', '</tbody></table>', 2],
2321 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2322 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2323 SELECT: ['<select>', '</select>', 1]
2324 }
2325 };
2326
2327 var tags = INSERTION_TRANSLATIONS.tags;
2328
2329 Object.extend(tags, {
2330 THEAD: tags.TBODY,
2331 TFOOT: tags.TBODY,
2332 TH: tags.TD
2333 });
2334
2335 function replace_IE(element, content) {
2336 element = $(element);
2337 if (content && content.toElement)
2338 content = content.toElement();
2339 if (Object.isElement(content)) {
2340 element.parentNode.replaceChild(content, element);
2341 return element;
2342 }
2343
2344 content = Object.toHTML(content);
2345 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2346
2347 if (tagName in INSERTION_TRANSLATIONS.tags) {
2348 var nextSibling = Element.next(element);
2349 var fragments = getContentFromAnonymousElement(
2350 tagName, content.stripScripts());
2351
2352 parent.removeChild(element);
2353
2354 var iterator;
2355 if (nextSibling)
2356 iterator = function(node) { parent.insertBefore(node, nextSibling) };
2357 else
2358 iterator = function(node) { parent.appendChild(node); }
2359
2360 fragments.each(iterator);
2361 } else {
2362 element.outerHTML = content.stripScripts();
2363 }
2364
2365 content.evalScripts.bind(content).defer();
2366 return element;
2367 }
2368
2369 if ('outerHTML' in document.documentElement)
2370 replace = replace_IE;
2371
2372 function isContent(content) {
2373 if (Object.isUndefined(content) || content === null) return false;
2374
2375 if (Object.isString(content) || Object.isNumber(content)) return true;
2376 if (Object.isElement(content)) return true;
2377 if (content.toElement || content.toHTML) return true;
2378
2379 return false;
2380 }
2381
2382 function insertContentAt(element, content, position) {
2383 position = position.toLowerCase();
2384 var method = INSERTION_TRANSLATIONS[position];
2385
2386 if (content && content.toElement) content = content.toElement();
2387 if (Object.isElement(content)) {
2388 method(element, content);
2389 return element;
2390 }
2391
2392 content = Object.toHTML(content);
2393 var tagName = ((position === 'before' || position === 'after') ?
2394 element.parentNode : element).tagName.toUpperCase();
2395
2396 var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2397
2398 if (position === 'top' || position === 'after') childNodes.reverse();
2399
2400 for (var i = 0, node; node = childNodes[i]; i++)
2401 method(element, node);
2402
2403 content.evalScripts.bind(content).defer();
2404 }
2405
2406 function insert(element, insertions) {
2407 element = $(element);
2408
2409 if (isContent(insertions))
2410 insertions = { bottom: insertions };
2411
2412 for (var position in insertions)
2413 insertContentAt(element, insertions[position], position);
2414
2415 return element;
2416 }
2417
2418 function wrap(element, wrapper, attributes) {
2419 element = $(element);
2420
2421 if (Object.isElement(wrapper)) {
2422 $(wrapper).writeAttribute(attributes || {});
2423 } else if (Object.isString(wrapper)) {
2424 wrapper = new Element(wrapper, attributes);
2425 } else {
2426 wrapper = new Element('div', wrapper);
2427 }
2428
2429 if (element.parentNode)
2430 element.parentNode.replaceChild(wrapper, element);
2431
2432 wrapper.appendChild(element);
2433
2434 return wrapper;
2435 }
2436
2437 function cleanWhitespace(element) {
2438 element = $(element);
2439 var node = element.firstChild;
2440
2441 while (node) {
2442 var nextNode = node.nextSibling;
2443 if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue))
2444 element.removeChild(node);
2445 node = nextNode;
2446 }
2447 return element;
2448 }
2449
2450 function empty(element) {
2451 return $(element).innerHTML.blank();
2452 }
2453
2454 function getContentFromAnonymousElement(tagName, html, force) {
2455 var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;
2456
2457 var workaround = !!t;
2458 if (!workaround && force) {
2459 workaround = true;
2460 t = ['', '', 0];
2461 }
2462
2463 if (workaround) {
2464 div.innerHTML = '&#160;' + t[0] + html + t[1];
2465 div.removeChild(div.firstChild);
2466 for (var i = t[2]; i--; )
2467 div = div.firstChild;
2468 } else {
2469 div.innerHTML = html;
2470 }
2471
2472 return $A(div.childNodes);
2473 }
2474
2475 function clone(element, deep) {
2476 if (!(element = $(element))) return;
2477 var clone = element.cloneNode(deep);
2478 if (!HAS_UNIQUE_ID_PROPERTY) {
2479 clone._prototypeUID = UNDEFINED;
2480 if (deep) {
2481 var descendants = Element.select(clone, '*'),
2482 i = descendants.length;
2483 while (i--)
2484 descendants[i]._prototypeUID = UNDEFINED;
2485 }
2486 }
2487 return Element.extend(clone);
2488 }
2489
2490 function purgeElement(element) {
2491 var uid = getUniqueElementID(element);
2492 if (uid) {
2493 Element.stopObserving(element);
2494 if (!HAS_UNIQUE_ID_PROPERTY)
2495 element._prototypeUID = UNDEFINED;
2496 delete Element.Storage[uid];
2497 }
2498 }
2499
2500 function purgeCollection(elements) {
2501 var i = elements.length;
2502 while (i--)
2503 purgeElement(elements[i]);
2504 }
2505
2506 function purgeCollection_IE(elements) {
2507 var i = elements.length, element, uid;
2508 while (i--) {
2509 element = elements[i];
2510 uid = getUniqueElementID(element);
2511 delete Element.Storage[uid];
2512 delete Event.cache[uid];
2513 }
2514 }
2515
2516 if (HAS_UNIQUE_ID_PROPERTY) {
2517 purgeCollection = purgeCollection_IE;
2518 }
2519
2520
2521 function purge(element) {
2522 if (!(element = $(element))) return;
2523 purgeElement(element);
2524
2525 var descendants = element.getElementsByTagName('*'),
2526 i = descendants.length;
2527
2528 while (i--) purgeElement(descendants[i]);
2529
2530 return null;
2531 }
2532
2533 Object.extend(methods, {
2534 remove: remove,
2535 update: update,
2536 replace: replace,
2537 insert: insert,
2538 wrap: wrap,
2539 cleanWhitespace: cleanWhitespace,
2540 empty: empty,
2541 clone: clone,
2542 purge: purge
2543 });
2544
2545
2546
2547 function recursivelyCollect(element, property, maximumLength) {
2548 element = $(element);
2549 maximumLength = maximumLength || -1;
2550 var elements = [];
2551
2552 while (element = element[property]) {
2553 if (element.nodeType === Node.ELEMENT_NODE)
2554 elements.push(Element.extend(element));
2555
2556 if (elements.length === maximumLength) break;
2557 }
2558
2559 return elements;
2560 }
2561
2562
2563 function ancestors(element) {
2564 return recursivelyCollect(element, 'parentNode');
2565 }
2566
2567 function descendants(element) {
2568 return Element.select(element, '*');
2569 }
2570
2571 function firstDescendant(element) {
2572 element = $(element).firstChild;
2573 while (element && element.nodeType !== Node.ELEMENT_NODE)
2574 element = element.nextSibling;
2575
2576 return $(element);
2577 }
2578
2579 function immediateDescendants(element) {
2580 var results = [], child = $(element).firstChild;
2581
2582 while (child) {
2583 if (child.nodeType === Node.ELEMENT_NODE)
2584 results.push(Element.extend(child));
2585
2586 child = child.nextSibling;
2587 }
2588
2589 return results;
2590 }
2591
2592 function previousSiblings(element) {
2593 return recursivelyCollect(element, 'previousSibling');
2594 }
2595
2596 function nextSiblings(element) {
2597 return recursivelyCollect(element, 'nextSibling');
2598 }
2599
2600 function siblings(element) {
2601 element = $(element);
2602 var previous = previousSiblings(element),
2603 next = nextSiblings(element);
2604 return previous.reverse().concat(next);
2605 }
2606
2607 function match(element, selector) {
2608 element = $(element);
2609
2610 if (Object.isString(selector))
2611 return Prototype.Selector.match(element, selector);
2612
2613 return selector.match(element);
2614 }
2615
2616
2617 function _recursivelyFind(element, property, expression, index) {
2618 element = $(element), expression = expression || 0, index = index || 0;
2619 if (Object.isNumber(expression)) {
2620 index = expression, expression = null;
2621 }
2622
2623 while (element = element[property]) {
2624 if (element.nodeType !== 1) continue;
2625 if (expression && !Prototype.Selector.match(element, expression))
2626 continue;
2627 if (--index >= 0) continue;
2628
2629 return Element.extend(element);
2630 }
2631 }
2632
2633
2634 function up(element, expression, index) {
2635 element = $(element);
2636
2637 if (arguments.length === 1) return $(element.parentNode);
2638 return _recursivelyFind(element, 'parentNode', expression, index);
2639 }
2640
2641 function down(element, expression, index) {
2642 if (arguments.length === 1) return firstDescendant(element);
2643 element = $(element), expression = expression || 0, index = index || 0;
2644
2645 if (Object.isNumber(expression))
2646 index = expression, expression = '*';
2647
2648 var node = Prototype.Selector.select(expression, element)[index];
2649 return Element.extend(node);
2650 }
2651
2652 function previous(element, expression, index) {
2653 return _recursivelyFind(element, 'previousSibling', expression, index);
2654 }
2655
2656 function next(element, expression, index) {
2657 return _recursivelyFind(element, 'nextSibling', expression, index);
2658 }
2659
2660 function select(element) {
2661 element = $(element);
2662 var expressions = SLICE.call(arguments, 1).join(', ');
2663 return Prototype.Selector.select(expressions, element);
2664 }
2665
2666 function adjacent(element) {
2667 element = $(element);
2668 var expressions = SLICE.call(arguments, 1).join(', ');
2669 var siblings = Element.siblings(element), results = [];
2670 for (var i = 0, sibling; sibling = siblings[i]; i++) {
2671 if (Prototype.Selector.match(sibling, expressions))
2672 results.push(sibling);
2673 }
2674
2675 return results;
2676 }
2677
2678 function descendantOf_DOM(element, ancestor) {
2679 element = $(element), ancestor = $(ancestor);
2680 if (!element || !ancestor) return false;
2681 while (element = element.parentNode)
2682 if (element === ancestor) return true;
2683 return false;
2684 }
2685
2686 function descendantOf_contains(element, ancestor) {
2687 element = $(element), ancestor = $(ancestor);
2688 if (!element || !ancestor) return false;
2689 if (!ancestor.contains) return descendantOf_DOM(element, ancestor);
2690 return ancestor.contains(element) && ancestor !== element;
2691 }
2692
2693 function descendantOf_compareDocumentPosition(element, ancestor) {
2694 element = $(element), ancestor = $(ancestor);
2695 if (!element || !ancestor) return false;
2696 return (element.compareDocumentPosition(ancestor) & 8) === 8;
2697 }
2698
2699 var descendantOf;
2700 if (DIV.compareDocumentPosition) {
2701 descendantOf = descendantOf_compareDocumentPosition;
2702 } else if (DIV.contains) {
2703 descendantOf = descendantOf_contains;
2704 } else {
2705 descendantOf = descendantOf_DOM;
2706 }
2707
2708
2709 Object.extend(methods, {
2710 recursivelyCollect: recursivelyCollect,
2711 ancestors: ancestors,
2712 descendants: descendants,
2713 firstDescendant: firstDescendant,
2714 immediateDescendants: immediateDescendants,
2715 previousSiblings: previousSiblings,
2716 nextSiblings: nextSiblings,
2717 siblings: siblings,
2718 match: match,
2719 up: up,
2720 down: down,
2721 previous: previous,
2722 next: next,
2723 select: select,
2724 adjacent: adjacent,
2725 descendantOf: descendantOf,
2726
2727 getElementsBySelector: select,
2728
2729 childElements: immediateDescendants
2730 });
2731
2732
2733 var idCounter = 1;
2734 function identify(element) {
2735 element = $(element);
2736 var id = Element.readAttribute(element, 'id');
2737 if (id) return id;
2738
2739 do { id = 'anonymous_element_' + idCounter++ } while ($(id));
2740
2741 Element.writeAttribute(element, 'id', id);
2742 return id;
2743 }
2744
2745
2746 function readAttribute(element, name) {
2747 return $(element).getAttribute(name);
2748 }
2749
2750 function readAttribute_IE(element, name) {
2751 element = $(element);
2752
2753 var table = ATTRIBUTE_TRANSLATIONS.read;
2754 if (table.values[name])
2755 return table.values[name](element, name);
2756
2757 if (table.names[name]) name = table.names[name];
2758
2759 if (name.include(':')) {
2760 if (!element.attributes || !element.attributes[name]) return null;
2761 return element.attributes[name].value;
2762 }
2763
2764 return element.getAttribute(name);
2765 }
2766
2767 function readAttribute_Opera(element, name) {
2768 if (name === 'title') return element.title;
2769 return element.getAttribute(name);
2770 }
2771
2772 var PROBLEMATIC_ATTRIBUTE_READING = (function() {
2773 DIV.setAttribute('onclick', []);
2774 var value = DIV.getAttribute('onclick');
2775 var isFunction = Object.isArray(value);
2776 DIV.removeAttribute('onclick');
2777 return isFunction;
2778 })();
2779
2780 if (PROBLEMATIC_ATTRIBUTE_READING) {
2781 readAttribute = readAttribute_IE;
2782 } else if (Prototype.Browser.Opera) {
2783 readAttribute = readAttribute_Opera;
2784 }
2785
2786
2787 function writeAttribute(element, name, value) {
2788 element = $(element);
2789 var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;
2790
2791 if (typeof name === 'object') {
2792 attributes = name;
2793 } else {
2794 attributes[name] = Object.isUndefined(value) ? true : value;
2795 }
2796
2797 for (var attr in attributes) {
2798 name = table.names[attr] || attr;
2799 value = attributes[attr];
2800 if (table.values[attr]) {
2801 value = table.values[attr](element, value);
2802 if (Object.isUndefined(value)) continue;
2803 }
2804 if (value === false || value === null)
2805 element.removeAttribute(name);
2806 else if (value === true)
2807 element.setAttribute(name, name);
2808 else element.setAttribute(name, value);
2809 }
2810
2811 return element;
2812 }
2813
2814 var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () {
2815 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) {
2816 return false;
2817 }
2818 var checkbox = document.createElement('<input type="checkbox">');
2819 checkbox.checked = true;
2820 var node = checkbox.getAttributeNode('checked');
2821 return !node || !node.specified;
2822 })();
2823
2824 function hasAttribute(element, attribute) {
2825 attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;
2826 var node = $(element).getAttributeNode(attribute);
2827 return !!(node && node.specified);
2828 }
2829
2830 function hasAttribute_IE(element, attribute) {
2831 if (attribute === 'checked') {
2832 return element.checked;
2833 }
2834 return hasAttribute(element, attribute);
2835 }
2836
2837 GLOBAL.Element.Methods.Simulated.hasAttribute =
2838 PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ?
2839 hasAttribute_IE : hasAttribute;
2840
2841 function classNames(element) {
2842 return new Element.ClassNames(element);
2843 }
2844
2845 var regExpCache = {};
2846 function getRegExpForClassName(className) {
2847 if (regExpCache[className]) return regExpCache[className];
2848
2849 var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
2850 regExpCache[className] = re;
2851 return re;
2852 }
2853
2854 function hasClassName(element, className) {
2855 if (!(element = $(element))) return;
2856
2857 var elementClassName = element.className;
2858
2859 if (elementClassName.length === 0) return false;
2860 if (elementClassName === className) return true;
2861
2862 return getRegExpForClassName(className).test(elementClassName);
2863 }
2864
2865 function addClassName(element, className) {
2866 if (!(element = $(element))) return;
2867
2868 if (!hasClassName(element, className))
2869 element.className += (element.className ? ' ' : '') + className;
2870
2871 return element;
2872 }
2873
2874 function removeClassName(element, className) {
2875 if (!(element = $(element))) return;
2876
2877 element.className = element.className.replace(
2878 getRegExpForClassName(className), ' ').strip();
2879
2880 return element;
2881 }
2882
2883 function toggleClassName(element, className, bool) {
2884 if (!(element = $(element))) return;
2885
2886 if (Object.isUndefined(bool))
2887 bool = !hasClassName(element, className);
2888
2889 var method = Element[bool ? 'addClassName' : 'removeClassName'];
2890 return method(element, className);
2891 }
2892
2893 var ATTRIBUTE_TRANSLATIONS = {};
2894
2895 var classProp = 'className', forProp = 'for';
2896
2897 DIV.setAttribute(classProp, 'x');
2898 if (DIV.className !== 'x') {
2899 DIV.setAttribute('class', 'x');
2900 if (DIV.className === 'x')
2901 classProp = 'class';
2902 }
2903
2904 var LABEL = document.createElement('label');
2905 LABEL.setAttribute(forProp, 'x');
2906 if (LABEL.htmlFor !== 'x') {
2907 LABEL.setAttribute('htmlFor', 'x');
2908 if (LABEL.htmlFor === 'x')
2909 forProp = 'htmlFor';
2910 }
2911 LABEL = null;
2912
2913 function _getAttr(element, attribute) {
2914 return element.getAttribute(attribute);
2915 }
2916
2917 function _getAttr2(element, attribute) {
2918 return element.getAttribute(attribute, 2);
2919 }
2920
2921 function _getAttrNode(element, attribute) {
2922 var node = element.getAttributeNode(attribute);
2923 return node ? node.value : '';
2924 }
2925
2926 function _getFlag(element, attribute) {
2927 return $(element).hasAttribute(attribute) ? attribute : null;
2928 }
2929
2930 DIV.onclick = Prototype.emptyFunction;
2931 var onclickValue = DIV.getAttribute('onclick');
2932
2933 var _getEv;
2934
2935 if (String(onclickValue).indexOf('{') > -1) {
2936 _getEv = function(element, attribute) {
2937 var value = element.getAttribute(attribute);
2938 if (!value) return null;
2939 value = value.toString();
2940 value = value.split('{')[1];
2941 value = value.split('}')[0];
2942 return value.strip();
2943 };
2944 }
2945 else if (onclickValue === '') {
2946 _getEv = function(element, attribute) {
2947 var value = element.getAttribute(attribute);
2948 if (!value) return null;
2949 return value.strip();
2950 };
2951 }
2952
2953 ATTRIBUTE_TRANSLATIONS.read = {
2954 names: {
2955 'class': classProp,
2956 'className': classProp,
2957 'for': forProp,
2958 'htmlFor': forProp
2959 },
2960
2961 values: {
2962 style: function(element) {
2963 return element.style.cssText.toLowerCase();
2964 },
2965 title: function(element) {
2966 return element.title;
2967 }
2968 }
2969 };
2970
2971 ATTRIBUTE_TRANSLATIONS.write = {
2972 names: {
2973 className: 'class',
2974 htmlFor: 'for',
2975 cellpadding: 'cellPadding',
2976 cellspacing: 'cellSpacing'
2977 },
2978
2979 values: {
2980 checked: function(element, value) {
2981 value = !!value;
2982 element.checked = value;
2983 return value ? 'checked' : null;
2984 },
2985
2986 style: function(element, value) {
2987 element.style.cssText = value ? value : '';
2988 }
2989 }
2990 };
2991
2992 ATTRIBUTE_TRANSLATIONS.has = { names: {} };
2993
2994 Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,
2995 ATTRIBUTE_TRANSLATIONS.read.names);
2996
2997 var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +
2998 'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');
2999
3000 for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {
3001 ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;
3002 ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()] = attr;
3003 }
3004
3005 Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {
3006 href: _getAttr2,
3007 src: _getAttr2,
3008 type: _getAttr,
3009 action: _getAttrNode,
3010 disabled: _getFlag,
3011 checked: _getFlag,
3012 readonly: _getFlag,
3013 multiple: _getFlag,
3014 onload: _getEv,
3015 onunload: _getEv,
3016 onclick: _getEv,
3017 ondblclick: _getEv,
3018 onmousedown: _getEv,
3019 onmouseup: _getEv,
3020 onmouseover: _getEv,
3021 onmousemove: _getEv,
3022 onmouseout: _getEv,
3023 onfocus: _getEv,
3024 onblur: _getEv,
3025 onkeypress: _getEv,
3026 onkeydown: _getEv,
3027 onkeyup: _getEv,
3028 onsubmit: _getEv,
3029 onreset: _getEv,
3030 onselect: _getEv,
3031 onchange: _getEv
3032 });
3033
3034
3035 Object.extend(methods, {
3036 identify: identify,
3037 readAttribute: readAttribute,
3038 writeAttribute: writeAttribute,
3039 classNames: classNames,
3040 hasClassName: hasClassName,
3041 addClassName: addClassName,
3042 removeClassName: removeClassName,
3043 toggleClassName: toggleClassName
3044 });
3045
3046
3047 function normalizeStyleName(style) {
3048 if (style === 'float' || style === 'styleFloat')
3049 return 'cssFloat';
3050 return style.camelize();
3051 }
3052
3053 function normalizeStyleName_IE(style) {
3054 if (style === 'float' || style === 'cssFloat')
3055 return 'styleFloat';
3056 return style.camelize();
3057 }
3058
3059 function setStyle(element, styles) {
3060 element = $(element);
3061 var elementStyle = element.style, match;
3062
3063 if (Object.isString(styles)) {
3064 elementStyle.cssText += ';' + styles;
3065 if (styles.include('opacity')) {
3066 var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1];
3067 Element.setOpacity(element, opacity);
3068 }
3069 return element;
3070 }
3071
3072 for (var property in styles) {
3073 if (property === 'opacity') {
3074 Element.setOpacity(element, styles[property]);
3075 } else {
3076 var value = styles[property];
3077 if (property === 'float' || property === 'cssFloat') {
3078 property = Object.isUndefined(elementStyle.styleFloat) ?
3079 'cssFloat' : 'styleFloat';
3080 }
3081 elementStyle[property] = value;
3082 }
3083 }
3084
3085 return element;
3086 }
3087
3088
3089 function getStyle(element, style) {
3090 element = $(element);
3091 style = normalizeStyleName(style);
3092
3093 var value = element.style[style];
3094 if (!value || value === 'auto') {
3095 var css = document.defaultView.getComputedStyle(element, null);
3096 value = css ? css[style] : null;
3097 }
3098
3099 if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3100 return value === 'auto' ? null : value;
3101 }
3102
3103 function getStyle_Opera(element, style) {
3104 switch (style) {
3105 case 'height': case 'width':
3106 if (!Element.visible(element)) return null;
3107
3108 var dim = parseInt(getStyle(element, style), 10);
3109
3110 if (dim !== element['offset' + style.capitalize()])
3111 return dim + 'px';
3112
3113 return Element.measure(element, style);
3114
3115 default: return getStyle(element, style);
3116 }
3117 }
3118
3119 function getStyle_IE(element, style) {
3120 element = $(element);
3121 style = normalizeStyleName_IE(style);
3122
3123 var value = element.style[style];
3124 if (!value && element.currentStyle) {
3125 value = element.currentStyle[style];
3126 }
3127
3128 if (style === 'opacity') {
3129 if (!STANDARD_CSS_OPACITY_SUPPORTED)
3130 return getOpacity_IE(element);
3131 else return value ? parseFloat(value) : 1.0;
3132 }
3133
3134 if (value === 'auto') {
3135 if ((style === 'width' || style === 'height') && Element.visible(element))
3136 return Element.measure(element, style) + 'px';
3137 return null;
3138 }
3139
3140 return value;
3141 }
3142
3143 function stripAlphaFromFilter_IE(filter) {
3144 return (filter || '').replace(/alpha\([^\)]*\)/gi, '');
3145 }
3146
3147 function hasLayout_IE(element) {
3148 if (!element.currentStyle || !element.currentStyle.hasLayout)
3149 element.style.zoom = 1;
3150 return element;
3151 }
3152
3153 var STANDARD_CSS_OPACITY_SUPPORTED = (function() {
3154 DIV.style.cssText = "opacity:.55";
3155 return /^0.55/.test(DIV.style.opacity);
3156 })();
3157
3158 function setOpacity(element, value) {
3159 element = $(element);
3160 if (value == 1 || value === '') value = '';
3161 else if (value < 0.00001) value = 0;
3162 element.style.opacity = value;
3163 return element;
3164 }
3165
3166 function setOpacity_IE(element, value) {
3167 if (STANDARD_CSS_OPACITY_SUPPORTED)
3168 return setOpacity(element, value);
3169
3170 element = hasLayout_IE($(element));
3171 var filter = Element.getStyle(element, 'filter'),
3172 style = element.style;
3173
3174 if (value == 1 || value === '') {
3175 filter = stripAlphaFromFilter_IE(filter);
3176 if (filter) style.filter = filter;
3177 else style.removeAttribute('filter');
3178 return element;
3179 }
3180
3181 if (value < 0.00001) value = 0;
3182
3183 style.filter = stripAlphaFromFilter_IE(filter) +
3184 ' alpha(opacity=' + (value * 100) + ')';
3185
3186 return element;
3187 }
3188
3189
3190 function getOpacity(element) {
3191 return Element.getStyle(element, 'opacity');
3192 }
3193
3194 function getOpacity_IE(element) {
3195 if (STANDARD_CSS_OPACITY_SUPPORTED)
3196 return getOpacity(element);
3197
3198 var filter = Element.getStyle(element, 'filter');
3199 if (filter.length === 0) return 1.0;
3200 var match = (filter || '').match(/alpha\(opacity=(.*)\)/i);
3201 if (match && match[1]) return parseFloat(match[1]) / 100;
3202 return 1.0;
3203 }
3204
3205
3206 Object.extend(methods, {
3207 setStyle: setStyle,
3208 getStyle: getStyle,
3209 setOpacity: setOpacity,
3210 getOpacity: getOpacity
3211 });
3212
3213 if ('styleFloat' in DIV.style) {
3214 methods.getStyle = getStyle_IE;
3215 methods.setOpacity = setOpacity_IE;
3216 methods.getOpacity = getOpacity_IE;
3217 }
3218
3219 var UID = 0;
3220
3221 GLOBAL.Element.Storage = { UID: 1 };
3222
3223 function getUniqueElementID(element) {
3224 if (element === window) return 0;
3225
3226 if (typeof element._prototypeUID === 'undefined')
3227 element._prototypeUID = Element.Storage.UID++;
3228 return element._prototypeUID;
3229 }
3230
3231 function getUniqueElementID_IE(element) {
3232 if (element === window) return 0;
3233 if (element == document) return 1;
3234 return element.uniqueID;
3235 }
3236
3237 var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);
3238 if (HAS_UNIQUE_ID_PROPERTY)
3239 getUniqueElementID = getUniqueElementID_IE;
3240
3241 function getStorage(element) {
3242 if (!(element = $(element))) return;
3243
3244 var uid = getUniqueElementID(element);
3245
3246 if (!Element.Storage[uid])
3247 Element.Storage[uid] = $H();
3248
3249 return Element.Storage[uid];
3250 }
3251
3252 function store(element, key, value) {
3253 if (!(element = $(element))) return;
3254 var storage = getStorage(element);
3255 if (arguments.length === 2) {
3256 storage.update(key);
3257 } else {
3258 storage.set(key, value);
3259 }
3260 return element;
3261 }
3262
3263 function retrieve(element, key, defaultValue) {
3264 if (!(element = $(element))) return;
3265 var storage = getStorage(element), value = storage.get(key);
3266
3267 if (Object.isUndefined(value)) {
3268 storage.set(key, defaultValue);
3269 value = defaultValue;
3270 }
3271
3272 return value;
3273 }
3274
3275
3276 Object.extend(methods, {
3277 getStorage: getStorage,
3278 store: store,
3279 retrieve: retrieve
3280 });
3281
3282
3283 var Methods = {}, ByTag = Element.Methods.ByTag,
3284 F = Prototype.BrowserFeatures;
3285
3286 if (!F.ElementExtensions && ('__proto__' in DIV)) {
3287 GLOBAL.HTMLElement = {};
3288 GLOBAL.HTMLElement.prototype = DIV['__proto__'];
3289 F.ElementExtensions = true;
3290 }
3291
3292 function checkElementPrototypeDeficiency(tagName) {
3293 if (typeof window.Element === 'undefined') return false;
3294 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false;
3295 var proto = window.Element.prototype;
3296 if (proto) {
3297 var id = '_' + (Math.random() + '').slice(2),
3298 el = document.createElement(tagName);
3299 proto[id] = 'x';
3300 var isBuggy = (el[id] !== 'x');
3301 delete proto[id];
3302 el = null;
3303 return isBuggy;
3304 }
3305
3306 return false;
3307 }
3308
3309 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =
3310 checkElementPrototypeDeficiency('object');
3311
3312 function extendElementWith(element, methods) {
3313 for (var property in methods) {
3314 var value = methods[property];
3315 if (Object.isFunction(value) && !(property in element))
3316 element[property] = value.methodize();
3317 }
3318 }
3319
3320 var EXTENDED = {};
3321 function elementIsExtended(element) {
3322 var uid = getUniqueElementID(element);
3323 return (uid in EXTENDED);
3324 }
3325
3326 function extend(element) {
3327 if (!element || elementIsExtended(element)) return element;
3328 if (element.nodeType !== Node.ELEMENT_NODE || element == window)
3329 return element;
3330
3331 var methods = Object.clone(Methods),
3332 tagName = element.tagName.toUpperCase();
3333
3334 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
3335
3336 extendElementWith(element, methods);
3337 EXTENDED[getUniqueElementID(element)] = true;
3338 return element;
3339 }
3340
3341 function extend_IE8(element) {
3342 if (!element || elementIsExtended(element)) return element;
3343
3344 var t = element.tagName;
3345 if (t && (/^(?:object|applet|embed)$/i.test(t))) {
3346 extendElementWith(element, Element.Methods);
3347 extendElementWith(element, Element.Methods.Simulated);
3348 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
3349 }
3350
3351 return element;
3352 }
3353
3354 if (F.SpecificElementExtensions) {
3355 extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;
3356 }
3357
3358 function addMethodsToTagName(tagName, methods) {
3359 tagName = tagName.toUpperCase();
3360 if (!ByTag[tagName]) ByTag[tagName] = {};
3361 Object.extend(ByTag[tagName], methods);
3362 }
3363
3364 function mergeMethods(destination, methods, onlyIfAbsent) {
3365 if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;
3366 for (var property in methods) {
3367 var value = methods[property];
3368 if (!Object.isFunction(value)) continue;
3369 if (!onlyIfAbsent || !(property in destination))
3370 destination[property] = value.methodize();
3371 }
3372 }
3373
3374 function findDOMClass(tagName) {
3375 var klass;
3376 var trans = {
3377 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3378 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3379 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3380 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3381 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3382 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3383 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3384 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3385 "FrameSet", "IFRAME": "IFrame"
3386 };
3387 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3388 if (window[klass]) return window[klass];
3389 klass = 'HTML' + tagName + 'Element';
3390 if (window[klass]) return window[klass];
3391 klass = 'HTML' + tagName.capitalize() + 'Element';
3392 if (window[klass]) return window[klass];
3393
3394 var element = document.createElement(tagName),
3395 proto = element['__proto__'] || element.constructor.prototype;
3396
3397 element = null;
3398 return proto;
3399 }
3400
3401 function addMethods(methods) {
3402 if (arguments.length === 0) addFormMethods();
3403
3404 if (arguments.length === 2) {
3405 var tagName = methods;
3406 methods = arguments[1];
3407 }
3408
3409 if (!tagName) {
3410 Object.extend(Element.Methods, methods || {});
3411 } else {
3412 if (Object.isArray(tagName)) {
3413 for (var i = 0, tag; tag = tagName[i]; i++)
3414 addMethodsToTagName(tag, methods);
3415 } else {
3416 addMethodsToTagName(tagName, methods);
3417 }
3418 }
3419
3420 var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
3421 Element.prototype;
3422
3423 if (F.ElementExtensions) {
3424 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
3425 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
3426 }
3427
3428 if (F.SpecificElementExtensions) {
3429 for (var tag in Element.Methods.ByTag) {
3430 var klass = findDOMClass(tag);
3431 if (Object.isUndefined(klass)) continue;
3432 mergeMethods(klass.prototype, ByTag[tag]);
3433 }
3434 }
3435
3436 Object.extend(Element, Element.Methods);
3437 Object.extend(Element, Element.Methods.Simulated);
3438 delete Element.ByTag;
3439 delete Element.Simulated;
3440
3441 Element.extend.refresh();
3442
3443 ELEMENT_CACHE = {};
3444 }
3445
3446 Object.extend(GLOBAL.Element, {
3447 extend: extend,
3448 addMethods: addMethods
3449 });
3450
3451 if (extend === Prototype.K) {
3452 GLOBAL.Element.extend.refresh = Prototype.emptyFunction;
3453 } else {
3454 GLOBAL.Element.extend.refresh = function() {
3455 if (Prototype.BrowserFeatures.ElementExtensions) return;
3456 Object.extend(Methods, Element.Methods);
3457 Object.extend(Methods, Element.Methods.Simulated);
3458
3459 EXTENDED = {};
3460 };
3461 }
3462
3463 function addFormMethods() {
3464 Object.extend(Form, Form.Methods);
3465 Object.extend(Form.Element, Form.Element.Methods);
3466 Object.extend(Element.Methods.ByTag, {
3467 "FORM": Object.clone(Form.Methods),
3468 "INPUT": Object.clone(Form.Element.Methods),
3469 "SELECT": Object.clone(Form.Element.Methods),
3470 "TEXTAREA": Object.clone(Form.Element.Methods),
3471 "BUTTON": Object.clone(Form.Element.Methods)
3472 });
3473 }
3474
3475 Element.addMethods(methods);
3476
3477 function destroyCache_IE() {
3478 DIV = null;
3479 ELEMENT_CACHE = null;
3480 }
3481
3482 if (window.attachEvent)
3483 window.attachEvent('onunload', destroyCache_IE);
3484
3485 })(this);
3486 (function() {
3487
3488 function toDecimal(pctString) {
3489 var match = pctString.match(/^(\d+)%?$/i);
3490 if (!match) return null;
3491 return (Number(match[1]) / 100);
3492 }
3493
3494 function getRawStyle(element, style) {
3495 element = $(element);
3496
3497 var value = element.style[style];
3498 if (!value || value === 'auto') {
3499 var css = document.defaultView.getComputedStyle(element, null);
3500 value = css ? css[style] : null;
3501 }
3502
3503 if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3504 return value === 'auto' ? null : value;
3505 }
3506
3507 function getRawStyle_IE(element, style) {
3508 var value = element.style[style];
3509 if (!value && element.currentStyle) {
3510 value = element.currentStyle[style];
3511 }
3512 return value;
3513 }
3514
3515 function getContentWidth(element, context) {
3516 var boxWidth = element.offsetWidth;
3517
3518 var bl = getPixelValue(element, 'borderLeftWidth', context) || 0;
3519 var br = getPixelValue(element, 'borderRightWidth', context) || 0;
3520 var pl = getPixelValue(element, 'paddingLeft', context) || 0;
3521 var pr = getPixelValue(element, 'paddingRight', context) || 0;
3522
3523 return boxWidth - bl - br - pl - pr;
3524 }
3525
3526 if (!Object.isUndefined(document.documentElement.currentStyle) && !Prototype.Browser.Opera) {
3527 getRawStyle = getRawStyle_IE;
3528 }
3529
3530
3531 function getPixelValue(value, property, context) {
3532 var element = null;
3533 if (Object.isElement(value)) {
3534 element = value;
3535 value = getRawStyle(element, property);
3536 }
3537
3538 if (value === null || Object.isUndefined(value)) {
3539 return null;
3540 }
3541
3542 if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
3543 return window.parseFloat(value);
3544 }
3545
3546 var isPercentage = value.include('%'), isViewport = (context === document.viewport);
3547
3548 if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
3549 var style = element.style.left, rStyle = element.runtimeStyle.left;
3550 element.runtimeStyle.left = element.currentStyle.left;
3551 element.style.left = value || 0;
3552 value = element.style.pixelLeft;
3553 element.style.left = style;
3554 element.runtimeStyle.left = rStyle;
3555
3556 return value;
3557 }
3558
3559 if (element && isPercentage) {
3560 context = context || element.parentNode;
3561 var decimal = toDecimal(value), whole = null;
3562
3563 var isHorizontal = property.include('left') || property.include('right') ||
3564 property.include('width');
3565
3566 var isVertical = property.include('top') || property.include('bottom') ||
3567 property.include('height');
3568
3569 if (context === document.viewport) {
3570 if (isHorizontal) {
3571 whole = document.viewport.getWidth();
3572 } else if (isVertical) {
3573 whole = document.viewport.getHeight();
3574 }
3575 } else {
3576 if (isHorizontal) {
3577 whole = $(context).measure('width');
3578 } else if (isVertical) {
3579 whole = $(context).measure('height');
3580 }
3581 }
3582
3583 return (whole === null) ? 0 : whole * decimal;
3584 }
3585
3586 return 0;
3587 }
3588
3589 function toCSSPixels(number) {
3590 if (Object.isString(number) && number.endsWith('px'))
3591 return number;
3592 return number + 'px';
3593 }
3594
3595 function isDisplayed(element) {
3596 while (element && element.parentNode) {
3597 var display = element.getStyle('display');
3598 if (display === 'none') {
3599 return false;
3600 }
3601 element = $(element.parentNode);
3602 }
3603 return true;
3604 }
3605
3606 var hasLayout = Prototype.K;
3607 if ('currentStyle' in document.documentElement) {
3608 hasLayout = function(element) {
3609 if (!element.currentStyle.hasLayout) {
3610 element.style.zoom = 1;
3611 }
3612 return element;
3613 };
3614 }
3615
3616 function cssNameFor(key) {
3617 if (key.include('border')) key = key + '-width';
3618 return key.camelize();
3619 }
3620
3621 Element.Layout = Class.create(Hash, {
3622 initialize: function($super, element, preCompute) {
3623 $super();
3624 this.element = $(element);
3625
3626 Element.Layout.PROPERTIES.each( function(property) {
3627 this._set(property, null);
3628 }, this);
3629
3630 if (preCompute) {
3631 this._preComputing = true;
3632 this._begin();
3633 Element.Layout.PROPERTIES.each( this._compute, this );
3634 this._end();
3635 this._preComputing = false;
3636 }
3637 },
3638
3639 _set: function(property, value) {
3640 return Hash.prototype.set.call(this, property, value);
3641 },
3642
3643 set: function(property, value) {
3644 throw "Properties of Element.Layout are read-only.";
3645 },
3646
3647 get: function($super, property) {
3648 var value = $super(property);
3649 return value === null ? this._compute(property) : value;
3650 },
3651
3652 _begin: function() {
3653 if (this._isPrepared()) return;
3654
3655 var element = this.element;
3656 if (isDisplayed(element)) {
3657 this._setPrepared(true);
3658 return;
3659 }
3660
3661
3662 var originalStyles = {
3663 position: element.style.position || '',
3664 width: element.style.width || '',
3665 visibility: element.style.visibility || '',
3666 display: element.style.display || ''
3667 };
3668
3669 element.store('prototype_original_styles', originalStyles);
3670
3671 var position = getRawStyle(element, 'position'), width = element.offsetWidth;
3672
3673 if (width === 0 || width === null) {
3674 element.style.display = 'block';
3675 width = element.offsetWidth;
3676 }
3677
3678 var context = (position === 'fixed') ? document.viewport :
3679 element.parentNode;
3680
3681 var tempStyles = {
3682 visibility: 'hidden',
3683 display: 'block'
3684 };
3685
3686 if (position !== 'fixed') tempStyles.position = 'absolute';
3687
3688 element.setStyle(tempStyles);
3689
3690 var positionedWidth = element.offsetWidth, newWidth;
3691 if (width && (positionedWidth === width)) {
3692 newWidth = getContentWidth(element, context);
3693 } else if (position === 'absolute' || position === 'fixed') {
3694 newWidth = getContentWidth(element, context);
3695 } else {
3696 var parent = element.parentNode, pLayout = $(parent).getLayout();
3697
3698 newWidth = pLayout.get('width') -
3699 this.get('margin-left') -
3700 this.get('border-left') -
3701 this.get('padding-left') -
3702 this.get('padding-right') -
3703 this.get('border-right') -
3704 this.get('margin-right');
3705 }
3706
3707 element.setStyle({ width: newWidth + 'px' });
3708
3709 this._setPrepared(true);
3710 },
3711
3712 _end: function() {
3713 var element = this.element;
3714 var originalStyles = element.retrieve('prototype_original_styles');
3715 element.store('prototype_original_styles', null);
3716 element.setStyle(originalStyles);
3717 this._setPrepared(false);
3718 },
3719
3720 _compute: function(property) {
3721 var COMPUTATIONS = Element.Layout.COMPUTATIONS;
3722 if (!(property in COMPUTATIONS)) {
3723 throw "Property not found.";
3724 }
3725
3726 return this._set(property, COMPUTATIONS[property].call(this, this.element));
3727 },
3728
3729 _isPrepared: function() {
3730 return this.element.retrieve('prototype_element_layout_prepared', false);
3731 },
3732
3733 _setPrepared: function(bool) {
3734 return this.element.store('prototype_element_layout_prepared', bool);
3735 },
3736
3737 toObject: function() {
3738 var args = $A(arguments);
3739 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3740 args.join(' ').split(' ');
3741 var obj = {};
3742 keys.each( function(key) {
3743 if (!Element.Layout.PROPERTIES.include(key)) return;
3744 var value = this.get(key);
3745 if (value != null) obj[key] = value;
3746 }, this);
3747 return obj;
3748 },
3749
3750 toHash: function() {
3751 var obj = this.toObject.apply(this, arguments);
3752 return new Hash(obj);
3753 },
3754
3755 toCSS: function() {
3756 var args = $A(arguments);
3757 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3758 args.join(' ').split(' ');
3759 var css = {};
3760
3761 keys.each( function(key) {
3762 if (!Element.Layout.PROPERTIES.include(key)) return;
3763 if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
3764
3765 var value = this.get(key);
3766 if (value != null) css[cssNameFor(key)] = value + 'px';
3767 }, this);
3768 return css;
3769 },
3770
3771 inspect: function() {
3772 return "#<Element.Layout>";
3773 }
3774 });
3775
3776 Object.extend(Element.Layout, {
3777 PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
3778
3779 COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
3780
3781 COMPUTATIONS: {
3782 'height': function(element) {
3783 if (!this._preComputing) this._begin();
3784
3785 var bHeight = this.get('border-box-height');
3786 if (bHeight <= 0) {
3787 if (!this._preComputing) this._end();
3788 return 0;
3789 }
3790
3791 var bTop = this.get('border-top'),
3792 bBottom = this.get('border-bottom');
3793
3794 var pTop = this.get('padding-top'),
3795 pBottom = this.get('padding-bottom');
3796
3797 if (!this._preComputing) this._end();
3798
3799 return bHeight - bTop - bBottom - pTop - pBottom;
3800 },
3801
3802 'width': function(element) {
3803 if (!this._preComputing) this._begin();
3804
3805 var bWidth = this.get('border-box-width');
3806 if (bWidth <= 0) {
3807 if (!this._preComputing) this._end();
3808 return 0;
3809 }
3810
3811 var bLeft = this.get('border-left'),
3812 bRight = this.get('border-right');
3813
3814 var pLeft = this.get('padding-left'),
3815 pRight = this.get('padding-right');
3816
3817 if (!this._preComputing) this._end();
3818 return bWidth - bLeft - bRight - pLeft - pRight;
3819 },
3820
3821 'padding-box-height': function(element) {
3822 var height = this.get('height'),
3823 pTop = this.get('padding-top'),
3824 pBottom = this.get('padding-bottom');
3825
3826 return height + pTop + pBottom;
3827 },
3828
3829 'padding-box-width': function(element) {
3830 var width = this.get('width'),
3831 pLeft = this.get('padding-left'),
3832 pRight = this.get('padding-right');
3833
3834 return width + pLeft + pRight;
3835 },
3836
3837 'border-box-height': function(element) {
3838 if (!this._preComputing) this._begin();
3839 var height = element.offsetHeight;
3840 if (!this._preComputing) this._end();
3841 return height;
3842 },
3843
3844 'border-box-width': function(element) {
3845 if (!this._preComputing) this._begin();
3846 var width = element.offsetWidth;
3847 if (!this._preComputing) this._end();
3848 return width;
3849 },
3850
3851 'margin-box-height': function(element) {
3852 var bHeight = this.get('border-box-height'),
3853 mTop = this.get('margin-top'),
3854 mBottom = this.get('margin-bottom');
3855
3856 if (bHeight <= 0) return 0;
3857
3858 return bHeight + mTop + mBottom;
3859 },
3860
3861 'margin-box-width': function(element) {
3862 var bWidth = this.get('border-box-width'),
3863 mLeft = this.get('margin-left'),
3864 mRight = this.get('margin-right');
3865
3866 if (bWidth <= 0) return 0;
3867
3868 return bWidth + mLeft + mRight;
3869 },
3870
3871 'top': function(element) {
3872 var offset = element.positionedOffset();
3873 return offset.top;
3874 },
3875
3876 'bottom': function(element) {
3877 var offset = element.positionedOffset(),
3878 parent = element.getOffsetParent(),
3879 pHeight = parent.measure('height');
3880
3881 var mHeight = this.get('border-box-height');
3882
3883 return pHeight - mHeight - offset.top;
3884 },
3885
3886 'left': function(element) {
3887 var offset = element.positionedOffset();
3888 return offset.left;
3889 },
3890
3891 'right': function(element) {
3892 var offset = element.positionedOffset(),
3893 parent = element.getOffsetParent(),
3894 pWidth = parent.measure('width');
3895
3896 var mWidth = this.get('border-box-width');
3897
3898 return pWidth - mWidth - offset.left;
3899 },
3900
3901 'padding-top': function(element) {
3902 return getPixelValue(element, 'paddingTop');
3903 },
3904
3905 'padding-bottom': function(element) {
3906 return getPixelValue(element, 'paddingBottom');
3907 },
3908
3909 'padding-left': function(element) {
3910 return getPixelValue(element, 'paddingLeft');
3911 },
3912
3913 'padding-right': function(element) {
3914 return getPixelValue(element, 'paddingRight');
3915 },
3916
3917 'border-top': function(element) {
3918 return getPixelValue(element, 'borderTopWidth');
3919 },
3920
3921 'border-bottom': function(element) {
3922 return getPixelValue(element, 'borderBottomWidth');
3923 },
3924
3925 'border-left': function(element) {
3926 return getPixelValue(element, 'borderLeftWidth');
3927 },
3928
3929 'border-right': function(element) {
3930 return getPixelValue(element, 'borderRightWidth');
3931 },
3932
3933 'margin-top': function(element) {
3934 return getPixelValue(element, 'marginTop');
3935 },
3936
3937 'margin-bottom': function(element) {
3938 return getPixelValue(element, 'marginBottom');
3939 },
3940
3941 'margin-left': function(element) {
3942 return getPixelValue(element, 'marginLeft');
3943 },
3944
3945 'margin-right': function(element) {
3946 return getPixelValue(element, 'marginRight');
3947 }
3948 }
3949 });
3950
3951 if ('getBoundingClientRect' in document.documentElement) {
3952 Object.extend(Element.Layout.COMPUTATIONS, {
3953 'right': function(element) {
3954 var parent = hasLayout(element.getOffsetParent());
3955 var rect = element.getBoundingClientRect(),
3956 pRect = parent.getBoundingClientRect();
3957
3958 return (pRect.right - rect.right).round();
3959 },
3960
3961 'bottom': function(element) {
3962 var parent = hasLayout(element.getOffsetParent());
3963 var rect = element.getBoundingClientRect(),
3964 pRect = parent.getBoundingClientRect();
3965
3966 return (pRect.bottom - rect.bottom).round();
3967 }
3968 });
3969 }
3970
3971 Element.Offset = Class.create({
3972 initialize: function(left, top) {
3973 this.left = left.round();
3974 this.top = top.round();
3975
3976 this[0] = this.left;
3977 this[1] = this.top;
3978 },
3979
3980 relativeTo: function(offset) {
3981 return new Element.Offset(
3982 this.left - offset.left,
3983 this.top - offset.top
3984 );
3985 },
3986
3987 inspect: function() {
3988 return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
3989 },
3990
3991 toString: function() {
3992 return "[#{left}, #{top}]".interpolate(this);
3993 },
3994
3995 toArray: function() {
3996 return [this.left, this.top];
3997 }
3998 });
3999
4000 function getLayout(element, preCompute) {
4001 return new Element.Layout(element, preCompute);
4002 }
4003
4004 function measure(element, property) {
4005 return $(element).getLayout().get(property);
4006 }
4007
4008 function getHeight(element) {
4009 return Element.getDimensions(element).height;
4010 }
4011
4012 function getWidth(element) {
4013 return Element.getDimensions(element).width;
4014 }
4015
4016 function getDimensions(element) {
4017 element = $(element);
4018 var display = Element.getStyle(element, 'display');
4019
4020 if (display && display !== 'none') {
4021 return { width: element.offsetWidth, height: element.offsetHeight };
4022 }
4023
4024 var style = element.style;
4025 var originalStyles = {
4026 visibility: style.visibility,
4027 position: style.position,
4028 display: style.display
4029 };
4030
4031 var newStyles = {
4032 visibility: 'hidden',
4033 display: 'block'
4034 };
4035
4036 if (originalStyles.position !== 'fixed')
4037 newStyles.position = 'absolute';
4038
4039 Element.setStyle(element, newStyles);
4040
4041 var dimensions = {
4042 width: element.offsetWidth,
4043 height: element.offsetHeight
4044 };
4045
4046 Element.setStyle(element, originalStyles);
4047
4048 return dimensions;
4049 }
4050
4051 function getOffsetParent(element) {
4052 element = $(element);
4053
4054 function selfOrBody(element) {
4055 return isHtml(element) ? $(document.body) : $(element);
4056 }
4057
4058 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4059 return $(document.body);
4060
4061 var isInline = (Element.getStyle(element, 'display') === 'inline');
4062 if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent);
4063
4064 while ((element = element.parentNode) && element !== document.body) {
4065 if (Element.getStyle(element, 'position') !== 'static') {
4066 return selfOrBody(element);
4067 }
4068 }
4069
4070 return $(document.body);
4071 }
4072
4073
4074 function cumulativeOffset(element) {
4075 element = $(element);
4076 var valueT = 0, valueL = 0;
4077 if (element.parentNode) {
4078 do {
4079 valueT += element.offsetTop || 0;
4080 valueL += element.offsetLeft || 0;
4081 element = element.offsetParent;
4082 } while (element);
4083 }
4084 return new Element.Offset(valueL, valueT);
4085 }
4086
4087 function positionedOffset(element) {
4088 element = $(element);
4089
4090 var layout = element.getLayout();
4091
4092 var valueT = 0, valueL = 0;
4093 do {
4094 valueT += element.offsetTop || 0;
4095 valueL += element.offsetLeft || 0;
4096 element = element.offsetParent;
4097 if (element) {
4098 if (isBody(element)) break;
4099 var p = Element.getStyle(element, 'position');
4100 if (p !== 'static') break;
4101 }
4102 } while (element);
4103
4104 valueL -= layout.get('margin-left');
4105 valueT -= layout.get('margin-top');
4106
4107 return new Element.Offset(valueL, valueT);
4108 }
4109
4110 function cumulativeScrollOffset(element) {
4111 var valueT = 0, valueL = 0;
4112 do {
4113 if (element === document.body) {
4114 var bodyScrollNode = document.documentElement || document.body.parentNode || document.body;
4115 valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0;
4116 valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0;
4117 break;
4118 } else {
4119 valueT += element.scrollTop || 0;
4120 valueL += element.scrollLeft || 0;
4121 element = element.parentNode;
4122 }
4123 } while (element);
4124 return new Element.Offset(valueL, valueT);
4125 }
4126
4127 function viewportOffset(forElement) {
4128 var valueT = 0, valueL = 0, docBody = document.body;
4129
4130 forElement = $(forElement);
4131 var element = forElement;
4132 do {
4133 valueT += element.offsetTop || 0;
4134 valueL += element.offsetLeft || 0;
4135 if (element.offsetParent == docBody &&
4136 Element.getStyle(element, 'position') == 'absolute') break;
4137 } while (element = element.offsetParent);
4138
4139 element = forElement;
4140 do {
4141 if (element != docBody) {
4142 valueT -= element.scrollTop || 0;
4143 valueL -= element.scrollLeft || 0;
4144 }
4145 } while (element = element.parentNode);
4146 return new Element.Offset(valueL, valueT);
4147 }
4148
4149 function absolutize(element) {
4150 element = $(element);
4151
4152 if (Element.getStyle(element, 'position') === 'absolute') {
4153 return element;
4154 }
4155
4156 var offsetParent = getOffsetParent(element);
4157 var eOffset = element.viewportOffset(),
4158 pOffset = offsetParent.viewportOffset();
4159
4160 var offset = eOffset.relativeTo(pOffset);
4161 var layout = element.getLayout();
4162
4163 element.store('prototype_absolutize_original_styles', {
4164 position: element.getStyle('position'),
4165 left: element.getStyle('left'),
4166 top: element.getStyle('top'),
4167 width: element.getStyle('width'),
4168 height: element.getStyle('height')
4169 });
4170
4171 element.setStyle({
4172 position: 'absolute',
4173 top: offset.top + 'px',
4174 left: offset.left + 'px',
4175 width: layout.get('width') + 'px',
4176 height: layout.get('height') + 'px'
4177 });
4178
4179 return element;
4180 }
4181
4182 function relativize(element) {
4183 element = $(element);
4184 if (Element.getStyle(element, 'position') === 'relative') {
4185 return element;
4186 }
4187
4188 var originalStyles =
4189 element.retrieve('prototype_absolutize_original_styles');
4190
4191 if (originalStyles) element.setStyle(originalStyles);
4192 return element;
4193 }
4194
4195
4196 function scrollTo(element) {
4197 element = $(element);
4198 var pos = Element.cumulativeOffset(element);
4199 window.scrollTo(pos.left, pos.top);
4200 return element;
4201 }
4202
4203
4204 function makePositioned(element) {
4205 element = $(element);
4206 var position = Element.getStyle(element, 'position'), styles = {};
4207 if (position === 'static' || !position) {
4208 styles.position = 'relative';
4209 if (Prototype.Browser.Opera) {
4210 styles.top = 0;
4211 styles.left = 0;
4212 }
4213 Element.setStyle(element, styles);
4214 Element.store(element, 'prototype_made_positioned', true);
4215 }
4216 return element;
4217 }
4218
4219 function undoPositioned(element) {
4220 element = $(element);
4221 var storage = Element.getStorage(element),
4222 madePositioned = storage.get('prototype_made_positioned');
4223
4224 if (madePositioned) {
4225 storage.unset('prototype_made_positioned');
4226 Element.setStyle(element, {
4227 position: '',
4228 top: '',
4229 bottom: '',
4230 left: '',
4231 right: ''
4232 });
4233 }
4234 return element;
4235 }
4236
4237 function makeClipping(element) {
4238 element = $(element);
4239
4240 var storage = Element.getStorage(element),
4241 madeClipping = storage.get('prototype_made_clipping');
4242
4243 if (Object.isUndefined(madeClipping)) {
4244 var overflow = Element.getStyle(element, 'overflow');
4245 storage.set('prototype_made_clipping', overflow);
4246 if (overflow !== 'hidden')
4247 element.style.overflow = 'hidden';
4248 }
4249
4250 return element;
4251 }
4252
4253 function undoClipping(element) {
4254 element = $(element);
4255 var storage = Element.getStorage(element),
4256 overflow = storage.get('prototype_made_clipping');
4257
4258 if (!Object.isUndefined(overflow)) {
4259 storage.unset('prototype_made_clipping');
4260 element.style.overflow = overflow || '';
4261 }
4262
4263 return element;
4264 }
4265
4266 function clonePosition(element, source, options) {
4267 options = Object.extend({
4268 setLeft: true,
4269 setTop: true,
4270 setWidth: true,
4271 setHeight: true,
4272 offsetTop: 0,
4273 offsetLeft: 0
4274 }, options || {});
4275
4276 var docEl = document.documentElement;
4277
4278 source = $(source);
4279 element = $(element);
4280 var p, delta, layout, styles = {};
4281
4282 if (options.setLeft || options.setTop) {
4283 p = Element.viewportOffset(source);
4284 delta = [0, 0];
4285 if (Element.getStyle(element, 'position') === 'absolute') {
4286 var parent = Element.getOffsetParent(element);
4287 if (parent !== document.body) delta = Element.viewportOffset(parent);
4288 }
4289 }
4290
4291 function pageScrollXY() {
4292 var x = 0, y = 0;
4293 if (Object.isNumber(window.pageXOffset)) {
4294 x = window.pageXOffset;
4295 y = window.pageYOffset;
4296 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
4297 x = document.body.scrollLeft;
4298 y = document.body.scrollTop;
4299 } else if (docEl && (docEl.scrollLeft || docEl.scrollTop)) {
4300 x = docEl.scrollLeft;
4301 y = docEl.scrollTop;
4302 }
4303 return { x: x, y: y };
4304 }
4305
4306 var pageXY = pageScrollXY();
4307
4308
4309 if (options.setWidth || options.setHeight) {
4310 layout = Element.getLayout(source);
4311 }
4312
4313 if (options.setLeft)
4314 styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px';
4315 if (options.setTop)
4316 styles.top = (p[1] + pageXY.y - delta[1] + options.offsetTop) + 'px';
4317
4318 var currentLayout = element.getLayout();
4319
4320 if (options.setWidth) {
4321 styles.width = layout.get('width') + 'px';
4322 }
4323 if (options.setHeight) {
4324 styles.height = layout.get('height') + 'px';
4325 }
4326
4327 return Element.setStyle(element, styles);
4328 }
4329
4330
4331 if (Prototype.Browser.IE) {
4332 getOffsetParent = getOffsetParent.wrap(
4333 function(proceed, element) {
4334 element = $(element);
4335
4336 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4337 return $(document.body);
4338
4339 var position = element.getStyle('position');
4340 if (position !== 'static') return proceed(element);
4341
4342 element.setStyle({ position: 'relative' });
4343 var value = proceed(element);
4344 element.setStyle({ position: position });
4345 return value;
4346 }
4347 );
4348
4349 positionedOffset = positionedOffset.wrap(function(proceed, element) {
4350 element = $(element);
4351 if (!element.parentNode) return new Element.Offset(0, 0);
4352 var position = element.getStyle('position');
4353 if (position !== 'static') return proceed(element);
4354
4355 var offsetParent = element.getOffsetParent();
4356 if (offsetParent && offsetParent.getStyle('position') === 'fixed')
4357 hasLayout(offsetParent);
4358
4359 element.setStyle({ position: 'relative' });
4360 var value = proceed(element);
4361 element.setStyle({ position: position });
4362 return value;
4363 });
4364 } else if (Prototype.Browser.Webkit) {
4365 cumulativeOffset = function(element) {
4366 element = $(element);
4367 var valueT = 0, valueL = 0;
4368 do {
4369 valueT += element.offsetTop || 0;
4370 valueL += element.offsetLeft || 0;
4371 if (element.offsetParent == document.body) {
4372 if (Element.getStyle(element, 'position') == 'absolute') break;
4373 }
4374
4375 element = element.offsetParent;
4376 } while (element);
4377
4378 return new Element.Offset(valueL, valueT);
4379 };
4380 }
4381
4382
4383 Element.addMethods({
4384 getLayout: getLayout,
4385 measure: measure,
4386 getWidth: getWidth,
4387 getHeight: getHeight,
4388 getDimensions: getDimensions,
4389 getOffsetParent: getOffsetParent,
4390 cumulativeOffset: cumulativeOffset,
4391 positionedOffset: positionedOffset,
4392 cumulativeScrollOffset: cumulativeScrollOffset,
4393 viewportOffset: viewportOffset,
4394 absolutize: absolutize,
4395 relativize: relativize,
4396 scrollTo: scrollTo,
4397 makePositioned: makePositioned,
4398 undoPositioned: undoPositioned,
4399 makeClipping: makeClipping,
4400 undoClipping: undoClipping,
4401 clonePosition: clonePosition
4402 });
4403
4404 function isBody(element) {
4405 return element.nodeName.toUpperCase() === 'BODY';
4406 }
4407
4408 function isHtml(element) {
4409 return element.nodeName.toUpperCase() === 'HTML';
4410 }
4411
4412 function isDocument(element) {
4413 return element.nodeType === Node.DOCUMENT_NODE;
4414 }
4415
4416 function isDetached(element) {
4417 return element !== document.body &&
4418 !Element.descendantOf(element, document.body);
4419 }
4420
4421 if ('getBoundingClientRect' in document.documentElement) {
4422 Element.addMethods({
4423 viewportOffset: function(element) {
4424 element = $(element);
4425 if (isDetached(element)) return new Element.Offset(0, 0);
4426
4427 var rect = element.getBoundingClientRect(),
4428 docEl = document.documentElement;
4429 return new Element.Offset(rect.left - docEl.clientLeft,
4430 rect.top - docEl.clientTop);
4431 }
4432 });
4433 }
4434
4435
4436 })();
4437
4438 (function() {
4439
4440 var IS_OLD_OPERA = Prototype.Browser.Opera &&
4441 (window.parseFloat(window.opera.version()) < 9.5);
4442 var ROOT = null;
4443 function getRootElement() {
4444 if (ROOT) return ROOT;
4445 ROOT = IS_OLD_OPERA ? document.body : document.documentElement;
4446 return ROOT;
4447 }
4448
4449 function getDimensions() {
4450 return { width: this.getWidth(), height: this.getHeight() };
4451 }
4452
4453 function getWidth() {
4454 return getRootElement().clientWidth;
4455 }
4456
4457 function getHeight() {
4458 return getRootElement().clientHeight;
4459 }
4460
4461 function getScrollOffsets() {
4462 var x = window.pageXOffset || document.documentElement.scrollLeft ||
4463 document.body.scrollLeft;
4464 var y = window.pageYOffset || document.documentElement.scrollTop ||
4465 document.body.scrollTop;
4466
4467 return new Element.Offset(x, y);
4468 }
4469
4470 document.viewport = {
4471 getDimensions: getDimensions,
4472 getWidth: getWidth,
4473 getHeight: getHeight,
4474 getScrollOffsets: getScrollOffsets
4475 };
4476
4477 })();
4478 window.$$ = function() {
4479 var expression = $A(arguments).join(', ');
4480 return Prototype.Selector.select(expression, document);
4481 };
4482
4483 Prototype.Selector = (function() {
4484
4485 function select() {
4486 throw new Error('Method "Prototype.Selector.select" must be defined.');
4487 }
4488
4489 function match() {
4490 throw new Error('Method "Prototype.Selector.match" must be defined.');
4491 }
4492
4493 function find(elements, expression, index) {
4494 index = index || 0;
4495 var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
4496
4497 for (i = 0; i < length; i++) {
4498 if (match(elements[i], expression) && index == matchIndex++) {
4499 return Element.extend(elements[i]);
4500 }
4501 }
4502 }
4503
4504 function extendElements(elements) {
4505 for (var i = 0, length = elements.length; i < length; i++) {
4506 Element.extend(elements[i]);
4507 }
4508 return elements;
4509 }
4510
4511
4512 var K = Prototype.K;
4513
4514 return {
4515 select: select,
4516 match: match,
4517 find: find,
4518 extendElements: (Element.extend === K) ? K : extendElements,
4519 extendElement: Element.extend
4520 };
4521 })();
4522 Prototype._original_property = window.Sizzle;
4523
4524 ;(function () {
4525 function fakeDefine(fn) {
4526 Prototype._actual_sizzle = fn();
4527 }
4528 fakeDefine.amd = true;
4529
4530 if (typeof define !== 'undefined' && define.amd) {
4531 Prototype._original_define = define;
4532 Prototype._actual_sizzle = null;
4533 window.define = fakeDefine;
4534 }
4535 })();
4536
4537 /*!
4538 * Sizzle CSS Selector Engine v1.10.18
4539 * http://sizzlejs.com/
4540 *
4541 * Copyright 2013 jQuery Foundation, Inc. and other contributors
4542 * Released under the MIT license
4543 * http://jquery.org/license
4544 *
4545 * Date: 2014-02-05
4546 */
4547 (function( window ) {
4548
4549 var i,
4550 support,
4551 Expr,
4552 getText,
4553 isXML,
4554 compile,
4555 select,
4556 outermostContext,
4557 sortInput,
4558 hasDuplicate,
4559
4560 setDocument,
4561 document,
4562 docElem,
4563 documentIsHTML,
4564 rbuggyQSA,
4565 rbuggyMatches,
4566 matches,
4567 contains,
4568
4569 expando = "sizzle" + -(new Date()),
4570 preferredDoc = window.document,
4571 dirruns = 0,
4572 done = 0,
4573 classCache = createCache(),
4574 tokenCache = createCache(),
4575 compilerCache = createCache(),
4576 sortOrder = function( a, b ) {
4577 if ( a === b ) {
4578 hasDuplicate = true;
4579 }
4580 return 0;
4581 },
4582
4583 strundefined = typeof undefined,
4584 MAX_NEGATIVE = 1 << 31,
4585
4586 hasOwn = ({}).hasOwnProperty,
4587 arr = [],
4588 pop = arr.pop,
4589 push_native = arr.push,
4590 push = arr.push,
4591 slice = arr.slice,
4592 indexOf = arr.indexOf || function( elem ) {
4593 var i = 0,
4594 len = this.length;
4595 for ( ; i < len; i++ ) {
4596 if ( this[i] === elem ) {
4597 return i;
4598 }
4599 }
4600 return -1;
4601 },
4602
4603 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
4604
4605
4606 whitespace = "[\\x20\\t\\r\\n\\f]",
4607 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
4608
4609 identifier = characterEncoding.replace( "w", "w#" ),
4610
4611 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
4612 "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
4613
4614 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
4615
4616 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
4617
4618 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
4619 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
4620
4621 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
4622
4623 rpseudo = new RegExp( pseudos ),
4624 ridentifier = new RegExp( "^" + identifier + "$" ),
4625
4626 matchExpr = {
4627 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
4628 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
4629 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
4630 "ATTR": new RegExp( "^" + attributes ),
4631 "PSEUDO": new RegExp( "^" + pseudos ),
4632 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
4633 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
4634 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
4635 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
4636 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
4637 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
4638 },
4639
4640 rinputs = /^(?:input|select|textarea|button)$/i,
4641 rheader = /^h\d$/i,
4642
4643 rnative = /^[^{]+\{\s*\[native \w/,
4644
4645 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
4646
4647 rsibling = /[+~]/,
4648 rescape = /'|\\/g,
4649
4650 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
4651 funescape = function( _, escaped, escapedWhitespace ) {
4652 var high = "0x" + escaped - 0x10000;
4653 return high !== high || escapedWhitespace ?
4654 escaped :
4655 high < 0 ?
4656 String.fromCharCode( high + 0x10000 ) :
4657 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
4658 };
4659
4660 try {
4661 push.apply(
4662 (arr = slice.call( preferredDoc.childNodes )),
4663 preferredDoc.childNodes
4664 );
4665 arr[ preferredDoc.childNodes.length ].nodeType;
4666 } catch ( e ) {
4667 push = { apply: arr.length ?
4668
4669 function( target, els ) {
4670 push_native.apply( target, slice.call(els) );
4671 } :
4672
4673 function( target, els ) {
4674 var j = target.length,
4675 i = 0;
4676 while ( (target[j++] = els[i++]) ) {}
4677 target.length = j - 1;
4678 }
4679 };
4680 }
4681
4682 function Sizzle( selector, context, results, seed ) {
4683 var match, elem, m, nodeType,
4684 i, groups, old, nid, newContext, newSelector;
4685
4686 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
4687 setDocument( context );
4688 }
4689
4690 context = context || document;
4691 results = results || [];
4692
4693 if ( !selector || typeof selector !== "string" ) {
4694 return results;
4695 }
4696
4697 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
4698 return [];
4699 }
4700
4701 if ( documentIsHTML && !seed ) {
4702
4703 if ( (match = rquickExpr.exec( selector )) ) {
4704 if ( (m = match[1]) ) {
4705 if ( nodeType === 9 ) {
4706 elem = context.getElementById( m );
4707 if ( elem && elem.parentNode ) {
4708 if ( elem.id === m ) {
4709 results.push( elem );
4710 return results;
4711 }
4712 } else {
4713 return results;
4714 }
4715 } else {
4716 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
4717 contains( context, elem ) && elem.id === m ) {
4718 results.push( elem );
4719 return results;
4720 }
4721 }
4722
4723 } else if ( match[2] ) {
4724 push.apply( results, context.getElementsByTagName( selector ) );
4725 return results;
4726
4727 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
4728 push.apply( results, context.getElementsByClassName( m ) );
4729 return results;
4730 }
4731 }
4732
4733 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
4734 nid = old = expando;
4735 newContext = context;
4736 newSelector = nodeType === 9 && selector;
4737
4738 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4739 groups = tokenize( selector );
4740
4741 if ( (old = context.getAttribute("id")) ) {
4742 nid = old.replace( rescape, "\\$&" );
4743 } else {
4744 context.setAttribute( "id", nid );
4745 }
4746 nid = "[id='" + nid + "'] ";
4747
4748 i = groups.length;
4749 while ( i-- ) {
4750 groups[i] = nid + toSelector( groups[i] );
4751 }
4752 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
4753 newSelector = groups.join(",");
4754 }
4755
4756 if ( newSelector ) {
4757 try {
4758 push.apply( results,
4759 newContext.querySelectorAll( newSelector )
4760 );
4761 return results;
4762 } catch(qsaError) {
4763 } finally {
4764 if ( !old ) {
4765 context.removeAttribute("id");
4766 }
4767 }
4768 }
4769 }
4770 }
4771
4772 return select( selector.replace( rtrim, "$1" ), context, results, seed );
4773 }
4774
4775 /**
4776 * Create key-value caches of limited size
4777 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
4778 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
4779 * deleting the oldest entry
4780 */
4781 function createCache() {
4782 var keys = [];
4783
4784 function cache( key, value ) {
4785 if ( keys.push( key + " " ) > Expr.cacheLength ) {
4786 delete cache[ keys.shift() ];
4787 }
4788 return (cache[ key + " " ] = value);
4789 }
4790 return cache;
4791 }
4792
4793 /**
4794 * Mark a function for special use by Sizzle
4795 * @param {Function} fn The function to mark
4796 */
4797 function markFunction( fn ) {
4798 fn[ expando ] = true;
4799 return fn;
4800 }
4801
4802 /**
4803 * Support testing using an element
4804 * @param {Function} fn Passed the created div and expects a boolean result
4805 */
4806 function assert( fn ) {
4807 var div = document.createElement("div");
4808
4809 try {
4810 return !!fn( div );
4811 } catch (e) {
4812 return false;
4813 } finally {
4814 if ( div.parentNode ) {
4815 div.parentNode.removeChild( div );
4816 }
4817 div = null;
4818 }
4819 }
4820
4821 /**
4822 * Adds the same handler for all of the specified attrs
4823 * @param {String} attrs Pipe-separated list of attributes
4824 * @param {Function} handler The method that will be applied
4825 */
4826 function addHandle( attrs, handler ) {
4827 var arr = attrs.split("|"),
4828 i = attrs.length;
4829
4830 while ( i-- ) {
4831 Expr.attrHandle[ arr[i] ] = handler;
4832 }
4833 }
4834
4835 /**
4836 * Checks document order of two siblings
4837 * @param {Element} a
4838 * @param {Element} b
4839 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
4840 */
4841 function siblingCheck( a, b ) {
4842 var cur = b && a,
4843 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
4844 ( ~b.sourceIndex || MAX_NEGATIVE ) -
4845 ( ~a.sourceIndex || MAX_NEGATIVE );
4846
4847 if ( diff ) {
4848 return diff;
4849 }
4850
4851 if ( cur ) {
4852 while ( (cur = cur.nextSibling) ) {
4853 if ( cur === b ) {
4854 return -1;
4855 }
4856 }
4857 }
4858
4859 return a ? 1 : -1;
4860 }
4861
4862 /**
4863 * Returns a function to use in pseudos for input types
4864 * @param {String} type
4865 */
4866 function createInputPseudo( type ) {
4867 return function( elem ) {
4868 var name = elem.nodeName.toLowerCase();
4869 return name === "input" && elem.type === type;
4870 };
4871 }
4872
4873 /**
4874 * Returns a function to use in pseudos for buttons
4875 * @param {String} type
4876 */
4877 function createButtonPseudo( type ) {
4878 return function( elem ) {
4879 var name = elem.nodeName.toLowerCase();
4880 return (name === "input" || name === "button") && elem.type === type;
4881 };
4882 }
4883
4884 /**
4885 * Returns a function to use in pseudos for positionals
4886 * @param {Function} fn
4887 */
4888 function createPositionalPseudo( fn ) {
4889 return markFunction(function( argument ) {
4890 argument = +argument;
4891 return markFunction(function( seed, matches ) {
4892 var j,
4893 matchIndexes = fn( [], seed.length, argument ),
4894 i = matchIndexes.length;
4895
4896 while ( i-- ) {
4897 if ( seed[ (j = matchIndexes[i]) ] ) {
4898 seed[j] = !(matches[j] = seed[j]);
4899 }
4900 }
4901 });
4902 });
4903 }
4904
4905 /**
4906 * Checks a node for validity as a Sizzle context
4907 * @param {Element|Object=} context
4908 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
4909 */
4910 function testContext( context ) {
4911 return context && typeof context.getElementsByTagName !== strundefined && context;
4912 }
4913
4914 support = Sizzle.support = {};
4915
4916 /**
4917 * Detects XML nodes
4918 * @param {Element|Object} elem An element or a document
4919 * @returns {Boolean} True iff elem is a non-HTML XML node
4920 */
4921 isXML = Sizzle.isXML = function( elem ) {
4922 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4923 return documentElement ? documentElement.nodeName !== "HTML" : false;
4924 };
4925
4926 /**
4927 * Sets document-related variables once based on the current document
4928 * @param {Element|Object} [doc] An element or document object to use to set the document
4929 * @returns {Object} Returns the current document
4930 */
4931 setDocument = Sizzle.setDocument = function( node ) {
4932 var hasCompare,
4933 doc = node ? node.ownerDocument || node : preferredDoc,
4934 parent = doc.defaultView;
4935
4936 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4937 return document;
4938 }
4939
4940 document = doc;
4941 docElem = doc.documentElement;
4942
4943 documentIsHTML = !isXML( doc );
4944
4945 if ( parent && parent !== parent.top ) {
4946 if ( parent.addEventListener ) {
4947 parent.addEventListener( "unload", function() {
4948 setDocument();
4949 }, false );
4950 } else if ( parent.attachEvent ) {
4951 parent.attachEvent( "onunload", function() {
4952 setDocument();
4953 });
4954 }
4955 }
4956
4957 /* Attributes
4958 ---------------------------------------------------------------------- */
4959
4960 support.attributes = assert(function( div ) {
4961 div.className = "i";
4962 return !div.getAttribute("className");
4963 });
4964
4965 /* getElement(s)By*
4966 ---------------------------------------------------------------------- */
4967
4968 support.getElementsByTagName = assert(function( div ) {
4969 div.appendChild( doc.createComment("") );
4970 return !div.getElementsByTagName("*").length;
4971 });
4972
4973 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
4974 div.innerHTML = "<div class='a'></div><div class='a i'></div>";
4975
4976 div.firstChild.className = "i";
4977 return div.getElementsByClassName("i").length === 2;
4978 });
4979
4980 support.getById = assert(function( div ) {
4981 docElem.appendChild( div ).id = expando;
4982 return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
4983 });
4984
4985 if ( support.getById ) {
4986 Expr.find["ID"] = function( id, context ) {
4987 if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
4988 var m = context.getElementById( id );
4989 return m && m.parentNode ? [m] : [];
4990 }
4991 };
4992 Expr.filter["ID"] = function( id ) {
4993 var attrId = id.replace( runescape, funescape );
4994 return function( elem ) {
4995 return elem.getAttribute("id") === attrId;
4996 };
4997 };
4998 } else {
4999 delete Expr.find["ID"];
5000
5001 Expr.filter["ID"] = function( id ) {
5002 var attrId = id.replace( runescape, funescape );
5003 return function( elem ) {
5004 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
5005 return node && node.value === attrId;
5006 };
5007 };
5008 }
5009
5010 Expr.find["TAG"] = support.getElementsByTagName ?
5011 function( tag, context ) {
5012 if ( typeof context.getElementsByTagName !== strundefined ) {
5013 return context.getElementsByTagName( tag );
5014 }
5015 } :
5016 function( tag, context ) {
5017 var elem,
5018 tmp = [],
5019 i = 0,
5020 results = context.getElementsByTagName( tag );
5021
5022 if ( tag === "*" ) {
5023 while ( (elem = results[i++]) ) {
5024 if ( elem.nodeType === 1 ) {
5025 tmp.push( elem );
5026 }
5027 }
5028
5029 return tmp;
5030 }
5031 return results;
5032 };
5033
5034 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
5035 if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
5036 return context.getElementsByClassName( className );
5037 }
5038 };
5039
5040 /* QSA/matchesSelector
5041 ---------------------------------------------------------------------- */
5042
5043
5044 rbuggyMatches = [];
5045
5046 rbuggyQSA = [];
5047
5048 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
5049 assert(function( div ) {
5050 div.innerHTML = "<select t=''><option selected=''></option></select>";
5051
5052 if ( div.querySelectorAll("[t^='']").length ) {
5053 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
5054 }
5055
5056 if ( !div.querySelectorAll("[selected]").length ) {
5057 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
5058 }
5059
5060 if ( !div.querySelectorAll(":checked").length ) {
5061 rbuggyQSA.push(":checked");
5062 }
5063 });
5064
5065 assert(function( div ) {
5066 var input = doc.createElement("input");
5067 input.setAttribute( "type", "hidden" );
5068 div.appendChild( input ).setAttribute( "name", "D" );
5069
5070 if ( div.querySelectorAll("[name=d]").length ) {
5071 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
5072 }
5073
5074 if ( !div.querySelectorAll(":enabled").length ) {
5075 rbuggyQSA.push( ":enabled", ":disabled" );
5076 }
5077
5078 div.querySelectorAll("*,:x");
5079 rbuggyQSA.push(",.*:");
5080 });
5081 }
5082
5083 if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
5084 docElem.mozMatchesSelector ||
5085 docElem.oMatchesSelector ||
5086 docElem.msMatchesSelector) )) ) {
5087
5088 assert(function( div ) {
5089 support.disconnectedMatch = matches.call( div, "div" );
5090
5091 matches.call( div, "[s!='']:x" );
5092 rbuggyMatches.push( "!=", pseudos );
5093 });
5094 }
5095
5096 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
5097 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
5098
5099 /* Contains
5100 ---------------------------------------------------------------------- */
5101 hasCompare = rnative.test( docElem.compareDocumentPosition );
5102
5103 contains = hasCompare || rnative.test( docElem.contains ) ?
5104 function( a, b ) {
5105 var adown = a.nodeType === 9 ? a.documentElement : a,
5106 bup = b && b.parentNode;
5107 return a === bup || !!( bup && bup.nodeType === 1 && (
5108 adown.contains ?
5109 adown.contains( bup ) :
5110 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
5111 ));
5112 } :
5113 function( a, b ) {
5114 if ( b ) {
5115 while ( (b = b.parentNode) ) {
5116 if ( b === a ) {
5117 return true;
5118 }
5119 }
5120 }
5121 return false;
5122 };
5123
5124 /* Sorting
5125 ---------------------------------------------------------------------- */
5126
5127 sortOrder = hasCompare ?
5128 function( a, b ) {
5129
5130 if ( a === b ) {
5131 hasDuplicate = true;
5132 return 0;
5133 }
5134
5135 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
5136 if ( compare ) {
5137 return compare;
5138 }
5139
5140 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
5141 a.compareDocumentPosition( b ) :
5142
5143 1;
5144
5145 if ( compare & 1 ||
5146 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
5147
5148 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
5149 return -1;
5150 }
5151 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
5152 return 1;
5153 }
5154
5155 return sortInput ?
5156 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5157 0;
5158 }
5159
5160 return compare & 4 ? -1 : 1;
5161 } :
5162 function( a, b ) {
5163 if ( a === b ) {
5164 hasDuplicate = true;
5165 return 0;
5166 }
5167
5168 var cur,
5169 i = 0,
5170 aup = a.parentNode,
5171 bup = b.parentNode,
5172 ap = [ a ],
5173 bp = [ b ];
5174
5175 if ( !aup || !bup ) {
5176 return a === doc ? -1 :
5177 b === doc ? 1 :
5178 aup ? -1 :
5179 bup ? 1 :
5180 sortInput ?
5181 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5182 0;
5183
5184 } else if ( aup === bup ) {
5185 return siblingCheck( a, b );
5186 }
5187
5188 cur = a;
5189 while ( (cur = cur.parentNode) ) {
5190 ap.unshift( cur );
5191 }
5192 cur = b;
5193 while ( (cur = cur.parentNode) ) {
5194 bp.unshift( cur );
5195 }
5196
5197 while ( ap[i] === bp[i] ) {
5198 i++;
5199 }
5200
5201 return i ?
5202 siblingCheck( ap[i], bp[i] ) :
5203
5204 ap[i] === preferredDoc ? -1 :
5205 bp[i] === preferredDoc ? 1 :
5206 0;
5207 };
5208
5209 return doc;
5210 };
5211
5212 Sizzle.matches = function( expr, elements ) {
5213 return Sizzle( expr, null, null, elements );
5214 };
5215
5216 Sizzle.matchesSelector = function( elem, expr ) {
5217 if ( ( elem.ownerDocument || elem ) !== document ) {
5218 setDocument( elem );
5219 }
5220
5221 expr = expr.replace( rattributeQuotes, "='$1']" );
5222
5223 if ( support.matchesSelector && documentIsHTML &&
5224 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
5225 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
5226
5227 try {
5228 var ret = matches.call( elem, expr );
5229
5230 if ( ret || support.disconnectedMatch ||
5231 elem.document && elem.document.nodeType !== 11 ) {
5232 return ret;
5233 }
5234 } catch(e) {}
5235 }
5236
5237 return Sizzle( expr, document, null, [elem] ).length > 0;
5238 };
5239
5240 Sizzle.contains = function( context, elem ) {
5241 if ( ( context.ownerDocument || context ) !== document ) {
5242 setDocument( context );
5243 }
5244 return contains( context, elem );
5245 };
5246
5247 Sizzle.attr = function( elem, name ) {
5248 if ( ( elem.ownerDocument || elem ) !== document ) {
5249 setDocument( elem );
5250 }
5251
5252 var fn = Expr.attrHandle[ name.toLowerCase() ],
5253 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
5254 fn( elem, name, !documentIsHTML ) :
5255 undefined;
5256
5257 return val !== undefined ?
5258 val :
5259 support.attributes || !documentIsHTML ?
5260 elem.getAttribute( name ) :
5261 (val = elem.getAttributeNode(name)) && val.specified ?
5262 val.value :
5263 null;
5264 };
5265
5266 Sizzle.error = function( msg ) {
5267 throw new Error( "Syntax error, unrecognized expression: " + msg );
5268 };
5269
5270 /**
5271 * Document sorting and removing duplicates
5272 * @param {ArrayLike} results
5273 */
5274 Sizzle.uniqueSort = function( results ) {
5275 var elem,
5276 duplicates = [],
5277 j = 0,
5278 i = 0;
5279
5280 hasDuplicate = !support.detectDuplicates;
5281 sortInput = !support.sortStable && results.slice( 0 );
5282 results.sort( sortOrder );
5283
5284 if ( hasDuplicate ) {
5285 while ( (elem = results[i++]) ) {
5286 if ( elem === results[ i ] ) {
5287 j = duplicates.push( i );
5288 }
5289 }
5290 while ( j-- ) {
5291 results.splice( duplicates[ j ], 1 );
5292 }
5293 }
5294
5295 sortInput = null;
5296
5297 return results;
5298 };
5299
5300 /**
5301 * Utility function for retrieving the text value of an array of DOM nodes
5302 * @param {Array|Element} elem
5303 */
5304 getText = Sizzle.getText = function( elem ) {
5305 var node,
5306 ret = "",
5307 i = 0,
5308 nodeType = elem.nodeType;
5309
5310 if ( !nodeType ) {
5311 while ( (node = elem[i++]) ) {
5312 ret += getText( node );
5313 }
5314 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
5315 if ( typeof elem.textContent === "string" ) {
5316 return elem.textContent;
5317 } else {
5318 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5319 ret += getText( elem );
5320 }
5321 }
5322 } else if ( nodeType === 3 || nodeType === 4 ) {
5323 return elem.nodeValue;
5324 }
5325
5326 return ret;
5327 };
5328
5329 Expr = Sizzle.selectors = {
5330
5331 cacheLength: 50,
5332
5333 createPseudo: markFunction,
5334
5335 match: matchExpr,
5336
5337 attrHandle: {},
5338
5339 find: {},
5340
5341 relative: {
5342 ">": { dir: "parentNode", first: true },
5343 " ": { dir: "parentNode" },
5344 "+": { dir: "previousSibling", first: true },
5345 "~": { dir: "previousSibling" }
5346 },
5347
5348 preFilter: {
5349 "ATTR": function( match ) {
5350 match[1] = match[1].replace( runescape, funescape );
5351
5352 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
5353
5354 if ( match[2] === "~=" ) {
5355 match[3] = " " + match[3] + " ";
5356 }
5357
5358 return match.slice( 0, 4 );
5359 },
5360
5361 "CHILD": function( match ) {
5362 /* matches from matchExpr["CHILD"]
5363 1 type (only|nth|...)
5364 2 what (child|of-type)
5365 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
5366 4 xn-component of xn+y argument ([+-]?\d*n|)
5367 5 sign of xn-component
5368 6 x of xn-component
5369 7 sign of y-component
5370 8 y of y-component
5371 */
5372 match[1] = match[1].toLowerCase();
5373
5374 if ( match[1].slice( 0, 3 ) === "nth" ) {
5375 if ( !match[3] ) {
5376 Sizzle.error( match[0] );
5377 }
5378
5379 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
5380 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
5381
5382 } else if ( match[3] ) {
5383 Sizzle.error( match[0] );
5384 }
5385
5386 return match;
5387 },
5388
5389 "PSEUDO": function( match ) {
5390 var excess,
5391 unquoted = !match[5] && match[2];
5392
5393 if ( matchExpr["CHILD"].test( match[0] ) ) {
5394 return null;
5395 }
5396
5397 if ( match[3] && match[4] !== undefined ) {
5398 match[2] = match[4];
5399
5400 } else if ( unquoted && rpseudo.test( unquoted ) &&
5401 (excess = tokenize( unquoted, true )) &&
5402 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
5403
5404 match[0] = match[0].slice( 0, excess );
5405 match[2] = unquoted.slice( 0, excess );
5406 }
5407
5408 return match.slice( 0, 3 );
5409 }
5410 },
5411
5412 filter: {
5413
5414 "TAG": function( nodeNameSelector ) {
5415 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
5416 return nodeNameSelector === "*" ?
5417 function() { return true; } :
5418 function( elem ) {
5419 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
5420 };
5421 },
5422
5423 "CLASS": function( className ) {
5424 var pattern = classCache[ className + " " ];
5425
5426 return pattern ||
5427 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
5428 classCache( className, function( elem ) {
5429 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
5430 });
5431 },
5432
5433 "ATTR": function( name, operator, check ) {
5434 return function( elem ) {
5435 var result = Sizzle.attr( elem, name );
5436
5437 if ( result == null ) {
5438 return operator === "!=";
5439 }
5440 if ( !operator ) {
5441 return true;
5442 }
5443
5444 result += "";
5445
5446 return operator === "=" ? result === check :
5447 operator === "!=" ? result !== check :
5448 operator === "^=" ? check && result.indexOf( check ) === 0 :
5449 operator === "*=" ? check && result.indexOf( check ) > -1 :
5450 operator === "$=" ? check && result.slice( -check.length ) === check :
5451 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
5452 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
5453 false;
5454 };
5455 },
5456
5457 "CHILD": function( type, what, argument, first, last ) {
5458 var simple = type.slice( 0, 3 ) !== "nth",
5459 forward = type.slice( -4 ) !== "last",
5460 ofType = what === "of-type";
5461
5462 return first === 1 && last === 0 ?
5463
5464 function( elem ) {
5465 return !!elem.parentNode;
5466 } :
5467
5468 function( elem, context, xml ) {
5469 var cache, outerCache, node, diff, nodeIndex, start,
5470 dir = simple !== forward ? "nextSibling" : "previousSibling",
5471 parent = elem.parentNode,
5472 name = ofType && elem.nodeName.toLowerCase(),
5473 useCache = !xml && !ofType;
5474
5475 if ( parent ) {
5476
5477 if ( simple ) {
5478 while ( dir ) {
5479 node = elem;
5480 while ( (node = node[ dir ]) ) {
5481 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
5482 return false;
5483 }
5484 }
5485 start = dir = type === "only" && !start && "nextSibling";
5486 }
5487 return true;
5488 }
5489
5490 start = [ forward ? parent.firstChild : parent.lastChild ];
5491
5492 if ( forward && useCache ) {
5493 outerCache = parent[ expando ] || (parent[ expando ] = {});
5494 cache = outerCache[ type ] || [];
5495 nodeIndex = cache[0] === dirruns && cache[1];
5496 diff = cache[0] === dirruns && cache[2];
5497 node = nodeIndex && parent.childNodes[ nodeIndex ];
5498
5499 while ( (node = ++nodeIndex && node && node[ dir ] ||
5500
5501 (diff = nodeIndex = 0) || start.pop()) ) {
5502
5503 if ( node.nodeType === 1 && ++diff && node === elem ) {
5504 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
5505 break;
5506 }
5507 }
5508
5509 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
5510 diff = cache[1];
5511
5512 } else {
5513 while ( (node = ++nodeIndex && node && node[ dir ] ||
5514 (diff = nodeIndex = 0) || start.pop()) ) {
5515
5516 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
5517 if ( useCache ) {
5518 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
5519 }
5520
5521 if ( node === elem ) {
5522 break;
5523 }
5524 }
5525 }
5526 }
5527
5528 diff -= last;
5529 return diff === first || ( diff % first === 0 && diff / first >= 0 );
5530 }
5531 };
5532 },
5533
5534 "PSEUDO": function( pseudo, argument ) {
5535 var args,
5536 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
5537 Sizzle.error( "unsupported pseudo: " + pseudo );
5538
5539 if ( fn[ expando ] ) {
5540 return fn( argument );
5541 }
5542
5543 if ( fn.length > 1 ) {
5544 args = [ pseudo, pseudo, "", argument ];
5545 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
5546 markFunction(function( seed, matches ) {
5547 var idx,
5548 matched = fn( seed, argument ),
5549 i = matched.length;
5550 while ( i-- ) {
5551 idx = indexOf.call( seed, matched[i] );
5552 seed[ idx ] = !( matches[ idx ] = matched[i] );
5553 }
5554 }) :
5555 function( elem ) {
5556 return fn( elem, 0, args );
5557 };
5558 }
5559
5560 return fn;
5561 }
5562 },
5563
5564 pseudos: {
5565 "not": markFunction(function( selector ) {
5566 var input = [],
5567 results = [],
5568 matcher = compile( selector.replace( rtrim, "$1" ) );
5569
5570 return matcher[ expando ] ?
5571 markFunction(function( seed, matches, context, xml ) {
5572 var elem,
5573 unmatched = matcher( seed, null, xml, [] ),
5574 i = seed.length;
5575
5576 while ( i-- ) {
5577 if ( (elem = unmatched[i]) ) {
5578 seed[i] = !(matches[i] = elem);
5579 }
5580 }
5581 }) :
5582 function( elem, context, xml ) {
5583 input[0] = elem;
5584 matcher( input, null, xml, results );
5585 return !results.pop();
5586 };
5587 }),
5588
5589 "has": markFunction(function( selector ) {
5590 return function( elem ) {
5591 return Sizzle( selector, elem ).length > 0;
5592 };
5593 }),
5594
5595 "contains": markFunction(function( text ) {
5596 return function( elem ) {
5597 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
5598 };
5599 }),
5600
5601 "lang": markFunction( function( lang ) {
5602 if ( !ridentifier.test(lang || "") ) {
5603 Sizzle.error( "unsupported lang: " + lang );
5604 }
5605 lang = lang.replace( runescape, funescape ).toLowerCase();
5606 return function( elem ) {
5607 var elemLang;
5608 do {
5609 if ( (elemLang = documentIsHTML ?
5610 elem.lang :
5611 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
5612
5613 elemLang = elemLang.toLowerCase();
5614 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
5615 }
5616 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
5617 return false;
5618 };
5619 }),
5620
5621 "target": function( elem ) {
5622 var hash = window.location && window.location.hash;
5623 return hash && hash.slice( 1 ) === elem.id;
5624 },
5625
5626 "root": function( elem ) {
5627 return elem === docElem;
5628 },
5629
5630 "focus": function( elem ) {
5631 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
5632 },
5633
5634 "enabled": function( elem ) {
5635 return elem.disabled === false;
5636 },
5637
5638 "disabled": function( elem ) {
5639 return elem.disabled === true;
5640 },
5641
5642 "checked": function( elem ) {
5643 var nodeName = elem.nodeName.toLowerCase();
5644 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
5645 },
5646
5647 "selected": function( elem ) {
5648 if ( elem.parentNode ) {
5649 elem.parentNode.selectedIndex;
5650 }
5651
5652 return elem.selected === true;
5653 },
5654
5655 "empty": function( elem ) {
5656 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5657 if ( elem.nodeType < 6 ) {
5658 return false;
5659 }
5660 }
5661 return true;
5662 },
5663
5664 "parent": function( elem ) {
5665 return !Expr.pseudos["empty"]( elem );
5666 },
5667
5668 "header": function( elem ) {
5669 return rheader.test( elem.nodeName );
5670 },
5671
5672 "input": function( elem ) {
5673 return rinputs.test( elem.nodeName );
5674 },
5675
5676 "button": function( elem ) {
5677 var name = elem.nodeName.toLowerCase();
5678 return name === "input" && elem.type === "button" || name === "button";
5679 },
5680
5681 "text": function( elem ) {
5682 var attr;
5683 return elem.nodeName.toLowerCase() === "input" &&
5684 elem.type === "text" &&
5685
5686 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
5687 },
5688
5689 "first": createPositionalPseudo(function() {
5690 return [ 0 ];
5691 }),
5692
5693 "last": createPositionalPseudo(function( matchIndexes, length ) {
5694 return [ length - 1 ];
5695 }),
5696
5697 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
5698 return [ argument < 0 ? argument + length : argument ];
5699 }),
5700
5701 "even": createPositionalPseudo(function( matchIndexes, length ) {
5702 var i = 0;
5703 for ( ; i < length; i += 2 ) {
5704 matchIndexes.push( i );
5705 }
5706 return matchIndexes;
5707 }),
5708
5709 "odd": createPositionalPseudo(function( matchIndexes, length ) {
5710 var i = 1;
5711 for ( ; i < length; i += 2 ) {
5712 matchIndexes.push( i );
5713 }
5714 return matchIndexes;
5715 }),
5716
5717 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5718 var i = argument < 0 ? argument + length : argument;
5719 for ( ; --i >= 0; ) {
5720 matchIndexes.push( i );
5721 }
5722 return matchIndexes;
5723 }),
5724
5725 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5726 var i = argument < 0 ? argument + length : argument;
5727 for ( ; ++i < length; ) {
5728 matchIndexes.push( i );
5729 }
5730 return matchIndexes;
5731 })
5732 }
5733 };
5734
5735 Expr.pseudos["nth"] = Expr.pseudos["eq"];
5736
5737 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5738 Expr.pseudos[ i ] = createInputPseudo( i );
5739 }
5740 for ( i in { submit: true, reset: true } ) {
5741 Expr.pseudos[ i ] = createButtonPseudo( i );
5742 }
5743
5744 function setFilters() {}
5745 setFilters.prototype = Expr.filters = Expr.pseudos;
5746 Expr.setFilters = new setFilters();
5747
5748 function tokenize( selector, parseOnly ) {
5749 var matched, match, tokens, type,
5750 soFar, groups, preFilters,
5751 cached = tokenCache[ selector + " " ];
5752
5753 if ( cached ) {
5754 return parseOnly ? 0 : cached.slice( 0 );
5755 }
5756
5757 soFar = selector;
5758 groups = [];
5759 preFilters = Expr.preFilter;
5760
5761 while ( soFar ) {
5762
5763 if ( !matched || (match = rcomma.exec( soFar )) ) {
5764 if ( match ) {
5765 soFar = soFar.slice( match[0].length ) || soFar;
5766 }
5767 groups.push( (tokens = []) );
5768 }
5769
5770 matched = false;
5771
5772 if ( (match = rcombinators.exec( soFar )) ) {
5773 matched = match.shift();
5774 tokens.push({
5775 value: matched,
5776 type: match[0].replace( rtrim, " " )
5777 });
5778 soFar = soFar.slice( matched.length );
5779 }
5780
5781 for ( type in Expr.filter ) {
5782 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5783 (match = preFilters[ type ]( match ))) ) {
5784 matched = match.shift();
5785 tokens.push({
5786 value: matched,
5787 type: type,
5788 matches: match
5789 });
5790 soFar = soFar.slice( matched.length );
5791 }
5792 }
5793
5794 if ( !matched ) {
5795 break;
5796 }
5797 }
5798
5799 return parseOnly ?
5800 soFar.length :
5801 soFar ?
5802 Sizzle.error( selector ) :
5803 tokenCache( selector, groups ).slice( 0 );
5804 }
5805
5806 function toSelector( tokens ) {
5807 var i = 0,
5808 len = tokens.length,
5809 selector = "";
5810 for ( ; i < len; i++ ) {
5811 selector += tokens[i].value;
5812 }
5813 return selector;
5814 }
5815
5816 function addCombinator( matcher, combinator, base ) {
5817 var dir = combinator.dir,
5818 checkNonElements = base && dir === "parentNode",
5819 doneName = done++;
5820
5821 return combinator.first ?
5822 function( elem, context, xml ) {
5823 while ( (elem = elem[ dir ]) ) {
5824 if ( elem.nodeType === 1 || checkNonElements ) {
5825 return matcher( elem, context, xml );
5826 }
5827 }
5828 } :
5829
5830 function( elem, context, xml ) {
5831 var oldCache, outerCache,
5832 newCache = [ dirruns, doneName ];
5833
5834 if ( xml ) {
5835 while ( (elem = elem[ dir ]) ) {
5836 if ( elem.nodeType === 1 || checkNonElements ) {
5837 if ( matcher( elem, context, xml ) ) {
5838 return true;
5839 }
5840 }
5841 }
5842 } else {
5843 while ( (elem = elem[ dir ]) ) {
5844 if ( elem.nodeType === 1 || checkNonElements ) {
5845 outerCache = elem[ expando ] || (elem[ expando ] = {});
5846 if ( (oldCache = outerCache[ dir ]) &&
5847 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
5848
5849 return (newCache[ 2 ] = oldCache[ 2 ]);
5850 } else {
5851 outerCache[ dir ] = newCache;
5852
5853 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
5854 return true;
5855 }
5856 }
5857 }
5858 }
5859 }
5860 };
5861 }
5862
5863 function elementMatcher( matchers ) {
5864 return matchers.length > 1 ?
5865 function( elem, context, xml ) {
5866 var i = matchers.length;
5867 while ( i-- ) {
5868 if ( !matchers[i]( elem, context, xml ) ) {
5869 return false;
5870 }
5871 }
5872 return true;
5873 } :
5874 matchers[0];
5875 }
5876
5877 function multipleContexts( selector, contexts, results ) {
5878 var i = 0,
5879 len = contexts.length;
5880 for ( ; i < len; i++ ) {
5881 Sizzle( selector, contexts[i], results );
5882 }
5883 return results;
5884 }
5885
5886 function condense( unmatched, map, filter, context, xml ) {
5887 var elem,
5888 newUnmatched = [],
5889 i = 0,
5890 len = unmatched.length,
5891 mapped = map != null;
5892
5893 for ( ; i < len; i++ ) {
5894 if ( (elem = unmatched[i]) ) {
5895 if ( !filter || filter( elem, context, xml ) ) {
5896 newUnmatched.push( elem );
5897 if ( mapped ) {
5898 map.push( i );
5899 }
5900 }
5901 }
5902 }
5903
5904 return newUnmatched;
5905 }
5906
5907 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5908 if ( postFilter && !postFilter[ expando ] ) {
5909 postFilter = setMatcher( postFilter );
5910 }
5911 if ( postFinder && !postFinder[ expando ] ) {
5912 postFinder = setMatcher( postFinder, postSelector );
5913 }
5914 return markFunction(function( seed, results, context, xml ) {
5915 var temp, i, elem,
5916 preMap = [],
5917 postMap = [],
5918 preexisting = results.length,
5919
5920 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5921
5922 matcherIn = preFilter && ( seed || !selector ) ?
5923 condense( elems, preMap, preFilter, context, xml ) :
5924 elems,
5925
5926 matcherOut = matcher ?
5927 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5928
5929 [] :
5930
5931 results :
5932 matcherIn;
5933
5934 if ( matcher ) {
5935 matcher( matcherIn, matcherOut, context, xml );
5936 }
5937
5938 if ( postFilter ) {
5939 temp = condense( matcherOut, postMap );
5940 postFilter( temp, [], context, xml );
5941
5942 i = temp.length;
5943 while ( i-- ) {
5944 if ( (elem = temp[i]) ) {
5945 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5946 }
5947 }
5948 }
5949
5950 if ( seed ) {
5951 if ( postFinder || preFilter ) {
5952 if ( postFinder ) {
5953 temp = [];
5954 i = matcherOut.length;
5955 while ( i-- ) {
5956 if ( (elem = matcherOut[i]) ) {
5957 temp.push( (matcherIn[i] = elem) );
5958 }
5959 }
5960 postFinder( null, (matcherOut = []), temp, xml );
5961 }
5962
5963 i = matcherOut.length;
5964 while ( i-- ) {
5965 if ( (elem = matcherOut[i]) &&
5966 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5967
5968 seed[temp] = !(results[temp] = elem);
5969 }
5970 }
5971 }
5972
5973 } else {
5974 matcherOut = condense(
5975 matcherOut === results ?
5976 matcherOut.splice( preexisting, matcherOut.length ) :
5977 matcherOut
5978 );
5979 if ( postFinder ) {
5980 postFinder( null, results, matcherOut, xml );
5981 } else {
5982 push.apply( results, matcherOut );
5983 }
5984 }
5985 });
5986 }
5987
5988 function matcherFromTokens( tokens ) {
5989 var checkContext, matcher, j,
5990 len = tokens.length,
5991 leadingRelative = Expr.relative[ tokens[0].type ],
5992 implicitRelative = leadingRelative || Expr.relative[" "],
5993 i = leadingRelative ? 1 : 0,
5994
5995 matchContext = addCombinator( function( elem ) {
5996 return elem === checkContext;
5997 }, implicitRelative, true ),
5998 matchAnyContext = addCombinator( function( elem ) {
5999 return indexOf.call( checkContext, elem ) > -1;
6000 }, implicitRelative, true ),
6001 matchers = [ function( elem, context, xml ) {
6002 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
6003 (checkContext = context).nodeType ?
6004 matchContext( elem, context, xml ) :
6005 matchAnyContext( elem, context, xml ) );
6006 } ];
6007
6008 for ( ; i < len; i++ ) {
6009 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
6010 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
6011 } else {
6012 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
6013
6014 if ( matcher[ expando ] ) {
6015 j = ++i;
6016 for ( ; j < len; j++ ) {
6017 if ( Expr.relative[ tokens[j].type ] ) {
6018 break;
6019 }
6020 }
6021 return setMatcher(
6022 i > 1 && elementMatcher( matchers ),
6023 i > 1 && toSelector(
6024 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
6025 ).replace( rtrim, "$1" ),
6026 matcher,
6027 i < j && matcherFromTokens( tokens.slice( i, j ) ),
6028 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
6029 j < len && toSelector( tokens )
6030 );
6031 }
6032 matchers.push( matcher );
6033 }
6034 }
6035
6036 return elementMatcher( matchers );
6037 }
6038
6039 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
6040 var bySet = setMatchers.length > 0,
6041 byElement = elementMatchers.length > 0,
6042 superMatcher = function( seed, context, xml, results, outermost ) {
6043 var elem, j, matcher,
6044 matchedCount = 0,
6045 i = "0",
6046 unmatched = seed && [],
6047 setMatched = [],
6048 contextBackup = outermostContext,
6049 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
6050 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
6051 len = elems.length;
6052
6053 if ( outermost ) {
6054 outermostContext = context !== document && context;
6055 }
6056
6057 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
6058 if ( byElement && elem ) {
6059 j = 0;
6060 while ( (matcher = elementMatchers[j++]) ) {
6061 if ( matcher( elem, context, xml ) ) {
6062 results.push( elem );
6063 break;
6064 }
6065 }
6066 if ( outermost ) {
6067 dirruns = dirrunsUnique;
6068 }
6069 }
6070
6071 if ( bySet ) {
6072 if ( (elem = !matcher && elem) ) {
6073 matchedCount--;
6074 }
6075
6076 if ( seed ) {
6077 unmatched.push( elem );
6078 }
6079 }
6080 }
6081
6082 matchedCount += i;
6083 if ( bySet && i !== matchedCount ) {
6084 j = 0;
6085 while ( (matcher = setMatchers[j++]) ) {
6086 matcher( unmatched, setMatched, context, xml );
6087 }
6088
6089 if ( seed ) {
6090 if ( matchedCount > 0 ) {
6091 while ( i-- ) {
6092 if ( !(unmatched[i] || setMatched[i]) ) {
6093 setMatched[i] = pop.call( results );
6094 }
6095 }
6096 }
6097
6098 setMatched = condense( setMatched );
6099 }
6100
6101 push.apply( results, setMatched );
6102
6103 if ( outermost && !seed && setMatched.length > 0 &&
6104 ( matchedCount + setMatchers.length ) > 1 ) {
6105
6106 Sizzle.uniqueSort( results );
6107 }
6108 }
6109
6110 if ( outermost ) {
6111 dirruns = dirrunsUnique;
6112 outermostContext = contextBackup;
6113 }
6114
6115 return unmatched;
6116 };
6117
6118 return bySet ?
6119 markFunction( superMatcher ) :
6120 superMatcher;
6121 }
6122
6123 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
6124 var i,
6125 setMatchers = [],
6126 elementMatchers = [],
6127 cached = compilerCache[ selector + " " ];
6128
6129 if ( !cached ) {
6130 if ( !match ) {
6131 match = tokenize( selector );
6132 }
6133 i = match.length;
6134 while ( i-- ) {
6135 cached = matcherFromTokens( match[i] );
6136 if ( cached[ expando ] ) {
6137 setMatchers.push( cached );
6138 } else {
6139 elementMatchers.push( cached );
6140 }
6141 }
6142
6143 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
6144
6145 cached.selector = selector;
6146 }
6147 return cached;
6148 };
6149
6150 /**
6151 * A low-level selection function that works with Sizzle's compiled
6152 * selector functions
6153 * @param {String|Function} selector A selector or a pre-compiled
6154 * selector function built with Sizzle.compile
6155 * @param {Element} context
6156 * @param {Array} [results]
6157 * @param {Array} [seed] A set of elements to match against
6158 */
6159 select = Sizzle.select = function( selector, context, results, seed ) {
6160 var i, tokens, token, type, find,
6161 compiled = typeof selector === "function" && selector,
6162 match = !seed && tokenize( (selector = compiled.selector || selector) );
6163
6164 results = results || [];
6165
6166 if ( match.length === 1 ) {
6167
6168 tokens = match[0] = match[0].slice( 0 );
6169 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
6170 support.getById && context.nodeType === 9 && documentIsHTML &&
6171 Expr.relative[ tokens[1].type ] ) {
6172
6173 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
6174 if ( !context ) {
6175 return results;
6176
6177 } else if ( compiled ) {
6178 context = context.parentNode;
6179 }
6180
6181 selector = selector.slice( tokens.shift().value.length );
6182 }
6183
6184 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
6185 while ( i-- ) {
6186 token = tokens[i];
6187
6188 if ( Expr.relative[ (type = token.type) ] ) {
6189 break;
6190 }
6191 if ( (find = Expr.find[ type ]) ) {
6192 if ( (seed = find(
6193 token.matches[0].replace( runescape, funescape ),
6194 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
6195 )) ) {
6196
6197 tokens.splice( i, 1 );
6198 selector = seed.length && toSelector( tokens );
6199 if ( !selector ) {
6200 push.apply( results, seed );
6201 return results;
6202 }
6203
6204 break;
6205 }
6206 }
6207 }
6208 }
6209
6210 ( compiled || compile( selector, match ) )(
6211 seed,
6212 context,
6213 !documentIsHTML,
6214 results,
6215 rsibling.test( selector ) && testContext( context.parentNode ) || context
6216 );
6217 return results;
6218 };
6219
6220
6221 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
6222
6223 support.detectDuplicates = !!hasDuplicate;
6224
6225 setDocument();
6226
6227 support.sortDetached = assert(function( div1 ) {
6228 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
6229 });
6230
6231 if ( !assert(function( div ) {
6232 div.innerHTML = "<a href='#'></a>";
6233 return div.firstChild.getAttribute("href") === "#" ;
6234 }) ) {
6235 addHandle( "type|href|height|width", function( elem, name, isXML ) {
6236 if ( !isXML ) {
6237 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
6238 }
6239 });
6240 }
6241
6242 if ( !support.attributes || !assert(function( div ) {
6243 div.innerHTML = "<input/>";
6244 div.firstChild.setAttribute( "value", "" );
6245 return div.firstChild.getAttribute( "value" ) === "";
6246 }) ) {
6247 addHandle( "value", function( elem, name, isXML ) {
6248 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
6249 return elem.defaultValue;
6250 }
6251 });
6252 }
6253
6254 if ( !assert(function( div ) {
6255 return div.getAttribute("disabled") == null;
6256 }) ) {
6257 addHandle( booleans, function( elem, name, isXML ) {
6258 var val;
6259 if ( !isXML ) {
6260 return elem[ name ] === true ? name.toLowerCase() :
6261 (val = elem.getAttributeNode( name )) && val.specified ?
6262 val.value :
6263 null;
6264 }
6265 });
6266 }
6267
6268 if ( typeof define === "function" && define.amd ) {
6269 define(function() { return Sizzle; });
6270 } else if ( typeof module !== "undefined" && module.exports ) {
6271 module.exports = Sizzle;
6272 } else {
6273 window.Sizzle = Sizzle;
6274 }
6275
6276 })( window );
6277
6278 ;(function() {
6279 if (typeof Sizzle !== 'undefined') {
6280 return;
6281 }
6282
6283 if (typeof define !== 'undefined' && define.amd) {
6284 window.Sizzle = Prototype._actual_sizzle;
6285 window.define = Prototype._original_define;
6286 delete Prototype._actual_sizzle;
6287 delete Prototype._original_define;
6288 } else if (typeof module !== 'undefined' && module.exports) {
6289 window.Sizzle = module.exports;
6290 module.exports = {};
6291 }
6292 })();
6293
6294 ;(function(engine) {
6295 var extendElements = Prototype.Selector.extendElements;
6296
6297 function select(selector, scope) {
6298 return extendElements(engine(selector, scope || document));
6299 }
6300
6301 function match(element, selector) {
6302 return engine.matches(selector, [element]).length == 1;
6303 }
6304
6305 Prototype.Selector.engine = engine;
6306 Prototype.Selector.select = select;
6307 Prototype.Selector.match = match;
6308 })(Sizzle);
6309
6310 window.Sizzle = Prototype._original_property;
6311 delete Prototype._original_property;
6312
6313 var Form = {
6314 reset: function(form) {
6315 form = $(form);
6316 form.reset();
6317 return form;
6318 },
6319
6320 serializeElements: function(elements, options) {
6321 if (typeof options != 'object') options = { hash: !!options };
6322 else if (Object.isUndefined(options.hash)) options.hash = true;
6323 var key, value, submitted = false, submit = options.submit, accumulator, initial;
6324
6325 if (options.hash) {
6326 initial = {};
6327 accumulator = function(result, key, value) {
6328 if (key in result) {
6329 if (!Object.isArray(result[key])) result[key] = [result[key]];
6330 result[key] = result[key].concat(value);
6331 } else result[key] = value;
6332 return result;
6333 };
6334 } else {
6335 initial = '';
6336 accumulator = function(result, key, values) {
6337 if (!Object.isArray(values)) {values = [values];}
6338 if (!values.length) {return result;}
6339 var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');
6340 return result + (result ? "&" : "") + values.map(function (value) {
6341 value = value.gsub(/(\r)?\n/, '\r\n');
6342 value = encodeURIComponent(value);
6343 value = value.gsub(/%20/, '+');
6344 return encodedKey + "=" + value;
6345 }).join("&");
6346 };
6347 }
6348
6349 return elements.inject(initial, function(result, element) {
6350 if (!element.disabled && element.name) {
6351 key = element.name; value = $(element).getValue();
6352 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
6353 submit !== false && (!submit || key == submit) && (submitted = true)))) {
6354 result = accumulator(result, key, value);
6355 }
6356 }
6357 return result;
6358 });
6359 }
6360 };
6361
6362 Form.Methods = {
6363 serialize: function(form, options) {
6364 return Form.serializeElements(Form.getElements(form), options);
6365 },
6366
6367
6368 getElements: function(form) {
6369 var elements = $(form).getElementsByTagName('*');
6370 var element, results = [], serializers = Form.Element.Serializers;
6371
6372 for (var i = 0; element = elements[i]; i++) {
6373 if (serializers[element.tagName.toLowerCase()])
6374 results.push(Element.extend(element));
6375 }
6376 return results;
6377 },
6378
6379 getInputs: function(form, typeName, name) {
6380 form = $(form);
6381 var inputs = form.getElementsByTagName('input');
6382
6383 if (!typeName && !name) return $A(inputs).map(Element.extend);
6384
6385 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
6386 var input = inputs[i];
6387 if ((typeName && input.type != typeName) || (name && input.name != name))
6388 continue;
6389 matchingInputs.push(Element.extend(input));
6390 }
6391
6392 return matchingInputs;
6393 },
6394
6395 disable: function(form) {
6396 form = $(form);
6397 Form.getElements(form).invoke('disable');
6398 return form;
6399 },
6400
6401 enable: function(form) {
6402 form = $(form);
6403 Form.getElements(form).invoke('enable');
6404 return form;
6405 },
6406
6407 findFirstElement: function(form) {
6408 var elements = $(form).getElements().findAll(function(element) {
6409 return 'hidden' != element.type && !element.disabled;
6410 });
6411 var firstByIndex = elements.findAll(function(element) {
6412 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
6413 }).sortBy(function(element) { return element.tabIndex }).first();
6414
6415 return firstByIndex ? firstByIndex : elements.find(function(element) {
6416 return /^(?:input|select|textarea)$/i.test(element.tagName);
6417 });
6418 },
6419
6420 focusFirstElement: function(form) {
6421 form = $(form);
6422 var element = form.findFirstElement();
6423 if (element) element.activate();
6424 return form;
6425 },
6426
6427 request: function(form, options) {
6428 form = $(form), options = Object.clone(options || { });
6429
6430 var params = options.parameters, action = form.readAttribute('action') || '';
6431 if (action.blank()) action = window.location.href;
6432 options.parameters = form.serialize(true);
6433
6434 if (params) {
6435 if (Object.isString(params)) params = params.toQueryParams();
6436 Object.extend(options.parameters, params);
6437 }
6438
6439 if (form.hasAttribute('method') && !options.method)
6440 options.method = form.method;
6441
6442 return new Ajax.Request(action, options);
6443 }
6444 };
6445
6446 /*--------------------------------------------------------------------------*/
6447
6448
6449 Form.Element = {
6450 focus: function(element) {
6451 $(element).focus();
6452 return element;
6453 },
6454
6455 select: function(element) {
6456 $(element).select();
6457 return element;
6458 }
6459 };
6460
6461 Form.Element.Methods = {
6462
6463 serialize: function(element) {
6464 element = $(element);
6465 if (!element.disabled && element.name) {
6466 var value = element.getValue();
6467 if (value != undefined) {
6468 var pair = { };
6469 pair[element.name] = value;
6470 return Object.toQueryString(pair);
6471 }
6472 }
6473 return '';
6474 },
6475
6476 getValue: function(element) {
6477 element = $(element);
6478 var method = element.tagName.toLowerCase();
6479 return Form.Element.Serializers[method](element);
6480 },
6481
6482 setValue: function(element, value) {
6483 element = $(element);
6484 var method = element.tagName.toLowerCase();
6485 Form.Element.Serializers[method](element, value);
6486 return element;
6487 },
6488
6489 clear: function(element) {
6490 $(element).value = '';
6491 return element;
6492 },
6493
6494 present: function(element) {
6495 return $(element).value != '';
6496 },
6497
6498 activate: function(element) {
6499 element = $(element);
6500 try {
6501 element.focus();
6502 if (element.select && (element.tagName.toLowerCase() != 'input' ||
6503 !(/^(?:button|reset|submit)$/i.test(element.type))))
6504 element.select();
6505 } catch (e) { }
6506 return element;
6507 },
6508
6509 disable: function(element) {
6510 element = $(element);
6511 element.disabled = true;
6512 return element;
6513 },
6514
6515 enable: function(element) {
6516 element = $(element);
6517 element.disabled = false;
6518 return element;
6519 }
6520 };
6521
6522 /*--------------------------------------------------------------------------*/
6523
6524 var Field = Form.Element;
6525
6526 var $F = Form.Element.Methods.getValue;
6527
6528 /*--------------------------------------------------------------------------*/
6529
6530 Form.Element.Serializers = (function() {
6531 function input(element, value) {
6532 switch (element.type.toLowerCase()) {
6533 case 'checkbox':
6534 case 'radio':
6535 return inputSelector(element, value);
6536 default:
6537 return valueSelector(element, value);
6538 }
6539 }
6540
6541 function inputSelector(element, value) {
6542 if (Object.isUndefined(value))
6543 return element.checked ? element.value : null;
6544 else element.checked = !!value;
6545 }
6546
6547 function valueSelector(element, value) {
6548 if (Object.isUndefined(value)) return element.value;
6549 else element.value = value;
6550 }
6551
6552 function select(element, value) {
6553 if (Object.isUndefined(value))
6554 return (element.type === 'select-one' ? selectOne : selectMany)(element);
6555
6556 var opt, currentValue, single = !Object.isArray(value);
6557 for (var i = 0, length = element.length; i < length; i++) {
6558 opt = element.options[i];
6559 currentValue = this.optionValue(opt);
6560 if (single) {
6561 if (currentValue == value) {
6562 opt.selected = true;
6563 return;
6564 }
6565 }
6566 else opt.selected = value.include(currentValue);
6567 }
6568 }
6569
6570 function selectOne(element) {
6571 var index = element.selectedIndex;
6572 return index >= 0 ? optionValue(element.options[index]) : null;
6573 }
6574
6575 function selectMany(element) {
6576 var values, length = element.length;
6577 if (!length) return null;
6578
6579 for (var i = 0, values = []; i < length; i++) {
6580 var opt = element.options[i];
6581 if (opt.selected) values.push(optionValue(opt));
6582 }
6583 return values;
6584 }
6585
6586 function optionValue(opt) {
6587 return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
6588 }
6589
6590 return {
6591 input: input,
6592 inputSelector: inputSelector,
6593 textarea: valueSelector,
6594 select: select,
6595 selectOne: selectOne,
6596 selectMany: selectMany,
6597 optionValue: optionValue,
6598 button: valueSelector
6599 };
6600 })();
6601
6602 /*--------------------------------------------------------------------------*/
6603
6604
6605 Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
6606 initialize: function($super, element, frequency, callback) {
6607 $super(callback, frequency);
6608 this.element = $(element);
6609 this.lastValue = this.getValue();
6610 },
6611
6612 execute: function() {
6613 var value = this.getValue();
6614 if (Object.isString(this.lastValue) && Object.isString(value) ?
6615 this.lastValue != value : String(this.lastValue) != String(value)) {
6616 this.callback(this.element, value);
6617 this.lastValue = value;
6618 }
6619 }
6620 });
6621
6622 Form.Element.Observer = Class.create(Abstract.TimedObserver, {
6623 getValue: function() {
6624 return Form.Element.getValue(this.element);
6625 }
6626 });
6627
6628 Form.Observer = Class.create(Abstract.TimedObserver, {
6629 getValue: function() {
6630 return Form.serialize(this.element);
6631 }
6632 });
6633
6634 /*--------------------------------------------------------------------------*/
6635
6636 Abstract.EventObserver = Class.create({
6637 initialize: function(element, callback) {
6638 this.element = $(element);
6639 this.callback = callback;
6640
6641 this.lastValue = this.getValue();
6642 if (this.element.tagName.toLowerCase() == 'form')
6643 this.registerFormCallbacks();
6644 else
6645 this.registerCallback(this.element);
6646 },
6647
6648 onElementEvent: function() {
6649 var value = this.getValue();
6650 if (this.lastValue != value) {
6651 this.callback(this.element, value);
6652 this.lastValue = value;
6653 }
6654 },
6655
6656 registerFormCallbacks: function() {
6657 Form.getElements(this.element).each(this.registerCallback, this);
6658 },
6659
6660 registerCallback: function(element) {
6661 if (element.type) {
6662 switch (element.type.toLowerCase()) {
6663 case 'checkbox':
6664 case 'radio':
6665 Event.observe(element, 'click', this.onElementEvent.bind(this));
6666 break;
6667 default:
6668 Event.observe(element, 'change', this.onElementEvent.bind(this));
6669 break;
6670 }
6671 }
6672 }
6673 });
6674
6675 Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
6676 getValue: function() {
6677 return Form.Element.getValue(this.element);
6678 }
6679 });
6680
6681 Form.EventObserver = Class.create(Abstract.EventObserver, {
6682 getValue: function() {
6683 return Form.serialize(this.element);
6684 }
6685 });
6686 (function(GLOBAL) {
6687 var DIV = document.createElement('div');
6688 var docEl = document.documentElement;
6689 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
6690 && 'onmouseleave' in docEl;
6691
6692 var Event = {
6693 KEY_BACKSPACE: 8,
6694 KEY_TAB: 9,
6695 KEY_RETURN: 13,
6696 KEY_ESC: 27,
6697 KEY_LEFT: 37,
6698 KEY_UP: 38,
6699 KEY_RIGHT: 39,
6700 KEY_DOWN: 40,
6701 KEY_DELETE: 46,
6702 KEY_HOME: 36,
6703 KEY_END: 35,
6704 KEY_PAGEUP: 33,
6705 KEY_PAGEDOWN: 34,
6706 KEY_INSERT: 45
6707 };
6708
6709
6710 var isIELegacyEvent = function(event) { return false; };
6711
6712 if (window.attachEvent) {
6713 if (window.addEventListener) {
6714 isIELegacyEvent = function(event) {
6715 return !(event instanceof window.Event);
6716 };
6717 } else {
6718 isIELegacyEvent = function(event) { return true; };
6719 }
6720 }
6721
6722 var _isButton;
6723
6724 function _isButtonForDOMEvents(event, code) {
6725 return event.which ? (event.which === code + 1) : (event.button === code);
6726 }
6727
6728 var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
6729 function _isButtonForLegacyEvents(event, code) {
6730 return event.button === legacyButtonMap[code];
6731 }
6732
6733 function _isButtonForWebKit(event, code) {
6734 switch (code) {
6735 case 0: return event.which == 1 && !event.metaKey;
6736 case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
6737 case 2: return event.which == 3;
6738 default: return false;
6739 }
6740 }
6741
6742 if (window.attachEvent) {
6743 if (!window.addEventListener) {
6744 _isButton = _isButtonForLegacyEvents;
6745 } else {
6746 _isButton = function(event, code) {
6747 return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
6748 _isButtonForDOMEvents(event, code);
6749 }
6750 }
6751 } else if (Prototype.Browser.WebKit) {
6752 _isButton = _isButtonForWebKit;
6753 } else {
6754 _isButton = _isButtonForDOMEvents;
6755 }
6756
6757 function isLeftClick(event) { return _isButton(event, 0) }
6758
6759 function isMiddleClick(event) { return _isButton(event, 1) }
6760
6761 function isRightClick(event) { return _isButton(event, 2) }
6762
6763 function element(event) {
6764 return Element.extend(_element(event));
6765 }
6766
6767 function _element(event) {
6768 event = Event.extend(event);
6769
6770 var node = event.target, type = event.type,
6771 currentTarget = event.currentTarget;
6772
6773 if (currentTarget && currentTarget.tagName) {
6774 if (type === 'load' || type === 'error' ||
6775 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
6776 && currentTarget.type === 'radio'))
6777 node = currentTarget;
6778 }
6779
6780 return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;
6781 }
6782
6783 function findElement(event, expression) {
6784 var element = _element(event), selector = Prototype.Selector;
6785 if (!expression) return Element.extend(element);
6786 while (element) {
6787 if (Object.isElement(element) && selector.match(element, expression))
6788 return Element.extend(element);
6789 element = element.parentNode;
6790 }
6791 }
6792
6793 function pointer(event) {
6794 return { x: pointerX(event), y: pointerY(event) };
6795 }
6796
6797 function pointerX(event) {
6798 var docElement = document.documentElement,
6799 body = document.body || { scrollLeft: 0 };
6800
6801 return event.pageX || (event.clientX +
6802 (docElement.scrollLeft || body.scrollLeft) -
6803 (docElement.clientLeft || 0));
6804 }
6805
6806 function pointerY(event) {
6807 var docElement = document.documentElement,
6808 body = document.body || { scrollTop: 0 };
6809
6810 return event.pageY || (event.clientY +
6811 (docElement.scrollTop || body.scrollTop) -
6812 (docElement.clientTop || 0));
6813 }
6814
6815
6816 function stop(event) {
6817 Event.extend(event);
6818 event.preventDefault();
6819 event.stopPropagation();
6820
6821 event.stopped = true;
6822 }
6823
6824
6825 Event.Methods = {
6826 isLeftClick: isLeftClick,
6827 isMiddleClick: isMiddleClick,
6828 isRightClick: isRightClick,
6829
6830 element: element,
6831 findElement: findElement,
6832
6833 pointer: pointer,
6834 pointerX: pointerX,
6835 pointerY: pointerY,
6836
6837 stop: stop
6838 };
6839
6840 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
6841 m[name] = Event.Methods[name].methodize();
6842 return m;
6843 });
6844
6845 if (window.attachEvent) {
6846 function _relatedTarget(event) {
6847 var element;
6848 switch (event.type) {
6849 case 'mouseover':
6850 case 'mouseenter':
6851 element = event.fromElement;
6852 break;
6853 case 'mouseout':
6854 case 'mouseleave':
6855 element = event.toElement;
6856 break;
6857 default:
6858 return null;
6859 }
6860 return Element.extend(element);
6861 }
6862
6863 var additionalMethods = {
6864 stopPropagation: function() { this.cancelBubble = true },
6865 preventDefault: function() { this.returnValue = false },
6866 inspect: function() { return '[object Event]' }
6867 };
6868
6869 Event.extend = function(event, element) {
6870 if (!event) return false;
6871
6872 if (!isIELegacyEvent(event)) return event;
6873
6874 if (event._extendedByPrototype) return event;
6875 event._extendedByPrototype = Prototype.emptyFunction;
6876
6877 var pointer = Event.pointer(event);
6878
6879 Object.extend(event, {
6880 target: event.srcElement || element,
6881 relatedTarget: _relatedTarget(event),
6882 pageX: pointer.x,
6883 pageY: pointer.y
6884 });
6885
6886 Object.extend(event, methods);
6887 Object.extend(event, additionalMethods);
6888
6889 return event;
6890 };
6891 } else {
6892 Event.extend = Prototype.K;
6893 }
6894
6895 if (window.addEventListener) {
6896 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
6897 Object.extend(Event.prototype, methods);
6898 }
6899
6900 var EVENT_TRANSLATIONS = {
6901 mouseenter: 'mouseover',
6902 mouseleave: 'mouseout'
6903 };
6904
6905 function getDOMEventName(eventName) {
6906 return EVENT_TRANSLATIONS[eventName] || eventName;
6907 }
6908
6909 if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)
6910 getDOMEventName = Prototype.K;
6911
6912 function getUniqueElementID(element) {
6913 if (element === window) return 0;
6914
6915 if (typeof element._prototypeUID === 'undefined')
6916 element._prototypeUID = Element.Storage.UID++;
6917 return element._prototypeUID;
6918 }
6919
6920 function getUniqueElementID_IE(element) {
6921 if (element === window) return 0;
6922 if (element == document) return 1;
6923 return element.uniqueID;
6924 }
6925
6926 if ('uniqueID' in DIV)
6927 getUniqueElementID = getUniqueElementID_IE;
6928
6929 function isCustomEvent(eventName) {
6930 return eventName.include(':');
6931 }
6932
6933 Event._isCustomEvent = isCustomEvent;
6934
6935 function getOrCreateRegistryFor(element, uid) {
6936 var CACHE = GLOBAL.Event.cache;
6937 if (Object.isUndefined(uid))
6938 uid = getUniqueElementID(element);
6939 if (!CACHE[uid]) CACHE[uid] = { element: element };
6940 return CACHE[uid];
6941 }
6942
6943 function destroyRegistryForElement(element, uid) {
6944 if (Object.isUndefined(uid))
6945 uid = getUniqueElementID(element);
6946 delete GLOBAL.Event.cache[uid];
6947 }
6948
6949
6950 function register(element, eventName, handler) {
6951 var registry = getOrCreateRegistryFor(element);
6952 if (!registry[eventName]) registry[eventName] = [];
6953 var entries = registry[eventName];
6954
6955 var i = entries.length;
6956 while (i--)
6957 if (entries[i].handler === handler) return null;
6958
6959 var uid = getUniqueElementID(element);
6960 var responder = GLOBAL.Event._createResponder(uid, eventName, handler);
6961 var entry = {
6962 responder: responder,
6963 handler: handler
6964 };
6965
6966 entries.push(entry);
6967 return entry;
6968 }
6969
6970 function unregister(element, eventName, handler) {
6971 var registry = getOrCreateRegistryFor(element);
6972 var entries = registry[eventName] || [];
6973
6974 var i = entries.length, entry;
6975 while (i--) {
6976 if (entries[i].handler === handler) {
6977 entry = entries[i];
6978 break;
6979 }
6980 }
6981
6982 if (entry) {
6983 var index = entries.indexOf(entry);
6984 entries.splice(index, 1);
6985 }
6986
6987 if (entries.length === 0) {
6988 delete registry[eventName];
6989 if (Object.keys(registry).length === 1 && ('element' in registry))
6990 destroyRegistryForElement(element);
6991 }
6992
6993 return entry;
6994 }
6995
6996
6997 function observe(element, eventName, handler) {
6998 element = $(element);
6999 var entry = register(element, eventName, handler);
7000
7001 if (entry === null) return element;
7002
7003 var responder = entry.responder;
7004 if (isCustomEvent(eventName))
7005 observeCustomEvent(element, eventName, responder);
7006 else
7007 observeStandardEvent(element, eventName, responder);
7008
7009 return element;
7010 }
7011
7012 function observeStandardEvent(element, eventName, responder) {
7013 var actualEventName = getDOMEventName(eventName);
7014 if (element.addEventListener) {
7015 element.addEventListener(actualEventName, responder, false);
7016 } else {
7017 element.attachEvent('on' + actualEventName, responder);
7018 }
7019 }
7020
7021 function observeCustomEvent(element, eventName, responder) {
7022 if (element.addEventListener) {
7023 element.addEventListener('dataavailable', responder, false);
7024 } else {
7025 element.attachEvent('ondataavailable', responder);
7026 element.attachEvent('onlosecapture', responder);
7027 }
7028 }
7029
7030 function stopObserving(element, eventName, handler) {
7031 element = $(element);
7032 var handlerGiven = !Object.isUndefined(handler),
7033 eventNameGiven = !Object.isUndefined(eventName);
7034
7035 if (!eventNameGiven && !handlerGiven) {
7036 stopObservingElement(element);
7037 return element;
7038 }
7039
7040 if (!handlerGiven) {
7041 stopObservingEventName(element, eventName);
7042 return element;
7043 }
7044
7045 var entry = unregister(element, eventName, handler);
7046
7047 if (!entry) return element;
7048 removeEvent(element, eventName, entry.responder);
7049 return element;
7050 }
7051
7052 function stopObservingStandardEvent(element, eventName, responder) {
7053 var actualEventName = getDOMEventName(eventName);
7054 if (element.removeEventListener) {
7055 element.removeEventListener(actualEventName, responder, false);
7056 } else {
7057 element.detachEvent('on' + actualEventName, responder);
7058 }
7059 }
7060
7061 function stopObservingCustomEvent(element, eventName, responder) {
7062 if (element.removeEventListener) {
7063 element.removeEventListener('dataavailable', responder, false);
7064 } else {
7065 element.detachEvent('ondataavailable', responder);
7066 element.detachEvent('onlosecapture', responder);
7067 }
7068 }
7069
7070
7071
7072 function stopObservingElement(element) {
7073 var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];
7074 if (!registry) return;
7075
7076 destroyRegistryForElement(element, uid);
7077
7078 var entries, i;
7079 for (var eventName in registry) {
7080 if (eventName === 'element') continue;
7081
7082 entries = registry[eventName];
7083 i = entries.length;
7084 while (i--)
7085 removeEvent(element, eventName, entries[i].responder);
7086 }
7087 }
7088
7089 function stopObservingEventName(element, eventName) {
7090 var registry = getOrCreateRegistryFor(element);
7091 var entries = registry[eventName];
7092 if (entries) {
7093 delete registry[eventName];
7094 }
7095
7096 entries = entries || [];
7097
7098 var i = entries.length;
7099 while (i--)
7100 removeEvent(element, eventName, entries[i].responder);
7101
7102 for (var name in registry) {
7103 if (name === 'element') continue;
7104 return; // There is another registered event
7105 }
7106
7107 destroyRegistryForElement(element);
7108 }
7109
7110
7111 function removeEvent(element, eventName, handler) {
7112 if (isCustomEvent(eventName))
7113 stopObservingCustomEvent(element, eventName, handler);
7114 else
7115 stopObservingStandardEvent(element, eventName, handler);
7116 }
7117
7118
7119
7120 function getFireTarget(element) {
7121 if (element !== document) return element;
7122 if (document.createEvent && !element.dispatchEvent)
7123 return document.documentElement;
7124 return element;
7125 }
7126
7127 function fire(element, eventName, memo, bubble) {
7128 element = getFireTarget($(element));
7129 if (Object.isUndefined(bubble)) bubble = true;
7130 memo = memo || {};
7131
7132 var event = fireEvent(element, eventName, memo, bubble);
7133 return Event.extend(event);
7134 }
7135
7136 function fireEvent_DOM(element, eventName, memo, bubble) {
7137 var event = document.createEvent('HTMLEvents');
7138 event.initEvent('dataavailable', bubble, true);
7139
7140 event.eventName = eventName;
7141 event.memo = memo;
7142
7143 element.dispatchEvent(event);
7144 return event;
7145 }
7146
7147 function fireEvent_IE(element, eventName, memo, bubble) {
7148 var event = document.createEventObject();
7149 event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
7150
7151 event.eventName = eventName;
7152 event.memo = memo;
7153
7154 element.fireEvent(event.eventType, event);
7155 return event;
7156 }
7157
7158 var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;
7159
7160
7161
7162 Event.Handler = Class.create({
7163 initialize: function(element, eventName, selector, callback) {
7164 this.element = $(element);
7165 this.eventName = eventName;
7166 this.selector = selector;
7167 this.callback = callback;
7168 this.handler = this.handleEvent.bind(this);
7169 },
7170
7171
7172 start: function() {
7173 Event.observe(this.element, this.eventName, this.handler);
7174 return this;
7175 },
7176
7177 stop: function() {
7178 Event.stopObserving(this.element, this.eventName, this.handler);
7179 return this;
7180 },
7181
7182 handleEvent: function(event) {
7183 var element = Event.findElement(event, this.selector);
7184 if (element) this.callback.call(this.element, event, element);
7185 }
7186 });
7187
7188 function on(element, eventName, selector, callback) {
7189 element = $(element);
7190 if (Object.isFunction(selector) && Object.isUndefined(callback)) {
7191 callback = selector, selector = null;
7192 }
7193
7194 return new Event.Handler(element, eventName, selector, callback).start();
7195 }
7196
7197 Object.extend(Event, Event.Methods);
7198
7199 Object.extend(Event, {
7200 fire: fire,
7201 observe: observe,
7202 stopObserving: stopObserving,
7203 p_on: on
7204 });
7205
7206 Element.addMethods({
7207 fire: fire,
7208
7209 observe: observe,
7210
7211 stopObserving: stopObserving,
7212
7213 p_on: on
7214 });
7215
7216 Object.extend(document, {
7217 fire: fire.methodize(),
7218
7219 observe: observe.methodize(),
7220
7221 stopObserving: stopObserving.methodize(),
7222
7223 p_on: on.methodize(),
7224
7225 loaded: false
7226 });
7227
7228 if (GLOBAL.Event) Object.extend(window.Event, Event);
7229 else GLOBAL.Event = Event;
7230
7231 GLOBAL.Event.cache = {};
7232
7233 function destroyCache_IE() {
7234 GLOBAL.Event.cache = null;
7235 }
7236
7237 if (window.attachEvent)
7238 window.attachEvent('onunload', destroyCache_IE);
7239
7240 DIV = null;
7241 docEl = null;
7242 })(this);
7243
7244 (function(GLOBAL) {
7245 /* Code for creating leak-free event responders is based on work by
7246 John-David Dalton. */
7247
7248 var docEl = document.documentElement;
7249 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
7250 && 'onmouseleave' in docEl;
7251
7252 function isSimulatedMouseEnterLeaveEvent(eventName) {
7253 return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
7254 (eventName === 'mouseenter' || eventName === 'mouseleave');
7255 }
7256
7257 function createResponder(uid, eventName, handler) {
7258 if (Event._isCustomEvent(eventName))
7259 return createResponderForCustomEvent(uid, eventName, handler);
7260 if (isSimulatedMouseEnterLeaveEvent(eventName))
7261 return createMouseEnterLeaveResponder(uid, eventName, handler);
7262
7263 return function(event) {
7264 if (!Event.cache) return;
7265
7266 var element = Event.cache[uid].element;
7267 Event.extend(event, element);
7268 handler.call(element, event);
7269 };
7270 }
7271
7272 function createResponderForCustomEvent(uid, eventName, handler) {
7273 return function(event) {
7274 var cache = Event.cache[uid];
7275 var element = cache && cache.element;
7276
7277 if (Object.isUndefined(event.eventName))
7278 return false;
7279
7280 if (event.eventName !== eventName)
7281 return false;
7282
7283 Event.extend(event, element);
7284 handler.call(element, event);
7285 };
7286 }
7287
7288 function createMouseEnterLeaveResponder(uid, eventName, handler) {
7289 return function(event) {
7290 var element = Event.cache[uid].element;
7291
7292 Event.extend(event, element);
7293 var parent = event.relatedTarget;
7294
7295 while (parent && parent !== element) {
7296 try { parent = parent.parentNode; }
7297 catch(e) { parent = element; }
7298 }
7299
7300 if (parent === element) return;
7301 handler.call(element, event);
7302 }
7303 }
7304
7305 GLOBAL.Event._createResponder = createResponder;
7306 docEl = null;
7307 })(this);
7308
7309 (function(GLOBAL) {
7310 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
7311 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
7312
7313 var TIMER;
7314
7315 function fireContentLoadedEvent() {
7316 if (document.loaded) return;
7317 if (TIMER) window.clearTimeout(TIMER);
7318 document.loaded = true;
7319 document.fire('dom:loaded');
7320 }
7321
7322 function checkReadyState() {
7323 if (document.readyState === 'complete') {
7324 document.detachEvent('onreadystatechange', checkReadyState);
7325 fireContentLoadedEvent();
7326 }
7327 }
7328
7329 function pollDoScroll() {
7330 try {
7331 document.documentElement.doScroll('left');
7332 } catch (e) {
7333 TIMER = pollDoScroll.defer();
7334 return;
7335 }
7336
7337 fireContentLoadedEvent();
7338 }
7339
7340
7341 if (document.readyState === 'complete') {
7342 fireContentLoadedEvent();
7343 return;
7344 }
7345
7346 if (document.addEventListener) {
7347 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
7348 } else {
7349 document.attachEvent('onreadystatechange', checkReadyState);
7350 if (window == top) TIMER = pollDoScroll.defer();
7351 }
7352
7353 Event.observe(window, 'load', fireContentLoadedEvent);
7354 })(this);
7355
7356
7357 Element.addMethods();
7358 /*------------------------------- DEPRECATED -------------------------------*/
7359
7360 Hash.toQueryString = Object.toQueryString;
7361
7362 var Toggle = { display: Element.toggle };
7363
7364 Element.addMethods({
7365 childOf: Element.Methods.descendantOf
7366 });
7367
7368 var Insertion = {
7369 Before: function(element, content) {
7370 return Element.insert(element, {before:content});
7371 },
7372
7373 Top: function(element, content) {
7374 return Element.insert(element, {top:content});
7375 },
7376
7377 Bottom: function(element, content) {
7378 return Element.insert(element, {bottom:content});
7379 },
7380
7381 After: function(element, content) {
7382 return Element.insert(element, {after:content});
7383 }
7384 };
7385
7386 var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
7387
7388 var Position = {
7389 includeScrollOffsets: false,
7390
7391 prepare: function() {
7392 this.deltaX = window.pageXOffset
7393 || document.documentElement.scrollLeft
7394 || document.body.scrollLeft
7395 || 0;
7396 this.deltaY = window.pageYOffset
7397 || document.documentElement.scrollTop
7398 || document.body.scrollTop
7399 || 0;
7400 },
7401
7402 within: function(element, x, y) {
7403 if (this.includeScrollOffsets)
7404 return this.withinIncludingScrolloffsets(element, x, y);
7405 this.xcomp = x;
7406 this.ycomp = y;
7407 this.offset = Element.cumulativeOffset(element);
7408
7409 return (y >= this.offset[1] &&
7410 y < this.offset[1] + element.offsetHeight &&
7411 x >= this.offset[0] &&
7412 x < this.offset[0] + element.offsetWidth);
7413 },
7414
7415 withinIncludingScrolloffsets: function(element, x, y) {
7416 var offsetcache = Element.cumulativeScrollOffset(element);
7417
7418 this.xcomp = x + offsetcache[0] - this.deltaX;
7419 this.ycomp = y + offsetcache[1] - this.deltaY;
7420 this.offset = Element.cumulativeOffset(element);
7421
7422 return (this.ycomp >= this.offset[1] &&
7423 this.ycomp < this.offset[1] + element.offsetHeight &&
7424 this.xcomp >= this.offset[0] &&
7425 this.xcomp < this.offset[0] + element.offsetWidth);
7426 },
7427
7428 overlap: function(mode, element) {
7429 if (!mode) return 0;
7430 if (mode == 'vertical')
7431 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
7432 element.offsetHeight;
7433 if (mode == 'horizontal')
7434 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
7435 element.offsetWidth;
7436 },
7437
7438
7439 cumulativeOffset: Element.Methods.cumulativeOffset,
7440
7441 positionedOffset: Element.Methods.positionedOffset,
7442
7443 absolutize: function(element) {
7444 Position.prepare();
7445 return Element.absolutize(element);
7446 },
7447
7448 relativize: function(element) {
7449 Position.prepare();
7450 return Element.relativize(element);
7451 },
7452
7453 realOffset: Element.Methods.cumulativeScrollOffset,
7454
7455 offsetParent: Element.Methods.getOffsetParent,
7456
7457 page: Element.Methods.viewportOffset,
7458
7459 clone: function(source, target, options) {
7460 options = options || { };
7461 return Element.clonePosition(target, source, options);
7462 }
7463 };
7464
7465 /*--------------------------------------------------------------------------*/
7466
7467 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
7468 function iter(name) {
7469 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
7470 }
7471
7472 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
7473 function(element, className) {
7474 className = className.toString().strip();
7475 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
7476 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
7477 } : function(element, className) {
7478 className = className.toString().strip();
7479 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
7480 if (!classNames && !className) return elements;
7481
7482 var nodes = $(element).getElementsByTagName('*');
7483 className = ' ' + className + ' ';
7484
7485 for (var i = 0, child, cn; child = nodes[i]; i++) {
7486 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
7487 (classNames && classNames.all(function(name) {
7488 return !name.toString().blank() && cn.include(' ' + name + ' ');
7489 }))))
7490 elements.push(Element.extend(child));
7491 }
7492 return elements;
7493 };
7494
7495 return function(className, parentElement) {
7496 return $(parentElement || document.body).getElementsByClassName(className);
7497 };
7498 }(Element.Methods);
7499
7500 /*--------------------------------------------------------------------------*/
7501
7502 Element.ClassNames = Class.create();
7503 Element.ClassNames.prototype = {
7504 initialize: function(element) {
7505 this.element = $(element);
7506 },
7507
7508 _each: function(iterator, context) {
7509 this.element.className.split(/\s+/).select(function(name) {
7510 return name.length > 0;
7511 })._each(iterator, context);
7512 },
7513
7514 set: function(className) {
7515 this.element.className = className;
7516 },
7517
7518 add: function(classNameToAdd) {
7519 if (this.include(classNameToAdd)) return;
7520 this.set($A(this).concat(classNameToAdd).join(' '));
7521 },
7522
7523 remove: function(classNameToRemove) {
7524 if (!this.include(classNameToRemove)) return;
7525 this.set($A(this).without(classNameToRemove).join(' '));
7526 },
7527
7528 toString: function() {
7529 return $A(this).join(' ');
7530 }
7531 };
7532
7533 Object.extend(Element.ClassNames.prototype, Enumerable);
7534
7535 /*--------------------------------------------------------------------------*/
7536
7537 (function() {
7538 window.Selector = Class.create({
7539 initialize: function(expression) {
7540 this.expression = expression.strip();
7541 },
7542
7543 findElements: function(rootElement) {
7544 return Prototype.Selector.select(this.expression, rootElement);
7545 },
7546
7547 match: function(element) {
7548 return Prototype.Selector.match(element, this.expression);
7549 },
7550
7551 toString: function() {
7552 return this.expression;
7553 },
7554
7555 inspect: function() {
7556 return "#<Selector: " + this.expression + ">";
7557 }
7558 });
7559
7560 Object.extend(Selector, {
7561 matchElements: function(elements, expression) {
7562 var match = Prototype.Selector.match,
7563 results = [];
7564
7565 for (var i = 0, length = elements.length; i < length; i++) {
7566 var element = elements[i];
7567 if (match(element, expression)) {
7568 results.push(Element.extend(element));
7569 }
7570 }
7571 return results;
7572 },
7573
7574 findElement: function(elements, expression, index) {
7575 index = index || 0;
7576 var matchIndex = 0, element;
7577 for (var i = 0, length = elements.length; i < length; i++) {
7578 element = elements[i];
7579 if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
7580 return Element.extend(element);
7581 }
7582 }
7583 },
7584
7585 findChildElements: function(element, expressions) {
7586 var selector = expressions.toArray().join(', ');
7587 return Prototype.Selector.select(selector, element || document);
7588 }
7589 });
7590 })();