]> git.wh0rd.org - tt-rss.git/blob - lib/prototype.js
Revert "remove floIcon: bugs"
[tt-rss.git] / lib / prototype.js
1 // Modified document.on() to modified.p_on() to fix compatibility with Dojo -fox
2
3 /* Prototype JavaScript framework, version 1.7
4 * (c) 2005-2010 Sam Stephenson
5 *
6 * Prototype is freely distributable under the terms of an MIT-style license.
7 * For details, see the Prototype web site: http://www.prototypejs.org/
8 *
9 *--------------------------------------------------------------------------*/
10
11 var Prototype = {
12
13 Version: '1.7',
14
15 Browser: (function(){
16 var ua = navigator.userAgent;
17 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
18 return {
19 IE: !!window.attachEvent && !isOpera,
20 Opera: isOpera,
21 WebKit: ua.indexOf('AppleWebKit/') > -1,
22 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
23 MobileSafari: /Apple.*Mobile/.test(ua)
24 }
25 })(),
26
27 BrowserFeatures: {
28 XPath: !!document.evaluate,
29
30 SelectorsAPI: !!document.querySelector,
31
32 ElementExtensions: (function() {
33 var constructor = window.Element || window.HTMLElement;
34 return !!(constructor && constructor.prototype);
35 })(),
36 SpecificElementExtensions: (function() {
37 if (typeof window.HTMLDivElement !== 'undefined')
38 return true;
39
40 var div = document.createElement('div'),
41 form = document.createElement('form'),
42 isSupported = false;
43
44 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
45 isSupported = true;
46 }
47
48 div = form = null;
49
50 return isSupported;
51 })()
52 },
53
54 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
55 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
56
57 emptyFunction: function() { },
58
59 K: function(x) { return x }
60 };
61
62 if (Prototype.Browser.MobileSafari)
63 Prototype.BrowserFeatures.SpecificElementExtensions = false;
64
65
66 var Abstract = { };
67
68
69 var Try = {
70 these: function() {
71 var returnValue;
72
73 for (var i = 0, length = arguments.length; i < length; i++) {
74 var lambda = arguments[i];
75 try {
76 returnValue = lambda();
77 break;
78 } catch (e) { }
79 }
80
81 return returnValue;
82 }
83 };
84
85 /* Based on Alex Arnell's inheritance implementation. */
86
87 var Class = (function() {
88
89 var IS_DONTENUM_BUGGY = (function(){
90 for (var p in { toString: 1 }) {
91 if (p === 'toString') return false;
92 }
93 return true;
94 })();
95
96 function subclass() {};
97 function create() {
98 var parent = null, properties = $A(arguments);
99 if (Object.isFunction(properties[0]))
100 parent = properties.shift();
101
102 function klass() {
103 this.initialize.apply(this, arguments);
104 }
105
106 Object.extend(klass, Class.Methods);
107 klass.superclass = parent;
108 klass.subclasses = [];
109
110 if (parent) {
111 subclass.prototype = parent.prototype;
112 klass.prototype = new subclass;
113 parent.subclasses.push(klass);
114 }
115
116 for (var i = 0, length = properties.length; i < length; i++)
117 klass.addMethods(properties[i]);
118
119 if (!klass.prototype.initialize)
120 klass.prototype.initialize = Prototype.emptyFunction;
121
122 klass.prototype.constructor = klass;
123 return klass;
124 }
125
126 function addMethods(source) {
127 var ancestor = this.superclass && this.superclass.prototype,
128 properties = Object.keys(source);
129
130 if (IS_DONTENUM_BUGGY) {
131 if (source.toString != Object.prototype.toString)
132 properties.push("toString");
133 if (source.valueOf != Object.prototype.valueOf)
134 properties.push("valueOf");
135 }
136
137 for (var i = 0, length = properties.length; i < length; i++) {
138 var property = properties[i], value = source[property];
139 if (ancestor && Object.isFunction(value) &&
140 value.argumentNames()[0] == "$super") {
141 var method = value;
142 value = (function(m) {
143 return function() { return ancestor[m].apply(this, arguments); };
144 })(property).wrap(method);
145
146 value.valueOf = method.valueOf.bind(method);
147 value.toString = method.toString.bind(method);
148 }
149 this.prototype[property] = value;
150 }
151
152 return this;
153 }
154
155 return {
156 create: create,
157 Methods: {
158 addMethods: addMethods
159 }
160 };
161 })();
162 (function() {
163
164 var _toString = Object.prototype.toString,
165 NULL_TYPE = 'Null',
166 UNDEFINED_TYPE = 'Undefined',
167 BOOLEAN_TYPE = 'Boolean',
168 NUMBER_TYPE = 'Number',
169 STRING_TYPE = 'String',
170 OBJECT_TYPE = 'Object',
171 FUNCTION_CLASS = '[object Function]',
172 BOOLEAN_CLASS = '[object Boolean]',
173 NUMBER_CLASS = '[object Number]',
174 STRING_CLASS = '[object String]',
175 ARRAY_CLASS = '[object Array]',
176 DATE_CLASS = '[object Date]',
177 NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
178 typeof JSON.stringify === 'function' &&
179 JSON.stringify(0) === '0' &&
180 typeof JSON.stringify(Prototype.K) === 'undefined';
181
182 function Type(o) {
183 switch(o) {
184 case null: return NULL_TYPE;
185 case (void 0): return UNDEFINED_TYPE;
186 }
187 var type = typeof o;
188 switch(type) {
189 case 'boolean': return BOOLEAN_TYPE;
190 case 'number': return NUMBER_TYPE;
191 case 'string': return STRING_TYPE;
192 }
193 return OBJECT_TYPE;
194 }
195
196 function extend(destination, source) {
197 for (var property in source)
198 destination[property] = source[property];
199 return destination;
200 }
201
202 function inspect(object) {
203 try {
204 if (isUndefined(object)) return 'undefined';
205 if (object === null) return 'null';
206 return object.inspect ? object.inspect() : String(object);
207 } catch (e) {
208 if (e instanceof RangeError) return '...';
209 throw e;
210 }
211 }
212
213 function toJSON(value) {
214 return Str('', { '': value }, []);
215 }
216
217 function Str(key, holder, stack) {
218 var value = holder[key],
219 type = typeof value;
220
221 if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
222 value = value.toJSON(key);
223 }
224
225 var _class = _toString.call(value);
226
227 switch (_class) {
228 case NUMBER_CLASS:
229 case BOOLEAN_CLASS:
230 case STRING_CLASS:
231 value = value.valueOf();
232 }
233
234 switch (value) {
235 case null: return 'null';
236 case true: return 'true';
237 case false: return 'false';
238 }
239
240 type = typeof value;
241 switch (type) {
242 case 'string':
243 return value.inspect(true);
244 case 'number':
245 return isFinite(value) ? String(value) : 'null';
246 case 'object':
247
248 for (var i = 0, length = stack.length; i < length; i++) {
249 if (stack[i] === value) { throw new TypeError(); }
250 }
251 stack.push(value);
252
253 var partial = [];
254 if (_class === ARRAY_CLASS) {
255 for (var i = 0, length = value.length; i < length; i++) {
256 var str = Str(i, value, stack);
257 partial.push(typeof str === 'undefined' ? 'null' : str);
258 }
259 partial = '[' + partial.join(',') + ']';
260 } else {
261 var keys = Object.keys(value);
262 for (var i = 0, length = keys.length; i < length; i++) {
263 var key = keys[i], str = Str(key, value, stack);
264 if (typeof str !== "undefined") {
265 partial.push(key.inspect(true)+ ':' + str);
266 }
267 }
268 partial = '{' + partial.join(',') + '}';
269 }
270 stack.pop();
271 return partial;
272 }
273 }
274
275 function stringify(object) {
276 return JSON.stringify(object);
277 }
278
279 function toQueryString(object) {
280 return $H(object).toQueryString();
281 }
282
283 function toHTML(object) {
284 return object && object.toHTML ? object.toHTML() : String.interpret(object);
285 }
286
287 function keys(object) {
288 if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
289 var results = [];
290 for (var property in object) {
291 if (object.hasOwnProperty(property)) {
292 results.push(property);
293 }
294 }
295 return results;
296 }
297
298 function values(object) {
299 var results = [];
300 for (var property in object)
301 results.push(object[property]);
302 return results;
303 }
304
305 function clone(object) {
306 return extend({ }, object);
307 }
308
309 function isElement(object) {
310 return !!(object && object.nodeType == 1);
311 }
312
313 function isArray(object) {
314 return _toString.call(object) === ARRAY_CLASS;
315 }
316
317 var hasNativeIsArray = (typeof Array.isArray == 'function')
318 && Array.isArray([]) && !Array.isArray({});
319
320 if (hasNativeIsArray) {
321 isArray = Array.isArray;
322 }
323
324 function isHash(object) {
325 return object instanceof Hash;
326 }
327
328 function isFunction(object) {
329 return _toString.call(object) === FUNCTION_CLASS;
330 }
331
332 function isString(object) {
333 return _toString.call(object) === STRING_CLASS;
334 }
335
336 function isNumber(object) {
337 return _toString.call(object) === NUMBER_CLASS;
338 }
339
340 function isDate(object) {
341 return _toString.call(object) === DATE_CLASS;
342 }
343
344 function isUndefined(object) {
345 return typeof object === "undefined";
346 }
347
348 extend(Object, {
349 extend: extend,
350 inspect: inspect,
351 toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
352 toQueryString: toQueryString,
353 toHTML: toHTML,
354 keys: Object.keys || keys,
355 values: values,
356 clone: clone,
357 isElement: isElement,
358 isArray: isArray,
359 isHash: isHash,
360 isFunction: isFunction,
361 isString: isString,
362 isNumber: isNumber,
363 isDate: isDate,
364 isUndefined: isUndefined
365 });
366 })();
367 Object.extend(Function.prototype, (function() {
368 var slice = Array.prototype.slice;
369
370 function update(array, args) {
371 var arrayLength = array.length, length = args.length;
372 while (length--) array[arrayLength + length] = args[length];
373 return array;
374 }
375
376 function merge(array, args) {
377 array = slice.call(array, 0);
378 return update(array, args);
379 }
380
381 function argumentNames() {
382 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
383 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
384 .replace(/\s+/g, '').split(',');
385 return names.length == 1 && !names[0] ? [] : names;
386 }
387
388 function bind(context) {
389 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
390 var __method = this, args = slice.call(arguments, 1);
391 return function() {
392 var a = merge(args, arguments);
393 return __method.apply(context, a);
394 }
395 }
396
397 function bindAsEventListener(context) {
398 var __method = this, args = slice.call(arguments, 1);
399 return function(event) {
400 var a = update([event || window.event], args);
401 return __method.apply(context, a);
402 }
403 }
404
405 function curry() {
406 if (!arguments.length) return this;
407 var __method = this, args = slice.call(arguments, 0);
408 return function() {
409 var a = merge(args, arguments);
410 return __method.apply(this, a);
411 }
412 }
413
414 function delay(timeout) {
415 var __method = this, args = slice.call(arguments, 1);
416 timeout = timeout * 1000;
417 return window.setTimeout(function() {
418 return __method.apply(__method, args);
419 }, timeout);
420 }
421
422 function defer() {
423 var args = update([0.01], arguments);
424 return this.delay.apply(this, args);
425 }
426
427 function wrap(wrapper) {
428 var __method = this;
429 return function() {
430 var a = update([__method.bind(this)], arguments);
431 return wrapper.apply(this, a);
432 }
433 }
434
435 function methodize() {
436 if (this._methodized) return this._methodized;
437 var __method = this;
438 return this._methodized = function() {
439 var a = update([this], arguments);
440 return __method.apply(null, a);
441 };
442 }
443
444 return {
445 argumentNames: argumentNames,
446 bind: bind,
447 bindAsEventListener: bindAsEventListener,
448 curry: curry,
449 delay: delay,
450 defer: defer,
451 wrap: wrap,
452 methodize: methodize
453 }
454 })());
455
456
457
458 (function(proto) {
459
460
461 function toISOString() {
462 return this.getUTCFullYear() + '-' +
463 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
464 this.getUTCDate().toPaddedString(2) + 'T' +
465 this.getUTCHours().toPaddedString(2) + ':' +
466 this.getUTCMinutes().toPaddedString(2) + ':' +
467 this.getUTCSeconds().toPaddedString(2) + 'Z';
468 }
469
470
471 function toJSON() {
472 return this.toISOString();
473 }
474
475 if (!proto.toISOString) proto.toISOString = toISOString;
476 if (!proto.toJSON) proto.toJSON = toJSON;
477
478 })(Date.prototype);
479
480
481 RegExp.prototype.match = RegExp.prototype.test;
482
483 RegExp.escape = function(str) {
484 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
485 };
486 var PeriodicalExecuter = Class.create({
487 initialize: function(callback, frequency) {
488 this.callback = callback;
489 this.frequency = frequency;
490 this.currentlyExecuting = false;
491
492 this.registerCallback();
493 },
494
495 registerCallback: function() {
496 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
497 },
498
499 execute: function() {
500 this.callback(this);
501 },
502
503 stop: function() {
504 if (!this.timer) return;
505 clearInterval(this.timer);
506 this.timer = null;
507 },
508
509 onTimerEvent: function() {
510 if (!this.currentlyExecuting) {
511 try {
512 this.currentlyExecuting = true;
513 this.execute();
514 this.currentlyExecuting = false;
515 } catch(e) {
516 this.currentlyExecuting = false;
517 throw e;
518 }
519 }
520 }
521 });
522 Object.extend(String, {
523 interpret: function(value) {
524 return value == null ? '' : String(value);
525 },
526 specialChar: {
527 '\b': '\\b',
528 '\t': '\\t',
529 '\n': '\\n',
530 '\f': '\\f',
531 '\r': '\\r',
532 '\\': '\\\\'
533 }
534 });
535
536 Object.extend(String.prototype, (function() {
537 var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
538 typeof JSON.parse === 'function' &&
539 JSON.parse('{"test": true}').test;
540
541 function prepareReplacement(replacement) {
542 if (Object.isFunction(replacement)) return replacement;
543 var template = new Template(replacement);
544 return function(match) { return template.evaluate(match) };
545 }
546
547 function gsub(pattern, replacement) {
548 var result = '', source = this, match;
549 replacement = prepareReplacement(replacement);
550
551 if (Object.isString(pattern))
552 pattern = RegExp.escape(pattern);
553
554 if (!(pattern.length || pattern.source)) {
555 replacement = replacement('');
556 return replacement + source.split('').join(replacement) + replacement;
557 }
558
559 while (source.length > 0) {
560 if (match = source.match(pattern)) {
561 result += source.slice(0, match.index);
562 result += String.interpret(replacement(match));
563 source = source.slice(match.index + match[0].length);
564 } else {
565 result += source, source = '';
566 }
567 }
568 return result;
569 }
570
571 function sub(pattern, replacement, count) {
572 replacement = prepareReplacement(replacement);
573 count = Object.isUndefined(count) ? 1 : count;
574
575 return this.gsub(pattern, function(match) {
576 if (--count < 0) return match[0];
577 return replacement(match);
578 });
579 }
580
581 function scan(pattern, iterator) {
582 this.gsub(pattern, iterator);
583 return String(this);
584 }
585
586 function truncate(length, truncation) {
587 length = length || 30;
588 truncation = Object.isUndefined(truncation) ? '...' : truncation;
589 return this.length > length ?
590 this.slice(0, length - truncation.length) + truncation : String(this);
591 }
592
593 function strip() {
594 return this.replace(/^\s+/, '').replace(/\s+$/, '');
595 }
596
597 function stripTags() {
598 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
599 }
600
601 function stripScripts() {
602 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
603 }
604
605 function extractScripts() {
606 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
607 matchOne = new RegExp(Prototype.ScriptFragment, 'im');
608 return (this.match(matchAll) || []).map(function(scriptTag) {
609 return (scriptTag.match(matchOne) || ['', ''])[1];
610 });
611 }
612
613 function evalScripts() {
614 return this.extractScripts().map(function(script) { return eval(script) });
615 }
616
617 function escapeHTML() {
618 return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
619 }
620
621 function unescapeHTML() {
622 return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
623 }
624
625
626 function toQueryParams(separator) {
627 var match = this.strip().match(/([^?#]*)(#.*)?$/);
628 if (!match) return { };
629
630 return match[1].split(separator || '&').inject({ }, function(hash, pair) {
631 if ((pair = pair.split('='))[0]) {
632 var key = decodeURIComponent(pair.shift()),
633 value = pair.length > 1 ? pair.join('=') : pair[0];
634
635 if (value != undefined) value = decodeURIComponent(value);
636
637 if (key in hash) {
638 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
639 hash[key].push(value);
640 }
641 else hash[key] = value;
642 }
643 return hash;
644 });
645 }
646
647 function toArray() {
648 return this.split('');
649 }
650
651 function succ() {
652 return this.slice(0, this.length - 1) +
653 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
654 }
655
656 function times(count) {
657 return count < 1 ? '' : new Array(count + 1).join(this);
658 }
659
660 function camelize() {
661 return this.replace(/-+(.)?/g, function(match, chr) {
662 return chr ? chr.toUpperCase() : '';
663 });
664 }
665
666 function capitalize() {
667 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
668 }
669
670 function underscore() {
671 return this.replace(/::/g, '/')
672 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
673 .replace(/([a-z\d])([A-Z])/g, '$1_$2')
674 .replace(/-/g, '_')
675 .toLowerCase();
676 }
677
678 function dasherize() {
679 return this.replace(/_/g, '-');
680 }
681
682 function inspect(useDoubleQuotes) {
683 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
684 if (character in String.specialChar) {
685 return String.specialChar[character];
686 }
687 return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
688 });
689 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
690 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
691 }
692
693 function unfilterJSON(filter) {
694 return this.replace(filter || Prototype.JSONFilter, '$1');
695 }
696
697 function isJSON() {
698 var str = this;
699 if (str.blank()) return false;
700 str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
701 str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
702 str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
703 return (/^[\],:{}\s]*$/).test(str);
704 }
705
706 function evalJSON(sanitize) {
707 var json = this.unfilterJSON(),
708 cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
709 if (cx.test(json)) {
710 json = json.replace(cx, function (a) {
711 return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
712 });
713 }
714 try {
715 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
716 } catch (e) { }
717 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
718 }
719
720 function parseJSON() {
721 var json = this.unfilterJSON();
722 return JSON.parse(json);
723 }
724
725 function include(pattern) {
726 return this.indexOf(pattern) > -1;
727 }
728
729 function startsWith(pattern) {
730 return this.lastIndexOf(pattern, 0) === 0;
731 }
732
733 function endsWith(pattern) {
734 var d = this.length - pattern.length;
735 return d >= 0 && this.indexOf(pattern, d) === d;
736 }
737
738 function empty() {
739 return this == '';
740 }
741
742 function blank() {
743 return /^\s*$/.test(this);
744 }
745
746 function interpolate(object, pattern) {
747 return new Template(this, pattern).evaluate(object);
748 }
749
750 return {
751 gsub: gsub,
752 sub: sub,
753 scan: scan,
754 truncate: truncate,
755 strip: String.prototype.trim || strip,
756 stripTags: stripTags,
757 stripScripts: stripScripts,
758 extractScripts: extractScripts,
759 evalScripts: evalScripts,
760 escapeHTML: escapeHTML,
761 unescapeHTML: unescapeHTML,
762 toQueryParams: toQueryParams,
763 parseQuery: toQueryParams,
764 toArray: toArray,
765 succ: succ,
766 times: times,
767 camelize: camelize,
768 capitalize: capitalize,
769 underscore: underscore,
770 dasherize: dasherize,
771 inspect: inspect,
772 unfilterJSON: unfilterJSON,
773 isJSON: isJSON,
774 evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
775 include: include,
776 startsWith: startsWith,
777 endsWith: endsWith,
778 empty: empty,
779 blank: blank,
780 interpolate: interpolate
781 };
782 })());
783
784 var Template = Class.create({
785 initialize: function(template, pattern) {
786 this.template = template.toString();
787 this.pattern = pattern || Template.Pattern;
788 },
789
790 evaluate: function(object) {
791 if (object && Object.isFunction(object.toTemplateReplacements))
792 object = object.toTemplateReplacements();
793
794 return this.template.gsub(this.pattern, function(match) {
795 if (object == null) return (match[1] + '');
796
797 var before = match[1] || '';
798 if (before == '\\') return match[2];
799
800 var ctx = object, expr = match[3],
801 pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
802
803 match = pattern.exec(expr);
804 if (match == null) return before;
805
806 while (match != null) {
807 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
808 ctx = ctx[comp];
809 if (null == ctx || '' == match[3]) break;
810 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
811 match = pattern.exec(expr);
812 }
813
814 return before + String.interpret(ctx);
815 });
816 }
817 });
818 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
819
820 var $break = { };
821
822 var Enumerable = (function() {
823 function each(iterator, context) {
824 var index = 0;
825 try {
826 this._each(function(value) {
827 iterator.call(context, value, index++);
828 });
829 } catch (e) {
830 if (e != $break) throw e;
831 }
832 return this;
833 }
834
835 function eachSlice(number, iterator, context) {
836 var index = -number, slices = [], array = this.toArray();
837 if (number < 1) return array;
838 while ((index += number) < array.length)
839 slices.push(array.slice(index, index+number));
840 return slices.collect(iterator, context);
841 }
842
843 function all(iterator, context) {
844 iterator = iterator || Prototype.K;
845 var result = true;
846 this.each(function(value, index) {
847 result = result && !!iterator.call(context, value, index);
848 if (!result) throw $break;
849 });
850 return result;
851 }
852
853 function any(iterator, context) {
854 iterator = iterator || Prototype.K;
855 var result = false;
856 this.each(function(value, index) {
857 if (result = !!iterator.call(context, value, index))
858 throw $break;
859 });
860 return result;
861 }
862
863 function collect(iterator, context) {
864 iterator = iterator || Prototype.K;
865 var results = [];
866 this.each(function(value, index) {
867 results.push(iterator.call(context, value, index));
868 });
869 return results;
870 }
871
872 function detect(iterator, context) {
873 var result;
874 this.each(function(value, index) {
875 if (iterator.call(context, value, index)) {
876 result = value;
877 throw $break;
878 }
879 });
880 return result;
881 }
882
883 function findAll(iterator, context) {
884 var results = [];
885 this.each(function(value, index) {
886 if (iterator.call(context, value, index))
887 results.push(value);
888 });
889 return results;
890 }
891
892 function grep(filter, iterator, context) {
893 iterator = iterator || Prototype.K;
894 var results = [];
895
896 if (Object.isString(filter))
897 filter = new RegExp(RegExp.escape(filter));
898
899 this.each(function(value, index) {
900 if (filter.match(value))
901 results.push(iterator.call(context, value, index));
902 });
903 return results;
904 }
905
906 function include(object) {
907 if (Object.isFunction(this.indexOf))
908 if (this.indexOf(object) != -1) return true;
909
910 var found = false;
911 this.each(function(value) {
912 if (value == object) {
913 found = true;
914 throw $break;
915 }
916 });
917 return found;
918 }
919
920 function inGroupsOf(number, fillWith) {
921 fillWith = Object.isUndefined(fillWith) ? null : fillWith;
922 return this.eachSlice(number, function(slice) {
923 while(slice.length < number) slice.push(fillWith);
924 return slice;
925 });
926 }
927
928 function inject(memo, iterator, context) {
929 this.each(function(value, index) {
930 memo = iterator.call(context, memo, value, index);
931 });
932 return memo;
933 }
934
935 function invoke(method) {
936 var args = $A(arguments).slice(1);
937 return this.map(function(value) {
938 return value[method].apply(value, args);
939 });
940 }
941
942 function max(iterator, context) {
943 iterator = iterator || Prototype.K;
944 var result;
945 this.each(function(value, index) {
946 value = iterator.call(context, value, index);
947 if (result == null || value >= result)
948 result = value;
949 });
950 return result;
951 }
952
953 function min(iterator, context) {
954 iterator = iterator || Prototype.K;
955 var result;
956 this.each(function(value, index) {
957 value = iterator.call(context, value, index);
958 if (result == null || value < result)
959 result = value;
960 });
961 return result;
962 }
963
964 function partition(iterator, context) {
965 iterator = iterator || Prototype.K;
966 var trues = [], falses = [];
967 this.each(function(value, index) {
968 (iterator.call(context, value, index) ?
969 trues : falses).push(value);
970 });
971 return [trues, falses];
972 }
973
974 function pluck(property) {
975 var results = [];
976 this.each(function(value) {
977 results.push(value[property]);
978 });
979 return results;
980 }
981
982 function reject(iterator, context) {
983 var results = [];
984 this.each(function(value, index) {
985 if (!iterator.call(context, value, index))
986 results.push(value);
987 });
988 return results;
989 }
990
991 function sortBy(iterator, context) {
992 return this.map(function(value, index) {
993 return {
994 value: value,
995 criteria: iterator.call(context, value, index)
996 };
997 }).sort(function(left, right) {
998 var a = left.criteria, b = right.criteria;
999 return a < b ? -1 : a > b ? 1 : 0;
1000 }).pluck('value');
1001 }
1002
1003 function toArray() {
1004 return this.map();
1005 }
1006
1007 function zip() {
1008 var iterator = Prototype.K, args = $A(arguments);
1009 if (Object.isFunction(args.last()))
1010 iterator = args.pop();
1011
1012 var collections = [this].concat(args).map($A);
1013 return this.map(function(value, index) {
1014 return iterator(collections.pluck(index));
1015 });
1016 }
1017
1018 function size() {
1019 return this.toArray().length;
1020 }
1021
1022 function inspect() {
1023 return '#<Enumerable:' + this.toArray().inspect() + '>';
1024 }
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034 return {
1035 each: each,
1036 eachSlice: eachSlice,
1037 all: all,
1038 every: all,
1039 any: any,
1040 some: any,
1041 collect: collect,
1042 map: collect,
1043 detect: detect,
1044 findAll: findAll,
1045 select: findAll,
1046 filter: findAll,
1047 grep: grep,
1048 include: include,
1049 member: include,
1050 inGroupsOf: inGroupsOf,
1051 inject: inject,
1052 invoke: invoke,
1053 max: max,
1054 min: min,
1055 partition: partition,
1056 pluck: pluck,
1057 reject: reject,
1058 sortBy: sortBy,
1059 toArray: toArray,
1060 entries: toArray,
1061 zip: zip,
1062 size: size,
1063 inspect: inspect,
1064 find: detect
1065 };
1066 })();
1067
1068 function $A(iterable) {
1069 if (!iterable) return [];
1070 if ('toArray' in Object(iterable)) return iterable.toArray();
1071 var length = iterable.length || 0, results = new Array(length);
1072 while (length--) results[length] = iterable[length];
1073 return results;
1074 }
1075
1076
1077 function $w(string) {
1078 if (!Object.isString(string)) return [];
1079 string = string.strip();
1080 return string ? string.split(/\s+/) : [];
1081 }
1082
1083 Array.from = $A;
1084
1085
1086 (function() {
1087 var arrayProto = Array.prototype,
1088 slice = arrayProto.slice,
1089 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1090
1091 function each(iterator, context) {
1092 for (var i = 0, length = this.length >>> 0; i < length; i++) {
1093 if (i in this) iterator.call(context, this[i], i, this);
1094 }
1095 }
1096 if (!_each) _each = each;
1097
1098 function clear() {
1099 this.length = 0;
1100 return this;
1101 }
1102
1103 function first() {
1104 return this[0];
1105 }
1106
1107 function last() {
1108 return this[this.length - 1];
1109 }
1110
1111 function compact() {
1112 return this.select(function(value) {
1113 return value != null;
1114 });
1115 }
1116
1117 function flatten() {
1118 return this.inject([], function(array, value) {
1119 if (Object.isArray(value))
1120 return array.concat(value.flatten());
1121 array.push(value);
1122 return array;
1123 });
1124 }
1125
1126 function without() {
1127 var values = slice.call(arguments, 0);
1128 return this.select(function(value) {
1129 return !values.include(value);
1130 });
1131 }
1132
1133 function reverse(inline) {
1134 return (inline === false ? this.toArray() : this)._reverse();
1135 }
1136
1137 function uniq(sorted) {
1138 return this.inject([], function(array, value, index) {
1139 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1140 array.push(value);
1141 return array;
1142 });
1143 }
1144
1145 function intersect(array) {
1146 return this.uniq().findAll(function(item) {
1147 return array.detect(function(value) { return item === value });
1148 });
1149 }
1150
1151
1152 function clone() {
1153 return slice.call(this, 0);
1154 }
1155
1156 function size() {
1157 return this.length;
1158 }
1159
1160 function inspect() {
1161 return '[' + this.map(Object.inspect).join(', ') + ']';
1162 }
1163
1164 function indexOf(item, i) {
1165 i || (i = 0);
1166 var length = this.length;
1167 if (i < 0) i = length + i;
1168 for (; i < length; i++)
1169 if (this[i] === item) return i;
1170 return -1;
1171 }
1172
1173 function lastIndexOf(item, i) {
1174 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
1175 var n = this.slice(0, i).reverse().indexOf(item);
1176 return (n < 0) ? n : i - n - 1;
1177 }
1178
1179 function concat() {
1180 var array = slice.call(this, 0), item;
1181 for (var i = 0, length = arguments.length; i < length; i++) {
1182 item = arguments[i];
1183 if (Object.isArray(item) && !('callee' in item)) {
1184 for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
1185 array.push(item[j]);
1186 } else {
1187 array.push(item);
1188 }
1189 }
1190 return array;
1191 }
1192
1193 Object.extend(arrayProto, Enumerable);
1194
1195 if (!arrayProto._reverse)
1196 arrayProto._reverse = arrayProto.reverse;
1197
1198 Object.extend(arrayProto, {
1199 _each: _each,
1200 clear: clear,
1201 first: first,
1202 last: last,
1203 compact: compact,
1204 flatten: flatten,
1205 without: without,
1206 reverse: reverse,
1207 uniq: uniq,
1208 intersect: intersect,
1209 clone: clone,
1210 toArray: clone,
1211 size: size,
1212 inspect: inspect
1213 });
1214
1215 var CONCAT_ARGUMENTS_BUGGY = (function() {
1216 return [].concat(arguments)[0][0] !== 1;
1217 })(1,2)
1218
1219 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1220
1221 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1222 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1223 })();
1224 function $H(object) {
1225 return new Hash(object);
1226 };
1227
1228 var Hash = Class.create(Enumerable, (function() {
1229 function initialize(object) {
1230 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1231 }
1232
1233
1234 function _each(iterator) {
1235 for (var key in this._object) {
1236 var value = this._object[key], pair = [key, value];
1237 pair.key = key;
1238 pair.value = value;
1239 iterator(pair);
1240 }
1241 }
1242
1243 function set(key, value) {
1244 return this._object[key] = value;
1245 }
1246
1247 function get(key) {
1248 if (this._object[key] !== Object.prototype[key])
1249 return this._object[key];
1250 }
1251
1252 function unset(key) {
1253 var value = this._object[key];
1254 delete this._object[key];
1255 return value;
1256 }
1257
1258 function toObject() {
1259 return Object.clone(this._object);
1260 }
1261
1262
1263
1264 function keys() {
1265 return this.pluck('key');
1266 }
1267
1268 function values() {
1269 return this.pluck('value');
1270 }
1271
1272 function index(value) {
1273 var match = this.detect(function(pair) {
1274 return pair.value === value;
1275 });
1276 return match && match.key;
1277 }
1278
1279 function merge(object) {
1280 return this.clone().update(object);
1281 }
1282
1283 function update(object) {
1284 return new Hash(object).inject(this, function(result, pair) {
1285 result.set(pair.key, pair.value);
1286 return result;
1287 });
1288 }
1289
1290 function toQueryPair(key, value) {
1291 if (Object.isUndefined(value)) return key;
1292 return key + '=' + encodeURIComponent(String.interpret(value));
1293 }
1294
1295 function toQueryString() {
1296 return this.inject([], function(results, pair) {
1297 var key = encodeURIComponent(pair.key), values = pair.value;
1298
1299 if (values && typeof values == 'object') {
1300 if (Object.isArray(values)) {
1301 var queryValues = [];
1302 for (var i = 0, len = values.length, value; i < len; i++) {
1303 value = values[i];
1304 queryValues.push(toQueryPair(key, value));
1305 }
1306 return results.concat(queryValues);
1307 }
1308 } else results.push(toQueryPair(key, values));
1309 return results;
1310 }).join('&');
1311 }
1312
1313 function inspect() {
1314 return '#<Hash:{' + this.map(function(pair) {
1315 return pair.map(Object.inspect).join(': ');
1316 }).join(', ') + '}>';
1317 }
1318
1319 function clone() {
1320 return new Hash(this);
1321 }
1322
1323 return {
1324 initialize: initialize,
1325 _each: _each,
1326 set: set,
1327 get: get,
1328 unset: unset,
1329 toObject: toObject,
1330 toTemplateReplacements: toObject,
1331 keys: keys,
1332 values: values,
1333 index: index,
1334 merge: merge,
1335 update: update,
1336 toQueryString: toQueryString,
1337 inspect: inspect,
1338 toJSON: toObject,
1339 clone: clone
1340 };
1341 })());
1342
1343 Hash.from = $H;
1344 Object.extend(Number.prototype, (function() {
1345 function toColorPart() {
1346 return this.toPaddedString(2, 16);
1347 }
1348
1349 function succ() {
1350 return this + 1;
1351 }
1352
1353 function times(iterator, context) {
1354 $R(0, this, true).each(iterator, context);
1355 return this;
1356 }
1357
1358 function toPaddedString(length, radix) {
1359 var string = this.toString(radix || 10);
1360 return '0'.times(length - string.length) + string;
1361 }
1362
1363 function abs() {
1364 return Math.abs(this);
1365 }
1366
1367 function round() {
1368 return Math.round(this);
1369 }
1370
1371 function ceil() {
1372 return Math.ceil(this);
1373 }
1374
1375 function floor() {
1376 return Math.floor(this);
1377 }
1378
1379 return {
1380 toColorPart: toColorPart,
1381 succ: succ,
1382 times: times,
1383 toPaddedString: toPaddedString,
1384 abs: abs,
1385 round: round,
1386 ceil: ceil,
1387 floor: floor
1388 };
1389 })());
1390
1391 function $R(start, end, exclusive) {
1392 return new ObjectRange(start, end, exclusive);
1393 }
1394
1395 var ObjectRange = Class.create(Enumerable, (function() {
1396 function initialize(start, end, exclusive) {
1397 this.start = start;
1398 this.end = end;
1399 this.exclusive = exclusive;
1400 }
1401
1402 function _each(iterator) {
1403 var value = this.start;
1404 while (this.include(value)) {
1405 iterator(value);
1406 value = value.succ();
1407 }
1408 }
1409
1410 function include(value) {
1411 if (value < this.start)
1412 return false;
1413 if (this.exclusive)
1414 return value < this.end;
1415 return value <= this.end;
1416 }
1417
1418 return {
1419 initialize: initialize,
1420 _each: _each,
1421 include: include
1422 };
1423 })());
1424
1425
1426
1427 var Ajax = {
1428 getTransport: function() {
1429 return Try.these(
1430 function() {return new XMLHttpRequest()},
1431 function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1432 function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1433 ) || false;
1434 },
1435
1436 activeRequestCount: 0
1437 };
1438
1439 Ajax.Responders = {
1440 responders: [],
1441
1442 _each: function(iterator) {
1443 this.responders._each(iterator);
1444 },
1445
1446 register: function(responder) {
1447 if (!this.include(responder))
1448 this.responders.push(responder);
1449 },
1450
1451 unregister: function(responder) {
1452 this.responders = this.responders.without(responder);
1453 },
1454
1455 dispatch: function(callback, request, transport, json) {
1456 this.each(function(responder) {
1457 if (Object.isFunction(responder[callback])) {
1458 try {
1459 responder[callback].apply(responder, [request, transport, json]);
1460 } catch (e) { }
1461 }
1462 });
1463 }
1464 };
1465
1466 Object.extend(Ajax.Responders, Enumerable);
1467
1468 Ajax.Responders.register({
1469 onCreate: function() { Ajax.activeRequestCount++ },
1470 onComplete: function() { Ajax.activeRequestCount-- }
1471 });
1472 Ajax.Base = Class.create({
1473 initialize: function(options) {
1474 this.options = {
1475 method: 'post',
1476 asynchronous: true,
1477 contentType: 'application/x-www-form-urlencoded',
1478 encoding: 'UTF-8',
1479 parameters: '',
1480 evalJSON: true,
1481 evalJS: true
1482 };
1483 Object.extend(this.options, options || { });
1484
1485 this.options.method = this.options.method.toLowerCase();
1486
1487 if (Object.isHash(this.options.parameters))
1488 this.options.parameters = this.options.parameters.toObject();
1489 }
1490 });
1491 Ajax.Request = Class.create(Ajax.Base, {
1492 _complete: false,
1493
1494 initialize: function($super, url, options) {
1495 $super(options);
1496 this.transport = Ajax.getTransport();
1497 this.request(url);
1498 },
1499
1500 request: function(url) {
1501 this.url = url;
1502 this.method = this.options.method;
1503 var params = Object.isString(this.options.parameters) ?
1504 this.options.parameters :
1505 Object.toQueryString(this.options.parameters);
1506
1507 if (!['get', 'post'].include(this.method)) {
1508 params += (params ? '&' : '') + "_method=" + this.method;
1509 this.method = 'post';
1510 }
1511
1512 if (params && this.method === 'get') {
1513 this.url += (this.url.include('?') ? '&' : '?') + params;
1514 }
1515
1516 this.parameters = params.toQueryParams();
1517
1518 try {
1519 var response = new Ajax.Response(this);
1520 if (this.options.onCreate) this.options.onCreate(response);
1521 Ajax.Responders.dispatch('onCreate', this, response);
1522
1523 this.transport.open(this.method.toUpperCase(), this.url,
1524 this.options.asynchronous);
1525
1526 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1527
1528 this.transport.onreadystatechange = this.onStateChange.bind(this);
1529 this.setRequestHeaders();
1530
1531 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1532 this.transport.send(this.body);
1533
1534 /* Force Firefox to handle ready state 4 for synchronous requests */
1535 if (!this.options.asynchronous && this.transport.overrideMimeType)
1536 this.onStateChange();
1537
1538 }
1539 catch (e) {
1540 this.dispatchException(e);
1541 }
1542 },
1543
1544 onStateChange: function() {
1545 var readyState = this.transport.readyState;
1546 if (readyState > 1 && !((readyState == 4) && this._complete))
1547 this.respondToReadyState(this.transport.readyState);
1548 },
1549
1550 setRequestHeaders: function() {
1551 var headers = {
1552 'X-Requested-With': 'XMLHttpRequest',
1553 'X-Prototype-Version': Prototype.Version,
1554 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1555 };
1556
1557 if (this.method == 'post') {
1558 headers['Content-type'] = this.options.contentType +
1559 (this.options.encoding ? '; charset=' + this.options.encoding : '');
1560
1561 /* Force "Connection: close" for older Mozilla browsers to work
1562 * around a bug where XMLHttpRequest sends an incorrect
1563 * Content-length header. See Mozilla Bugzilla #246651.
1564 */
1565 if (this.transport.overrideMimeType &&
1566 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1567 headers['Connection'] = 'close';
1568 }
1569
1570 if (typeof this.options.requestHeaders == 'object') {
1571 var extras = this.options.requestHeaders;
1572
1573 if (Object.isFunction(extras.push))
1574 for (var i = 0, length = extras.length; i < length; i += 2)
1575 headers[extras[i]] = extras[i+1];
1576 else
1577 $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1578 }
1579
1580 for (var name in headers)
1581 this.transport.setRequestHeader(name, headers[name]);
1582 },
1583
1584 success: function() {
1585 var status = this.getStatus();
1586 return !status || (status >= 200 && status < 300) || status == 304;
1587 },
1588
1589 getStatus: function() {
1590 try {
1591 if (this.transport.status === 1223) return 204;
1592 return this.transport.status || 0;
1593 } catch (e) { return 0 }
1594 },
1595
1596 respondToReadyState: function(readyState) {
1597 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1598
1599 if (state == 'Complete') {
1600 try {
1601 this._complete = true;
1602 (this.options['on' + response.status]
1603 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1604 || Prototype.emptyFunction)(response, response.headerJSON);
1605 } catch (e) {
1606 this.dispatchException(e);
1607 }
1608
1609 var contentType = response.getHeader('Content-type');
1610 if (this.options.evalJS == 'force'
1611 || (this.options.evalJS && this.isSameOrigin() && contentType
1612 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1613 this.evalResponse();
1614 }
1615
1616 try {
1617 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1618 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1619 } catch (e) {
1620 this.dispatchException(e);
1621 }
1622
1623 if (state == 'Complete') {
1624 this.transport.onreadystatechange = Prototype.emptyFunction;
1625 }
1626 },
1627
1628 isSameOrigin: function() {
1629 var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1630 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1631 protocol: location.protocol,
1632 domain: document.domain,
1633 port: location.port ? ':' + location.port : ''
1634 }));
1635 },
1636
1637 getHeader: function(name) {
1638 try {
1639 return this.transport.getResponseHeader(name) || null;
1640 } catch (e) { return null; }
1641 },
1642
1643 evalResponse: function() {
1644 try {
1645 return eval((this.transport.responseText || '').unfilterJSON());
1646 } catch (e) {
1647 this.dispatchException(e);
1648 }
1649 },
1650
1651 dispatchException: function(exception) {
1652 (this.options.onException || Prototype.emptyFunction)(this, exception);
1653 Ajax.Responders.dispatch('onException', this, exception);
1654 }
1655 });
1656
1657 Ajax.Request.Events =
1658 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1659
1660
1661
1662
1663
1664
1665
1666
1667 Ajax.Response = Class.create({
1668 initialize: function(request){
1669 this.request = request;
1670 var transport = this.transport = request.transport,
1671 readyState = this.readyState = transport.readyState;
1672
1673 if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1674 this.status = this.getStatus();
1675 this.statusText = this.getStatusText();
1676 this.responseText = String.interpret(transport.responseText);
1677 this.headerJSON = this._getHeaderJSON();
1678 }
1679
1680 if (readyState == 4) {
1681 var xml = transport.responseXML;
1682 this.responseXML = Object.isUndefined(xml) ? null : xml;
1683 this.responseJSON = this._getResponseJSON();
1684 }
1685 },
1686
1687 status: 0,
1688
1689 statusText: '',
1690
1691 getStatus: Ajax.Request.prototype.getStatus,
1692
1693 getStatusText: function() {
1694 try {
1695 return this.transport.statusText || '';
1696 } catch (e) { return '' }
1697 },
1698
1699 getHeader: Ajax.Request.prototype.getHeader,
1700
1701 getAllHeaders: function() {
1702 try {
1703 return this.getAllResponseHeaders();
1704 } catch (e) { return null }
1705 },
1706
1707 getResponseHeader: function(name) {
1708 return this.transport.getResponseHeader(name);
1709 },
1710
1711 getAllResponseHeaders: function() {
1712 return this.transport.getAllResponseHeaders();
1713 },
1714
1715 _getHeaderJSON: function() {
1716 var json = this.getHeader('X-JSON');
1717 if (!json) return null;
1718 json = decodeURIComponent(escape(json));
1719 try {
1720 return json.evalJSON(this.request.options.sanitizeJSON ||
1721 !this.request.isSameOrigin());
1722 } catch (e) {
1723 this.request.dispatchException(e);
1724 }
1725 },
1726
1727 _getResponseJSON: function() {
1728 var options = this.request.options;
1729 if (!options.evalJSON || (options.evalJSON != 'force' &&
1730 !(this.getHeader('Content-type') || '').include('application/json')) ||
1731 this.responseText.blank())
1732 return null;
1733 try {
1734 return this.responseText.evalJSON(options.sanitizeJSON ||
1735 !this.request.isSameOrigin());
1736 } catch (e) {
1737 this.request.dispatchException(e);
1738 }
1739 }
1740 });
1741
1742 Ajax.Updater = Class.create(Ajax.Request, {
1743 initialize: function($super, container, url, options) {
1744 this.container = {
1745 success: (container.success || container),
1746 failure: (container.failure || (container.success ? null : container))
1747 };
1748
1749 options = Object.clone(options);
1750 var onComplete = options.onComplete;
1751 options.onComplete = (function(response, json) {
1752 this.updateContent(response.responseText);
1753 if (Object.isFunction(onComplete)) onComplete(response, json);
1754 }).bind(this);
1755
1756 $super(url, options);
1757 },
1758
1759 updateContent: function(responseText) {
1760 var receiver = this.container[this.success() ? 'success' : 'failure'],
1761 options = this.options;
1762
1763 if (!options.evalScripts) responseText = responseText.stripScripts();
1764
1765 if (receiver = $(receiver)) {
1766 if (options.insertion) {
1767 if (Object.isString(options.insertion)) {
1768 var insertion = { }; insertion[options.insertion] = responseText;
1769 receiver.insert(insertion);
1770 }
1771 else options.insertion(receiver, responseText);
1772 }
1773 else receiver.update(responseText);
1774 }
1775 }
1776 });
1777
1778 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1779 initialize: function($super, container, url, options) {
1780 $super(options);
1781 this.onComplete = this.options.onComplete;
1782
1783 this.frequency = (this.options.frequency || 2);
1784 this.decay = (this.options.decay || 1);
1785
1786 this.updater = { };
1787 this.container = container;
1788 this.url = url;
1789
1790 this.start();
1791 },
1792
1793 start: function() {
1794 this.options.onComplete = this.updateComplete.bind(this);
1795 this.onTimerEvent();
1796 },
1797
1798 stop: function() {
1799 this.updater.options.onComplete = undefined;
1800 clearTimeout(this.timer);
1801 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1802 },
1803
1804 updateComplete: function(response) {
1805 if (this.options.decay) {
1806 this.decay = (response.responseText == this.lastText ?
1807 this.decay * this.options.decay : 1);
1808
1809 this.lastText = response.responseText;
1810 }
1811 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1812 },
1813
1814 onTimerEvent: function() {
1815 this.updater = new Ajax.Updater(this.container, this.url, this.options);
1816 }
1817 });
1818
1819
1820 function $(element) {
1821 if (arguments.length > 1) {
1822 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1823 elements.push($(arguments[i]));
1824 return elements;
1825 }
1826 if (Object.isString(element))
1827 element = document.getElementById(element);
1828 return Element.extend(element);
1829 }
1830
1831 if (Prototype.BrowserFeatures.XPath) {
1832 document._getElementsByXPath = function(expression, parentElement) {
1833 var results = [];
1834 var query = document.evaluate(expression, $(parentElement) || document,
1835 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1836 for (var i = 0, length = query.snapshotLength; i < length; i++)
1837 results.push(Element.extend(query.snapshotItem(i)));
1838 return results;
1839 };
1840 }
1841
1842 /*--------------------------------------------------------------------------*/
1843
1844 if (!Node) var Node = { };
1845
1846 if (!Node.ELEMENT_NODE) {
1847 Object.extend(Node, {
1848 ELEMENT_NODE: 1,
1849 ATTRIBUTE_NODE: 2,
1850 TEXT_NODE: 3,
1851 CDATA_SECTION_NODE: 4,
1852 ENTITY_REFERENCE_NODE: 5,
1853 ENTITY_NODE: 6,
1854 PROCESSING_INSTRUCTION_NODE: 7,
1855 COMMENT_NODE: 8,
1856 DOCUMENT_NODE: 9,
1857 DOCUMENT_TYPE_NODE: 10,
1858 DOCUMENT_FRAGMENT_NODE: 11,
1859 NOTATION_NODE: 12
1860 });
1861 }
1862
1863
1864
1865 (function(global) {
1866 function shouldUseCache(tagName, attributes) {
1867 if (tagName === 'select') return false;
1868 if ('type' in attributes) return false;
1869 return true;
1870 }
1871
1872 var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
1873 try {
1874 var el = document.createElement('<input name="x">');
1875 return el.tagName.toLowerCase() === 'input' && el.name === 'x';
1876 }
1877 catch(err) {
1878 return false;
1879 }
1880 })();
1881
1882 var element = global.Element;
1883
1884 global.Element = function(tagName, attributes) {
1885 attributes = attributes || { };
1886 tagName = tagName.toLowerCase();
1887 var cache = Element.cache;
1888
1889 if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
1890 tagName = '<' + tagName + ' name="' + attributes.name + '">';
1891 delete attributes.name;
1892 return Element.writeAttribute(document.createElement(tagName), attributes);
1893 }
1894
1895 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1896
1897 var node = shouldUseCache(tagName, attributes) ?
1898 cache[tagName].cloneNode(false) : document.createElement(tagName);
1899
1900 return Element.writeAttribute(node, attributes);
1901 };
1902
1903 Object.extend(global.Element, element || { });
1904 if (element) global.Element.prototype = element.prototype;
1905
1906 })(this);
1907
1908 Element.idCounter = 1;
1909 Element.cache = { };
1910
1911 Element._purgeElement = function(element) {
1912 var uid = element._prototypeUID;
1913 if (uid) {
1914 Element.stopObserving(element);
1915 element._prototypeUID = void 0;
1916 delete Element.Storage[uid];
1917 }
1918 }
1919
1920 Element.Methods = {
1921 visible: function(element) {
1922 return $(element).style.display != 'none';
1923 },
1924
1925 toggle: function(element) {
1926 element = $(element);
1927 Element[Element.visible(element) ? 'hide' : 'show'](element);
1928 return element;
1929 },
1930
1931 hide: function(element) {
1932 element = $(element);
1933 element.style.display = 'none';
1934 return element;
1935 },
1936
1937 show: function(element) {
1938 element = $(element);
1939 element.style.display = '';
1940 return element;
1941 },
1942
1943 remove: function(element) {
1944 element = $(element);
1945 element.parentNode.removeChild(element);
1946 return element;
1947 },
1948
1949 update: (function(){
1950
1951 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
1952 var el = document.createElement("select"),
1953 isBuggy = true;
1954 el.innerHTML = "<option value=\"test\">test</option>";
1955 if (el.options && el.options[0]) {
1956 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
1957 }
1958 el = null;
1959 return isBuggy;
1960 })();
1961
1962 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
1963 try {
1964 var el = document.createElement("table");
1965 if (el && el.tBodies) {
1966 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
1967 var isBuggy = typeof el.tBodies[0] == "undefined";
1968 el = null;
1969 return isBuggy;
1970 }
1971 } catch (e) {
1972 return true;
1973 }
1974 })();
1975
1976 var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
1977 try {
1978 var el = document.createElement('div');
1979 el.innerHTML = "<link>";
1980 var isBuggy = (el.childNodes.length === 0);
1981 el = null;
1982 return isBuggy;
1983 } catch(e) {
1984 return true;
1985 }
1986 })();
1987
1988 var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
1989 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
1990
1991 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
1992 var s = document.createElement("script"),
1993 isBuggy = false;
1994 try {
1995 s.appendChild(document.createTextNode(""));
1996 isBuggy = !s.firstChild ||
1997 s.firstChild && s.firstChild.nodeType !== 3;
1998 } catch (e) {
1999 isBuggy = true;
2000 }
2001 s = null;
2002 return isBuggy;
2003 })();
2004
2005
2006 function update(element, content) {
2007 element = $(element);
2008 var purgeElement = Element._purgeElement;
2009
2010 var descendants = element.getElementsByTagName('*'),
2011 i = descendants.length;
2012 while (i--) purgeElement(descendants[i]);
2013
2014 if (content && content.toElement)
2015 content = content.toElement();
2016
2017 if (Object.isElement(content))
2018 return element.update().insert(content);
2019
2020 content = Object.toHTML(content);
2021
2022 var tagName = element.tagName.toUpperCase();
2023
2024 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
2025 element.text = content;
2026 return element;
2027 }
2028
2029 if (ANY_INNERHTML_BUGGY) {
2030 if (tagName in Element._insertionTranslations.tags) {
2031 while (element.firstChild) {
2032 element.removeChild(element.firstChild);
2033 }
2034 Element._getContentFromAnonymousElement(tagName, content.stripScripts())
2035 .each(function(node) {
2036 element.appendChild(node)
2037 });
2038 } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
2039 while (element.firstChild) {
2040 element.removeChild(element.firstChild);
2041 }
2042 var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
2043 nodes.each(function(node) { element.appendChild(node) });
2044 }
2045 else {
2046 element.innerHTML = content.stripScripts();
2047 }
2048 }
2049 else {
2050 element.innerHTML = content.stripScripts();
2051 }
2052
2053 content.evalScripts.bind(content).defer();
2054 return element;
2055 }
2056
2057 return update;
2058 })(),
2059
2060 replace: function(element, content) {
2061 element = $(element);
2062 if (content && content.toElement) content = content.toElement();
2063 else if (!Object.isElement(content)) {
2064 content = Object.toHTML(content);
2065 var range = element.ownerDocument.createRange();
2066 range.selectNode(element);
2067 content.evalScripts.bind(content).defer();
2068 content = range.createContextualFragment(content.stripScripts());
2069 }
2070 element.parentNode.replaceChild(content, element);
2071 return element;
2072 },
2073
2074 insert: function(element, insertions) {
2075 element = $(element);
2076
2077 if (Object.isString(insertions) || Object.isNumber(insertions) ||
2078 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
2079 insertions = {bottom:insertions};
2080
2081 var content, insert, tagName, childNodes;
2082
2083 for (var position in insertions) {
2084 content = insertions[position];
2085 position = position.toLowerCase();
2086 insert = Element._insertionTranslations[position];
2087
2088 if (content && content.toElement) content = content.toElement();
2089 if (Object.isElement(content)) {
2090 insert(element, content);
2091 continue;
2092 }
2093
2094 content = Object.toHTML(content);
2095
2096 tagName = ((position == 'before' || position == 'after')
2097 ? element.parentNode : element).tagName.toUpperCase();
2098
2099 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2100
2101 if (position == 'top' || position == 'after') childNodes.reverse();
2102 childNodes.each(insert.curry(element));
2103
2104 content.evalScripts.bind(content).defer();
2105 }
2106
2107 return element;
2108 },
2109
2110 wrap: function(element, wrapper, attributes) {
2111 element = $(element);
2112 if (Object.isElement(wrapper))
2113 $(wrapper).writeAttribute(attributes || { });
2114 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
2115 else wrapper = new Element('div', wrapper);
2116 if (element.parentNode)
2117 element.parentNode.replaceChild(wrapper, element);
2118 wrapper.appendChild(element);
2119 return wrapper;
2120 },
2121
2122 inspect: function(element) {
2123 element = $(element);
2124 var result = '<' + element.tagName.toLowerCase();
2125 $H({'id': 'id', 'className': 'class'}).each(function(pair) {
2126 var property = pair.first(),
2127 attribute = pair.last(),
2128 value = (element[property] || '').toString();
2129 if (value) result += ' ' + attribute + '=' + value.inspect(true);
2130 });
2131 return result + '>';
2132 },
2133
2134 recursivelyCollect: function(element, property, maximumLength) {
2135 element = $(element);
2136 maximumLength = maximumLength || -1;
2137 var elements = [];
2138
2139 while (element = element[property]) {
2140 if (element.nodeType == 1)
2141 elements.push(Element.extend(element));
2142 if (elements.length == maximumLength)
2143 break;
2144 }
2145
2146 return elements;
2147 },
2148
2149 ancestors: function(element) {
2150 return Element.recursivelyCollect(element, 'parentNode');
2151 },
2152
2153 descendants: function(element) {
2154 return Element.select(element, "*");
2155 },
2156
2157 firstDescendant: function(element) {
2158 element = $(element).firstChild;
2159 while (element && element.nodeType != 1) element = element.nextSibling;
2160 return $(element);
2161 },
2162
2163 immediateDescendants: function(element) {
2164 var results = [], child = $(element).firstChild;
2165 while (child) {
2166 if (child.nodeType === 1) {
2167 results.push(Element.extend(child));
2168 }
2169 child = child.nextSibling;
2170 }
2171 return results;
2172 },
2173
2174 previousSiblings: function(element, maximumLength) {
2175 return Element.recursivelyCollect(element, 'previousSibling');
2176 },
2177
2178 nextSiblings: function(element) {
2179 return Element.recursivelyCollect(element, 'nextSibling');
2180 },
2181
2182 siblings: function(element) {
2183 element = $(element);
2184 return Element.previousSiblings(element).reverse()
2185 .concat(Element.nextSiblings(element));
2186 },
2187
2188 match: function(element, selector) {
2189 element = $(element);
2190 if (Object.isString(selector))
2191 return Prototype.Selector.match(element, selector);
2192 return selector.match(element);
2193 },
2194
2195 up: function(element, expression, index) {
2196 element = $(element);
2197 if (arguments.length == 1) return $(element.parentNode);
2198 var ancestors = Element.ancestors(element);
2199 return Object.isNumber(expression) ? ancestors[expression] :
2200 Prototype.Selector.find(ancestors, expression, index);
2201 },
2202
2203 down: function(element, expression, index) {
2204 element = $(element);
2205 if (arguments.length == 1) return Element.firstDescendant(element);
2206 return Object.isNumber(expression) ? Element.descendants(element)[expression] :
2207 Element.select(element, expression)[index || 0];
2208 },
2209
2210 previous: function(element, expression, index) {
2211 element = $(element);
2212 if (Object.isNumber(expression)) index = expression, expression = false;
2213 if (!Object.isNumber(index)) index = 0;
2214
2215 if (expression) {
2216 return Prototype.Selector.find(element.previousSiblings(), expression, index);
2217 } else {
2218 return element.recursivelyCollect("previousSibling", index + 1)[index];
2219 }
2220 },
2221
2222 next: function(element, expression, index) {
2223 element = $(element);
2224 if (Object.isNumber(expression)) index = expression, expression = false;
2225 if (!Object.isNumber(index)) index = 0;
2226
2227 if (expression) {
2228 return Prototype.Selector.find(element.nextSiblings(), expression, index);
2229 } else {
2230 var maximumLength = Object.isNumber(index) ? index + 1 : 1;
2231 return element.recursivelyCollect("nextSibling", index + 1)[index];
2232 }
2233 },
2234
2235
2236 select: function(element) {
2237 element = $(element);
2238 var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
2239 return Prototype.Selector.select(expressions, element);
2240 },
2241
2242 adjacent: function(element) {
2243 element = $(element);
2244 var expressions = Array.prototype.slice.call(arguments, 1).join(', ');
2245 return Prototype.Selector.select(expressions, element.parentNode).without(element);
2246 },
2247
2248 identify: function(element) {
2249 element = $(element);
2250 var id = Element.readAttribute(element, 'id');
2251 if (id) return id;
2252 do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id));
2253 Element.writeAttribute(element, 'id', id);
2254 return id;
2255 },
2256
2257 readAttribute: function(element, name) {
2258 element = $(element);
2259 if (Prototype.Browser.IE) {
2260 var t = Element._attributeTranslations.read;
2261 if (t.values[name]) return t.values[name](element, name);
2262 if (t.names[name]) name = t.names[name];
2263 if (name.include(':')) {
2264 return (!element.attributes || !element.attributes[name]) ? null :
2265 element.attributes[name].value;
2266 }
2267 }
2268 return element.getAttribute(name);
2269 },
2270
2271 writeAttribute: function(element, name, value) {
2272 element = $(element);
2273 var attributes = { }, t = Element._attributeTranslations.write;
2274
2275 if (typeof name == 'object') attributes = name;
2276 else attributes[name] = Object.isUndefined(value) ? true : value;
2277
2278 for (var attr in attributes) {
2279 name = t.names[attr] || attr;
2280 value = attributes[attr];
2281 if (t.values[attr]) name = t.values[attr](element, value);
2282 if (value === false || value === null)
2283 element.removeAttribute(name);
2284 else if (value === true)
2285 element.setAttribute(name, name);
2286 else element.setAttribute(name, value);
2287 }
2288 return element;
2289 },
2290
2291 getHeight: function(element) {
2292 return Element.getDimensions(element).height;
2293 },
2294
2295 getWidth: function(element) {
2296 return Element.getDimensions(element).width;
2297 },
2298
2299 classNames: function(element) {
2300 return new Element.ClassNames(element);
2301 },
2302
2303 hasClassName: function(element, className) {
2304 if (!(element = $(element))) return;
2305 var elementClassName = element.className;
2306 return (elementClassName.length > 0 && (elementClassName == className ||
2307 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
2308 },
2309
2310 addClassName: function(element, className) {
2311 if (!(element = $(element))) return;
2312 if (!Element.hasClassName(element, className))
2313 element.className += (element.className ? ' ' : '') + className;
2314 return element;
2315 },
2316
2317 removeClassName: function(element, className) {
2318 if (!(element = $(element))) return;
2319 element.className = element.className.replace(
2320 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
2321 return element;
2322 },
2323
2324 toggleClassName: function(element, className) {
2325 if (!(element = $(element))) return;
2326 return Element[Element.hasClassName(element, className) ?
2327 'removeClassName' : 'addClassName'](element, className);
2328 },
2329
2330 cleanWhitespace: function(element) {
2331 element = $(element);
2332 var node = element.firstChild;
2333 while (node) {
2334 var nextNode = node.nextSibling;
2335 if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
2336 element.removeChild(node);
2337 node = nextNode;
2338 }
2339 return element;
2340 },
2341
2342 empty: function(element) {
2343 return $(element).innerHTML.blank();
2344 },
2345
2346 descendantOf: function(element, ancestor) {
2347 element = $(element), ancestor = $(ancestor);
2348
2349 if (element.compareDocumentPosition)
2350 return (element.compareDocumentPosition(ancestor) & 8) === 8;
2351
2352 if (ancestor.contains)
2353 return ancestor.contains(element) && ancestor !== element;
2354
2355 while (element = element.parentNode)
2356 if (element == ancestor) return true;
2357
2358 return false;
2359 },
2360
2361 scrollTo: function(element) {
2362 element = $(element);
2363 var pos = Element.cumulativeOffset(element);
2364 window.scrollTo(pos[0], pos[1]);
2365 return element;
2366 },
2367
2368 getStyle: function(element, style) {
2369 element = $(element);
2370 style = style == 'float' ? 'cssFloat' : style.camelize();
2371 var value = element.style[style];
2372 if (!value || value == 'auto') {
2373 var css = document.defaultView.getComputedStyle(element, null);
2374 value = css ? css[style] : null;
2375 }
2376 if (style == 'opacity') return value ? parseFloat(value) : 1.0;
2377 return value == 'auto' ? null : value;
2378 },
2379
2380 getOpacity: function(element) {
2381 return $(element).getStyle('opacity');
2382 },
2383
2384 setStyle: function(element, styles) {
2385 element = $(element);
2386 var elementStyle = element.style, match;
2387 if (Object.isString(styles)) {
2388 element.style.cssText += ';' + styles;
2389 return styles.include('opacity') ?
2390 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
2391 }
2392 for (var property in styles)
2393 if (property == 'opacity') element.setOpacity(styles[property]);
2394 else
2395 elementStyle[(property == 'float' || property == 'cssFloat') ?
2396 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
2397 property] = styles[property];
2398
2399 return element;
2400 },
2401
2402 setOpacity: function(element, value) {
2403 element = $(element);
2404 element.style.opacity = (value == 1 || value === '') ? '' :
2405 (value < 0.00001) ? 0 : value;
2406 return element;
2407 },
2408
2409 makePositioned: function(element) {
2410 element = $(element);
2411 var pos = Element.getStyle(element, 'position');
2412 if (pos == 'static' || !pos) {
2413 element._madePositioned = true;
2414 element.style.position = 'relative';
2415 if (Prototype.Browser.Opera) {
2416 element.style.top = 0;
2417 element.style.left = 0;
2418 }
2419 }
2420 return element;
2421 },
2422
2423 undoPositioned: function(element) {
2424 element = $(element);
2425 if (element._madePositioned) {
2426 element._madePositioned = undefined;
2427 element.style.position =
2428 element.style.top =
2429 element.style.left =
2430 element.style.bottom =
2431 element.style.right = '';
2432 }
2433 return element;
2434 },
2435
2436 makeClipping: function(element) {
2437 element = $(element);
2438 if (element._overflow) return element;
2439 element._overflow = Element.getStyle(element, 'overflow') || 'auto';
2440 if (element._overflow !== 'hidden')
2441 element.style.overflow = 'hidden';
2442 return element;
2443 },
2444
2445 undoClipping: function(element) {
2446 element = $(element);
2447 if (!element._overflow) return element;
2448 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
2449 element._overflow = null;
2450 return element;
2451 },
2452
2453 clonePosition: function(element, source) {
2454 var options = Object.extend({
2455 setLeft: true,
2456 setTop: true,
2457 setWidth: true,
2458 setHeight: true,
2459 offsetTop: 0,
2460 offsetLeft: 0
2461 }, arguments[2] || { });
2462
2463 source = $(source);
2464 var p = Element.viewportOffset(source), delta = [0, 0], parent = null;
2465
2466 element = $(element);
2467
2468 if (Element.getStyle(element, 'position') == 'absolute') {
2469 parent = Element.getOffsetParent(element);
2470 delta = Element.viewportOffset(parent);
2471 }
2472
2473 if (parent == document.body) {
2474 delta[0] -= document.body.offsetLeft;
2475 delta[1] -= document.body.offsetTop;
2476 }
2477
2478 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
2479 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
2480 if (options.setWidth) element.style.width = source.offsetWidth + 'px';
2481 if (options.setHeight) element.style.height = source.offsetHeight + 'px';
2482 return element;
2483 }
2484 };
2485
2486 Object.extend(Element.Methods, {
2487 getElementsBySelector: Element.Methods.select,
2488
2489 childElements: Element.Methods.immediateDescendants
2490 });
2491
2492 Element._attributeTranslations = {
2493 write: {
2494 names: {
2495 className: 'class',
2496 htmlFor: 'for'
2497 },
2498 values: { }
2499 }
2500 };
2501
2502 if (Prototype.Browser.Opera) {
2503 Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2504 function(proceed, element, style) {
2505 switch (style) {
2506 case 'height': case 'width':
2507 if (!Element.visible(element)) return null;
2508
2509 var dim = parseInt(proceed(element, style), 10);
2510
2511 if (dim !== element['offset' + style.capitalize()])
2512 return dim + 'px';
2513
2514 var properties;
2515 if (style === 'height') {
2516 properties = ['border-top-width', 'padding-top',
2517 'padding-bottom', 'border-bottom-width'];
2518 }
2519 else {
2520 properties = ['border-left-width', 'padding-left',
2521 'padding-right', 'border-right-width'];
2522 }
2523 return properties.inject(dim, function(memo, property) {
2524 var val = proceed(element, property);
2525 return val === null ? memo : memo - parseInt(val, 10);
2526 }) + 'px';
2527 default: return proceed(element, style);
2528 }
2529 }
2530 );
2531
2532 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2533 function(proceed, element, attribute) {
2534 if (attribute === 'title') return element.title;
2535 return proceed(element, attribute);
2536 }
2537 );
2538 }
2539
2540 else if (Prototype.Browser.IE) {
2541 Element.Methods.getStyle = function(element, style) {
2542 element = $(element);
2543 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
2544 var value = element.style[style];
2545 if (!value && element.currentStyle) value = element.currentStyle[style];
2546
2547 if (style == 'opacity') {
2548 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
2549 if (value[1]) return parseFloat(value[1]) / 100;
2550 return 1.0;
2551 }
2552
2553 if (value == 'auto') {
2554 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
2555 return element['offset' + style.capitalize()] + 'px';
2556 return null;
2557 }
2558 return value;
2559 };
2560
2561 Element.Methods.setOpacity = function(element, value) {
2562 function stripAlpha(filter){
2563 return filter.replace(/alpha\([^\)]*\)/gi,'');
2564 }
2565 element = $(element);
2566 var currentStyle = element.currentStyle;
2567 if ((currentStyle && !currentStyle.hasLayout) ||
2568 (!currentStyle && element.style.zoom == 'normal'))
2569 element.style.zoom = 1;
2570
2571 var filter = element.getStyle('filter'), style = element.style;
2572 if (value == 1 || value === '') {
2573 (filter = stripAlpha(filter)) ?
2574 style.filter = filter : style.removeAttribute('filter');
2575 return element;
2576 } else if (value < 0.00001) value = 0;
2577 style.filter = stripAlpha(filter) +
2578 'alpha(opacity=' + (value * 100) + ')';
2579 return element;
2580 };
2581
2582 Element._attributeTranslations = (function(){
2583
2584 var classProp = 'className',
2585 forProp = 'for',
2586 el = document.createElement('div');
2587
2588 el.setAttribute(classProp, 'x');
2589
2590 if (el.className !== 'x') {
2591 el.setAttribute('class', 'x');
2592 if (el.className === 'x') {
2593 classProp = 'class';
2594 }
2595 }
2596 el = null;
2597
2598 el = document.createElement('label');
2599 el.setAttribute(forProp, 'x');
2600 if (el.htmlFor !== 'x') {
2601 el.setAttribute('htmlFor', 'x');
2602 if (el.htmlFor === 'x') {
2603 forProp = 'htmlFor';
2604 }
2605 }
2606 el = null;
2607
2608 return {
2609 read: {
2610 names: {
2611 'class': classProp,
2612 'className': classProp,
2613 'for': forProp,
2614 'htmlFor': forProp
2615 },
2616 values: {
2617 _getAttr: function(element, attribute) {
2618 return element.getAttribute(attribute);
2619 },
2620 _getAttr2: function(element, attribute) {
2621 return element.getAttribute(attribute, 2);
2622 },
2623 _getAttrNode: function(element, attribute) {
2624 var node = element.getAttributeNode(attribute);
2625 return node ? node.value : "";
2626 },
2627 _getEv: (function(){
2628
2629 var el = document.createElement('div'), f;
2630 el.onclick = Prototype.emptyFunction;
2631 var value = el.getAttribute('onclick');
2632
2633 if (String(value).indexOf('{') > -1) {
2634 f = function(element, attribute) {
2635 attribute = element.getAttribute(attribute);
2636 if (!attribute) return null;
2637 attribute = attribute.toString();
2638 attribute = attribute.split('{')[1];
2639 attribute = attribute.split('}')[0];
2640 return attribute.strip();
2641 };
2642 }
2643 else if (value === '') {
2644 f = function(element, attribute) {
2645 attribute = element.getAttribute(attribute);
2646 if (!attribute) return null;
2647 return attribute.strip();
2648 };
2649 }
2650 el = null;
2651 return f;
2652 })(),
2653 _flag: function(element, attribute) {
2654 return $(element).hasAttribute(attribute) ? attribute : null;
2655 },
2656 style: function(element) {
2657 return element.style.cssText.toLowerCase();
2658 },
2659 title: function(element) {
2660 return element.title;
2661 }
2662 }
2663 }
2664 }
2665 })();
2666
2667 Element._attributeTranslations.write = {
2668 names: Object.extend({
2669 cellpadding: 'cellPadding',
2670 cellspacing: 'cellSpacing'
2671 }, Element._attributeTranslations.read.names),
2672 values: {
2673 checked: function(element, value) {
2674 element.checked = !!value;
2675 },
2676
2677 style: function(element, value) {
2678 element.style.cssText = value ? value : '';
2679 }
2680 }
2681 };
2682
2683 Element._attributeTranslations.has = {};
2684
2685 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
2686 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
2687 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
2688 Element._attributeTranslations.has[attr.toLowerCase()] = attr;
2689 });
2690
2691 (function(v) {
2692 Object.extend(v, {
2693 href: v._getAttr2,
2694 src: v._getAttr2,
2695 type: v._getAttr,
2696 action: v._getAttrNode,
2697 disabled: v._flag,
2698 checked: v._flag,
2699 readonly: v._flag,
2700 multiple: v._flag,
2701 onload: v._getEv,
2702 onunload: v._getEv,
2703 onclick: v._getEv,
2704 ondblclick: v._getEv,
2705 onmousedown: v._getEv,
2706 onmouseup: v._getEv,
2707 onmouseover: v._getEv,
2708 onmousemove: v._getEv,
2709 onmouseout: v._getEv,
2710 onfocus: v._getEv,
2711 onblur: v._getEv,
2712 onkeypress: v._getEv,
2713 onkeydown: v._getEv,
2714 onkeyup: v._getEv,
2715 onsubmit: v._getEv,
2716 onreset: v._getEv,
2717 onselect: v._getEv,
2718 onchange: v._getEv
2719 });
2720 })(Element._attributeTranslations.read.values);
2721
2722 if (Prototype.BrowserFeatures.ElementExtensions) {
2723 (function() {
2724 function _descendants(element) {
2725 var nodes = element.getElementsByTagName('*'), results = [];
2726 for (var i = 0, node; node = nodes[i]; i++)
2727 if (node.tagName !== "!") // Filter out comment nodes.
2728 results.push(node);
2729 return results;
2730 }
2731
2732 Element.Methods.down = function(element, expression, index) {
2733 element = $(element);
2734 if (arguments.length == 1) return element.firstDescendant();
2735 return Object.isNumber(expression) ? _descendants(element)[expression] :
2736 Element.select(element, expression)[index || 0];
2737 }
2738 })();
2739 }
2740
2741 }
2742
2743 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
2744 Element.Methods.setOpacity = function(element, value) {
2745 element = $(element);
2746 element.style.opacity = (value == 1) ? 0.999999 :
2747 (value === '') ? '' : (value < 0.00001) ? 0 : value;
2748 return element;
2749 };
2750 }
2751
2752 else if (Prototype.Browser.WebKit) {
2753 Element.Methods.setOpacity = function(element, value) {
2754 element = $(element);
2755 element.style.opacity = (value == 1 || value === '') ? '' :
2756 (value < 0.00001) ? 0 : value;
2757
2758 if (value == 1)
2759 if (element.tagName.toUpperCase() == 'IMG' && element.width) {
2760 element.width++; element.width--;
2761 } else try {
2762 var n = document.createTextNode(' ');
2763 element.appendChild(n);
2764 element.removeChild(n);
2765 } catch (e) { }
2766
2767 return element;
2768 };
2769 }
2770
2771 if ('outerHTML' in document.documentElement) {
2772 Element.Methods.replace = function(element, content) {
2773 element = $(element);
2774
2775 if (content && content.toElement) content = content.toElement();
2776 if (Object.isElement(content)) {
2777 element.parentNode.replaceChild(content, element);
2778 return element;
2779 }
2780
2781 content = Object.toHTML(content);
2782 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2783
2784 if (Element._insertionTranslations.tags[tagName]) {
2785 var nextSibling = element.next(),
2786 fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2787 parent.removeChild(element);
2788 if (nextSibling)
2789 fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
2790 else
2791 fragments.each(function(node) { parent.appendChild(node) });
2792 }
2793 else element.outerHTML = content.stripScripts();
2794
2795 content.evalScripts.bind(content).defer();
2796 return element;
2797 };
2798 }
2799
2800 Element._returnOffset = function(l, t) {
2801 var result = [l, t];
2802 result.left = l;
2803 result.top = t;
2804 return result;
2805 };
2806
2807 Element._getContentFromAnonymousElement = function(tagName, html, force) {
2808 var div = new Element('div'),
2809 t = Element._insertionTranslations.tags[tagName];
2810
2811 var workaround = false;
2812 if (t) workaround = true;
2813 else if (force) {
2814 workaround = true;
2815 t = ['', '', 0];
2816 }
2817
2818 if (workaround) {
2819 div.innerHTML = '&nbsp;' + t[0] + html + t[1];
2820 div.removeChild(div.firstChild);
2821 for (var i = t[2]; i--; ) {
2822 div = div.firstChild;
2823 }
2824 }
2825 else {
2826 div.innerHTML = html;
2827 }
2828 return $A(div.childNodes);
2829 };
2830
2831 Element._insertionTranslations = {
2832 before: function(element, node) {
2833 element.parentNode.insertBefore(node, element);
2834 },
2835 top: function(element, node) {
2836 element.insertBefore(node, element.firstChild);
2837 },
2838 bottom: function(element, node) {
2839 element.appendChild(node);
2840 },
2841 after: function(element, node) {
2842 element.parentNode.insertBefore(node, element.nextSibling);
2843 },
2844 tags: {
2845 TABLE: ['<table>', '</table>', 1],
2846 TBODY: ['<table><tbody>', '</tbody></table>', 2],
2847 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2848 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2849 SELECT: ['<select>', '</select>', 1]
2850 }
2851 };
2852
2853 (function() {
2854 var tags = Element._insertionTranslations.tags;
2855 Object.extend(tags, {
2856 THEAD: tags.TBODY,
2857 TFOOT: tags.TBODY,
2858 TH: tags.TD
2859 });
2860 })();
2861
2862 Element.Methods.Simulated = {
2863 hasAttribute: function(element, attribute) {
2864 attribute = Element._attributeTranslations.has[attribute] || attribute;
2865 var node = $(element).getAttributeNode(attribute);
2866 return !!(node && node.specified);
2867 }
2868 };
2869
2870 Element.Methods.ByTag = { };
2871
2872 Object.extend(Element, Element.Methods);
2873
2874 (function(div) {
2875
2876 if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) {
2877 window.HTMLElement = { };
2878 window.HTMLElement.prototype = div['__proto__'];
2879 Prototype.BrowserFeatures.ElementExtensions = true;
2880 }
2881
2882 div = null;
2883
2884 })(document.createElement('div'));
2885
2886 Element.extend = (function() {
2887
2888 function checkDeficiency(tagName) {
2889 if (typeof window.Element != 'undefined') {
2890 var proto = window.Element.prototype;
2891 if (proto) {
2892 var id = '_' + (Math.random()+'').slice(2),
2893 el = document.createElement(tagName);
2894 proto[id] = 'x';
2895 var isBuggy = (el[id] !== 'x');
2896 delete proto[id];
2897 el = null;
2898 return isBuggy;
2899 }
2900 }
2901 return false;
2902 }
2903
2904 function extendElementWith(element, methods) {
2905 for (var property in methods) {
2906 var value = methods[property];
2907 if (Object.isFunction(value) && !(property in element))
2908 element[property] = value.methodize();
2909 }
2910 }
2911
2912 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');
2913
2914 if (Prototype.BrowserFeatures.SpecificElementExtensions) {
2915 if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
2916 return function(element) {
2917 if (element && typeof element._extendedByPrototype == 'undefined') {
2918 var t = element.tagName;
2919 if (t && (/^(?:object|applet|embed)$/i.test(t))) {
2920 extendElementWith(element, Element.Methods);
2921 extendElementWith(element, Element.Methods.Simulated);
2922 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
2923 }
2924 }
2925 return element;
2926 }
2927 }
2928 return Prototype.K;
2929 }
2930
2931 var Methods = { }, ByTag = Element.Methods.ByTag;
2932
2933 var extend = Object.extend(function(element) {
2934 if (!element || typeof element._extendedByPrototype != 'undefined' ||
2935 element.nodeType != 1 || element == window) return element;
2936
2937 var methods = Object.clone(Methods),
2938 tagName = element.tagName.toUpperCase();
2939
2940 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2941
2942 extendElementWith(element, methods);
2943
2944 element._extendedByPrototype = Prototype.emptyFunction;
2945 return element;
2946
2947 }, {
2948 refresh: function() {
2949 if (!Prototype.BrowserFeatures.ElementExtensions) {
2950 Object.extend(Methods, Element.Methods);
2951 Object.extend(Methods, Element.Methods.Simulated);
2952 }
2953 }
2954 });
2955
2956 extend.refresh();
2957 return extend;
2958 })();
2959
2960 if (document.documentElement.hasAttribute) {
2961 Element.hasAttribute = function(element, attribute) {
2962 return element.hasAttribute(attribute);
2963 };
2964 }
2965 else {
2966 Element.hasAttribute = Element.Methods.Simulated.hasAttribute;
2967 }
2968
2969 Element.addMethods = function(methods) {
2970 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
2971
2972 if (!methods) {
2973 Object.extend(Form, Form.Methods);
2974 Object.extend(Form.Element, Form.Element.Methods);
2975 Object.extend(Element.Methods.ByTag, {
2976 "FORM": Object.clone(Form.Methods),
2977 "INPUT": Object.clone(Form.Element.Methods),
2978 "SELECT": Object.clone(Form.Element.Methods),
2979 "TEXTAREA": Object.clone(Form.Element.Methods),
2980 "BUTTON": Object.clone(Form.Element.Methods)
2981 });
2982 }
2983
2984 if (arguments.length == 2) {
2985 var tagName = methods;
2986 methods = arguments[1];
2987 }
2988
2989 if (!tagName) Object.extend(Element.Methods, methods || { });
2990 else {
2991 if (Object.isArray(tagName)) tagName.each(extend);
2992 else extend(tagName);
2993 }
2994
2995 function extend(tagName) {
2996 tagName = tagName.toUpperCase();
2997 if (!Element.Methods.ByTag[tagName])
2998 Element.Methods.ByTag[tagName] = { };
2999 Object.extend(Element.Methods.ByTag[tagName], methods);
3000 }
3001
3002 function copy(methods, destination, onlyIfAbsent) {
3003 onlyIfAbsent = onlyIfAbsent || false;
3004 for (var property in methods) {
3005 var value = methods[property];
3006 if (!Object.isFunction(value)) continue;
3007 if (!onlyIfAbsent || !(property in destination))
3008 destination[property] = value.methodize();
3009 }
3010 }
3011
3012 function findDOMClass(tagName) {
3013 var klass;
3014 var trans = {
3015 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3016 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3017 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3018 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3019 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3020 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3021 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3022 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3023 "FrameSet", "IFRAME": "IFrame"
3024 };
3025 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3026 if (window[klass]) return window[klass];
3027 klass = 'HTML' + tagName + 'Element';
3028 if (window[klass]) return window[klass];
3029 klass = 'HTML' + tagName.capitalize() + 'Element';
3030 if (window[klass]) return window[klass];
3031
3032 var element = document.createElement(tagName),
3033 proto = element['__proto__'] || element.constructor.prototype;
3034
3035 element = null;
3036 return proto;
3037 }
3038
3039 var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
3040 Element.prototype;
3041
3042 if (F.ElementExtensions) {
3043 copy(Element.Methods, elementPrototype);
3044 copy(Element.Methods.Simulated, elementPrototype, true);
3045 }
3046
3047 if (F.SpecificElementExtensions) {
3048 for (var tag in Element.Methods.ByTag) {
3049 var klass = findDOMClass(tag);
3050 if (Object.isUndefined(klass)) continue;
3051 copy(T[tag], klass.prototype);
3052 }
3053 }
3054
3055 Object.extend(Element, Element.Methods);
3056 delete Element.ByTag;
3057
3058 if (Element.extend.refresh) Element.extend.refresh();
3059 Element.cache = { };
3060 };
3061
3062
3063 document.viewport = {
3064
3065 getDimensions: function() {
3066 return { width: this.getWidth(), height: this.getHeight() };
3067 },
3068
3069 getScrollOffsets: function() {
3070 return Element._returnOffset(
3071 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
3072 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
3073 }
3074 };
3075
3076 (function(viewport) {
3077 var B = Prototype.Browser, doc = document, element, property = {};
3078
3079 function getRootElement() {
3080 if (B.WebKit && !doc.evaluate)
3081 return document;
3082
3083 if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
3084 return document.body;
3085
3086 return document.documentElement;
3087 }
3088
3089 function define(D) {
3090 if (!element) element = getRootElement();
3091
3092 property[D] = 'client' + D;
3093
3094 viewport['get' + D] = function() { return element[property[D]] };
3095 return viewport['get' + D]();
3096 }
3097
3098 viewport.getWidth = define.curry('Width');
3099
3100 viewport.getHeight = define.curry('Height');
3101 })(document.viewport);
3102
3103
3104 Element.Storage = {
3105 UID: 1
3106 };
3107
3108 Element.addMethods({
3109 getStorage: function(element) {
3110 if (!(element = $(element))) return;
3111
3112 var uid;
3113 if (element === window) {
3114 uid = 0;
3115 } else {
3116 if (typeof element._prototypeUID === "undefined")
3117 element._prototypeUID = Element.Storage.UID++;
3118 uid = element._prototypeUID;
3119 }
3120
3121 if (!Element.Storage[uid])
3122 Element.Storage[uid] = $H();
3123
3124 return Element.Storage[uid];
3125 },
3126
3127 store: function(element, key, value) {
3128 if (!(element = $(element))) return;
3129
3130 if (arguments.length === 2) {
3131 Element.getStorage(element).update(key);
3132 } else {
3133 Element.getStorage(element).set(key, value);
3134 }
3135
3136 return element;
3137 },
3138
3139 retrieve: function(element, key, defaultValue) {
3140 if (!(element = $(element))) return;
3141 var hash = Element.getStorage(element), value = hash.get(key);
3142
3143 if (Object.isUndefined(value)) {
3144 hash.set(key, defaultValue);
3145 value = defaultValue;
3146 }
3147
3148 return value;
3149 },
3150
3151 clone: function(element, deep) {
3152 if (!(element = $(element))) return;
3153 var clone = element.cloneNode(deep);
3154 clone._prototypeUID = void 0;
3155 if (deep) {
3156 var descendants = Element.select(clone, '*'),
3157 i = descendants.length;
3158 while (i--) {
3159 descendants[i]._prototypeUID = void 0;
3160 }
3161 }
3162 return Element.extend(clone);
3163 },
3164
3165 purge: function(element) {
3166 if (!(element = $(element))) return;
3167 var purgeElement = Element._purgeElement;
3168
3169 purgeElement(element);
3170
3171 var descendants = element.getElementsByTagName('*'),
3172 i = descendants.length;
3173
3174 while (i--) purgeElement(descendants[i]);
3175
3176 return null;
3177 }
3178 });
3179
3180 (function() {
3181
3182 function toDecimal(pctString) {
3183 var match = pctString.match(/^(\d+)%?$/i);
3184 if (!match) return null;
3185 return (Number(match[1]) / 100);
3186 }
3187
3188 function getPixelValue(value, property, context) {
3189 var element = null;
3190 if (Object.isElement(value)) {
3191 element = value;
3192 value = element.getStyle(property);
3193 }
3194
3195 if (value === null) {
3196 return null;
3197 }
3198
3199 if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
3200 return window.parseFloat(value);
3201 }
3202
3203 var isPercentage = value.include('%'), isViewport = (context === document.viewport);
3204
3205 if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
3206 var style = element.style.left, rStyle = element.runtimeStyle.left;
3207 element.runtimeStyle.left = element.currentStyle.left;
3208 element.style.left = value || 0;
3209 value = element.style.pixelLeft;
3210 element.style.left = style;
3211 element.runtimeStyle.left = rStyle;
3212
3213 return value;
3214 }
3215
3216 if (element && isPercentage) {
3217 context = context || element.parentNode;
3218 var decimal = toDecimal(value);
3219 var whole = null;
3220 var position = element.getStyle('position');
3221
3222 var isHorizontal = property.include('left') || property.include('right') ||
3223 property.include('width');
3224
3225 var isVertical = property.include('top') || property.include('bottom') ||
3226 property.include('height');
3227
3228 if (context === document.viewport) {
3229 if (isHorizontal) {
3230 whole = document.viewport.getWidth();
3231 } else if (isVertical) {
3232 whole = document.viewport.getHeight();
3233 }
3234 } else {
3235 if (isHorizontal) {
3236 whole = $(context).measure('width');
3237 } else if (isVertical) {
3238 whole = $(context).measure('height');
3239 }
3240 }
3241
3242 return (whole === null) ? 0 : whole * decimal;
3243 }
3244
3245 return 0;
3246 }
3247
3248 function toCSSPixels(number) {
3249 if (Object.isString(number) && number.endsWith('px')) {
3250 return number;
3251 }
3252 return number + 'px';
3253 }
3254
3255 function isDisplayed(element) {
3256 var originalElement = element;
3257 while (element && element.parentNode) {
3258 var display = element.getStyle('display');
3259 if (display === 'none') {
3260 return false;
3261 }
3262 element = $(element.parentNode);
3263 }
3264 return true;
3265 }
3266
3267 var hasLayout = Prototype.K;
3268 if ('currentStyle' in document.documentElement) {
3269 hasLayout = function(element) {
3270 if (!element.currentStyle.hasLayout) {
3271 element.style.zoom = 1;
3272 }
3273 return element;
3274 };
3275 }
3276
3277 function cssNameFor(key) {
3278 if (key.include('border')) key = key + '-width';
3279 return key.camelize();
3280 }
3281
3282 Element.Layout = Class.create(Hash, {
3283 initialize: function($super, element, preCompute) {
3284 $super();
3285 this.element = $(element);
3286
3287 Element.Layout.PROPERTIES.each( function(property) {
3288 this._set(property, null);
3289 }, this);
3290
3291 if (preCompute) {
3292 this._preComputing = true;
3293 this._begin();
3294 Element.Layout.PROPERTIES.each( this._compute, this );
3295 this._end();
3296 this._preComputing = false;
3297 }
3298 },
3299
3300 _set: function(property, value) {
3301 return Hash.prototype.set.call(this, property, value);
3302 },
3303
3304 set: function(property, value) {
3305 throw "Properties of Element.Layout are read-only.";
3306 },
3307
3308 get: function($super, property) {
3309 var value = $super(property);
3310 return value === null ? this._compute(property) : value;
3311 },
3312
3313 _begin: function() {
3314 if (this._prepared) return;
3315
3316 var element = this.element;
3317 if (isDisplayed(element)) {
3318 this._prepared = true;
3319 return;
3320 }
3321
3322 var originalStyles = {
3323 position: element.style.position || '',
3324 width: element.style.width || '',
3325 visibility: element.style.visibility || '',
3326 display: element.style.display || ''
3327 };
3328
3329 element.store('prototype_original_styles', originalStyles);
3330
3331 var position = element.getStyle('position'),
3332 width = element.getStyle('width');
3333
3334 if (width === "0px" || width === null) {
3335 element.style.display = 'block';
3336 width = element.getStyle('width');
3337 }
3338
3339 var context = (position === 'fixed') ? document.viewport :
3340 element.parentNode;
3341
3342 element.setStyle({
3343 position: 'absolute',
3344 visibility: 'hidden',
3345 display: 'block'
3346 });
3347
3348 var positionedWidth = element.getStyle('width');
3349
3350 var newWidth;
3351 if (width && (positionedWidth === width)) {
3352 newWidth = getPixelValue(element, 'width', context);
3353 } else if (position === 'absolute' || position === 'fixed') {
3354 newWidth = getPixelValue(element, 'width', context);
3355 } else {
3356 var parent = element.parentNode, pLayout = $(parent).getLayout();
3357
3358 newWidth = pLayout.get('width') -
3359 this.get('margin-left') -
3360 this.get('border-left') -
3361 this.get('padding-left') -
3362 this.get('padding-right') -
3363 this.get('border-right') -
3364 this.get('margin-right');
3365 }
3366
3367 element.setStyle({ width: newWidth + 'px' });
3368
3369 this._prepared = true;
3370 },
3371
3372 _end: function() {
3373 var element = this.element;
3374 var originalStyles = element.retrieve('prototype_original_styles');
3375 element.store('prototype_original_styles', null);
3376 element.setStyle(originalStyles);
3377 this._prepared = false;
3378 },
3379
3380 _compute: function(property) {
3381 var COMPUTATIONS = Element.Layout.COMPUTATIONS;
3382 if (!(property in COMPUTATIONS)) {
3383 throw "Property not found.";
3384 }
3385
3386 return this._set(property, COMPUTATIONS[property].call(this, this.element));
3387 },
3388
3389 toObject: function() {
3390 var args = $A(arguments);
3391 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3392 args.join(' ').split(' ');
3393 var obj = {};
3394 keys.each( function(key) {
3395 if (!Element.Layout.PROPERTIES.include(key)) return;
3396 var value = this.get(key);
3397 if (value != null) obj[key] = value;
3398 }, this);
3399 return obj;
3400 },
3401
3402 toHash: function() {
3403 var obj = this.toObject.apply(this, arguments);
3404 return new Hash(obj);
3405 },
3406
3407 toCSS: function() {
3408 var args = $A(arguments);
3409 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3410 args.join(' ').split(' ');
3411 var css = {};
3412
3413 keys.each( function(key) {
3414 if (!Element.Layout.PROPERTIES.include(key)) return;
3415 if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
3416
3417 var value = this.get(key);
3418 if (value != null) css[cssNameFor(key)] = value + 'px';
3419 }, this);
3420 return css;
3421 },
3422
3423 inspect: function() {
3424 return "#<Element.Layout>";
3425 }
3426 });
3427
3428 Object.extend(Element.Layout, {
3429 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'),
3430
3431 COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
3432
3433 COMPUTATIONS: {
3434 'height': function(element) {
3435 if (!this._preComputing) this._begin();
3436
3437 var bHeight = this.get('border-box-height');
3438 if (bHeight <= 0) {
3439 if (!this._preComputing) this._end();
3440 return 0;
3441 }
3442
3443 var bTop = this.get('border-top'),
3444 bBottom = this.get('border-bottom');
3445
3446 var pTop = this.get('padding-top'),
3447 pBottom = this.get('padding-bottom');
3448
3449 if (!this._preComputing) this._end();
3450
3451 return bHeight - bTop - bBottom - pTop - pBottom;
3452 },
3453
3454 'width': function(element) {
3455 if (!this._preComputing) this._begin();
3456
3457 var bWidth = this.get('border-box-width');
3458 if (bWidth <= 0) {
3459 if (!this._preComputing) this._end();
3460 return 0;
3461 }
3462
3463 var bLeft = this.get('border-left'),
3464 bRight = this.get('border-right');
3465
3466 var pLeft = this.get('padding-left'),
3467 pRight = this.get('padding-right');
3468
3469 if (!this._preComputing) this._end();
3470
3471 return bWidth - bLeft - bRight - pLeft - pRight;
3472 },
3473
3474 'padding-box-height': function(element) {
3475 var height = this.get('height'),
3476 pTop = this.get('padding-top'),
3477 pBottom = this.get('padding-bottom');
3478
3479 return height + pTop + pBottom;
3480 },
3481
3482 'padding-box-width': function(element) {
3483 var width = this.get('width'),
3484 pLeft = this.get('padding-left'),
3485 pRight = this.get('padding-right');
3486
3487 return width + pLeft + pRight;
3488 },
3489
3490 'border-box-height': function(element) {
3491 if (!this._preComputing) this._begin();
3492 var height = element.offsetHeight;
3493 if (!this._preComputing) this._end();
3494 return height;
3495 },
3496
3497 'border-box-width': function(element) {
3498 if (!this._preComputing) this._begin();
3499 var width = element.offsetWidth;
3500 if (!this._preComputing) this._end();
3501 return width;
3502 },
3503
3504 'margin-box-height': function(element) {
3505 var bHeight = this.get('border-box-height'),
3506 mTop = this.get('margin-top'),
3507 mBottom = this.get('margin-bottom');
3508
3509 if (bHeight <= 0) return 0;
3510
3511 return bHeight + mTop + mBottom;
3512 },
3513
3514 'margin-box-width': function(element) {
3515 var bWidth = this.get('border-box-width'),
3516 mLeft = this.get('margin-left'),
3517 mRight = this.get('margin-right');
3518
3519 if (bWidth <= 0) return 0;
3520
3521 return bWidth + mLeft + mRight;
3522 },
3523
3524 'top': function(element) {
3525 var offset = element.positionedOffset();
3526 return offset.top;
3527 },
3528
3529 'bottom': function(element) {
3530 var offset = element.positionedOffset(),
3531 parent = element.getOffsetParent(),
3532 pHeight = parent.measure('height');
3533
3534 var mHeight = this.get('border-box-height');
3535
3536 return pHeight - mHeight - offset.top;
3537 },
3538
3539 'left': function(element) {
3540 var offset = element.positionedOffset();
3541 return offset.left;
3542 },
3543
3544 'right': function(element) {
3545 var offset = element.positionedOffset(),
3546 parent = element.getOffsetParent(),
3547 pWidth = parent.measure('width');
3548
3549 var mWidth = this.get('border-box-width');
3550
3551 return pWidth - mWidth - offset.left;
3552 },
3553
3554 'padding-top': function(element) {
3555 return getPixelValue(element, 'paddingTop');
3556 },
3557
3558 'padding-bottom': function(element) {
3559 return getPixelValue(element, 'paddingBottom');
3560 },
3561
3562 'padding-left': function(element) {
3563 return getPixelValue(element, 'paddingLeft');
3564 },
3565
3566 'padding-right': function(element) {
3567 return getPixelValue(element, 'paddingRight');
3568 },
3569
3570 'border-top': function(element) {
3571 return getPixelValue(element, 'borderTopWidth');
3572 },
3573
3574 'border-bottom': function(element) {
3575 return getPixelValue(element, 'borderBottomWidth');
3576 },
3577
3578 'border-left': function(element) {
3579 return getPixelValue(element, 'borderLeftWidth');
3580 },
3581
3582 'border-right': function(element) {
3583 return getPixelValue(element, 'borderRightWidth');
3584 },
3585
3586 'margin-top': function(element) {
3587 return getPixelValue(element, 'marginTop');
3588 },
3589
3590 'margin-bottom': function(element) {
3591 return getPixelValue(element, 'marginBottom');
3592 },
3593
3594 'margin-left': function(element) {
3595 return getPixelValue(element, 'marginLeft');
3596 },
3597
3598 'margin-right': function(element) {
3599 return getPixelValue(element, 'marginRight');
3600 }
3601 }
3602 });
3603
3604 if ('getBoundingClientRect' in document.documentElement) {
3605 Object.extend(Element.Layout.COMPUTATIONS, {
3606 'right': function(element) {
3607 var parent = hasLayout(element.getOffsetParent());
3608 var rect = element.getBoundingClientRect(),
3609 pRect = parent.getBoundingClientRect();
3610
3611 return (pRect.right - rect.right).round();
3612 },
3613
3614 'bottom': function(element) {
3615 var parent = hasLayout(element.getOffsetParent());
3616 var rect = element.getBoundingClientRect(),
3617 pRect = parent.getBoundingClientRect();
3618
3619 return (pRect.bottom - rect.bottom).round();
3620 }
3621 });
3622 }
3623
3624 Element.Offset = Class.create({
3625 initialize: function(left, top) {
3626 this.left = left.round();
3627 this.top = top.round();
3628
3629 this[0] = this.left;
3630 this[1] = this.top;
3631 },
3632
3633 relativeTo: function(offset) {
3634 return new Element.Offset(
3635 this.left - offset.left,
3636 this.top - offset.top
3637 );
3638 },
3639
3640 inspect: function() {
3641 return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
3642 },
3643
3644 toString: function() {
3645 return "[#{left}, #{top}]".interpolate(this);
3646 },
3647
3648 toArray: function() {
3649 return [this.left, this.top];
3650 }
3651 });
3652
3653 function getLayout(element, preCompute) {
3654 return new Element.Layout(element, preCompute);
3655 }
3656
3657 function measure(element, property) {
3658 return $(element).getLayout().get(property);
3659 }
3660
3661 function getDimensions(element) {
3662 element = $(element);
3663 var display = Element.getStyle(element, 'display');
3664
3665 if (display && display !== 'none') {
3666 return { width: element.offsetWidth, height: element.offsetHeight };
3667 }
3668
3669 var style = element.style;
3670 var originalStyles = {
3671 visibility: style.visibility,
3672 position: style.position,
3673 display: style.display
3674 };
3675
3676 var newStyles = {
3677 visibility: 'hidden',
3678 display: 'block'
3679 };
3680
3681 if (originalStyles.position !== 'fixed')
3682 newStyles.position = 'absolute';
3683
3684 Element.setStyle(element, newStyles);
3685
3686 var dimensions = {
3687 width: element.offsetWidth,
3688 height: element.offsetHeight
3689 };
3690
3691 Element.setStyle(element, originalStyles);
3692
3693 return dimensions;
3694 }
3695
3696 function getOffsetParent(element) {
3697 element = $(element);
3698
3699 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
3700 return $(document.body);
3701
3702 var isInline = (Element.getStyle(element, 'display') === 'inline');
3703 if (!isInline && element.offsetParent) return $(element.offsetParent);
3704
3705 while ((element = element.parentNode) && element !== document.body) {
3706 if (Element.getStyle(element, 'position') !== 'static') {
3707 return isHtml(element) ? $(document.body) : $(element);
3708 }
3709 }
3710
3711 return $(document.body);
3712 }
3713
3714
3715 function cumulativeOffset(element) {
3716 element = $(element);
3717 var valueT = 0, valueL = 0;
3718 if (element.parentNode) {
3719 do {
3720 valueT += element.offsetTop || 0;
3721 valueL += element.offsetLeft || 0;
3722 element = element.offsetParent;
3723 } while (element);
3724 }
3725 return new Element.Offset(valueL, valueT);
3726 }
3727
3728 function positionedOffset(element) {
3729 element = $(element);
3730
3731 var layout = element.getLayout();
3732
3733 var valueT = 0, valueL = 0;
3734 do {
3735 valueT += element.offsetTop || 0;
3736 valueL += element.offsetLeft || 0;
3737 element = element.offsetParent;
3738 if (element) {
3739 if (isBody(element)) break;
3740 var p = Element.getStyle(element, 'position');
3741 if (p !== 'static') break;
3742 }
3743 } while (element);
3744
3745 valueL -= layout.get('margin-top');
3746 valueT -= layout.get('margin-left');
3747
3748 return new Element.Offset(valueL, valueT);
3749 }
3750
3751 function cumulativeScrollOffset(element) {
3752 var valueT = 0, valueL = 0;
3753 do {
3754 valueT += element.scrollTop || 0;
3755 valueL += element.scrollLeft || 0;
3756 element = element.parentNode;
3757 } while (element);
3758 return new Element.Offset(valueL, valueT);
3759 }
3760
3761 function viewportOffset(forElement) {
3762 element = $(element);
3763 var valueT = 0, valueL = 0, docBody = document.body;
3764
3765 var element = forElement;
3766 do {
3767 valueT += element.offsetTop || 0;
3768 valueL += element.offsetLeft || 0;
3769 if (element.offsetParent == docBody &&
3770 Element.getStyle(element, 'position') == 'absolute') break;
3771 } while (element = element.offsetParent);
3772
3773 element = forElement;
3774 do {
3775 if (element != docBody) {
3776 valueT -= element.scrollTop || 0;
3777 valueL -= element.scrollLeft || 0;
3778 }
3779 } while (element = element.parentNode);
3780 return new Element.Offset(valueL, valueT);
3781 }
3782
3783 function absolutize(element) {
3784 element = $(element);
3785
3786 if (Element.getStyle(element, 'position') === 'absolute') {
3787 return element;
3788 }
3789
3790 var offsetParent = getOffsetParent(element);
3791 var eOffset = element.viewportOffset(),
3792 pOffset = offsetParent.viewportOffset();
3793
3794 var offset = eOffset.relativeTo(pOffset);
3795 var layout = element.getLayout();
3796
3797 element.store('prototype_absolutize_original_styles', {
3798 left: element.getStyle('left'),
3799 top: element.getStyle('top'),
3800 width: element.getStyle('width'),
3801 height: element.getStyle('height')
3802 });
3803
3804 element.setStyle({
3805 position: 'absolute',
3806 top: offset.top + 'px',
3807 left: offset.left + 'px',
3808 width: layout.get('width') + 'px',
3809 height: layout.get('height') + 'px'
3810 });
3811
3812 return element;
3813 }
3814
3815 function relativize(element) {
3816 element = $(element);
3817 if (Element.getStyle(element, 'position') === 'relative') {
3818 return element;
3819 }
3820
3821 var originalStyles =
3822 element.retrieve('prototype_absolutize_original_styles');
3823
3824 if (originalStyles) element.setStyle(originalStyles);
3825 return element;
3826 }
3827
3828 if (Prototype.Browser.IE) {
3829 getOffsetParent = getOffsetParent.wrap(
3830 function(proceed, element) {
3831 element = $(element);
3832
3833 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
3834 return $(document.body);
3835
3836 var position = element.getStyle('position');
3837 if (position !== 'static') return proceed(element);
3838
3839 element.setStyle({ position: 'relative' });
3840 var value = proceed(element);
3841 element.setStyle({ position: position });
3842 return value;
3843 }
3844 );
3845
3846 positionedOffset = positionedOffset.wrap(function(proceed, element) {
3847 element = $(element);
3848 if (!element.parentNode) return new Element.Offset(0, 0);
3849 var position = element.getStyle('position');
3850 if (position !== 'static') return proceed(element);
3851
3852 var offsetParent = element.getOffsetParent();
3853 if (offsetParent && offsetParent.getStyle('position') === 'fixed')
3854 hasLayout(offsetParent);
3855
3856 element.setStyle({ position: 'relative' });
3857 var value = proceed(element);
3858 element.setStyle({ position: position });
3859 return value;
3860 });
3861 } else if (Prototype.Browser.Webkit) {
3862 cumulativeOffset = function(element) {
3863 element = $(element);
3864 var valueT = 0, valueL = 0;
3865 do {
3866 valueT += element.offsetTop || 0;
3867 valueL += element.offsetLeft || 0;
3868 if (element.offsetParent == document.body)
3869 if (Element.getStyle(element, 'position') == 'absolute') break;
3870
3871 element = element.offsetParent;
3872 } while (element);
3873
3874 return new Element.Offset(valueL, valueT);
3875 };
3876 }
3877
3878
3879 Element.addMethods({
3880 getLayout: getLayout,
3881 measure: measure,
3882 getDimensions: getDimensions,
3883 getOffsetParent: getOffsetParent,
3884 cumulativeOffset: cumulativeOffset,
3885 positionedOffset: positionedOffset,
3886 cumulativeScrollOffset: cumulativeScrollOffset,
3887 viewportOffset: viewportOffset,
3888 absolutize: absolutize,
3889 relativize: relativize
3890 });
3891
3892 function isBody(element) {
3893 return element.nodeName.toUpperCase() === 'BODY';
3894 }
3895
3896 function isHtml(element) {
3897 return element.nodeName.toUpperCase() === 'HTML';
3898 }
3899
3900 function isDocument(element) {
3901 return element.nodeType === Node.DOCUMENT_NODE;
3902 }
3903
3904 function isDetached(element) {
3905 return element !== document.body &&
3906 !Element.descendantOf(element, document.body);
3907 }
3908
3909 if ('getBoundingClientRect' in document.documentElement) {
3910 Element.addMethods({
3911 viewportOffset: function(element) {
3912 element = $(element);
3913 if (isDetached(element)) return new Element.Offset(0, 0);
3914
3915 var rect = element.getBoundingClientRect(),
3916 docEl = document.documentElement;
3917 return new Element.Offset(rect.left - docEl.clientLeft,
3918 rect.top - docEl.clientTop);
3919 }
3920 });
3921 }
3922 })();
3923 window.$$ = function() {
3924 var expression = $A(arguments).join(', ');
3925 return Prototype.Selector.select(expression, document);
3926 };
3927
3928 Prototype.Selector = (function() {
3929
3930 function select() {
3931 throw new Error('Method "Prototype.Selector.select" must be defined.');
3932 }
3933
3934 function match() {
3935 throw new Error('Method "Prototype.Selector.match" must be defined.');
3936 }
3937
3938 function find(elements, expression, index) {
3939 index = index || 0;
3940 var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
3941
3942 for (i = 0; i < length; i++) {
3943 if (match(elements[i], expression) && index == matchIndex++) {
3944 return Element.extend(elements[i]);
3945 }
3946 }
3947 }
3948
3949 function extendElements(elements) {
3950 for (var i = 0, length = elements.length; i < length; i++) {
3951 Element.extend(elements[i]);
3952 }
3953 return elements;
3954 }
3955
3956
3957 var K = Prototype.K;
3958
3959 return {
3960 select: select,
3961 match: match,
3962 find: find,
3963 extendElements: (Element.extend === K) ? K : extendElements,
3964 extendElement: Element.extend
3965 };
3966 })();
3967 Prototype._original_property = window.Sizzle;
3968 /*!
3969 * Sizzle CSS Selector Engine - v1.0
3970 * Copyright 2009, The Dojo Foundation
3971 * Released under the MIT, BSD, and GPL Licenses.
3972 * More information: http://sizzlejs.com/
3973 */
3974 (function(){
3975
3976 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3977 done = 0,
3978 toString = Object.prototype.toString,
3979 hasDuplicate = false,
3980 baseHasDuplicate = true;
3981
3982 [0, 0].sort(function(){
3983 baseHasDuplicate = false;
3984 return 0;
3985 });
3986
3987 var Sizzle = function(selector, context, results, seed) {
3988 results = results || [];
3989 var origContext = context = context || document;
3990
3991 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
3992 return [];
3993 }
3994
3995 if ( !selector || typeof selector !== "string" ) {
3996 return results;
3997 }
3998
3999 var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context),
4000 soFar = selector;
4001
4002 while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
4003 soFar = m[3];
4004
4005 parts.push( m[1] );
4006
4007 if ( m[2] ) {
4008 extra = m[3];
4009 break;
4010 }
4011 }
4012
4013 if ( parts.length > 1 && origPOS.exec( selector ) ) {
4014 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
4015 set = posProcess( parts[0] + parts[1], context );
4016 } else {
4017 set = Expr.relative[ parts[0] ] ?
4018 [ context ] :
4019 Sizzle( parts.shift(), context );
4020
4021 while ( parts.length ) {
4022 selector = parts.shift();
4023
4024 if ( Expr.relative[ selector ] )
4025 selector += parts.shift();
4026
4027 set = posProcess( selector, set );
4028 }
4029 }
4030 } else {
4031 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
4032 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
4033 var ret = Sizzle.find( parts.shift(), context, contextXML );
4034 context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
4035 }
4036
4037 if ( context ) {
4038 var ret = seed ?
4039 { expr: parts.pop(), set: makeArray(seed) } :
4040 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
4041 set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
4042
4043 if ( parts.length > 0 ) {
4044 checkSet = makeArray(set);
4045 } else {
4046 prune = false;
4047 }
4048
4049 while ( parts.length ) {
4050 var cur = parts.pop(), pop = cur;
4051
4052 if ( !Expr.relative[ cur ] ) {
4053 cur = "";
4054 } else {
4055 pop = parts.pop();
4056 }
4057
4058 if ( pop == null ) {
4059 pop = context;
4060 }
4061
4062 Expr.relative[ cur ]( checkSet, pop, contextXML );
4063 }
4064 } else {
4065 checkSet = parts = [];
4066 }
4067 }
4068
4069 if ( !checkSet ) {
4070 checkSet = set;
4071 }
4072
4073 if ( !checkSet ) {
4074 throw "Syntax error, unrecognized expression: " + (cur || selector);
4075 }
4076
4077 if ( toString.call(checkSet) === "[object Array]" ) {
4078 if ( !prune ) {
4079 results.push.apply( results, checkSet );
4080 } else if ( context && context.nodeType === 1 ) {
4081 for ( var i = 0; checkSet[i] != null; i++ ) {
4082 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
4083 results.push( set[i] );
4084 }
4085 }
4086 } else {
4087 for ( var i = 0; checkSet[i] != null; i++ ) {
4088 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4089 results.push( set[i] );
4090 }
4091 }
4092 }
4093 } else {
4094 makeArray( checkSet, results );
4095 }
4096
4097 if ( extra ) {
4098 Sizzle( extra, origContext, results, seed );
4099 Sizzle.uniqueSort( results );
4100 }
4101
4102 return results;
4103 };
4104
4105 Sizzle.uniqueSort = function(results){
4106 if ( sortOrder ) {
4107 hasDuplicate = baseHasDuplicate;
4108 results.sort(sortOrder);
4109
4110 if ( hasDuplicate ) {
4111 for ( var i = 1; i < results.length; i++ ) {
4112 if ( results[i] === results[i-1] ) {
4113 results.splice(i--, 1);
4114 }
4115 }
4116 }
4117 }
4118
4119 return results;
4120 };
4121
4122 Sizzle.matches = function(expr, set){
4123 return Sizzle(expr, null, null, set);
4124 };
4125
4126 Sizzle.find = function(expr, context, isXML){
4127 var set, match;
4128
4129 if ( !expr ) {
4130 return [];
4131 }
4132
4133 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
4134 var type = Expr.order[i], match;
4135
4136 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4137 var left = match[1];
4138 match.splice(1,1);
4139
4140 if ( left.substr( left.length - 1 ) !== "\\" ) {
4141 match[1] = (match[1] || "").replace(/\\/g, "");
4142 set = Expr.find[ type ]( match, context, isXML );
4143 if ( set != null ) {
4144 expr = expr.replace( Expr.match[ type ], "" );
4145 break;
4146 }
4147 }
4148 }
4149 }
4150
4151 if ( !set ) {
4152 set = context.getElementsByTagName("*");
4153 }
4154
4155 return {set: set, expr: expr};
4156 };
4157
4158 Sizzle.filter = function(expr, set, inplace, not){
4159 var old = expr, result = [], curLoop = set, match, anyFound,
4160 isXMLFilter = set && set[0] && isXML(set[0]);
4161
4162 while ( expr && set.length ) {
4163 for ( var type in Expr.filter ) {
4164 if ( (match = Expr.match[ type ].exec( expr )) != null ) {
4165 var filter = Expr.filter[ type ], found, item;
4166 anyFound = false;
4167
4168 if ( curLoop == result ) {
4169 result = [];
4170 }
4171
4172 if ( Expr.preFilter[ type ] ) {
4173 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4174
4175 if ( !match ) {
4176 anyFound = found = true;
4177 } else if ( match === true ) {
4178 continue;
4179 }
4180 }
4181
4182 if ( match ) {
4183 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
4184 if ( item ) {
4185 found = filter( item, match, i, curLoop );
4186 var pass = not ^ !!found;
4187
4188 if ( inplace && found != null ) {
4189 if ( pass ) {
4190 anyFound = true;
4191 } else {
4192 curLoop[i] = false;
4193 }
4194 } else if ( pass ) {
4195 result.push( item );
4196 anyFound = true;
4197 }
4198 }
4199 }
4200 }
4201
4202 if ( found !== undefined ) {
4203 if ( !inplace ) {
4204 curLoop = result;
4205 }
4206
4207 expr = expr.replace( Expr.match[ type ], "" );
4208
4209 if ( !anyFound ) {
4210 return [];
4211 }
4212
4213 break;
4214 }
4215 }
4216 }
4217
4218 if ( expr == old ) {
4219 if ( anyFound == null ) {
4220 throw "Syntax error, unrecognized expression: " + expr;
4221 } else {
4222 break;
4223 }
4224 }
4225
4226 old = expr;
4227 }
4228
4229 return curLoop;
4230 };
4231
4232 var Expr = Sizzle.selectors = {
4233 order: [ "ID", "NAME", "TAG" ],
4234 match: {
4235 ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
4236 CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
4237 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
4238 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
4239 TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
4240 CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
4241 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
4242 PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
4243 },
4244 leftMatch: {},
4245 attrMap: {
4246 "class": "className",
4247 "for": "htmlFor"
4248 },
4249 attrHandle: {
4250 href: function(elem){
4251 return elem.getAttribute("href");
4252 }
4253 },
4254 relative: {
4255 "+": function(checkSet, part, isXML){
4256 var isPartStr = typeof part === "string",
4257 isTag = isPartStr && !/\W/.test(part),
4258 isPartStrNotTag = isPartStr && !isTag;
4259
4260 if ( isTag && !isXML ) {
4261 part = part.toUpperCase();
4262 }
4263
4264 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4265 if ( (elem = checkSet[i]) ) {
4266 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4267
4268 checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
4269 elem || false :
4270 elem === part;
4271 }
4272 }
4273
4274 if ( isPartStrNotTag ) {
4275 Sizzle.filter( part, checkSet, true );
4276 }
4277 },
4278 ">": function(checkSet, part, isXML){
4279 var isPartStr = typeof part === "string";
4280
4281 if ( isPartStr && !/\W/.test(part) ) {
4282 part = isXML ? part : part.toUpperCase();
4283
4284 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4285 var elem = checkSet[i];
4286 if ( elem ) {
4287 var parent = elem.parentNode;
4288 checkSet[i] = parent.nodeName === part ? parent : false;
4289 }
4290 }
4291 } else {
4292 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4293 var elem = checkSet[i];
4294 if ( elem ) {
4295 checkSet[i] = isPartStr ?
4296 elem.parentNode :
4297 elem.parentNode === part;
4298 }
4299 }
4300
4301 if ( isPartStr ) {
4302 Sizzle.filter( part, checkSet, true );
4303 }
4304 }
4305 },
4306 "": function(checkSet, part, isXML){
4307 var doneName = done++, checkFn = dirCheck;
4308
4309 if ( !/\W/.test(part) ) {
4310 var nodeCheck = part = isXML ? part : part.toUpperCase();
4311 checkFn = dirNodeCheck;
4312 }
4313
4314 checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
4315 },
4316 "~": function(checkSet, part, isXML){
4317 var doneName = done++, checkFn = dirCheck;
4318
4319 if ( typeof part === "string" && !/\W/.test(part) ) {
4320 var nodeCheck = part = isXML ? part : part.toUpperCase();
4321 checkFn = dirNodeCheck;
4322 }
4323
4324 checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
4325 }
4326 },
4327 find: {
4328 ID: function(match, context, isXML){
4329 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4330 var m = context.getElementById(match[1]);
4331 return m ? [m] : [];
4332 }
4333 },
4334 NAME: function(match, context, isXML){
4335 if ( typeof context.getElementsByName !== "undefined" ) {
4336 var ret = [], results = context.getElementsByName(match[1]);
4337
4338 for ( var i = 0, l = results.length; i < l; i++ ) {
4339 if ( results[i].getAttribute("name") === match[1] ) {
4340 ret.push( results[i] );
4341 }
4342 }
4343
4344 return ret.length === 0 ? null : ret;
4345 }
4346 },
4347 TAG: function(match, context){
4348 return context.getElementsByTagName(match[1]);
4349 }
4350 },
4351 preFilter: {
4352 CLASS: function(match, curLoop, inplace, result, not, isXML){
4353 match = " " + match[1].replace(/\\/g, "") + " ";
4354
4355 if ( isXML ) {
4356 return match;
4357 }
4358
4359 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
4360 if ( elem ) {
4361 if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
4362 if ( !inplace )
4363 result.push( elem );
4364 } else if ( inplace ) {
4365 curLoop[i] = false;
4366 }
4367 }
4368 }
4369
4370 return false;
4371 },
4372 ID: function(match){
4373 return match[1].replace(/\\/g, "");
4374 },
4375 TAG: function(match, curLoop){
4376 for ( var i = 0; curLoop[i] === false; i++ ){}
4377 return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
4378 },
4379 CHILD: function(match){
4380 if ( match[1] == "nth" ) {
4381 var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
4382 match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
4383 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
4384
4385 match[2] = (test[1] + (test[2] || 1)) - 0;
4386 match[3] = test[3] - 0;
4387 }
4388
4389 match[0] = done++;
4390
4391 return match;
4392 },
4393 ATTR: function(match, curLoop, inplace, result, not, isXML){
4394 var name = match[1].replace(/\\/g, "");
4395
4396 if ( !isXML && Expr.attrMap[name] ) {
4397 match[1] = Expr.attrMap[name];
4398 }
4399
4400 if ( match[2] === "~=" ) {
4401 match[4] = " " + match[4] + " ";
4402 }
4403
4404 return match;
4405 },
4406 PSEUDO: function(match, curLoop, inplace, result, not){
4407 if ( match[1] === "not" ) {
4408 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
4409 match[3] = Sizzle(match[3], null, null, curLoop);
4410 } else {
4411 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
4412 if ( !inplace ) {
4413 result.push.apply( result, ret );
4414 }
4415 return false;
4416 }
4417 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
4418 return true;
4419 }
4420
4421 return match;
4422 },
4423 POS: function(match){
4424 match.unshift( true );
4425 return match;
4426 }
4427 },
4428 filters: {
4429 enabled: function(elem){
4430 return elem.disabled === false && elem.type !== "hidden";
4431 },
4432 disabled: function(elem){
4433 return elem.disabled === true;
4434 },
4435 checked: function(elem){
4436 return elem.checked === true;
4437 },
4438 selected: function(elem){
4439 elem.parentNode.selectedIndex;
4440 return elem.selected === true;
4441 },
4442 parent: function(elem){
4443 return !!elem.firstChild;
4444 },
4445 empty: function(elem){
4446 return !elem.firstChild;
4447 },
4448 has: function(elem, i, match){
4449 return !!Sizzle( match[3], elem ).length;
4450 },
4451 header: function(elem){
4452 return /h\d/i.test( elem.nodeName );
4453 },
4454 text: function(elem){
4455 return "text" === elem.type;
4456 },
4457 radio: function(elem){
4458 return "radio" === elem.type;
4459 },
4460 checkbox: function(elem){
4461 return "checkbox" === elem.type;
4462 },
4463 file: function(elem){
4464 return "file" === elem.type;
4465 },
4466 password: function(elem){
4467 return "password" === elem.type;
4468 },
4469 submit: function(elem){
4470 return "submit" === elem.type;
4471 },
4472 image: function(elem){
4473 return "image" === elem.type;
4474 },
4475 reset: function(elem){
4476 return "reset" === elem.type;
4477 },
4478 button: function(elem){
4479 return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
4480 },
4481 input: function(elem){
4482 return /input|select|textarea|button/i.test(elem.nodeName);
4483 }
4484 },
4485 setFilters: {
4486 first: function(elem, i){
4487 return i === 0;
4488 },
4489 last: function(elem, i, match, array){
4490 return i === array.length - 1;
4491 },
4492 even: function(elem, i){
4493 return i % 2 === 0;
4494 },
4495 odd: function(elem, i){
4496 return i % 2 === 1;
4497 },
4498 lt: function(elem, i, match){
4499 return i < match[3] - 0;
4500 },
4501 gt: function(elem, i, match){
4502 return i > match[3] - 0;
4503 },
4504 nth: function(elem, i, match){
4505 return match[3] - 0 == i;
4506 },
4507 eq: function(elem, i, match){
4508 return match[3] - 0 == i;
4509 }
4510 },
4511 filter: {
4512 PSEUDO: function(elem, match, i, array){
4513 var name = match[1], filter = Expr.filters[ name ];
4514
4515 if ( filter ) {
4516 return filter( elem, i, match, array );
4517 } else if ( name === "contains" ) {
4518 return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
4519 } else if ( name === "not" ) {
4520 var not = match[3];
4521
4522 for ( var i = 0, l = not.length; i < l; i++ ) {
4523 if ( not[i] === elem ) {
4524 return false;
4525 }
4526 }
4527
4528 return true;
4529 }
4530 },
4531 CHILD: function(elem, match){
4532 var type = match[1], node = elem;
4533 switch (type) {
4534 case 'only':
4535 case 'first':
4536 while ( (node = node.previousSibling) ) {
4537 if ( node.nodeType === 1 ) return false;
4538 }
4539 if ( type == 'first') return true;
4540 node = elem;
4541 case 'last':
4542 while ( (node = node.nextSibling) ) {
4543 if ( node.nodeType === 1 ) return false;
4544 }
4545 return true;
4546 case 'nth':
4547 var first = match[2], last = match[3];
4548
4549 if ( first == 1 && last == 0 ) {
4550 return true;
4551 }
4552
4553 var doneName = match[0],
4554 parent = elem.parentNode;
4555
4556 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
4557 var count = 0;
4558 for ( node = parent.firstChild; node; node = node.nextSibling ) {
4559 if ( node.nodeType === 1 ) {
4560 node.nodeIndex = ++count;
4561 }
4562 }
4563 parent.sizcache = doneName;
4564 }
4565
4566 var diff = elem.nodeIndex - last;
4567 if ( first == 0 ) {
4568 return diff == 0;
4569 } else {
4570 return ( diff % first == 0 && diff / first >= 0 );
4571 }
4572 }
4573 },
4574 ID: function(elem, match){
4575 return elem.nodeType === 1 && elem.getAttribute("id") === match;
4576 },
4577 TAG: function(elem, match){
4578 return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
4579 },
4580 CLASS: function(elem, match){
4581 return (" " + (elem.className || elem.getAttribute("class")) + " ")
4582 .indexOf( match ) > -1;
4583 },
4584 ATTR: function(elem, match){
4585 var name = match[1],
4586 result = Expr.attrHandle[ name ] ?
4587 Expr.attrHandle[ name ]( elem ) :
4588 elem[ name ] != null ?
4589 elem[ name ] :
4590 elem.getAttribute( name ),
4591 value = result + "",
4592 type = match[2],
4593 check = match[4];
4594
4595 return result == null ?
4596 type === "!=" :
4597 type === "=" ?
4598 value === check :
4599 type === "*=" ?
4600 value.indexOf(check) >= 0 :
4601 type === "~=" ?
4602 (" " + value + " ").indexOf(check) >= 0 :
4603 !check ?
4604 value && result !== false :
4605 type === "!=" ?
4606 value != check :
4607 type === "^=" ?
4608 value.indexOf(check) === 0 :
4609 type === "$=" ?
4610 value.substr(value.length - check.length) === check :
4611 type === "|=" ?
4612 value === check || value.substr(0, check.length + 1) === check + "-" :
4613 false;
4614 },
4615 POS: function(elem, match, i, array){
4616 var name = match[2], filter = Expr.setFilters[ name ];
4617
4618 if ( filter ) {
4619 return filter( elem, i, match, array );
4620 }
4621 }
4622 }
4623 };
4624
4625 var origPOS = Expr.match.POS;
4626
4627 for ( var type in Expr.match ) {
4628 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
4629 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source );
4630 }
4631
4632 var makeArray = function(array, results) {
4633 array = Array.prototype.slice.call( array, 0 );
4634
4635 if ( results ) {
4636 results.push.apply( results, array );
4637 return results;
4638 }
4639
4640 return array;
4641 };
4642
4643 try {
4644 Array.prototype.slice.call( document.documentElement.childNodes, 0 );
4645
4646 } catch(e){
4647 makeArray = function(array, results) {
4648 var ret = results || [];
4649
4650 if ( toString.call(array) === "[object Array]" ) {
4651 Array.prototype.push.apply( ret, array );
4652 } else {
4653 if ( typeof array.length === "number" ) {
4654 for ( var i = 0, l = array.length; i < l; i++ ) {
4655 ret.push( array[i] );
4656 }
4657 } else {
4658 for ( var i = 0; array[i]; i++ ) {
4659 ret.push( array[i] );
4660 }
4661 }
4662 }
4663
4664 return ret;
4665 };
4666 }
4667
4668 var sortOrder;
4669
4670 if ( document.documentElement.compareDocumentPosition ) {
4671 sortOrder = function( a, b ) {
4672 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
4673 if ( a == b ) {
4674 hasDuplicate = true;
4675 }
4676 return 0;
4677 }
4678
4679 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
4680 if ( ret === 0 ) {
4681 hasDuplicate = true;
4682 }
4683 return ret;
4684 };
4685 } else if ( "sourceIndex" in document.documentElement ) {
4686 sortOrder = function( a, b ) {
4687 if ( !a.sourceIndex || !b.sourceIndex ) {
4688 if ( a == b ) {
4689 hasDuplicate = true;
4690 }
4691 return 0;
4692 }
4693
4694 var ret = a.sourceIndex - b.sourceIndex;
4695 if ( ret === 0 ) {
4696 hasDuplicate = true;
4697 }
4698 return ret;
4699 };
4700 } else if ( document.createRange ) {
4701 sortOrder = function( a, b ) {
4702 if ( !a.ownerDocument || !b.ownerDocument ) {
4703 if ( a == b ) {
4704 hasDuplicate = true;
4705 }
4706 return 0;
4707 }
4708
4709 var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
4710 aRange.setStart(a, 0);
4711 aRange.setEnd(a, 0);
4712 bRange.setStart(b, 0);
4713 bRange.setEnd(b, 0);
4714 var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
4715 if ( ret === 0 ) {
4716 hasDuplicate = true;
4717 }
4718 return ret;
4719 };
4720 }
4721
4722 (function(){
4723 var form = document.createElement("div"),
4724 id = "script" + (new Date).getTime();
4725 form.innerHTML = "<a name='" + id + "'/>";
4726
4727 var root = document.documentElement;
4728 root.insertBefore( form, root.firstChild );
4729
4730 if ( !!document.getElementById( id ) ) {
4731 Expr.find.ID = function(match, context, isXML){
4732 if ( typeof context.getElementById !== "undefined" && !isXML ) {
4733 var m = context.getElementById(match[1]);
4734 return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
4735 }
4736 };
4737
4738 Expr.filter.ID = function(elem, match){
4739 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4740 return elem.nodeType === 1 && node && node.nodeValue === match;
4741 };
4742 }
4743
4744 root.removeChild( form );
4745 root = form = null; // release memory in IE
4746 })();
4747
4748 (function(){
4749
4750 var div = document.createElement("div");
4751 div.appendChild( document.createComment("") );
4752
4753 if ( div.getElementsByTagName("*").length > 0 ) {
4754 Expr.find.TAG = function(match, context){
4755 var results = context.getElementsByTagName(match[1]);
4756
4757 if ( match[1] === "*" ) {
4758 var tmp = [];
4759
4760 for ( var i = 0; results[i]; i++ ) {
4761 if ( results[i].nodeType === 1 ) {
4762 tmp.push( results[i] );
4763 }
4764 }
4765
4766 results = tmp;
4767 }
4768
4769 return results;
4770 };
4771 }
4772
4773 div.innerHTML = "<a href='#'></a>";
4774 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
4775 div.firstChild.getAttribute("href") !== "#" ) {
4776 Expr.attrHandle.href = function(elem){
4777 return elem.getAttribute("href", 2);
4778 };
4779 }
4780
4781 div = null; // release memory in IE
4782 })();
4783
4784 if ( document.querySelectorAll ) (function(){
4785 var oldSizzle = Sizzle, div = document.createElement("div");
4786 div.innerHTML = "<p class='TEST'></p>";
4787
4788 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
4789 return;
4790 }
4791
4792 Sizzle = function(query, context, extra, seed){
4793 context = context || document;
4794
4795 if ( !seed && context.nodeType === 9 && !isXML(context) ) {
4796 try {
4797 return makeArray( context.querySelectorAll(query), extra );
4798 } catch(e){}
4799 }
4800
4801 return oldSizzle(query, context, extra, seed);
4802 };
4803
4804 for ( var prop in oldSizzle ) {
4805 Sizzle[ prop ] = oldSizzle[ prop ];
4806 }
4807
4808 div = null; // release memory in IE
4809 })();
4810
4811 if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
4812 var div = document.createElement("div");
4813 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
4814
4815 if ( div.getElementsByClassName("e").length === 0 )
4816 return;
4817
4818 div.lastChild.className = "e";
4819
4820 if ( div.getElementsByClassName("e").length === 1 )
4821 return;
4822
4823 Expr.order.splice(1, 0, "CLASS");
4824 Expr.find.CLASS = function(match, context, isXML) {
4825 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
4826 return context.getElementsByClassName(match[1]);
4827 }
4828 };
4829
4830 div = null; // release memory in IE
4831 })();
4832
4833 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4834 var sibDir = dir == "previousSibling" && !isXML;
4835 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4836 var elem = checkSet[i];
4837 if ( elem ) {
4838 if ( sibDir && elem.nodeType === 1 ){
4839 elem.sizcache = doneName;
4840 elem.sizset = i;
4841 }
4842 elem = elem[dir];
4843 var match = false;
4844
4845 while ( elem ) {
4846 if ( elem.sizcache === doneName ) {
4847 match = checkSet[elem.sizset];
4848 break;
4849 }
4850
4851 if ( elem.nodeType === 1 && !isXML ){
4852 elem.sizcache = doneName;
4853 elem.sizset = i;
4854 }
4855
4856 if ( elem.nodeName === cur ) {
4857 match = elem;
4858 break;
4859 }
4860
4861 elem = elem[dir];
4862 }
4863
4864 checkSet[i] = match;
4865 }
4866 }
4867 }
4868
4869 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
4870 var sibDir = dir == "previousSibling" && !isXML;
4871 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
4872 var elem = checkSet[i];
4873 if ( elem ) {
4874 if ( sibDir && elem.nodeType === 1 ) {
4875 elem.sizcache = doneName;
4876 elem.sizset = i;
4877 }
4878 elem = elem[dir];
4879 var match = false;
4880
4881 while ( elem ) {
4882 if ( elem.sizcache === doneName ) {
4883 match = checkSet[elem.sizset];
4884 break;
4885 }
4886
4887 if ( elem.nodeType === 1 ) {
4888 if ( !isXML ) {
4889 elem.sizcache = doneName;
4890 elem.sizset = i;
4891 }
4892 if ( typeof cur !== "string" ) {
4893 if ( elem === cur ) {
4894 match = true;
4895 break;
4896 }
4897
4898 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
4899 match = elem;
4900 break;
4901 }
4902 }
4903
4904 elem = elem[dir];
4905 }
4906
4907 checkSet[i] = match;
4908 }
4909 }
4910 }
4911
4912 var contains = document.compareDocumentPosition ? function(a, b){
4913 return a.compareDocumentPosition(b) & 16;
4914 } : function(a, b){
4915 return a !== b && (a.contains ? a.contains(b) : true);
4916 };
4917
4918 var isXML = function(elem){
4919 return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
4920 !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
4921 };
4922
4923 var posProcess = function(selector, context){
4924 var tmpSet = [], later = "", match,
4925 root = context.nodeType ? [context] : context;
4926
4927 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
4928 later += match[0];
4929 selector = selector.replace( Expr.match.PSEUDO, "" );
4930 }
4931
4932 selector = Expr.relative[selector] ? selector + "*" : selector;
4933
4934 for ( var i = 0, l = root.length; i < l; i++ ) {
4935 Sizzle( selector, root[i], tmpSet );
4936 }
4937
4938 return Sizzle.filter( later, tmpSet );
4939 };
4940
4941
4942 window.Sizzle = Sizzle;
4943
4944 })();
4945
4946 ;(function(engine) {
4947 var extendElements = Prototype.Selector.extendElements;
4948
4949 function select(selector, scope) {
4950 return extendElements(engine(selector, scope || document));
4951 }
4952
4953 function match(element, selector) {
4954 return engine.matches(selector, [element]).length == 1;
4955 }
4956
4957 Prototype.Selector.engine = engine;
4958 Prototype.Selector.select = select;
4959 Prototype.Selector.match = match;
4960 })(Sizzle);
4961
4962 window.Sizzle = Prototype._original_property;
4963 delete Prototype._original_property;
4964
4965 var Form = {
4966 reset: function(form) {
4967 form = $(form);
4968 form.reset();
4969 return form;
4970 },
4971
4972 serializeElements: function(elements, options) {
4973 if (typeof options != 'object') options = { hash: !!options };
4974 else if (Object.isUndefined(options.hash)) options.hash = true;
4975 var key, value, submitted = false, submit = options.submit, accumulator, initial;
4976
4977 if (options.hash) {
4978 initial = {};
4979 accumulator = function(result, key, value) {
4980 if (key in result) {
4981 if (!Object.isArray(result[key])) result[key] = [result[key]];
4982 result[key].push(value);
4983 } else result[key] = value;
4984 return result;
4985 };
4986 } else {
4987 initial = '';
4988 accumulator = function(result, key, value) {
4989 return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value);
4990 }
4991 }
4992
4993 return elements.inject(initial, function(result, element) {
4994 if (!element.disabled && element.name) {
4995 key = element.name; value = $(element).getValue();
4996 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
4997 submit !== false && (!submit || key == submit) && (submitted = true)))) {
4998 result = accumulator(result, key, value);
4999 }
5000 }
5001 return result;
5002 });
5003 }
5004 };
5005
5006 Form.Methods = {
5007 serialize: function(form, options) {
5008 return Form.serializeElements(Form.getElements(form), options);
5009 },
5010
5011 getElements: function(form) {
5012 var elements = $(form).getElementsByTagName('*'),
5013 element,
5014 arr = [ ],
5015 serializers = Form.Element.Serializers;
5016 for (var i = 0; element = elements[i]; i++) {
5017 arr.push(element);
5018 }
5019 return arr.inject([], function(elements, child) {
5020 if (serializers[child.tagName.toLowerCase()])
5021 elements.push(Element.extend(child));
5022 return elements;
5023 })
5024 },
5025
5026 getInputs: function(form, typeName, name) {
5027 form = $(form);
5028 var inputs = form.getElementsByTagName('input');
5029
5030 if (!typeName && !name) return $A(inputs).map(Element.extend);
5031
5032 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
5033 var input = inputs[i];
5034 if ((typeName && input.type != typeName) || (name && input.name != name))
5035 continue;
5036 matchingInputs.push(Element.extend(input));
5037 }
5038
5039 return matchingInputs;
5040 },
5041
5042 disable: function(form) {
5043 form = $(form);
5044 Form.getElements(form).invoke('disable');
5045 return form;
5046 },
5047
5048 enable: function(form) {
5049 form = $(form);
5050 Form.getElements(form).invoke('enable');
5051 return form;
5052 },
5053
5054 findFirstElement: function(form) {
5055 var elements = $(form).getElements().findAll(function(element) {
5056 return 'hidden' != element.type && !element.disabled;
5057 });
5058 var firstByIndex = elements.findAll(function(element) {
5059 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
5060 }).sortBy(function(element) { return element.tabIndex }).first();
5061
5062 return firstByIndex ? firstByIndex : elements.find(function(element) {
5063 return /^(?:input|select|textarea)$/i.test(element.tagName);
5064 });
5065 },
5066
5067 focusFirstElement: function(form) {
5068 form = $(form);
5069 var element = form.findFirstElement();
5070 if (element) element.activate();
5071 return form;
5072 },
5073
5074 request: function(form, options) {
5075 form = $(form), options = Object.clone(options || { });
5076
5077 var params = options.parameters, action = form.readAttribute('action') || '';
5078 if (action.blank()) action = window.location.href;
5079 options.parameters = form.serialize(true);
5080
5081 if (params) {
5082 if (Object.isString(params)) params = params.toQueryParams();
5083 Object.extend(options.parameters, params);
5084 }
5085
5086 if (form.hasAttribute('method') && !options.method)
5087 options.method = form.method;
5088
5089 return new Ajax.Request(action, options);
5090 }
5091 };
5092
5093 /*--------------------------------------------------------------------------*/
5094
5095
5096 Form.Element = {
5097 focus: function(element) {
5098 $(element).focus();
5099 return element;
5100 },
5101
5102 select: function(element) {
5103 $(element).select();
5104 return element;
5105 }
5106 };
5107
5108 Form.Element.Methods = {
5109
5110 serialize: function(element) {
5111 element = $(element);
5112 if (!element.disabled && element.name) {
5113 var value = element.getValue();
5114 if (value != undefined) {
5115 var pair = { };
5116 pair[element.name] = value;
5117 return Object.toQueryString(pair);
5118 }
5119 }
5120 return '';
5121 },
5122
5123 getValue: function(element) {
5124 element = $(element);
5125 var method = element.tagName.toLowerCase();
5126 return Form.Element.Serializers[method](element);
5127 },
5128
5129 setValue: function(element, value) {
5130 element = $(element);
5131 var method = element.tagName.toLowerCase();
5132 Form.Element.Serializers[method](element, value);
5133 return element;
5134 },
5135
5136 clear: function(element) {
5137 $(element).value = '';
5138 return element;
5139 },
5140
5141 present: function(element) {
5142 return $(element).value != '';
5143 },
5144
5145 activate: function(element) {
5146 element = $(element);
5147 try {
5148 element.focus();
5149 if (element.select && (element.tagName.toLowerCase() != 'input' ||
5150 !(/^(?:button|reset|submit)$/i.test(element.type))))
5151 element.select();
5152 } catch (e) { }
5153 return element;
5154 },
5155
5156 disable: function(element) {
5157 element = $(element);
5158 element.disabled = true;
5159 return element;
5160 },
5161
5162 enable: function(element) {
5163 element = $(element);
5164 element.disabled = false;
5165 return element;
5166 }
5167 };
5168
5169 /*--------------------------------------------------------------------------*/
5170
5171 var Field = Form.Element;
5172
5173 var $F = Form.Element.Methods.getValue;
5174
5175 /*--------------------------------------------------------------------------*/
5176
5177 Form.Element.Serializers = (function() {
5178 function input(element, value) {
5179 switch (element.type.toLowerCase()) {
5180 case 'checkbox':
5181 case 'radio':
5182 return inputSelector(element, value);
5183 default:
5184 return valueSelector(element, value);
5185 }
5186 }
5187
5188 function inputSelector(element, value) {
5189 if (Object.isUndefined(value))
5190 return element.checked ? element.value : null;
5191 else element.checked = !!value;
5192 }
5193
5194 function valueSelector(element, value) {
5195 if (Object.isUndefined(value)) return element.value;
5196 else element.value = value;
5197 }
5198
5199 function select(element, value) {
5200 if (Object.isUndefined(value))
5201 return (element.type === 'select-one' ? selectOne : selectMany)(element);
5202
5203 var opt, currentValue, single = !Object.isArray(value);
5204 for (var i = 0, length = element.length; i < length; i++) {
5205 opt = element.options[i];
5206 currentValue = this.optionValue(opt);
5207 if (single) {
5208 if (currentValue == value) {
5209 opt.selected = true;
5210 return;
5211 }
5212 }
5213 else opt.selected = value.include(currentValue);
5214 }
5215 }
5216
5217 function selectOne(element) {
5218 var index = element.selectedIndex;
5219 return index >= 0 ? optionValue(element.options[index]) : null;
5220 }
5221
5222 function selectMany(element) {
5223 var values, length = element.length;
5224 if (!length) return null;
5225
5226 for (var i = 0, values = []; i < length; i++) {
5227 var opt = element.options[i];
5228 if (opt.selected) values.push(optionValue(opt));
5229 }
5230 return values;
5231 }
5232
5233 function optionValue(opt) {
5234 return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
5235 }
5236
5237 return {
5238 input: input,
5239 inputSelector: inputSelector,
5240 textarea: valueSelector,
5241 select: select,
5242 selectOne: selectOne,
5243 selectMany: selectMany,
5244 optionValue: optionValue,
5245 button: valueSelector
5246 };
5247 })();
5248
5249 /*--------------------------------------------------------------------------*/
5250
5251
5252 Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
5253 initialize: function($super, element, frequency, callback) {
5254 $super(callback, frequency);
5255 this.element = $(element);
5256 this.lastValue = this.getValue();
5257 },
5258
5259 execute: function() {
5260 var value = this.getValue();
5261 if (Object.isString(this.lastValue) && Object.isString(value) ?
5262 this.lastValue != value : String(this.lastValue) != String(value)) {
5263 this.callback(this.element, value);
5264 this.lastValue = value;
5265 }
5266 }
5267 });
5268
5269 Form.Element.Observer = Class.create(Abstract.TimedObserver, {
5270 getValue: function() {
5271 return Form.Element.getValue(this.element);
5272 }
5273 });
5274
5275 Form.Observer = Class.create(Abstract.TimedObserver, {
5276 getValue: function() {
5277 return Form.serialize(this.element);
5278 }
5279 });
5280
5281 /*--------------------------------------------------------------------------*/
5282
5283 Abstract.EventObserver = Class.create({
5284 initialize: function(element, callback) {
5285 this.element = $(element);
5286 this.callback = callback;
5287
5288 this.lastValue = this.getValue();
5289 if (this.element.tagName.toLowerCase() == 'form')
5290 this.registerFormCallbacks();
5291 else
5292 this.registerCallback(this.element);
5293 },
5294
5295 onElementEvent: function() {
5296 var value = this.getValue();
5297 if (this.lastValue != value) {
5298 this.callback(this.element, value);
5299 this.lastValue = value;
5300 }
5301 },
5302
5303 registerFormCallbacks: function() {
5304 Form.getElements(this.element).each(this.registerCallback, this);
5305 },
5306
5307 registerCallback: function(element) {
5308 if (element.type) {
5309 switch (element.type.toLowerCase()) {
5310 case 'checkbox':
5311 case 'radio':
5312 Event.observe(element, 'click', this.onElementEvent.bind(this));
5313 break;
5314 default:
5315 Event.observe(element, 'change', this.onElementEvent.bind(this));
5316 break;
5317 }
5318 }
5319 }
5320 });
5321
5322 Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
5323 getValue: function() {
5324 return Form.Element.getValue(this.element);
5325 }
5326 });
5327
5328 Form.EventObserver = Class.create(Abstract.EventObserver, {
5329 getValue: function() {
5330 return Form.serialize(this.element);
5331 }
5332 });
5333 (function() {
5334
5335 var Event = {
5336 KEY_BACKSPACE: 8,
5337 KEY_TAB: 9,
5338 KEY_RETURN: 13,
5339 KEY_ESC: 27,
5340 KEY_LEFT: 37,
5341 KEY_UP: 38,
5342 KEY_RIGHT: 39,
5343 KEY_DOWN: 40,
5344 KEY_DELETE: 46,
5345 KEY_HOME: 36,
5346 KEY_END: 35,
5347 KEY_PAGEUP: 33,
5348 KEY_PAGEDOWN: 34,
5349 KEY_INSERT: 45,
5350
5351 cache: {}
5352 };
5353
5354 var docEl = document.documentElement;
5355 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
5356 && 'onmouseleave' in docEl;
5357
5358
5359
5360 var isIELegacyEvent = function(event) { return false; };
5361
5362 if (window.attachEvent) {
5363 if (window.addEventListener) {
5364 isIELegacyEvent = function(event) {
5365 return !(event instanceof window.Event);
5366 };
5367 } else {
5368 isIELegacyEvent = function(event) { return true; };
5369 }
5370 }
5371
5372 var _isButton;
5373
5374 function _isButtonForDOMEvents(event, code) {
5375 return event.which ? (event.which === code + 1) : (event.button === code);
5376 }
5377
5378 var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
5379 function _isButtonForLegacyEvents(event, code) {
5380 return event.button === legacyButtonMap[code];
5381 }
5382
5383 function _isButtonForWebKit(event, code) {
5384 switch (code) {
5385 case 0: return event.which == 1 && !event.metaKey;
5386 case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
5387 case 2: return event.which == 3;
5388 default: return false;
5389 }
5390 }
5391
5392 if (window.attachEvent) {
5393 if (!window.addEventListener) {
5394 _isButton = _isButtonForLegacyEvents;
5395 } else {
5396 _isButton = function(event, code) {
5397 return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
5398 _isButtonForDOMEvents(event, code);
5399 }
5400 }
5401 } else if (Prototype.Browser.WebKit) {
5402 _isButton = _isButtonForWebKit;
5403 } else {
5404 _isButton = _isButtonForDOMEvents;
5405 }
5406
5407 function isLeftClick(event) { return _isButton(event, 0) }
5408
5409 function isMiddleClick(event) { return _isButton(event, 1) }
5410
5411 function isRightClick(event) { return _isButton(event, 2) }
5412
5413 function element(event) {
5414 event = Event.extend(event);
5415
5416 var node = event.target, type = event.type,
5417 currentTarget = event.currentTarget;
5418
5419 if (currentTarget && currentTarget.tagName) {
5420 if (type === 'load' || type === 'error' ||
5421 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
5422 && currentTarget.type === 'radio'))
5423 node = currentTarget;
5424 }
5425
5426 if (node.nodeType == Node.TEXT_NODE)
5427 node = node.parentNode;
5428
5429 return Element.extend(node);
5430 }
5431
5432 function findElement(event, expression) {
5433 var element = Event.element(event);
5434
5435 if (!expression) return element;
5436 while (element) {
5437 if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
5438 return Element.extend(element);
5439 }
5440 element = element.parentNode;
5441 }
5442 }
5443
5444 function pointer(event) {
5445 return { x: pointerX(event), y: pointerY(event) };
5446 }
5447
5448 function pointerX(event) {
5449 var docElement = document.documentElement,
5450 body = document.body || { scrollLeft: 0 };
5451
5452 return event.pageX || (event.clientX +
5453 (docElement.scrollLeft || body.scrollLeft) -
5454 (docElement.clientLeft || 0));
5455 }
5456
5457 function pointerY(event) {
5458 var docElement = document.documentElement,
5459 body = document.body || { scrollTop: 0 };
5460
5461 return event.pageY || (event.clientY +
5462 (docElement.scrollTop || body.scrollTop) -
5463 (docElement.clientTop || 0));
5464 }
5465
5466
5467 function stop(event) {
5468 Event.extend(event);
5469 event.preventDefault();
5470 event.stopPropagation();
5471
5472 event.stopped = true;
5473 }
5474
5475
5476 Event.Methods = {
5477 isLeftClick: isLeftClick,
5478 isMiddleClick: isMiddleClick,
5479 isRightClick: isRightClick,
5480
5481 element: element,
5482 findElement: findElement,
5483
5484 pointer: pointer,
5485 pointerX: pointerX,
5486 pointerY: pointerY,
5487
5488 stop: stop
5489 };
5490
5491 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
5492 m[name] = Event.Methods[name].methodize();
5493 return m;
5494 });
5495
5496 if (window.attachEvent) {
5497 function _relatedTarget(event) {
5498 var element;
5499 switch (event.type) {
5500 case 'mouseover':
5501 case 'mouseenter':
5502 element = event.fromElement;
5503 break;
5504 case 'mouseout':
5505 case 'mouseleave':
5506 element = event.toElement;
5507 break;
5508 default:
5509 return null;
5510 }
5511 return Element.extend(element);
5512 }
5513
5514 var additionalMethods = {
5515 stopPropagation: function() { this.cancelBubble = true },
5516 preventDefault: function() { this.returnValue = false },
5517 inspect: function() { return '[object Event]' }
5518 };
5519
5520 Event.extend = function(event, element) {
5521 if (!event) return false;
5522
5523 if (!isIELegacyEvent(event)) return event;
5524
5525 if (event._extendedByPrototype) return event;
5526 event._extendedByPrototype = Prototype.emptyFunction;
5527
5528 var pointer = Event.pointer(event);
5529
5530 Object.extend(event, {
5531 target: event.srcElement || element,
5532 relatedTarget: _relatedTarget(event),
5533 pageX: pointer.x,
5534 pageY: pointer.y
5535 });
5536
5537 Object.extend(event, methods);
5538 Object.extend(event, additionalMethods);
5539
5540 return event;
5541 };
5542 } else {
5543 Event.extend = Prototype.K;
5544 }
5545
5546 if (window.addEventListener) {
5547 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
5548 Object.extend(Event.prototype, methods);
5549 }
5550
5551 function _createResponder(element, eventName, handler) {
5552 var registry = Element.retrieve(element, 'prototype_event_registry');
5553
5554 if (Object.isUndefined(registry)) {
5555 CACHE.push(element);
5556 registry = Element.retrieve(element, 'prototype_event_registry', $H());
5557 }
5558
5559 var respondersForEvent = registry.get(eventName);
5560 if (Object.isUndefined(respondersForEvent)) {
5561 respondersForEvent = [];
5562 registry.set(eventName, respondersForEvent);
5563 }
5564
5565 if (respondersForEvent.pluck('handler').include(handler)) return false;
5566
5567 var responder;
5568 if (eventName.include(":")) {
5569 responder = function(event) {
5570 if (Object.isUndefined(event.eventName))
5571 return false;
5572
5573 if (event.eventName !== eventName)
5574 return false;
5575
5576 Event.extend(event, element);
5577 handler.call(element, event);
5578 };
5579 } else {
5580 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
5581 (eventName === "mouseenter" || eventName === "mouseleave")) {
5582 if (eventName === "mouseenter" || eventName === "mouseleave") {
5583 responder = function(event) {
5584 Event.extend(event, element);
5585
5586 var parent = event.relatedTarget;
5587 while (parent && parent !== element) {
5588 try { parent = parent.parentNode; }
5589 catch(e) { parent = element; }
5590 }
5591
5592 if (parent === element) return;
5593
5594 handler.call(element, event);
5595 };
5596 }
5597 } else {
5598 responder = function(event) {
5599 Event.extend(event, element);
5600 handler.call(element, event);
5601 };
5602 }
5603 }
5604
5605 responder.handler = handler;
5606 respondersForEvent.push(responder);
5607 return responder;
5608 }
5609
5610 function _destroyCache() {
5611 for (var i = 0, length = CACHE.length; i < length; i++) {
5612 Event.stopObserving(CACHE[i]);
5613 CACHE[i] = null;
5614 }
5615 }
5616
5617 var CACHE = [];
5618
5619 if (Prototype.Browser.IE)
5620 window.attachEvent('onunload', _destroyCache);
5621
5622 if (Prototype.Browser.WebKit)
5623 window.addEventListener('unload', Prototype.emptyFunction, false);
5624
5625
5626 var _getDOMEventName = Prototype.K,
5627 translations = { mouseenter: "mouseover", mouseleave: "mouseout" };
5628
5629 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
5630 _getDOMEventName = function(eventName) {
5631 return (translations[eventName] || eventName);
5632 };
5633 }
5634
5635 function observe(element, eventName, handler) {
5636 element = $(element);
5637
5638 var responder = _createResponder(element, eventName, handler);
5639
5640 if (!responder) return element;
5641
5642 if (eventName.include(':')) {
5643 if (element.addEventListener)
5644 element.addEventListener("dataavailable", responder, false);
5645 else {
5646 element.attachEvent("ondataavailable", responder);
5647 element.attachEvent("onlosecapture", responder);
5648 }
5649 } else {
5650 var actualEventName = _getDOMEventName(eventName);
5651
5652 if (element.addEventListener)
5653 element.addEventListener(actualEventName, responder, false);
5654 else
5655 element.attachEvent("on" + actualEventName, responder);
5656 }
5657
5658 return element;
5659 }
5660
5661 function stopObserving(element, eventName, handler) {
5662 element = $(element);
5663
5664 var registry = Element.retrieve(element, 'prototype_event_registry');
5665 if (!registry) return element;
5666
5667 if (!eventName) {
5668 registry.each( function(pair) {
5669 var eventName = pair.key;
5670 stopObserving(element, eventName);
5671 });
5672 return element;
5673 }
5674
5675 var responders = registry.get(eventName);
5676 if (!responders) return element;
5677
5678 if (!handler) {
5679 responders.each(function(r) {
5680 stopObserving(element, eventName, r.handler);
5681 });
5682 return element;
5683 }
5684
5685 var i = responders.length, responder;
5686 while (i--) {
5687 if (responders[i].handler === handler) {
5688 responder = responders[i];
5689 break;
5690 }
5691 }
5692 if (!responder) return element;
5693
5694 if (eventName.include(':')) {
5695 if (element.removeEventListener)
5696 element.removeEventListener("dataavailable", responder, false);
5697 else {
5698 element.detachEvent("ondataavailable", responder);
5699 element.detachEvent("onlosecapture", responder);
5700 }
5701 } else {
5702 var actualEventName = _getDOMEventName(eventName);
5703 if (element.removeEventListener)
5704 element.removeEventListener(actualEventName, responder, false);
5705 else
5706 element.detachEvent('on' + actualEventName, responder);
5707 }
5708
5709 registry.set(eventName, responders.without(responder));
5710
5711 return element;
5712 }
5713
5714 function fire(element, eventName, memo, bubble) {
5715 element = $(element);
5716
5717 if (Object.isUndefined(bubble))
5718 bubble = true;
5719
5720 if (element == document && document.createEvent && !element.dispatchEvent)
5721 element = document.documentElement;
5722
5723 var event;
5724 if (document.createEvent) {
5725 event = document.createEvent('HTMLEvents');
5726 event.initEvent('dataavailable', bubble, true);
5727 } else {
5728 event = document.createEventObject();
5729 event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
5730 }
5731
5732 event.eventName = eventName;
5733 event.memo = memo || { };
5734
5735 if (document.createEvent)
5736 element.dispatchEvent(event);
5737 else
5738 element.fireEvent(event.eventType, event);
5739
5740 return Event.extend(event);
5741 }
5742
5743 Event.Handler = Class.create({
5744 initialize: function(element, eventName, selector, callback) {
5745 this.element = $(element);
5746 this.eventName = eventName;
5747 this.selector = selector;
5748 this.callback = callback;
5749 this.handler = this.handleEvent.bind(this);
5750 },
5751
5752 start: function() {
5753 Event.observe(this.element, this.eventName, this.handler);
5754 return this;
5755 },
5756
5757 stop: function() {
5758 Event.stopObserving(this.element, this.eventName, this.handler);
5759 return this;
5760 },
5761
5762 handleEvent: function(event) {
5763 var element = Event.findElement(event, this.selector);
5764 if (element) this.callback.call(this.element, event, element);
5765 }
5766 });
5767
5768 function on(element, eventName, selector, callback) {
5769 element = $(element);
5770 if (Object.isFunction(selector) && Object.isUndefined(callback)) {
5771 callback = selector, selector = null;
5772 }
5773
5774 return new Event.Handler(element, eventName, selector, callback).start();
5775 }
5776
5777 Object.extend(Event, Event.Methods);
5778
5779 Object.extend(Event, {
5780 fire: fire,
5781 observe: observe,
5782 stopObserving: stopObserving,
5783 p_on: on
5784 });
5785
5786 Element.addMethods({
5787 fire: fire,
5788
5789 observe: observe,
5790
5791 stopObserving: stopObserving,
5792
5793 p_on: on
5794 });
5795
5796 Object.extend(document, {
5797 fire: fire.methodize(),
5798
5799 observe: observe.methodize(),
5800
5801 stopObserving: stopObserving.methodize(),
5802
5803 p_on: on.methodize(),
5804
5805 loaded: false
5806 });
5807
5808 if (window.Event) Object.extend(window.Event, Event);
5809 else window.Event = Event;
5810 })();
5811
5812 (function() {
5813 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
5814 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
5815
5816 var timer;
5817
5818 function fireContentLoadedEvent() {
5819 if (document.loaded) return;
5820 if (timer) window.clearTimeout(timer);
5821 document.loaded = true;
5822 document.fire('dom:loaded');
5823 }
5824
5825 function checkReadyState() {
5826 if (document.readyState === 'complete') {
5827 document.stopObserving('readystatechange', checkReadyState);
5828 fireContentLoadedEvent();
5829 }
5830 }
5831
5832 function pollDoScroll() {
5833 try { document.documentElement.doScroll('left'); }
5834 catch(e) {
5835 timer = pollDoScroll.defer();
5836 return;
5837 }
5838 fireContentLoadedEvent();
5839 }
5840
5841 if (document.addEventListener) {
5842 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
5843 } else {
5844 document.observe('readystatechange', checkReadyState);
5845 if (window == top)
5846 timer = pollDoScroll.defer();
5847 }
5848
5849 Event.observe(window, 'load', fireContentLoadedEvent);
5850 })();
5851
5852 Element.addMethods();
5853
5854 /*------------------------------- DEPRECATED -------------------------------*/
5855
5856 Hash.toQueryString = Object.toQueryString;
5857
5858 var Toggle = { display: Element.toggle };
5859
5860 Element.Methods.childOf = Element.Methods.descendantOf;
5861
5862 var Insertion = {
5863 Before: function(element, content) {
5864 return Element.insert(element, {before:content});
5865 },
5866
5867 Top: function(element, content) {
5868 return Element.insert(element, {top:content});
5869 },
5870
5871 Bottom: function(element, content) {
5872 return Element.insert(element, {bottom:content});
5873 },
5874
5875 After: function(element, content) {
5876 return Element.insert(element, {after:content});
5877 }
5878 };
5879
5880 var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
5881
5882 var Position = {
5883 includeScrollOffsets: false,
5884
5885 prepare: function() {
5886 this.deltaX = window.pageXOffset
5887 || document.documentElement.scrollLeft
5888 || document.body.scrollLeft
5889 || 0;
5890 this.deltaY = window.pageYOffset
5891 || document.documentElement.scrollTop
5892 || document.body.scrollTop
5893 || 0;
5894 },
5895
5896 within: function(element, x, y) {
5897 if (this.includeScrollOffsets)
5898 return this.withinIncludingScrolloffsets(element, x, y);
5899 this.xcomp = x;
5900 this.ycomp = y;
5901 this.offset = Element.cumulativeOffset(element);
5902
5903 return (y >= this.offset[1] &&
5904 y < this.offset[1] + element.offsetHeight &&
5905 x >= this.offset[0] &&
5906 x < this.offset[0] + element.offsetWidth);
5907 },
5908
5909 withinIncludingScrolloffsets: function(element, x, y) {
5910 var offsetcache = Element.cumulativeScrollOffset(element);
5911
5912 this.xcomp = x + offsetcache[0] - this.deltaX;
5913 this.ycomp = y + offsetcache[1] - this.deltaY;
5914 this.offset = Element.cumulativeOffset(element);
5915
5916 return (this.ycomp >= this.offset[1] &&
5917 this.ycomp < this.offset[1] + element.offsetHeight &&
5918 this.xcomp >= this.offset[0] &&
5919 this.xcomp < this.offset[0] + element.offsetWidth);
5920 },
5921
5922 overlap: function(mode, element) {
5923 if (!mode) return 0;
5924 if (mode == 'vertical')
5925 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
5926 element.offsetHeight;
5927 if (mode == 'horizontal')
5928 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
5929 element.offsetWidth;
5930 },
5931
5932
5933 cumulativeOffset: Element.Methods.cumulativeOffset,
5934
5935 positionedOffset: Element.Methods.positionedOffset,
5936
5937 absolutize: function(element) {
5938 Position.prepare();
5939 return Element.absolutize(element);
5940 },
5941
5942 relativize: function(element) {
5943 Position.prepare();
5944 return Element.relativize(element);
5945 },
5946
5947 realOffset: Element.Methods.cumulativeScrollOffset,
5948
5949 offsetParent: Element.Methods.getOffsetParent,
5950
5951 page: Element.Methods.viewportOffset,
5952
5953 clone: function(source, target, options) {
5954 options = options || { };
5955 return Element.clonePosition(target, source, options);
5956 }
5957 };
5958
5959 /*--------------------------------------------------------------------------*/
5960
5961 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
5962 function iter(name) {
5963 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
5964 }
5965
5966 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
5967 function(element, className) {
5968 className = className.toString().strip();
5969 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
5970 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
5971 } : function(element, className) {
5972 className = className.toString().strip();
5973 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
5974 if (!classNames && !className) return elements;
5975
5976 var nodes = $(element).getElementsByTagName('*');
5977 className = ' ' + className + ' ';
5978
5979 for (var i = 0, child, cn; child = nodes[i]; i++) {
5980 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
5981 (classNames && classNames.all(function(name) {
5982 return !name.toString().blank() && cn.include(' ' + name + ' ');
5983 }))))
5984 elements.push(Element.extend(child));
5985 }
5986 return elements;
5987 };
5988
5989 return function(className, parentElement) {
5990 return $(parentElement || document.body).getElementsByClassName(className);
5991 };
5992 }(Element.Methods);
5993
5994 /*--------------------------------------------------------------------------*/
5995
5996 Element.ClassNames = Class.create();
5997 Element.ClassNames.prototype = {
5998 initialize: function(element) {
5999 this.element = $(element);
6000 },
6001
6002 _each: function(iterator) {
6003 this.element.className.split(/\s+/).select(function(name) {
6004 return name.length > 0;
6005 })._each(iterator);
6006 },
6007
6008 set: function(className) {
6009 this.element.className = className;
6010 },
6011
6012 add: function(classNameToAdd) {
6013 if (this.include(classNameToAdd)) return;
6014 this.set($A(this).concat(classNameToAdd).join(' '));
6015 },
6016
6017 remove: function(classNameToRemove) {
6018 if (!this.include(classNameToRemove)) return;
6019 this.set($A(this).without(classNameToRemove).join(' '));
6020 },
6021
6022 toString: function() {
6023 return $A(this).join(' ');
6024 }
6025 };
6026
6027 Object.extend(Element.ClassNames.prototype, Enumerable);
6028
6029 /*--------------------------------------------------------------------------*/
6030
6031 (function() {
6032 window.Selector = Class.create({
6033 initialize: function(expression) {
6034 this.expression = expression.strip();
6035 },
6036
6037 findElements: function(rootElement) {
6038 return Prototype.Selector.select(this.expression, rootElement);
6039 },
6040
6041 match: function(element) {
6042 return Prototype.Selector.match(element, this.expression);
6043 },
6044
6045 toString: function() {
6046 return this.expression;
6047 },
6048
6049 inspect: function() {
6050 return "#<Selector: " + this.expression + ">";
6051 }
6052 });
6053
6054 Object.extend(Selector, {
6055 matchElements: function(elements, expression) {
6056 var match = Prototype.Selector.match,
6057 results = [];
6058
6059 for (var i = 0, length = elements.length; i < length; i++) {
6060 var element = elements[i];
6061 if (match(element, expression)) {
6062 results.push(Element.extend(element));
6063 }
6064 }
6065 return results;
6066 },
6067
6068 findElement: function(elements, expression, index) {
6069 index = index || 0;
6070 var matchIndex = 0, element;
6071 for (var i = 0, length = elements.length; i < length; i++) {
6072 element = elements[i];
6073 if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
6074 return Element.extend(element);
6075 }
6076 }
6077 },
6078
6079 findChildElements: function(element, expressions) {
6080 var selector = expressions.toArray().join(', ');
6081 return Prototype.Selector.select(selector, element || document);
6082 }
6083 });
6084 })();