-
+ 066CB61E50765A665D7A67D70150FDD04668DAB0D87C5B98EB13FDCCBAB0C79E1DD904C870C73C8871DDD2A2EA20F0975F10CC0D7643FB00D12B9D414A4D6E29
mp-wp/wp-includes/js/prototype.js
(0 . 0)(1 . 4184)
102873 /* Prototype JavaScript framework, version 1.6.0
102874 * (c) 2005-2007 Sam Stephenson
102875 *
102876 * Prototype is freely distributable under the terms of an MIT-style license.
102877 * For details, see the Prototype web site: http://www.prototypejs.org/
102878 *
102879 *--------------------------------------------------------------------------*/
102880
102881 var Prototype = {
102882 Version: '1.6.0',
102883
102884 Browser: {
102885 IE: !!(window.attachEvent && !window.opera),
102886 Opera: !!window.opera,
102887 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
102888 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
102889 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
102890 },
102891
102892 BrowserFeatures: {
102893 XPath: !!document.evaluate,
102894 ElementExtensions: !!window.HTMLElement,
102895 SpecificElementExtensions:
102896 document.createElement('div').__proto__ &&
102897 document.createElement('div').__proto__ !==
102898 document.createElement('form').__proto__
102899 },
102900
102901 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
102902 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
102903
102904 emptyFunction: function() { },
102905 K: function(x) { return x }
102906 };
102907
102908 if (Prototype.Browser.MobileSafari)
102909 Prototype.BrowserFeatures.SpecificElementExtensions = false;
102910
102911 if (Prototype.Browser.WebKit)
102912 Prototype.BrowserFeatures.XPath = false;
102913
102914 /* Based on Alex Arnell's inheritance implementation. */
102915 var Class = {
102916 create: function() {
102917 var parent = null, properties = $A(arguments);
102918 if (Object.isFunction(properties[0]))
102919 parent = properties.shift();
102920
102921 function klass() {
102922 this.initialize.apply(this, arguments);
102923 }
102924
102925 Object.extend(klass, Class.Methods);
102926 klass.superclass = parent;
102927 klass.subclasses = [];
102928
102929 if (parent) {
102930 var subclass = function() { };
102931 subclass.prototype = parent.prototype;
102932 klass.prototype = new subclass;
102933 parent.subclasses.push(klass);
102934 }
102935
102936 for (var i = 0; i < properties.length; i++)
102937 klass.addMethods(properties[i]);
102938
102939 if (!klass.prototype.initialize)
102940 klass.prototype.initialize = Prototype.emptyFunction;
102941
102942 klass.prototype.constructor = klass;
102943
102944 return klass;
102945 }
102946 };
102947
102948 Class.Methods = {
102949 addMethods: function(source) {
102950 var ancestor = this.superclass && this.superclass.prototype;
102951 var properties = Object.keys(source);
102952
102953 if (!Object.keys({ toString: true }).length)
102954 properties.push("toString", "valueOf");
102955
102956 for (var i = 0, length = properties.length; i < length; i++) {
102957 var property = properties[i], value = source[property];
102958 if (ancestor && Object.isFunction(value) &&
102959 value.argumentNames().first() == "$super") {
102960 var method = value, value = Object.extend((function(m) {
102961 return function() { return ancestor[m].apply(this, arguments) };
102962 })(property).wrap(method), {
102963 valueOf: function() { return method },
102964 toString: function() { return method.toString() }
102965 });
102966 }
102967 this.prototype[property] = value;
102968 }
102969
102970 return this;
102971 }
102972 };
102973
102974 var Abstract = { };
102975
102976 Object.extend = function(destination, source) {
102977 for (var property in source)
102978 destination[property] = source[property];
102979 return destination;
102980 };
102981
102982 Object.extend(Object, {
102983 inspect: function(object) {
102984 try {
102985 if (object === undefined) return 'undefined';
102986 if (object === null) return 'null';
102987 return object.inspect ? object.inspect() : object.toString();
102988 } catch (e) {
102989 if (e instanceof RangeError) return '...';
102990 throw e;
102991 }
102992 },
102993
102994 toJSON: function(object) {
102995 var type = typeof object;
102996 switch (type) {
102997 case 'undefined':
102998 case 'function':
102999 case 'unknown': return;
103000 case 'boolean': return object.toString();
103001 }
103002
103003 if (object === null) return 'null';
103004 if (object.toJSON) return object.toJSON();
103005 if (Object.isElement(object)) return;
103006
103007 var results = [];
103008 for (var property in object) {
103009 var value = Object.toJSON(object[property]);
103010 if (value !== undefined)
103011 results.push(property.toJSON() + ': ' + value);
103012 }
103013
103014 return '{' + results.join(', ') + '}';
103015 },
103016
103017 toQueryString: function(object) {
103018 return $H(object).toQueryString();
103019 },
103020
103021 toHTML: function(object) {
103022 return object && object.toHTML ? object.toHTML() : String.interpret(object);
103023 },
103024
103025 keys: function(object) {
103026 var keys = [];
103027 for (var property in object)
103028 keys.push(property);
103029 return keys;
103030 },
103031
103032 values: function(object) {
103033 var values = [];
103034 for (var property in object)
103035 values.push(object[property]);
103036 return values;
103037 },
103038
103039 clone: function(object) {
103040 return Object.extend({ }, object);
103041 },
103042
103043 isElement: function(object) {
103044 return object && object.nodeType == 1;
103045 },
103046
103047 isArray: function(object) {
103048 return object && object.constructor === Array;
103049 },
103050
103051 isHash: function(object) {
103052 return object instanceof Hash;
103053 },
103054
103055 isFunction: function(object) {
103056 return typeof object == "function";
103057 },
103058
103059 isString: function(object) {
103060 return typeof object == "string";
103061 },
103062
103063 isNumber: function(object) {
103064 return typeof object == "number";
103065 },
103066
103067 isUndefined: function(object) {
103068 return typeof object == "undefined";
103069 }
103070 });
103071
103072 Object.extend(Function.prototype, {
103073 argumentNames: function() {
103074 var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
103075 return names.length == 1 && !names[0] ? [] : names;
103076 },
103077
103078 bind: function() {
103079 if (arguments.length < 2 && arguments[0] === undefined) return this;
103080 var __method = this, args = $A(arguments), object = args.shift();
103081 return function() {
103082 return __method.apply(object, args.concat($A(arguments)));
103083 }
103084 },
103085
103086 bindAsEventListener: function() {
103087 var __method = this, args = $A(arguments), object = args.shift();
103088 return function(event) {
103089 return __method.apply(object, [event || window.event].concat(args));
103090 }
103091 },
103092
103093 curry: function() {
103094 if (!arguments.length) return this;
103095 var __method = this, args = $A(arguments);
103096 return function() {
103097 return __method.apply(this, args.concat($A(arguments)));
103098 }
103099 },
103100
103101 delay: function() {
103102 var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
103103 return window.setTimeout(function() {
103104 return __method.apply(__method, args);
103105 }, timeout);
103106 },
103107
103108 wrap: function(wrapper) {
103109 var __method = this;
103110 return function() {
103111 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
103112 }
103113 },
103114
103115 methodize: function() {
103116 if (this._methodized) return this._methodized;
103117 var __method = this;
103118 return this._methodized = function() {
103119 return __method.apply(null, [this].concat($A(arguments)));
103120 };
103121 }
103122 });
103123
103124 Function.prototype.defer = Function.prototype.delay.curry(0.01);
103125
103126 Date.prototype.toJSON = function() {
103127 return '"' + this.getUTCFullYear() + '-' +
103128 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
103129 this.getUTCDate().toPaddedString(2) + 'T' +
103130 this.getUTCHours().toPaddedString(2) + ':' +
103131 this.getUTCMinutes().toPaddedString(2) + ':' +
103132 this.getUTCSeconds().toPaddedString(2) + 'Z"';
103133 };
103134
103135 var Try = {
103136 these: function() {
103137 var returnValue;
103138
103139 for (var i = 0, length = arguments.length; i < length; i++) {
103140 var lambda = arguments[i];
103141 try {
103142 returnValue = lambda();
103143 break;
103144 } catch (e) { }
103145 }
103146
103147 return returnValue;
103148 }
103149 };
103150
103151 RegExp.prototype.match = RegExp.prototype.test;
103152
103153 RegExp.escape = function(str) {
103154 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
103155 };
103156
103157 /*--------------------------------------------------------------------------*/
103158
103159 var PeriodicalExecuter = Class.create({
103160 initialize: function(callback, frequency) {
103161 this.callback = callback;
103162 this.frequency = frequency;
103163 this.currentlyExecuting = false;
103164
103165 this.registerCallback();
103166 },
103167
103168 registerCallback: function() {
103169 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
103170 },
103171
103172 execute: function() {
103173 this.callback(this);
103174 },
103175
103176 stop: function() {
103177 if (!this.timer) return;
103178 clearInterval(this.timer);
103179 this.timer = null;
103180 },
103181
103182 onTimerEvent: function() {
103183 if (!this.currentlyExecuting) {
103184 try {
103185 this.currentlyExecuting = true;
103186 this.execute();
103187 } finally {
103188 this.currentlyExecuting = false;
103189 }
103190 }
103191 }
103192 });
103193 Object.extend(String, {
103194 interpret: function(value) {
103195 return value == null ? '' : String(value);
103196 },
103197 specialChar: {
103198 '\b': '\\b',
103199 '\t': '\\t',
103200 '\n': '\\n',
103201 '\f': '\\f',
103202 '\r': '\\r',
103203 '\\': '\\\\'
103204 }
103205 });
103206
103207 Object.extend(String.prototype, {
103208 gsub: function(pattern, replacement) {
103209 var result = '', source = this, match;
103210 replacement = arguments.callee.prepareReplacement(replacement);
103211
103212 while (source.length > 0) {
103213 if (match = source.match(pattern)) {
103214 result += source.slice(0, match.index);
103215 result += String.interpret(replacement(match));
103216 source = source.slice(match.index + match[0].length);
103217 } else {
103218 result += source, source = '';
103219 }
103220 }
103221 return result;
103222 },
103223
103224 sub: function(pattern, replacement, count) {
103225 replacement = this.gsub.prepareReplacement(replacement);
103226 count = count === undefined ? 1 : count;
103227
103228 return this.gsub(pattern, function(match) {
103229 if (--count < 0) return match[0];
103230 return replacement(match);
103231 });
103232 },
103233
103234 scan: function(pattern, iterator) {
103235 this.gsub(pattern, iterator);
103236 return String(this);
103237 },
103238
103239 truncate: function(length, truncation) {
103240 length = length || 30;
103241 truncation = truncation === undefined ? '...' : truncation;
103242 return this.length > length ?
103243 this.slice(0, length - truncation.length) + truncation : String(this);
103244 },
103245
103246 strip: function() {
103247 return this.replace(/^\s+/, '').replace(/\s+$/, '');
103248 },
103249
103250 stripTags: function() {
103251 return this.replace(/<\/?[^>]+>/gi, '');
103252 },
103253
103254 stripScripts: function() {
103255 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
103256 },
103257
103258 extractScripts: function() {
103259 var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
103260 var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
103261 return (this.match(matchAll) || []).map(function(scriptTag) {
103262 return (scriptTag.match(matchOne) || ['', ''])[1];
103263 });
103264 },
103265
103266 evalScripts: function() {
103267 return this.extractScripts().map(function(script) { return eval(script) });
103268 },
103269
103270 escapeHTML: function() {
103271 var self = arguments.callee;
103272 self.text.data = this;
103273 return self.div.innerHTML;
103274 },
103275
103276 unescapeHTML: function() {
103277 var div = new Element('div');
103278 div.innerHTML = this.stripTags();
103279 return div.childNodes[0] ? (div.childNodes.length > 1 ?
103280 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
103281 div.childNodes[0].nodeValue) : '';
103282 },
103283
103284 toQueryParams: function(separator) {
103285 var match = this.strip().match(/([^?#]*)(#.*)?$/);
103286 if (!match) return { };
103287
103288 return match[1].split(separator || '&').inject({ }, function(hash, pair) {
103289 if ((pair = pair.split('='))[0]) {
103290 var key = decodeURIComponent(pair.shift());
103291 var value = pair.length > 1 ? pair.join('=') : pair[0];
103292 if (value != undefined) value = decodeURIComponent(value);
103293
103294 if (key in hash) {
103295 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
103296 hash[key].push(value);
103297 }
103298 else hash[key] = value;
103299 }
103300 return hash;
103301 });
103302 },
103303
103304 toArray: function() {
103305 return this.split('');
103306 },
103307
103308 succ: function() {
103309 return this.slice(0, this.length - 1) +
103310 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
103311 },
103312
103313 times: function(count) {
103314 return count < 1 ? '' : new Array(count + 1).join(this);
103315 },
103316
103317 camelize: function() {
103318 var parts = this.split('-'), len = parts.length;
103319 if (len == 1) return parts[0];
103320
103321 var camelized = this.charAt(0) == '-'
103322 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
103323 : parts[0];
103324
103325 for (var i = 1; i < len; i++)
103326 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
103327
103328 return camelized;
103329 },
103330
103331 capitalize: function() {
103332 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
103333 },
103334
103335 underscore: function() {
103336 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
103337 },
103338
103339 dasherize: function() {
103340 return this.gsub(/_/,'-');
103341 },
103342
103343 inspect: function(useDoubleQuotes) {
103344 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
103345 var character = String.specialChar[match[0]];
103346 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
103347 });
103348 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
103349 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
103350 },
103351
103352 toJSON: function() {
103353 return this.inspect(true);
103354 },
103355
103356 unfilterJSON: function(filter) {
103357 return this.sub(filter || Prototype.JSONFilter, '#{1}');
103358 },
103359
103360 isJSON: function() {
103361 var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
103362 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
103363 },
103364
103365 evalJSON: function(sanitize) {
103366 var json = this.unfilterJSON();
103367 try {
103368 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
103369 } catch (e) { }
103370 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
103371 },
103372
103373 include: function(pattern) {
103374 return this.indexOf(pattern) > -1;
103375 },
103376
103377 startsWith: function(pattern) {
103378 return this.indexOf(pattern) === 0;
103379 },
103380
103381 endsWith: function(pattern) {
103382 var d = this.length - pattern.length;
103383 return d >= 0 && this.lastIndexOf(pattern) === d;
103384 },
103385
103386 empty: function() {
103387 return this == '';
103388 },
103389
103390 blank: function() {
103391 return /^\s*$/.test(this);
103392 },
103393
103394 interpolate: function(object, pattern) {
103395 return new Template(this, pattern).evaluate(object);
103396 }
103397 });
103398
103399 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
103400 escapeHTML: function() {
103401 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
103402 },
103403 unescapeHTML: function() {
103404 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
103405 }
103406 });
103407
103408 String.prototype.gsub.prepareReplacement = function(replacement) {
103409 if (Object.isFunction(replacement)) return replacement;
103410 var template = new Template(replacement);
103411 return function(match) { return template.evaluate(match) };
103412 };
103413
103414 String.prototype.parseQuery = String.prototype.toQueryParams;
103415
103416 Object.extend(String.prototype.escapeHTML, {
103417 div: document.createElement('div'),
103418 text: document.createTextNode('')
103419 });
103420
103421 with (String.prototype.escapeHTML) div.appendChild(text);
103422
103423 var Template = Class.create({
103424 initialize: function(template, pattern) {
103425 this.template = template.toString();
103426 this.pattern = pattern || Template.Pattern;
103427 },
103428
103429 evaluate: function(object) {
103430 if (Object.isFunction(object.toTemplateReplacements))
103431 object = object.toTemplateReplacements();
103432
103433 return this.template.gsub(this.pattern, function(match) {
103434 if (object == null) return '';
103435
103436 var before = match[1] || '';
103437 if (before == '\\') return match[2];
103438
103439 var ctx = object, expr = match[3];
103440 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
103441 if (match == null) return before;
103442
103443 while (match != null) {
103444 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
103445 ctx = ctx[comp];
103446 if (null == ctx || '' == match[3]) break;
103447 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
103448 match = pattern.exec(expr);
103449 }
103450
103451 return before + String.interpret(ctx);
103452 }.bind(this));
103453 }
103454 });
103455 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
103456
103457 var $break = { };
103458
103459 var Enumerable = {
103460 each: function(iterator, context) {
103461 var index = 0;
103462 iterator = iterator.bind(context);
103463 try {
103464 this._each(function(value) {
103465 iterator(value, index++);
103466 });
103467 } catch (e) {
103468 if (e != $break) throw e;
103469 }
103470 return this;
103471 },
103472
103473 eachSlice: function(number, iterator, context) {
103474 iterator = iterator ? iterator.bind(context) : Prototype.K;
103475 var index = -number, slices = [], array = this.toArray();
103476 while ((index += number) < array.length)
103477 slices.push(array.slice(index, index+number));
103478 return slices.collect(iterator, context);
103479 },
103480
103481 all: function(iterator, context) {
103482 iterator = iterator ? iterator.bind(context) : Prototype.K;
103483 var result = true;
103484 this.each(function(value, index) {
103485 result = result && !!iterator(value, index);
103486 if (!result) throw $break;
103487 });
103488 return result;
103489 },
103490
103491 any: function(iterator, context) {
103492 iterator = iterator ? iterator.bind(context) : Prototype.K;
103493 var result = false;
103494 this.each(function(value, index) {
103495 if (result = !!iterator(value, index))
103496 throw $break;
103497 });
103498 return result;
103499 },
103500
103501 collect: function(iterator, context) {
103502 iterator = iterator ? iterator.bind(context) : Prototype.K;
103503 var results = [];
103504 this.each(function(value, index) {
103505 results.push(iterator(value, index));
103506 });
103507 return results;
103508 },
103509
103510 detect: function(iterator, context) {
103511 iterator = iterator.bind(context);
103512 var result;
103513 this.each(function(value, index) {
103514 if (iterator(value, index)) {
103515 result = value;
103516 throw $break;
103517 }
103518 });
103519 return result;
103520 },
103521
103522 findAll: function(iterator, context) {
103523 iterator = iterator.bind(context);
103524 var results = [];
103525 this.each(function(value, index) {
103526 if (iterator(value, index))
103527 results.push(value);
103528 });
103529 return results;
103530 },
103531
103532 grep: function(filter, iterator, context) {
103533 iterator = iterator ? iterator.bind(context) : Prototype.K;
103534 var results = [];
103535
103536 if (Object.isString(filter))
103537 filter = new RegExp(filter);
103538
103539 this.each(function(value, index) {
103540 if (filter.match(value))
103541 results.push(iterator(value, index));
103542 });
103543 return results;
103544 },
103545
103546 include: function(object) {
103547 if (Object.isFunction(this.indexOf))
103548 if (this.indexOf(object) != -1) return true;
103549
103550 var found = false;
103551 this.each(function(value) {
103552 if (value == object) {
103553 found = true;
103554 throw $break;
103555 }
103556 });
103557 return found;
103558 },
103559
103560 inGroupsOf: function(number, fillWith) {
103561 fillWith = fillWith === undefined ? null : fillWith;
103562 return this.eachSlice(number, function(slice) {
103563 while(slice.length < number) slice.push(fillWith);
103564 return slice;
103565 });
103566 },
103567
103568 inject: function(memo, iterator, context) {
103569 iterator = iterator.bind(context);
103570 this.each(function(value, index) {
103571 memo = iterator(memo, value, index);
103572 });
103573 return memo;
103574 },
103575
103576 invoke: function(method) {
103577 var args = $A(arguments).slice(1);
103578 return this.map(function(value) {
103579 return value[method].apply(value, args);
103580 });
103581 },
103582
103583 max: function(iterator, context) {
103584 iterator = iterator ? iterator.bind(context) : Prototype.K;
103585 var result;
103586 this.each(function(value, index) {
103587 value = iterator(value, index);
103588 if (result == undefined || value >= result)
103589 result = value;
103590 });
103591 return result;
103592 },
103593
103594 min: function(iterator, context) {
103595 iterator = iterator ? iterator.bind(context) : Prototype.K;
103596 var result;
103597 this.each(function(value, index) {
103598 value = iterator(value, index);
103599 if (result == undefined || value < result)
103600 result = value;
103601 });
103602 return result;
103603 },
103604
103605 partition: function(iterator, context) {
103606 iterator = iterator ? iterator.bind(context) : Prototype.K;
103607 var trues = [], falses = [];
103608 this.each(function(value, index) {
103609 (iterator(value, index) ?
103610 trues : falses).push(value);
103611 });
103612 return [trues, falses];
103613 },
103614
103615 pluck: function(property) {
103616 var results = [];
103617 this.each(function(value) {
103618 results.push(value[property]);
103619 });
103620 return results;
103621 },
103622
103623 reject: function(iterator, context) {
103624 iterator = iterator.bind(context);
103625 var results = [];
103626 this.each(function(value, index) {
103627 if (!iterator(value, index))
103628 results.push(value);
103629 });
103630 return results;
103631 },
103632
103633 sortBy: function(iterator, context) {
103634 iterator = iterator.bind(context);
103635 return this.map(function(value, index) {
103636 return {value: value, criteria: iterator(value, index)};
103637 }).sort(function(left, right) {
103638 var a = left.criteria, b = right.criteria;
103639 return a < b ? -1 : a > b ? 1 : 0;
103640 }).pluck('value');
103641 },
103642
103643 toArray: function() {
103644 return this.map();
103645 },
103646
103647 zip: function() {
103648 var iterator = Prototype.K, args = $A(arguments);
103649 if (Object.isFunction(args.last()))
103650 iterator = args.pop();
103651
103652 var collections = [this].concat(args).map($A);
103653 return this.map(function(value, index) {
103654 return iterator(collections.pluck(index));
103655 });
103656 },
103657
103658 size: function() {
103659 return this.toArray().length;
103660 },
103661
103662 inspect: function() {
103663 return '#<Enumerable:' + this.toArray().inspect() + '>';
103664 }
103665 };
103666
103667 Object.extend(Enumerable, {
103668 map: Enumerable.collect,
103669 find: Enumerable.detect,
103670 select: Enumerable.findAll,
103671 filter: Enumerable.findAll,
103672 member: Enumerable.include,
103673 entries: Enumerable.toArray,
103674 every: Enumerable.all,
103675 some: Enumerable.any
103676 });
103677 function $A(iterable) {
103678 if (!iterable) return [];
103679 if (iterable.toArray) return iterable.toArray();
103680 var length = iterable.length, results = new Array(length);
103681 while (length--) results[length] = iterable[length];
103682 return results;
103683 }
103684
103685 if (Prototype.Browser.WebKit) {
103686 function $A(iterable) {
103687 if (!iterable) return [];
103688 if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
103689 iterable.toArray) return iterable.toArray();
103690 var length = iterable.length, results = new Array(length);
103691 while (length--) results[length] = iterable[length];
103692 return results;
103693 }
103694 }
103695
103696 Array.from = $A;
103697
103698 Object.extend(Array.prototype, Enumerable);
103699
103700 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
103701
103702 Object.extend(Array.prototype, {
103703 _each: function(iterator) {
103704 for (var i = 0, length = this.length; i < length; i++)
103705 iterator(this[i]);
103706 },
103707
103708 clear: function() {
103709 this.length = 0;
103710 return this;
103711 },
103712
103713 first: function() {
103714 return this[0];
103715 },
103716
103717 last: function() {
103718 return this[this.length - 1];
103719 },
103720
103721 compact: function() {
103722 return this.select(function(value) {
103723 return value != null;
103724 });
103725 },
103726
103727 flatten: function() {
103728 return this.inject([], function(array, value) {
103729 return array.concat(Object.isArray(value) ?
103730 value.flatten() : [value]);
103731 });
103732 },
103733
103734 without: function() {
103735 var values = $A(arguments);
103736 return this.select(function(value) {
103737 return !values.include(value);
103738 });
103739 },
103740
103741 reverse: function(inline) {
103742 return (inline !== false ? this : this.toArray())._reverse();
103743 },
103744
103745 reduce: function() {
103746 return this.length > 1 ? this : this[0];
103747 },
103748
103749 uniq: function(sorted) {
103750 return this.inject([], function(array, value, index) {
103751 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
103752 array.push(value);
103753 return array;
103754 });
103755 },
103756
103757 intersect: function(array) {
103758 return this.uniq().findAll(function(item) {
103759 return array.detect(function(value) { return item === value });
103760 });
103761 },
103762
103763 clone: function() {
103764 return [].concat(this);
103765 },
103766
103767 size: function() {
103768 return this.length;
103769 },
103770
103771 inspect: function() {
103772 return '[' + this.map(Object.inspect).join(', ') + ']';
103773 },
103774
103775 toJSON: function() {
103776 var results = [];
103777 this.each(function(object) {
103778 var value = Object.toJSON(object);
103779 if (value !== undefined) results.push(value);
103780 });
103781 return '[' + results.join(', ') + ']';
103782 }
103783 });
103784
103785 // use native browser JS 1.6 implementation if available
103786 if (Object.isFunction(Array.prototype.forEach))
103787 Array.prototype._each = Array.prototype.forEach;
103788
103789 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
103790 i || (i = 0);
103791 var length = this.length;
103792 if (i < 0) i = length + i;
103793 for (; i < length; i++)
103794 if (this[i] === item) return i;
103795 return -1;
103796 };
103797
103798 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
103799 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
103800 var n = this.slice(0, i).reverse().indexOf(item);
103801 return (n < 0) ? n : i - n - 1;
103802 };
103803
103804 Array.prototype.toArray = Array.prototype.clone;
103805
103806 function $w(string) {
103807 if (!Object.isString(string)) return [];
103808 string = string.strip();
103809 return string ? string.split(/\s+/) : [];
103810 }
103811
103812 if (Prototype.Browser.Opera){
103813 Array.prototype.concat = function() {
103814 var array = [];
103815 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
103816 for (var i = 0, length = arguments.length; i < length; i++) {
103817 if (Object.isArray(arguments[i])) {
103818 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
103819 array.push(arguments[i][j]);
103820 } else {
103821 array.push(arguments[i]);
103822 }
103823 }
103824 return array;
103825 };
103826 }
103827 Object.extend(Number.prototype, {
103828 toColorPart: function() {
103829 return this.toPaddedString(2, 16);
103830 },
103831
103832 succ: function() {
103833 return this + 1;
103834 },
103835
103836 times: function(iterator) {
103837 $R(0, this, true).each(iterator);
103838 return this;
103839 },
103840
103841 toPaddedString: function(length, radix) {
103842 var string = this.toString(radix || 10);
103843 return '0'.times(length - string.length) + string;
103844 },
103845
103846 toJSON: function() {
103847 return isFinite(this) ? this.toString() : 'null';
103848 }
103849 });
103850
103851 $w('abs round ceil floor').each(function(method){
103852 Number.prototype[method] = Math[method].methodize();
103853 });
103854 function $H(object) {
103855 return new Hash(object);
103856 };
103857
103858 var Hash = Class.create(Enumerable, (function() {
103859 if (function() {
103860 var i = 0, Test = function(value) { this.key = value };
103861 Test.prototype.key = 'foo';
103862 for (var property in new Test('bar')) i++;
103863 return i > 1;
103864 }()) {
103865 function each(iterator) {
103866 var cache = [];
103867 for (var key in this._object) {
103868 var value = this._object[key];
103869 if (cache.include(key)) continue;
103870 cache.push(key);
103871 var pair = [key, value];
103872 pair.key = key;
103873 pair.value = value;
103874 iterator(pair);
103875 }
103876 }
103877 } else {
103878 function each(iterator) {
103879 for (var key in this._object) {
103880 var value = this._object[key], pair = [key, value];
103881 pair.key = key;
103882 pair.value = value;
103883 iterator(pair);
103884 }
103885 }
103886 }
103887
103888 function toQueryPair(key, value) {
103889 if (Object.isUndefined(value)) return key;
103890 return key + '=' + encodeURIComponent(String.interpret(value));
103891 }
103892
103893 return {
103894 initialize: function(object) {
103895 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
103896 },
103897
103898 _each: each,
103899
103900 set: function(key, value) {
103901 return this._object[key] = value;
103902 },
103903
103904 get: function(key) {
103905 return this._object[key];
103906 },
103907
103908 unset: function(key) {
103909 var value = this._object[key];
103910 delete this._object[key];
103911 return value;
103912 },
103913
103914 toObject: function() {
103915 return Object.clone(this._object);
103916 },
103917
103918 keys: function() {
103919 return this.pluck('key');
103920 },
103921
103922 values: function() {
103923 return this.pluck('value');
103924 },
103925
103926 index: function(value) {
103927 var match = this.detect(function(pair) {
103928 return pair.value === value;
103929 });
103930 return match && match.key;
103931 },
103932
103933 merge: function(object) {
103934 return this.clone().update(object);
103935 },
103936
103937 update: function(object) {
103938 return new Hash(object).inject(this, function(result, pair) {
103939 result.set(pair.key, pair.value);
103940 return result;
103941 });
103942 },
103943
103944 toQueryString: function() {
103945 return this.map(function(pair) {
103946 var key = encodeURIComponent(pair.key), values = pair.value;
103947
103948 if (values && typeof values == 'object') {
103949 if (Object.isArray(values))
103950 return values.map(toQueryPair.curry(key)).join('&');
103951 }
103952 return toQueryPair(key, values);
103953 }).join('&');
103954 },
103955
103956 inspect: function() {
103957 return '#<Hash:{' + this.map(function(pair) {
103958 return pair.map(Object.inspect).join(': ');
103959 }).join(', ') + '}>';
103960 },
103961
103962 toJSON: function() {
103963 return Object.toJSON(this.toObject());
103964 },
103965
103966 clone: function() {
103967 return new Hash(this);
103968 }
103969 }
103970 })());
103971
103972 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
103973 Hash.from = $H;
103974 var ObjectRange = Class.create(Enumerable, {
103975 initialize: function(start, end, exclusive) {
103976 this.start = start;
103977 this.end = end;
103978 this.exclusive = exclusive;
103979 },
103980
103981 _each: function(iterator) {
103982 var value = this.start;
103983 while (this.include(value)) {
103984 iterator(value);
103985 value = value.succ();
103986 }
103987 },
103988
103989 include: function(value) {
103990 if (value < this.start)
103991 return false;
103992 if (this.exclusive)
103993 return value < this.end;
103994 return value <= this.end;
103995 }
103996 });
103997
103998 var $R = function(start, end, exclusive) {
103999 return new ObjectRange(start, end, exclusive);
104000 };
104001
104002 var Ajax = {
104003 getTransport: function() {
104004 return Try.these(
104005 function() {return new XMLHttpRequest()},
104006 function() {return new ActiveXObject('Msxml2.XMLHTTP')},
104007 function() {return new ActiveXObject('Microsoft.XMLHTTP')}
104008 ) || false;
104009 },
104010
104011 activeRequestCount: 0
104012 };
104013
104014 Ajax.Responders = {
104015 responders: [],
104016
104017 _each: function(iterator) {
104018 this.responders._each(iterator);
104019 },
104020
104021 register: function(responder) {
104022 if (!this.include(responder))
104023 this.responders.push(responder);
104024 },
104025
104026 unregister: function(responder) {
104027 this.responders = this.responders.without(responder);
104028 },
104029
104030 dispatch: function(callback, request, transport, json) {
104031 this.each(function(responder) {
104032 if (Object.isFunction(responder[callback])) {
104033 try {
104034 responder[callback].apply(responder, [request, transport, json]);
104035 } catch (e) { }
104036 }
104037 });
104038 }
104039 };
104040
104041 Object.extend(Ajax.Responders, Enumerable);
104042
104043 Ajax.Responders.register({
104044 onCreate: function() { Ajax.activeRequestCount++ },
104045 onComplete: function() { Ajax.activeRequestCount-- }
104046 });
104047
104048 Ajax.Base = Class.create({
104049 initialize: function(options) {
104050 this.options = {
104051 method: 'post',
104052 asynchronous: true,
104053 contentType: 'application/x-www-form-urlencoded',
104054 encoding: 'UTF-8',
104055 parameters: '',
104056 evalJSON: true,
104057 evalJS: true
104058 };
104059 Object.extend(this.options, options || { });
104060
104061 this.options.method = this.options.method.toLowerCase();
104062 if (Object.isString(this.options.parameters))
104063 this.options.parameters = this.options.parameters.toQueryParams();
104064 }
104065 });
104066
104067 Ajax.Request = Class.create(Ajax.Base, {
104068 _complete: false,
104069
104070 initialize: function($super, url, options) {
104071 $super(options);
104072 this.transport = Ajax.getTransport();
104073 this.request(url);
104074 },
104075
104076 request: function(url) {
104077 this.url = url;
104078 this.method = this.options.method;
104079 var params = Object.clone(this.options.parameters);
104080
104081 if (!['get', 'post'].include(this.method)) {
104082 // simulate other verbs over post
104083 params['_method'] = this.method;
104084 this.method = 'post';
104085 }
104086
104087 this.parameters = params;
104088
104089 if (params = Object.toQueryString(params)) {
104090 // when GET, append parameters to URL
104091 if (this.method == 'get')
104092 this.url += (this.url.include('?') ? '&' : '?') + params;
104093 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
104094 params += '&_=';
104095 }
104096
104097 try {
104098 var response = new Ajax.Response(this);
104099 if (this.options.onCreate) this.options.onCreate(response);
104100 Ajax.Responders.dispatch('onCreate', this, response);
104101
104102 this.transport.open(this.method.toUpperCase(), this.url,
104103 this.options.asynchronous);
104104
104105 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
104106
104107 this.transport.onreadystatechange = this.onStateChange.bind(this);
104108 this.setRequestHeaders();
104109
104110 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
104111 this.transport.send(this.body);
104112
104113 /* Force Firefox to handle ready state 4 for synchronous requests */
104114 if (!this.options.asynchronous && this.transport.overrideMimeType)
104115 this.onStateChange();
104116
104117 }
104118 catch (e) {
104119 this.dispatchException(e);
104120 }
104121 },
104122
104123 onStateChange: function() {
104124 var readyState = this.transport.readyState;
104125 if (readyState > 1 && !((readyState == 4) && this._complete))
104126 this.respondToReadyState(this.transport.readyState);
104127 },
104128
104129 setRequestHeaders: function() {
104130 var headers = {
104131 'X-Requested-With': 'XMLHttpRequest',
104132 'X-Prototype-Version': Prototype.Version,
104133 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
104134 };
104135
104136 if (this.method == 'post') {
104137 headers['Content-type'] = this.options.contentType +
104138 (this.options.encoding ? '; charset=' + this.options.encoding : '');
104139
104140 /* Force "Connection: close" for older Mozilla browsers to work
104141 * around a bug where XMLHttpRequest sends an incorrect
104142 * Content-length header. See Mozilla Bugzilla #246651.
104143 */
104144 if (this.transport.overrideMimeType &&
104145 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
104146 headers['Connection'] = 'close';
104147 }
104148
104149 // user-defined headers
104150 if (typeof this.options.requestHeaders == 'object') {
104151 var extras = this.options.requestHeaders;
104152
104153 if (Object.isFunction(extras.push))
104154 for (var i = 0, length = extras.length; i < length; i += 2)
104155 headers[extras[i]] = extras[i+1];
104156 else
104157 $H(extras).each(function(pair) { headers[pair.key] = pair.value });
104158 }
104159
104160 for (var name in headers)
104161 this.transport.setRequestHeader(name, headers[name]);
104162 },
104163
104164 success: function() {
104165 var status = this.getStatus();
104166 return !status || (status >= 200 && status < 300);
104167 },
104168
104169 getStatus: function() {
104170 try {
104171 return this.transport.status || 0;
104172 } catch (e) { return 0 }
104173 },
104174
104175 respondToReadyState: function(readyState) {
104176 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
104177
104178 if (state == 'Complete') {
104179 try {
104180 this._complete = true;
104181 (this.options['on' + response.status]
104182 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
104183 || Prototype.emptyFunction)(response, response.headerJSON);
104184 } catch (e) {
104185 this.dispatchException(e);
104186 }
104187
104188 var contentType = response.getHeader('Content-type');
104189 if (this.options.evalJS == 'force'
104190 || (this.options.evalJS && contentType
104191 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
104192 this.evalResponse();
104193 }
104194
104195 try {
104196 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
104197 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
104198 } catch (e) {
104199 this.dispatchException(e);
104200 }
104201
104202 if (state == 'Complete') {
104203 // avoid memory leak in MSIE: clean up
104204 this.transport.onreadystatechange = Prototype.emptyFunction;
104205 }
104206 },
104207
104208 getHeader: function(name) {
104209 try {
104210 return this.transport.getResponseHeader(name);
104211 } catch (e) { return null }
104212 },
104213
104214 evalResponse: function() {
104215 try {
104216 return eval((this.transport.responseText || '').unfilterJSON());
104217 } catch (e) {
104218 this.dispatchException(e);
104219 }
104220 },
104221
104222 dispatchException: function(exception) {
104223 (this.options.onException || Prototype.emptyFunction)(this, exception);
104224 Ajax.Responders.dispatch('onException', this, exception);
104225 }
104226 });
104227
104228 Ajax.Request.Events =
104229 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
104230
104231 Ajax.Response = Class.create({
104232 initialize: function(request){
104233 this.request = request;
104234 var transport = this.transport = request.transport,
104235 readyState = this.readyState = transport.readyState;
104236
104237 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
104238 this.status = this.getStatus();
104239 this.statusText = this.getStatusText();
104240 this.responseText = String.interpret(transport.responseText);
104241 this.headerJSON = this._getHeaderJSON();
104242 }
104243
104244 if(readyState == 4) {
104245 var xml = transport.responseXML;
104246 this.responseXML = xml === undefined ? null : xml;
104247 this.responseJSON = this._getResponseJSON();
104248 }
104249 },
104250
104251 status: 0,
104252 statusText: '',
104253
104254 getStatus: Ajax.Request.prototype.getStatus,
104255
104256 getStatusText: function() {
104257 try {
104258 return this.transport.statusText || '';
104259 } catch (e) { return '' }
104260 },
104261
104262 getHeader: Ajax.Request.prototype.getHeader,
104263
104264 getAllHeaders: function() {
104265 try {
104266 return this.getAllResponseHeaders();
104267 } catch (e) { return null }
104268 },
104269
104270 getResponseHeader: function(name) {
104271 return this.transport.getResponseHeader(name);
104272 },
104273
104274 getAllResponseHeaders: function() {
104275 return this.transport.getAllResponseHeaders();
104276 },
104277
104278 _getHeaderJSON: function() {
104279 var json = this.getHeader('X-JSON');
104280 if (!json) return null;
104281 json = decodeURIComponent(escape(json));
104282 try {
104283 return json.evalJSON(this.request.options.sanitizeJSON);
104284 } catch (e) {
104285 this.request.dispatchException(e);
104286 }
104287 },
104288
104289 _getResponseJSON: function() {
104290 var options = this.request.options;
104291 if (!options.evalJSON || (options.evalJSON != 'force' &&
104292 !(this.getHeader('Content-type') || '').include('application/json')))
104293 return null;
104294 try {
104295 return this.transport.responseText.evalJSON(options.sanitizeJSON);
104296 } catch (e) {
104297 this.request.dispatchException(e);
104298 }
104299 }
104300 });
104301
104302 Ajax.Updater = Class.create(Ajax.Request, {
104303 initialize: function($super, container, url, options) {
104304 this.container = {
104305 success: (container.success || container),
104306 failure: (container.failure || (container.success ? null : container))
104307 };
104308
104309 options = options || { };
104310 var onComplete = options.onComplete;
104311 options.onComplete = (function(response, param) {
104312 this.updateContent(response.responseText);
104313 if (Object.isFunction(onComplete)) onComplete(response, param);
104314 }).bind(this);
104315
104316 $super(url, options);
104317 },
104318
104319 updateContent: function(responseText) {
104320 var receiver = this.container[this.success() ? 'success' : 'failure'],
104321 options = this.options;
104322
104323 if (!options.evalScripts) responseText = responseText.stripScripts();
104324
104325 if (receiver = $(receiver)) {
104326 if (options.insertion) {
104327 if (Object.isString(options.insertion)) {
104328 var insertion = { }; insertion[options.insertion] = responseText;
104329 receiver.insert(insertion);
104330 }
104331 else options.insertion(receiver, responseText);
104332 }
104333 else receiver.update(responseText);
104334 }
104335
104336 if (this.success()) {
104337 if (this.onComplete) this.onComplete.bind(this).defer();
104338 }
104339 }
104340 });
104341
104342 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
104343 initialize: function($super, container, url, options) {
104344 $super(options);
104345 this.onComplete = this.options.onComplete;
104346
104347 this.frequency = (this.options.frequency || 2);
104348 this.decay = (this.options.decay || 1);
104349
104350 this.updater = { };
104351 this.container = container;
104352 this.url = url;
104353
104354 this.start();
104355 },
104356
104357 start: function() {
104358 this.options.onComplete = this.updateComplete.bind(this);
104359 this.onTimerEvent();
104360 },
104361
104362 stop: function() {
104363 this.updater.options.onComplete = undefined;
104364 clearTimeout(this.timer);
104365 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
104366 },
104367
104368 updateComplete: function(response) {
104369 if (this.options.decay) {
104370 this.decay = (response.responseText == this.lastText ?
104371 this.decay * this.options.decay : 1);
104372
104373 this.lastText = response.responseText;
104374 }
104375 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
104376 },
104377
104378 onTimerEvent: function() {
104379 this.updater = new Ajax.Updater(this.container, this.url, this.options);
104380 }
104381 });
104382 function $(element) {
104383 if (arguments.length > 1) {
104384 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
104385 elements.push($(arguments[i]));
104386 return elements;
104387 }
104388 if (Object.isString(element))
104389 element = document.getElementById(element);
104390 return Element.extend(element);
104391 }
104392
104393 if (Prototype.BrowserFeatures.XPath) {
104394 document._getElementsByXPath = function(expression, parentElement) {
104395 var results = [];
104396 var query = document.evaluate(expression, $(parentElement) || document,
104397 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
104398 for (var i = 0, length = query.snapshotLength; i < length; i++)
104399 results.push(Element.extend(query.snapshotItem(i)));
104400 return results;
104401 };
104402 }
104403
104404 /*--------------------------------------------------------------------------*/
104405
104406 if (!window.Node) var Node = { };
104407
104408 if (!Node.ELEMENT_NODE) {
104409 // DOM level 2 ECMAScript Language Binding
104410 Object.extend(Node, {
104411 ELEMENT_NODE: 1,
104412 ATTRIBUTE_NODE: 2,
104413 TEXT_NODE: 3,
104414 CDATA_SECTION_NODE: 4,
104415 ENTITY_REFERENCE_NODE: 5,
104416 ENTITY_NODE: 6,
104417 PROCESSING_INSTRUCTION_NODE: 7,
104418 COMMENT_NODE: 8,
104419 DOCUMENT_NODE: 9,
104420 DOCUMENT_TYPE_NODE: 10,
104421 DOCUMENT_FRAGMENT_NODE: 11,
104422 NOTATION_NODE: 12
104423 });
104424 }
104425
104426 (function() {
104427 var element = this.Element;
104428 this.Element = function(tagName, attributes) {
104429 attributes = attributes || { };
104430 tagName = tagName.toLowerCase();
104431 var cache = Element.cache;
104432 if (Prototype.Browser.IE && attributes.name) {
104433 tagName = '<' + tagName + ' name="' + attributes.name + '">';
104434 delete attributes.name;
104435 return Element.writeAttribute(document.createElement(tagName), attributes);
104436 }
104437 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
104438 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
104439 };
104440 Object.extend(this.Element, element || { });
104441 }).call(window);
104442
104443 Element.cache = { };
104444
104445 Element.Methods = {
104446 visible: function(element) {
104447 return $(element).style.display != 'none';
104448 },
104449
104450 toggle: function(element) {
104451 element = $(element);
104452 Element[Element.visible(element) ? 'hide' : 'show'](element);
104453 return element;
104454 },
104455
104456 hide: function(element) {
104457 $(element).style.display = 'none';
104458 return element;
104459 },
104460
104461 show: function(element) {
104462 $(element).style.display = '';
104463 return element;
104464 },
104465
104466 remove: function(element) {
104467 element = $(element);
104468 element.parentNode.removeChild(element);
104469 return element;
104470 },
104471
104472 update: function(element, content) {
104473 element = $(element);
104474 if (content && content.toElement) content = content.toElement();
104475 if (Object.isElement(content)) return element.update().insert(content);
104476 content = Object.toHTML(content);
104477 element.innerHTML = content.stripScripts();
104478 content.evalScripts.bind(content).defer();
104479 return element;
104480 },
104481
104482 replace: function(element, content) {
104483 element = $(element);
104484 if (content && content.toElement) content = content.toElement();
104485 else if (!Object.isElement(content)) {
104486 content = Object.toHTML(content);
104487 var range = element.ownerDocument.createRange();
104488 range.selectNode(element);
104489 content.evalScripts.bind(content).defer();
104490 content = range.createContextualFragment(content.stripScripts());
104491 }
104492 element.parentNode.replaceChild(content, element);
104493 return element;
104494 },
104495
104496 insert: function(element, insertions) {
104497 element = $(element);
104498
104499 if (Object.isString(insertions) || Object.isNumber(insertions) ||
104500 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
104501 insertions = {bottom:insertions};
104502
104503 var content, t, range;
104504
104505 for (position in insertions) {
104506 content = insertions[position];
104507 position = position.toLowerCase();
104508 t = Element._insertionTranslations[position];
104509
104510 if (content && content.toElement) content = content.toElement();
104511 if (Object.isElement(content)) {
104512 t.insert(element, content);
104513 continue;
104514 }
104515
104516 content = Object.toHTML(content);
104517
104518 range = element.ownerDocument.createRange();
104519 t.initializeRange(element, range);
104520 t.insert(element, range.createContextualFragment(content.stripScripts()));
104521
104522 content.evalScripts.bind(content).defer();
104523 }
104524
104525 return element;
104526 },
104527
104528 wrap: function(element, wrapper, attributes) {
104529 element = $(element);
104530 if (Object.isElement(wrapper))
104531 $(wrapper).writeAttribute(attributes || { });
104532 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
104533 else wrapper = new Element('div', wrapper);
104534 if (element.parentNode)
104535 element.parentNode.replaceChild(wrapper, element);
104536 wrapper.appendChild(element);
104537 return wrapper;
104538 },
104539
104540 inspect: function(element) {
104541 element = $(element);
104542 var result = '<' + element.tagName.toLowerCase();
104543 $H({'id': 'id', 'className': 'class'}).each(function(pair) {
104544 var property = pair.first(), attribute = pair.last();
104545 var value = (element[property] || '').toString();
104546 if (value) result += ' ' + attribute + '=' + value.inspect(true);
104547 });
104548 return result + '>';
104549 },
104550
104551 recursivelyCollect: function(element, property) {
104552 element = $(element);
104553 var elements = [];
104554 while (element = element[property])
104555 if (element.nodeType == 1)
104556 elements.push(Element.extend(element));
104557 return elements;
104558 },
104559
104560 ancestors: function(element) {
104561 return $(element).recursivelyCollect('parentNode');
104562 },
104563
104564 descendants: function(element) {
104565 return $A($(element).getElementsByTagName('*')).each(Element.extend);
104566 },
104567
104568 firstDescendant: function(element) {
104569 element = $(element).firstChild;
104570 while (element && element.nodeType != 1) element = element.nextSibling;
104571 return $(element);
104572 },
104573
104574 immediateDescendants: function(element) {
104575 if (!(element = $(element).firstChild)) return [];
104576 while (element && element.nodeType != 1) element = element.nextSibling;
104577 if (element) return [element].concat($(element).nextSiblings());
104578 return [];
104579 },
104580
104581 previousSiblings: function(element) {
104582 return $(element).recursivelyCollect('previousSibling');
104583 },
104584
104585 nextSiblings: function(element) {
104586 return $(element).recursivelyCollect('nextSibling');
104587 },
104588
104589 siblings: function(element) {
104590 element = $(element);
104591 return element.previousSiblings().reverse().concat(element.nextSiblings());
104592 },
104593
104594 match: function(element, selector) {
104595 if (Object.isString(selector))
104596 selector = new Selector(selector);
104597 return selector.match($(element));
104598 },
104599
104600 up: function(element, expression, index) {
104601 element = $(element);
104602 if (arguments.length == 1) return $(element.parentNode);
104603 var ancestors = element.ancestors();
104604 return expression ? Selector.findElement(ancestors, expression, index) :
104605 ancestors[index || 0];
104606 },
104607
104608 down: function(element, expression, index) {
104609 element = $(element);
104610 if (arguments.length == 1) return element.firstDescendant();
104611 var descendants = element.descendants();
104612 return expression ? Selector.findElement(descendants, expression, index) :
104613 descendants[index || 0];
104614 },
104615
104616 previous: function(element, expression, index) {
104617 element = $(element);
104618 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
104619 var previousSiblings = element.previousSiblings();
104620 return expression ? Selector.findElement(previousSiblings, expression, index) :
104621 previousSiblings[index || 0];
104622 },
104623
104624 next: function(element, expression, index) {
104625 element = $(element);
104626 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
104627 var nextSiblings = element.nextSiblings();
104628 return expression ? Selector.findElement(nextSiblings, expression, index) :
104629 nextSiblings[index || 0];
104630 },
104631
104632 select: function() {
104633 var args = $A(arguments), element = $(args.shift());
104634 return Selector.findChildElements(element, args);
104635 },
104636
104637 adjacent: function() {
104638 var args = $A(arguments), element = $(args.shift());
104639 return Selector.findChildElements(element.parentNode, args).without(element);
104640 },
104641
104642 identify: function(element) {
104643 element = $(element);
104644 var id = element.readAttribute('id'), self = arguments.callee;
104645 if (id) return id;
104646 do { id = 'anonymous_element_' + self.counter++ } while ($(id));
104647 element.writeAttribute('id', id);
104648 return id;
104649 },
104650
104651 readAttribute: function(element, name) {
104652 element = $(element);
104653 if (Prototype.Browser.IE) {
104654 var t = Element._attributeTranslations.read;
104655 if (t.values[name]) return t.values[name](element, name);
104656 if (t.names[name]) name = t.names[name];
104657 if (name.include(':')) {
104658 return (!element.attributes || !element.attributes[name]) ? null :
104659 element.attributes[name].value;
104660 }
104661 }
104662 return element.getAttribute(name);
104663 },
104664
104665 writeAttribute: function(element, name, value) {
104666 element = $(element);
104667 var attributes = { }, t = Element._attributeTranslations.write;
104668
104669 if (typeof name == 'object') attributes = name;
104670 else attributes[name] = value === undefined ? true : value;
104671
104672 for (var attr in attributes) {
104673 var name = t.names[attr] || attr, value = attributes[attr];
104674 if (t.values[attr]) name = t.values[attr](element, value);
104675 if (value === false || value === null)
104676 element.removeAttribute(name);
104677 else if (value === true)
104678 element.setAttribute(name, name);
104679 else element.setAttribute(name, value);
104680 }
104681 return element;
104682 },
104683
104684 getHeight: function(element) {
104685 return $(element).getDimensions().height;
104686 },
104687
104688 getWidth: function(element) {
104689 return $(element).getDimensions().width;
104690 },
104691
104692 classNames: function(element) {
104693 return new Element.ClassNames(element);
104694 },
104695
104696 hasClassName: function(element, className) {
104697 if (!(element = $(element))) return;
104698 var elementClassName = element.className;
104699 return (elementClassName.length > 0 && (elementClassName == className ||
104700 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
104701 },
104702
104703 addClassName: function(element, className) {
104704 if (!(element = $(element))) return;
104705 if (!element.hasClassName(className))
104706 element.className += (element.className ? ' ' : '') + className;
104707 return element;
104708 },
104709
104710 removeClassName: function(element, className) {
104711 if (!(element = $(element))) return;
104712 element.className = element.className.replace(
104713 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
104714 return element;
104715 },
104716
104717 toggleClassName: function(element, className) {
104718 if (!(element = $(element))) return;
104719 return element[element.hasClassName(className) ?
104720 'removeClassName' : 'addClassName'](className);
104721 },
104722
104723 // removes whitespace-only text node children
104724 cleanWhitespace: function(element) {
104725 element = $(element);
104726 var node = element.firstChild;
104727 while (node) {
104728 var nextNode = node.nextSibling;
104729 if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
104730 element.removeChild(node);
104731 node = nextNode;
104732 }
104733 return element;
104734 },
104735
104736 empty: function(element) {
104737 return $(element).innerHTML.blank();
104738 },
104739
104740 descendantOf: function(element, ancestor) {
104741 element = $(element), ancestor = $(ancestor);
104742
104743 if (element.compareDocumentPosition)
104744 return (element.compareDocumentPosition(ancestor) & 8) === 8;
104745
104746 if (element.sourceIndex && !Prototype.Browser.Opera) {
104747 var e = element.sourceIndex, a = ancestor.sourceIndex,
104748 nextAncestor = ancestor.nextSibling;
104749 if (!nextAncestor) {
104750 do { ancestor = ancestor.parentNode; }
104751 while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
104752 }
104753 if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
104754 }
104755
104756 while (element = element.parentNode)
104757 if (element == ancestor) return true;
104758 return false;
104759 },
104760
104761 scrollTo: function(element) {
104762 element = $(element);
104763 var pos = element.cumulativeOffset();
104764 window.scrollTo(pos[0], pos[1]);
104765 return element;
104766 },
104767
104768 getStyle: function(element, style) {
104769 element = $(element);
104770 style = style == 'float' ? 'cssFloat' : style.camelize();
104771 var value = element.style[style];
104772 if (!value) {
104773 var css = document.defaultView.getComputedStyle(element, null);
104774 value = css ? css[style] : null;
104775 }
104776 if (style == 'opacity') return value ? parseFloat(value) : 1.0;
104777 return value == 'auto' ? null : value;
104778 },
104779
104780 getOpacity: function(element) {
104781 return $(element).getStyle('opacity');
104782 },
104783
104784 setStyle: function(element, styles) {
104785 element = $(element);
104786 var elementStyle = element.style, match;
104787 if (Object.isString(styles)) {
104788 element.style.cssText += ';' + styles;
104789 return styles.include('opacity') ?
104790 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
104791 }
104792 for (var property in styles)
104793 if (property == 'opacity') element.setOpacity(styles[property]);
104794 else
104795 elementStyle[(property == 'float' || property == 'cssFloat') ?
104796 (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
104797 property] = styles[property];
104798
104799 return element;
104800 },
104801
104802 setOpacity: function(element, value) {
104803 element = $(element);
104804 element.style.opacity = (value == 1 || value === '') ? '' :
104805 (value < 0.00001) ? 0 : value;
104806 return element;
104807 },
104808
104809 getDimensions: function(element) {
104810 element = $(element);
104811 var display = $(element).getStyle('display');
104812 if (display != 'none' && display != null) // Safari bug
104813 return {width: element.offsetWidth, height: element.offsetHeight};
104814
104815 // All *Width and *Height properties give 0 on elements with display none,
104816 // so enable the element temporarily
104817 var els = element.style;
104818 var originalVisibility = els.visibility;
104819 var originalPosition = els.position;
104820 var originalDisplay = els.display;
104821 els.visibility = 'hidden';
104822 els.position = 'absolute';
104823 els.display = 'block';
104824 var originalWidth = element.clientWidth;
104825 var originalHeight = element.clientHeight;
104826 els.display = originalDisplay;
104827 els.position = originalPosition;
104828 els.visibility = originalVisibility;
104829 return {width: originalWidth, height: originalHeight};
104830 },
104831
104832 makePositioned: function(element) {
104833 element = $(element);
104834 var pos = Element.getStyle(element, 'position');
104835 if (pos == 'static' || !pos) {
104836 element._madePositioned = true;
104837 element.style.position = 'relative';
104838 // Opera returns the offset relative to the positioning context, when an
104839 // element is position relative but top and left have not been defined
104840 if (window.opera) {
104841 element.style.top = 0;
104842 element.style.left = 0;
104843 }
104844 }
104845 return element;
104846 },
104847
104848 undoPositioned: function(element) {
104849 element = $(element);
104850 if (element._madePositioned) {
104851 element._madePositioned = undefined;
104852 element.style.position =
104853 element.style.top =
104854 element.style.left =
104855 element.style.bottom =
104856 element.style.right = '';
104857 }
104858 return element;
104859 },
104860
104861 makeClipping: function(element) {
104862 element = $(element);
104863 if (element._overflow) return element;
104864 element._overflow = Element.getStyle(element, 'overflow') || 'auto';
104865 if (element._overflow !== 'hidden')
104866 element.style.overflow = 'hidden';
104867 return element;
104868 },
104869
104870 undoClipping: function(element) {
104871 element = $(element);
104872 if (!element._overflow) return element;
104873 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
104874 element._overflow = null;
104875 return element;
104876 },
104877
104878 cumulativeOffset: function(element) {
104879 var valueT = 0, valueL = 0;
104880 do {
104881 valueT += element.offsetTop || 0;
104882 valueL += element.offsetLeft || 0;
104883 element = element.offsetParent;
104884 } while (element);
104885 return Element._returnOffset(valueL, valueT);
104886 },
104887
104888 positionedOffset: function(element) {
104889 var valueT = 0, valueL = 0;
104890 do {
104891 valueT += element.offsetTop || 0;
104892 valueL += element.offsetLeft || 0;
104893 element = element.offsetParent;
104894 if (element) {
104895 if (element.tagName == 'BODY') break;
104896 var p = Element.getStyle(element, 'position');
104897 if (p == 'relative' || p == 'absolute') break;
104898 }
104899 } while (element);
104900 return Element._returnOffset(valueL, valueT);
104901 },
104902
104903 absolutize: function(element) {
104904 element = $(element);
104905 if (element.getStyle('position') == 'absolute') return;
104906 // Position.prepare(); // To be done manually by Scripty when it needs it.
104907
104908 var offsets = element.positionedOffset();
104909 var top = offsets[1];
104910 var left = offsets[0];
104911 var width = element.clientWidth;
104912 var height = element.clientHeight;
104913
104914 element._originalLeft = left - parseFloat(element.style.left || 0);
104915 element._originalTop = top - parseFloat(element.style.top || 0);
104916 element._originalWidth = element.style.width;
104917 element._originalHeight = element.style.height;
104918
104919 element.style.position = 'absolute';
104920 element.style.top = top + 'px';
104921 element.style.left = left + 'px';
104922 element.style.width = width + 'px';
104923 element.style.height = height + 'px';
104924 return element;
104925 },
104926
104927 relativize: function(element) {
104928 element = $(element);
104929 if (element.getStyle('position') == 'relative') return;
104930 // Position.prepare(); // To be done manually by Scripty when it needs it.
104931
104932 element.style.position = 'relative';
104933 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
104934 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
104935
104936 element.style.top = top + 'px';
104937 element.style.left = left + 'px';
104938 element.style.height = element._originalHeight;
104939 element.style.width = element._originalWidth;
104940 return element;
104941 },
104942
104943 cumulativeScrollOffset: function(element) {
104944 var valueT = 0, valueL = 0;
104945 do {
104946 valueT += element.scrollTop || 0;
104947 valueL += element.scrollLeft || 0;
104948 element = element.parentNode;
104949 } while (element);
104950 return Element._returnOffset(valueL, valueT);
104951 },
104952
104953 getOffsetParent: function(element) {
104954 if (element.offsetParent) return $(element.offsetParent);
104955 if (element == document.body) return $(element);
104956
104957 while ((element = element.parentNode) && element != document.body)
104958 if (Element.getStyle(element, 'position') != 'static')
104959 return $(element);
104960
104961 return $(document.body);
104962 },
104963
104964 viewportOffset: function(forElement) {
104965 var valueT = 0, valueL = 0;
104966
104967 var element = forElement;
104968 do {
104969 valueT += element.offsetTop || 0;
104970 valueL += element.offsetLeft || 0;
104971
104972 // Safari fix
104973 if (element.offsetParent == document.body &&
104974 Element.getStyle(element, 'position') == 'absolute') break;
104975
104976 } while (element = element.offsetParent);
104977
104978 element = forElement;
104979 do {
104980 if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
104981 valueT -= element.scrollTop || 0;
104982 valueL -= element.scrollLeft || 0;
104983 }
104984 } while (element = element.parentNode);
104985
104986 return Element._returnOffset(valueL, valueT);
104987 },
104988
104989 clonePosition: function(element, source) {
104990 var options = Object.extend({
104991 setLeft: true,
104992 setTop: true,
104993 setWidth: true,
104994 setHeight: true,
104995 offsetTop: 0,
104996 offsetLeft: 0
104997 }, arguments[2] || { });
104998
104999 // find page position of source
105000 source = $(source);
105001 var p = source.viewportOffset();
105002
105003 // find coordinate system to use
105004 element = $(element);
105005 var delta = [0, 0];
105006 var parent = null;
105007 // delta [0,0] will do fine with position: fixed elements,
105008 // position:absolute needs offsetParent deltas
105009 if (Element.getStyle(element, 'position') == 'absolute') {
105010 parent = element.getOffsetParent();
105011 delta = parent.viewportOffset();
105012 }
105013
105014 // correct by body offsets (fixes Safari)
105015 if (parent == document.body) {
105016 delta[0] -= document.body.offsetLeft;
105017 delta[1] -= document.body.offsetTop;
105018 }
105019
105020 // set position
105021 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
105022 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
105023 if (options.setWidth) element.style.width = source.offsetWidth + 'px';
105024 if (options.setHeight) element.style.height = source.offsetHeight + 'px';
105025 return element;
105026 }
105027 };
105028
105029 Element.Methods.identify.counter = 1;
105030
105031 Object.extend(Element.Methods, {
105032 getElementsBySelector: Element.Methods.select,
105033 childElements: Element.Methods.immediateDescendants
105034 });
105035
105036 Element._attributeTranslations = {
105037 write: {
105038 names: {
105039 className: 'class',
105040 htmlFor: 'for'
105041 },
105042 values: { }
105043 }
105044 };
105045
105046
105047 if (!document.createRange || Prototype.Browser.Opera) {
105048 Element.Methods.insert = function(element, insertions) {
105049 element = $(element);
105050
105051 if (Object.isString(insertions) || Object.isNumber(insertions) ||
105052 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
105053 insertions = { bottom: insertions };
105054
105055 var t = Element._insertionTranslations, content, position, pos, tagName;
105056
105057 for (position in insertions) {
105058 content = insertions[position];
105059 position = position.toLowerCase();
105060 pos = t[position];
105061
105062 if (content && content.toElement) content = content.toElement();
105063 if (Object.isElement(content)) {
105064 pos.insert(element, content);
105065 continue;
105066 }
105067
105068 content = Object.toHTML(content);
105069 tagName = ((position == 'before' || position == 'after')
105070 ? element.parentNode : element).tagName.toUpperCase();
105071
105072 if (t.tags[tagName]) {
105073 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
105074 if (position == 'top' || position == 'after') fragments.reverse();
105075 fragments.each(pos.insert.curry(element));
105076 }
105077 else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
105078
105079 content.evalScripts.bind(content).defer();
105080 }
105081
105082 return element;
105083 };
105084 }
105085
105086 if (Prototype.Browser.Opera) {
105087 Element.Methods._getStyle = Element.Methods.getStyle;
105088 Element.Methods.getStyle = function(element, style) {
105089 switch(style) {
105090 case 'left':
105091 case 'top':
105092 case 'right':
105093 case 'bottom':
105094 if (Element._getStyle(element, 'position') == 'static') return null;
105095 default: return Element._getStyle(element, style);
105096 }
105097 };
105098 Element.Methods._readAttribute = Element.Methods.readAttribute;
105099 Element.Methods.readAttribute = function(element, attribute) {
105100 if (attribute == 'title') return element.title;
105101 return Element._readAttribute(element, attribute);
105102 };
105103 }
105104
105105 else if (Prototype.Browser.IE) {
105106 $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
105107 Element.Methods[method] = Element.Methods[method].wrap(
105108 function(proceed, element) {
105109 element = $(element);
105110 var position = element.getStyle('position');
105111 if (position != 'static') return proceed(element);
105112 element.setStyle({ position: 'relative' });
105113 var value = proceed(element);
105114 element.setStyle({ position: position });
105115 return value;
105116 }
105117 );
105118 });
105119
105120 Element.Methods.getStyle = function(element, style) {
105121 element = $(element);
105122 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
105123 var value = element.style[style];
105124 if (!value && element.currentStyle) value = element.currentStyle[style];
105125
105126 if (style == 'opacity') {
105127 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
105128 if (value[1]) return parseFloat(value[1]) / 100;
105129 return 1.0;
105130 }
105131
105132 if (value == 'auto') {
105133 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
105134 return element['offset' + style.capitalize()] + 'px';
105135 return null;
105136 }
105137 return value;
105138 };
105139
105140 Element.Methods.setOpacity = function(element, value) {
105141 function stripAlpha(filter){
105142 return filter.replace(/alpha\([^\)]*\)/gi,'');
105143 }
105144 element = $(element);
105145 var currentStyle = element.currentStyle;
105146 if ((currentStyle && !currentStyle.hasLayout) ||
105147 (!currentStyle && element.style.zoom == 'normal'))
105148 element.style.zoom = 1;
105149
105150 var filter = element.getStyle('filter'), style = element.style;
105151 if (value == 1 || value === '') {
105152 (filter = stripAlpha(filter)) ?
105153 style.filter = filter : style.removeAttribute('filter');
105154 return element;
105155 } else if (value < 0.00001) value = 0;
105156 style.filter = stripAlpha(filter) +
105157 'alpha(opacity=' + (value * 100) + ')';
105158 return element;
105159 };
105160
105161 Element._attributeTranslations = {
105162 read: {
105163 names: {
105164 'class': 'className',
105165 'for': 'htmlFor'
105166 },
105167 values: {
105168 _getAttr: function(element, attribute) {
105169 return element.getAttribute(attribute, 2);
105170 },
105171 _getAttrNode: function(element, attribute) {
105172 var node = element.getAttributeNode(attribute);
105173 return node ? node.value : "";
105174 },
105175 _getEv: function(element, attribute) {
105176 var attribute = element.getAttribute(attribute);
105177 return attribute ? attribute.toString().slice(23, -2) : null;
105178 },
105179 _flag: function(element, attribute) {
105180 return $(element).hasAttribute(attribute) ? attribute : null;
105181 },
105182 style: function(element) {
105183 return element.style.cssText.toLowerCase();
105184 },
105185 title: function(element) {
105186 return element.title;
105187 }
105188 }
105189 }
105190 };
105191
105192 Element._attributeTranslations.write = {
105193 names: Object.clone(Element._attributeTranslations.read.names),
105194 values: {
105195 checked: function(element, value) {
105196 element.checked = !!value;
105197 },
105198
105199 style: function(element, value) {
105200 element.style.cssText = value ? value : '';
105201 }
105202 }
105203 };
105204
105205 Element._attributeTranslations.has = {};
105206
105207 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
105208 'encType maxLength readOnly longDesc').each(function(attr) {
105209 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
105210 Element._attributeTranslations.has[attr.toLowerCase()] = attr;
105211 });
105212
105213 (function(v) {
105214 Object.extend(v, {
105215 href: v._getAttr,
105216 src: v._getAttr,
105217 type: v._getAttr,
105218 action: v._getAttrNode,
105219 disabled: v._flag,
105220 checked: v._flag,
105221 readonly: v._flag,
105222 multiple: v._flag,
105223 onload: v._getEv,
105224 onunload: v._getEv,
105225 onclick: v._getEv,
105226 ondblclick: v._getEv,
105227 onmousedown: v._getEv,
105228 onmouseup: v._getEv,
105229 onmouseover: v._getEv,
105230 onmousemove: v._getEv,
105231 onmouseout: v._getEv,
105232 onfocus: v._getEv,
105233 onblur: v._getEv,
105234 onkeypress: v._getEv,
105235 onkeydown: v._getEv,
105236 onkeyup: v._getEv,
105237 onsubmit: v._getEv,
105238 onreset: v._getEv,
105239 onselect: v._getEv,
105240 onchange: v._getEv
105241 });
105242 })(Element._attributeTranslations.read.values);
105243 }
105244
105245 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
105246 Element.Methods.setOpacity = function(element, value) {
105247 element = $(element);
105248 element.style.opacity = (value == 1) ? 0.999999 :
105249 (value === '') ? '' : (value < 0.00001) ? 0 : value;
105250 return element;
105251 };
105252 }
105253
105254 else if (Prototype.Browser.WebKit) {
105255 Element.Methods.setOpacity = function(element, value) {
105256 element = $(element);
105257 element.style.opacity = (value == 1 || value === '') ? '' :
105258 (value < 0.00001) ? 0 : value;
105259
105260 if (value == 1)
105261 if(element.tagName == 'IMG' && element.width) {
105262 element.width++; element.width--;
105263 } else try {
105264 var n = document.createTextNode(' ');
105265 element.appendChild(n);
105266 element.removeChild(n);
105267 } catch (e) { }
105268
105269 return element;
105270 };
105271
105272 // Safari returns margins on body which is incorrect if the child is absolutely
105273 // positioned. For performance reasons, redefine Position.cumulativeOffset for
105274 // KHTML/WebKit only.
105275 Element.Methods.cumulativeOffset = function(element) {
105276 var valueT = 0, valueL = 0;
105277 do {
105278 valueT += element.offsetTop || 0;
105279 valueL += element.offsetLeft || 0;
105280 if (element.offsetParent == document.body)
105281 if (Element.getStyle(element, 'position') == 'absolute') break;
105282
105283 element = element.offsetParent;
105284 } while (element);
105285
105286 return Element._returnOffset(valueL, valueT);
105287 };
105288 }
105289
105290 if (Prototype.Browser.IE || Prototype.Browser.Opera) {
105291 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
105292 Element.Methods.update = function(element, content) {
105293 element = $(element);
105294
105295 if (content && content.toElement) content = content.toElement();
105296 if (Object.isElement(content)) return element.update().insert(content);
105297
105298 content = Object.toHTML(content);
105299 var tagName = element.tagName.toUpperCase();
105300
105301 if (tagName in Element._insertionTranslations.tags) {
105302 $A(element.childNodes).each(function(node) { element.removeChild(node) });
105303 Element._getContentFromAnonymousElement(tagName, content.stripScripts())
105304 .each(function(node) { element.appendChild(node) });
105305 }
105306 else element.innerHTML = content.stripScripts();
105307
105308 content.evalScripts.bind(content).defer();
105309 return element;
105310 };
105311 }
105312
105313 if (document.createElement('div').outerHTML) {
105314 Element.Methods.replace = function(element, content) {
105315 element = $(element);
105316
105317 if (content && content.toElement) content = content.toElement();
105318 if (Object.isElement(content)) {
105319 element.parentNode.replaceChild(content, element);
105320 return element;
105321 }
105322
105323 content = Object.toHTML(content);
105324 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
105325
105326 if (Element._insertionTranslations.tags[tagName]) {
105327 var nextSibling = element.next();
105328 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
105329 parent.removeChild(element);
105330 if (nextSibling)
105331 fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
105332 else
105333 fragments.each(function(node) { parent.appendChild(node) });
105334 }
105335 else element.outerHTML = content.stripScripts();
105336
105337 content.evalScripts.bind(content).defer();
105338 return element;
105339 };
105340 }
105341
105342 Element._returnOffset = function(l, t) {
105343 var result = [l, t];
105344 result.left = l;
105345 result.top = t;
105346 return result;
105347 };
105348
105349 Element._getContentFromAnonymousElement = function(tagName, html) {
105350 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
105351 div.innerHTML = t[0] + html + t[1];
105352 t[2].times(function() { div = div.firstChild });
105353 return $A(div.childNodes);
105354 };
105355
105356 Element._insertionTranslations = {
105357 before: {
105358 adjacency: 'beforeBegin',
105359 insert: function(element, node) {
105360 element.parentNode.insertBefore(node, element);
105361 },
105362 initializeRange: function(element, range) {
105363 range.setStartBefore(element);
105364 }
105365 },
105366 top: {
105367 adjacency: 'afterBegin',
105368 insert: function(element, node) {
105369 element.insertBefore(node, element.firstChild);
105370 },
105371 initializeRange: function(element, range) {
105372 range.selectNodeContents(element);
105373 range.collapse(true);
105374 }
105375 },
105376 bottom: {
105377 adjacency: 'beforeEnd',
105378 insert: function(element, node) {
105379 element.appendChild(node);
105380 }
105381 },
105382 after: {
105383 adjacency: 'afterEnd',
105384 insert: function(element, node) {
105385 element.parentNode.insertBefore(node, element.nextSibling);
105386 },
105387 initializeRange: function(element, range) {
105388 range.setStartAfter(element);
105389 }
105390 },
105391 tags: {
105392 TABLE: ['<table>', '</table>', 1],
105393 TBODY: ['<table><tbody>', '</tbody></table>', 2],
105394 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
105395 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
105396 SELECT: ['<select>', '</select>', 1]
105397 }
105398 };
105399
105400 (function() {
105401 this.bottom.initializeRange = this.top.initializeRange;
105402 Object.extend(this.tags, {
105403 THEAD: this.tags.TBODY,
105404 TFOOT: this.tags.TBODY,
105405 TH: this.tags.TD
105406 });
105407 }).call(Element._insertionTranslations);
105408
105409 Element.Methods.Simulated = {
105410 hasAttribute: function(element, attribute) {
105411 attribute = Element._attributeTranslations.has[attribute] || attribute;
105412 var node = $(element).getAttributeNode(attribute);
105413 return node && node.specified;
105414 }
105415 };
105416
105417 Element.Methods.ByTag = { };
105418
105419 Object.extend(Element, Element.Methods);
105420
105421 if (!Prototype.BrowserFeatures.ElementExtensions &&
105422 document.createElement('div').__proto__) {
105423 window.HTMLElement = { };
105424 window.HTMLElement.prototype = document.createElement('div').__proto__;
105425 Prototype.BrowserFeatures.ElementExtensions = true;
105426 }
105427
105428 Element.extend = (function() {
105429 if (Prototype.BrowserFeatures.SpecificElementExtensions)
105430 return Prototype.K;
105431
105432 var Methods = { }, ByTag = Element.Methods.ByTag;
105433
105434 var extend = Object.extend(function(element) {
105435 if (!element || element._extendedByPrototype ||
105436 element.nodeType != 1 || element == window) return element;
105437
105438 var methods = Object.clone(Methods),
105439 tagName = element.tagName, property, value;
105440
105441 // extend methods for specific tags
105442 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
105443
105444 for (property in methods) {
105445 value = methods[property];
105446 if (Object.isFunction(value) && !(property in element))
105447 element[property] = value.methodize();
105448 }
105449
105450 element._extendedByPrototype = Prototype.emptyFunction;
105451 return element;
105452
105453 }, {
105454 refresh: function() {
105455 // extend methods for all tags (Safari doesn't need this)
105456 if (!Prototype.BrowserFeatures.ElementExtensions) {
105457 Object.extend(Methods, Element.Methods);
105458 Object.extend(Methods, Element.Methods.Simulated);
105459 }
105460 }
105461 });
105462
105463 extend.refresh();
105464 return extend;
105465 })();
105466
105467 Element.hasAttribute = function(element, attribute) {
105468 if (element.hasAttribute) return element.hasAttribute(attribute);
105469 return Element.Methods.Simulated.hasAttribute(element, attribute);
105470 };
105471
105472 Element.addMethods = function(methods) {
105473 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
105474
105475 if (!methods) {
105476 Object.extend(Form, Form.Methods);
105477 Object.extend(Form.Element, Form.Element.Methods);
105478 Object.extend(Element.Methods.ByTag, {
105479 "FORM": Object.clone(Form.Methods),
105480 "INPUT": Object.clone(Form.Element.Methods),
105481 "SELECT": Object.clone(Form.Element.Methods),
105482 "TEXTAREA": Object.clone(Form.Element.Methods)
105483 });
105484 }
105485
105486 if (arguments.length == 2) {
105487 var tagName = methods;
105488 methods = arguments[1];
105489 }
105490
105491 if (!tagName) Object.extend(Element.Methods, methods || { });
105492 else {
105493 if (Object.isArray(tagName)) tagName.each(extend);
105494 else extend(tagName);
105495 }
105496
105497 function extend(tagName) {
105498 tagName = tagName.toUpperCase();
105499 if (!Element.Methods.ByTag[tagName])
105500 Element.Methods.ByTag[tagName] = { };
105501 Object.extend(Element.Methods.ByTag[tagName], methods);
105502 }
105503
105504 function copy(methods, destination, onlyIfAbsent) {
105505 onlyIfAbsent = onlyIfAbsent || false;
105506 for (var property in methods) {
105507 var value = methods[property];
105508 if (!Object.isFunction(value)) continue;
105509 if (!onlyIfAbsent || !(property in destination))
105510 destination[property] = value.methodize();
105511 }
105512 }
105513
105514 function findDOMClass(tagName) {
105515 var klass;
105516 var trans = {
105517 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
105518 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
105519 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
105520 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
105521 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
105522 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
105523 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
105524 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
105525 "FrameSet", "IFRAME": "IFrame"
105526 };
105527 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
105528 if (window[klass]) return window[klass];
105529 klass = 'HTML' + tagName + 'Element';
105530 if (window[klass]) return window[klass];
105531 klass = 'HTML' + tagName.capitalize() + 'Element';
105532 if (window[klass]) return window[klass];
105533
105534 window[klass] = { };
105535 window[klass].prototype = document.createElement(tagName).__proto__;
105536 return window[klass];
105537 }
105538
105539 if (F.ElementExtensions) {
105540 copy(Element.Methods, HTMLElement.prototype);
105541 copy(Element.Methods.Simulated, HTMLElement.prototype, true);
105542 }
105543
105544 if (F.SpecificElementExtensions) {
105545 for (var tag in Element.Methods.ByTag) {
105546 var klass = findDOMClass(tag);
105547 if (Object.isUndefined(klass)) continue;
105548 copy(T[tag], klass.prototype);
105549 }
105550 }
105551
105552 Object.extend(Element, Element.Methods);
105553 delete Element.ByTag;
105554
105555 if (Element.extend.refresh) Element.extend.refresh();
105556 Element.cache = { };
105557 };
105558
105559 document.viewport = {
105560 getDimensions: function() {
105561 var dimensions = { };
105562 $w('width height').each(function(d) {
105563 var D = d.capitalize();
105564 dimensions[d] = self['inner' + D] ||
105565 (document.documentElement['client' + D] || document.body['client' + D]);
105566 });
105567 return dimensions;
105568 },
105569
105570 getWidth: function() {
105571 return this.getDimensions().width;
105572 },
105573
105574 getHeight: function() {
105575 return this.getDimensions().height;
105576 },
105577
105578 getScrollOffsets: function() {
105579 return Element._returnOffset(
105580 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
105581 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
105582 }
105583 };
105584 /* Portions of the Selector class are derived from Jack Slocum`s DomQuery,
105585 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
105586 * license. Please see http://www.yui-ext.com/ for more information. */
105587
105588 var Selector = Class.create({
105589 initialize: function(expression) {
105590 this.expression = expression.strip();
105591 this.compileMatcher();
105592 },
105593
105594 compileMatcher: function() {
105595 // Selectors with namespaced attributes can't use the XPath version
105596 if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
105597 return this.compileXPathMatcher();
105598
105599 var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
105600 c = Selector.criteria, le, p, m;
105601
105602 if (Selector._cache[e]) {
105603 this.matcher = Selector._cache[e];
105604 return;
105605 }
105606
105607 this.matcher = ["this.matcher = function(root) {",
105608 "var r = root, h = Selector.handlers, c = false, n;"];
105609
105610 while (e && le != e && (/\S/).test(e)) {
105611 le = e;
105612 for (var i in ps) {
105613 p = ps[i];
105614 if (m = e.match(p)) {
105615 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
105616 new Template(c[i]).evaluate(m));
105617 e = e.replace(m[0], '');
105618 break;
105619 }
105620 }
105621 }
105622
105623 this.matcher.push("return h.unique(n);\n}");
105624 eval(this.matcher.join('\n'));
105625 Selector._cache[this.expression] = this.matcher;
105626 },
105627
105628 compileXPathMatcher: function() {
105629 var e = this.expression, ps = Selector.patterns,
105630 x = Selector.xpath, le, m;
105631
105632 if (Selector._cache[e]) {
105633 this.xpath = Selector._cache[e]; return;
105634 }
105635
105636 this.matcher = ['.//*'];
105637 while (e && le != e && (/\S/).test(e)) {
105638 le = e;
105639 for (var i in ps) {
105640 if (m = e.match(ps[i])) {
105641 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
105642 new Template(x[i]).evaluate(m));
105643 e = e.replace(m[0], '');
105644 break;
105645 }
105646 }
105647 }
105648
105649 this.xpath = this.matcher.join('');
105650 Selector._cache[this.expression] = this.xpath;
105651 },
105652
105653 findElements: function(root) {
105654 root = root || document;
105655 if (this.xpath) return document._getElementsByXPath(this.xpath, root);
105656 return this.matcher(root);
105657 },
105658
105659 match: function(element) {
105660 this.tokens = [];
105661
105662 var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
105663 var le, p, m;
105664
105665 while (e && le !== e && (/\S/).test(e)) {
105666 le = e;
105667 for (var i in ps) {
105668 p = ps[i];
105669 if (m = e.match(p)) {
105670 // use the Selector.assertions methods unless the selector
105671 // is too complex.
105672 if (as[i]) {
105673 this.tokens.push([i, Object.clone(m)]);
105674 e = e.replace(m[0], '');
105675 } else {
105676 // reluctantly do a document-wide search
105677 // and look for a match in the array
105678 return this.findElements(document).include(element);
105679 }
105680 }
105681 }
105682 }
105683
105684 var match = true, name, matches;
105685 for (var i = 0, token; token = this.tokens[i]; i++) {
105686 name = token[0], matches = token[1];
105687 if (!Selector.assertions[name](element, matches)) {
105688 match = false; break;
105689 }
105690 }
105691
105692 return match;
105693 },
105694
105695 toString: function() {
105696 return this.expression;
105697 },
105698
105699 inspect: function() {
105700 return "#<Selector:" + this.expression.inspect() + ">";
105701 }
105702 });
105703
105704 Object.extend(Selector, {
105705 _cache: { },
105706
105707 xpath: {
105708 descendant: "//*",
105709 child: "/*",
105710 adjacent: "/following-sibling::*[1]",
105711 laterSibling: '/following-sibling::*',
105712 tagName: function(m) {
105713 if (m[1] == '*') return '';
105714 return "[local-name()='" + m[1].toLowerCase() +
105715 "' or local-name()='" + m[1].toUpperCase() + "']";
105716 },
105717 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
105718 id: "[@id='#{1}']",
105719 attrPresence: "[@#{1}]",
105720 attr: function(m) {
105721 m[3] = m[5] || m[6];
105722 return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
105723 },
105724 pseudo: function(m) {
105725 var h = Selector.xpath.pseudos[m[1]];
105726 if (!h) return '';
105727 if (Object.isFunction(h)) return h(m);
105728 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
105729 },
105730 operators: {
105731 '=': "[@#{1}='#{3}']",
105732 '!=': "[@#{1}!='#{3}']",
105733 '^=': "[starts-with(@#{1}, '#{3}')]",
105734 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
105735 '*=': "[contains(@#{1}, '#{3}')]",
105736 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
105737 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
105738 },
105739 pseudos: {
105740 'first-child': '[not(preceding-sibling::*)]',
105741 'last-child': '[not(following-sibling::*)]',
105742 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
105743 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
105744 'checked': "[@checked]",
105745 'disabled': "[@disabled]",
105746 'enabled': "[not(@disabled)]",
105747 'not': function(m) {
105748 var e = m[6], p = Selector.patterns,
105749 x = Selector.xpath, le, m, v;
105750
105751 var exclusion = [];
105752 while (e && le != e && (/\S/).test(e)) {
105753 le = e;
105754 for (var i in p) {
105755 if (m = e.match(p[i])) {
105756 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
105757 exclusion.push("(" + v.substring(1, v.length - 1) + ")");
105758 e = e.replace(m[0], '');
105759 break;
105760 }
105761 }
105762 }
105763 return "[not(" + exclusion.join(" and ") + ")]";
105764 },
105765 'nth-child': function(m) {
105766 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
105767 },
105768 'nth-last-child': function(m) {
105769 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
105770 },
105771 'nth-of-type': function(m) {
105772 return Selector.xpath.pseudos.nth("position() ", m);
105773 },
105774 'nth-last-of-type': function(m) {
105775 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
105776 },
105777 'first-of-type': function(m) {
105778 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
105779 },
105780 'last-of-type': function(m) {
105781 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
105782 },
105783 'only-of-type': function(m) {
105784 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
105785 },
105786 nth: function(fragment, m) {
105787 var mm, formula = m[6], predicate;
105788 if (formula == 'even') formula = '2n+0';
105789 if (formula == 'odd') formula = '2n+1';
105790 if (mm = formula.match(/^(\d+)$/)) // digit only
105791 return '[' + fragment + "= " + mm[1] + ']';
105792 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
105793 if (mm[1] == "-") mm[1] = -1;
105794 var a = mm[1] ? Number(mm[1]) : 1;
105795 var b = mm[2] ? Number(mm[2]) : 0;
105796 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
105797 "((#{fragment} - #{b}) div #{a} >= 0)]";
105798 return new Template(predicate).evaluate({
105799 fragment: fragment, a: a, b: b });
105800 }
105801 }
105802 }
105803 },
105804
105805 criteria: {
105806 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
105807 className: 'n = h.className(n, r, "#{1}", c); c = false;',
105808 id: 'n = h.id(n, r, "#{1}", c); c = false;',
105809 attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
105810 attr: function(m) {
105811 m[3] = (m[5] || m[6]);
105812 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
105813 },
105814 pseudo: function(m) {
105815 if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
105816 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
105817 },
105818 descendant: 'c = "descendant";',
105819 child: 'c = "child";',
105820 adjacent: 'c = "adjacent";',
105821 laterSibling: 'c = "laterSibling";'
105822 },
105823
105824 patterns: {
105825 // combinators must be listed first
105826 // (and descendant needs to be last combinator)
105827 laterSibling: /^\s*~\s*/,
105828 child: /^\s*>\s*/,
105829 adjacent: /^\s*\+\s*/,
105830 descendant: /^\s/,
105831
105832 // selectors follow
105833 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
105834 id: /^#([\w\-\*]+)(\b|$)/,
105835 className: /^\.([\w\-\*]+)(\b|$)/,
105836 pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
105837 attrPresence: /^\[([\w]+)\]/,
105838 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
105839 },
105840
105841 // for Selector.match and Element#match
105842 assertions: {
105843 tagName: function(element, matches) {
105844 return matches[1].toUpperCase() == element.tagName.toUpperCase();
105845 },
105846
105847 className: function(element, matches) {
105848 return Element.hasClassName(element, matches[1]);
105849 },
105850
105851 id: function(element, matches) {
105852 return element.id === matches[1];
105853 },
105854
105855 attrPresence: function(element, matches) {
105856 return Element.hasAttribute(element, matches[1]);
105857 },
105858
105859 attr: function(element, matches) {
105860 var nodeValue = Element.readAttribute(element, matches[1]);
105861 return Selector.operators[matches[2]](nodeValue, matches[3]);
105862 }
105863 },
105864
105865 handlers: {
105866 // UTILITY FUNCTIONS
105867 // joins two collections
105868 concat: function(a, b) {
105869 for (var i = 0, node; node = b[i]; i++)
105870 a.push(node);
105871 return a;
105872 },
105873
105874 // marks an array of nodes for counting
105875 mark: function(nodes) {
105876 for (var i = 0, node; node = nodes[i]; i++)
105877 node._counted = true;
105878 return nodes;
105879 },
105880
105881 unmark: function(nodes) {
105882 for (var i = 0, node; node = nodes[i]; i++)
105883 node._counted = undefined;
105884 return nodes;
105885 },
105886
105887 // mark each child node with its position (for nth calls)
105888 // "ofType" flag indicates whether we're indexing for nth-of-type
105889 // rather than nth-child
105890 index: function(parentNode, reverse, ofType) {
105891 parentNode._counted = true;
105892 if (reverse) {
105893 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
105894 var node = nodes[i];
105895 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
105896 }
105897 } else {
105898 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
105899 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
105900 }
105901 },
105902
105903 // filters out duplicates and extends all nodes
105904 unique: function(nodes) {
105905 if (nodes.length == 0) return nodes;
105906 var results = [], n;
105907 for (var i = 0, l = nodes.length; i < l; i++)
105908 if (!(n = nodes[i])._counted) {
105909 n._counted = true;
105910 results.push(Element.extend(n));
105911 }
105912 return Selector.handlers.unmark(results);
105913 },
105914
105915 // COMBINATOR FUNCTIONS
105916 descendant: function(nodes) {
105917 var h = Selector.handlers;
105918 for (var i = 0, results = [], node; node = nodes[i]; i++)
105919 h.concat(results, node.getElementsByTagName('*'));
105920 return results;
105921 },
105922
105923 child: function(nodes) {
105924 var h = Selector.handlers;
105925 for (var i = 0, results = [], node; node = nodes[i]; i++) {
105926 for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
105927 if (child.nodeType == 1 && child.tagName != '!') results.push(child);
105928 }
105929 return results;
105930 },
105931
105932 adjacent: function(nodes) {
105933 for (var i = 0, results = [], node; node = nodes[i]; i++) {
105934 var next = this.nextElementSibling(node);
105935 if (next) results.push(next);
105936 }
105937 return results;
105938 },
105939
105940 laterSibling: function(nodes) {
105941 var h = Selector.handlers;
105942 for (var i = 0, results = [], node; node = nodes[i]; i++)
105943 h.concat(results, Element.nextSiblings(node));
105944 return results;
105945 },
105946
105947 nextElementSibling: function(node) {
105948 while (node = node.nextSibling)
105949 if (node.nodeType == 1) return node;
105950 return null;
105951 },
105952
105953 previousElementSibling: function(node) {
105954 while (node = node.previousSibling)
105955 if (node.nodeType == 1) return node;
105956 return null;
105957 },
105958
105959 // TOKEN FUNCTIONS
105960 tagName: function(nodes, root, tagName, combinator) {
105961 tagName = tagName.toUpperCase();
105962 var results = [], h = Selector.handlers;
105963 if (nodes) {
105964 if (combinator) {
105965 // fastlane for ordinary descendant combinators
105966 if (combinator == "descendant") {
105967 for (var i = 0, node; node = nodes[i]; i++)
105968 h.concat(results, node.getElementsByTagName(tagName));
105969 return results;
105970 } else nodes = this[combinator](nodes);
105971 if (tagName == "*") return nodes;
105972 }
105973 for (var i = 0, node; node = nodes[i]; i++)
105974 if (node.tagName.toUpperCase() == tagName) results.push(node);
105975 return results;
105976 } else return root.getElementsByTagName(tagName);
105977 },
105978
105979 id: function(nodes, root, id, combinator) {
105980 var targetNode = $(id), h = Selector.handlers;
105981 if (!targetNode) return [];
105982 if (!nodes && root == document) return [targetNode];
105983 if (nodes) {
105984 if (combinator) {
105985 if (combinator == 'child') {
105986 for (var i = 0, node; node = nodes[i]; i++)
105987 if (targetNode.parentNode == node) return [targetNode];
105988 } else if (combinator == 'descendant') {
105989 for (var i = 0, node; node = nodes[i]; i++)
105990 if (Element.descendantOf(targetNode, node)) return [targetNode];
105991 } else if (combinator == 'adjacent') {
105992 for (var i = 0, node; node = nodes[i]; i++)
105993 if (Selector.handlers.previousElementSibling(targetNode) == node)
105994 return [targetNode];
105995 } else nodes = h[combinator](nodes);
105996 }
105997 for (var i = 0, node; node = nodes[i]; i++)
105998 if (node == targetNode) return [targetNode];
105999 return [];
106000 }
106001 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
106002 },
106003
106004 className: function(nodes, root, className, combinator) {
106005 if (nodes && combinator) nodes = this[combinator](nodes);
106006 return Selector.handlers.byClassName(nodes, root, className);
106007 },
106008
106009 byClassName: function(nodes, root, className) {
106010 if (!nodes) nodes = Selector.handlers.descendant([root]);
106011 var needle = ' ' + className + ' ';
106012 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
106013 nodeClassName = node.className;
106014 if (nodeClassName.length == 0) continue;
106015 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
106016 results.push(node);
106017 }
106018 return results;
106019 },
106020
106021 attrPresence: function(nodes, root, attr) {
106022 if (!nodes) nodes = root.getElementsByTagName("*");
106023 var results = [];
106024 for (var i = 0, node; node = nodes[i]; i++)
106025 if (Element.hasAttribute(node, attr)) results.push(node);
106026 return results;
106027 },
106028
106029 attr: function(nodes, root, attr, value, operator) {
106030 if (!nodes) nodes = root.getElementsByTagName("*");
106031 var handler = Selector.operators[operator], results = [];
106032 for (var i = 0, node; node = nodes[i]; i++) {
106033 var nodeValue = Element.readAttribute(node, attr);
106034 if (nodeValue === null) continue;
106035 if (handler(nodeValue, value)) results.push(node);
106036 }
106037 return results;
106038 },
106039
106040 pseudo: function(nodes, name, value, root, combinator) {
106041 if (nodes && combinator) nodes = this[combinator](nodes);
106042 if (!nodes) nodes = root.getElementsByTagName("*");
106043 return Selector.pseudos[name](nodes, value, root);
106044 }
106045 },
106046
106047 pseudos: {
106048 'first-child': function(nodes, value, root) {
106049 for (var i = 0, results = [], node; node = nodes[i]; i++) {
106050 if (Selector.handlers.previousElementSibling(node)) continue;
106051 results.push(node);
106052 }
106053 return results;
106054 },
106055 'last-child': function(nodes, value, root) {
106056 for (var i = 0, results = [], node; node = nodes[i]; i++) {
106057 if (Selector.handlers.nextElementSibling(node)) continue;
106058 results.push(node);
106059 }
106060 return results;
106061 },
106062 'only-child': function(nodes, value, root) {
106063 var h = Selector.handlers;
106064 for (var i = 0, results = [], node; node = nodes[i]; i++)
106065 if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
106066 results.push(node);
106067 return results;
106068 },
106069 'nth-child': function(nodes, formula, root) {
106070 return Selector.pseudos.nth(nodes, formula, root);
106071 },
106072 'nth-last-child': function(nodes, formula, root) {
106073 return Selector.pseudos.nth(nodes, formula, root, true);
106074 },
106075 'nth-of-type': function(nodes, formula, root) {
106076 return Selector.pseudos.nth(nodes, formula, root, false, true);
106077 },
106078 'nth-last-of-type': function(nodes, formula, root) {
106079 return Selector.pseudos.nth(nodes, formula, root, true, true);
106080 },
106081 'first-of-type': function(nodes, formula, root) {
106082 return Selector.pseudos.nth(nodes, "1", root, false, true);
106083 },
106084 'last-of-type': function(nodes, formula, root) {
106085 return Selector.pseudos.nth(nodes, "1", root, true, true);
106086 },
106087 'only-of-type': function(nodes, formula, root) {
106088 var p = Selector.pseudos;
106089 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
106090 },
106091
106092 // handles the an+b logic
106093 getIndices: function(a, b, total) {
106094 if (a == 0) return b > 0 ? [b] : [];
106095 return $R(1, total).inject([], function(memo, i) {
106096 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
106097 return memo;
106098 });
106099 },
106100
106101 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
106102 nth: function(nodes, formula, root, reverse, ofType) {
106103 if (nodes.length == 0) return [];
106104 if (formula == 'even') formula = '2n+0';
106105 if (formula == 'odd') formula = '2n+1';
106106 var h = Selector.handlers, results = [], indexed = [], m;
106107 h.mark(nodes);
106108 for (var i = 0, node; node = nodes[i]; i++) {
106109 if (!node.parentNode._counted) {
106110 h.index(node.parentNode, reverse, ofType);
106111 indexed.push(node.parentNode);
106112 }
106113 }
106114 if (formula.match(/^\d+$/)) { // just a number
106115 formula = Number(formula);
106116 for (var i = 0, node; node = nodes[i]; i++)
106117 if (node.nodeIndex == formula) results.push(node);
106118 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
106119 if (m[1] == "-") m[1] = -1;
106120 var a = m[1] ? Number(m[1]) : 1;
106121 var b = m[2] ? Number(m[2]) : 0;
106122 var indices = Selector.pseudos.getIndices(a, b, nodes.length);
106123 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
106124 for (var j = 0; j < l; j++)
106125 if (node.nodeIndex == indices[j]) results.push(node);
106126 }
106127 }
106128 h.unmark(nodes);
106129 h.unmark(indexed);
106130 return results;
106131 },
106132
106133 'empty': function(nodes, value, root) {
106134 for (var i = 0, results = [], node; node = nodes[i]; i++) {
106135 // IE treats comments as element nodes
106136 if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
106137 results.push(node);
106138 }
106139 return results;
106140 },
106141
106142 'not': function(nodes, selector, root) {
106143 var h = Selector.handlers, selectorType, m;
106144 var exclusions = new Selector(selector).findElements(root);
106145 h.mark(exclusions);
106146 for (var i = 0, results = [], node; node = nodes[i]; i++)
106147 if (!node._counted) results.push(node);
106148 h.unmark(exclusions);
106149 return results;
106150 },
106151
106152 'enabled': function(nodes, value, root) {
106153 for (var i = 0, results = [], node; node = nodes[i]; i++)
106154 if (!node.disabled) results.push(node);
106155 return results;
106156 },
106157
106158 'disabled': function(nodes, value, root) {
106159 for (var i = 0, results = [], node; node = nodes[i]; i++)
106160 if (node.disabled) results.push(node);
106161 return results;
106162 },
106163
106164 'checked': function(nodes, value, root) {
106165 for (var i = 0, results = [], node; node = nodes[i]; i++)
106166 if (node.checked) results.push(node);
106167 return results;
106168 }
106169 },
106170
106171 operators: {
106172 '=': function(nv, v) { return nv == v; },
106173 '!=': function(nv, v) { return nv != v; },
106174 '^=': function(nv, v) { return nv.startsWith(v); },
106175 '$=': function(nv, v) { return nv.endsWith(v); },
106176 '*=': function(nv, v) { return nv.include(v); },
106177 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
106178 '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
106179 },
106180
106181 matchElements: function(elements, expression) {
106182 var matches = new Selector(expression).findElements(), h = Selector.handlers;
106183 h.mark(matches);
106184 for (var i = 0, results = [], element; element = elements[i]; i++)
106185 if (element._counted) results.push(element);
106186 h.unmark(matches);
106187 return results;
106188 },
106189
106190 findElement: function(elements, expression, index) {
106191 if (Object.isNumber(expression)) {
106192 index = expression; expression = false;
106193 }
106194 return Selector.matchElements(elements, expression || '*')[index || 0];
106195 },
106196
106197 findChildElements: function(element, expressions) {
106198 var exprs = expressions.join(','), expressions = [];
106199 exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
106200 expressions.push(m[1].strip());
106201 });
106202 var results = [], h = Selector.handlers;
106203 for (var i = 0, l = expressions.length, selector; i < l; i++) {
106204 selector = new Selector(expressions[i].strip());
106205 h.concat(results, selector.findElements(element));
106206 }
106207 return (l > 1) ? h.unique(results) : results;
106208 }
106209 });
106210
106211 function $$() {
106212 return Selector.findChildElements(document, $A(arguments));
106213 }
106214 var Form = {
106215 reset: function(form) {
106216 $(form).reset();
106217 return form;
106218 },
106219
106220 serializeElements: function(elements, options) {
106221 if (typeof options != 'object') options = { hash: !!options };
106222 else if (options.hash === undefined) options.hash = true;
106223 var key, value, submitted = false, submit = options.submit;
106224
106225 var data = elements.inject({ }, function(result, element) {
106226 if (!element.disabled && element.name) {
106227 key = element.name; value = $(element).getValue();
106228 if (value != null && (element.type != 'submit' || (!submitted &&
106229 submit !== false && (!submit || key == submit) && (submitted = true)))) {
106230 if (key in result) {
106231 // a key is already present; construct an array of values
106232 if (!Object.isArray(result[key])) result[key] = [result[key]];
106233 result[key].push(value);
106234 }
106235 else result[key] = value;
106236 }
106237 }
106238 return result;
106239 });
106240
106241 return options.hash ? data : Object.toQueryString(data);
106242 }
106243 };
106244
106245 Form.Methods = {
106246 serialize: function(form, options) {
106247 return Form.serializeElements(Form.getElements(form), options);
106248 },
106249
106250 getElements: function(form) {
106251 return $A($(form).getElementsByTagName('*')).inject([],
106252 function(elements, child) {
106253 if (Form.Element.Serializers[child.tagName.toLowerCase()])
106254 elements.push(Element.extend(child));
106255 return elements;
106256 }
106257 );
106258 },
106259
106260 getInputs: function(form, typeName, name) {
106261 form = $(form);
106262 var inputs = form.getElementsByTagName('input');
106263
106264 if (!typeName && !name) return $A(inputs).map(Element.extend);
106265
106266 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
106267 var input = inputs[i];
106268 if ((typeName && input.type != typeName) || (name && input.name != name))
106269 continue;
106270 matchingInputs.push(Element.extend(input));
106271 }
106272
106273 return matchingInputs;
106274 },
106275
106276 disable: function(form) {
106277 form = $(form);
106278 Form.getElements(form).invoke('disable');
106279 return form;
106280 },
106281
106282 enable: function(form) {
106283 form = $(form);
106284 Form.getElements(form).invoke('enable');
106285 return form;
106286 },
106287
106288 findFirstElement: function(form) {
106289 var elements = $(form).getElements().findAll(function(element) {
106290 return 'hidden' != element.type && !element.disabled;
106291 });
106292 var firstByIndex = elements.findAll(function(element) {
106293 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
106294 }).sortBy(function(element) { return element.tabIndex }).first();
106295
106296 return firstByIndex ? firstByIndex : elements.find(function(element) {
106297 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
106298 });
106299 },
106300
106301 focusFirstElement: function(form) {
106302 form = $(form);
106303 form.findFirstElement().activate();
106304 return form;
106305 },
106306
106307 request: function(form, options) {
106308 form = $(form), options = Object.clone(options || { });
106309
106310 var params = options.parameters, action = form.readAttribute('action') || '';
106311 if (action.blank()) action = window.location.href;
106312 options.parameters = form.serialize(true);
106313
106314 if (params) {
106315 if (Object.isString(params)) params = params.toQueryParams();
106316 Object.extend(options.parameters, params);
106317 }
106318
106319 if (form.hasAttribute('method') && !options.method)
106320 options.method = form.method;
106321
106322 return new Ajax.Request(action, options);
106323 }
106324 };
106325
106326 /*--------------------------------------------------------------------------*/
106327
106328 Form.Element = {
106329 focus: function(element) {
106330 $(element).focus();
106331 return element;
106332 },
106333
106334 select: function(element) {
106335 $(element).select();
106336 return element;
106337 }
106338 };
106339
106340 Form.Element.Methods = {
106341 serialize: function(element) {
106342 element = $(element);
106343 if (!element.disabled && element.name) {
106344 var value = element.getValue();
106345 if (value != undefined) {
106346 var pair = { };
106347 pair[element.name] = value;
106348 return Object.toQueryString(pair);
106349 }
106350 }
106351 return '';
106352 },
106353
106354 getValue: function(element) {
106355 element = $(element);
106356 var method = element.tagName.toLowerCase();
106357 return Form.Element.Serializers[method](element);
106358 },
106359
106360 setValue: function(element, value) {
106361 element = $(element);
106362 var method = element.tagName.toLowerCase();
106363 Form.Element.Serializers[method](element, value);
106364 return element;
106365 },
106366
106367 clear: function(element) {
106368 $(element).value = '';
106369 return element;
106370 },
106371
106372 present: function(element) {
106373 return $(element).value != '';
106374 },
106375
106376 activate: function(element) {
106377 element = $(element);
106378 try {
106379 element.focus();
106380 if (element.select && (element.tagName.toLowerCase() != 'input' ||
106381 !['button', 'reset', 'submit'].include(element.type)))
106382 element.select();
106383 } catch (e) { }
106384 return element;
106385 },
106386
106387 disable: function(element) {
106388 element = $(element);
106389 element.blur();
106390 element.disabled = true;
106391 return element;
106392 },
106393
106394 enable: function(element) {
106395 element = $(element);
106396 element.disabled = false;
106397 return element;
106398 }
106399 };
106400
106401 /*--------------------------------------------------------------------------*/
106402
106403 var Field = Form.Element;
106404 var $F = Form.Element.Methods.getValue;
106405
106406 /*--------------------------------------------------------------------------*/
106407
106408 Form.Element.Serializers = {
106409 input: function(element, value) {
106410 switch (element.type.toLowerCase()) {
106411 case 'checkbox':
106412 case 'radio':
106413 return Form.Element.Serializers.inputSelector(element, value);
106414 default:
106415 return Form.Element.Serializers.textarea(element, value);
106416 }
106417 },
106418
106419 inputSelector: function(element, value) {
106420 if (value === undefined) return element.checked ? element.value : null;
106421 else element.checked = !!value;
106422 },
106423
106424 textarea: function(element, value) {
106425 if (value === undefined) return element.value;
106426 else element.value = value;
106427 },
106428
106429 select: function(element, index) {
106430 if (index === undefined)
106431 return this[element.type == 'select-one' ?
106432 'selectOne' : 'selectMany'](element);
106433 else {
106434 var opt, value, single = !Object.isArray(index);
106435 for (var i = 0, length = element.length; i < length; i++) {
106436 opt = element.options[i];
106437 value = this.optionValue(opt);
106438 if (single) {
106439 if (value == index) {
106440 opt.selected = true;
106441 return;
106442 }
106443 }
106444 else opt.selected = index.include(value);
106445 }
106446 }
106447 },
106448
106449 selectOne: function(element) {
106450 var index = element.selectedIndex;
106451 return index >= 0 ? this.optionValue(element.options[index]) : null;
106452 },
106453
106454 selectMany: function(element) {
106455 var values, length = element.length;
106456 if (!length) return null;
106457
106458 for (var i = 0, values = []; i < length; i++) {
106459 var opt = element.options[i];
106460 if (opt.selected) values.push(this.optionValue(opt));
106461 }
106462 return values;
106463 },
106464
106465 optionValue: function(opt) {
106466 // extend element because hasAttribute may not be native
106467 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
106468 }
106469 };
106470
106471 /*--------------------------------------------------------------------------*/
106472
106473 Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
106474 initialize: function($super, element, frequency, callback) {
106475 $super(callback, frequency);
106476 this.element = $(element);
106477 this.lastValue = this.getValue();
106478 },
106479
106480 execute: function() {
106481 var value = this.getValue();
106482 if (Object.isString(this.lastValue) && Object.isString(value) ?
106483 this.lastValue != value : String(this.lastValue) != String(value)) {
106484 this.callback(this.element, value);
106485 this.lastValue = value;
106486 }
106487 }
106488 });
106489
106490 Form.Element.Observer = Class.create(Abstract.TimedObserver, {
106491 getValue: function() {
106492 return Form.Element.getValue(this.element);
106493 }
106494 });
106495
106496 Form.Observer = Class.create(Abstract.TimedObserver, {
106497 getValue: function() {
106498 return Form.serialize(this.element);
106499 }
106500 });
106501
106502 /*--------------------------------------------------------------------------*/
106503
106504 Abstract.EventObserver = Class.create({
106505 initialize: function(element, callback) {
106506 this.element = $(element);
106507 this.callback = callback;
106508
106509 this.lastValue = this.getValue();
106510 if (this.element.tagName.toLowerCase() == 'form')
106511 this.registerFormCallbacks();
106512 else
106513 this.registerCallback(this.element);
106514 },
106515
106516 onElementEvent: function() {
106517 var value = this.getValue();
106518 if (this.lastValue != value) {
106519 this.callback(this.element, value);
106520 this.lastValue = value;
106521 }
106522 },
106523
106524 registerFormCallbacks: function() {
106525 Form.getElements(this.element).each(this.registerCallback, this);
106526 },
106527
106528 registerCallback: function(element) {
106529 if (element.type) {
106530 switch (element.type.toLowerCase()) {
106531 case 'checkbox':
106532 case 'radio':
106533 Event.observe(element, 'click', this.onElementEvent.bind(this));
106534 break;
106535 default:
106536 Event.observe(element, 'change', this.onElementEvent.bind(this));
106537 break;
106538 }
106539 }
106540 }
106541 });
106542
106543 Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
106544 getValue: function() {
106545 return Form.Element.getValue(this.element);
106546 }
106547 });
106548
106549 Form.EventObserver = Class.create(Abstract.EventObserver, {
106550 getValue: function() {
106551 return Form.serialize(this.element);
106552 }
106553 });
106554 if (!window.Event) var Event = { };
106555
106556 Object.extend(Event, {
106557 KEY_BACKSPACE: 8,
106558 KEY_TAB: 9,
106559 KEY_RETURN: 13,
106560 KEY_ESC: 27,
106561 KEY_LEFT: 37,
106562 KEY_UP: 38,
106563 KEY_RIGHT: 39,
106564 KEY_DOWN: 40,
106565 KEY_DELETE: 46,
106566 KEY_HOME: 36,
106567 KEY_END: 35,
106568 KEY_PAGEUP: 33,
106569 KEY_PAGEDOWN: 34,
106570 KEY_INSERT: 45,
106571
106572 cache: { },
106573
106574 relatedTarget: function(event) {
106575 var element;
106576 switch(event.type) {
106577 case 'mouseover': element = event.fromElement; break;
106578 case 'mouseout': element = event.toElement; break;
106579 default: return null;
106580 }
106581 return Element.extend(element);
106582 }
106583 });
106584
106585 Event.Methods = (function() {
106586 var isButton;
106587
106588 if (Prototype.Browser.IE) {
106589 var buttonMap = { 0: 1, 1: 4, 2: 2 };
106590 isButton = function(event, code) {
106591 return event.button == buttonMap[code];
106592 };
106593
106594 } else if (Prototype.Browser.WebKit) {
106595 isButton = function(event, code) {
106596 switch (code) {
106597 case 0: return event.which == 1 && !event.metaKey;
106598 case 1: return event.which == 1 && event.metaKey;
106599 default: return false;
106600 }
106601 };
106602
106603 } else {
106604 isButton = function(event, code) {
106605 return event.which ? (event.which === code + 1) : (event.button === code);
106606 };
106607 }
106608
106609 return {
106610 isLeftClick: function(event) { return isButton(event, 0) },
106611 isMiddleClick: function(event) { return isButton(event, 1) },
106612 isRightClick: function(event) { return isButton(event, 2) },
106613
106614 element: function(event) {
106615 var node = Event.extend(event).target;
106616 return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
106617 },
106618
106619 findElement: function(event, expression) {
106620 var element = Event.element(event);
106621 return element.match(expression) ? element : element.up(expression);
106622 },
106623
106624 pointer: function(event) {
106625 return {
106626 x: event.pageX || (event.clientX +
106627 (document.documentElement.scrollLeft || document.body.scrollLeft)),
106628 y: event.pageY || (event.clientY +
106629 (document.documentElement.scrollTop || document.body.scrollTop))
106630 };
106631 },
106632
106633 pointerX: function(event) { return Event.pointer(event).x },
106634 pointerY: function(event) { return Event.pointer(event).y },
106635
106636 stop: function(event) {
106637 Event.extend(event);
106638 event.preventDefault();
106639 event.stopPropagation();
106640 event.stopped = true;
106641 }
106642 };
106643 })();
106644
106645 Event.extend = (function() {
106646 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
106647 m[name] = Event.Methods[name].methodize();
106648 return m;
106649 });
106650
106651 if (Prototype.Browser.IE) {
106652 Object.extend(methods, {
106653 stopPropagation: function() { this.cancelBubble = true },
106654 preventDefault: function() { this.returnValue = false },
106655 inspect: function() { return "[object Event]" }
106656 });
106657
106658 return function(event) {
106659 if (!event) return false;
106660 if (event._extendedByPrototype) return event;
106661
106662 event._extendedByPrototype = Prototype.emptyFunction;
106663 var pointer = Event.pointer(event);
106664 Object.extend(event, {
106665 target: event.srcElement,
106666 relatedTarget: Event.relatedTarget(event),
106667 pageX: pointer.x,
106668 pageY: pointer.y
106669 });
106670 return Object.extend(event, methods);
106671 };
106672
106673 } else {
106674 Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
106675 Object.extend(Event.prototype, methods);
106676 return Prototype.K;
106677 }
106678 })();
106679
106680 Object.extend(Event, (function() {
106681 var cache = Event.cache;
106682
106683 function getEventID(element) {
106684 if (element._eventID) return element._eventID;
106685 arguments.callee.id = arguments.callee.id || 1;
106686 return element._eventID = ++arguments.callee.id;
106687 }
106688
106689 function getDOMEventName(eventName) {
106690 if (eventName && eventName.include(':')) return "dataavailable";
106691 return eventName;
106692 }
106693
106694 function getCacheForID(id) {
106695 return cache[id] = cache[id] || { };
106696 }
106697
106698 function getWrappersForEventName(id, eventName) {
106699 var c = getCacheForID(id);
106700 return c[eventName] = c[eventName] || [];
106701 }
106702
106703 function createWrapper(element, eventName, handler) {
106704 var id = getEventID(element);
106705 var c = getWrappersForEventName(id, eventName);
106706 if (c.pluck("handler").include(handler)) return false;
106707
106708 var wrapper = function(event) {
106709 if (!Event || !Event.extend ||
106710 (event.eventName && event.eventName != eventName))
106711 return false;
106712
106713 Event.extend(event);
106714 handler.call(element, event)
106715 };
106716
106717 wrapper.handler = handler;
106718 c.push(wrapper);
106719 return wrapper;
106720 }
106721
106722 function findWrapper(id, eventName, handler) {
106723 var c = getWrappersForEventName(id, eventName);
106724 return c.find(function(wrapper) { return wrapper.handler == handler });
106725 }
106726
106727 function destroyWrapper(id, eventName, handler) {
106728 var c = getCacheForID(id);
106729 if (!c[eventName]) return false;
106730 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
106731 }
106732
106733 function destroyCache() {
106734 for (var id in cache)
106735 for (var eventName in cache[id])
106736 cache[id][eventName] = null;
106737 }
106738
106739 if (window.attachEvent) {
106740 window.attachEvent("onunload", destroyCache);
106741 }
106742
106743 return {
106744 observe: function(element, eventName, handler) {
106745 element = $(element);
106746 var name = getDOMEventName(eventName);
106747
106748 var wrapper = createWrapper(element, eventName, handler);
106749 if (!wrapper) return element;
106750
106751 if (element.addEventListener) {
106752 element.addEventListener(name, wrapper, false);
106753 } else {
106754 element.attachEvent("on" + name, wrapper);
106755 }
106756
106757 return element;
106758 },
106759
106760 stopObserving: function(element, eventName, handler) {
106761 element = $(element);
106762 var id = getEventID(element), name = getDOMEventName(eventName);
106763
106764 if (!handler && eventName) {
106765 getWrappersForEventName(id, eventName).each(function(wrapper) {
106766 element.stopObserving(eventName, wrapper.handler);
106767 });
106768 return element;
106769
106770 } else if (!eventName) {
106771 Object.keys(getCacheForID(id)).each(function(eventName) {
106772 element.stopObserving(eventName);
106773 });
106774 return element;
106775 }
106776
106777 var wrapper = findWrapper(id, eventName, handler);
106778 if (!wrapper) return element;
106779
106780 if (element.removeEventListener) {
106781 element.removeEventListener(name, wrapper, false);
106782 } else {
106783 element.detachEvent("on" + name, wrapper);
106784 }
106785
106786 destroyWrapper(id, eventName, handler);
106787
106788 return element;
106789 },
106790
106791 fire: function(element, eventName, memo) {
106792 element = $(element);
106793 if (element == document && document.createEvent && !element.dispatchEvent)
106794 element = document.documentElement;
106795
106796 if (document.createEvent) {
106797 var event = document.createEvent("HTMLEvents");
106798 event.initEvent("dataavailable", true, true);
106799 } else {
106800 var event = document.createEventObject();
106801 event.eventType = "ondataavailable";
106802 }
106803
106804 event.eventName = eventName;
106805 event.memo = memo || { };
106806
106807 if (document.createEvent) {
106808 element.dispatchEvent(event);
106809 } else {
106810 element.fireEvent(event.eventType, event);
106811 }
106812
106813 return event;
106814 }
106815 };
106816 })());
106817
106818 Object.extend(Event, Event.Methods);
106819
106820 Element.addMethods({
106821 fire: Event.fire,
106822 observe: Event.observe,
106823 stopObserving: Event.stopObserving
106824 });
106825
106826 Object.extend(document, {
106827 fire: Element.Methods.fire.methodize(),
106828 observe: Element.Methods.observe.methodize(),
106829 stopObserving: Element.Methods.stopObserving.methodize()
106830 });
106831
106832 (function() {
106833 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
106834 Matthias Miller, Dean Edwards and John Resig. */
106835
106836 var timer, fired = false;
106837
106838 function fireContentLoadedEvent() {
106839 if (fired) return;
106840 if (timer) window.clearInterval(timer);
106841 document.fire("dom:loaded");
106842 fired = true;
106843 }
106844
106845 if (document.addEventListener) {
106846 if (Prototype.Browser.WebKit) {
106847 timer = window.setInterval(function() {
106848 if (/loaded|complete/.test(document.readyState))
106849 fireContentLoadedEvent();
106850 }, 0);
106851
106852 Event.observe(window, "load", fireContentLoadedEvent);
106853
106854 } else {
106855 document.addEventListener("DOMContentLoaded",
106856 fireContentLoadedEvent, false);
106857 }
106858
106859 } else {
106860 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
106861 $("__onDOMContentLoaded").onreadystatechange = function() {
106862 if (this.readyState == "complete") {
106863 this.onreadystatechange = null;
106864 fireContentLoadedEvent();
106865 }
106866 };
106867 }
106868 })();
106869 /*------------------------------- DEPRECATED -------------------------------*/
106870
106871 Hash.toQueryString = Object.toQueryString;
106872
106873 var Toggle = { display: Element.toggle };
106874
106875 Element.Methods.childOf = Element.Methods.descendantOf;
106876
106877 var Insertion = {
106878 Before: function(element, content) {
106879 return Element.insert(element, {before:content});
106880 },
106881
106882 Top: function(element, content) {
106883 return Element.insert(element, {top:content});
106884 },
106885
106886 Bottom: function(element, content) {
106887 return Element.insert(element, {bottom:content});
106888 },
106889
106890 After: function(element, content) {
106891 return Element.insert(element, {after:content});
106892 }
106893 };
106894
106895 var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
106896
106897 // This should be moved to script.aculo.us; notice the deprecated methods
106898 // further below, that map to the newer Element methods.
106899 var Position = {
106900 // set to true if needed, warning: firefox performance problems
106901 // NOT neeeded for page scrolling, only if draggable contained in
106902 // scrollable elements
106903 includeScrollOffsets: false,
106904
106905 // must be called before calling withinIncludingScrolloffset, every time the
106906 // page is scrolled
106907 prepare: function() {
106908 this.deltaX = window.pageXOffset
106909 || document.documentElement.scrollLeft
106910 || document.body.scrollLeft
106911 || 0;
106912 this.deltaY = window.pageYOffset
106913 || document.documentElement.scrollTop
106914 || document.body.scrollTop
106915 || 0;
106916 },
106917
106918 // caches x/y coordinate pair to use with overlap
106919 within: function(element, x, y) {
106920 if (this.includeScrollOffsets)
106921 return this.withinIncludingScrolloffsets(element, x, y);
106922 this.xcomp = x;
106923 this.ycomp = y;
106924 this.offset = Element.cumulativeOffset(element);
106925
106926 return (y >= this.offset[1] &&
106927 y < this.offset[1] + element.offsetHeight &&
106928 x >= this.offset[0] &&
106929 x < this.offset[0] + element.offsetWidth);
106930 },
106931
106932 withinIncludingScrolloffsets: function(element, x, y) {
106933 var offsetcache = Element.cumulativeScrollOffset(element);
106934
106935 this.xcomp = x + offsetcache[0] - this.deltaX;
106936 this.ycomp = y + offsetcache[1] - this.deltaY;
106937 this.offset = Element.cumulativeOffset(element);
106938
106939 return (this.ycomp >= this.offset[1] &&
106940 this.ycomp < this.offset[1] + element.offsetHeight &&
106941 this.xcomp >= this.offset[0] &&
106942 this.xcomp < this.offset[0] + element.offsetWidth);
106943 },
106944
106945 // within must be called directly before
106946 overlap: function(mode, element) {
106947 if (!mode) return 0;
106948 if (mode == 'vertical')
106949 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
106950 element.offsetHeight;
106951 if (mode == 'horizontal')
106952 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
106953 element.offsetWidth;
106954 },
106955
106956 // Deprecation layer -- use newer Element methods now (1.5.2).
106957
106958 cumulativeOffset: Element.Methods.cumulativeOffset,
106959
106960 positionedOffset: Element.Methods.positionedOffset,
106961
106962 absolutize: function(element) {
106963 Position.prepare();
106964 return Element.absolutize(element);
106965 },
106966
106967 relativize: function(element) {
106968 Position.prepare();
106969 return Element.relativize(element);
106970 },
106971
106972 realOffset: Element.Methods.cumulativeScrollOffset,
106973
106974 offsetParent: Element.Methods.getOffsetParent,
106975
106976 page: Element.Methods.viewportOffset,
106977
106978 clone: function(source, target, options) {
106979 options = options || { };
106980 return Element.clonePosition(target, source, options);
106981 }
106982 };
106983
106984 /*--------------------------------------------------------------------------*/
106985
106986 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
106987 function iter(name) {
106988 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
106989 }
106990
106991 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
106992 function(element, className) {
106993 className = className.toString().strip();
106994 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
106995 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
106996 } : function(element, className) {
106997 className = className.toString().strip();
106998 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
106999 if (!classNames && !className) return elements;
107000
107001 var nodes = $(element).getElementsByTagName('*');
107002 className = ' ' + className + ' ';
107003
107004 for (var i = 0, child, cn; child = nodes[i]; i++) {
107005 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
107006 (classNames && classNames.all(function(name) {
107007 return !name.toString().blank() && cn.include(' ' + name + ' ');
107008 }))))
107009 elements.push(Element.extend(child));
107010 }
107011 return elements;
107012 };
107013
107014 return function(className, parentElement) {
107015 return $(parentElement || document.body).getElementsByClassName(className);
107016 };
107017 }(Element.Methods);
107018
107019 /*--------------------------------------------------------------------------*/
107020
107021 Element.ClassNames = Class.create();
107022 Element.ClassNames.prototype = {
107023 initialize: function(element) {
107024 this.element = $(element);
107025 },
107026
107027 _each: function(iterator) {
107028 this.element.className.split(/\s+/).select(function(name) {
107029 return name.length > 0;
107030 })._each(iterator);
107031 },
107032
107033 set: function(className) {
107034 this.element.className = className;
107035 },
107036
107037 add: function(classNameToAdd) {
107038 if (this.include(classNameToAdd)) return;
107039 this.set($A(this).concat(classNameToAdd).join(' '));
107040 },
107041
107042 remove: function(classNameToRemove) {
107043 if (!this.include(classNameToRemove)) return;
107044 this.set($A(this).without(classNameToRemove).join(' '));
107045 },
107046
107047 toString: function() {
107048 return $A(this).join(' ');
107049 }
107050 };
107051
107052 Object.extend(Element.ClassNames.prototype, Enumerable);
107053
107054 /*--------------------------------------------------------------------------*/
107055
107056 Element.addMethods();