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