seedlot upload with accession synonyms. seedlot upload works to update existing seedlots
[sgn.git] / js / Prototype.js
blobcc89dafcd6ae69cf81adfea016a0f1a8d8341c58
1 /* Prototype JavaScript framework, version 1.7.3
2 * (c) 2005-2010 Sam Stephenson
4 * Prototype is freely distributable under the terms of an MIT-style license.
5 * For details, see the Prototype web site: http://www.prototypejs.org/
7 *--------------------------------------------------------------------------*/
9 var Prototype = {
11 Version: '1.7.3',
13 Browser: (function(){
14 var ua = navigator.userAgent;
15 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
16 return {
17 IE: !!window.attachEvent && !isOpera,
18 Opera: isOpera,
19 WebKit: ua.indexOf('AppleWebKit/') > -1,
20 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
21 MobileSafari: /Apple.*Mobile/.test(ua)
23 })(),
25 BrowserFeatures: {
26 XPath: !!document.evaluate,
28 SelectorsAPI: !!document.querySelector,
30 ElementExtensions: (function() {
31 var constructor = window.Element || window.HTMLElement;
32 return !!(constructor && constructor.prototype);
33 })(),
34 SpecificElementExtensions: (function() {
35 if (typeof window.HTMLDivElement !== 'undefined')
36 return true;
38 var div = document.createElement('div'),
39 form = document.createElement('form'),
40 isSupported = false;
42 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
43 isSupported = true;
46 div = form = null;
48 return isSupported;
49 })()
52 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
53 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
55 emptyFunction: function() { },
57 K: function(x) { return x }
60 if (Prototype.Browser.MobileSafari)
61 Prototype.BrowserFeatures.SpecificElementExtensions = false;
62 /* Based on Alex Arnell's inheritance implementation. */
64 var Class = (function() {
66 var IS_DONTENUM_BUGGY = (function(){
67 for (var p in { toString: 1 }) {
68 if (p === 'toString') return false;
70 return true;
71 })();
73 function subclass() {};
74 function create() {
75 var parent = null, properties = $A(arguments);
76 if (Object.isFunction(properties[0]))
77 parent = properties.shift();
79 function klass() {
80 this.initialize.apply(this, arguments);
83 Object.extend(klass, Class.Methods);
84 klass.superclass = parent;
85 klass.subclasses = [];
87 if (parent) {
88 subclass.prototype = parent.prototype;
89 klass.prototype = new subclass;
90 parent.subclasses.push(klass);
93 for (var i = 0, length = properties.length; i < length; i++)
94 klass.addMethods(properties[i]);
96 if (!klass.prototype.initialize)
97 klass.prototype.initialize = Prototype.emptyFunction;
99 klass.prototype.constructor = klass;
100 return klass;
103 function addMethods(source) {
104 var ancestor = this.superclass && this.superclass.prototype,
105 properties = Object.keys(source);
107 if (IS_DONTENUM_BUGGY) {
108 if (source.toString != Object.prototype.toString)
109 properties.push("toString");
110 if (source.valueOf != Object.prototype.valueOf)
111 properties.push("valueOf");
114 for (var i = 0, length = properties.length; i < length; i++) {
115 var property = properties[i], value = source[property];
116 if (ancestor && Object.isFunction(value) &&
117 value.argumentNames()[0] == "$super") {
118 var method = value;
119 value = (function(m) {
120 return function() { return ancestor[m].apply(this, arguments); };
121 })(property).wrap(method);
123 value.valueOf = (function(method) {
124 return function() { return method.valueOf.call(method); };
125 })(method);
127 value.toString = (function(method) {
128 return function() { return method.toString.call(method); };
129 })(method);
131 this.prototype[property] = value;
134 return this;
137 return {
138 create: create,
139 Methods: {
140 addMethods: addMethods
143 })();
144 (function() {
146 var _toString = Object.prototype.toString,
147 _hasOwnProperty = Object.prototype.hasOwnProperty,
148 NULL_TYPE = 'Null',
149 UNDEFINED_TYPE = 'Undefined',
150 BOOLEAN_TYPE = 'Boolean',
151 NUMBER_TYPE = 'Number',
152 STRING_TYPE = 'String',
153 OBJECT_TYPE = 'Object',
154 FUNCTION_CLASS = '[object Function]',
155 BOOLEAN_CLASS = '[object Boolean]',
156 NUMBER_CLASS = '[object Number]',
157 STRING_CLASS = '[object String]',
158 ARRAY_CLASS = '[object Array]',
159 DATE_CLASS = '[object Date]',
160 NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
161 typeof JSON.stringify === 'function' &&
162 JSON.stringify(0) === '0' &&
163 typeof JSON.stringify(Prototype.K) === 'undefined';
167 var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',
168 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
170 var IS_DONTENUM_BUGGY = (function(){
171 for (var p in { toString: 1 }) {
172 if (p === 'toString') return false;
174 return true;
175 })();
177 function Type(o) {
178 switch(o) {
179 case null: return NULL_TYPE;
180 case (void 0): return UNDEFINED_TYPE;
182 var type = typeof o;
183 switch(type) {
184 case 'boolean': return BOOLEAN_TYPE;
185 case 'number': return NUMBER_TYPE;
186 case 'string': return STRING_TYPE;
188 return OBJECT_TYPE;
191 function extend(destination, source) {
192 for (var property in source)
193 destination[property] = source[property];
194 return destination;
197 function inspect(object) {
198 try {
199 if (isUndefined(object)) return 'undefined';
200 if (object === null) return 'null';
201 return object.inspect ? object.inspect() : String(object);
202 } catch (e) {
203 if (e instanceof RangeError) return '...';
204 throw e;
208 function toJSON(value) {
209 return Str('', { '': value }, []);
212 function Str(key, holder, stack) {
213 var value = holder[key];
214 if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
215 value = value.toJSON(key);
218 var _class = _toString.call(value);
220 switch (_class) {
221 case NUMBER_CLASS:
222 case BOOLEAN_CLASS:
223 case STRING_CLASS:
224 value = value.valueOf();
227 switch (value) {
228 case null: return 'null';
229 case true: return 'true';
230 case false: return 'false';
233 var type = typeof value;
234 switch (type) {
235 case 'string':
236 return value.inspect(true);
237 case 'number':
238 return isFinite(value) ? String(value) : 'null';
239 case 'object':
241 for (var i = 0, length = stack.length; i < length; i++) {
242 if (stack[i] === value) {
243 throw new TypeError("Cyclic reference to '" + value + "' in object");
246 stack.push(value);
248 var partial = [];
249 if (_class === ARRAY_CLASS) {
250 for (var i = 0, length = value.length; i < length; i++) {
251 var str = Str(i, value, stack);
252 partial.push(typeof str === 'undefined' ? 'null' : str);
254 partial = '[' + partial.join(',') + ']';
255 } else {
256 var keys = Object.keys(value);
257 for (var i = 0, length = keys.length; i < length; i++) {
258 var key = keys[i], str = Str(key, value, stack);
259 if (typeof str !== "undefined") {
260 partial.push(key.inspect(true)+ ':' + str);
263 partial = '{' + partial.join(',') + '}';
265 stack.pop();
266 return partial;
270 function stringify(object) {
271 return JSON.stringify(object);
274 function toQueryString(object) {
275 return $H(object).toQueryString();
278 function toHTML(object) {
279 return object && object.toHTML ? object.toHTML() : String.interpret(object);
282 function keys(object) {
283 if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
284 var results = [];
285 for (var property in object) {
286 if (_hasOwnProperty.call(object, property))
287 results.push(property);
290 if (IS_DONTENUM_BUGGY) {
291 for (var i = 0; property = DONT_ENUMS[i]; i++) {
292 if (_hasOwnProperty.call(object, property))
293 results.push(property);
297 return results;
300 function values(object) {
301 var results = [];
302 for (var property in object)
303 results.push(object[property]);
304 return results;
307 function clone(object) {
308 return extend({ }, object);
311 function isElement(object) {
312 return !!(object && object.nodeType == 1);
315 function isArray(object) {
316 return _toString.call(object) === ARRAY_CLASS;
319 var hasNativeIsArray = (typeof Array.isArray == 'function')
320 && Array.isArray([]) && !Array.isArray({});
322 if (hasNativeIsArray) {
323 isArray = Array.isArray;
326 function isHash(object) {
327 return object instanceof Hash;
330 function isFunction(object) {
331 return _toString.call(object) === FUNCTION_CLASS;
334 function isString(object) {
335 return _toString.call(object) === STRING_CLASS;
338 function isNumber(object) {
339 return _toString.call(object) === NUMBER_CLASS;
342 function isDate(object) {
343 return _toString.call(object) === DATE_CLASS;
346 function isUndefined(object) {
347 return typeof object === "undefined";
350 extend(Object, {
351 extend: extend,
352 inspect: inspect,
353 toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
354 toQueryString: toQueryString,
355 toHTML: toHTML,
356 keys: Object.keys || keys,
357 values: values,
358 clone: clone,
359 isElement: isElement,
360 isArray: isArray,
361 isHash: isHash,
362 isFunction: isFunction,
363 isString: isString,
364 isNumber: isNumber,
365 isDate: isDate,
366 isUndefined: isUndefined
368 })();
369 Object.extend(Function.prototype, (function() {
370 var slice = Array.prototype.slice;
372 function update(array, args) {
373 var arrayLength = array.length, length = args.length;
374 while (length--) array[arrayLength + length] = args[length];
375 return array;
378 function merge(array, args) {
379 array = slice.call(array, 0);
380 return update(array, args);
383 function argumentNames() {
384 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
385 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
386 .replace(/\s+/g, '').split(',');
387 return names.length == 1 && !names[0] ? [] : names;
391 function bind(context) {
392 if (arguments.length < 2 && Object.isUndefined(arguments[0]))
393 return this;
395 if (!Object.isFunction(this))
396 throw new TypeError("The object is not callable.");
398 var nop = function() {};
399 var __method = this, args = slice.call(arguments, 1);
401 var bound = function() {
402 var a = merge(args, arguments);
403 var c = this instanceof bound ? this : context;
404 return __method.apply(c, a);
407 nop.prototype = this.prototype;
408 bound.prototype = new nop();
410 return bound;
413 function bindAsEventListener(context) {
414 var __method = this, args = slice.call(arguments, 1);
415 return function(event) {
416 var a = update([event || window.event], args);
417 return __method.apply(context, a);
421 function curry() {
422 if (!arguments.length) return this;
423 var __method = this, args = slice.call(arguments, 0);
424 return function() {
425 var a = merge(args, arguments);
426 return __method.apply(this, a);
430 function delay(timeout) {
431 var __method = this, args = slice.call(arguments, 1);
432 timeout = timeout * 1000;
433 return window.setTimeout(function() {
434 return __method.apply(__method, args);
435 }, timeout);
438 function defer() {
439 var args = update([0.01], arguments);
440 return this.delay.apply(this, args);
443 function wrap(wrapper) {
444 var __method = this;
445 return function() {
446 var a = update([__method.bind(this)], arguments);
447 return wrapper.apply(this, a);
451 function methodize() {
452 if (this._methodized) return this._methodized;
453 var __method = this;
454 return this._methodized = function() {
455 var a = update([this], arguments);
456 return __method.apply(null, a);
460 var extensions = {
461 argumentNames: argumentNames,
462 bindAsEventListener: bindAsEventListener,
463 curry: curry,
464 delay: delay,
465 defer: defer,
466 wrap: wrap,
467 methodize: methodize
470 if (!Function.prototype.bind)
471 extensions.bind = bind;
473 return extensions;
474 })());
478 (function(proto) {
481 function toISOString() {
482 return this.getUTCFullYear() + '-' +
483 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
484 this.getUTCDate().toPaddedString(2) + 'T' +
485 this.getUTCHours().toPaddedString(2) + ':' +
486 this.getUTCMinutes().toPaddedString(2) + ':' +
487 this.getUTCSeconds().toPaddedString(2) + 'Z';
491 function toJSON() {
492 return this.toISOString();
495 if (!proto.toISOString) proto.toISOString = toISOString;
496 if (!proto.toJSON) proto.toJSON = toJSON;
498 })(Date.prototype);
501 RegExp.prototype.match = RegExp.prototype.test;
503 RegExp.escape = function(str) {
504 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
506 var PeriodicalExecuter = Class.create({
507 initialize: function(callback, frequency) {
508 this.callback = callback;
509 this.frequency = frequency;
510 this.currentlyExecuting = false;
512 this.registerCallback();
515 registerCallback: function() {
516 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
519 execute: function() {
520 this.callback(this);
523 stop: function() {
524 if (!this.timer) return;
525 clearInterval(this.timer);
526 this.timer = null;
529 onTimerEvent: function() {
530 if (!this.currentlyExecuting) {
531 try {
532 this.currentlyExecuting = true;
533 this.execute();
534 this.currentlyExecuting = false;
535 } catch(e) {
536 this.currentlyExecuting = false;
537 throw e;
542 Object.extend(String, {
543 interpret: function(value) {
544 return value == null ? '' : String(value);
546 specialChar: {
547 '\b': '\\b',
548 '\t': '\\t',
549 '\n': '\\n',
550 '\f': '\\f',
551 '\r': '\\r',
552 '\\': '\\\\'
556 Object.extend(String.prototype, (function() {
557 var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
558 typeof JSON.parse === 'function' &&
559 JSON.parse('{"test": true}').test;
561 function prepareReplacement(replacement) {
562 if (Object.isFunction(replacement)) return replacement;
563 var template = new Template(replacement);
564 return function(match) { return template.evaluate(match) };
567 function isNonEmptyRegExp(regexp) {
568 return regexp.source && regexp.source !== '(?:)';
572 function gsub(pattern, replacement) {
573 var result = '', source = this, match;
574 replacement = prepareReplacement(replacement);
576 if (Object.isString(pattern))
577 pattern = RegExp.escape(pattern);
579 if (!(pattern.length || isNonEmptyRegExp(pattern))) {
580 replacement = replacement('');
581 return replacement + source.split('').join(replacement) + replacement;
584 while (source.length > 0) {
585 match = source.match(pattern)
586 if (match && match[0].length > 0) {
587 result += source.slice(0, match.index);
588 result += String.interpret(replacement(match));
589 source = source.slice(match.index + match[0].length);
590 } else {
591 result += source, source = '';
594 return result;
597 function sub(pattern, replacement, count) {
598 replacement = prepareReplacement(replacement);
599 count = Object.isUndefined(count) ? 1 : count;
601 return this.gsub(pattern, function(match) {
602 if (--count < 0) return match[0];
603 return replacement(match);
607 function scan(pattern, iterator) {
608 this.gsub(pattern, iterator);
609 return String(this);
612 function truncate(length, truncation) {
613 length = length || 30;
614 truncation = Object.isUndefined(truncation) ? '...' : truncation;
615 return this.length > length ?
616 this.slice(0, length - truncation.length) + truncation : String(this);
619 function strip() {
620 return this.replace(/^\s+/, '').replace(/\s+$/, '');
623 function stripTags() {
624 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, '');
627 function stripScripts() {
628 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
631 function extractScripts() {
632 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
633 matchOne = new RegExp(Prototype.ScriptFragment, 'im');
634 return (this.match(matchAll) || []).map(function(scriptTag) {
635 return (scriptTag.match(matchOne) || ['', ''])[1];
639 function evalScripts() {
640 return this.extractScripts().map(function(script) { return eval(script); });
643 function escapeHTML() {
644 return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
647 function unescapeHTML() {
648 return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
652 function toQueryParams(separator) {
653 var match = this.strip().match(/([^?#]*)(#.*)?$/);
654 if (!match) return { };
656 return match[1].split(separator || '&').inject({ }, function(hash, pair) {
657 if ((pair = pair.split('='))[0]) {
658 var key = decodeURIComponent(pair.shift()),
659 value = pair.length > 1 ? pair.join('=') : pair[0];
661 if (value != undefined) {
662 value = value.gsub('+', ' ');
663 value = decodeURIComponent(value);
666 if (key in hash) {
667 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
668 hash[key].push(value);
670 else hash[key] = value;
672 return hash;
676 function toArray() {
677 return this.split('');
680 function succ() {
681 return this.slice(0, this.length - 1) +
682 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
685 function times(count) {
686 return count < 1 ? '' : new Array(count + 1).join(this);
689 function camelize() {
690 return this.replace(/-+(.)?/g, function(match, chr) {
691 return chr ? chr.toUpperCase() : '';
695 function capitalize() {
696 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
699 function underscore() {
700 return this.replace(/::/g, '/')
701 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
702 .replace(/([a-z\d])([A-Z])/g, '$1_$2')
703 .replace(/-/g, '_')
704 .toLowerCase();
707 function dasherize() {
708 return this.replace(/_/g, '-');
711 function inspect(useDoubleQuotes) {
712 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
713 if (character in String.specialChar) {
714 return String.specialChar[character];
716 return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
718 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
719 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
722 function unfilterJSON(filter) {
723 return this.replace(filter || Prototype.JSONFilter, '$1');
726 function isJSON() {
727 var str = this;
728 if (str.blank()) return false;
729 str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
730 str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
731 str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
732 return (/^[\],:{}\s]*$/).test(str);
735 function evalJSON(sanitize) {
736 var json = this.unfilterJSON(),
737 cx = /[\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\u0000]/g;
738 if (cx.test(json)) {
739 json = json.replace(cx, function (a) {
740 return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
743 try {
744 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
745 } catch (e) { }
746 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
749 function parseJSON() {
750 var json = this.unfilterJSON();
751 return JSON.parse(json);
754 function include(pattern) {
755 return this.indexOf(pattern) > -1;
758 function startsWith(pattern, position) {
759 position = Object.isNumber(position) ? position : 0;
760 return this.lastIndexOf(pattern, position) === position;
763 function endsWith(pattern, position) {
764 pattern = String(pattern);
765 position = Object.isNumber(position) ? position : this.length;
766 if (position < 0) position = 0;
767 if (position > this.length) position = this.length;
768 var d = position - pattern.length;
769 return d >= 0 && this.indexOf(pattern, d) === d;
772 function empty() {
773 return this == '';
776 function blank() {
777 return /^\s*$/.test(this);
780 function interpolate(object, pattern) {
781 return new Template(this, pattern).evaluate(object);
784 return {
785 gsub: gsub,
786 sub: sub,
787 scan: scan,
788 truncate: truncate,
789 strip: String.prototype.trim || strip,
790 stripTags: stripTags,
791 stripScripts: stripScripts,
792 extractScripts: extractScripts,
793 evalScripts: evalScripts,
794 escapeHTML: escapeHTML,
795 unescapeHTML: unescapeHTML,
796 toQueryParams: toQueryParams,
797 parseQuery: toQueryParams,
798 toArray: toArray,
799 succ: succ,
800 times: times,
801 camelize: camelize,
802 capitalize: capitalize,
803 underscore: underscore,
804 dasherize: dasherize,
805 inspect: inspect,
806 unfilterJSON: unfilterJSON,
807 isJSON: isJSON,
808 evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
809 include: include,
810 startsWith: String.prototype.startsWith || startsWith,
811 endsWith: String.prototype.endsWith || endsWith,
812 empty: empty,
813 blank: blank,
814 interpolate: interpolate
816 })());
818 var Template = Class.create({
819 initialize: function(template, pattern) {
820 this.template = template.toString();
821 this.pattern = pattern || Template.Pattern;
824 evaluate: function(object) {
825 if (object && Object.isFunction(object.toTemplateReplacements))
826 object = object.toTemplateReplacements();
828 return this.template.gsub(this.pattern, function(match) {
829 if (object == null) return (match[1] + '');
831 var before = match[1] || '';
832 if (before == '\\') return match[2];
834 var ctx = object, expr = match[3],
835 pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
837 match = pattern.exec(expr);
838 if (match == null) return before;
840 while (match != null) {
841 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
842 ctx = ctx[comp];
843 if (null == ctx || '' == match[3]) break;
844 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
845 match = pattern.exec(expr);
848 return before + String.interpret(ctx);
852 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
854 var $break = { };
856 var Enumerable = (function() {
857 function each(iterator, context) {
858 try {
859 this._each(iterator, context);
860 } catch (e) {
861 if (e != $break) throw e;
863 return this;
866 function eachSlice(number, iterator, context) {
867 var index = -number, slices = [], array = this.toArray();
868 if (number < 1) return array;
869 while ((index += number) < array.length)
870 slices.push(array.slice(index, index+number));
871 return slices.collect(iterator, context);
874 function all(iterator, context) {
875 iterator = iterator || Prototype.K;
876 var result = true;
877 this.each(function(value, index) {
878 result = result && !!iterator.call(context, value, index, this);
879 if (!result) throw $break;
880 }, this);
881 return result;
884 function any(iterator, context) {
885 iterator = iterator || Prototype.K;
886 var result = false;
887 this.each(function(value, index) {
888 if (result = !!iterator.call(context, value, index, this))
889 throw $break;
890 }, this);
891 return result;
894 function collect(iterator, context) {
895 iterator = iterator || Prototype.K;
896 var results = [];
897 this.each(function(value, index) {
898 results.push(iterator.call(context, value, index, this));
899 }, this);
900 return results;
903 function detect(iterator, context) {
904 var result;
905 this.each(function(value, index) {
906 if (iterator.call(context, value, index, this)) {
907 result = value;
908 throw $break;
910 }, this);
911 return result;
914 function findAll(iterator, context) {
915 var results = [];
916 this.each(function(value, index) {
917 if (iterator.call(context, value, index, this))
918 results.push(value);
919 }, this);
920 return results;
923 function grep(filter, iterator, context) {
924 iterator = iterator || Prototype.K;
925 var results = [];
927 if (Object.isString(filter))
928 filter = new RegExp(RegExp.escape(filter));
930 this.each(function(value, index) {
931 if (filter.match(value))
932 results.push(iterator.call(context, value, index, this));
933 }, this);
934 return results;
937 function include(object) {
938 if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)
939 return true;
941 var found = false;
942 this.each(function(value) {
943 if (value == object) {
944 found = true;
945 throw $break;
948 return found;
951 function inGroupsOf(number, fillWith) {
952 fillWith = Object.isUndefined(fillWith) ? null : fillWith;
953 return this.eachSlice(number, function(slice) {
954 while(slice.length < number) slice.push(fillWith);
955 return slice;
959 function inject(memo, iterator, context) {
960 this.each(function(value, index) {
961 memo = iterator.call(context, memo, value, index, this);
962 }, this);
963 return memo;
966 function invoke(method) {
967 var args = $A(arguments).slice(1);
968 return this.map(function(value) {
969 return value[method].apply(value, args);
973 function max(iterator, context) {
974 iterator = iterator || Prototype.K;
975 var result;
976 this.each(function(value, index) {
977 value = iterator.call(context, value, index, this);
978 if (result == null || value >= result)
979 result = value;
980 }, this);
981 return result;
984 function min(iterator, context) {
985 iterator = iterator || Prototype.K;
986 var result;
987 this.each(function(value, index) {
988 value = iterator.call(context, value, index, this);
989 if (result == null || value < result)
990 result = value;
991 }, this);
992 return result;
995 function partition(iterator, context) {
996 iterator = iterator || Prototype.K;
997 var trues = [], falses = [];
998 this.each(function(value, index) {
999 (iterator.call(context, value, index, this) ?
1000 trues : falses).push(value);
1001 }, this);
1002 return [trues, falses];
1005 function pluck(property) {
1006 var results = [];
1007 this.each(function(value) {
1008 results.push(value[property]);
1010 return results;
1013 function reject(iterator, context) {
1014 var results = [];
1015 this.each(function(value, index) {
1016 if (!iterator.call(context, value, index, this))
1017 results.push(value);
1018 }, this);
1019 return results;
1022 function sortBy(iterator, context) {
1023 return this.map(function(value, index) {
1024 return {
1025 value: value,
1026 criteria: iterator.call(context, value, index, this)
1028 }, this).sort(function(left, right) {
1029 var a = left.criteria, b = right.criteria;
1030 return a < b ? -1 : a > b ? 1 : 0;
1031 }).pluck('value');
1034 function toArray() {
1035 return this.map();
1038 function zip() {
1039 var iterator = Prototype.K, args = $A(arguments);
1040 if (Object.isFunction(args.last()))
1041 iterator = args.pop();
1043 var collections = [this].concat(args).map($A);
1044 return this.map(function(value, index) {
1045 return iterator(collections.pluck(index));
1049 function size() {
1050 return this.toArray().length;
1053 function inspect() {
1054 return '#<Enumerable:' + this.toArray().inspect() + '>';
1065 return {
1066 each: each,
1067 eachSlice: eachSlice,
1068 all: all,
1069 every: all,
1070 any: any,
1071 some: any,
1072 collect: collect,
1073 map: collect,
1074 detect: detect,
1075 findAll: findAll,
1076 select: findAll,
1077 filter: findAll,
1078 grep: grep,
1079 include: include,
1080 member: include,
1081 inGroupsOf: inGroupsOf,
1082 inject: inject,
1083 invoke: invoke,
1084 max: max,
1085 min: min,
1086 partition: partition,
1087 pluck: pluck,
1088 reject: reject,
1089 sortBy: sortBy,
1090 toArray: toArray,
1091 entries: toArray,
1092 zip: zip,
1093 size: size,
1094 inspect: inspect,
1095 find: detect
1097 })();
1099 function $A(iterable) {
1100 if (!iterable) return [];
1101 if ('toArray' in Object(iterable)) return iterable.toArray();
1102 var length = iterable.length || 0, results = new Array(length);
1103 while (length--) results[length] = iterable[length];
1104 return results;
1108 function $w(string) {
1109 if (!Object.isString(string)) return [];
1110 string = string.strip();
1111 return string ? string.split(/\s+/) : [];
1114 Array.from = $A;
1117 (function() {
1118 var arrayProto = Array.prototype,
1119 slice = arrayProto.slice,
1120 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
1122 function each(iterator, context) {
1123 for (var i = 0, length = this.length >>> 0; i < length; i++) {
1124 if (i in this) iterator.call(context, this[i], i, this);
1127 if (!_each) _each = each;
1129 function clear() {
1130 this.length = 0;
1131 return this;
1134 function first() {
1135 return this[0];
1138 function last() {
1139 return this[this.length - 1];
1142 function compact() {
1143 return this.select(function(value) {
1144 return value != null;
1148 function flatten() {
1149 return this.inject([], function(array, value) {
1150 if (Object.isArray(value))
1151 return array.concat(value.flatten());
1152 array.push(value);
1153 return array;
1157 function without() {
1158 var values = slice.call(arguments, 0);
1159 return this.select(function(value) {
1160 return !values.include(value);
1164 function reverse(inline) {
1165 return (inline === false ? this.toArray() : this)._reverse();
1168 function uniq(sorted) {
1169 return this.inject([], function(array, value, index) {
1170 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
1171 array.push(value);
1172 return array;
1176 function intersect(array) {
1177 return this.uniq().findAll(function(item) {
1178 return array.indexOf(item) !== -1;
1183 function clone() {
1184 return slice.call(this, 0);
1187 function size() {
1188 return this.length;
1191 function inspect() {
1192 return '[' + this.map(Object.inspect).join(', ') + ']';
1195 function indexOf(item, i) {
1196 if (this == null) throw new TypeError();
1198 var array = Object(this), length = array.length >>> 0;
1199 if (length === 0) return -1;
1201 i = Number(i);
1202 if (isNaN(i)) {
1203 i = 0;
1204 } else if (i !== 0 && isFinite(i)) {
1205 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1208 if (i > length) return -1;
1210 var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);
1211 for (; k < length; k++)
1212 if (k in array && array[k] === item) return k;
1213 return -1;
1217 function lastIndexOf(item, i) {
1218 if (this == null) throw new TypeError();
1220 var array = Object(this), length = array.length >>> 0;
1221 if (length === 0) return -1;
1223 if (!Object.isUndefined(i)) {
1224 i = Number(i);
1225 if (isNaN(i)) {
1226 i = 0;
1227 } else if (i !== 0 && isFinite(i)) {
1228 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
1230 } else {
1231 i = length;
1234 var k = i >= 0 ? Math.min(i, length - 1) :
1235 length - Math.abs(i);
1237 for (; k >= 0; k--)
1238 if (k in array && array[k] === item) return k;
1239 return -1;
1242 function concat(_) {
1243 var array = [], items = slice.call(arguments, 0), item, n = 0;
1244 items.unshift(this);
1245 for (var i = 0, length = items.length; i < length; i++) {
1246 item = items[i];
1247 if (Object.isArray(item) && !('callee' in item)) {
1248 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
1249 if (j in item) array[n] = item[j];
1250 n++;
1252 } else {
1253 array[n++] = item;
1256 array.length = n;
1257 return array;
1261 function wrapNative(method) {
1262 return function() {
1263 if (arguments.length === 0) {
1264 return method.call(this, Prototype.K);
1265 } else if (arguments[0] === undefined) {
1266 var args = slice.call(arguments, 1);
1267 args.unshift(Prototype.K);
1268 return method.apply(this, args);
1269 } else {
1270 return method.apply(this, arguments);
1276 function map(iterator) {
1277 if (this == null) throw new TypeError();
1278 iterator = iterator || Prototype.K;
1280 var object = Object(this);
1281 var results = [], context = arguments[1], n = 0;
1283 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1284 if (i in object) {
1285 results[n] = iterator.call(context, object[i], i, object);
1287 n++;
1289 results.length = n;
1290 return results;
1293 if (arrayProto.map) {
1294 map = wrapNative(Array.prototype.map);
1297 function filter(iterator) {
1298 if (this == null || !Object.isFunction(iterator))
1299 throw new TypeError();
1301 var object = Object(this);
1302 var results = [], context = arguments[1], value;
1304 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1305 if (i in object) {
1306 value = object[i];
1307 if (iterator.call(context, value, i, object)) {
1308 results.push(value);
1312 return results;
1315 if (arrayProto.filter) {
1316 filter = Array.prototype.filter;
1319 function some(iterator) {
1320 if (this == null) throw new TypeError();
1321 iterator = iterator || Prototype.K;
1322 var context = arguments[1];
1324 var object = Object(this);
1325 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1326 if (i in object && iterator.call(context, object[i], i, object)) {
1327 return true;
1331 return false;
1334 if (arrayProto.some) {
1335 some = wrapNative(Array.prototype.some);
1338 function every(iterator) {
1339 if (this == null) throw new TypeError();
1340 iterator = iterator || Prototype.K;
1341 var context = arguments[1];
1343 var object = Object(this);
1344 for (var i = 0, length = object.length >>> 0; i < length; i++) {
1345 if (i in object && !iterator.call(context, object[i], i, object)) {
1346 return false;
1350 return true;
1353 if (arrayProto.every) {
1354 every = wrapNative(Array.prototype.every);
1358 Object.extend(arrayProto, Enumerable);
1360 if (arrayProto.entries === Enumerable.entries) {
1361 delete arrayProto.entries;
1364 if (!arrayProto._reverse)
1365 arrayProto._reverse = arrayProto.reverse;
1367 Object.extend(arrayProto, {
1368 _each: _each,
1370 map: map,
1371 collect: map,
1372 select: filter,
1373 filter: filter,
1374 findAll: filter,
1375 some: some,
1376 any: some,
1377 every: every,
1378 all: every,
1380 clear: clear,
1381 first: first,
1382 last: last,
1383 compact: compact,
1384 flatten: flatten,
1385 without: without,
1386 reverse: reverse,
1387 uniq: uniq,
1388 intersect: intersect,
1389 clone: clone,
1390 toArray: clone,
1391 size: size,
1392 inspect: inspect
1395 var CONCAT_ARGUMENTS_BUGGY = (function() {
1396 return [].concat(arguments)[0][0] !== 1;
1397 })(1,2);
1399 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
1401 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
1402 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
1403 })();
1404 function $H(object) {
1405 return new Hash(object);
1408 var Hash = Class.create(Enumerable, (function() {
1409 function initialize(object) {
1410 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1414 function _each(iterator, context) {
1415 var i = 0;
1416 for (var key in this._object) {
1417 var value = this._object[key], pair = [key, value];
1418 pair.key = key;
1419 pair.value = value;
1420 iterator.call(context, pair, i);
1421 i++;
1425 function set(key, value) {
1426 return this._object[key] = value;
1429 function get(key) {
1430 if (this._object[key] !== Object.prototype[key])
1431 return this._object[key];
1434 function unset(key) {
1435 var value = this._object[key];
1436 delete this._object[key];
1437 return value;
1440 function toObject() {
1441 return Object.clone(this._object);
1446 function keys() {
1447 return this.pluck('key');
1450 function values() {
1451 return this.pluck('value');
1454 function index(value) {
1455 var match = this.detect(function(pair) {
1456 return pair.value === value;
1458 return match && match.key;
1461 function merge(object) {
1462 return this.clone().update(object);
1465 function update(object) {
1466 return new Hash(object).inject(this, function(result, pair) {
1467 result.set(pair.key, pair.value);
1468 return result;
1472 function toQueryPair(key, value) {
1473 if (Object.isUndefined(value)) return key;
1475 value = String.interpret(value);
1477 value = value.gsub(/(\r)?\n/, '\r\n');
1478 value = encodeURIComponent(value);
1479 value = value.gsub(/%20/, '+');
1480 return key + '=' + value;
1483 function toQueryString() {
1484 return this.inject([], function(results, pair) {
1485 var key = encodeURIComponent(pair.key), values = pair.value;
1487 if (values && typeof values == 'object') {
1488 if (Object.isArray(values)) {
1489 var queryValues = [];
1490 for (var i = 0, len = values.length, value; i < len; i++) {
1491 value = values[i];
1492 queryValues.push(toQueryPair(key, value));
1494 return results.concat(queryValues);
1496 } else results.push(toQueryPair(key, values));
1497 return results;
1498 }).join('&');
1501 function inspect() {
1502 return '#<Hash:{' + this.map(function(pair) {
1503 return pair.map(Object.inspect).join(': ');
1504 }).join(', ') + '}>';
1507 function clone() {
1508 return new Hash(this);
1511 return {
1512 initialize: initialize,
1513 _each: _each,
1514 set: set,
1515 get: get,
1516 unset: unset,
1517 toObject: toObject,
1518 toTemplateReplacements: toObject,
1519 keys: keys,
1520 values: values,
1521 index: index,
1522 merge: merge,
1523 update: update,
1524 toQueryString: toQueryString,
1525 inspect: inspect,
1526 toJSON: toObject,
1527 clone: clone
1529 })());
1531 Hash.from = $H;
1532 Object.extend(Number.prototype, (function() {
1533 function toColorPart() {
1534 return this.toPaddedString(2, 16);
1537 function succ() {
1538 return this + 1;
1541 function times(iterator, context) {
1542 $R(0, this, true).each(iterator, context);
1543 return this;
1546 function toPaddedString(length, radix) {
1547 var string = this.toString(radix || 10);
1548 return '0'.times(length - string.length) + string;
1551 function abs() {
1552 return Math.abs(this);
1555 function round() {
1556 return Math.round(this);
1559 function ceil() {
1560 return Math.ceil(this);
1563 function floor() {
1564 return Math.floor(this);
1567 return {
1568 toColorPart: toColorPart,
1569 succ: succ,
1570 times: times,
1571 toPaddedString: toPaddedString,
1572 abs: abs,
1573 round: round,
1574 ceil: ceil,
1575 floor: floor
1577 })());
1579 function $R(start, end, exclusive) {
1580 return new ObjectRange(start, end, exclusive);
1583 var ObjectRange = Class.create(Enumerable, (function() {
1584 function initialize(start, end, exclusive) {
1585 this.start = start;
1586 this.end = end;
1587 this.exclusive = exclusive;
1590 function _each(iterator, context) {
1591 var value = this.start, i;
1592 for (i = 0; this.include(value); i++) {
1593 iterator.call(context, value, i);
1594 value = value.succ();
1598 function include(value) {
1599 if (value < this.start)
1600 return false;
1601 if (this.exclusive)
1602 return value < this.end;
1603 return value <= this.end;
1606 return {
1607 initialize: initialize,
1608 _each: _each,
1609 include: include
1611 })());
1615 var Abstract = { };
1618 var Try = {
1619 these: function() {
1620 var returnValue;
1622 for (var i = 0, length = arguments.length; i < length; i++) {
1623 var lambda = arguments[i];
1624 try {
1625 returnValue = lambda();
1626 break;
1627 } catch (e) { }
1630 return returnValue;
1634 var Ajax = {
1635 getTransport: function() {
1636 return Try.these(
1637 function() {return new XMLHttpRequest()},
1638 function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1639 function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1640 ) || false;
1643 activeRequestCount: 0
1646 Ajax.Responders = {
1647 responders: [],
1649 _each: function(iterator, context) {
1650 this.responders._each(iterator, context);
1653 register: function(responder) {
1654 if (!this.include(responder))
1655 this.responders.push(responder);
1658 unregister: function(responder) {
1659 this.responders = this.responders.without(responder);
1662 dispatch: function(callback, request, transport, json) {
1663 this.each(function(responder) {
1664 if (Object.isFunction(responder[callback])) {
1665 try {
1666 responder[callback].apply(responder, [request, transport, json]);
1667 } catch (e) { }
1673 Object.extend(Ajax.Responders, Enumerable);
1675 Ajax.Responders.register({
1676 onCreate: function() { Ajax.activeRequestCount++ },
1677 onComplete: function() { Ajax.activeRequestCount-- }
1679 Ajax.Base = Class.create({
1680 initialize: function(options) {
1681 this.options = {
1682 method: 'post',
1683 asynchronous: true,
1684 contentType: 'application/x-www-form-urlencoded',
1685 encoding: 'UTF-8',
1686 parameters: '',
1687 evalJSON: true,
1688 evalJS: true
1690 Object.extend(this.options, options || { });
1692 this.options.method = this.options.method.toLowerCase();
1694 if (Object.isHash(this.options.parameters))
1695 this.options.parameters = this.options.parameters.toObject();
1698 Ajax.Request = Class.create(Ajax.Base, {
1699 _complete: false,
1701 initialize: function($super, url, options) {
1702 $super(options);
1703 this.transport = Ajax.getTransport();
1704 this.request(url);
1707 request: function(url) {
1708 this.url = url;
1709 this.method = this.options.method;
1710 var params = Object.isString(this.options.parameters) ?
1711 this.options.parameters :
1712 Object.toQueryString(this.options.parameters);
1714 if (!['get', 'post'].include(this.method)) {
1715 params += (params ? '&' : '') + "_method=" + this.method;
1716 this.method = 'post';
1719 if (params && this.method === 'get') {
1720 this.url += (this.url.include('?') ? '&' : '?') + params;
1723 this.parameters = params.toQueryParams();
1725 try {
1726 var response = new Ajax.Response(this);
1727 if (this.options.onCreate) this.options.onCreate(response);
1728 Ajax.Responders.dispatch('onCreate', this, response);
1730 this.transport.open(this.method.toUpperCase(), this.url,
1731 this.options.asynchronous);
1733 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1735 this.transport.onreadystatechange = this.onStateChange.bind(this);
1736 this.setRequestHeaders();
1738 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1739 this.transport.send(this.body);
1741 /* Force Firefox to handle ready state 4 for synchronous requests */
1742 if (!this.options.asynchronous && this.transport.overrideMimeType)
1743 this.onStateChange();
1746 catch (e) {
1747 this.dispatchException(e);
1751 onStateChange: function() {
1752 var readyState = this.transport.readyState;
1753 if (readyState > 1 && !((readyState == 4) && this._complete))
1754 this.respondToReadyState(this.transport.readyState);
1757 setRequestHeaders: function() {
1758 var headers = {
1759 'X-Requested-With': 'XMLHttpRequest',
1760 'X-Prototype-Version': Prototype.Version,
1761 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1764 if (this.method == 'post') {
1765 headers['Content-type'] = this.options.contentType +
1766 (this.options.encoding ? '; charset=' + this.options.encoding : '');
1768 /* Force "Connection: close" for older Mozilla browsers to work
1769 * around a bug where XMLHttpRequest sends an incorrect
1770 * Content-length header. See Mozilla Bugzilla #246651.
1772 if (this.transport.overrideMimeType &&
1773 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1774 headers['Connection'] = 'close';
1777 if (typeof this.options.requestHeaders == 'object') {
1778 var extras = this.options.requestHeaders;
1780 if (Object.isFunction(extras.push))
1781 for (var i = 0, length = extras.length; i < length; i += 2)
1782 headers[extras[i]] = extras[i+1];
1783 else
1784 $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1787 for (var name in headers)
1788 if (headers[name] != null)
1789 this.transport.setRequestHeader(name, headers[name]);
1792 success: function() {
1793 var status = this.getStatus();
1794 return !status || (status >= 200 && status < 300) || status == 304;
1797 getStatus: function() {
1798 try {
1799 if (this.transport.status === 1223) return 204;
1800 return this.transport.status || 0;
1801 } catch (e) { return 0 }
1804 respondToReadyState: function(readyState) {
1805 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1807 if (state == 'Complete') {
1808 try {
1809 this._complete = true;
1810 (this.options['on' + response.status]
1811 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1812 || Prototype.emptyFunction)(response, response.headerJSON);
1813 } catch (e) {
1814 this.dispatchException(e);
1817 var contentType = response.getHeader('Content-type');
1818 if (this.options.evalJS == 'force'
1819 || (this.options.evalJS && this.isSameOrigin() && contentType
1820 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1821 this.evalResponse();
1824 try {
1825 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1826 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1827 } catch (e) {
1828 this.dispatchException(e);
1831 if (state == 'Complete') {
1832 this.transport.onreadystatechange = Prototype.emptyFunction;
1836 isSameOrigin: function() {
1837 var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1838 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1839 protocol: location.protocol,
1840 domain: document.domain,
1841 port: location.port ? ':' + location.port : ''
1842 }));
1845 getHeader: function(name) {
1846 try {
1847 return this.transport.getResponseHeader(name) || null;
1848 } catch (e) { return null; }
1851 evalResponse: function() {
1852 try {
1853 return eval((this.transport.responseText || '').unfilterJSON());
1854 } catch (e) {
1855 this.dispatchException(e);
1859 dispatchException: function(exception) {
1860 (this.options.onException || Prototype.emptyFunction)(this, exception);
1861 Ajax.Responders.dispatch('onException', this, exception);
1865 Ajax.Request.Events =
1866 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1875 Ajax.Response = Class.create({
1876 initialize: function(request){
1877 this.request = request;
1878 var transport = this.transport = request.transport,
1879 readyState = this.readyState = transport.readyState;
1881 if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1882 this.status = this.getStatus();
1883 this.statusText = this.getStatusText();
1884 this.responseText = String.interpret(transport.responseText);
1885 this.headerJSON = this._getHeaderJSON();
1888 if (readyState == 4) {
1889 var xml = transport.responseXML;
1890 this.responseXML = Object.isUndefined(xml) ? null : xml;
1891 this.responseJSON = this._getResponseJSON();
1895 status: 0,
1897 statusText: '',
1899 getStatus: Ajax.Request.prototype.getStatus,
1901 getStatusText: function() {
1902 try {
1903 return this.transport.statusText || '';
1904 } catch (e) { return '' }
1907 getHeader: Ajax.Request.prototype.getHeader,
1909 getAllHeaders: function() {
1910 try {
1911 return this.getAllResponseHeaders();
1912 } catch (e) { return null }
1915 getResponseHeader: function(name) {
1916 return this.transport.getResponseHeader(name);
1919 getAllResponseHeaders: function() {
1920 return this.transport.getAllResponseHeaders();
1923 _getHeaderJSON: function() {
1924 var json = this.getHeader('X-JSON');
1925 if (!json) return null;
1927 try {
1928 json = decodeURIComponent(escape(json));
1929 } catch(e) {
1932 try {
1933 return json.evalJSON(this.request.options.sanitizeJSON ||
1934 !this.request.isSameOrigin());
1935 } catch (e) {
1936 this.request.dispatchException(e);
1940 _getResponseJSON: function() {
1941 var options = this.request.options;
1942 if (!options.evalJSON || (options.evalJSON != 'force' &&
1943 !(this.getHeader('Content-type') || '').include('application/json')) ||
1944 this.responseText.blank())
1945 return null;
1946 try {
1947 return this.responseText.evalJSON(options.sanitizeJSON ||
1948 !this.request.isSameOrigin());
1949 } catch (e) {
1950 this.request.dispatchException(e);
1955 Ajax.Updater = Class.create(Ajax.Request, {
1956 initialize: function($super, container, url, options) {
1957 this.container = {
1958 success: (container.success || container),
1959 failure: (container.failure || (container.success ? null : container))
1962 options = Object.clone(options);
1963 var onComplete = options.onComplete;
1964 options.onComplete = (function(response, json) {
1965 this.updateContent(response.responseText);
1966 if (Object.isFunction(onComplete)) onComplete(response, json);
1967 }).bind(this);
1969 $super(url, options);
1972 updateContent: function(responseText) {
1973 var receiver = this.container[this.success() ? 'success' : 'failure'],
1974 options = this.options;
1976 if (!options.evalScripts) responseText = responseText.stripScripts();
1978 if (receiver = $(receiver)) {
1979 if (options.insertion) {
1980 if (Object.isString(options.insertion)) {
1981 var insertion = { }; insertion[options.insertion] = responseText;
1982 receiver.insert(insertion);
1984 else options.insertion(receiver, responseText);
1986 else receiver.update(responseText);
1991 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1992 initialize: function($super, container, url, options) {
1993 $super(options);
1994 this.onComplete = this.options.onComplete;
1996 this.frequency = (this.options.frequency || 2);
1997 this.decay = (this.options.decay || 1);
1999 this.updater = { };
2000 this.container = container;
2001 this.url = url;
2003 this.start();
2006 start: function() {
2007 this.options.onComplete = this.updateComplete.bind(this);
2008 this.onTimerEvent();
2011 stop: function() {
2012 this.updater.options.onComplete = undefined;
2013 clearTimeout(this.timer);
2014 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
2017 updateComplete: function(response) {
2018 if (this.options.decay) {
2019 this.decay = (response.responseText == this.lastText ?
2020 this.decay * this.options.decay : 1);
2022 this.lastText = response.responseText;
2024 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
2027 onTimerEvent: function() {
2028 this.updater = new Ajax.Updater(this.container, this.url, this.options);
2032 (function(GLOBAL) {
2034 var UNDEFINED;
2035 var SLICE = Array.prototype.slice;
2037 var DIV = document.createElement('div');
2040 function $(element) {
2041 if (arguments.length > 1) {
2042 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
2043 elements.push($(arguments[i]));
2044 return elements;
2047 if (Object.isString(element))
2048 element = document.getElementById(element);
2049 return Element.extend(element);
2052 GLOBAL.$ = $;
2055 if (!GLOBAL.Node) GLOBAL.Node = {};
2057 if (!GLOBAL.Node.ELEMENT_NODE) {
2058 Object.extend(GLOBAL.Node, {
2059 ELEMENT_NODE: 1,
2060 ATTRIBUTE_NODE: 2,
2061 TEXT_NODE: 3,
2062 CDATA_SECTION_NODE: 4,
2063 ENTITY_REFERENCE_NODE: 5,
2064 ENTITY_NODE: 6,
2065 PROCESSING_INSTRUCTION_NODE: 7,
2066 COMMENT_NODE: 8,
2067 DOCUMENT_NODE: 9,
2068 DOCUMENT_TYPE_NODE: 10,
2069 DOCUMENT_FRAGMENT_NODE: 11,
2070 NOTATION_NODE: 12
2074 var ELEMENT_CACHE = {};
2076 function shouldUseCreationCache(tagName, attributes) {
2077 if (tagName === 'select') return false;
2078 if ('type' in attributes) return false;
2079 return true;
2082 var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
2083 try {
2084 var el = document.createElement('<input name="x">');
2085 return el.tagName.toLowerCase() === 'input' && el.name === 'x';
2087 catch(err) {
2088 return false;
2090 })();
2093 var oldElement = GLOBAL.Element;
2094 function Element(tagName, attributes) {
2095 attributes = attributes || {};
2096 tagName = tagName.toLowerCase();
2098 if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
2099 tagName = '<' + tagName + ' name="' + attributes.name + '">';
2100 delete attributes.name;
2101 return Element.writeAttribute(document.createElement(tagName), attributes);
2104 if (!ELEMENT_CACHE[tagName])
2105 ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));
2107 var node = shouldUseCreationCache(tagName, attributes) ?
2108 ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);
2110 return Element.writeAttribute(node, attributes);
2113 GLOBAL.Element = Element;
2115 Object.extend(GLOBAL.Element, oldElement || {});
2116 if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;
2118 Element.Methods = { ByTag: {}, Simulated: {} };
2120 var methods = {};
2122 var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };
2123 function inspect(element) {
2124 element = $(element);
2125 var result = '<' + element.tagName.toLowerCase();
2127 var attribute, value;
2128 for (var property in INSPECT_ATTRIBUTES) {
2129 attribute = INSPECT_ATTRIBUTES[property];
2130 value = (element[property] || '').toString();
2131 if (value) result += ' ' + attribute + '=' + value.inspect(true);
2134 return result + '>';
2137 methods.inspect = inspect;
2140 function visible(element) {
2141 return $(element).getStyle('display') !== 'none';
2144 function toggle(element, bool) {
2145 element = $(element);
2146 if (typeof bool !== 'boolean')
2147 bool = !Element.visible(element);
2148 Element[bool ? 'show' : 'hide'](element);
2150 return element;
2153 function hide(element) {
2154 element = $(element);
2155 element.style.display = 'none';
2156 return element;
2159 function show(element) {
2160 element = $(element);
2161 element.style.display = '';
2162 return element;
2166 Object.extend(methods, {
2167 visible: visible,
2168 toggle: toggle,
2169 hide: hide,
2170 show: show
2174 function remove(element) {
2175 element = $(element);
2176 element.parentNode.removeChild(element);
2177 return element;
2180 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
2181 var el = document.createElement("select"),
2182 isBuggy = true;
2183 el.innerHTML = "<option value=\"test\">test</option>";
2184 if (el.options && el.options[0]) {
2185 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
2187 el = null;
2188 return isBuggy;
2189 })();
2191 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
2192 try {
2193 var el = document.createElement("table");
2194 if (el && el.tBodies) {
2195 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
2196 var isBuggy = typeof el.tBodies[0] == "undefined";
2197 el = null;
2198 return isBuggy;
2200 } catch (e) {
2201 return true;
2203 })();
2205 var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
2206 try {
2207 var el = document.createElement('div');
2208 el.innerHTML = "<link />";
2209 var isBuggy = (el.childNodes.length === 0);
2210 el = null;
2211 return isBuggy;
2212 } catch(e) {
2213 return true;
2215 })();
2217 var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
2218 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
2220 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
2221 var s = document.createElement("script"),
2222 isBuggy = false;
2223 try {
2224 s.appendChild(document.createTextNode(""));
2225 isBuggy = !s.firstChild ||
2226 s.firstChild && s.firstChild.nodeType !== 3;
2227 } catch (e) {
2228 isBuggy = true;
2230 s = null;
2231 return isBuggy;
2232 })();
2234 function update(element, content) {
2235 element = $(element);
2237 var descendants = element.getElementsByTagName('*'),
2238 i = descendants.length;
2239 while (i--) purgeElement(descendants[i]);
2241 if (content && content.toElement)
2242 content = content.toElement();
2244 if (Object.isElement(content))
2245 return element.update().insert(content);
2248 content = Object.toHTML(content);
2249 var tagName = element.tagName.toUpperCase();
2251 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
2252 element.text = content;
2253 return element;
2256 if (ANY_INNERHTML_BUGGY) {
2257 if (tagName in INSERTION_TRANSLATIONS.tags) {
2258 while (element.firstChild)
2259 element.removeChild(element.firstChild);
2261 var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2262 for (var i = 0, node; node = nodes[i]; i++)
2263 element.appendChild(node);
2265 } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
2266 while (element.firstChild)
2267 element.removeChild(element.firstChild);
2269 var nodes = getContentFromAnonymousElement(tagName,
2270 content.stripScripts(), true);
2272 for (var i = 0, node; node = nodes[i]; i++)
2273 element.appendChild(node);
2274 } else {
2275 element.innerHTML = content.stripScripts();
2277 } else {
2278 element.innerHTML = content.stripScripts();
2281 content.evalScripts.bind(content).defer();
2282 return element;
2285 function replace(element, content) {
2286 element = $(element);
2288 if (content && content.toElement) {
2289 content = content.toElement();
2290 } else if (!Object.isElement(content)) {
2291 content = Object.toHTML(content);
2292 var range = element.ownerDocument.createRange();
2293 range.selectNode(element);
2294 content.evalScripts.bind(content).defer();
2295 content = range.createContextualFragment(content.stripScripts());
2298 element.parentNode.replaceChild(content, element);
2299 return element;
2302 var INSERTION_TRANSLATIONS = {
2303 before: function(element, node) {
2304 element.parentNode.insertBefore(node, element);
2306 top: function(element, node) {
2307 element.insertBefore(node, element.firstChild);
2309 bottom: function(element, node) {
2310 element.appendChild(node);
2312 after: function(element, node) {
2313 element.parentNode.insertBefore(node, element.nextSibling);
2316 tags: {
2317 TABLE: ['<table>', '</table>', 1],
2318 TBODY: ['<table><tbody>', '</tbody></table>', 2],
2319 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2320 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2321 SELECT: ['<select>', '</select>', 1]
2325 var tags = INSERTION_TRANSLATIONS.tags;
2327 Object.extend(tags, {
2328 THEAD: tags.TBODY,
2329 TFOOT: tags.TBODY,
2330 TH: tags.TD
2333 function replace_IE(element, content) {
2334 element = $(element);
2335 if (content && content.toElement)
2336 content = content.toElement();
2337 if (Object.isElement(content)) {
2338 element.parentNode.replaceChild(content, element);
2339 return element;
2342 content = Object.toHTML(content);
2343 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2345 if (tagName in INSERTION_TRANSLATIONS.tags) {
2346 var nextSibling = Element.next(element);
2347 var fragments = getContentFromAnonymousElement(
2348 tagName, content.stripScripts());
2350 parent.removeChild(element);
2352 var iterator;
2353 if (nextSibling)
2354 iterator = function(node) { parent.insertBefore(node, nextSibling) };
2355 else
2356 iterator = function(node) { parent.appendChild(node); }
2358 fragments.each(iterator);
2359 } else {
2360 element.outerHTML = content.stripScripts();
2363 content.evalScripts.bind(content).defer();
2364 return element;
2367 if ('outerHTML' in document.documentElement)
2368 replace = replace_IE;
2370 function isContent(content) {
2371 if (Object.isUndefined(content) || content === null) return false;
2373 if (Object.isString(content) || Object.isNumber(content)) return true;
2374 if (Object.isElement(content)) return true;
2375 if (content.toElement || content.toHTML) return true;
2377 return false;
2380 function insertContentAt(element, content, position) {
2381 position = position.toLowerCase();
2382 var method = INSERTION_TRANSLATIONS[position];
2384 if (content && content.toElement) content = content.toElement();
2385 if (Object.isElement(content)) {
2386 method(element, content);
2387 return element;
2390 content = Object.toHTML(content);
2391 var tagName = ((position === 'before' || position === 'after') ?
2392 element.parentNode : element).tagName.toUpperCase();
2394 var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());
2396 if (position === 'top' || position === 'after') childNodes.reverse();
2398 for (var i = 0, node; node = childNodes[i]; i++)
2399 method(element, node);
2401 content.evalScripts.bind(content).defer();
2404 function insert(element, insertions) {
2405 element = $(element);
2407 if (isContent(insertions))
2408 insertions = { bottom: insertions };
2410 for (var position in insertions)
2411 insertContentAt(element, insertions[position], position);
2413 return element;
2416 function wrap(element, wrapper, attributes) {
2417 element = $(element);
2419 if (Object.isElement(wrapper)) {
2420 $(wrapper).writeAttribute(attributes || {});
2421 } else if (Object.isString(wrapper)) {
2422 wrapper = new Element(wrapper, attributes);
2423 } else {
2424 wrapper = new Element('div', wrapper);
2427 if (element.parentNode)
2428 element.parentNode.replaceChild(wrapper, element);
2430 wrapper.appendChild(element);
2432 return wrapper;
2435 function cleanWhitespace(element) {
2436 element = $(element);
2437 var node = element.firstChild;
2439 while (node) {
2440 var nextNode = node.nextSibling;
2441 if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue))
2442 element.removeChild(node);
2443 node = nextNode;
2445 return element;
2448 function empty(element) {
2449 return $(element).innerHTML.blank();
2452 function getContentFromAnonymousElement(tagName, html, force) {
2453 var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;
2455 var workaround = !!t;
2456 if (!workaround && force) {
2457 workaround = true;
2458 t = ['', '', 0];
2461 if (workaround) {
2462 div.innerHTML = '&#160;' + t[0] + html + t[1];
2463 div.removeChild(div.firstChild);
2464 for (var i = t[2]; i--; )
2465 div = div.firstChild;
2466 } else {
2467 div.innerHTML = html;
2470 return $A(div.childNodes);
2473 function clone(element, deep) {
2474 if (!(element = $(element))) return;
2475 var clone = element.cloneNode(deep);
2476 if (!HAS_UNIQUE_ID_PROPERTY) {
2477 clone._prototypeUID = UNDEFINED;
2478 if (deep) {
2479 var descendants = Element.select(clone, '*'),
2480 i = descendants.length;
2481 while (i--)
2482 descendants[i]._prototypeUID = UNDEFINED;
2485 return Element.extend(clone);
2488 function purgeElement(element) {
2489 var uid = getUniqueElementID(element);
2490 if (uid) {
2491 Element.stopObserving(element);
2492 if (!HAS_UNIQUE_ID_PROPERTY)
2493 element._prototypeUID = UNDEFINED;
2494 delete Element.Storage[uid];
2498 function purgeCollection(elements) {
2499 var i = elements.length;
2500 while (i--)
2501 purgeElement(elements[i]);
2504 function purgeCollection_IE(elements) {
2505 var i = elements.length, element, uid;
2506 while (i--) {
2507 element = elements[i];
2508 uid = getUniqueElementID(element);
2509 delete Element.Storage[uid];
2510 delete Event.cache[uid];
2514 if (HAS_UNIQUE_ID_PROPERTY) {
2515 purgeCollection = purgeCollection_IE;
2519 function purge(element) {
2520 if (!(element = $(element))) return;
2521 purgeElement(element);
2523 var descendants = element.getElementsByTagName('*'),
2524 i = descendants.length;
2526 while (i--) purgeElement(descendants[i]);
2528 return null;
2531 Object.extend(methods, {
2532 remove: remove,
2533 update: update,
2534 replace: replace,
2535 insert: insert,
2536 wrap: wrap,
2537 cleanWhitespace: cleanWhitespace,
2538 empty: empty,
2539 clone: clone,
2540 purge: purge
2545 function recursivelyCollect(element, property, maximumLength) {
2546 element = $(element);
2547 maximumLength = maximumLength || -1;
2548 var elements = [];
2550 while (element = element[property]) {
2551 if (element.nodeType === Node.ELEMENT_NODE)
2552 elements.push(Element.extend(element));
2554 if (elements.length === maximumLength) break;
2557 return elements;
2561 function ancestors(element) {
2562 return recursivelyCollect(element, 'parentNode');
2565 function descendants(element) {
2566 return Element.select(element, '*');
2569 function firstDescendant(element) {
2570 element = $(element).firstChild;
2571 while (element && element.nodeType !== Node.ELEMENT_NODE)
2572 element = element.nextSibling;
2574 return $(element);
2577 function immediateDescendants(element) {
2578 var results = [], child = $(element).firstChild;
2580 while (child) {
2581 if (child.nodeType === Node.ELEMENT_NODE)
2582 results.push(Element.extend(child));
2584 child = child.nextSibling;
2587 return results;
2590 function previousSiblings(element) {
2591 return recursivelyCollect(element, 'previousSibling');
2594 function nextSiblings(element) {
2595 return recursivelyCollect(element, 'nextSibling');
2598 function siblings(element) {
2599 element = $(element);
2600 var previous = previousSiblings(element),
2601 next = nextSiblings(element);
2602 return previous.reverse().concat(next);
2605 function match(element, selector) {
2606 element = $(element);
2608 if (Object.isString(selector))
2609 return Prototype.Selector.match(element, selector);
2611 return selector.match(element);
2615 function _recursivelyFind(element, property, expression, index) {
2616 element = $(element), expression = expression || 0, index = index || 0;
2617 if (Object.isNumber(expression)) {
2618 index = expression, expression = null;
2621 while (element = element[property]) {
2622 if (element.nodeType !== 1) continue;
2623 if (expression && !Prototype.Selector.match(element, expression))
2624 continue;
2625 if (--index >= 0) continue;
2627 return Element.extend(element);
2632 function up(element, expression, index) {
2633 element = $(element);
2635 if (arguments.length === 1) return $(element.parentNode);
2636 return _recursivelyFind(element, 'parentNode', expression, index);
2639 function down(element, expression, index) {
2640 if (arguments.length === 1) return firstDescendant(element);
2641 element = $(element), expression = expression || 0, index = index || 0;
2643 if (Object.isNumber(expression))
2644 index = expression, expression = '*';
2646 var node = Prototype.Selector.select(expression, element)[index];
2647 return Element.extend(node);
2650 function previous(element, expression, index) {
2651 return _recursivelyFind(element, 'previousSibling', expression, index);
2654 function next(element, expression, index) {
2655 return _recursivelyFind(element, 'nextSibling', expression, index);
2658 function select(element) {
2659 element = $(element);
2660 var expressions = SLICE.call(arguments, 1).join(', ');
2661 return Prototype.Selector.select(expressions, element);
2664 function adjacent(element) {
2665 element = $(element);
2666 var expressions = SLICE.call(arguments, 1).join(', ');
2667 var siblings = Element.siblings(element), results = [];
2668 for (var i = 0, sibling; sibling = siblings[i]; i++) {
2669 if (Prototype.Selector.match(sibling, expressions))
2670 results.push(sibling);
2673 return results;
2676 function descendantOf_DOM(element, ancestor) {
2677 element = $(element), ancestor = $(ancestor);
2678 if (!element || !ancestor) return false;
2679 while (element = element.parentNode)
2680 if (element === ancestor) return true;
2681 return false;
2684 function descendantOf_contains(element, ancestor) {
2685 element = $(element), ancestor = $(ancestor);
2686 if (!element || !ancestor) return false;
2687 if (!ancestor.contains) return descendantOf_DOM(element, ancestor);
2688 return ancestor.contains(element) && ancestor !== element;
2691 function descendantOf_compareDocumentPosition(element, ancestor) {
2692 element = $(element), ancestor = $(ancestor);
2693 if (!element || !ancestor) return false;
2694 return (element.compareDocumentPosition(ancestor) & 8) === 8;
2697 var descendantOf;
2698 if (DIV.compareDocumentPosition) {
2699 descendantOf = descendantOf_compareDocumentPosition;
2700 } else if (DIV.contains) {
2701 descendantOf = descendantOf_contains;
2702 } else {
2703 descendantOf = descendantOf_DOM;
2707 Object.extend(methods, {
2708 recursivelyCollect: recursivelyCollect,
2709 ancestors: ancestors,
2710 descendants: descendants,
2711 firstDescendant: firstDescendant,
2712 immediateDescendants: immediateDescendants,
2713 previousSiblings: previousSiblings,
2714 nextSiblings: nextSiblings,
2715 siblings: siblings,
2716 match: match,
2717 up: up,
2718 down: down,
2719 previous: previous,
2720 next: next,
2721 select: select,
2722 adjacent: adjacent,
2723 descendantOf: descendantOf,
2725 getElementsBySelector: select,
2727 childElements: immediateDescendants
2731 var idCounter = 1;
2732 function identify(element) {
2733 element = $(element);
2734 var id = Element.readAttribute(element, 'id');
2735 if (id) return id;
2737 do { id = 'anonymous_element_' + idCounter++ } while ($(id));
2739 Element.writeAttribute(element, 'id', id);
2740 return id;
2744 function readAttribute(element, name) {
2745 return $(element).getAttribute(name);
2748 function readAttribute_IE(element, name) {
2749 element = $(element);
2751 var table = ATTRIBUTE_TRANSLATIONS.read;
2752 if (table.values[name])
2753 return table.values[name](element, name);
2755 if (table.names[name]) name = table.names[name];
2757 if (name.include(':')) {
2758 if (!element.attributes || !element.attributes[name]) return null;
2759 return element.attributes[name].value;
2762 return element.getAttribute(name);
2765 function readAttribute_Opera(element, name) {
2766 if (name === 'title') return element.title;
2767 return element.getAttribute(name);
2770 var PROBLEMATIC_ATTRIBUTE_READING = (function() {
2771 DIV.setAttribute('onclick', []);
2772 var value = DIV.getAttribute('onclick');
2773 var isFunction = Object.isArray(value);
2774 DIV.removeAttribute('onclick');
2775 return isFunction;
2776 })();
2778 if (PROBLEMATIC_ATTRIBUTE_READING) {
2779 readAttribute = readAttribute_IE;
2780 } else if (Prototype.Browser.Opera) {
2781 readAttribute = readAttribute_Opera;
2785 function writeAttribute(element, name, value) {
2786 element = $(element);
2787 var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;
2789 if (typeof name === 'object') {
2790 attributes = name;
2791 } else {
2792 attributes[name] = Object.isUndefined(value) ? true : value;
2795 for (var attr in attributes) {
2796 name = table.names[attr] || attr;
2797 value = attributes[attr];
2798 if (table.values[attr]) {
2799 value = table.values[attr](element, value);
2800 if (Object.isUndefined(value)) continue;
2802 if (value === false || value === null)
2803 element.removeAttribute(name);
2804 else if (value === true)
2805 element.setAttribute(name, name);
2806 else element.setAttribute(name, value);
2809 return element;
2812 var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () {
2813 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) {
2814 return false;
2816 var checkbox = document.createElement('<input type="checkbox">');
2817 checkbox.checked = true;
2818 var node = checkbox.getAttributeNode('checked');
2819 return !node || !node.specified;
2820 })();
2822 function hasAttribute(element, attribute) {
2823 attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;
2824 var node = $(element).getAttributeNode(attribute);
2825 return !!(node && node.specified);
2828 function hasAttribute_IE(element, attribute) {
2829 if (attribute === 'checked') {
2830 return element.checked;
2832 return hasAttribute(element, attribute);
2835 GLOBAL.Element.Methods.Simulated.hasAttribute =
2836 PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ?
2837 hasAttribute_IE : hasAttribute;
2839 function classNames(element) {
2840 return new Element.ClassNames(element);
2843 var regExpCache = {};
2844 function getRegExpForClassName(className) {
2845 if (regExpCache[className]) return regExpCache[className];
2847 var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
2848 regExpCache[className] = re;
2849 return re;
2852 function hasClassName(element, className) {
2853 if (!(element = $(element))) return;
2855 var elementClassName = element.className;
2857 if (elementClassName.length === 0) return false;
2858 if (elementClassName === className) return true;
2860 return getRegExpForClassName(className).test(elementClassName);
2863 function addClassName(element, className) {
2864 if (!(element = $(element))) return;
2866 if (!hasClassName(element, className))
2867 element.className += (element.className ? ' ' : '') + className;
2869 return element;
2872 function removeClassName(element, className) {
2873 if (!(element = $(element))) return;
2875 element.className = element.className.replace(
2876 getRegExpForClassName(className), ' ').strip();
2878 return element;
2881 function toggleClassName(element, className, bool) {
2882 if (!(element = $(element))) return;
2884 if (Object.isUndefined(bool))
2885 bool = !hasClassName(element, className);
2887 var method = Element[bool ? 'addClassName' : 'removeClassName'];
2888 return method(element, className);
2891 var ATTRIBUTE_TRANSLATIONS = {};
2893 var classProp = 'className', forProp = 'for';
2895 DIV.setAttribute(classProp, 'x');
2896 if (DIV.className !== 'x') {
2897 DIV.setAttribute('class', 'x');
2898 if (DIV.className === 'x')
2899 classProp = 'class';
2902 var LABEL = document.createElement('label');
2903 LABEL.setAttribute(forProp, 'x');
2904 if (LABEL.htmlFor !== 'x') {
2905 LABEL.setAttribute('htmlFor', 'x');
2906 if (LABEL.htmlFor === 'x')
2907 forProp = 'htmlFor';
2909 LABEL = null;
2911 function _getAttr(element, attribute) {
2912 return element.getAttribute(attribute);
2915 function _getAttr2(element, attribute) {
2916 return element.getAttribute(attribute, 2);
2919 function _getAttrNode(element, attribute) {
2920 var node = element.getAttributeNode(attribute);
2921 return node ? node.value : '';
2924 function _getFlag(element, attribute) {
2925 return $(element).hasAttribute(attribute) ? attribute : null;
2928 DIV.onclick = Prototype.emptyFunction;
2929 var onclickValue = DIV.getAttribute('onclick');
2931 var _getEv;
2933 if (String(onclickValue).indexOf('{') > -1) {
2934 _getEv = function(element, attribute) {
2935 var value = element.getAttribute(attribute);
2936 if (!value) return null;
2937 value = value.toString();
2938 value = value.split('{')[1];
2939 value = value.split('}')[0];
2940 return value.strip();
2943 else if (onclickValue === '') {
2944 _getEv = function(element, attribute) {
2945 var value = element.getAttribute(attribute);
2946 if (!value) return null;
2947 return value.strip();
2951 ATTRIBUTE_TRANSLATIONS.read = {
2952 names: {
2953 'class': classProp,
2954 'className': classProp,
2955 'for': forProp,
2956 'htmlFor': forProp
2959 values: {
2960 style: function(element) {
2961 return element.style.cssText.toLowerCase();
2963 title: function(element) {
2964 return element.title;
2969 ATTRIBUTE_TRANSLATIONS.write = {
2970 names: {
2971 className: 'class',
2972 htmlFor: 'for',
2973 cellpadding: 'cellPadding',
2974 cellspacing: 'cellSpacing'
2977 values: {
2978 checked: function(element, value) {
2979 value = !!value;
2980 element.checked = value;
2981 return value ? 'checked' : null;
2984 style: function(element, value) {
2985 element.style.cssText = value ? value : '';
2990 ATTRIBUTE_TRANSLATIONS.has = { names: {} };
2992 Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,
2993 ATTRIBUTE_TRANSLATIONS.read.names);
2995 var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +
2996 'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');
2998 for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {
2999 ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;
3000 ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()] = attr;
3003 Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {
3004 href: _getAttr2,
3005 src: _getAttr2,
3006 type: _getAttr,
3007 action: _getAttrNode,
3008 disabled: _getFlag,
3009 checked: _getFlag,
3010 readonly: _getFlag,
3011 multiple: _getFlag,
3012 onload: _getEv,
3013 onunload: _getEv,
3014 onclick: _getEv,
3015 ondblclick: _getEv,
3016 onmousedown: _getEv,
3017 onmouseup: _getEv,
3018 onmouseover: _getEv,
3019 onmousemove: _getEv,
3020 onmouseout: _getEv,
3021 onfocus: _getEv,
3022 onblur: _getEv,
3023 onkeypress: _getEv,
3024 onkeydown: _getEv,
3025 onkeyup: _getEv,
3026 onsubmit: _getEv,
3027 onreset: _getEv,
3028 onselect: _getEv,
3029 onchange: _getEv
3033 Object.extend(methods, {
3034 identify: identify,
3035 readAttribute: readAttribute,
3036 writeAttribute: writeAttribute,
3037 classNames: classNames,
3038 hasClassName: hasClassName,
3039 addClassName: addClassName,
3040 removeClassName: removeClassName,
3041 toggleClassName: toggleClassName
3045 function normalizeStyleName(style) {
3046 if (style === 'float' || style === 'styleFloat')
3047 return 'cssFloat';
3048 return style.camelize();
3051 function normalizeStyleName_IE(style) {
3052 if (style === 'float' || style === 'cssFloat')
3053 return 'styleFloat';
3054 return style.camelize();
3057 function setStyle(element, styles) {
3058 element = $(element);
3059 var elementStyle = element.style, match;
3061 if (Object.isString(styles)) {
3062 elementStyle.cssText += ';' + styles;
3063 if (styles.include('opacity')) {
3064 var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1];
3065 Element.setOpacity(element, opacity);
3067 return element;
3070 for (var property in styles) {
3071 if (property === 'opacity') {
3072 Element.setOpacity(element, styles[property]);
3073 } else {
3074 var value = styles[property];
3075 if (property === 'float' || property === 'cssFloat') {
3076 property = Object.isUndefined(elementStyle.styleFloat) ?
3077 'cssFloat' : 'styleFloat';
3079 elementStyle[property] = value;
3083 return element;
3087 function getStyle(element, style) {
3088 element = $(element);
3089 style = normalizeStyleName(style);
3091 var value = element.style[style];
3092 if (!value || value === 'auto') {
3093 var css = document.defaultView.getComputedStyle(element, null);
3094 value = css ? css[style] : null;
3097 if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3098 return value === 'auto' ? null : value;
3101 function getStyle_Opera(element, style) {
3102 switch (style) {
3103 case 'height': case 'width':
3104 if (!Element.visible(element)) return null;
3106 var dim = parseInt(getStyle(element, style), 10);
3108 if (dim !== element['offset' + style.capitalize()])
3109 return dim + 'px';
3111 return Element.measure(element, style);
3113 default: return getStyle(element, style);
3117 function getStyle_IE(element, style) {
3118 element = $(element);
3119 style = normalizeStyleName_IE(style);
3121 var value = element.style[style];
3122 if (!value && element.currentStyle) {
3123 value = element.currentStyle[style];
3126 if (style === 'opacity') {
3127 if (!STANDARD_CSS_OPACITY_SUPPORTED)
3128 return getOpacity_IE(element);
3129 else return value ? parseFloat(value) : 1.0;
3132 if (value === 'auto') {
3133 if ((style === 'width' || style === 'height') && Element.visible(element))
3134 return Element.measure(element, style) + 'px';
3135 return null;
3138 return value;
3141 function stripAlphaFromFilter_IE(filter) {
3142 return (filter || '').replace(/alpha\([^\)]*\)/gi, '');
3145 function hasLayout_IE(element) {
3146 if (!element.currentStyle || !element.currentStyle.hasLayout)
3147 element.style.zoom = 1;
3148 return element;
3151 var STANDARD_CSS_OPACITY_SUPPORTED = (function() {
3152 DIV.style.cssText = "opacity:.55";
3153 return /^0.55/.test(DIV.style.opacity);
3154 })();
3156 function setOpacity(element, value) {
3157 element = $(element);
3158 if (value == 1 || value === '') value = '';
3159 else if (value < 0.00001) value = 0;
3160 element.style.opacity = value;
3161 return element;
3164 function setOpacity_IE(element, value) {
3165 if (STANDARD_CSS_OPACITY_SUPPORTED)
3166 return setOpacity(element, value);
3168 element = hasLayout_IE($(element));
3169 var filter = Element.getStyle(element, 'filter'),
3170 style = element.style;
3172 if (value == 1 || value === '') {
3173 filter = stripAlphaFromFilter_IE(filter);
3174 if (filter) style.filter = filter;
3175 else style.removeAttribute('filter');
3176 return element;
3179 if (value < 0.00001) value = 0;
3181 style.filter = stripAlphaFromFilter_IE(filter) +
3182 ' alpha(opacity=' + (value * 100) + ')';
3184 return element;
3188 function getOpacity(element) {
3189 return Element.getStyle(element, 'opacity');
3192 function getOpacity_IE(element) {
3193 if (STANDARD_CSS_OPACITY_SUPPORTED)
3194 return getOpacity(element);
3196 var filter = Element.getStyle(element, 'filter');
3197 if (filter.length === 0) return 1.0;
3198 var match = (filter || '').match(/alpha\(opacity=(.*)\)/i);
3199 if (match && match[1]) return parseFloat(match[1]) / 100;
3200 return 1.0;
3204 Object.extend(methods, {
3205 setStyle: setStyle,
3206 getStyle: getStyle,
3207 setOpacity: setOpacity,
3208 getOpacity: getOpacity
3211 if ('styleFloat' in DIV.style) {
3212 methods.getStyle = getStyle_IE;
3213 methods.setOpacity = setOpacity_IE;
3214 methods.getOpacity = getOpacity_IE;
3217 var UID = 0;
3219 GLOBAL.Element.Storage = { UID: 1 };
3221 function getUniqueElementID(element) {
3222 if (element === window) return 0;
3224 if (typeof element._prototypeUID === 'undefined')
3225 element._prototypeUID = Element.Storage.UID++;
3226 return element._prototypeUID;
3229 function getUniqueElementID_IE(element) {
3230 if (element === window) return 0;
3231 if (element == document) return 1;
3232 return element.uniqueID;
3235 var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);
3236 if (HAS_UNIQUE_ID_PROPERTY)
3237 getUniqueElementID = getUniqueElementID_IE;
3239 function getStorage(element) {
3240 if (!(element = $(element))) return;
3242 var uid = getUniqueElementID(element);
3244 if (!Element.Storage[uid])
3245 Element.Storage[uid] = $H();
3247 return Element.Storage[uid];
3250 function store(element, key, value) {
3251 if (!(element = $(element))) return;
3252 var storage = getStorage(element);
3253 if (arguments.length === 2) {
3254 storage.update(key);
3255 } else {
3256 storage.set(key, value);
3258 return element;
3261 function retrieve(element, key, defaultValue) {
3262 if (!(element = $(element))) return;
3263 var storage = getStorage(element), value = storage.get(key);
3265 if (Object.isUndefined(value)) {
3266 storage.set(key, defaultValue);
3267 value = defaultValue;
3270 return value;
3274 Object.extend(methods, {
3275 getStorage: getStorage,
3276 store: store,
3277 retrieve: retrieve
3281 var Methods = {}, ByTag = Element.Methods.ByTag,
3282 F = Prototype.BrowserFeatures;
3284 if (!F.ElementExtensions && ('__proto__' in DIV)) {
3285 GLOBAL.HTMLElement = {};
3286 GLOBAL.HTMLElement.prototype = DIV['__proto__'];
3287 F.ElementExtensions = true;
3290 function checkElementPrototypeDeficiency(tagName) {
3291 if (typeof window.Element === 'undefined') return false;
3292 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false;
3293 var proto = window.Element.prototype;
3294 if (proto) {
3295 var id = '_' + (Math.random() + '').slice(2),
3296 el = document.createElement(tagName);
3297 proto[id] = 'x';
3298 var isBuggy = (el[id] !== 'x');
3299 delete proto[id];
3300 el = null;
3301 return isBuggy;
3304 return false;
3307 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =
3308 checkElementPrototypeDeficiency('object');
3310 function extendElementWith(element, methods) {
3311 for (var property in methods) {
3312 var value = methods[property];
3313 if (Object.isFunction(value) && !(property in element))
3314 element[property] = value.methodize();
3318 var EXTENDED = {};
3319 function elementIsExtended(element) {
3320 var uid = getUniqueElementID(element);
3321 return (uid in EXTENDED);
3324 function extend(element) {
3325 if (!element || elementIsExtended(element)) return element;
3326 if (element.nodeType !== Node.ELEMENT_NODE || element == window)
3327 return element;
3329 var methods = Object.clone(Methods),
3330 tagName = element.tagName.toUpperCase();
3332 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
3334 extendElementWith(element, methods);
3335 EXTENDED[getUniqueElementID(element)] = true;
3336 return element;
3339 function extend_IE8(element) {
3340 if (!element || elementIsExtended(element)) return element;
3342 var t = element.tagName;
3343 if (t && (/^(?:object|applet|embed)$/i.test(t))) {
3344 extendElementWith(element, Element.Methods);
3345 extendElementWith(element, Element.Methods.Simulated);
3346 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
3349 return element;
3352 if (F.SpecificElementExtensions) {
3353 extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;
3356 function addMethodsToTagName(tagName, methods) {
3357 tagName = tagName.toUpperCase();
3358 if (!ByTag[tagName]) ByTag[tagName] = {};
3359 Object.extend(ByTag[tagName], methods);
3362 function mergeMethods(destination, methods, onlyIfAbsent) {
3363 if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;
3364 for (var property in methods) {
3365 var value = methods[property];
3366 if (!Object.isFunction(value)) continue;
3367 if (!onlyIfAbsent || !(property in destination))
3368 destination[property] = value.methodize();
3372 function findDOMClass(tagName) {
3373 var klass;
3374 var trans = {
3375 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
3376 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
3377 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
3378 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
3379 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
3380 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
3381 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
3382 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
3383 "FrameSet", "IFRAME": "IFrame"
3385 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
3386 if (window[klass]) return window[klass];
3387 klass = 'HTML' + tagName + 'Element';
3388 if (window[klass]) return window[klass];
3389 klass = 'HTML' + tagName.capitalize() + 'Element';
3390 if (window[klass]) return window[klass];
3392 var element = document.createElement(tagName),
3393 proto = element['__proto__'] || element.constructor.prototype;
3395 element = null;
3396 return proto;
3399 function addMethods(methods) {
3400 if (arguments.length === 0) addFormMethods();
3402 if (arguments.length === 2) {
3403 var tagName = methods;
3404 methods = arguments[1];
3407 if (!tagName) {
3408 Object.extend(Element.Methods, methods || {});
3409 } else {
3410 if (Object.isArray(tagName)) {
3411 for (var i = 0, tag; tag = tagName[i]; i++)
3412 addMethodsToTagName(tag, methods);
3413 } else {
3414 addMethodsToTagName(tagName, methods);
3418 var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
3419 Element.prototype;
3421 if (F.ElementExtensions) {
3422 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
3423 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
3426 if (F.SpecificElementExtensions) {
3427 for (var tag in Element.Methods.ByTag) {
3428 var klass = findDOMClass(tag);
3429 if (Object.isUndefined(klass)) continue;
3430 mergeMethods(klass.prototype, ByTag[tag]);
3434 Object.extend(Element, Element.Methods);
3435 Object.extend(Element, Element.Methods.Simulated);
3436 delete Element.ByTag;
3437 delete Element.Simulated;
3439 Element.extend.refresh();
3441 ELEMENT_CACHE = {};
3444 Object.extend(GLOBAL.Element, {
3445 extend: extend,
3446 addMethods: addMethods
3449 if (extend === Prototype.K) {
3450 GLOBAL.Element.extend.refresh = Prototype.emptyFunction;
3451 } else {
3452 GLOBAL.Element.extend.refresh = function() {
3453 if (Prototype.BrowserFeatures.ElementExtensions) return;
3454 Object.extend(Methods, Element.Methods);
3455 Object.extend(Methods, Element.Methods.Simulated);
3457 EXTENDED = {};
3461 function addFormMethods() {
3462 Object.extend(Form, Form.Methods);
3463 Object.extend(Form.Element, Form.Element.Methods);
3464 Object.extend(Element.Methods.ByTag, {
3465 "FORM": Object.clone(Form.Methods),
3466 "INPUT": Object.clone(Form.Element.Methods),
3467 "SELECT": Object.clone(Form.Element.Methods),
3468 "TEXTAREA": Object.clone(Form.Element.Methods),
3469 "BUTTON": Object.clone(Form.Element.Methods)
3473 Element.addMethods(methods);
3475 function destroyCache_IE() {
3476 DIV = null;
3477 ELEMENT_CACHE = null;
3480 if (window.attachEvent)
3481 window.attachEvent('onunload', destroyCache_IE);
3483 })(this);
3484 (function() {
3486 function toDecimal(pctString) {
3487 var match = pctString.match(/^(\d+)%?$/i);
3488 if (!match) return null;
3489 return (Number(match[1]) / 100);
3492 function getRawStyle(element, style) {
3493 element = $(element);
3495 var value = element.style[style];
3496 if (!value || value === 'auto') {
3497 var css = document.defaultView.getComputedStyle(element, null);
3498 value = css ? css[style] : null;
3501 if (style === 'opacity') return value ? parseFloat(value) : 1.0;
3502 return value === 'auto' ? null : value;
3505 function getRawStyle_IE(element, style) {
3506 var value = element.style[style];
3507 if (!value && element.currentStyle) {
3508 value = element.currentStyle[style];
3510 return value;
3513 function getContentWidth(element, context) {
3514 var boxWidth = element.offsetWidth;
3516 var bl = getPixelValue(element, 'borderLeftWidth', context) || 0;
3517 var br = getPixelValue(element, 'borderRightWidth', context) || 0;
3518 var pl = getPixelValue(element, 'paddingLeft', context) || 0;
3519 var pr = getPixelValue(element, 'paddingRight', context) || 0;
3521 return boxWidth - bl - br - pl - pr;
3524 if (!Object.isUndefined(document.documentElement.currentStyle) && !Prototype.Browser.Opera) {
3525 getRawStyle = getRawStyle_IE;
3529 function getPixelValue(value, property, context) {
3530 var element = null;
3531 if (Object.isElement(value)) {
3532 element = value;
3533 value = getRawStyle(element, property);
3536 if (value === null || Object.isUndefined(value)) {
3537 return null;
3540 if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
3541 return window.parseFloat(value);
3544 var isPercentage = value.include('%'), isViewport = (context === document.viewport);
3546 if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
3547 var style = element.style.left, rStyle = element.runtimeStyle.left;
3548 element.runtimeStyle.left = element.currentStyle.left;
3549 element.style.left = value || 0;
3550 value = element.style.pixelLeft;
3551 element.style.left = style;
3552 element.runtimeStyle.left = rStyle;
3554 return value;
3557 if (element && isPercentage) {
3558 context = context || element.parentNode;
3559 var decimal = toDecimal(value), whole = null;
3561 var isHorizontal = property.include('left') || property.include('right') ||
3562 property.include('width');
3564 var isVertical = property.include('top') || property.include('bottom') ||
3565 property.include('height');
3567 if (context === document.viewport) {
3568 if (isHorizontal) {
3569 whole = document.viewport.getWidth();
3570 } else if (isVertical) {
3571 whole = document.viewport.getHeight();
3573 } else {
3574 if (isHorizontal) {
3575 whole = $(context).measure('width');
3576 } else if (isVertical) {
3577 whole = $(context).measure('height');
3581 return (whole === null) ? 0 : whole * decimal;
3584 return 0;
3587 function toCSSPixels(number) {
3588 if (Object.isString(number) && number.endsWith('px'))
3589 return number;
3590 return number + 'px';
3593 function isDisplayed(element) {
3594 while (element && element.parentNode) {
3595 var display = element.getStyle('display');
3596 if (display === 'none') {
3597 return false;
3599 element = $(element.parentNode);
3601 return true;
3604 var hasLayout = Prototype.K;
3605 if ('currentStyle' in document.documentElement) {
3606 hasLayout = function(element) {
3607 if (!element.currentStyle.hasLayout) {
3608 element.style.zoom = 1;
3610 return element;
3614 function cssNameFor(key) {
3615 if (key.include('border')) key = key + '-width';
3616 return key.camelize();
3619 Element.Layout = Class.create(Hash, {
3620 initialize: function($super, element, preCompute) {
3621 $super();
3622 this.element = $(element);
3624 Element.Layout.PROPERTIES.each( function(property) {
3625 this._set(property, null);
3626 }, this);
3628 if (preCompute) {
3629 this._preComputing = true;
3630 this._begin();
3631 Element.Layout.PROPERTIES.each( this._compute, this );
3632 this._end();
3633 this._preComputing = false;
3637 _set: function(property, value) {
3638 return Hash.prototype.set.call(this, property, value);
3641 set: function(property, value) {
3642 throw "Properties of Element.Layout are read-only.";
3645 get: function($super, property) {
3646 var value = $super(property);
3647 return value === null ? this._compute(property) : value;
3650 _begin: function() {
3651 if (this._isPrepared()) return;
3653 var element = this.element;
3654 if (isDisplayed(element)) {
3655 this._setPrepared(true);
3656 return;
3660 var originalStyles = {
3661 position: element.style.position || '',
3662 width: element.style.width || '',
3663 visibility: element.style.visibility || '',
3664 display: element.style.display || ''
3667 element.store('prototype_original_styles', originalStyles);
3669 var position = getRawStyle(element, 'position'), width = element.offsetWidth;
3671 if (width === 0 || width === null) {
3672 element.style.display = 'block';
3673 width = element.offsetWidth;
3676 var context = (position === 'fixed') ? document.viewport :
3677 element.parentNode;
3679 var tempStyles = {
3680 visibility: 'hidden',
3681 display: 'block'
3684 if (position !== 'fixed') tempStyles.position = 'absolute';
3686 element.setStyle(tempStyles);
3688 var positionedWidth = element.offsetWidth, newWidth;
3689 if (width && (positionedWidth === width)) {
3690 newWidth = getContentWidth(element, context);
3691 } else if (position === 'absolute' || position === 'fixed') {
3692 newWidth = getContentWidth(element, context);
3693 } else {
3694 var parent = element.parentNode, pLayout = $(parent).getLayout();
3696 newWidth = pLayout.get('width') -
3697 this.get('margin-left') -
3698 this.get('border-left') -
3699 this.get('padding-left') -
3700 this.get('padding-right') -
3701 this.get('border-right') -
3702 this.get('margin-right');
3705 element.setStyle({ width: newWidth + 'px' });
3707 this._setPrepared(true);
3710 _end: function() {
3711 var element = this.element;
3712 var originalStyles = element.retrieve('prototype_original_styles');
3713 element.store('prototype_original_styles', null);
3714 element.setStyle(originalStyles);
3715 this._setPrepared(false);
3718 _compute: function(property) {
3719 var COMPUTATIONS = Element.Layout.COMPUTATIONS;
3720 if (!(property in COMPUTATIONS)) {
3721 throw "Property not found.";
3724 return this._set(property, COMPUTATIONS[property].call(this, this.element));
3727 _isPrepared: function() {
3728 return this.element.retrieve('prototype_element_layout_prepared', false);
3731 _setPrepared: function(bool) {
3732 return this.element.store('prototype_element_layout_prepared', bool);
3735 toObject: function() {
3736 var args = $A(arguments);
3737 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3738 args.join(' ').split(' ');
3739 var obj = {};
3740 keys.each( function(key) {
3741 if (!Element.Layout.PROPERTIES.include(key)) return;
3742 var value = this.get(key);
3743 if (value != null) obj[key] = value;
3744 }, this);
3745 return obj;
3748 toHash: function() {
3749 var obj = this.toObject.apply(this, arguments);
3750 return new Hash(obj);
3753 toCSS: function() {
3754 var args = $A(arguments);
3755 var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
3756 args.join(' ').split(' ');
3757 var css = {};
3759 keys.each( function(key) {
3760 if (!Element.Layout.PROPERTIES.include(key)) return;
3761 if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
3763 var value = this.get(key);
3764 if (value != null) css[cssNameFor(key)] = value + 'px';
3765 }, this);
3766 return css;
3769 inspect: function() {
3770 return "#<Element.Layout>";
3774 Object.extend(Element.Layout, {
3775 PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
3777 COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
3779 COMPUTATIONS: {
3780 'height': function(element) {
3781 if (!this._preComputing) this._begin();
3783 var bHeight = this.get('border-box-height');
3784 if (bHeight <= 0) {
3785 if (!this._preComputing) this._end();
3786 return 0;
3789 var bTop = this.get('border-top'),
3790 bBottom = this.get('border-bottom');
3792 var pTop = this.get('padding-top'),
3793 pBottom = this.get('padding-bottom');
3795 if (!this._preComputing) this._end();
3797 return bHeight - bTop - bBottom - pTop - pBottom;
3800 'width': function(element) {
3801 if (!this._preComputing) this._begin();
3803 var bWidth = this.get('border-box-width');
3804 if (bWidth <= 0) {
3805 if (!this._preComputing) this._end();
3806 return 0;
3809 var bLeft = this.get('border-left'),
3810 bRight = this.get('border-right');
3812 var pLeft = this.get('padding-left'),
3813 pRight = this.get('padding-right');
3815 if (!this._preComputing) this._end();
3816 return bWidth - bLeft - bRight - pLeft - pRight;
3819 'padding-box-height': function(element) {
3820 var height = this.get('height'),
3821 pTop = this.get('padding-top'),
3822 pBottom = this.get('padding-bottom');
3824 return height + pTop + pBottom;
3827 'padding-box-width': function(element) {
3828 var width = this.get('width'),
3829 pLeft = this.get('padding-left'),
3830 pRight = this.get('padding-right');
3832 return width + pLeft + pRight;
3835 'border-box-height': function(element) {
3836 if (!this._preComputing) this._begin();
3837 var height = element.offsetHeight;
3838 if (!this._preComputing) this._end();
3839 return height;
3842 'border-box-width': function(element) {
3843 if (!this._preComputing) this._begin();
3844 var width = element.offsetWidth;
3845 if (!this._preComputing) this._end();
3846 return width;
3849 'margin-box-height': function(element) {
3850 var bHeight = this.get('border-box-height'),
3851 mTop = this.get('margin-top'),
3852 mBottom = this.get('margin-bottom');
3854 if (bHeight <= 0) return 0;
3856 return bHeight + mTop + mBottom;
3859 'margin-box-width': function(element) {
3860 var bWidth = this.get('border-box-width'),
3861 mLeft = this.get('margin-left'),
3862 mRight = this.get('margin-right');
3864 if (bWidth <= 0) return 0;
3866 return bWidth + mLeft + mRight;
3869 'top': function(element) {
3870 var offset = element.positionedOffset();
3871 return offset.top;
3874 'bottom': function(element) {
3875 var offset = element.positionedOffset(),
3876 parent = element.getOffsetParent(),
3877 pHeight = parent.measure('height');
3879 var mHeight = this.get('border-box-height');
3881 return pHeight - mHeight - offset.top;
3884 'left': function(element) {
3885 var offset = element.positionedOffset();
3886 return offset.left;
3889 'right': function(element) {
3890 var offset = element.positionedOffset(),
3891 parent = element.getOffsetParent(),
3892 pWidth = parent.measure('width');
3894 var mWidth = this.get('border-box-width');
3896 return pWidth - mWidth - offset.left;
3899 'padding-top': function(element) {
3900 return getPixelValue(element, 'paddingTop');
3903 'padding-bottom': function(element) {
3904 return getPixelValue(element, 'paddingBottom');
3907 'padding-left': function(element) {
3908 return getPixelValue(element, 'paddingLeft');
3911 'padding-right': function(element) {
3912 return getPixelValue(element, 'paddingRight');
3915 'border-top': function(element) {
3916 return getPixelValue(element, 'borderTopWidth');
3919 'border-bottom': function(element) {
3920 return getPixelValue(element, 'borderBottomWidth');
3923 'border-left': function(element) {
3924 return getPixelValue(element, 'borderLeftWidth');
3927 'border-right': function(element) {
3928 return getPixelValue(element, 'borderRightWidth');
3931 'margin-top': function(element) {
3932 return getPixelValue(element, 'marginTop');
3935 'margin-bottom': function(element) {
3936 return getPixelValue(element, 'marginBottom');
3939 'margin-left': function(element) {
3940 return getPixelValue(element, 'marginLeft');
3943 'margin-right': function(element) {
3944 return getPixelValue(element, 'marginRight');
3949 if ('getBoundingClientRect' in document.documentElement) {
3950 Object.extend(Element.Layout.COMPUTATIONS, {
3951 'right': function(element) {
3952 var parent = hasLayout(element.getOffsetParent());
3953 var rect = element.getBoundingClientRect(),
3954 pRect = parent.getBoundingClientRect();
3956 return (pRect.right - rect.right).round();
3959 'bottom': function(element) {
3960 var parent = hasLayout(element.getOffsetParent());
3961 var rect = element.getBoundingClientRect(),
3962 pRect = parent.getBoundingClientRect();
3964 return (pRect.bottom - rect.bottom).round();
3969 Element.Offset = Class.create({
3970 initialize: function(left, top) {
3971 this.left = left.round();
3972 this.top = top.round();
3974 this[0] = this.left;
3975 this[1] = this.top;
3978 relativeTo: function(offset) {
3979 return new Element.Offset(
3980 this.left - offset.left,
3981 this.top - offset.top
3985 inspect: function() {
3986 return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
3989 toString: function() {
3990 return "[#{left}, #{top}]".interpolate(this);
3993 toArray: function() {
3994 return [this.left, this.top];
3998 function getLayout(element, preCompute) {
3999 return new Element.Layout(element, preCompute);
4002 function measure(element, property) {
4003 return $(element).getLayout().get(property);
4006 function getHeight(element) {
4007 return Element.getDimensions(element).height;
4010 function getWidth(element) {
4011 return Element.getDimensions(element).width;
4014 function getDimensions(element) {
4015 element = $(element);
4016 var display = Element.getStyle(element, 'display');
4018 if (display && display !== 'none') {
4019 return { width: element.offsetWidth, height: element.offsetHeight };
4022 var style = element.style;
4023 var originalStyles = {
4024 visibility: style.visibility,
4025 position: style.position,
4026 display: style.display
4029 var newStyles = {
4030 visibility: 'hidden',
4031 display: 'block'
4034 if (originalStyles.position !== 'fixed')
4035 newStyles.position = 'absolute';
4037 Element.setStyle(element, newStyles);
4039 var dimensions = {
4040 width: element.offsetWidth,
4041 height: element.offsetHeight
4044 Element.setStyle(element, originalStyles);
4046 return dimensions;
4049 function getOffsetParent(element) {
4050 element = $(element);
4052 function selfOrBody(element) {
4053 return isHtml(element) ? $(document.body) : $(element);
4056 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4057 return $(document.body);
4059 var isInline = (Element.getStyle(element, 'display') === 'inline');
4060 if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent);
4062 while ((element = element.parentNode) && element !== document.body) {
4063 if (Element.getStyle(element, 'position') !== 'static') {
4064 return selfOrBody(element);
4068 return $(document.body);
4072 function cumulativeOffset(element) {
4073 element = $(element);
4074 var valueT = 0, valueL = 0;
4075 if (element.parentNode) {
4076 do {
4077 valueT += element.offsetTop || 0;
4078 valueL += element.offsetLeft || 0;
4079 element = element.offsetParent;
4080 } while (element);
4082 return new Element.Offset(valueL, valueT);
4085 function positionedOffset(element) {
4086 element = $(element);
4088 var layout = element.getLayout();
4090 var valueT = 0, valueL = 0;
4091 do {
4092 valueT += element.offsetTop || 0;
4093 valueL += element.offsetLeft || 0;
4094 element = element.offsetParent;
4095 if (element) {
4096 if (isBody(element)) break;
4097 var p = Element.getStyle(element, 'position');
4098 if (p !== 'static') break;
4100 } while (element);
4102 valueL -= layout.get('margin-left');
4103 valueT -= layout.get('margin-top');
4105 return new Element.Offset(valueL, valueT);
4108 function cumulativeScrollOffset(element) {
4109 var valueT = 0, valueL = 0;
4110 do {
4111 if (element === document.body) {
4112 var bodyScrollNode = document.documentElement || document.body.parentNode || document.body;
4113 valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0;
4114 valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0;
4115 break;
4116 } else {
4117 valueT += element.scrollTop || 0;
4118 valueL += element.scrollLeft || 0;
4119 element = element.parentNode;
4121 } while (element);
4122 return new Element.Offset(valueL, valueT);
4125 function viewportOffset(forElement) {
4126 var valueT = 0, valueL = 0, docBody = document.body;
4128 forElement = $(forElement);
4129 var element = forElement;
4130 do {
4131 valueT += element.offsetTop || 0;
4132 valueL += element.offsetLeft || 0;
4133 if (element.offsetParent == docBody &&
4134 Element.getStyle(element, 'position') == 'absolute') break;
4135 } while (element = element.offsetParent);
4137 element = forElement;
4138 do {
4139 if (element != docBody) {
4140 valueT -= element.scrollTop || 0;
4141 valueL -= element.scrollLeft || 0;
4143 } while (element = element.parentNode);
4144 return new Element.Offset(valueL, valueT);
4147 function absolutize(element) {
4148 element = $(element);
4150 if (Element.getStyle(element, 'position') === 'absolute') {
4151 return element;
4154 var offsetParent = getOffsetParent(element);
4155 var eOffset = element.viewportOffset(),
4156 pOffset = offsetParent.viewportOffset();
4158 var offset = eOffset.relativeTo(pOffset);
4159 var layout = element.getLayout();
4161 element.store('prototype_absolutize_original_styles', {
4162 position: element.getStyle('position'),
4163 left: element.getStyle('left'),
4164 top: element.getStyle('top'),
4165 width: element.getStyle('width'),
4166 height: element.getStyle('height')
4169 element.setStyle({
4170 position: 'absolute',
4171 top: offset.top + 'px',
4172 left: offset.left + 'px',
4173 width: layout.get('width') + 'px',
4174 height: layout.get('height') + 'px'
4177 return element;
4180 function relativize(element) {
4181 element = $(element);
4182 if (Element.getStyle(element, 'position') === 'relative') {
4183 return element;
4186 var originalStyles =
4187 element.retrieve('prototype_absolutize_original_styles');
4189 if (originalStyles) element.setStyle(originalStyles);
4190 return element;
4194 function scrollTo(element) {
4195 element = $(element);
4196 var pos = Element.cumulativeOffset(element);
4197 window.scrollTo(pos.left, pos.top);
4198 return element;
4202 function makePositioned(element) {
4203 element = $(element);
4204 var position = Element.getStyle(element, 'position'), styles = {};
4205 if (position === 'static' || !position) {
4206 styles.position = 'relative';
4207 if (Prototype.Browser.Opera) {
4208 styles.top = 0;
4209 styles.left = 0;
4211 Element.setStyle(element, styles);
4212 Element.store(element, 'prototype_made_positioned', true);
4214 return element;
4217 function undoPositioned(element) {
4218 element = $(element);
4219 var storage = Element.getStorage(element),
4220 madePositioned = storage.get('prototype_made_positioned');
4222 if (madePositioned) {
4223 storage.unset('prototype_made_positioned');
4224 Element.setStyle(element, {
4225 position: '',
4226 top: '',
4227 bottom: '',
4228 left: '',
4229 right: ''
4232 return element;
4235 function makeClipping(element) {
4236 element = $(element);
4238 var storage = Element.getStorage(element),
4239 madeClipping = storage.get('prototype_made_clipping');
4241 if (Object.isUndefined(madeClipping)) {
4242 var overflow = Element.getStyle(element, 'overflow');
4243 storage.set('prototype_made_clipping', overflow);
4244 if (overflow !== 'hidden')
4245 element.style.overflow = 'hidden';
4248 return element;
4251 function undoClipping(element) {
4252 element = $(element);
4253 var storage = Element.getStorage(element),
4254 overflow = storage.get('prototype_made_clipping');
4256 if (!Object.isUndefined(overflow)) {
4257 storage.unset('prototype_made_clipping');
4258 element.style.overflow = overflow || '';
4261 return element;
4264 function clonePosition(element, source, options) {
4265 options = Object.extend({
4266 setLeft: true,
4267 setTop: true,
4268 setWidth: true,
4269 setHeight: true,
4270 offsetTop: 0,
4271 offsetLeft: 0
4272 }, options || {});
4274 var docEl = document.documentElement;
4276 source = $(source);
4277 element = $(element);
4278 var p, delta, layout, styles = {};
4280 if (options.setLeft || options.setTop) {
4281 p = Element.viewportOffset(source);
4282 delta = [0, 0];
4283 if (Element.getStyle(element, 'position') === 'absolute') {
4284 var parent = Element.getOffsetParent(element);
4285 if (parent !== document.body) delta = Element.viewportOffset(parent);
4289 function pageScrollXY() {
4290 var x = 0, y = 0;
4291 if (Object.isNumber(window.pageXOffset)) {
4292 x = window.pageXOffset;
4293 y = window.pageYOffset;
4294 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
4295 x = document.body.scrollLeft;
4296 y = document.body.scrollTop;
4297 } else if (docEl && (docEl.scrollLeft || docEl.scrollTop)) {
4298 x = docEl.scrollLeft;
4299 y = docEl.scrollTop;
4301 return { x: x, y: y };
4304 var pageXY = pageScrollXY();
4307 if (options.setWidth || options.setHeight) {
4308 layout = Element.getLayout(source);
4311 if (options.setLeft)
4312 styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px';
4313 if (options.setTop)
4314 styles.top = (p[1] + pageXY.y - delta[1] + options.offsetTop) + 'px';
4316 var currentLayout = element.getLayout();
4318 if (options.setWidth) {
4319 styles.width = layout.get('width') + 'px';
4321 if (options.setHeight) {
4322 styles.height = layout.get('height') + 'px';
4325 return Element.setStyle(element, styles);
4329 if (Prototype.Browser.IE) {
4330 getOffsetParent = getOffsetParent.wrap(
4331 function(proceed, element) {
4332 element = $(element);
4334 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
4335 return $(document.body);
4337 var position = element.getStyle('position');
4338 if (position !== 'static') return proceed(element);
4340 element.setStyle({ position: 'relative' });
4341 var value = proceed(element);
4342 element.setStyle({ position: position });
4343 return value;
4347 positionedOffset = positionedOffset.wrap(function(proceed, element) {
4348 element = $(element);
4349 if (!element.parentNode) return new Element.Offset(0, 0);
4350 var position = element.getStyle('position');
4351 if (position !== 'static') return proceed(element);
4353 var offsetParent = element.getOffsetParent();
4354 if (offsetParent && offsetParent.getStyle('position') === 'fixed')
4355 hasLayout(offsetParent);
4357 element.setStyle({ position: 'relative' });
4358 var value = proceed(element);
4359 element.setStyle({ position: position });
4360 return value;
4362 } else if (Prototype.Browser.Webkit) {
4363 cumulativeOffset = function(element) {
4364 element = $(element);
4365 var valueT = 0, valueL = 0;
4366 do {
4367 valueT += element.offsetTop || 0;
4368 valueL += element.offsetLeft || 0;
4369 if (element.offsetParent == document.body) {
4370 if (Element.getStyle(element, 'position') == 'absolute') break;
4373 element = element.offsetParent;
4374 } while (element);
4376 return new Element.Offset(valueL, valueT);
4381 Element.addMethods({
4382 getLayout: getLayout,
4383 measure: measure,
4384 getWidth: getWidth,
4385 getHeight: getHeight,
4386 getDimensions: getDimensions,
4387 getOffsetParent: getOffsetParent,
4388 cumulativeOffset: cumulativeOffset,
4389 positionedOffset: positionedOffset,
4390 cumulativeScrollOffset: cumulativeScrollOffset,
4391 viewportOffset: viewportOffset,
4392 absolutize: absolutize,
4393 relativize: relativize,
4394 scrollTo: scrollTo,
4395 makePositioned: makePositioned,
4396 undoPositioned: undoPositioned,
4397 makeClipping: makeClipping,
4398 undoClipping: undoClipping,
4399 clonePosition: clonePosition
4402 function isBody(element) {
4403 return element.nodeName.toUpperCase() === 'BODY';
4406 function isHtml(element) {
4407 return element.nodeName.toUpperCase() === 'HTML';
4410 function isDocument(element) {
4411 return element.nodeType === Node.DOCUMENT_NODE;
4414 function isDetached(element) {
4415 return element !== document.body &&
4416 !Element.descendantOf(element, document.body);
4419 if ('getBoundingClientRect' in document.documentElement) {
4420 Element.addMethods({
4421 viewportOffset: function(element) {
4422 element = $(element);
4423 if (isDetached(element)) return new Element.Offset(0, 0);
4425 var rect = element.getBoundingClientRect(),
4426 docEl = document.documentElement;
4427 return new Element.Offset(rect.left - docEl.clientLeft,
4428 rect.top - docEl.clientTop);
4434 })();
4436 (function() {
4438 var IS_OLD_OPERA = Prototype.Browser.Opera &&
4439 (window.parseFloat(window.opera.version()) < 9.5);
4440 var ROOT = null;
4441 function getRootElement() {
4442 if (ROOT) return ROOT;
4443 ROOT = IS_OLD_OPERA ? document.body : document.documentElement;
4444 return ROOT;
4447 function getDimensions() {
4448 return { width: this.getWidth(), height: this.getHeight() };
4451 function getWidth() {
4452 return getRootElement().clientWidth;
4455 function getHeight() {
4456 return getRootElement().clientHeight;
4459 function getScrollOffsets() {
4460 var x = window.pageXOffset || document.documentElement.scrollLeft ||
4461 document.body.scrollLeft;
4462 var y = window.pageYOffset || document.documentElement.scrollTop ||
4463 document.body.scrollTop;
4465 return new Element.Offset(x, y);
4468 document.viewport = {
4469 getDimensions: getDimensions,
4470 getWidth: getWidth,
4471 getHeight: getHeight,
4472 getScrollOffsets: getScrollOffsets
4475 })();
4476 window.$$ = function() {
4477 var expression = $A(arguments).join(', ');
4478 return Prototype.Selector.select(expression, document);
4481 Prototype.Selector = (function() {
4483 function select() {
4484 throw new Error('Method "Prototype.Selector.select" must be defined.');
4487 function match() {
4488 throw new Error('Method "Prototype.Selector.match" must be defined.');
4491 function find(elements, expression, index) {
4492 index = index || 0;
4493 var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
4495 for (i = 0; i < length; i++) {
4496 if (match(elements[i], expression) && index == matchIndex++) {
4497 return Element.extend(elements[i]);
4502 function extendElements(elements) {
4503 for (var i = 0, length = elements.length; i < length; i++) {
4504 Element.extend(elements[i]);
4506 return elements;
4510 var K = Prototype.K;
4512 return {
4513 select: select,
4514 match: match,
4515 find: find,
4516 extendElements: (Element.extend === K) ? K : extendElements,
4517 extendElement: Element.extend
4519 })();
4520 Prototype._original_property = window.Sizzle;
4522 ;(function () {
4523 function fakeDefine(fn) {
4524 Prototype._actual_sizzle = fn();
4526 fakeDefine.amd = true;
4528 if (typeof define !== 'undefined' && define.amd) {
4529 Prototype._original_define = define;
4530 Prototype._actual_sizzle = null;
4531 window.define = fakeDefine;
4533 })();
4536 * Sizzle CSS Selector Engine v1.10.18
4537 * http://sizzlejs.com/
4539 * Copyright 2013 jQuery Foundation, Inc. and other contributors
4540 * Released under the MIT license
4541 * http://jquery.org/license
4543 * Date: 2014-02-05
4545 (function( window ) {
4547 var i,
4548 support,
4549 Expr,
4550 getText,
4551 isXML,
4552 compile,
4553 select,
4554 outermostContext,
4555 sortInput,
4556 hasDuplicate,
4558 setDocument,
4559 document,
4560 docElem,
4561 documentIsHTML,
4562 rbuggyQSA,
4563 rbuggyMatches,
4564 matches,
4565 contains,
4567 expando = "sizzle" + -(new Date()),
4568 preferredDoc = window.document,
4569 dirruns = 0,
4570 done = 0,
4571 classCache = createCache(),
4572 tokenCache = createCache(),
4573 compilerCache = createCache(),
4574 sortOrder = function( a, b ) {
4575 if ( a === b ) {
4576 hasDuplicate = true;
4578 return 0;
4581 strundefined = typeof undefined,
4582 MAX_NEGATIVE = 1 << 31,
4584 hasOwn = ({}).hasOwnProperty,
4585 arr = [],
4586 pop = arr.pop,
4587 push_native = arr.push,
4588 push = arr.push,
4589 slice = arr.slice,
4590 indexOf = arr.indexOf || function( elem ) {
4591 var i = 0,
4592 len = this.length;
4593 for ( ; i < len; i++ ) {
4594 if ( this[i] === elem ) {
4595 return i;
4598 return -1;
4601 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
4604 whitespace = "[\\x20\\t\\r\\n\\f]",
4605 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
4607 identifier = characterEncoding.replace( "w", "w#" ),
4609 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
4610 "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
4612 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
4614 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
4616 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
4617 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
4619 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
4621 rpseudo = new RegExp( pseudos ),
4622 ridentifier = new RegExp( "^" + identifier + "$" ),
4624 matchExpr = {
4625 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
4626 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
4627 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
4628 "ATTR": new RegExp( "^" + attributes ),
4629 "PSEUDO": new RegExp( "^" + pseudos ),
4630 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
4631 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
4632 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
4633 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
4634 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
4635 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
4638 rinputs = /^(?:input|select|textarea|button)$/i,
4639 rheader = /^h\d$/i,
4641 rnative = /^[^{]+\{\s*\[native \w/,
4643 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
4645 rsibling = /[+~]/,
4646 rescape = /'|\\/g,
4648 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
4649 funescape = function( _, escaped, escapedWhitespace ) {
4650 var high = "0x" + escaped - 0x10000;
4651 return high !== high || escapedWhitespace ?
4652 escaped :
4653 high < 0 ?
4654 String.fromCharCode( high + 0x10000 ) :
4655 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
4658 try {
4659 push.apply(
4660 (arr = slice.call( preferredDoc.childNodes )),
4661 preferredDoc.childNodes
4663 arr[ preferredDoc.childNodes.length ].nodeType;
4664 } catch ( e ) {
4665 push = { apply: arr.length ?
4667 function( target, els ) {
4668 push_native.apply( target, slice.call(els) );
4671 function( target, els ) {
4672 var j = target.length,
4673 i = 0;
4674 while ( (target[j++] = els[i++]) ) {}
4675 target.length = j - 1;
4680 function Sizzle( selector, context, results, seed ) {
4681 var match, elem, m, nodeType,
4682 i, groups, old, nid, newContext, newSelector;
4684 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
4685 setDocument( context );
4688 context = context || document;
4689 results = results || [];
4691 if ( !selector || typeof selector !== "string" ) {
4692 return results;
4695 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
4696 return [];
4699 if ( documentIsHTML && !seed ) {
4701 if ( (match = rquickExpr.exec( selector )) ) {
4702 if ( (m = match[1]) ) {
4703 if ( nodeType === 9 ) {
4704 elem = context.getElementById( m );
4705 if ( elem && elem.parentNode ) {
4706 if ( elem.id === m ) {
4707 results.push( elem );
4708 return results;
4710 } else {
4711 return results;
4713 } else {
4714 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
4715 contains( context, elem ) && elem.id === m ) {
4716 results.push( elem );
4717 return results;
4721 } else if ( match[2] ) {
4722 push.apply( results, context.getElementsByTagName( selector ) );
4723 return results;
4725 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
4726 push.apply( results, context.getElementsByClassName( m ) );
4727 return results;
4731 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
4732 nid = old = expando;
4733 newContext = context;
4734 newSelector = nodeType === 9 && selector;
4736 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4737 groups = tokenize( selector );
4739 if ( (old = context.getAttribute("id")) ) {
4740 nid = old.replace( rescape, "\\$&" );
4741 } else {
4742 context.setAttribute( "id", nid );
4744 nid = "[id='" + nid + "'] ";
4746 i = groups.length;
4747 while ( i-- ) {
4748 groups[i] = nid + toSelector( groups[i] );
4750 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
4751 newSelector = groups.join(",");
4754 if ( newSelector ) {
4755 try {
4756 push.apply( results,
4757 newContext.querySelectorAll( newSelector )
4759 return results;
4760 } catch(qsaError) {
4761 } finally {
4762 if ( !old ) {
4763 context.removeAttribute("id");
4770 return select( selector.replace( rtrim, "$1" ), context, results, seed );
4774 * Create key-value caches of limited size
4775 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
4776 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
4777 * deleting the oldest entry
4779 function createCache() {
4780 var keys = [];
4782 function cache( key, value ) {
4783 if ( keys.push( key + " " ) > Expr.cacheLength ) {
4784 delete cache[ keys.shift() ];
4786 return (cache[ key + " " ] = value);
4788 return cache;
4792 * Mark a function for special use by Sizzle
4793 * @param {Function} fn The function to mark
4795 function markFunction( fn ) {
4796 fn[ expando ] = true;
4797 return fn;
4801 * Support testing using an element
4802 * @param {Function} fn Passed the created div and expects a boolean result
4804 function assert( fn ) {
4805 var div = document.createElement("div");
4807 try {
4808 return !!fn( div );
4809 } catch (e) {
4810 return false;
4811 } finally {
4812 if ( div.parentNode ) {
4813 div.parentNode.removeChild( div );
4815 div = null;
4820 * Adds the same handler for all of the specified attrs
4821 * @param {String} attrs Pipe-separated list of attributes
4822 * @param {Function} handler The method that will be applied
4824 function addHandle( attrs, handler ) {
4825 var arr = attrs.split("|"),
4826 i = attrs.length;
4828 while ( i-- ) {
4829 Expr.attrHandle[ arr[i] ] = handler;
4834 * Checks document order of two siblings
4835 * @param {Element} a
4836 * @param {Element} b
4837 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
4839 function siblingCheck( a, b ) {
4840 var cur = b && a,
4841 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
4842 ( ~b.sourceIndex || MAX_NEGATIVE ) -
4843 ( ~a.sourceIndex || MAX_NEGATIVE );
4845 if ( diff ) {
4846 return diff;
4849 if ( cur ) {
4850 while ( (cur = cur.nextSibling) ) {
4851 if ( cur === b ) {
4852 return -1;
4857 return a ? 1 : -1;
4861 * Returns a function to use in pseudos for input types
4862 * @param {String} type
4864 function createInputPseudo( type ) {
4865 return function( elem ) {
4866 var name = elem.nodeName.toLowerCase();
4867 return name === "input" && elem.type === type;
4872 * Returns a function to use in pseudos for buttons
4873 * @param {String} type
4875 function createButtonPseudo( type ) {
4876 return function( elem ) {
4877 var name = elem.nodeName.toLowerCase();
4878 return (name === "input" || name === "button") && elem.type === type;
4883 * Returns a function to use in pseudos for positionals
4884 * @param {Function} fn
4886 function createPositionalPseudo( fn ) {
4887 return markFunction(function( argument ) {
4888 argument = +argument;
4889 return markFunction(function( seed, matches ) {
4890 var j,
4891 matchIndexes = fn( [], seed.length, argument ),
4892 i = matchIndexes.length;
4894 while ( i-- ) {
4895 if ( seed[ (j = matchIndexes[i]) ] ) {
4896 seed[j] = !(matches[j] = seed[j]);
4904 * Checks a node for validity as a Sizzle context
4905 * @param {Element|Object=} context
4906 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
4908 function testContext( context ) {
4909 return context && typeof context.getElementsByTagName !== strundefined && context;
4912 support = Sizzle.support = {};
4915 * Detects XML nodes
4916 * @param {Element|Object} elem An element or a document
4917 * @returns {Boolean} True iff elem is a non-HTML XML node
4919 isXML = Sizzle.isXML = function( elem ) {
4920 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4921 return documentElement ? documentElement.nodeName !== "HTML" : false;
4925 * Sets document-related variables once based on the current document
4926 * @param {Element|Object} [doc] An element or document object to use to set the document
4927 * @returns {Object} Returns the current document
4929 setDocument = Sizzle.setDocument = function( node ) {
4930 var hasCompare,
4931 doc = node ? node.ownerDocument || node : preferredDoc,
4932 parent = doc.defaultView;
4934 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4935 return document;
4938 document = doc;
4939 docElem = doc.documentElement;
4941 documentIsHTML = !isXML( doc );
4943 if ( parent && parent !== parent.top ) {
4944 if ( parent.addEventListener ) {
4945 parent.addEventListener( "unload", function() {
4946 setDocument();
4947 }, false );
4948 } else if ( parent.attachEvent ) {
4949 parent.attachEvent( "onunload", function() {
4950 setDocument();
4955 /* Attributes
4956 ---------------------------------------------------------------------- */
4958 support.attributes = assert(function( div ) {
4959 div.className = "i";
4960 return !div.getAttribute("className");
4963 /* getElement(s)By*
4964 ---------------------------------------------------------------------- */
4966 support.getElementsByTagName = assert(function( div ) {
4967 div.appendChild( doc.createComment("") );
4968 return !div.getElementsByTagName("*").length;
4971 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
4972 div.innerHTML = "<div class='a'></div><div class='a i'></div>";
4974 div.firstChild.className = "i";
4975 return div.getElementsByClassName("i").length === 2;
4978 support.getById = assert(function( div ) {
4979 docElem.appendChild( div ).id = expando;
4980 return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
4983 if ( support.getById ) {
4984 Expr.find["ID"] = function( id, context ) {
4985 if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
4986 var m = context.getElementById( id );
4987 return m && m.parentNode ? [m] : [];
4990 Expr.filter["ID"] = function( id ) {
4991 var attrId = id.replace( runescape, funescape );
4992 return function( elem ) {
4993 return elem.getAttribute("id") === attrId;
4996 } else {
4997 delete Expr.find["ID"];
4999 Expr.filter["ID"] = function( id ) {
5000 var attrId = id.replace( runescape, funescape );
5001 return function( elem ) {
5002 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
5003 return node && node.value === attrId;
5008 Expr.find["TAG"] = support.getElementsByTagName ?
5009 function( tag, context ) {
5010 if ( typeof context.getElementsByTagName !== strundefined ) {
5011 return context.getElementsByTagName( tag );
5014 function( tag, context ) {
5015 var elem,
5016 tmp = [],
5017 i = 0,
5018 results = context.getElementsByTagName( tag );
5020 if ( tag === "*" ) {
5021 while ( (elem = results[i++]) ) {
5022 if ( elem.nodeType === 1 ) {
5023 tmp.push( elem );
5027 return tmp;
5029 return results;
5032 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
5033 if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
5034 return context.getElementsByClassName( className );
5038 /* QSA/matchesSelector
5039 ---------------------------------------------------------------------- */
5042 rbuggyMatches = [];
5044 rbuggyQSA = [];
5046 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
5047 assert(function( div ) {
5048 div.innerHTML = "<select t=''><option selected=''></option></select>";
5050 if ( div.querySelectorAll("[t^='']").length ) {
5051 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
5054 if ( !div.querySelectorAll("[selected]").length ) {
5055 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
5058 if ( !div.querySelectorAll(":checked").length ) {
5059 rbuggyQSA.push(":checked");
5063 assert(function( div ) {
5064 var input = doc.createElement("input");
5065 input.setAttribute( "type", "hidden" );
5066 div.appendChild( input ).setAttribute( "name", "D" );
5068 if ( div.querySelectorAll("[name=d]").length ) {
5069 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
5072 if ( !div.querySelectorAll(":enabled").length ) {
5073 rbuggyQSA.push( ":enabled", ":disabled" );
5076 div.querySelectorAll("*,:x");
5077 rbuggyQSA.push(",.*:");
5081 if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
5082 docElem.mozMatchesSelector ||
5083 docElem.oMatchesSelector ||
5084 docElem.msMatchesSelector) )) ) {
5086 assert(function( div ) {
5087 support.disconnectedMatch = matches.call( div, "div" );
5089 matches.call( div, "[s!='']:x" );
5090 rbuggyMatches.push( "!=", pseudos );
5094 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
5095 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
5097 /* Contains
5098 ---------------------------------------------------------------------- */
5099 hasCompare = rnative.test( docElem.compareDocumentPosition );
5101 contains = hasCompare || rnative.test( docElem.contains ) ?
5102 function( a, b ) {
5103 var adown = a.nodeType === 9 ? a.documentElement : a,
5104 bup = b && b.parentNode;
5105 return a === bup || !!( bup && bup.nodeType === 1 && (
5106 adown.contains ?
5107 adown.contains( bup ) :
5108 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
5111 function( a, b ) {
5112 if ( b ) {
5113 while ( (b = b.parentNode) ) {
5114 if ( b === a ) {
5115 return true;
5119 return false;
5122 /* Sorting
5123 ---------------------------------------------------------------------- */
5125 sortOrder = hasCompare ?
5126 function( a, b ) {
5128 if ( a === b ) {
5129 hasDuplicate = true;
5130 return 0;
5133 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
5134 if ( compare ) {
5135 return compare;
5138 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
5139 a.compareDocumentPosition( b ) :
5143 if ( compare & 1 ||
5144 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
5146 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
5147 return -1;
5149 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
5150 return 1;
5153 return sortInput ?
5154 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5158 return compare & 4 ? -1 : 1;
5160 function( a, b ) {
5161 if ( a === b ) {
5162 hasDuplicate = true;
5163 return 0;
5166 var cur,
5167 i = 0,
5168 aup = a.parentNode,
5169 bup = b.parentNode,
5170 ap = [ a ],
5171 bp = [ b ];
5173 if ( !aup || !bup ) {
5174 return a === doc ? -1 :
5175 b === doc ? 1 :
5176 aup ? -1 :
5177 bup ? 1 :
5178 sortInput ?
5179 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
5182 } else if ( aup === bup ) {
5183 return siblingCheck( a, b );
5186 cur = a;
5187 while ( (cur = cur.parentNode) ) {
5188 ap.unshift( cur );
5190 cur = b;
5191 while ( (cur = cur.parentNode) ) {
5192 bp.unshift( cur );
5195 while ( ap[i] === bp[i] ) {
5196 i++;
5199 return i ?
5200 siblingCheck( ap[i], bp[i] ) :
5202 ap[i] === preferredDoc ? -1 :
5203 bp[i] === preferredDoc ? 1 :
5207 return doc;
5210 Sizzle.matches = function( expr, elements ) {
5211 return Sizzle( expr, null, null, elements );
5214 Sizzle.matchesSelector = function( elem, expr ) {
5215 if ( ( elem.ownerDocument || elem ) !== document ) {
5216 setDocument( elem );
5219 expr = expr.replace( rattributeQuotes, "='$1']" );
5221 if ( support.matchesSelector && documentIsHTML &&
5222 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
5223 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
5225 try {
5226 var ret = matches.call( elem, expr );
5228 if ( ret || support.disconnectedMatch ||
5229 elem.document && elem.document.nodeType !== 11 ) {
5230 return ret;
5232 } catch(e) {}
5235 return Sizzle( expr, document, null, [elem] ).length > 0;
5238 Sizzle.contains = function( context, elem ) {
5239 if ( ( context.ownerDocument || context ) !== document ) {
5240 setDocument( context );
5242 return contains( context, elem );
5245 Sizzle.attr = function( elem, name ) {
5246 if ( ( elem.ownerDocument || elem ) !== document ) {
5247 setDocument( elem );
5250 var fn = Expr.attrHandle[ name.toLowerCase() ],
5251 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
5252 fn( elem, name, !documentIsHTML ) :
5253 undefined;
5255 return val !== undefined ?
5256 val :
5257 support.attributes || !documentIsHTML ?
5258 elem.getAttribute( name ) :
5259 (val = elem.getAttributeNode(name)) && val.specified ?
5260 val.value :
5261 null;
5264 Sizzle.error = function( msg ) {
5265 throw new Error( "Syntax error, unrecognized expression: " + msg );
5269 * Document sorting and removing duplicates
5270 * @param {ArrayLike} results
5272 Sizzle.uniqueSort = function( results ) {
5273 var elem,
5274 duplicates = [],
5275 j = 0,
5276 i = 0;
5278 hasDuplicate = !support.detectDuplicates;
5279 sortInput = !support.sortStable && results.slice( 0 );
5280 results.sort( sortOrder );
5282 if ( hasDuplicate ) {
5283 while ( (elem = results[i++]) ) {
5284 if ( elem === results[ i ] ) {
5285 j = duplicates.push( i );
5288 while ( j-- ) {
5289 results.splice( duplicates[ j ], 1 );
5293 sortInput = null;
5295 return results;
5299 * Utility function for retrieving the text value of an array of DOM nodes
5300 * @param {Array|Element} elem
5302 getText = Sizzle.getText = function( elem ) {
5303 var node,
5304 ret = "",
5305 i = 0,
5306 nodeType = elem.nodeType;
5308 if ( !nodeType ) {
5309 while ( (node = elem[i++]) ) {
5310 ret += getText( node );
5312 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
5313 if ( typeof elem.textContent === "string" ) {
5314 return elem.textContent;
5315 } else {
5316 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5317 ret += getText( elem );
5320 } else if ( nodeType === 3 || nodeType === 4 ) {
5321 return elem.nodeValue;
5324 return ret;
5327 Expr = Sizzle.selectors = {
5329 cacheLength: 50,
5331 createPseudo: markFunction,
5333 match: matchExpr,
5335 attrHandle: {},
5337 find: {},
5339 relative: {
5340 ">": { dir: "parentNode", first: true },
5341 " ": { dir: "parentNode" },
5342 "+": { dir: "previousSibling", first: true },
5343 "~": { dir: "previousSibling" }
5346 preFilter: {
5347 "ATTR": function( match ) {
5348 match[1] = match[1].replace( runescape, funescape );
5350 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
5352 if ( match[2] === "~=" ) {
5353 match[3] = " " + match[3] + " ";
5356 return match.slice( 0, 4 );
5359 "CHILD": function( match ) {
5360 /* matches from matchExpr["CHILD"]
5361 1 type (only|nth|...)
5362 2 what (child|of-type)
5363 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
5364 4 xn-component of xn+y argument ([+-]?\d*n|)
5365 5 sign of xn-component
5366 6 x of xn-component
5367 7 sign of y-component
5368 8 y of y-component
5370 match[1] = match[1].toLowerCase();
5372 if ( match[1].slice( 0, 3 ) === "nth" ) {
5373 if ( !match[3] ) {
5374 Sizzle.error( match[0] );
5377 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
5378 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
5380 } else if ( match[3] ) {
5381 Sizzle.error( match[0] );
5384 return match;
5387 "PSEUDO": function( match ) {
5388 var excess,
5389 unquoted = !match[5] && match[2];
5391 if ( matchExpr["CHILD"].test( match[0] ) ) {
5392 return null;
5395 if ( match[3] && match[4] !== undefined ) {
5396 match[2] = match[4];
5398 } else if ( unquoted && rpseudo.test( unquoted ) &&
5399 (excess = tokenize( unquoted, true )) &&
5400 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
5402 match[0] = match[0].slice( 0, excess );
5403 match[2] = unquoted.slice( 0, excess );
5406 return match.slice( 0, 3 );
5410 filter: {
5412 "TAG": function( nodeNameSelector ) {
5413 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
5414 return nodeNameSelector === "*" ?
5415 function() { return true; } :
5416 function( elem ) {
5417 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
5421 "CLASS": function( className ) {
5422 var pattern = classCache[ className + " " ];
5424 return pattern ||
5425 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
5426 classCache( className, function( elem ) {
5427 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
5431 "ATTR": function( name, operator, check ) {
5432 return function( elem ) {
5433 var result = Sizzle.attr( elem, name );
5435 if ( result == null ) {
5436 return operator === "!=";
5438 if ( !operator ) {
5439 return true;
5442 result += "";
5444 return operator === "=" ? result === check :
5445 operator === "!=" ? result !== check :
5446 operator === "^=" ? check && result.indexOf( check ) === 0 :
5447 operator === "*=" ? check && result.indexOf( check ) > -1 :
5448 operator === "$=" ? check && result.slice( -check.length ) === check :
5449 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
5450 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
5451 false;
5455 "CHILD": function( type, what, argument, first, last ) {
5456 var simple = type.slice( 0, 3 ) !== "nth",
5457 forward = type.slice( -4 ) !== "last",
5458 ofType = what === "of-type";
5460 return first === 1 && last === 0 ?
5462 function( elem ) {
5463 return !!elem.parentNode;
5466 function( elem, context, xml ) {
5467 var cache, outerCache, node, diff, nodeIndex, start,
5468 dir = simple !== forward ? "nextSibling" : "previousSibling",
5469 parent = elem.parentNode,
5470 name = ofType && elem.nodeName.toLowerCase(),
5471 useCache = !xml && !ofType;
5473 if ( parent ) {
5475 if ( simple ) {
5476 while ( dir ) {
5477 node = elem;
5478 while ( (node = node[ dir ]) ) {
5479 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
5480 return false;
5483 start = dir = type === "only" && !start && "nextSibling";
5485 return true;
5488 start = [ forward ? parent.firstChild : parent.lastChild ];
5490 if ( forward && useCache ) {
5491 outerCache = parent[ expando ] || (parent[ expando ] = {});
5492 cache = outerCache[ type ] || [];
5493 nodeIndex = cache[0] === dirruns && cache[1];
5494 diff = cache[0] === dirruns && cache[2];
5495 node = nodeIndex && parent.childNodes[ nodeIndex ];
5497 while ( (node = ++nodeIndex && node && node[ dir ] ||
5499 (diff = nodeIndex = 0) || start.pop()) ) {
5501 if ( node.nodeType === 1 && ++diff && node === elem ) {
5502 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
5503 break;
5507 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
5508 diff = cache[1];
5510 } else {
5511 while ( (node = ++nodeIndex && node && node[ dir ] ||
5512 (diff = nodeIndex = 0) || start.pop()) ) {
5514 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
5515 if ( useCache ) {
5516 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
5519 if ( node === elem ) {
5520 break;
5526 diff -= last;
5527 return diff === first || ( diff % first === 0 && diff / first >= 0 );
5532 "PSEUDO": function( pseudo, argument ) {
5533 var args,
5534 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
5535 Sizzle.error( "unsupported pseudo: " + pseudo );
5537 if ( fn[ expando ] ) {
5538 return fn( argument );
5541 if ( fn.length > 1 ) {
5542 args = [ pseudo, pseudo, "", argument ];
5543 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
5544 markFunction(function( seed, matches ) {
5545 var idx,
5546 matched = fn( seed, argument ),
5547 i = matched.length;
5548 while ( i-- ) {
5549 idx = indexOf.call( seed, matched[i] );
5550 seed[ idx ] = !( matches[ idx ] = matched[i] );
5552 }) :
5553 function( elem ) {
5554 return fn( elem, 0, args );
5558 return fn;
5562 pseudos: {
5563 "not": markFunction(function( selector ) {
5564 var input = [],
5565 results = [],
5566 matcher = compile( selector.replace( rtrim, "$1" ) );
5568 return matcher[ expando ] ?
5569 markFunction(function( seed, matches, context, xml ) {
5570 var elem,
5571 unmatched = matcher( seed, null, xml, [] ),
5572 i = seed.length;
5574 while ( i-- ) {
5575 if ( (elem = unmatched[i]) ) {
5576 seed[i] = !(matches[i] = elem);
5579 }) :
5580 function( elem, context, xml ) {
5581 input[0] = elem;
5582 matcher( input, null, xml, results );
5583 return !results.pop();
5587 "has": markFunction(function( selector ) {
5588 return function( elem ) {
5589 return Sizzle( selector, elem ).length > 0;
5593 "contains": markFunction(function( text ) {
5594 return function( elem ) {
5595 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
5599 "lang": markFunction( function( lang ) {
5600 if ( !ridentifier.test(lang || "") ) {
5601 Sizzle.error( "unsupported lang: " + lang );
5603 lang = lang.replace( runescape, funescape ).toLowerCase();
5604 return function( elem ) {
5605 var elemLang;
5606 do {
5607 if ( (elemLang = documentIsHTML ?
5608 elem.lang :
5609 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
5611 elemLang = elemLang.toLowerCase();
5612 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
5614 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
5615 return false;
5619 "target": function( elem ) {
5620 var hash = window.location && window.location.hash;
5621 return hash && hash.slice( 1 ) === elem.id;
5624 "root": function( elem ) {
5625 return elem === docElem;
5628 "focus": function( elem ) {
5629 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
5632 "enabled": function( elem ) {
5633 return elem.disabled === false;
5636 "disabled": function( elem ) {
5637 return elem.disabled === true;
5640 "checked": function( elem ) {
5641 var nodeName = elem.nodeName.toLowerCase();
5642 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
5645 "selected": function( elem ) {
5646 if ( elem.parentNode ) {
5647 elem.parentNode.selectedIndex;
5650 return elem.selected === true;
5653 "empty": function( elem ) {
5654 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5655 if ( elem.nodeType < 6 ) {
5656 return false;
5659 return true;
5662 "parent": function( elem ) {
5663 return !Expr.pseudos["empty"]( elem );
5666 "header": function( elem ) {
5667 return rheader.test( elem.nodeName );
5670 "input": function( elem ) {
5671 return rinputs.test( elem.nodeName );
5674 "button": function( elem ) {
5675 var name = elem.nodeName.toLowerCase();
5676 return name === "input" && elem.type === "button" || name === "button";
5679 "text": function( elem ) {
5680 var attr;
5681 return elem.nodeName.toLowerCase() === "input" &&
5682 elem.type === "text" &&
5684 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
5687 "first": createPositionalPseudo(function() {
5688 return [ 0 ];
5691 "last": createPositionalPseudo(function( matchIndexes, length ) {
5692 return [ length - 1 ];
5695 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
5696 return [ argument < 0 ? argument + length : argument ];
5699 "even": createPositionalPseudo(function( matchIndexes, length ) {
5700 var i = 0;
5701 for ( ; i < length; i += 2 ) {
5702 matchIndexes.push( i );
5704 return matchIndexes;
5707 "odd": createPositionalPseudo(function( matchIndexes, length ) {
5708 var i = 1;
5709 for ( ; i < length; i += 2 ) {
5710 matchIndexes.push( i );
5712 return matchIndexes;
5715 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5716 var i = argument < 0 ? argument + length : argument;
5717 for ( ; --i >= 0; ) {
5718 matchIndexes.push( i );
5720 return matchIndexes;
5723 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5724 var i = argument < 0 ? argument + length : argument;
5725 for ( ; ++i < length; ) {
5726 matchIndexes.push( i );
5728 return matchIndexes;
5733 Expr.pseudos["nth"] = Expr.pseudos["eq"];
5735 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5736 Expr.pseudos[ i ] = createInputPseudo( i );
5738 for ( i in { submit: true, reset: true } ) {
5739 Expr.pseudos[ i ] = createButtonPseudo( i );
5742 function setFilters() {}
5743 setFilters.prototype = Expr.filters = Expr.pseudos;
5744 Expr.setFilters = new setFilters();
5746 function tokenize( selector, parseOnly ) {
5747 var matched, match, tokens, type,
5748 soFar, groups, preFilters,
5749 cached = tokenCache[ selector + " " ];
5751 if ( cached ) {
5752 return parseOnly ? 0 : cached.slice( 0 );
5755 soFar = selector;
5756 groups = [];
5757 preFilters = Expr.preFilter;
5759 while ( soFar ) {
5761 if ( !matched || (match = rcomma.exec( soFar )) ) {
5762 if ( match ) {
5763 soFar = soFar.slice( match[0].length ) || soFar;
5765 groups.push( (tokens = []) );
5768 matched = false;
5770 if ( (match = rcombinators.exec( soFar )) ) {
5771 matched = match.shift();
5772 tokens.push({
5773 value: matched,
5774 type: match[0].replace( rtrim, " " )
5776 soFar = soFar.slice( matched.length );
5779 for ( type in Expr.filter ) {
5780 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5781 (match = preFilters[ type ]( match ))) ) {
5782 matched = match.shift();
5783 tokens.push({
5784 value: matched,
5785 type: type,
5786 matches: match
5788 soFar = soFar.slice( matched.length );
5792 if ( !matched ) {
5793 break;
5797 return parseOnly ?
5798 soFar.length :
5799 soFar ?
5800 Sizzle.error( selector ) :
5801 tokenCache( selector, groups ).slice( 0 );
5804 function toSelector( tokens ) {
5805 var i = 0,
5806 len = tokens.length,
5807 selector = "";
5808 for ( ; i < len; i++ ) {
5809 selector += tokens[i].value;
5811 return selector;
5814 function addCombinator( matcher, combinator, base ) {
5815 var dir = combinator.dir,
5816 checkNonElements = base && dir === "parentNode",
5817 doneName = done++;
5819 return combinator.first ?
5820 function( elem, context, xml ) {
5821 while ( (elem = elem[ dir ]) ) {
5822 if ( elem.nodeType === 1 || checkNonElements ) {
5823 return matcher( elem, context, xml );
5828 function( elem, context, xml ) {
5829 var oldCache, outerCache,
5830 newCache = [ dirruns, doneName ];
5832 if ( xml ) {
5833 while ( (elem = elem[ dir ]) ) {
5834 if ( elem.nodeType === 1 || checkNonElements ) {
5835 if ( matcher( elem, context, xml ) ) {
5836 return true;
5840 } else {
5841 while ( (elem = elem[ dir ]) ) {
5842 if ( elem.nodeType === 1 || checkNonElements ) {
5843 outerCache = elem[ expando ] || (elem[ expando ] = {});
5844 if ( (oldCache = outerCache[ dir ]) &&
5845 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
5847 return (newCache[ 2 ] = oldCache[ 2 ]);
5848 } else {
5849 outerCache[ dir ] = newCache;
5851 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
5852 return true;
5861 function elementMatcher( matchers ) {
5862 return matchers.length > 1 ?
5863 function( elem, context, xml ) {
5864 var i = matchers.length;
5865 while ( i-- ) {
5866 if ( !matchers[i]( elem, context, xml ) ) {
5867 return false;
5870 return true;
5872 matchers[0];
5875 function multipleContexts( selector, contexts, results ) {
5876 var i = 0,
5877 len = contexts.length;
5878 for ( ; i < len; i++ ) {
5879 Sizzle( selector, contexts[i], results );
5881 return results;
5884 function condense( unmatched, map, filter, context, xml ) {
5885 var elem,
5886 newUnmatched = [],
5887 i = 0,
5888 len = unmatched.length,
5889 mapped = map != null;
5891 for ( ; i < len; i++ ) {
5892 if ( (elem = unmatched[i]) ) {
5893 if ( !filter || filter( elem, context, xml ) ) {
5894 newUnmatched.push( elem );
5895 if ( mapped ) {
5896 map.push( i );
5902 return newUnmatched;
5905 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5906 if ( postFilter && !postFilter[ expando ] ) {
5907 postFilter = setMatcher( postFilter );
5909 if ( postFinder && !postFinder[ expando ] ) {
5910 postFinder = setMatcher( postFinder, postSelector );
5912 return markFunction(function( seed, results, context, xml ) {
5913 var temp, i, elem,
5914 preMap = [],
5915 postMap = [],
5916 preexisting = results.length,
5918 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5920 matcherIn = preFilter && ( seed || !selector ) ?
5921 condense( elems, preMap, preFilter, context, xml ) :
5922 elems,
5924 matcherOut = matcher ?
5925 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5927 [] :
5929 results :
5930 matcherIn;
5932 if ( matcher ) {
5933 matcher( matcherIn, matcherOut, context, xml );
5936 if ( postFilter ) {
5937 temp = condense( matcherOut, postMap );
5938 postFilter( temp, [], context, xml );
5940 i = temp.length;
5941 while ( i-- ) {
5942 if ( (elem = temp[i]) ) {
5943 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5948 if ( seed ) {
5949 if ( postFinder || preFilter ) {
5950 if ( postFinder ) {
5951 temp = [];
5952 i = matcherOut.length;
5953 while ( i-- ) {
5954 if ( (elem = matcherOut[i]) ) {
5955 temp.push( (matcherIn[i] = elem) );
5958 postFinder( null, (matcherOut = []), temp, xml );
5961 i = matcherOut.length;
5962 while ( i-- ) {
5963 if ( (elem = matcherOut[i]) &&
5964 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5966 seed[temp] = !(results[temp] = elem);
5971 } else {
5972 matcherOut = condense(
5973 matcherOut === results ?
5974 matcherOut.splice( preexisting, matcherOut.length ) :
5975 matcherOut
5977 if ( postFinder ) {
5978 postFinder( null, results, matcherOut, xml );
5979 } else {
5980 push.apply( results, matcherOut );
5986 function matcherFromTokens( tokens ) {
5987 var checkContext, matcher, j,
5988 len = tokens.length,
5989 leadingRelative = Expr.relative[ tokens[0].type ],
5990 implicitRelative = leadingRelative || Expr.relative[" "],
5991 i = leadingRelative ? 1 : 0,
5993 matchContext = addCombinator( function( elem ) {
5994 return elem === checkContext;
5995 }, implicitRelative, true ),
5996 matchAnyContext = addCombinator( function( elem ) {
5997 return indexOf.call( checkContext, elem ) > -1;
5998 }, implicitRelative, true ),
5999 matchers = [ function( elem, context, xml ) {
6000 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
6001 (checkContext = context).nodeType ?
6002 matchContext( elem, context, xml ) :
6003 matchAnyContext( elem, context, xml ) );
6004 } ];
6006 for ( ; i < len; i++ ) {
6007 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
6008 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
6009 } else {
6010 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
6012 if ( matcher[ expando ] ) {
6013 j = ++i;
6014 for ( ; j < len; j++ ) {
6015 if ( Expr.relative[ tokens[j].type ] ) {
6016 break;
6019 return setMatcher(
6020 i > 1 && elementMatcher( matchers ),
6021 i > 1 && toSelector(
6022 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
6023 ).replace( rtrim, "$1" ),
6024 matcher,
6025 i < j && matcherFromTokens( tokens.slice( i, j ) ),
6026 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
6027 j < len && toSelector( tokens )
6030 matchers.push( matcher );
6034 return elementMatcher( matchers );
6037 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
6038 var bySet = setMatchers.length > 0,
6039 byElement = elementMatchers.length > 0,
6040 superMatcher = function( seed, context, xml, results, outermost ) {
6041 var elem, j, matcher,
6042 matchedCount = 0,
6043 i = "0",
6044 unmatched = seed && [],
6045 setMatched = [],
6046 contextBackup = outermostContext,
6047 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
6048 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
6049 len = elems.length;
6051 if ( outermost ) {
6052 outermostContext = context !== document && context;
6055 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
6056 if ( byElement && elem ) {
6057 j = 0;
6058 while ( (matcher = elementMatchers[j++]) ) {
6059 if ( matcher( elem, context, xml ) ) {
6060 results.push( elem );
6061 break;
6064 if ( outermost ) {
6065 dirruns = dirrunsUnique;
6069 if ( bySet ) {
6070 if ( (elem = !matcher && elem) ) {
6071 matchedCount--;
6074 if ( seed ) {
6075 unmatched.push( elem );
6080 matchedCount += i;
6081 if ( bySet && i !== matchedCount ) {
6082 j = 0;
6083 while ( (matcher = setMatchers[j++]) ) {
6084 matcher( unmatched, setMatched, context, xml );
6087 if ( seed ) {
6088 if ( matchedCount > 0 ) {
6089 while ( i-- ) {
6090 if ( !(unmatched[i] || setMatched[i]) ) {
6091 setMatched[i] = pop.call( results );
6096 setMatched = condense( setMatched );
6099 push.apply( results, setMatched );
6101 if ( outermost && !seed && setMatched.length > 0 &&
6102 ( matchedCount + setMatchers.length ) > 1 ) {
6104 Sizzle.uniqueSort( results );
6108 if ( outermost ) {
6109 dirruns = dirrunsUnique;
6110 outermostContext = contextBackup;
6113 return unmatched;
6116 return bySet ?
6117 markFunction( superMatcher ) :
6118 superMatcher;
6121 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
6122 var i,
6123 setMatchers = [],
6124 elementMatchers = [],
6125 cached = compilerCache[ selector + " " ];
6127 if ( !cached ) {
6128 if ( !match ) {
6129 match = tokenize( selector );
6131 i = match.length;
6132 while ( i-- ) {
6133 cached = matcherFromTokens( match[i] );
6134 if ( cached[ expando ] ) {
6135 setMatchers.push( cached );
6136 } else {
6137 elementMatchers.push( cached );
6141 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
6143 cached.selector = selector;
6145 return cached;
6149 * A low-level selection function that works with Sizzle's compiled
6150 * selector functions
6151 * @param {String|Function} selector A selector or a pre-compiled
6152 * selector function built with Sizzle.compile
6153 * @param {Element} context
6154 * @param {Array} [results]
6155 * @param {Array} [seed] A set of elements to match against
6157 select = Sizzle.select = function( selector, context, results, seed ) {
6158 var i, tokens, token, type, find,
6159 compiled = typeof selector === "function" && selector,
6160 match = !seed && tokenize( (selector = compiled.selector || selector) );
6162 results = results || [];
6164 if ( match.length === 1 ) {
6166 tokens = match[0] = match[0].slice( 0 );
6167 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
6168 support.getById && context.nodeType === 9 && documentIsHTML &&
6169 Expr.relative[ tokens[1].type ] ) {
6171 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
6172 if ( !context ) {
6173 return results;
6175 } else if ( compiled ) {
6176 context = context.parentNode;
6179 selector = selector.slice( tokens.shift().value.length );
6182 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
6183 while ( i-- ) {
6184 token = tokens[i];
6186 if ( Expr.relative[ (type = token.type) ] ) {
6187 break;
6189 if ( (find = Expr.find[ type ]) ) {
6190 if ( (seed = find(
6191 token.matches[0].replace( runescape, funescape ),
6192 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
6193 )) ) {
6195 tokens.splice( i, 1 );
6196 selector = seed.length && toSelector( tokens );
6197 if ( !selector ) {
6198 push.apply( results, seed );
6199 return results;
6202 break;
6208 ( compiled || compile( selector, match ) )(
6209 seed,
6210 context,
6211 !documentIsHTML,
6212 results,
6213 rsibling.test( selector ) && testContext( context.parentNode ) || context
6215 return results;
6219 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
6221 support.detectDuplicates = !!hasDuplicate;
6223 setDocument();
6225 support.sortDetached = assert(function( div1 ) {
6226 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
6229 if ( !assert(function( div ) {
6230 div.innerHTML = "<a href='#'></a>";
6231 return div.firstChild.getAttribute("href") === "#" ;
6232 }) ) {
6233 addHandle( "type|href|height|width", function( elem, name, isXML ) {
6234 if ( !isXML ) {
6235 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
6240 if ( !support.attributes || !assert(function( div ) {
6241 div.innerHTML = "<input/>";
6242 div.firstChild.setAttribute( "value", "" );
6243 return div.firstChild.getAttribute( "value" ) === "";
6244 }) ) {
6245 addHandle( "value", function( elem, name, isXML ) {
6246 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
6247 return elem.defaultValue;
6252 if ( !assert(function( div ) {
6253 return div.getAttribute("disabled") == null;
6254 }) ) {
6255 addHandle( booleans, function( elem, name, isXML ) {
6256 var val;
6257 if ( !isXML ) {
6258 return elem[ name ] === true ? name.toLowerCase() :
6259 (val = elem.getAttributeNode( name )) && val.specified ?
6260 val.value :
6261 null;
6266 if ( typeof define === "function" && define.amd ) {
6267 define(function() { return Sizzle; });
6268 } else if ( typeof module !== "undefined" && module.exports ) {
6269 module.exports = Sizzle;
6270 } else {
6271 window.Sizzle = Sizzle;
6274 })( window );
6276 ;(function() {
6277 if (typeof Sizzle !== 'undefined') {
6278 return;
6281 if (typeof define !== 'undefined' && define.amd) {
6282 window.Sizzle = Prototype._actual_sizzle;
6283 window.define = Prototype._original_define;
6284 delete Prototype._actual_sizzle;
6285 delete Prototype._original_define;
6286 } else if (typeof module !== 'undefined' && module.exports) {
6287 window.Sizzle = module.exports;
6288 module.exports = {};
6290 })();
6292 ;(function(engine) {
6293 var extendElements = Prototype.Selector.extendElements;
6295 function select(selector, scope) {
6296 return extendElements(engine(selector, scope || document));
6299 function match(element, selector) {
6300 return engine.matches(selector, [element]).length == 1;
6303 Prototype.Selector.engine = engine;
6304 Prototype.Selector.select = select;
6305 Prototype.Selector.match = match;
6306 })(Sizzle);
6308 window.Sizzle = Prototype._original_property;
6309 delete Prototype._original_property;
6311 var Form = {
6312 reset: function(form) {
6313 form = $(form);
6314 form.reset();
6315 return form;
6318 serializeElements: function(elements, options) {
6319 if (typeof options != 'object') options = { hash: !!options };
6320 else if (Object.isUndefined(options.hash)) options.hash = true;
6321 var key, value, submitted = false, submit = options.submit, accumulator, initial;
6323 if (options.hash) {
6324 initial = {};
6325 accumulator = function(result, key, value) {
6326 if (key in result) {
6327 if (!Object.isArray(result[key])) result[key] = [result[key]];
6328 result[key] = result[key].concat(value);
6329 } else result[key] = value;
6330 return result;
6332 } else {
6333 initial = '';
6334 accumulator = function(result, key, values) {
6335 if (!Object.isArray(values)) {values = [values];}
6336 if (!values.length) {return result;}
6337 var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');
6338 return result + (result ? "&" : "") + values.map(function (value) {
6339 value = value.gsub(/(\r)?\n/, '\r\n');
6340 value = encodeURIComponent(value);
6341 value = value.gsub(/%20/, '+');
6342 return encodedKey + "=" + value;
6343 }).join("&");
6347 return elements.inject(initial, function(result, element) {
6348 if (!element.disabled && element.name) {
6349 key = element.name; value = $(element).getValue();
6350 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
6351 submit !== false && (!submit || key == submit) && (submitted = true)))) {
6352 result = accumulator(result, key, value);
6355 return result;
6360 Form.Methods = {
6361 serialize: function(form, options) {
6362 return Form.serializeElements(Form.getElements(form), options);
6366 getElements: function(form) {
6367 var elements = $(form).getElementsByTagName('*');
6368 var element, results = [], serializers = Form.Element.Serializers;
6370 for (var i = 0; element = elements[i]; i++) {
6371 if (serializers[element.tagName.toLowerCase()])
6372 results.push(Element.extend(element));
6374 return results;
6377 getInputs: function(form, typeName, name) {
6378 form = $(form);
6379 var inputs = form.getElementsByTagName('input');
6381 if (!typeName && !name) return $A(inputs).map(Element.extend);
6383 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
6384 var input = inputs[i];
6385 if ((typeName && input.type != typeName) || (name && input.name != name))
6386 continue;
6387 matchingInputs.push(Element.extend(input));
6390 return matchingInputs;
6393 disable: function(form) {
6394 form = $(form);
6395 Form.getElements(form).invoke('disable');
6396 return form;
6399 enable: function(form) {
6400 form = $(form);
6401 Form.getElements(form).invoke('enable');
6402 return form;
6405 findFirstElement: function(form) {
6406 var elements = $(form).getElements().findAll(function(element) {
6407 return 'hidden' != element.type && !element.disabled;
6409 var firstByIndex = elements.findAll(function(element) {
6410 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
6411 }).sortBy(function(element) { return element.tabIndex }).first();
6413 return firstByIndex ? firstByIndex : elements.find(function(element) {
6414 return /^(?:input|select|textarea)$/i.test(element.tagName);
6418 focusFirstElement: function(form) {
6419 form = $(form);
6420 var element = form.findFirstElement();
6421 if (element) element.activate();
6422 return form;
6425 request: function(form, options) {
6426 form = $(form), options = Object.clone(options || { });
6428 var params = options.parameters, action = form.readAttribute('action') || '';
6429 if (action.blank()) action = window.location.href;
6430 options.parameters = form.serialize(true);
6432 if (params) {
6433 if (Object.isString(params)) params = params.toQueryParams();
6434 Object.extend(options.parameters, params);
6437 if (form.hasAttribute('method') && !options.method)
6438 options.method = form.method;
6440 return new Ajax.Request(action, options);
6444 /*--------------------------------------------------------------------------*/
6447 Form.Element = {
6448 focus: function(element) {
6449 $(element).focus();
6450 return element;
6453 select: function(element) {
6454 $(element).select();
6455 return element;
6459 Form.Element.Methods = {
6461 serialize: function(element) {
6462 element = $(element);
6463 if (!element.disabled && element.name) {
6464 var value = element.getValue();
6465 if (value != undefined) {
6466 var pair = { };
6467 pair[element.name] = value;
6468 return Object.toQueryString(pair);
6471 return '';
6474 getValue: function(element) {
6475 element = $(element);
6476 var method = element.tagName.toLowerCase();
6477 return Form.Element.Serializers[method](element);
6480 setValue: function(element, value) {
6481 element = $(element);
6482 var method = element.tagName.toLowerCase();
6483 Form.Element.Serializers[method](element, value);
6484 return element;
6487 clear: function(element) {
6488 $(element).value = '';
6489 return element;
6492 present: function(element) {
6493 return $(element).value != '';
6496 activate: function(element) {
6497 element = $(element);
6498 try {
6499 element.focus();
6500 if (element.select && (element.tagName.toLowerCase() != 'input' ||
6501 !(/^(?:button|reset|submit)$/i.test(element.type))))
6502 element.select();
6503 } catch (e) { }
6504 return element;
6507 disable: function(element) {
6508 element = $(element);
6509 element.disabled = true;
6510 return element;
6513 enable: function(element) {
6514 element = $(element);
6515 element.disabled = false;
6516 return element;
6520 /*--------------------------------------------------------------------------*/
6522 var Field = Form.Element;
6524 var $F = Form.Element.Methods.getValue;
6526 /*--------------------------------------------------------------------------*/
6528 Form.Element.Serializers = (function() {
6529 function input(element, value) {
6530 switch (element.type.toLowerCase()) {
6531 case 'checkbox':
6532 case 'radio':
6533 return inputSelector(element, value);
6534 default:
6535 return valueSelector(element, value);
6539 function inputSelector(element, value) {
6540 if (Object.isUndefined(value))
6541 return element.checked ? element.value : null;
6542 else element.checked = !!value;
6545 function valueSelector(element, value) {
6546 if (Object.isUndefined(value)) return element.value;
6547 else element.value = value;
6550 function select(element, value) {
6551 if (Object.isUndefined(value))
6552 return (element.type === 'select-one' ? selectOne : selectMany)(element);
6554 var opt, currentValue, single = !Object.isArray(value);
6555 for (var i = 0, length = element.length; i < length; i++) {
6556 opt = element.options[i];
6557 currentValue = this.optionValue(opt);
6558 if (single) {
6559 if (currentValue == value) {
6560 opt.selected = true;
6561 return;
6564 else opt.selected = value.include(currentValue);
6568 function selectOne(element) {
6569 var index = element.selectedIndex;
6570 return index >= 0 ? optionValue(element.options[index]) : null;
6573 function selectMany(element) {
6574 var values, length = element.length;
6575 if (!length) return null;
6577 for (var i = 0, values = []; i < length; i++) {
6578 var opt = element.options[i];
6579 if (opt.selected) values.push(optionValue(opt));
6581 return values;
6584 function optionValue(opt) {
6585 return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
6588 return {
6589 input: input,
6590 inputSelector: inputSelector,
6591 textarea: valueSelector,
6592 select: select,
6593 selectOne: selectOne,
6594 selectMany: selectMany,
6595 optionValue: optionValue,
6596 button: valueSelector
6598 })();
6600 /*--------------------------------------------------------------------------*/
6603 Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
6604 initialize: function($super, element, frequency, callback) {
6605 $super(callback, frequency);
6606 this.element = $(element);
6607 this.lastValue = this.getValue();
6610 execute: function() {
6611 var value = this.getValue();
6612 if (Object.isString(this.lastValue) && Object.isString(value) ?
6613 this.lastValue != value : String(this.lastValue) != String(value)) {
6614 this.callback(this.element, value);
6615 this.lastValue = value;
6620 Form.Element.Observer = Class.create(Abstract.TimedObserver, {
6621 getValue: function() {
6622 return Form.Element.getValue(this.element);
6626 Form.Observer = Class.create(Abstract.TimedObserver, {
6627 getValue: function() {
6628 return Form.serialize(this.element);
6632 /*--------------------------------------------------------------------------*/
6634 Abstract.EventObserver = Class.create({
6635 initialize: function(element, callback) {
6636 this.element = $(element);
6637 this.callback = callback;
6639 this.lastValue = this.getValue();
6640 if (this.element.tagName.toLowerCase() == 'form')
6641 this.registerFormCallbacks();
6642 else
6643 this.registerCallback(this.element);
6646 onElementEvent: function() {
6647 var value = this.getValue();
6648 if (this.lastValue != value) {
6649 this.callback(this.element, value);
6650 this.lastValue = value;
6654 registerFormCallbacks: function() {
6655 Form.getElements(this.element).each(this.registerCallback, this);
6658 registerCallback: function(element) {
6659 if (element.type) {
6660 switch (element.type.toLowerCase()) {
6661 case 'checkbox':
6662 case 'radio':
6663 Event.observe(element, 'click', this.onElementEvent.bind(this));
6664 break;
6665 default:
6666 Event.observe(element, 'change', this.onElementEvent.bind(this));
6667 break;
6673 Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
6674 getValue: function() {
6675 return Form.Element.getValue(this.element);
6679 Form.EventObserver = Class.create(Abstract.EventObserver, {
6680 getValue: function() {
6681 return Form.serialize(this.element);
6684 (function(GLOBAL) {
6685 var DIV = document.createElement('div');
6686 var docEl = document.documentElement;
6687 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
6688 && 'onmouseleave' in docEl;
6690 var Event = {
6691 KEY_BACKSPACE: 8,
6692 KEY_TAB: 9,
6693 KEY_RETURN: 13,
6694 KEY_ESC: 27,
6695 KEY_LEFT: 37,
6696 KEY_UP: 38,
6697 KEY_RIGHT: 39,
6698 KEY_DOWN: 40,
6699 KEY_DELETE: 46,
6700 KEY_HOME: 36,
6701 KEY_END: 35,
6702 KEY_PAGEUP: 33,
6703 KEY_PAGEDOWN: 34,
6704 KEY_INSERT: 45
6708 var isIELegacyEvent = function(event) { return false; };
6710 if (window.attachEvent) {
6711 if (window.addEventListener) {
6712 isIELegacyEvent = function(event) {
6713 return !(event instanceof window.Event);
6715 } else {
6716 isIELegacyEvent = function(event) { return true; };
6720 var _isButton;
6722 function _isButtonForDOMEvents(event, code) {
6723 return event.which ? (event.which === code + 1) : (event.button === code);
6726 var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
6727 function _isButtonForLegacyEvents(event, code) {
6728 return event.button === legacyButtonMap[code];
6731 function _isButtonForWebKit(event, code) {
6732 switch (code) {
6733 case 0: return event.which == 1 && !event.metaKey;
6734 case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
6735 case 2: return event.which == 3;
6736 default: return false;
6740 if (window.attachEvent) {
6741 if (!window.addEventListener) {
6742 _isButton = _isButtonForLegacyEvents;
6743 } else {
6744 _isButton = function(event, code) {
6745 return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
6746 _isButtonForDOMEvents(event, code);
6749 } else if (Prototype.Browser.WebKit) {
6750 _isButton = _isButtonForWebKit;
6751 } else {
6752 _isButton = _isButtonForDOMEvents;
6755 function isLeftClick(event) { return _isButton(event, 0) }
6757 function isMiddleClick(event) { return _isButton(event, 1) }
6759 function isRightClick(event) { return _isButton(event, 2) }
6761 function element(event) {
6762 return Element.extend(_element(event));
6765 function _element(event) {
6766 event = Event.extend(event);
6768 var node = event.target, type = event.type,
6769 currentTarget = event.currentTarget;
6771 if (currentTarget && currentTarget.tagName) {
6772 if (type === 'load' || type === 'error' ||
6773 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
6774 && currentTarget.type === 'radio'))
6775 node = currentTarget;
6778 return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;
6781 function findElement(event, expression) {
6782 var element = _element(event), selector = Prototype.Selector;
6783 if (!expression) return Element.extend(element);
6784 while (element) {
6785 if (Object.isElement(element) && selector.match(element, expression))
6786 return Element.extend(element);
6787 element = element.parentNode;
6791 function pointer(event) {
6792 return { x: pointerX(event), y: pointerY(event) };
6795 function pointerX(event) {
6796 var docElement = document.documentElement,
6797 body = document.body || { scrollLeft: 0 };
6799 return event.pageX || (event.clientX +
6800 (docElement.scrollLeft || body.scrollLeft) -
6801 (docElement.clientLeft || 0));
6804 function pointerY(event) {
6805 var docElement = document.documentElement,
6806 body = document.body || { scrollTop: 0 };
6808 return event.pageY || (event.clientY +
6809 (docElement.scrollTop || body.scrollTop) -
6810 (docElement.clientTop || 0));
6814 function stop(event) {
6815 Event.extend(event);
6816 event.preventDefault();
6817 event.stopPropagation();
6819 event.stopped = true;
6823 Event.Methods = {
6824 isLeftClick: isLeftClick,
6825 isMiddleClick: isMiddleClick,
6826 isRightClick: isRightClick,
6828 element: element,
6829 findElement: findElement,
6831 pointer: pointer,
6832 pointerX: pointerX,
6833 pointerY: pointerY,
6835 stop: stop
6838 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
6839 m[name] = Event.Methods[name].methodize();
6840 return m;
6843 if (window.attachEvent) {
6844 function _relatedTarget(event) {
6845 var element;
6846 switch (event.type) {
6847 case 'mouseover':
6848 case 'mouseenter':
6849 element = event.fromElement;
6850 break;
6851 case 'mouseout':
6852 case 'mouseleave':
6853 element = event.toElement;
6854 break;
6855 default:
6856 return null;
6858 return Element.extend(element);
6861 var additionalMethods = {
6862 stopPropagation: function() { this.cancelBubble = true },
6863 preventDefault: function() { this.returnValue = false },
6864 inspect: function() { return '[object Event]' }
6867 Event.extend = function(event, element) {
6868 if (!event) return false;
6870 if (!isIELegacyEvent(event)) return event;
6872 if (event._extendedByPrototype) return event;
6873 event._extendedByPrototype = Prototype.emptyFunction;
6875 var pointer = Event.pointer(event);
6877 Object.extend(event, {
6878 target: event.srcElement || element,
6879 relatedTarget: _relatedTarget(event),
6880 pageX: pointer.x,
6881 pageY: pointer.y
6884 Object.extend(event, methods);
6885 Object.extend(event, additionalMethods);
6887 return event;
6889 } else {
6890 Event.extend = Prototype.K;
6893 if (window.addEventListener) {
6894 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
6895 Object.extend(Event.prototype, methods);
6898 var EVENT_TRANSLATIONS = {
6899 mouseenter: 'mouseover',
6900 mouseleave: 'mouseout'
6903 function getDOMEventName(eventName) {
6904 return EVENT_TRANSLATIONS[eventName] || eventName;
6907 if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)
6908 getDOMEventName = Prototype.K;
6910 function getUniqueElementID(element) {
6911 if (element === window) return 0;
6913 if (typeof element._prototypeUID === 'undefined')
6914 element._prototypeUID = Element.Storage.UID++;
6915 return element._prototypeUID;
6918 function getUniqueElementID_IE(element) {
6919 if (element === window) return 0;
6920 if (element == document) return 1;
6921 return element.uniqueID;
6924 if ('uniqueID' in DIV)
6925 getUniqueElementID = getUniqueElementID_IE;
6927 function isCustomEvent(eventName) {
6928 return eventName.include(':');
6931 Event._isCustomEvent = isCustomEvent;
6933 function getOrCreateRegistryFor(element, uid) {
6934 var CACHE = GLOBAL.Event.cache;
6935 if (Object.isUndefined(uid))
6936 uid = getUniqueElementID(element);
6937 if (!CACHE[uid]) CACHE[uid] = { element: element };
6938 return CACHE[uid];
6941 function destroyRegistryForElement(element, uid) {
6942 if (Object.isUndefined(uid))
6943 uid = getUniqueElementID(element);
6944 delete GLOBAL.Event.cache[uid];
6948 function register(element, eventName, handler) {
6949 var registry = getOrCreateRegistryFor(element);
6950 if (!registry[eventName]) registry[eventName] = [];
6951 var entries = registry[eventName];
6953 var i = entries.length;
6954 while (i--)
6955 if (entries[i].handler === handler) return null;
6957 var uid = getUniqueElementID(element);
6958 var responder = GLOBAL.Event._createResponder(uid, eventName, handler);
6959 var entry = {
6960 responder: responder,
6961 handler: handler
6964 entries.push(entry);
6965 return entry;
6968 function unregister(element, eventName, handler) {
6969 var registry = getOrCreateRegistryFor(element);
6970 var entries = registry[eventName] || [];
6972 var i = entries.length, entry;
6973 while (i--) {
6974 if (entries[i].handler === handler) {
6975 entry = entries[i];
6976 break;
6980 if (entry) {
6981 var index = entries.indexOf(entry);
6982 entries.splice(index, 1);
6985 if (entries.length === 0) {
6986 delete registry[eventName];
6987 if (Object.keys(registry).length === 1 && ('element' in registry))
6988 destroyRegistryForElement(element);
6991 return entry;
6995 function observe(element, eventName, handler) {
6996 element = $(element);
6997 var entry = register(element, eventName, handler);
6999 if (entry === null) return element;
7001 var responder = entry.responder;
7002 if (isCustomEvent(eventName))
7003 observeCustomEvent(element, eventName, responder);
7004 else
7005 observeStandardEvent(element, eventName, responder);
7007 return element;
7010 function observeStandardEvent(element, eventName, responder) {
7011 var actualEventName = getDOMEventName(eventName);
7012 if (element.addEventListener) {
7013 element.addEventListener(actualEventName, responder, false);
7014 } else {
7015 element.attachEvent('on' + actualEventName, responder);
7019 function observeCustomEvent(element, eventName, responder) {
7020 if (element.addEventListener) {
7021 element.addEventListener('dataavailable', responder, false);
7022 } else {
7023 element.attachEvent('ondataavailable', responder);
7024 element.attachEvent('onlosecapture', responder);
7028 function stopObserving(element, eventName, handler) {
7029 element = $(element);
7030 var handlerGiven = !Object.isUndefined(handler),
7031 eventNameGiven = !Object.isUndefined(eventName);
7033 if (!eventNameGiven && !handlerGiven) {
7034 stopObservingElement(element);
7035 return element;
7038 if (!handlerGiven) {
7039 stopObservingEventName(element, eventName);
7040 return element;
7043 var entry = unregister(element, eventName, handler);
7045 if (!entry) return element;
7046 removeEvent(element, eventName, entry.responder);
7047 return element;
7050 function stopObservingStandardEvent(element, eventName, responder) {
7051 var actualEventName = getDOMEventName(eventName);
7052 if (element.removeEventListener) {
7053 element.removeEventListener(actualEventName, responder, false);
7054 } else {
7055 element.detachEvent('on' + actualEventName, responder);
7059 function stopObservingCustomEvent(element, eventName, responder) {
7060 if (element.removeEventListener) {
7061 element.removeEventListener('dataavailable', responder, false);
7062 } else {
7063 element.detachEvent('ondataavailable', responder);
7064 element.detachEvent('onlosecapture', responder);
7070 function stopObservingElement(element) {
7071 var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];
7072 if (!registry) return;
7074 destroyRegistryForElement(element, uid);
7076 var entries, i;
7077 for (var eventName in registry) {
7078 if (eventName === 'element') continue;
7080 entries = registry[eventName];
7081 i = entries.length;
7082 while (i--)
7083 removeEvent(element, eventName, entries[i].responder);
7087 function stopObservingEventName(element, eventName) {
7088 var registry = getOrCreateRegistryFor(element);
7089 var entries = registry[eventName];
7090 if (entries) {
7091 delete registry[eventName];
7094 entries = entries || [];
7096 var i = entries.length;
7097 while (i--)
7098 removeEvent(element, eventName, entries[i].responder);
7100 for (var name in registry) {
7101 if (name === 'element') continue;
7102 return; // There is another registered event
7105 destroyRegistryForElement(element);
7109 function removeEvent(element, eventName, handler) {
7110 if (isCustomEvent(eventName))
7111 stopObservingCustomEvent(element, eventName, handler);
7112 else
7113 stopObservingStandardEvent(element, eventName, handler);
7118 function getFireTarget(element) {
7119 if (element !== document) return element;
7120 if (document.createEvent && !element.dispatchEvent)
7121 return document.documentElement;
7122 return element;
7125 function fire(element, eventName, memo, bubble) {
7126 element = getFireTarget($(element));
7127 if (Object.isUndefined(bubble)) bubble = true;
7128 memo = memo || {};
7130 var event = fireEvent(element, eventName, memo, bubble);
7131 return Event.extend(event);
7134 function fireEvent_DOM(element, eventName, memo, bubble) {
7135 var event = document.createEvent('HTMLEvents');
7136 event.initEvent('dataavailable', bubble, true);
7138 event.eventName = eventName;
7139 event.memo = memo;
7141 element.dispatchEvent(event);
7142 return event;
7145 function fireEvent_IE(element, eventName, memo, bubble) {
7146 var event = document.createEventObject();
7147 event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
7149 event.eventName = eventName;
7150 event.memo = memo;
7152 element.fireEvent(event.eventType, event);
7153 return event;
7156 var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;
7160 Event.Handler = Class.create({
7161 initialize: function(element, eventName, selector, callback) {
7162 this.element = $(element);
7163 this.eventName = eventName;
7164 this.selector = selector;
7165 this.callback = callback;
7166 this.handler = this.handleEvent.bind(this);
7170 start: function() {
7171 Event.observe(this.element, this.eventName, this.handler);
7172 return this;
7175 stop: function() {
7176 Event.stopObserving(this.element, this.eventName, this.handler);
7177 return this;
7180 handleEvent: function(event) {
7181 var element = Event.findElement(event, this.selector);
7182 if (element) this.callback.call(this.element, event, element);
7186 function on(element, eventName, selector, callback) {
7187 element = $(element);
7188 if (Object.isFunction(selector) && Object.isUndefined(callback)) {
7189 callback = selector, selector = null;
7192 return new Event.Handler(element, eventName, selector, callback).start();
7195 Object.extend(Event, Event.Methods);
7197 Object.extend(Event, {
7198 fire: fire,
7199 observe: observe,
7200 stopObserving: stopObserving,
7201 on: on
7204 Element.addMethods({
7205 fire: fire,
7207 observe: observe,
7209 stopObserving: stopObserving,
7211 on: on
7214 Object.extend(document, {
7215 fire: fire.methodize(),
7217 observe: observe.methodize(),
7219 stopObserving: stopObserving.methodize(),
7221 on: on.methodize(),
7223 loaded: false
7226 if (GLOBAL.Event) Object.extend(window.Event, Event);
7227 else GLOBAL.Event = Event;
7229 GLOBAL.Event.cache = {};
7231 function destroyCache_IE() {
7232 GLOBAL.Event.cache = null;
7235 if (window.attachEvent)
7236 window.attachEvent('onunload', destroyCache_IE);
7238 DIV = null;
7239 docEl = null;
7240 })(this);
7242 (function(GLOBAL) {
7243 /* Code for creating leak-free event responders is based on work by
7244 John-David Dalton. */
7246 var docEl = document.documentElement;
7247 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
7248 && 'onmouseleave' in docEl;
7250 function isSimulatedMouseEnterLeaveEvent(eventName) {
7251 return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
7252 (eventName === 'mouseenter' || eventName === 'mouseleave');
7255 function createResponder(uid, eventName, handler) {
7256 if (Event._isCustomEvent(eventName))
7257 return createResponderForCustomEvent(uid, eventName, handler);
7258 if (isSimulatedMouseEnterLeaveEvent(eventName))
7259 return createMouseEnterLeaveResponder(uid, eventName, handler);
7261 return function(event) {
7262 if (!Event.cache) return;
7264 var element = Event.cache[uid].element;
7265 Event.extend(event, element);
7266 handler.call(element, event);
7270 function createResponderForCustomEvent(uid, eventName, handler) {
7271 return function(event) {
7272 var cache = Event.cache[uid];
7273 var element = cache && cache.element;
7275 if (Object.isUndefined(event.eventName))
7276 return false;
7278 if (event.eventName !== eventName)
7279 return false;
7281 Event.extend(event, element);
7282 handler.call(element, event);
7286 function createMouseEnterLeaveResponder(uid, eventName, handler) {
7287 return function(event) {
7288 var element = Event.cache[uid].element;
7290 Event.extend(event, element);
7291 var parent = event.relatedTarget;
7293 while (parent && parent !== element) {
7294 try { parent = parent.parentNode; }
7295 catch(e) { parent = element; }
7298 if (parent === element) return;
7299 handler.call(element, event);
7303 GLOBAL.Event._createResponder = createResponder;
7304 docEl = null;
7305 })(this);
7307 (function(GLOBAL) {
7308 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
7309 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
7311 var TIMER;
7313 function fireContentLoadedEvent() {
7314 if (document.loaded) return;
7315 if (TIMER) window.clearTimeout(TIMER);
7316 document.loaded = true;
7317 document.fire('dom:loaded');
7320 function checkReadyState() {
7321 if (document.readyState === 'complete') {
7322 document.detachEvent('onreadystatechange', checkReadyState);
7323 fireContentLoadedEvent();
7327 function pollDoScroll() {
7328 try {
7329 document.documentElement.doScroll('left');
7330 } catch (e) {
7331 TIMER = pollDoScroll.defer();
7332 return;
7335 fireContentLoadedEvent();
7339 if (document.readyState === 'complete') {
7340 fireContentLoadedEvent();
7341 return;
7344 if (document.addEventListener) {
7345 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
7346 } else {
7347 document.attachEvent('onreadystatechange', checkReadyState);
7348 if (window == top) TIMER = pollDoScroll.defer();
7351 Event.observe(window, 'load', fireContentLoadedEvent);
7352 })(this);
7355 Element.addMethods();
7356 /*------------------------------- DEPRECATED -------------------------------*/
7358 Hash.toQueryString = Object.toQueryString;
7360 var Toggle = { display: Element.toggle };
7362 Element.addMethods({
7363 childOf: Element.Methods.descendantOf
7366 var Insertion = {
7367 Before: function(element, content) {
7368 return Element.insert(element, {before:content});
7371 Top: function(element, content) {
7372 return Element.insert(element, {top:content});
7375 Bottom: function(element, content) {
7376 return Element.insert(element, {bottom:content});
7379 After: function(element, content) {
7380 return Element.insert(element, {after:content});
7384 var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
7386 var Position = {
7387 includeScrollOffsets: false,
7389 prepare: function() {
7390 this.deltaX = window.pageXOffset
7391 || document.documentElement.scrollLeft
7392 || document.body.scrollLeft
7393 || 0;
7394 this.deltaY = window.pageYOffset
7395 || document.documentElement.scrollTop
7396 || document.body.scrollTop
7397 || 0;
7400 within: function(element, x, y) {
7401 if (this.includeScrollOffsets)
7402 return this.withinIncludingScrolloffsets(element, x, y);
7403 this.xcomp = x;
7404 this.ycomp = y;
7405 this.offset = Element.cumulativeOffset(element);
7407 return (y >= this.offset[1] &&
7408 y < this.offset[1] + element.offsetHeight &&
7409 x >= this.offset[0] &&
7410 x < this.offset[0] + element.offsetWidth);
7413 withinIncludingScrolloffsets: function(element, x, y) {
7414 var offsetcache = Element.cumulativeScrollOffset(element);
7416 this.xcomp = x + offsetcache[0] - this.deltaX;
7417 this.ycomp = y + offsetcache[1] - this.deltaY;
7418 this.offset = Element.cumulativeOffset(element);
7420 return (this.ycomp >= this.offset[1] &&
7421 this.ycomp < this.offset[1] + element.offsetHeight &&
7422 this.xcomp >= this.offset[0] &&
7423 this.xcomp < this.offset[0] + element.offsetWidth);
7426 overlap: function(mode, element) {
7427 if (!mode) return 0;
7428 if (mode == 'vertical')
7429 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
7430 element.offsetHeight;
7431 if (mode == 'horizontal')
7432 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
7433 element.offsetWidth;
7437 cumulativeOffset: Element.Methods.cumulativeOffset,
7439 positionedOffset: Element.Methods.positionedOffset,
7441 absolutize: function(element) {
7442 Position.prepare();
7443 return Element.absolutize(element);
7446 relativize: function(element) {
7447 Position.prepare();
7448 return Element.relativize(element);
7451 realOffset: Element.Methods.cumulativeScrollOffset,
7453 offsetParent: Element.Methods.getOffsetParent,
7455 page: Element.Methods.viewportOffset,
7457 clone: function(source, target, options) {
7458 options = options || { };
7459 return Element.clonePosition(target, source, options);
7463 /*--------------------------------------------------------------------------*/
7465 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
7466 function iter(name) {
7467 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
7470 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
7471 function(element, className) {
7472 className = className.toString().strip();
7473 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
7474 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
7475 } : function(element, className) {
7476 className = className.toString().strip();
7477 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
7478 if (!classNames && !className) return elements;
7480 var nodes = $(element).getElementsByTagName('*');
7481 className = ' ' + className + ' ';
7483 for (var i = 0, child, cn; child = nodes[i]; i++) {
7484 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
7485 (classNames && classNames.all(function(name) {
7486 return !name.toString().blank() && cn.include(' ' + name + ' ');
7487 }))))
7488 elements.push(Element.extend(child));
7490 return elements;
7493 return function(className, parentElement) {
7494 return $(parentElement || document.body).getElementsByClassName(className);
7496 }(Element.Methods);
7498 /*--------------------------------------------------------------------------*/
7500 Element.ClassNames = Class.create();
7501 Element.ClassNames.prototype = {
7502 initialize: function(element) {
7503 this.element = $(element);
7506 _each: function(iterator, context) {
7507 this.element.className.split(/\s+/).select(function(name) {
7508 return name.length > 0;
7509 })._each(iterator, context);
7512 set: function(className) {
7513 this.element.className = className;
7516 add: function(classNameToAdd) {
7517 if (this.include(classNameToAdd)) return;
7518 this.set($A(this).concat(classNameToAdd).join(' '));
7521 remove: function(classNameToRemove) {
7522 if (!this.include(classNameToRemove)) return;
7523 this.set($A(this).without(classNameToRemove).join(' '));
7526 toString: function() {
7527 return $A(this).join(' ');
7531 Object.extend(Element.ClassNames.prototype, Enumerable);
7533 /*--------------------------------------------------------------------------*/
7535 (function() {
7536 window.Selector = Class.create({
7537 initialize: function(expression) {
7538 this.expression = expression.strip();
7541 findElements: function(rootElement) {
7542 return Prototype.Selector.select(this.expression, rootElement);
7545 match: function(element) {
7546 return Prototype.Selector.match(element, this.expression);
7549 toString: function() {
7550 return this.expression;
7553 inspect: function() {
7554 return "#<Selector: " + this.expression + ">";
7558 Object.extend(Selector, {
7559 matchElements: function(elements, expression) {
7560 var match = Prototype.Selector.match,
7561 results = [];
7563 for (var i = 0, length = elements.length; i < length; i++) {
7564 var element = elements[i];
7565 if (match(element, expression)) {
7566 results.push(Element.extend(element));
7569 return results;
7572 findElement: function(elements, expression, index) {
7573 index = index || 0;
7574 var matchIndex = 0, element;
7575 for (var i = 0, length = elements.length; i < length; i++) {
7576 element = elements[i];
7577 if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
7578 return Element.extend(element);
7583 findChildElements: function(element, expressions) {
7584 var selector = expressions.toArray().join(', ');
7585 return Prototype.Selector.select(selector, element || document);
7588 })();