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