-
+ 066CB61E50765A665D7A67D70150FDD04668DAB0D87C5B98EB13FDCCBAB0C79E1DD904C870C73C8871DDD2A2EA20F0975F10CC0D7643FB00D12B9D414A4D6E29
mp-wp/wp-includes/js/scriptaculous/prototype.js
(0 . 0)(1 . 4184)
110885 /* Prototype JavaScript framework, version 1.6.0
110886 * (c) 2005-2007 Sam Stephenson
110887 *
110888 * Prototype is freely distributable under the terms of an MIT-style license.
110889 * For details, see the Prototype web site: http://www.prototypejs.org/
110890 *
110891 *--------------------------------------------------------------------------*/
110892
110893 var Prototype = {
110894 Version: '1.6.0',
110895
110896 Browser: {
110897 IE: !!(window.attachEvent && !window.opera),
110898 Opera: !!window.opera,
110899 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
110900 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
110901 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
110902 },
110903
110904 BrowserFeatures: {
110905 XPath: !!document.evaluate,
110906 ElementExtensions: !!window.HTMLElement,
110907 SpecificElementExtensions:
110908 document.createElement('div').__proto__ &&
110909 document.createElement('div').__proto__ !==
110910 document.createElement('form').__proto__
110911 },
110912
110913 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
110914 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
110915
110916 emptyFunction: function() { },
110917 K: function(x) { return x }
110918 };
110919
110920 if (Prototype.Browser.MobileSafari)
110921 Prototype.BrowserFeatures.SpecificElementExtensions = false;
110922
110923 if (Prototype.Browser.WebKit)
110924 Prototype.BrowserFeatures.XPath = false;
110925
110926 /* Based on Alex Arnell's inheritance implementation. */
110927 var Class = {
110928 create: function() {
110929 var parent = null, properties = $A(arguments);
110930 if (Object.isFunction(properties[0]))
110931 parent = properties.shift();
110932
110933 function klass() {
110934 this.initialize.apply(this, arguments);
110935 }
110936
110937 Object.extend(klass, Class.Methods);
110938 klass.superclass = parent;
110939 klass.subclasses = [];
110940
110941 if (parent) {
110942 var subclass = function() { };
110943 subclass.prototype = parent.prototype;
110944 klass.prototype = new subclass;
110945 parent.subclasses.push(klass);
110946 }
110947
110948 for (var i = 0; i < properties.length; i++)
110949 klass.addMethods(properties[i]);
110950
110951 if (!klass.prototype.initialize)
110952 klass.prototype.initialize = Prototype.emptyFunction;
110953
110954 klass.prototype.constructor = klass;
110955
110956 return klass;
110957 }
110958 };
110959
110960 Class.Methods = {
110961 addMethods: function(source) {
110962 var ancestor = this.superclass && this.superclass.prototype;
110963 var properties = Object.keys(source);
110964
110965 if (!Object.keys({ toString: true }).length)
110966 properties.push("toString", "valueOf");
110967
110968 for (var i = 0, length = properties.length; i < length; i++) {
110969 var property = properties[i], value = source[property];
110970 if (ancestor && Object.isFunction(value) &&
110971 value.argumentNames().first() == "$super") {
110972 var method = value, value = Object.extend((function(m) {
110973 return function() { return ancestor[m].apply(this, arguments) };
110974 })(property).wrap(method), {
110975 valueOf: function() { return method },
110976 toString: function() { return method.toString() }
110977 });
110978 }
110979 this.prototype[property] = value;
110980 }
110981
110982 return this;
110983 }
110984 };
110985
110986 var Abstract = { };
110987
110988 Object.extend = function(destination, source) {
110989 for (var property in source)
110990 destination[property] = source[property];
110991 return destination;
110992 };
110993
110994 Object.extend(Object, {
110995 inspect: function(object) {
110996 try {
110997 if (object === undefined) return 'undefined';
110998 if (object === null) return 'null';
110999 return object.inspect ? object.inspect() : object.toString();
111000 } catch (e) {
111001 if (e instanceof RangeError) return '...';
111002 throw e;
111003 }
111004 },
111005
111006 toJSON: function(object) {
111007 var type = typeof object;
111008 switch (type) {
111009 case 'undefined':
111010 case 'function':
111011 case 'unknown': return;
111012 case 'boolean': return object.toString();
111013 }
111014
111015 if (object === null) return 'null';
111016 if (object.toJSON) return object.toJSON();
111017 if (Object.isElement(object)) return;
111018
111019 var results = [];
111020 for (var property in object) {
111021 var value = Object.toJSON(object[property]);
111022 if (value !== undefined)
111023 results.push(property.toJSON() + ': ' + value);
111024 }
111025
111026 return '{' + results.join(', ') + '}';
111027 },
111028
111029 toQueryString: function(object) {
111030 return $H(object).toQueryString();
111031 },
111032
111033 toHTML: function(object) {
111034 return object && object.toHTML ? object.toHTML() : String.interpret(object);
111035 },
111036
111037 keys: function(object) {
111038 var keys = [];
111039 for (var property in object)
111040 keys.push(property);
111041 return keys;
111042 },
111043
111044 values: function(object) {
111045 var values = [];
111046 for (var property in object)
111047 values.push(object[property]);
111048 return values;
111049 },
111050
111051 clone: function(object) {
111052 return Object.extend({ }, object);
111053 },
111054
111055 isElement: function(object) {
111056 return object && object.nodeType == 1;
111057 },
111058
111059 isArray: function(object) {
111060 return object && object.constructor === Array;
111061 },
111062
111063 isHash: function(object) {
111064 return object instanceof Hash;
111065 },
111066
111067 isFunction: function(object) {
111068 return typeof object == "function";
111069 },
111070
111071 isString: function(object) {
111072 return typeof object == "string";
111073 },
111074
111075 isNumber: function(object) {
111076 return typeof object == "number";
111077 },
111078
111079 isUndefined: function(object) {
111080 return typeof object == "undefined";
111081 }
111082 });
111083
111084 Object.extend(Function.prototype, {
111085 argumentNames: function() {
111086 var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
111087 return names.length == 1 && !names[0] ? [] : names;
111088 },
111089
111090 bind: function() {
111091 if (arguments.length < 2 && arguments[0] === undefined) return this;
111092 var __method = this, args = $A(arguments), object = args.shift();
111093 return function() {
111094 return __method.apply(object, args.concat($A(arguments)));
111095 }
111096 },
111097
111098 bindAsEventListener: function() {
111099 var __method = this, args = $A(arguments), object = args.shift();
111100 return function(event) {
111101 return __method.apply(object, [event || window.event].concat(args));
111102 }
111103 },
111104
111105 curry: function() {
111106 if (!arguments.length) return this;
111107 var __method = this, args = $A(arguments);
111108 return function() {
111109 return __method.apply(this, args.concat($A(arguments)));
111110 }
111111 },
111112
111113 delay: function() {
111114 var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
111115 return window.setTimeout(function() {
111116 return __method.apply(__method, args);
111117 }, timeout);
111118 },
111119
111120 wrap: function(wrapper) {
111121 var __method = this;
111122 return function() {
111123 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
111124 }
111125 },
111126
111127 methodize: function() {
111128 if (this._methodized) return this._methodized;
111129 var __method = this;
111130 return this._methodized = function() {
111131 return __method.apply(null, [this].concat($A(arguments)));
111132 };
111133 }
111134 });
111135
111136 Function.prototype.defer = Function.prototype.delay.curry(0.01);
111137
111138 Date.prototype.toJSON = function() {
111139 return '"' + this.getUTCFullYear() + '-' +
111140 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
111141 this.getUTCDate().toPaddedString(2) + 'T' +
111142 this.getUTCHours().toPaddedString(2) + ':' +
111143 this.getUTCMinutes().toPaddedString(2) + ':' +
111144 this.getUTCSeconds().toPaddedString(2) + 'Z"';
111145 };
111146
111147 var Try = {
111148 these: function() {
111149 var returnValue;
111150
111151 for (var i = 0, length = arguments.length; i < length; i++) {
111152 var lambda = arguments[i];
111153 try {
111154 returnValue = lambda();
111155 break;
111156 } catch (e) { }
111157 }
111158
111159 return returnValue;
111160 }
111161 };
111162
111163 RegExp.prototype.match = RegExp.prototype.test;
111164
111165 RegExp.escape = function(str) {
111166 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
111167 };
111168
111169 /*--------------------------------------------------------------------------*/
111170
111171 var PeriodicalExecuter = Class.create({
111172 initialize: function(callback, frequency) {
111173 this.callback = callback;
111174 this.frequency = frequency;
111175 this.currentlyExecuting = false;
111176
111177 this.registerCallback();
111178 },
111179
111180 registerCallback: function() {
111181 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
111182 },
111183
111184 execute: function() {
111185 this.callback(this);
111186 },
111187
111188 stop: function() {
111189 if (!this.timer) return;
111190 clearInterval(this.timer);
111191 this.timer = null;
111192 },
111193
111194 onTimerEvent: function() {
111195 if (!this.currentlyExecuting) {
111196 try {
111197 this.currentlyExecuting = true;
111198 this.execute();
111199 } finally {
111200 this.currentlyExecuting = false;
111201 }
111202 }
111203 }
111204 });
111205 Object.extend(String, {
111206 interpret: function(value) {
111207 return value == null ? '' : String(value);
111208 },
111209 specialChar: {
111210 '\b': '\\b',
111211 '\t': '\\t',
111212 '\n': '\\n',
111213 '\f': '\\f',
111214 '\r': '\\r',
111215 '\\': '\\\\'
111216 }
111217 });
111218
111219 Object.extend(String.prototype, {
111220 gsub: function(pattern, replacement) {
111221 var result = '', source = this, match;
111222 replacement = arguments.callee.prepareReplacement(replacement);
111223
111224 while (source.length > 0) {
111225 if (match = source.match(pattern)) {
111226 result += source.slice(0, match.index);
111227 result += String.interpret(replacement(match));
111228 source = source.slice(match.index + match[0].length);
111229 } else {
111230 result += source, source = '';
111231 }
111232 }
111233 return result;
111234 },
111235
111236 sub: function(pattern, replacement, count) {
111237 replacement = this.gsub.prepareReplacement(replacement);
111238 count = count === undefined ? 1 : count;
111239
111240 return this.gsub(pattern, function(match) {
111241 if (--count < 0) return match[0];
111242 return replacement(match);
111243 });
111244 },
111245
111246 scan: function(pattern, iterator) {
111247 this.gsub(pattern, iterator);
111248 return String(this);
111249 },
111250
111251 truncate: function(length, truncation) {
111252 length = length || 30;
111253 truncation = truncation === undefined ? '...' : truncation;
111254 return this.length > length ?
111255 this.slice(0, length - truncation.length) + truncation : String(this);
111256 },
111257
111258 strip: function() {
111259 return this.replace(/^\s+/, '').replace(/\s+$/, '');
111260 },
111261
111262 stripTags: function() {
111263 return this.replace(/<\/?[^>]+>/gi, '');
111264 },
111265
111266 stripScripts: function() {
111267 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
111268 },
111269
111270 extractScripts: function() {
111271 var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
111272 var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
111273 return (this.match(matchAll) || []).map(function(scriptTag) {
111274 return (scriptTag.match(matchOne) || ['', ''])[1];
111275 });
111276 },
111277
111278 evalScripts: function() {
111279 return this.extractScripts().map(function(script) { return eval(script) });
111280 },
111281
111282 escapeHTML: function() {
111283 var self = arguments.callee;
111284 self.text.data = this;
111285 return self.div.innerHTML;
111286 },
111287
111288 unescapeHTML: function() {
111289 var div = new Element('div');
111290 div.innerHTML = this.stripTags();
111291 return div.childNodes[0] ? (div.childNodes.length > 1 ?
111292 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
111293 div.childNodes[0].nodeValue) : '';
111294 },
111295
111296 toQueryParams: function(separator) {
111297 var match = this.strip().match(/([^?#]*)(#.*)?$/);
111298 if (!match) return { };
111299
111300 return match[1].split(separator || '&').inject({ }, function(hash, pair) {
111301 if ((pair = pair.split('='))[0]) {
111302 var key = decodeURIComponent(pair.shift());
111303 var value = pair.length > 1 ? pair.join('=') : pair[0];
111304 if (value != undefined) value = decodeURIComponent(value);
111305
111306 if (key in hash) {
111307 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
111308 hash[key].push(value);
111309 }
111310 else hash[key] = value;
111311 }
111312 return hash;
111313 });
111314 },
111315
111316 toArray: function() {
111317 return this.split('');
111318 },
111319
111320 succ: function() {
111321 return this.slice(0, this.length - 1) +
111322 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
111323 },
111324
111325 times: function(count) {
111326 return count < 1 ? '' : new Array(count + 1).join(this);
111327 },
111328
111329 camelize: function() {
111330 var parts = this.split('-'), len = parts.length;
111331 if (len == 1) return parts[0];
111332
111333 var camelized = this.charAt(0) == '-'
111334 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
111335 : parts[0];
111336
111337 for (var i = 1; i < len; i++)
111338 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
111339
111340 return camelized;
111341 },
111342
111343 capitalize: function() {
111344 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
111345 },
111346
111347 underscore: function() {
111348 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
111349 },
111350
111351 dasherize: function() {
111352 return this.gsub(/_/,'-');
111353 },
111354
111355 inspect: function(useDoubleQuotes) {
111356 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
111357 var character = String.specialChar[match[0]];
111358 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
111359 });
111360 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
111361 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
111362 },
111363
111364 toJSON: function() {
111365 return this.inspect(true);
111366 },
111367
111368 unfilterJSON: function(filter) {
111369 return this.sub(filter || Prototype.JSONFilter, '#{1}');
111370 },
111371
111372 isJSON: function() {
111373 var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
111374 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
111375 },
111376
111377 evalJSON: function(sanitize) {
111378 var json = this.unfilterJSON();
111379 try {
111380 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
111381 } catch (e) { }
111382 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
111383 },
111384
111385 include: function(pattern) {
111386 return this.indexOf(pattern) > -1;
111387 },
111388
111389 startsWith: function(pattern) {
111390 return this.indexOf(pattern) === 0;
111391 },
111392
111393 endsWith: function(pattern) {
111394 var d = this.length - pattern.length;
111395 return d >= 0 && this.lastIndexOf(pattern) === d;
111396 },
111397
111398 empty: function() {
111399 return this == '';
111400 },
111401
111402 blank: function() {
111403 return /^\s*$/.test(this);
111404 },
111405
111406 interpolate: function(object, pattern) {
111407 return new Template(this, pattern).evaluate(object);
111408 }
111409 });
111410
111411 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
111412 escapeHTML: function() {
111413 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
111414 },
111415 unescapeHTML: function() {
111416 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
111417 }
111418 });
111419
111420 String.prototype.gsub.prepareReplacement = function(replacement) {
111421 if (Object.isFunction(replacement)) return replacement;
111422 var template = new Template(replacement);
111423 return function(match) { return template.evaluate(match) };
111424 };
111425
111426 String.prototype.parseQuery = String.prototype.toQueryParams;
111427
111428 Object.extend(String.prototype.escapeHTML, {
111429 div: document.createElement('div'),
111430 text: document.createTextNode('')
111431 });
111432
111433 with (String.prototype.escapeHTML) div.appendChild(text);
111434
111435 var Template = Class.create({
111436 initialize: function(template, pattern) {
111437 this.template = template.toString();
111438 this.pattern = pattern || Template.Pattern;
111439 },
111440
111441 evaluate: function(object) {
111442 if (Object.isFunction(object.toTemplateReplacements))
111443 object = object.toTemplateReplacements();
111444
111445 return this.template.gsub(this.pattern, function(match) {
111446 if (object == null) return '';
111447
111448 var before = match[1] || '';
111449 if (before == '\\') return match[2];
111450
111451 var ctx = object, expr = match[3];
111452 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
111453 if (match == null) return before;
111454
111455 while (match != null) {
111456 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
111457 ctx = ctx[comp];
111458 if (null == ctx || '' == match[3]) break;
111459 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
111460 match = pattern.exec(expr);
111461 }
111462
111463 return before + String.interpret(ctx);
111464 }.bind(this));
111465 }
111466 });
111467 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
111468
111469 var $break = { };
111470
111471 var Enumerable = {
111472 each: function(iterator, context) {
111473 var index = 0;
111474 iterator = iterator.bind(context);
111475 try {
111476 this._each(function(value) {
111477 iterator(value, index++);
111478 });
111479 } catch (e) {
111480 if (e != $break) throw e;
111481 }
111482 return this;
111483 },
111484
111485 eachSlice: function(number, iterator, context) {
111486 iterator = iterator ? iterator.bind(context) : Prototype.K;
111487 var index = -number, slices = [], array = this.toArray();
111488 while ((index += number) < array.length)
111489 slices.push(array.slice(index, index+number));
111490 return slices.collect(iterator, context);
111491 },
111492
111493 all: function(iterator, context) {
111494 iterator = iterator ? iterator.bind(context) : Prototype.K;
111495 var result = true;
111496 this.each(function(value, index) {
111497 result = result && !!iterator(value, index);
111498 if (!result) throw $break;
111499 });
111500 return result;
111501 },
111502
111503 any: function(iterator, context) {
111504 iterator = iterator ? iterator.bind(context) : Prototype.K;
111505 var result = false;
111506 this.each(function(value, index) {
111507 if (result = !!iterator(value, index))
111508 throw $break;
111509 });
111510 return result;
111511 },
111512
111513 collect: function(iterator, context) {
111514 iterator = iterator ? iterator.bind(context) : Prototype.K;
111515 var results = [];
111516 this.each(function(value, index) {
111517 results.push(iterator(value, index));
111518 });
111519 return results;
111520 },
111521
111522 detect: function(iterator, context) {
111523 iterator = iterator.bind(context);
111524 var result;
111525 this.each(function(value, index) {
111526 if (iterator(value, index)) {
111527 result = value;
111528 throw $break;
111529 }
111530 });
111531 return result;
111532 },
111533
111534 findAll: function(iterator, context) {
111535 iterator = iterator.bind(context);
111536 var results = [];
111537 this.each(function(value, index) {
111538 if (iterator(value, index))
111539 results.push(value);
111540 });
111541 return results;
111542 },
111543
111544 grep: function(filter, iterator, context) {
111545 iterator = iterator ? iterator.bind(context) : Prototype.K;
111546 var results = [];
111547
111548 if (Object.isString(filter))
111549 filter = new RegExp(filter);
111550
111551 this.each(function(value, index) {
111552 if (filter.match(value))
111553 results.push(iterator(value, index));
111554 });
111555 return results;
111556 },
111557
111558 include: function(object) {
111559 if (Object.isFunction(this.indexOf))
111560 if (this.indexOf(object) != -1) return true;
111561
111562 var found = false;
111563 this.each(function(value) {
111564 if (value == object) {
111565 found = true;
111566 throw $break;
111567 }
111568 });
111569 return found;
111570 },
111571
111572 inGroupsOf: function(number, fillWith) {
111573 fillWith = fillWith === undefined ? null : fillWith;
111574 return this.eachSlice(number, function(slice) {
111575 while(slice.length < number) slice.push(fillWith);
111576 return slice;
111577 });
111578 },
111579
111580 inject: function(memo, iterator, context) {
111581 iterator = iterator.bind(context);
111582 this.each(function(value, index) {
111583 memo = iterator(memo, value, index);
111584 });
111585 return memo;
111586 },
111587
111588 invoke: function(method) {
111589 var args = $A(arguments).slice(1);
111590 return this.map(function(value) {
111591 return value[method].apply(value, args);
111592 });
111593 },
111594
111595 max: function(iterator, context) {
111596 iterator = iterator ? iterator.bind(context) : Prototype.K;
111597 var result;
111598 this.each(function(value, index) {
111599 value = iterator(value, index);
111600 if (result == undefined || value >= result)
111601 result = value;
111602 });
111603 return result;
111604 },
111605
111606 min: function(iterator, context) {
111607 iterator = iterator ? iterator.bind(context) : Prototype.K;
111608 var result;
111609 this.each(function(value, index) {
111610 value = iterator(value, index);
111611 if (result == undefined || value < result)
111612 result = value;
111613 });
111614 return result;
111615 },
111616
111617 partition: function(iterator, context) {
111618 iterator = iterator ? iterator.bind(context) : Prototype.K;
111619 var trues = [], falses = [];
111620 this.each(function(value, index) {
111621 (iterator(value, index) ?
111622 trues : falses).push(value);
111623 });
111624 return [trues, falses];
111625 },
111626
111627 pluck: function(property) {
111628 var results = [];
111629 this.each(function(value) {
111630 results.push(value[property]);
111631 });
111632 return results;
111633 },
111634
111635 reject: function(iterator, context) {
111636 iterator = iterator.bind(context);
111637 var results = [];
111638 this.each(function(value, index) {
111639 if (!iterator(value, index))
111640 results.push(value);
111641 });
111642 return results;
111643 },
111644
111645 sortBy: function(iterator, context) {
111646 iterator = iterator.bind(context);
111647 return this.map(function(value, index) {
111648 return {value: value, criteria: iterator(value, index)};
111649 }).sort(function(left, right) {
111650 var a = left.criteria, b = right.criteria;
111651 return a < b ? -1 : a > b ? 1 : 0;
111652 }).pluck('value');
111653 },
111654
111655 toArray: function() {
111656 return this.map();
111657 },
111658
111659 zip: function() {
111660 var iterator = Prototype.K, args = $A(arguments);
111661 if (Object.isFunction(args.last()))
111662 iterator = args.pop();
111663
111664 var collections = [this].concat(args).map($A);
111665 return this.map(function(value, index) {
111666 return iterator(collections.pluck(index));
111667 });
111668 },
111669
111670 size: function() {
111671 return this.toArray().length;
111672 },
111673
111674 inspect: function() {
111675 return '#<Enumerable:' + this.toArray().inspect() + '>';
111676 }
111677 };
111678
111679 Object.extend(Enumerable, {
111680 map: Enumerable.collect,
111681 find: Enumerable.detect,
111682 select: Enumerable.findAll,
111683 filter: Enumerable.findAll,
111684 member: Enumerable.include,
111685 entries: Enumerable.toArray,
111686 every: Enumerable.all,
111687 some: Enumerable.any
111688 });
111689 function $A(iterable) {
111690 if (!iterable) return [];
111691 if (iterable.toArray) return iterable.toArray();
111692 var length = iterable.length, results = new Array(length);
111693 while (length--) results[length] = iterable[length];
111694 return results;
111695 }
111696
111697 if (Prototype.Browser.WebKit) {
111698 function $A(iterable) {
111699 if (!iterable) return [];
111700 if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
111701 iterable.toArray) return iterable.toArray();
111702 var length = iterable.length, results = new Array(length);
111703 while (length--) results[length] = iterable[length];
111704 return results;
111705 }
111706 }
111707
111708 Array.from = $A;
111709
111710 Object.extend(Array.prototype, Enumerable);
111711
111712 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
111713
111714 Object.extend(Array.prototype, {
111715 _each: function(iterator) {
111716 for (var i = 0, length = this.length; i < length; i++)
111717 iterator(this[i]);
111718 },
111719
111720 clear: function() {
111721 this.length = 0;
111722 return this;
111723 },
111724
111725 first: function() {
111726 return this[0];
111727 },
111728
111729 last: function() {
111730 return this[this.length - 1];
111731 },
111732
111733 compact: function() {
111734 return this.select(function(value) {
111735 return value != null;
111736 });
111737 },
111738
111739 flatten: function() {
111740 return this.inject([], function(array, value) {
111741 return array.concat(Object.isArray(value) ?
111742 value.flatten() : [value]);
111743 });
111744 },
111745
111746 without: function() {
111747 var values = $A(arguments);
111748 return this.select(function(value) {
111749 return !values.include(value);
111750 });
111751 },
111752
111753 reverse: function(inline) {
111754 return (inline !== false ? this : this.toArray())._reverse();
111755 },
111756
111757 reduce: function() {
111758 return this.length > 1 ? this : this[0];
111759 },
111760
111761 uniq: function(sorted) {
111762 return this.inject([], function(array, value, index) {
111763 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
111764 array.push(value);
111765 return array;
111766 });
111767 },
111768
111769 intersect: function(array) {
111770 return this.uniq().findAll(function(item) {
111771 return array.detect(function(value) { return item === value });
111772 });
111773 },
111774
111775 clone: function() {
111776 return [].concat(this);
111777 },
111778
111779 size: function() {
111780 return this.length;
111781 },
111782
111783 inspect: function() {
111784 return '[' + this.map(Object.inspect).join(', ') + ']';
111785 },
111786
111787 toJSON: function() {
111788 var results = [];
111789 this.each(function(object) {
111790 var value = Object.toJSON(object);
111791 if (value !== undefined) results.push(value);
111792 });
111793 return '[' + results.join(', ') + ']';
111794 }
111795 });
111796
111797 // use native browser JS 1.6 implementation if available
111798 if (Object.isFunction(Array.prototype.forEach))
111799 Array.prototype._each = Array.prototype.forEach;
111800
111801 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
111802 i || (i = 0);
111803 var length = this.length;
111804 if (i < 0) i = length + i;
111805 for (; i < length; i++)
111806 if (this[i] === item) return i;
111807 return -1;
111808 };
111809
111810 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
111811 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
111812 var n = this.slice(0, i).reverse().indexOf(item);
111813 return (n < 0) ? n : i - n - 1;
111814 };
111815
111816 Array.prototype.toArray = Array.prototype.clone;
111817
111818 function $w(string) {
111819 if (!Object.isString(string)) return [];
111820 string = string.strip();
111821 return string ? string.split(/\s+/) : [];
111822 }
111823
111824 if (Prototype.Browser.Opera){
111825 Array.prototype.concat = function() {
111826 var array = [];
111827 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
111828 for (var i = 0, length = arguments.length; i < length; i++) {
111829 if (Object.isArray(arguments[i])) {
111830 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
111831 array.push(arguments[i][j]);
111832 } else {
111833 array.push(arguments[i]);
111834 }
111835 }
111836 return array;
111837 };
111838 }
111839 Object.extend(Number.prototype, {
111840 toColorPart: function() {
111841 return this.toPaddedString(2, 16);
111842 },
111843
111844 succ: function() {
111845 return this + 1;
111846 },
111847
111848 times: function(iterator) {
111849 $R(0, this, true).each(iterator);
111850 return this;
111851 },
111852
111853 toPaddedString: function(length, radix) {
111854 var string = this.toString(radix || 10);
111855 return '0'.times(length - string.length) + string;
111856 },
111857
111858 toJSON: function() {
111859 return isFinite(this) ? this.toString() : 'null';
111860 }
111861 });
111862
111863 $w('abs round ceil floor').each(function(method){
111864 Number.prototype[method] = Math[method].methodize();
111865 });
111866 function $H(object) {
111867 return new Hash(object);
111868 };
111869
111870 var Hash = Class.create(Enumerable, (function() {
111871 if (function() {
111872 var i = 0, Test = function(value) { this.key = value };
111873 Test.prototype.key = 'foo';
111874 for (var property in new Test('bar')) i++;
111875 return i > 1;
111876 }()) {
111877 function each(iterator) {
111878 var cache = [];
111879 for (var key in this._object) {
111880 var value = this._object[key];
111881 if (cache.include(key)) continue;
111882 cache.push(key);
111883 var pair = [key, value];
111884 pair.key = key;
111885 pair.value = value;
111886 iterator(pair);
111887 }
111888 }
111889 } else {
111890 function each(iterator) {
111891 for (var key in this._object) {
111892 var value = this._object[key], pair = [key, value];
111893 pair.key = key;
111894 pair.value = value;
111895 iterator(pair);
111896 }
111897 }
111898 }
111899
111900 function toQueryPair(key, value) {
111901 if (Object.isUndefined(value)) return key;
111902 return key + '=' + encodeURIComponent(String.interpret(value));
111903 }
111904
111905 return {
111906 initialize: function(object) {
111907 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
111908 },
111909
111910 _each: each,
111911
111912 set: function(key, value) {
111913 return this._object[key] = value;
111914 },
111915
111916 get: function(key) {
111917 return this._object[key];
111918 },
111919
111920 unset: function(key) {
111921 var value = this._object[key];
111922 delete this._object[key];
111923 return value;
111924 },
111925
111926 toObject: function() {
111927 return Object.clone(this._object);
111928 },
111929
111930 keys: function() {
111931 return this.pluck('key');
111932 },
111933
111934 values: function() {
111935 return this.pluck('value');
111936 },
111937
111938 index: function(value) {
111939 var match = this.detect(function(pair) {
111940 return pair.value === value;
111941 });
111942 return match && match.key;
111943 },
111944
111945 merge: function(object) {
111946 return this.clone().update(object);
111947 },
111948
111949 update: function(object) {
111950 return new Hash(object).inject(this, function(result, pair) {
111951 result.set(pair.key, pair.value);
111952 return result;
111953 });
111954 },
111955
111956 toQueryString: function() {
111957 return this.map(function(pair) {
111958 var key = encodeURIComponent(pair.key), values = pair.value;
111959
111960 if (values && typeof values == 'object') {
111961 if (Object.isArray(values))
111962 return values.map(toQueryPair.curry(key)).join('&');
111963 }
111964 return toQueryPair(key, values);
111965 }).join('&');
111966 },
111967
111968 inspect: function() {
111969 return '#<Hash:{' + this.map(function(pair) {
111970 return pair.map(Object.inspect).join(': ');
111971 }).join(', ') + '}>';
111972 },
111973
111974 toJSON: function() {
111975 return Object.toJSON(this.toObject());
111976 },
111977
111978 clone: function() {
111979 return new Hash(this);
111980 }
111981 }
111982 })());
111983
111984 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
111985 Hash.from = $H;
111986 var ObjectRange = Class.create(Enumerable, {
111987 initialize: function(start, end, exclusive) {
111988 this.start = start;
111989 this.end = end;
111990 this.exclusive = exclusive;
111991 },
111992
111993 _each: function(iterator) {
111994 var value = this.start;
111995 while (this.include(value)) {
111996 iterator(value);
111997 value = value.succ();
111998 }
111999 },
112000
112001 include: function(value) {
112002 if (value < this.start)
112003 return false;
112004 if (this.exclusive)
112005 return value < this.end;
112006 return value <= this.end;
112007 }
112008 });
112009
112010 var $R = function(start, end, exclusive) {
112011 return new ObjectRange(start, end, exclusive);
112012 };
112013
112014 var Ajax = {
112015 getTransport: function() {
112016 return Try.these(
112017 function() {return new XMLHttpRequest()},
112018 function() {return new ActiveXObject('Msxml2.XMLHTTP')},
112019 function() {return new ActiveXObject('Microsoft.XMLHTTP')}
112020 ) || false;
112021 },
112022
112023 activeRequestCount: 0
112024 };
112025
112026 Ajax.Responders = {
112027 responders: [],
112028
112029 _each: function(iterator) {
112030 this.responders._each(iterator);
112031 },
112032
112033 register: function(responder) {
112034 if (!this.include(responder))
112035 this.responders.push(responder);
112036 },
112037
112038 unregister: function(responder) {
112039 this.responders = this.responders.without(responder);
112040 },
112041
112042 dispatch: function(callback, request, transport, json) {
112043 this.each(function(responder) {
112044 if (Object.isFunction(responder[callback])) {
112045 try {
112046 responder[callback].apply(responder, [request, transport, json]);
112047 } catch (e) { }
112048 }
112049 });
112050 }
112051 };
112052
112053 Object.extend(Ajax.Responders, Enumerable);
112054
112055 Ajax.Responders.register({
112056 onCreate: function() { Ajax.activeRequestCount++ },
112057 onComplete: function() { Ajax.activeRequestCount-- }
112058 });
112059
112060 Ajax.Base = Class.create({
112061 initialize: function(options) {
112062 this.options = {
112063 method: 'post',
112064 asynchronous: true,
112065 contentType: 'application/x-www-form-urlencoded',
112066 encoding: 'UTF-8',
112067 parameters: '',
112068 evalJSON: true,
112069 evalJS: true
112070 };
112071 Object.extend(this.options, options || { });
112072
112073 this.options.method = this.options.method.toLowerCase();
112074 if (Object.isString(this.options.parameters))
112075 this.options.parameters = this.options.parameters.toQueryParams();
112076 }
112077 });
112078
112079 Ajax.Request = Class.create(Ajax.Base, {
112080 _complete: false,
112081
112082 initialize: function($super, url, options) {
112083 $super(options);
112084 this.transport = Ajax.getTransport();
112085 this.request(url);
112086 },
112087
112088 request: function(url) {
112089 this.url = url;
112090 this.method = this.options.method;
112091 var params = Object.clone(this.options.parameters);
112092
112093 if (!['get', 'post'].include(this.method)) {
112094 // simulate other verbs over post
112095 params['_method'] = this.method;
112096 this.method = 'post';
112097 }
112098
112099 this.parameters = params;
112100
112101 if (params = Object.toQueryString(params)) {
112102 // when GET, append parameters to URL
112103 if (this.method == 'get')
112104 this.url += (this.url.include('?') ? '&' : '?') + params;
112105 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
112106 params += '&_=';
112107 }
112108
112109 try {
112110 var response = new Ajax.Response(this);
112111 if (this.options.onCreate) this.options.onCreate(response);
112112 Ajax.Responders.dispatch('onCreate', this, response);
112113
112114 this.transport.open(this.method.toUpperCase(), this.url,
112115 this.options.asynchronous);
112116
112117 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
112118
112119 this.transport.onreadystatechange = this.onStateChange.bind(this);
112120 this.setRequestHeaders();
112121
112122 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
112123 this.transport.send(this.body);
112124
112125 /* Force Firefox to handle ready state 4 for synchronous requests */
112126 if (!this.options.asynchronous && this.transport.overrideMimeType)
112127 this.onStateChange();
112128
112129 }
112130 catch (e) {
112131 this.dispatchException(e);
112132 }
112133 },
112134
112135 onStateChange: function() {
112136 var readyState = this.transport.readyState;
112137 if (readyState > 1 && !((readyState == 4) && this._complete))
112138 this.respondToReadyState(this.transport.readyState);
112139 },
112140
112141 setRequestHeaders: function() {
112142 var headers = {
112143 'X-Requested-With': 'XMLHttpRequest',
112144 'X-Prototype-Version': Prototype.Version,
112145 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
112146 };
112147
112148 if (this.method == 'post') {
112149 headers['Content-type'] = this.options.contentType +
112150 (this.options.encoding ? '; charset=' + this.options.encoding : '');
112151
112152 /* Force "Connection: close" for older Mozilla browsers to work
112153 * around a bug where XMLHttpRequest sends an incorrect
112154 * Content-length header. See Mozilla Bugzilla #246651.
112155 */
112156 if (this.transport.overrideMimeType &&
112157 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
112158 headers['Connection'] = 'close';
112159 }
112160
112161 // user-defined headers
112162 if (typeof this.options.requestHeaders == 'object') {
112163 var extras = this.options.requestHeaders;
112164
112165 if (Object.isFunction(extras.push))
112166 for (var i = 0, length = extras.length; i < length; i += 2)
112167 headers[extras[i]] = extras[i+1];
112168 else
112169 $H(extras).each(function(pair) { headers[pair.key] = pair.value });
112170 }
112171
112172 for (var name in headers)
112173 this.transport.setRequestHeader(name, headers[name]);
112174 },
112175
112176 success: function() {
112177 var status = this.getStatus();
112178 return !status || (status >= 200 && status < 300);
112179 },
112180
112181 getStatus: function() {
112182 try {
112183 return this.transport.status || 0;
112184 } catch (e) { return 0 }
112185 },
112186
112187 respondToReadyState: function(readyState) {
112188 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
112189
112190 if (state == 'Complete') {
112191 try {
112192 this._complete = true;
112193 (this.options['on' + response.status]
112194 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
112195 || Prototype.emptyFunction)(response, response.headerJSON);
112196 } catch (e) {
112197 this.dispatchException(e);
112198 }
112199
112200 var contentType = response.getHeader('Content-type');
112201 if (this.options.evalJS == 'force'
112202 || (this.options.evalJS && contentType
112203 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
112204 this.evalResponse();
112205 }
112206
112207 try {
112208 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
112209 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
112210 } catch (e) {
112211 this.dispatchException(e);
112212 }
112213
112214 if (state == 'Complete') {
112215 // avoid memory leak in MSIE: clean up
112216 this.transport.onreadystatechange = Prototype.emptyFunction;
112217 }
112218 },
112219
112220 getHeader: function(name) {
112221 try {
112222 return this.transport.getResponseHeader(name);
112223 } catch (e) { return null }
112224 },
112225
112226 evalResponse: function() {
112227 try {
112228 return eval((this.transport.responseText || '').unfilterJSON());
112229 } catch (e) {
112230 this.dispatchException(e);
112231 }
112232 },
112233
112234 dispatchException: function(exception) {
112235 (this.options.onException || Prototype.emptyFunction)(this, exception);
112236 Ajax.Responders.dispatch('onException', this, exception);
112237 }
112238 });
112239
112240 Ajax.Request.Events =
112241 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
112242
112243 Ajax.Response = Class.create({
112244 initialize: function(request){
112245 this.request = request;
112246 var transport = this.transport = request.transport,
112247 readyState = this.readyState = transport.readyState;
112248
112249 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
112250 this.status = this.getStatus();
112251 this.statusText = this.getStatusText();
112252 this.responseText = String.interpret(transport.responseText);
112253 this.headerJSON = this._getHeaderJSON();
112254 }
112255
112256 if(readyState == 4) {
112257 var xml = transport.responseXML;
112258 this.responseXML = xml === undefined ? null : xml;
112259 this.responseJSON = this._getResponseJSON();
112260 }
112261 },
112262
112263 status: 0,
112264 statusText: '',
112265
112266 getStatus: Ajax.Request.prototype.getStatus,
112267
112268 getStatusText: function() {
112269 try {
112270 return this.transport.statusText || '';
112271 } catch (e) { return '' }
112272 },
112273
112274 getHeader: Ajax.Request.prototype.getHeader,
112275
112276 getAllHeaders: function() {
112277 try {
112278 return this.getAllResponseHeaders();
112279 } catch (e) { return null }
112280 },
112281
112282 getResponseHeader: function(name) {
112283 return this.transport.getResponseHeader(name);
112284 },
112285
112286 getAllResponseHeaders: function() {
112287 return this.transport.getAllResponseHeaders();
112288 },
112289
112290 _getHeaderJSON: function() {
112291 var json = this.getHeader('X-JSON');
112292 if (!json) return null;
112293 json = decodeURIComponent(escape(json));
112294 try {
112295 return json.evalJSON(this.request.options.sanitizeJSON);
112296 } catch (e) {
112297 this.request.dispatchException(e);
112298 }
112299 },
112300
112301 _getResponseJSON: function() {
112302 var options = this.request.options;
112303 if (!options.evalJSON || (options.evalJSON != 'force' &&
112304 !(this.getHeader('Content-type') || '').include('application/json')))
112305 return null;
112306 try {
112307 return this.transport.responseText.evalJSON(options.sanitizeJSON);
112308 } catch (e) {
112309 this.request.dispatchException(e);
112310 }
112311 }
112312 });
112313
112314 Ajax.Updater = Class.create(Ajax.Request, {
112315 initialize: function($super, container, url, options) {
112316 this.container = {
112317 success: (container.success || container),
112318 failure: (container.failure || (container.success ? null : container))
112319 };
112320
112321 options = options || { };
112322 var onComplete = options.onComplete;
112323 options.onComplete = (function(response, param) {
112324 this.updateContent(response.responseText);
112325 if (Object.isFunction(onComplete)) onComplete(response, param);
112326 }).bind(this);
112327
112328 $super(url, options);
112329 },
112330
112331 updateContent: function(responseText) {
112332 var receiver = this.container[this.success() ? 'success' : 'failure'],
112333 options = this.options;
112334
112335 if (!options.evalScripts) responseText = responseText.stripScripts();
112336
112337 if (receiver = $(receiver)) {
112338 if (options.insertion) {
112339 if (Object.isString(options.insertion)) {
112340 var insertion = { }; insertion[options.insertion] = responseText;
112341 receiver.insert(insertion);
112342 }
112343 else options.insertion(receiver, responseText);
112344 }
112345 else receiver.update(responseText);
112346 }
112347
112348 if (this.success()) {
112349 if (this.onComplete) this.onComplete.bind(this).defer();
112350 }
112351 }
112352 });
112353
112354 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
112355 initialize: function($super, container, url, options) {
112356 $super(options);
112357 this.onComplete = this.options.onComplete;
112358
112359 this.frequency = (this.options.frequency || 2);
112360 this.decay = (this.options.decay || 1);
112361
112362 this.updater = { };
112363 this.container = container;
112364 this.url = url;
112365
112366 this.start();
112367 },
112368
112369 start: function() {
112370 this.options.onComplete = this.updateComplete.bind(this);
112371 this.onTimerEvent();
112372 },
112373
112374 stop: function() {
112375 this.updater.options.onComplete = undefined;
112376 clearTimeout(this.timer);
112377 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
112378 },
112379
112380 updateComplete: function(response) {
112381 if (this.options.decay) {
112382 this.decay = (response.responseText == this.lastText ?
112383 this.decay * this.options.decay : 1);
112384
112385 this.lastText = response.responseText;
112386 }
112387 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
112388 },
112389
112390 onTimerEvent: function() {
112391 this.updater = new Ajax.Updater(this.container, this.url, this.options);
112392 }
112393 });
112394 function $(element) {
112395 if (arguments.length > 1) {
112396 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
112397 elements.push($(arguments[i]));
112398 return elements;
112399 }
112400 if (Object.isString(element))
112401 element = document.getElementById(element);
112402 return Element.extend(element);
112403 }
112404
112405 if (Prototype.BrowserFeatures.XPath) {
112406 document._getElementsByXPath = function(expression, parentElement) {
112407 var results = [];
112408 var query = document.evaluate(expression, $(parentElement) || document,
112409 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
112410 for (var i = 0, length = query.snapshotLength; i < length; i++)
112411 results.push(Element.extend(query.snapshotItem(i)));
112412 return results;
112413 };
112414 }
112415
112416 /*--------------------------------------------------------------------------*/
112417
112418 if (!window.Node) var Node = { };
112419
112420 if (!Node.ELEMENT_NODE) {
112421 // DOM level 2 ECMAScript Language Binding
112422 Object.extend(Node, {
112423 ELEMENT_NODE: 1,
112424 ATTRIBUTE_NODE: 2,
112425 TEXT_NODE: 3,
112426 CDATA_SECTION_NODE: 4,
112427 ENTITY_REFERENCE_NODE: 5,
112428 ENTITY_NODE: 6,
112429 PROCESSING_INSTRUCTION_NODE: 7,
112430 COMMENT_NODE: 8,
112431 DOCUMENT_NODE: 9,
112432 DOCUMENT_TYPE_NODE: 10,
112433 DOCUMENT_FRAGMENT_NODE: 11,
112434 NOTATION_NODE: 12
112435 });
112436 }
112437
112438 (function() {
112439 var element = this.Element;
112440 this.Element = function(tagName, attributes) {
112441 attributes = attributes || { };
112442 tagName = tagName.toLowerCase();
112443 var cache = Element.cache;
112444 if (Prototype.Browser.IE && attributes.name) {
112445 tagName = '<' + tagName + ' name="' + attributes.name + '">';
112446 delete attributes.name;
112447 return Element.writeAttribute(document.createElement(tagName), attributes);
112448 }
112449 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
112450 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
112451 };
112452 Object.extend(this.Element, element || { });
112453 }).call(window);
112454
112455 Element.cache = { };
112456
112457 Element.Methods = {
112458 visible: function(element) {
112459 return $(element).style.display != 'none';
112460 },
112461
112462 toggle: function(element) {
112463 element = $(element);
112464 Element[Element.visible(element) ? 'hide' : 'show'](element);
112465 return element;
112466 },
112467
112468 hide: function(element) {
112469 $(element).style.display = 'none';
112470 return element;
112471 },
112472
112473 show: function(element) {
112474 $(element).style.display = '';
112475 return element;
112476 },
112477
112478 remove: function(element) {
112479 element = $(element);
112480 element.parentNode.removeChild(element);
112481 return element;
112482 },
112483
112484 update: function(element, content) {
112485 element = $(element);
112486 if (content && content.toElement) content = content.toElement();
112487 if (Object.isElement(content)) return element.update().insert(content);
112488 content = Object.toHTML(content);
112489 element.innerHTML = content.stripScripts();
112490 content.evalScripts.bind(content).defer();
112491 return element;
112492 },
112493
112494 replace: function(element, content) {
112495 element = $(element);
112496 if (content && content.toElement) content = content.toElement();
112497 else if (!Object.isElement(content)) {
112498 content = Object.toHTML(content);
112499 var range = element.ownerDocument.createRange();
112500 range.selectNode(element);
112501 content.evalScripts.bind(content).defer();
112502 content = range.createContextualFragment(content.stripScripts());
112503 }
112504 element.parentNode.replaceChild(content, element);
112505 return element;
112506 },
112507
112508 insert: function(element, insertions) {
112509 element = $(element);
112510
112511 if (Object.isString(insertions) || Object.isNumber(insertions) ||
112512 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
112513 insertions = {bottom:insertions};
112514
112515 var content, t, range;
112516
112517 for (position in insertions) {
112518 content = insertions[position];
112519 position = position.toLowerCase();
112520 t = Element._insertionTranslations[position];
112521
112522 if (content && content.toElement) content = content.toElement();
112523 if (Object.isElement(content)) {
112524 t.insert(element, content);
112525 continue;
112526 }
112527
112528 content = Object.toHTML(content);
112529
112530 range = element.ownerDocument.createRange();
112531 t.initializeRange(element, range);
112532 t.insert(element, range.createContextualFragment(content.stripScripts()));
112533
112534 content.evalScripts.bind(content).defer();
112535 }
112536
112537 return element;
112538 },
112539
112540 wrap: function(element, wrapper, attributes) {
112541 element = $(element);
112542 if (Object.isElement(wrapper))
112543 $(wrapper).writeAttribute(attributes || { });
112544 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
112545 else wrapper = new Element('div', wrapper);
112546 if (element.parentNode)
112547 element.parentNode.replaceChild(wrapper, element);
112548 wrapper.appendChild(element);
112549 return wrapper;
112550 },
112551
112552 inspect: function(element) {
112553 element = $(element);
112554 var result = '<' + element.tagName.toLowerCase();
112555 $H({'id': 'id', 'className': 'class'}).each(function(pair) {
112556 var property = pair.first(), attribute = pair.last();
112557 var value = (element[property] || '').toString();
112558 if (value) result += ' ' + attribute + '=' + value.inspect(true);
112559 });
112560 return result + '>';
112561 },
112562
112563 recursivelyCollect: function(element, property) {
112564 element = $(element);
112565 var elements = [];
112566 while (element = element[property])
112567 if (element.nodeType == 1)
112568 elements.push(Element.extend(element));
112569 return elements;
112570 },
112571
112572 ancestors: function(element) {
112573 return $(element).recursivelyCollect('parentNode');
112574 },
112575
112576 descendants: function(element) {
112577 return $A($(element).getElementsByTagName('*')).each(Element.extend);
112578 },
112579
112580 firstDescendant: function(element) {
112581 element = $(element).firstChild;
112582 while (element && element.nodeType != 1) element = element.nextSibling;
112583 return $(element);
112584 },
112585
112586 immediateDescendants: function(element) {
112587 if (!(element = $(element).firstChild)) return [];
112588 while (element && element.nodeType != 1) element = element.nextSibling;
112589 if (element) return [element].concat($(element).nextSiblings());
112590 return [];
112591 },
112592
112593 previousSiblings: function(element) {
112594 return $(element).recursivelyCollect('previousSibling');
112595 },
112596
112597 nextSiblings: function(element) {
112598 return $(element).recursivelyCollect('nextSibling');
112599 },
112600
112601 siblings: function(element) {
112602 element = $(element);
112603 return element.previousSiblings().reverse().concat(element.nextSiblings());
112604 },
112605
112606 match: function(element, selector) {
112607 if (Object.isString(selector))
112608 selector = new Selector(selector);
112609 return selector.match($(element));
112610 },
112611
112612 up: function(element, expression, index) {
112613 element = $(element);
112614 if (arguments.length == 1) return $(element.parentNode);
112615 var ancestors = element.ancestors();
112616 return expression ? Selector.findElement(ancestors, expression, index) :
112617 ancestors[index || 0];
112618 },
112619
112620 down: function(element, expression, index) {
112621 element = $(element);
112622 if (arguments.length == 1) return element.firstDescendant();
112623 var descendants = element.descendants();
112624 return expression ? Selector.findElement(descendants, expression, index) :
112625 descendants[index || 0];
112626 },
112627
112628 previous: function(element, expression, index) {
112629 element = $(element);
112630 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
112631 var previousSiblings = element.previousSiblings();
112632 return expression ? Selector.findElement(previousSiblings, expression, index) :
112633 previousSiblings[index || 0];
112634 },
112635
112636 next: function(element, expression, index) {
112637 element = $(element);
112638 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
112639 var nextSiblings = element.nextSiblings();
112640 return expression ? Selector.findElement(nextSiblings, expression, index) :
112641 nextSiblings[index || 0];
112642 },
112643
112644 select: function() {
112645 var args = $A(arguments), element = $(args.shift());
112646 return Selector.findChildElements(element, args);
112647 },
112648
112649 adjacent: function() {
112650 var args = $A(arguments), element = $(args.shift());
112651 return Selector.findChildElements(element.parentNode, args).without(element);
112652 },
112653
112654 identify: function(element) {
112655 element = $(element);
112656 var id = element.readAttribute('id'), self = arguments.callee;
112657 if (id) return id;
112658 do { id = 'anonymous_element_' + self.counter++ } while ($(id));
112659 element.writeAttribute('id', id);
112660 return id;
112661 },
112662
112663 readAttribute: function(element, name) {
112664 element = $(element);
112665 if (Prototype.Browser.IE) {
112666 var t = Element._attributeTranslations.read;
112667 if (t.values[name]) return t.values[name](element, name);
112668 if (t.names[name]) name = t.names[name];
112669 if (name.include(':')) {
112670 return (!element.attributes || !element.attributes[name]) ? null :
112671 element.attributes[name].value;
112672 }
112673 }
112674 return element.getAttribute(name);
112675 },
112676
112677 writeAttribute: function(element, name, value) {
112678 element = $(element);
112679 var attributes = { }, t = Element._attributeTranslations.write;
112680
112681 if (typeof name == 'object') attributes = name;
112682 else attributes[name] = value === undefined ? true : value;
112683
112684 for (var attr in attributes) {
112685 var name = t.names[attr] || attr, value = attributes[attr];
112686 if (t.values[attr]) name = t.values[attr](element, value);
112687 if (value === false || value === null)
112688 element.removeAttribute(name);
112689 else if (value === true)
112690 element.setAttribute(name, name);
112691 else element.setAttribute(name, value);
112692 }
112693 return element;
112694 },
112695
112696 getHeight: function(element) {
112697 return $(element).getDimensions().height;
112698 },
112699
112700 getWidth: function(element) {
112701 return $(element).getDimensions().width;
112702 },
112703
112704 classNames: function(element) {
112705 return new Element.ClassNames(element);
112706 },
112707
112708 hasClassName: function(element, className) {
112709 if (!(element = $(element))) return;
112710 var elementClassName = element.className;
112711 return (elementClassName.length > 0 && (elementClassName == className ||
112712 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
112713 },
112714
112715 addClassName: function(element, className) {
112716 if (!(element = $(element))) return;
112717 if (!element.hasClassName(className))
112718 element.className += (element.className ? ' ' : '') + className;
112719 return element;
112720 },
112721
112722 removeClassName: function(element, className) {
112723 if (!(element = $(element))) return;
112724 element.className = element.className.replace(
112725 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
112726 return element;
112727 },
112728
112729 toggleClassName: function(element, className) {
112730 if (!(element = $(element))) return;
112731 return element[element.hasClassName(className) ?
112732 'removeClassName' : 'addClassName'](className);
112733 },
112734
112735 // removes whitespace-only text node children
112736 cleanWhitespace: function(element) {
112737 element = $(element);
112738 var node = element.firstChild;
112739 while (node) {
112740 var nextNode = node.nextSibling;
112741 if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
112742 element.removeChild(node);
112743 node = nextNode;
112744 }
112745 return element;
112746 },
112747
112748 empty: function(element) {
112749 return $(element).innerHTML.blank();
112750 },
112751
112752 descendantOf: function(element, ancestor) {
112753 element = $(element), ancestor = $(ancestor);
112754
112755 if (element.compareDocumentPosition)
112756 return (element.compareDocumentPosition(ancestor) & 8) === 8;
112757
112758 if (element.sourceIndex && !Prototype.Browser.Opera) {
112759 var e = element.sourceIndex, a = ancestor.sourceIndex,
112760 nextAncestor = ancestor.nextSibling;
112761 if (!nextAncestor) {
112762 do { ancestor = ancestor.parentNode; }
112763 while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
112764 }
112765 if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
112766 }
112767
112768 while (element = element.parentNode)
112769 if (element == ancestor) return true;
112770 return false;
112771 },
112772
112773 scrollTo: function(element) {
112774 element = $(element);
112775 var pos = element.cumulativeOffset();
112776 window.scrollTo(pos[0], pos[1]);
112777 return element;
112778 },
112779
112780 getStyle: function(element, style) {
112781 element = $(element);
112782 style = style == 'float' ? 'cssFloat' : style.camelize();
112783 var value = element.style[style];
112784 if (!value) {
112785 var css = document.defaultView.getComputedStyle(element, null);
112786 value = css ? css[style] : null;
112787 }
112788 if (style == 'opacity') return value ? parseFloat(value) : 1.0;
112789 return value == 'auto' ? null : value;
112790 },
112791
112792 getOpacity: function(element) {
112793 return $(element).getStyle('opacity');
112794 },
112795
112796 setStyle: function(element, styles) {
112797 element = $(element);
112798 var elementStyle = element.style, match;
112799 if (Object.isString(styles)) {
112800 element.style.cssText += ';' + styles;
112801 return styles.include('opacity') ?
112802 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
112803 }
112804 for (var property in styles)
112805 if (property == 'opacity') element.setOpacity(styles[property]);
112806 else
112807 elementStyle[(property == 'float' || property == 'cssFloat') ?
112808 (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
112809 property] = styles[property];
112810
112811 return element;
112812 },
112813
112814 setOpacity: function(element, value) {
112815 element = $(element);
112816 element.style.opacity = (value == 1 || value === '') ? '' :
112817 (value < 0.00001) ? 0 : value;
112818 return element;
112819 },
112820
112821 getDimensions: function(element) {
112822 element = $(element);
112823 var display = $(element).getStyle('display');
112824 if (display != 'none' && display != null) // Safari bug
112825 return {width: element.offsetWidth, height: element.offsetHeight};
112826
112827 // All *Width and *Height properties give 0 on elements with display none,
112828 // so enable the element temporarily
112829 var els = element.style;
112830 var originalVisibility = els.visibility;
112831 var originalPosition = els.position;
112832 var originalDisplay = els.display;
112833 els.visibility = 'hidden';
112834 els.position = 'absolute';
112835 els.display = 'block';
112836 var originalWidth = element.clientWidth;
112837 var originalHeight = element.clientHeight;
112838 els.display = originalDisplay;
112839 els.position = originalPosition;
112840 els.visibility = originalVisibility;
112841 return {width: originalWidth, height: originalHeight};
112842 },
112843
112844 makePositioned: function(element) {
112845 element = $(element);
112846 var pos = Element.getStyle(element, 'position');
112847 if (pos == 'static' || !pos) {
112848 element._madePositioned = true;
112849 element.style.position = 'relative';
112850 // Opera returns the offset relative to the positioning context, when an
112851 // element is position relative but top and left have not been defined
112852 if (window.opera) {
112853 element.style.top = 0;
112854 element.style.left = 0;
112855 }
112856 }
112857 return element;
112858 },
112859
112860 undoPositioned: function(element) {
112861 element = $(element);
112862 if (element._madePositioned) {
112863 element._madePositioned = undefined;
112864 element.style.position =
112865 element.style.top =
112866 element.style.left =
112867 element.style.bottom =
112868 element.style.right = '';
112869 }
112870 return element;
112871 },
112872
112873 makeClipping: function(element) {
112874 element = $(element);
112875 if (element._overflow) return element;
112876 element._overflow = Element.getStyle(element, 'overflow') || 'auto';
112877 if (element._overflow !== 'hidden')
112878 element.style.overflow = 'hidden';
112879 return element;
112880 },
112881
112882 undoClipping: function(element) {
112883 element = $(element);
112884 if (!element._overflow) return element;
112885 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
112886 element._overflow = null;
112887 return element;
112888 },
112889
112890 cumulativeOffset: function(element) {
112891 var valueT = 0, valueL = 0;
112892 do {
112893 valueT += element.offsetTop || 0;
112894 valueL += element.offsetLeft || 0;
112895 element = element.offsetParent;
112896 } while (element);
112897 return Element._returnOffset(valueL, valueT);
112898 },
112899
112900 positionedOffset: function(element) {
112901 var valueT = 0, valueL = 0;
112902 do {
112903 valueT += element.offsetTop || 0;
112904 valueL += element.offsetLeft || 0;
112905 element = element.offsetParent;
112906 if (element) {
112907 if (element.tagName == 'BODY') break;
112908 var p = Element.getStyle(element, 'position');
112909 if (p == 'relative' || p == 'absolute') break;
112910 }
112911 } while (element);
112912 return Element._returnOffset(valueL, valueT);
112913 },
112914
112915 absolutize: function(element) {
112916 element = $(element);
112917 if (element.getStyle('position') == 'absolute') return;
112918 // Position.prepare(); // To be done manually by Scripty when it needs it.
112919
112920 var offsets = element.positionedOffset();
112921 var top = offsets[1];
112922 var left = offsets[0];
112923 var width = element.clientWidth;
112924 var height = element.clientHeight;
112925
112926 element._originalLeft = left - parseFloat(element.style.left || 0);
112927 element._originalTop = top - parseFloat(element.style.top || 0);
112928 element._originalWidth = element.style.width;
112929 element._originalHeight = element.style.height;
112930
112931 element.style.position = 'absolute';
112932 element.style.top = top + 'px';
112933 element.style.left = left + 'px';
112934 element.style.width = width + 'px';
112935 element.style.height = height + 'px';
112936 return element;
112937 },
112938
112939 relativize: function(element) {
112940 element = $(element);
112941 if (element.getStyle('position') == 'relative') return;
112942 // Position.prepare(); // To be done manually by Scripty when it needs it.
112943
112944 element.style.position = 'relative';
112945 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
112946 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
112947
112948 element.style.top = top + 'px';
112949 element.style.left = left + 'px';
112950 element.style.height = element._originalHeight;
112951 element.style.width = element._originalWidth;
112952 return element;
112953 },
112954
112955 cumulativeScrollOffset: function(element) {
112956 var valueT = 0, valueL = 0;
112957 do {
112958 valueT += element.scrollTop || 0;
112959 valueL += element.scrollLeft || 0;
112960 element = element.parentNode;
112961 } while (element);
112962 return Element._returnOffset(valueL, valueT);
112963 },
112964
112965 getOffsetParent: function(element) {
112966 if (element.offsetParent) return $(element.offsetParent);
112967 if (element == document.body) return $(element);
112968
112969 while ((element = element.parentNode) && element != document.body)
112970 if (Element.getStyle(element, 'position') != 'static')
112971 return $(element);
112972
112973 return $(document.body);
112974 },
112975
112976 viewportOffset: function(forElement) {
112977 var valueT = 0, valueL = 0;
112978
112979 var element = forElement;
112980 do {
112981 valueT += element.offsetTop || 0;
112982 valueL += element.offsetLeft || 0;
112983
112984 // Safari fix
112985 if (element.offsetParent == document.body &&
112986 Element.getStyle(element, 'position') == 'absolute') break;
112987
112988 } while (element = element.offsetParent);
112989
112990 element = forElement;
112991 do {
112992 if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
112993 valueT -= element.scrollTop || 0;
112994 valueL -= element.scrollLeft || 0;
112995 }
112996 } while (element = element.parentNode);
112997
112998 return Element._returnOffset(valueL, valueT);
112999 },
113000
113001 clonePosition: function(element, source) {
113002 var options = Object.extend({
113003 setLeft: true,
113004 setTop: true,
113005 setWidth: true,
113006 setHeight: true,
113007 offsetTop: 0,
113008 offsetLeft: 0
113009 }, arguments[2] || { });
113010
113011 // find page position of source
113012 source = $(source);
113013 var p = source.viewportOffset();
113014
113015 // find coordinate system to use
113016 element = $(element);
113017 var delta = [0, 0];
113018 var parent = null;
113019 // delta [0,0] will do fine with position: fixed elements,
113020 // position:absolute needs offsetParent deltas
113021 if (Element.getStyle(element, 'position') == 'absolute') {
113022 parent = element.getOffsetParent();
113023 delta = parent.viewportOffset();
113024 }
113025
113026 // correct by body offsets (fixes Safari)
113027 if (parent == document.body) {
113028 delta[0] -= document.body.offsetLeft;
113029 delta[1] -= document.body.offsetTop;
113030 }
113031
113032 // set position
113033 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
113034 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
113035 if (options.setWidth) element.style.width = source.offsetWidth + 'px';
113036 if (options.setHeight) element.style.height = source.offsetHeight + 'px';
113037 return element;
113038 }
113039 };
113040
113041 Element.Methods.identify.counter = 1;
113042
113043 Object.extend(Element.Methods, {
113044 getElementsBySelector: Element.Methods.select,
113045 childElements: Element.Methods.immediateDescendants
113046 });
113047
113048 Element._attributeTranslations = {
113049 write: {
113050 names: {
113051 className: 'class',
113052 htmlFor: 'for'
113053 },
113054 values: { }
113055 }
113056 };
113057
113058
113059 if (!document.createRange || Prototype.Browser.Opera) {
113060 Element.Methods.insert = function(element, insertions) {
113061 element = $(element);
113062
113063 if (Object.isString(insertions) || Object.isNumber(insertions) ||
113064 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
113065 insertions = { bottom: insertions };
113066
113067 var t = Element._insertionTranslations, content, position, pos, tagName;
113068
113069 for (position in insertions) {
113070 content = insertions[position];
113071 position = position.toLowerCase();
113072 pos = t[position];
113073
113074 if (content && content.toElement) content = content.toElement();
113075 if (Object.isElement(content)) {
113076 pos.insert(element, content);
113077 continue;
113078 }
113079
113080 content = Object.toHTML(content);
113081 tagName = ((position == 'before' || position == 'after')
113082 ? element.parentNode : element).tagName.toUpperCase();
113083
113084 if (t.tags[tagName]) {
113085 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
113086 if (position == 'top' || position == 'after') fragments.reverse();
113087 fragments.each(pos.insert.curry(element));
113088 }
113089 else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
113090
113091 content.evalScripts.bind(content).defer();
113092 }
113093
113094 return element;
113095 };
113096 }
113097
113098 if (Prototype.Browser.Opera) {
113099 Element.Methods._getStyle = Element.Methods.getStyle;
113100 Element.Methods.getStyle = function(element, style) {
113101 switch(style) {
113102 case 'left':
113103 case 'top':
113104 case 'right':
113105 case 'bottom':
113106 if (Element._getStyle(element, 'position') == 'static') return null;
113107 default: return Element._getStyle(element, style);
113108 }
113109 };
113110 Element.Methods._readAttribute = Element.Methods.readAttribute;
113111 Element.Methods.readAttribute = function(element, attribute) {
113112 if (attribute == 'title') return element.title;
113113 return Element._readAttribute(element, attribute);
113114 };
113115 }
113116
113117 else if (Prototype.Browser.IE) {
113118 $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
113119 Element.Methods[method] = Element.Methods[method].wrap(
113120 function(proceed, element) {
113121 element = $(element);
113122 var position = element.getStyle('position');
113123 if (position != 'static') return proceed(element);
113124 element.setStyle({ position: 'relative' });
113125 var value = proceed(element);
113126 element.setStyle({ position: position });
113127 return value;
113128 }
113129 );
113130 });
113131
113132 Element.Methods.getStyle = function(element, style) {
113133 element = $(element);
113134 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
113135 var value = element.style[style];
113136 if (!value && element.currentStyle) value = element.currentStyle[style];
113137
113138 if (style == 'opacity') {
113139 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
113140 if (value[1]) return parseFloat(value[1]) / 100;
113141 return 1.0;
113142 }
113143
113144 if (value == 'auto') {
113145 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
113146 return element['offset' + style.capitalize()] + 'px';
113147 return null;
113148 }
113149 return value;
113150 };
113151
113152 Element.Methods.setOpacity = function(element, value) {
113153 function stripAlpha(filter){
113154 return filter.replace(/alpha\([^\)]*\)/gi,'');
113155 }
113156 element = $(element);
113157 var currentStyle = element.currentStyle;
113158 if ((currentStyle && !currentStyle.hasLayout) ||
113159 (!currentStyle && element.style.zoom == 'normal'))
113160 element.style.zoom = 1;
113161
113162 var filter = element.getStyle('filter'), style = element.style;
113163 if (value == 1 || value === '') {
113164 (filter = stripAlpha(filter)) ?
113165 style.filter = filter : style.removeAttribute('filter');
113166 return element;
113167 } else if (value < 0.00001) value = 0;
113168 style.filter = stripAlpha(filter) +
113169 'alpha(opacity=' + (value * 100) + ')';
113170 return element;
113171 };
113172
113173 Element._attributeTranslations = {
113174 read: {
113175 names: {
113176 'class': 'className',
113177 'for': 'htmlFor'
113178 },
113179 values: {
113180 _getAttr: function(element, attribute) {
113181 return element.getAttribute(attribute, 2);
113182 },
113183 _getAttrNode: function(element, attribute) {
113184 var node = element.getAttributeNode(attribute);
113185 return node ? node.value : "";
113186 },
113187 _getEv: function(element, attribute) {
113188 var attribute = element.getAttribute(attribute);
113189 return attribute ? attribute.toString().slice(23, -2) : null;
113190 },
113191 _flag: function(element, attribute) {
113192 return $(element).hasAttribute(attribute) ? attribute : null;
113193 },
113194 style: function(element) {
113195 return element.style.cssText.toLowerCase();
113196 },
113197 title: function(element) {
113198 return element.title;
113199 }
113200 }
113201 }
113202 };
113203
113204 Element._attributeTranslations.write = {
113205 names: Object.clone(Element._attributeTranslations.read.names),
113206 values: {
113207 checked: function(element, value) {
113208 element.checked = !!value;
113209 },
113210
113211 style: function(element, value) {
113212 element.style.cssText = value ? value : '';
113213 }
113214 }
113215 };
113216
113217 Element._attributeTranslations.has = {};
113218
113219 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
113220 'encType maxLength readOnly longDesc').each(function(attr) {
113221 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
113222 Element._attributeTranslations.has[attr.toLowerCase()] = attr;
113223 });
113224
113225 (function(v) {
113226 Object.extend(v, {
113227 href: v._getAttr,
113228 src: v._getAttr,
113229 type: v._getAttr,
113230 action: v._getAttrNode,
113231 disabled: v._flag,
113232 checked: v._flag,
113233 readonly: v._flag,
113234 multiple: v._flag,
113235 onload: v._getEv,
113236 onunload: v._getEv,
113237 onclick: v._getEv,
113238 ondblclick: v._getEv,
113239 onmousedown: v._getEv,
113240 onmouseup: v._getEv,
113241 onmouseover: v._getEv,
113242 onmousemove: v._getEv,
113243 onmouseout: v._getEv,
113244 onfocus: v._getEv,
113245 onblur: v._getEv,
113246 onkeypress: v._getEv,
113247 onkeydown: v._getEv,
113248 onkeyup: v._getEv,
113249 onsubmit: v._getEv,
113250 onreset: v._getEv,
113251 onselect: v._getEv,
113252 onchange: v._getEv
113253 });
113254 })(Element._attributeTranslations.read.values);
113255 }
113256
113257 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
113258 Element.Methods.setOpacity = function(element, value) {
113259 element = $(element);
113260 element.style.opacity = (value == 1) ? 0.999999 :
113261 (value === '') ? '' : (value < 0.00001) ? 0 : value;
113262 return element;
113263 };
113264 }
113265
113266 else if (Prototype.Browser.WebKit) {
113267 Element.Methods.setOpacity = function(element, value) {
113268 element = $(element);
113269 element.style.opacity = (value == 1 || value === '') ? '' :
113270 (value < 0.00001) ? 0 : value;
113271
113272 if (value == 1)
113273 if(element.tagName == 'IMG' && element.width) {
113274 element.width++; element.width--;
113275 } else try {
113276 var n = document.createTextNode(' ');
113277 element.appendChild(n);
113278 element.removeChild(n);
113279 } catch (e) { }
113280
113281 return element;
113282 };
113283
113284 // Safari returns margins on body which is incorrect if the child is absolutely
113285 // positioned. For performance reasons, redefine Position.cumulativeOffset for
113286 // KHTML/WebKit only.
113287 Element.Methods.cumulativeOffset = function(element) {
113288 var valueT = 0, valueL = 0;
113289 do {
113290 valueT += element.offsetTop || 0;
113291 valueL += element.offsetLeft || 0;
113292 if (element.offsetParent == document.body)
113293 if (Element.getStyle(element, 'position') == 'absolute') break;
113294
113295 element = element.offsetParent;
113296 } while (element);
113297
113298 return Element._returnOffset(valueL, valueT);
113299 };
113300 }
113301
113302 if (Prototype.Browser.IE || Prototype.Browser.Opera) {
113303 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
113304 Element.Methods.update = function(element, content) {
113305 element = $(element);
113306
113307 if (content && content.toElement) content = content.toElement();
113308 if (Object.isElement(content)) return element.update().insert(content);
113309
113310 content = Object.toHTML(content);
113311 var tagName = element.tagName.toUpperCase();
113312
113313 if (tagName in Element._insertionTranslations.tags) {
113314 $A(element.childNodes).each(function(node) { element.removeChild(node) });
113315 Element._getContentFromAnonymousElement(tagName, content.stripScripts())
113316 .each(function(node) { element.appendChild(node) });
113317 }
113318 else element.innerHTML = content.stripScripts();
113319
113320 content.evalScripts.bind(content).defer();
113321 return element;
113322 };
113323 }
113324
113325 if (document.createElement('div').outerHTML) {
113326 Element.Methods.replace = function(element, content) {
113327 element = $(element);
113328
113329 if (content && content.toElement) content = content.toElement();
113330 if (Object.isElement(content)) {
113331 element.parentNode.replaceChild(content, element);
113332 return element;
113333 }
113334
113335 content = Object.toHTML(content);
113336 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
113337
113338 if (Element._insertionTranslations.tags[tagName]) {
113339 var nextSibling = element.next();
113340 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
113341 parent.removeChild(element);
113342 if (nextSibling)
113343 fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
113344 else
113345 fragments.each(function(node) { parent.appendChild(node) });
113346 }
113347 else element.outerHTML = content.stripScripts();
113348
113349 content.evalScripts.bind(content).defer();
113350 return element;
113351 };
113352 }
113353
113354 Element._returnOffset = function(l, t) {
113355 var result = [l, t];
113356 result.left = l;
113357 result.top = t;
113358 return result;
113359 };
113360
113361 Element._getContentFromAnonymousElement = function(tagName, html) {
113362 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
113363 div.innerHTML = t[0] + html + t[1];
113364 t[2].times(function() { div = div.firstChild });
113365 return $A(div.childNodes);
113366 };
113367
113368 Element._insertionTranslations = {
113369 before: {
113370 adjacency: 'beforeBegin',
113371 insert: function(element, node) {
113372 element.parentNode.insertBefore(node, element);
113373 },
113374 initializeRange: function(element, range) {
113375 range.setStartBefore(element);
113376 }
113377 },
113378 top: {
113379 adjacency: 'afterBegin',
113380 insert: function(element, node) {
113381 element.insertBefore(node, element.firstChild);
113382 },
113383 initializeRange: function(element, range) {
113384 range.selectNodeContents(element);
113385 range.collapse(true);
113386 }
113387 },
113388 bottom: {
113389 adjacency: 'beforeEnd',
113390 insert: function(element, node) {
113391 element.appendChild(node);
113392 }
113393 },
113394 after: {
113395 adjacency: 'afterEnd',
113396 insert: function(element, node) {
113397 element.parentNode.insertBefore(node, element.nextSibling);
113398 },
113399 initializeRange: function(element, range) {
113400 range.setStartAfter(element);
113401 }
113402 },
113403 tags: {
113404 TABLE: ['<table>', '</table>', 1],
113405 TBODY: ['<table><tbody>', '</tbody></table>', 2],
113406 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
113407 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
113408 SELECT: ['<select>', '</select>', 1]
113409 }
113410 };
113411
113412 (function() {
113413 this.bottom.initializeRange = this.top.initializeRange;
113414 Object.extend(this.tags, {
113415 THEAD: this.tags.TBODY,
113416 TFOOT: this.tags.TBODY,
113417 TH: this.tags.TD
113418 });
113419 }).call(Element._insertionTranslations);
113420
113421 Element.Methods.Simulated = {
113422 hasAttribute: function(element, attribute) {
113423 attribute = Element._attributeTranslations.has[attribute] || attribute;
113424 var node = $(element).getAttributeNode(attribute);
113425 return node && node.specified;
113426 }
113427 };
113428
113429 Element.Methods.ByTag = { };
113430
113431 Object.extend(Element, Element.Methods);
113432
113433 if (!Prototype.BrowserFeatures.ElementExtensions &&
113434 document.createElement('div').__proto__) {
113435 window.HTMLElement = { };
113436 window.HTMLElement.prototype = document.createElement('div').__proto__;
113437 Prototype.BrowserFeatures.ElementExtensions = true;
113438 }
113439
113440 Element.extend = (function() {
113441 if (Prototype.BrowserFeatures.SpecificElementExtensions)
113442 return Prototype.K;
113443
113444 var Methods = { }, ByTag = Element.Methods.ByTag;
113445
113446 var extend = Object.extend(function(element) {
113447 if (!element || element._extendedByPrototype ||
113448 element.nodeType != 1 || element == window) return element;
113449
113450 var methods = Object.clone(Methods),
113451 tagName = element.tagName, property, value;
113452
113453 // extend methods for specific tags
113454 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
113455
113456 for (property in methods) {
113457 value = methods[property];
113458 if (Object.isFunction(value) && !(property in element))
113459 element[property] = value.methodize();
113460 }
113461
113462 element._extendedByPrototype = Prototype.emptyFunction;
113463 return element;
113464
113465 }, {
113466 refresh: function() {
113467 // extend methods for all tags (Safari doesn't need this)
113468 if (!Prototype.BrowserFeatures.ElementExtensions) {
113469 Object.extend(Methods, Element.Methods);
113470 Object.extend(Methods, Element.Methods.Simulated);
113471 }
113472 }
113473 });
113474
113475 extend.refresh();
113476 return extend;
113477 })();
113478
113479 Element.hasAttribute = function(element, attribute) {
113480 if (element.hasAttribute) return element.hasAttribute(attribute);
113481 return Element.Methods.Simulated.hasAttribute(element, attribute);
113482 };
113483
113484 Element.addMethods = function(methods) {
113485 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
113486
113487 if (!methods) {
113488 Object.extend(Form, Form.Methods);
113489 Object.extend(Form.Element, Form.Element.Methods);
113490 Object.extend(Element.Methods.ByTag, {
113491 "FORM": Object.clone(Form.Methods),
113492 "INPUT": Object.clone(Form.Element.Methods),
113493 "SELECT": Object.clone(Form.Element.Methods),
113494 "TEXTAREA": Object.clone(Form.Element.Methods)
113495 });
113496 }
113497
113498 if (arguments.length == 2) {
113499 var tagName = methods;
113500 methods = arguments[1];
113501 }
113502
113503 if (!tagName) Object.extend(Element.Methods, methods || { });
113504 else {
113505 if (Object.isArray(tagName)) tagName.each(extend);
113506 else extend(tagName);
113507 }
113508
113509 function extend(tagName) {
113510 tagName = tagName.toUpperCase();
113511 if (!Element.Methods.ByTag[tagName])
113512 Element.Methods.ByTag[tagName] = { };
113513 Object.extend(Element.Methods.ByTag[tagName], methods);
113514 }
113515
113516 function copy(methods, destination, onlyIfAbsent) {
113517 onlyIfAbsent = onlyIfAbsent || false;
113518 for (var property in methods) {
113519 var value = methods[property];
113520 if (!Object.isFunction(value)) continue;
113521 if (!onlyIfAbsent || !(property in destination))
113522 destination[property] = value.methodize();
113523 }
113524 }
113525
113526 function findDOMClass(tagName) {
113527 var klass;
113528 var trans = {
113529 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
113530 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
113531 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
113532 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
113533 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
113534 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
113535 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
113536 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
113537 "FrameSet", "IFRAME": "IFrame"
113538 };
113539 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
113540 if (window[klass]) return window[klass];
113541 klass = 'HTML' + tagName + 'Element';
113542 if (window[klass]) return window[klass];
113543 klass = 'HTML' + tagName.capitalize() + 'Element';
113544 if (window[klass]) return window[klass];
113545
113546 window[klass] = { };
113547 window[klass].prototype = document.createElement(tagName).__proto__;
113548 return window[klass];
113549 }
113550
113551 if (F.ElementExtensions) {
113552 copy(Element.Methods, HTMLElement.prototype);
113553 copy(Element.Methods.Simulated, HTMLElement.prototype, true);
113554 }
113555
113556 if (F.SpecificElementExtensions) {
113557 for (var tag in Element.Methods.ByTag) {
113558 var klass = findDOMClass(tag);
113559 if (Object.isUndefined(klass)) continue;
113560 copy(T[tag], klass.prototype);
113561 }
113562 }
113563
113564 Object.extend(Element, Element.Methods);
113565 delete Element.ByTag;
113566
113567 if (Element.extend.refresh) Element.extend.refresh();
113568 Element.cache = { };
113569 };
113570
113571 document.viewport = {
113572 getDimensions: function() {
113573 var dimensions = { };
113574 $w('width height').each(function(d) {
113575 var D = d.capitalize();
113576 dimensions[d] = self['inner' + D] ||
113577 (document.documentElement['client' + D] || document.body['client' + D]);
113578 });
113579 return dimensions;
113580 },
113581
113582 getWidth: function() {
113583 return this.getDimensions().width;
113584 },
113585
113586 getHeight: function() {
113587 return this.getDimensions().height;
113588 },
113589
113590 getScrollOffsets: function() {
113591 return Element._returnOffset(
113592 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
113593 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
113594 }
113595 };
113596 /* Portions of the Selector class are derived from Jack Slocum`s DomQuery,
113597 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
113598 * license. Please see http://www.yui-ext.com/ for more information. */
113599
113600 var Selector = Class.create({
113601 initialize: function(expression) {
113602 this.expression = expression.strip();
113603 this.compileMatcher();
113604 },
113605
113606 compileMatcher: function() {
113607 // Selectors with namespaced attributes can't use the XPath version
113608 if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
113609 return this.compileXPathMatcher();
113610
113611 var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
113612 c = Selector.criteria, le, p, m;
113613
113614 if (Selector._cache[e]) {
113615 this.matcher = Selector._cache[e];
113616 return;
113617 }
113618
113619 this.matcher = ["this.matcher = function(root) {",
113620 "var r = root, h = Selector.handlers, c = false, n;"];
113621
113622 while (e && le != e && (/\S/).test(e)) {
113623 le = e;
113624 for (var i in ps) {
113625 p = ps[i];
113626 if (m = e.match(p)) {
113627 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
113628 new Template(c[i]).evaluate(m));
113629 e = e.replace(m[0], '');
113630 break;
113631 }
113632 }
113633 }
113634
113635 this.matcher.push("return h.unique(n);\n}");
113636 eval(this.matcher.join('\n'));
113637 Selector._cache[this.expression] = this.matcher;
113638 },
113639
113640 compileXPathMatcher: function() {
113641 var e = this.expression, ps = Selector.patterns,
113642 x = Selector.xpath, le, m;
113643
113644 if (Selector._cache[e]) {
113645 this.xpath = Selector._cache[e]; return;
113646 }
113647
113648 this.matcher = ['.//*'];
113649 while (e && le != e && (/\S/).test(e)) {
113650 le = e;
113651 for (var i in ps) {
113652 if (m = e.match(ps[i])) {
113653 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
113654 new Template(x[i]).evaluate(m));
113655 e = e.replace(m[0], '');
113656 break;
113657 }
113658 }
113659 }
113660
113661 this.xpath = this.matcher.join('');
113662 Selector._cache[this.expression] = this.xpath;
113663 },
113664
113665 findElements: function(root) {
113666 root = root || document;
113667 if (this.xpath) return document._getElementsByXPath(this.xpath, root);
113668 return this.matcher(root);
113669 },
113670
113671 match: function(element) {
113672 this.tokens = [];
113673
113674 var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
113675 var le, p, m;
113676
113677 while (e && le !== e && (/\S/).test(e)) {
113678 le = e;
113679 for (var i in ps) {
113680 p = ps[i];
113681 if (m = e.match(p)) {
113682 // use the Selector.assertions methods unless the selector
113683 // is too complex.
113684 if (as[i]) {
113685 this.tokens.push([i, Object.clone(m)]);
113686 e = e.replace(m[0], '');
113687 } else {
113688 // reluctantly do a document-wide search
113689 // and look for a match in the array
113690 return this.findElements(document).include(element);
113691 }
113692 }
113693 }
113694 }
113695
113696 var match = true, name, matches;
113697 for (var i = 0, token; token = this.tokens[i]; i++) {
113698 name = token[0], matches = token[1];
113699 if (!Selector.assertions[name](element, matches)) {
113700 match = false; break;
113701 }
113702 }
113703
113704 return match;
113705 },
113706
113707 toString: function() {
113708 return this.expression;
113709 },
113710
113711 inspect: function() {
113712 return "#<Selector:" + this.expression.inspect() + ">";
113713 }
113714 });
113715
113716 Object.extend(Selector, {
113717 _cache: { },
113718
113719 xpath: {
113720 descendant: "//*",
113721 child: "/*",
113722 adjacent: "/following-sibling::*[1]",
113723 laterSibling: '/following-sibling::*',
113724 tagName: function(m) {
113725 if (m[1] == '*') return '';
113726 return "[local-name()='" + m[1].toLowerCase() +
113727 "' or local-name()='" + m[1].toUpperCase() + "']";
113728 },
113729 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
113730 id: "[@id='#{1}']",
113731 attrPresence: "[@#{1}]",
113732 attr: function(m) {
113733 m[3] = m[5] || m[6];
113734 return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
113735 },
113736 pseudo: function(m) {
113737 var h = Selector.xpath.pseudos[m[1]];
113738 if (!h) return '';
113739 if (Object.isFunction(h)) return h(m);
113740 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
113741 },
113742 operators: {
113743 '=': "[@#{1}='#{3}']",
113744 '!=': "[@#{1}!='#{3}']",
113745 '^=': "[starts-with(@#{1}, '#{3}')]",
113746 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
113747 '*=': "[contains(@#{1}, '#{3}')]",
113748 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
113749 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
113750 },
113751 pseudos: {
113752 'first-child': '[not(preceding-sibling::*)]',
113753 'last-child': '[not(following-sibling::*)]',
113754 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
113755 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
113756 'checked': "[@checked]",
113757 'disabled': "[@disabled]",
113758 'enabled': "[not(@disabled)]",
113759 'not': function(m) {
113760 var e = m[6], p = Selector.patterns,
113761 x = Selector.xpath, le, m, v;
113762
113763 var exclusion = [];
113764 while (e && le != e && (/\S/).test(e)) {
113765 le = e;
113766 for (var i in p) {
113767 if (m = e.match(p[i])) {
113768 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
113769 exclusion.push("(" + v.substring(1, v.length - 1) + ")");
113770 e = e.replace(m[0], '');
113771 break;
113772 }
113773 }
113774 }
113775 return "[not(" + exclusion.join(" and ") + ")]";
113776 },
113777 'nth-child': function(m) {
113778 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
113779 },
113780 'nth-last-child': function(m) {
113781 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
113782 },
113783 'nth-of-type': function(m) {
113784 return Selector.xpath.pseudos.nth("position() ", m);
113785 },
113786 'nth-last-of-type': function(m) {
113787 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
113788 },
113789 'first-of-type': function(m) {
113790 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
113791 },
113792 'last-of-type': function(m) {
113793 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
113794 },
113795 'only-of-type': function(m) {
113796 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
113797 },
113798 nth: function(fragment, m) {
113799 var mm, formula = m[6], predicate;
113800 if (formula == 'even') formula = '2n+0';
113801 if (formula == 'odd') formula = '2n+1';
113802 if (mm = formula.match(/^(\d+)$/)) // digit only
113803 return '[' + fragment + "= " + mm[1] + ']';
113804 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
113805 if (mm[1] == "-") mm[1] = -1;
113806 var a = mm[1] ? Number(mm[1]) : 1;
113807 var b = mm[2] ? Number(mm[2]) : 0;
113808 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
113809 "((#{fragment} - #{b}) div #{a} >= 0)]";
113810 return new Template(predicate).evaluate({
113811 fragment: fragment, a: a, b: b });
113812 }
113813 }
113814 }
113815 },
113816
113817 criteria: {
113818 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
113819 className: 'n = h.className(n, r, "#{1}", c); c = false;',
113820 id: 'n = h.id(n, r, "#{1}", c); c = false;',
113821 attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
113822 attr: function(m) {
113823 m[3] = (m[5] || m[6]);
113824 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
113825 },
113826 pseudo: function(m) {
113827 if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
113828 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
113829 },
113830 descendant: 'c = "descendant";',
113831 child: 'c = "child";',
113832 adjacent: 'c = "adjacent";',
113833 laterSibling: 'c = "laterSibling";'
113834 },
113835
113836 patterns: {
113837 // combinators must be listed first
113838 // (and descendant needs to be last combinator)
113839 laterSibling: /^\s*~\s*/,
113840 child: /^\s*>\s*/,
113841 adjacent: /^\s*\+\s*/,
113842 descendant: /^\s/,
113843
113844 // selectors follow
113845 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
113846 id: /^#([\w\-\*]+)(\b|$)/,
113847 className: /^\.([\w\-\*]+)(\b|$)/,
113848 pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
113849 attrPresence: /^\[([\w]+)\]/,
113850 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
113851 },
113852
113853 // for Selector.match and Element#match
113854 assertions: {
113855 tagName: function(element, matches) {
113856 return matches[1].toUpperCase() == element.tagName.toUpperCase();
113857 },
113858
113859 className: function(element, matches) {
113860 return Element.hasClassName(element, matches[1]);
113861 },
113862
113863 id: function(element, matches) {
113864 return element.id === matches[1];
113865 },
113866
113867 attrPresence: function(element, matches) {
113868 return Element.hasAttribute(element, matches[1]);
113869 },
113870
113871 attr: function(element, matches) {
113872 var nodeValue = Element.readAttribute(element, matches[1]);
113873 return Selector.operators[matches[2]](nodeValue, matches[3]);
113874 }
113875 },
113876
113877 handlers: {
113878 // UTILITY FUNCTIONS
113879 // joins two collections
113880 concat: function(a, b) {
113881 for (var i = 0, node; node = b[i]; i++)
113882 a.push(node);
113883 return a;
113884 },
113885
113886 // marks an array of nodes for counting
113887 mark: function(nodes) {
113888 for (var i = 0, node; node = nodes[i]; i++)
113889 node._counted = true;
113890 return nodes;
113891 },
113892
113893 unmark: function(nodes) {
113894 for (var i = 0, node; node = nodes[i]; i++)
113895 node._counted = undefined;
113896 return nodes;
113897 },
113898
113899 // mark each child node with its position (for nth calls)
113900 // "ofType" flag indicates whether we're indexing for nth-of-type
113901 // rather than nth-child
113902 index: function(parentNode, reverse, ofType) {
113903 parentNode._counted = true;
113904 if (reverse) {
113905 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
113906 var node = nodes[i];
113907 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
113908 }
113909 } else {
113910 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
113911 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
113912 }
113913 },
113914
113915 // filters out duplicates and extends all nodes
113916 unique: function(nodes) {
113917 if (nodes.length == 0) return nodes;
113918 var results = [], n;
113919 for (var i = 0, l = nodes.length; i < l; i++)
113920 if (!(n = nodes[i])._counted) {
113921 n._counted = true;
113922 results.push(Element.extend(n));
113923 }
113924 return Selector.handlers.unmark(results);
113925 },
113926
113927 // COMBINATOR FUNCTIONS
113928 descendant: function(nodes) {
113929 var h = Selector.handlers;
113930 for (var i = 0, results = [], node; node = nodes[i]; i++)
113931 h.concat(results, node.getElementsByTagName('*'));
113932 return results;
113933 },
113934
113935 child: function(nodes) {
113936 var h = Selector.handlers;
113937 for (var i = 0, results = [], node; node = nodes[i]; i++) {
113938 for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
113939 if (child.nodeType == 1 && child.tagName != '!') results.push(child);
113940 }
113941 return results;
113942 },
113943
113944 adjacent: function(nodes) {
113945 for (var i = 0, results = [], node; node = nodes[i]; i++) {
113946 var next = this.nextElementSibling(node);
113947 if (next) results.push(next);
113948 }
113949 return results;
113950 },
113951
113952 laterSibling: function(nodes) {
113953 var h = Selector.handlers;
113954 for (var i = 0, results = [], node; node = nodes[i]; i++)
113955 h.concat(results, Element.nextSiblings(node));
113956 return results;
113957 },
113958
113959 nextElementSibling: function(node) {
113960 while (node = node.nextSibling)
113961 if (node.nodeType == 1) return node;
113962 return null;
113963 },
113964
113965 previousElementSibling: function(node) {
113966 while (node = node.previousSibling)
113967 if (node.nodeType == 1) return node;
113968 return null;
113969 },
113970
113971 // TOKEN FUNCTIONS
113972 tagName: function(nodes, root, tagName, combinator) {
113973 tagName = tagName.toUpperCase();
113974 var results = [], h = Selector.handlers;
113975 if (nodes) {
113976 if (combinator) {
113977 // fastlane for ordinary descendant combinators
113978 if (combinator == "descendant") {
113979 for (var i = 0, node; node = nodes[i]; i++)
113980 h.concat(results, node.getElementsByTagName(tagName));
113981 return results;
113982 } else nodes = this[combinator](nodes);
113983 if (tagName == "*") return nodes;
113984 }
113985 for (var i = 0, node; node = nodes[i]; i++)
113986 if (node.tagName.toUpperCase() == tagName) results.push(node);
113987 return results;
113988 } else return root.getElementsByTagName(tagName);
113989 },
113990
113991 id: function(nodes, root, id, combinator) {
113992 var targetNode = $(id), h = Selector.handlers;
113993 if (!targetNode) return [];
113994 if (!nodes && root == document) return [targetNode];
113995 if (nodes) {
113996 if (combinator) {
113997 if (combinator == 'child') {
113998 for (var i = 0, node; node = nodes[i]; i++)
113999 if (targetNode.parentNode == node) return [targetNode];
114000 } else if (combinator == 'descendant') {
114001 for (var i = 0, node; node = nodes[i]; i++)
114002 if (Element.descendantOf(targetNode, node)) return [targetNode];
114003 } else if (combinator == 'adjacent') {
114004 for (var i = 0, node; node = nodes[i]; i++)
114005 if (Selector.handlers.previousElementSibling(targetNode) == node)
114006 return [targetNode];
114007 } else nodes = h[combinator](nodes);
114008 }
114009 for (var i = 0, node; node = nodes[i]; i++)
114010 if (node == targetNode) return [targetNode];
114011 return [];
114012 }
114013 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
114014 },
114015
114016 className: function(nodes, root, className, combinator) {
114017 if (nodes && combinator) nodes = this[combinator](nodes);
114018 return Selector.handlers.byClassName(nodes, root, className);
114019 },
114020
114021 byClassName: function(nodes, root, className) {
114022 if (!nodes) nodes = Selector.handlers.descendant([root]);
114023 var needle = ' ' + className + ' ';
114024 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
114025 nodeClassName = node.className;
114026 if (nodeClassName.length == 0) continue;
114027 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
114028 results.push(node);
114029 }
114030 return results;
114031 },
114032
114033 attrPresence: function(nodes, root, attr) {
114034 if (!nodes) nodes = root.getElementsByTagName("*");
114035 var results = [];
114036 for (var i = 0, node; node = nodes[i]; i++)
114037 if (Element.hasAttribute(node, attr)) results.push(node);
114038 return results;
114039 },
114040
114041 attr: function(nodes, root, attr, value, operator) {
114042 if (!nodes) nodes = root.getElementsByTagName("*");
114043 var handler = Selector.operators[operator], results = [];
114044 for (var i = 0, node; node = nodes[i]; i++) {
114045 var nodeValue = Element.readAttribute(node, attr);
114046 if (nodeValue === null) continue;
114047 if (handler(nodeValue, value)) results.push(node);
114048 }
114049 return results;
114050 },
114051
114052 pseudo: function(nodes, name, value, root, combinator) {
114053 if (nodes && combinator) nodes = this[combinator](nodes);
114054 if (!nodes) nodes = root.getElementsByTagName("*");
114055 return Selector.pseudos[name](nodes, value, root);
114056 }
114057 },
114058
114059 pseudos: {
114060 'first-child': function(nodes, value, root) {
114061 for (var i = 0, results = [], node; node = nodes[i]; i++) {
114062 if (Selector.handlers.previousElementSibling(node)) continue;
114063 results.push(node);
114064 }
114065 return results;
114066 },
114067 'last-child': function(nodes, value, root) {
114068 for (var i = 0, results = [], node; node = nodes[i]; i++) {
114069 if (Selector.handlers.nextElementSibling(node)) continue;
114070 results.push(node);
114071 }
114072 return results;
114073 },
114074 'only-child': function(nodes, value, root) {
114075 var h = Selector.handlers;
114076 for (var i = 0, results = [], node; node = nodes[i]; i++)
114077 if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
114078 results.push(node);
114079 return results;
114080 },
114081 'nth-child': function(nodes, formula, root) {
114082 return Selector.pseudos.nth(nodes, formula, root);
114083 },
114084 'nth-last-child': function(nodes, formula, root) {
114085 return Selector.pseudos.nth(nodes, formula, root, true);
114086 },
114087 'nth-of-type': function(nodes, formula, root) {
114088 return Selector.pseudos.nth(nodes, formula, root, false, true);
114089 },
114090 'nth-last-of-type': function(nodes, formula, root) {
114091 return Selector.pseudos.nth(nodes, formula, root, true, true);
114092 },
114093 'first-of-type': function(nodes, formula, root) {
114094 return Selector.pseudos.nth(nodes, "1", root, false, true);
114095 },
114096 'last-of-type': function(nodes, formula, root) {
114097 return Selector.pseudos.nth(nodes, "1", root, true, true);
114098 },
114099 'only-of-type': function(nodes, formula, root) {
114100 var p = Selector.pseudos;
114101 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
114102 },
114103
114104 // handles the an+b logic
114105 getIndices: function(a, b, total) {
114106 if (a == 0) return b > 0 ? [b] : [];
114107 return $R(1, total).inject([], function(memo, i) {
114108 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
114109 return memo;
114110 });
114111 },
114112
114113 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
114114 nth: function(nodes, formula, root, reverse, ofType) {
114115 if (nodes.length == 0) return [];
114116 if (formula == 'even') formula = '2n+0';
114117 if (formula == 'odd') formula = '2n+1';
114118 var h = Selector.handlers, results = [], indexed = [], m;
114119 h.mark(nodes);
114120 for (var i = 0, node; node = nodes[i]; i++) {
114121 if (!node.parentNode._counted) {
114122 h.index(node.parentNode, reverse, ofType);
114123 indexed.push(node.parentNode);
114124 }
114125 }
114126 if (formula.match(/^\d+$/)) { // just a number
114127 formula = Number(formula);
114128 for (var i = 0, node; node = nodes[i]; i++)
114129 if (node.nodeIndex == formula) results.push(node);
114130 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
114131 if (m[1] == "-") m[1] = -1;
114132 var a = m[1] ? Number(m[1]) : 1;
114133 var b = m[2] ? Number(m[2]) : 0;
114134 var indices = Selector.pseudos.getIndices(a, b, nodes.length);
114135 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
114136 for (var j = 0; j < l; j++)
114137 if (node.nodeIndex == indices[j]) results.push(node);
114138 }
114139 }
114140 h.unmark(nodes);
114141 h.unmark(indexed);
114142 return results;
114143 },
114144
114145 'empty': function(nodes, value, root) {
114146 for (var i = 0, results = [], node; node = nodes[i]; i++) {
114147 // IE treats comments as element nodes
114148 if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
114149 results.push(node);
114150 }
114151 return results;
114152 },
114153
114154 'not': function(nodes, selector, root) {
114155 var h = Selector.handlers, selectorType, m;
114156 var exclusions = new Selector(selector).findElements(root);
114157 h.mark(exclusions);
114158 for (var i = 0, results = [], node; node = nodes[i]; i++)
114159 if (!node._counted) results.push(node);
114160 h.unmark(exclusions);
114161 return results;
114162 },
114163
114164 'enabled': function(nodes, value, root) {
114165 for (var i = 0, results = [], node; node = nodes[i]; i++)
114166 if (!node.disabled) results.push(node);
114167 return results;
114168 },
114169
114170 'disabled': function(nodes, value, root) {
114171 for (var i = 0, results = [], node; node = nodes[i]; i++)
114172 if (node.disabled) results.push(node);
114173 return results;
114174 },
114175
114176 'checked': function(nodes, value, root) {
114177 for (var i = 0, results = [], node; node = nodes[i]; i++)
114178 if (node.checked) results.push(node);
114179 return results;
114180 }
114181 },
114182
114183 operators: {
114184 '=': function(nv, v) { return nv == v; },
114185 '!=': function(nv, v) { return nv != v; },
114186 '^=': function(nv, v) { return nv.startsWith(v); },
114187 '$=': function(nv, v) { return nv.endsWith(v); },
114188 '*=': function(nv, v) { return nv.include(v); },
114189 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
114190 '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
114191 },
114192
114193 matchElements: function(elements, expression) {
114194 var matches = new Selector(expression).findElements(), h = Selector.handlers;
114195 h.mark(matches);
114196 for (var i = 0, results = [], element; element = elements[i]; i++)
114197 if (element._counted) results.push(element);
114198 h.unmark(matches);
114199 return results;
114200 },
114201
114202 findElement: function(elements, expression, index) {
114203 if (Object.isNumber(expression)) {
114204 index = expression; expression = false;
114205 }
114206 return Selector.matchElements(elements, expression || '*')[index || 0];
114207 },
114208
114209 findChildElements: function(element, expressions) {
114210 var exprs = expressions.join(','), expressions = [];
114211 exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
114212 expressions.push(m[1].strip());
114213 });
114214 var results = [], h = Selector.handlers;
114215 for (var i = 0, l = expressions.length, selector; i < l; i++) {
114216 selector = new Selector(expressions[i].strip());
114217 h.concat(results, selector.findElements(element));
114218 }
114219 return (l > 1) ? h.unique(results) : results;
114220 }
114221 });
114222
114223 function $$() {
114224 return Selector.findChildElements(document, $A(arguments));
114225 }
114226 var Form = {
114227 reset: function(form) {
114228 $(form).reset();
114229 return form;
114230 },
114231
114232 serializeElements: function(elements, options) {
114233 if (typeof options != 'object') options = { hash: !!options };
114234 else if (options.hash === undefined) options.hash = true;
114235 var key, value, submitted = false, submit = options.submit;
114236
114237 var data = elements.inject({ }, function(result, element) {
114238 if (!element.disabled && element.name) {
114239 key = element.name; value = $(element).getValue();
114240 if (value != null && (element.type != 'submit' || (!submitted &&
114241 submit !== false && (!submit || key == submit) && (submitted = true)))) {
114242 if (key in result) {
114243 // a key is already present; construct an array of values
114244 if (!Object.isArray(result[key])) result[key] = [result[key]];
114245 result[key].push(value);
114246 }
114247 else result[key] = value;
114248 }
114249 }
114250 return result;
114251 });
114252
114253 return options.hash ? data : Object.toQueryString(data);
114254 }
114255 };
114256
114257 Form.Methods = {
114258 serialize: function(form, options) {
114259 return Form.serializeElements(Form.getElements(form), options);
114260 },
114261
114262 getElements: function(form) {
114263 return $A($(form).getElementsByTagName('*')).inject([],
114264 function(elements, child) {
114265 if (Form.Element.Serializers[child.tagName.toLowerCase()])
114266 elements.push(Element.extend(child));
114267 return elements;
114268 }
114269 );
114270 },
114271
114272 getInputs: function(form, typeName, name) {
114273 form = $(form);
114274 var inputs = form.getElementsByTagName('input');
114275
114276 if (!typeName && !name) return $A(inputs).map(Element.extend);
114277
114278 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
114279 var input = inputs[i];
114280 if ((typeName && input.type != typeName) || (name && input.name != name))
114281 continue;
114282 matchingInputs.push(Element.extend(input));
114283 }
114284
114285 return matchingInputs;
114286 },
114287
114288 disable: function(form) {
114289 form = $(form);
114290 Form.getElements(form).invoke('disable');
114291 return form;
114292 },
114293
114294 enable: function(form) {
114295 form = $(form);
114296 Form.getElements(form).invoke('enable');
114297 return form;
114298 },
114299
114300 findFirstElement: function(form) {
114301 var elements = $(form).getElements().findAll(function(element) {
114302 return 'hidden' != element.type && !element.disabled;
114303 });
114304 var firstByIndex = elements.findAll(function(element) {
114305 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
114306 }).sortBy(function(element) { return element.tabIndex }).first();
114307
114308 return firstByIndex ? firstByIndex : elements.find(function(element) {
114309 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
114310 });
114311 },
114312
114313 focusFirstElement: function(form) {
114314 form = $(form);
114315 form.findFirstElement().activate();
114316 return form;
114317 },
114318
114319 request: function(form, options) {
114320 form = $(form), options = Object.clone(options || { });
114321
114322 var params = options.parameters, action = form.readAttribute('action') || '';
114323 if (action.blank()) action = window.location.href;
114324 options.parameters = form.serialize(true);
114325
114326 if (params) {
114327 if (Object.isString(params)) params = params.toQueryParams();
114328 Object.extend(options.parameters, params);
114329 }
114330
114331 if (form.hasAttribute('method') && !options.method)
114332 options.method = form.method;
114333
114334 return new Ajax.Request(action, options);
114335 }
114336 };
114337
114338 /*--------------------------------------------------------------------------*/
114339
114340 Form.Element = {
114341 focus: function(element) {
114342 $(element).focus();
114343 return element;
114344 },
114345
114346 select: function(element) {
114347 $(element).select();
114348 return element;
114349 }
114350 };
114351
114352 Form.Element.Methods = {
114353 serialize: function(element) {
114354 element = $(element);
114355 if (!element.disabled && element.name) {
114356 var value = element.getValue();
114357 if (value != undefined) {
114358 var pair = { };
114359 pair[element.name] = value;
114360 return Object.toQueryString(pair);
114361 }
114362 }
114363 return '';
114364 },
114365
114366 getValue: function(element) {
114367 element = $(element);
114368 var method = element.tagName.toLowerCase();
114369 return Form.Element.Serializers[method](element);
114370 },
114371
114372 setValue: function(element, value) {
114373 element = $(element);
114374 var method = element.tagName.toLowerCase();
114375 Form.Element.Serializers[method](element, value);
114376 return element;
114377 },
114378
114379 clear: function(element) {
114380 $(element).value = '';
114381 return element;
114382 },
114383
114384 present: function(element) {
114385 return $(element).value != '';
114386 },
114387
114388 activate: function(element) {
114389 element = $(element);
114390 try {
114391 element.focus();
114392 if (element.select && (element.tagName.toLowerCase() != 'input' ||
114393 !['button', 'reset', 'submit'].include(element.type)))
114394 element.select();
114395 } catch (e) { }
114396 return element;
114397 },
114398
114399 disable: function(element) {
114400 element = $(element);
114401 element.blur();
114402 element.disabled = true;
114403 return element;
114404 },
114405
114406 enable: function(element) {
114407 element = $(element);
114408 element.disabled = false;
114409 return element;
114410 }
114411 };
114412
114413 /*--------------------------------------------------------------------------*/
114414
114415 var Field = Form.Element;
114416 var $F = Form.Element.Methods.getValue;
114417
114418 /*--------------------------------------------------------------------------*/
114419
114420 Form.Element.Serializers = {
114421 input: function(element, value) {
114422 switch (element.type.toLowerCase()) {
114423 case 'checkbox':
114424 case 'radio':
114425 return Form.Element.Serializers.inputSelector(element, value);
114426 default:
114427 return Form.Element.Serializers.textarea(element, value);
114428 }
114429 },
114430
114431 inputSelector: function(element, value) {
114432 if (value === undefined) return element.checked ? element.value : null;
114433 else element.checked = !!value;
114434 },
114435
114436 textarea: function(element, value) {
114437 if (value === undefined) return element.value;
114438 else element.value = value;
114439 },
114440
114441 select: function(element, index) {
114442 if (index === undefined)
114443 return this[element.type == 'select-one' ?
114444 'selectOne' : 'selectMany'](element);
114445 else {
114446 var opt, value, single = !Object.isArray(index);
114447 for (var i = 0, length = element.length; i < length; i++) {
114448 opt = element.options[i];
114449 value = this.optionValue(opt);
114450 if (single) {
114451 if (value == index) {
114452 opt.selected = true;
114453 return;
114454 }
114455 }
114456 else opt.selected = index.include(value);
114457 }
114458 }
114459 },
114460
114461 selectOne: function(element) {
114462 var index = element.selectedIndex;
114463 return index >= 0 ? this.optionValue(element.options[index]) : null;
114464 },
114465
114466 selectMany: function(element) {
114467 var values, length = element.length;
114468 if (!length) return null;
114469
114470 for (var i = 0, values = []; i < length; i++) {
114471 var opt = element.options[i];
114472 if (opt.selected) values.push(this.optionValue(opt));
114473 }
114474 return values;
114475 },
114476
114477 optionValue: function(opt) {
114478 // extend element because hasAttribute may not be native
114479 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
114480 }
114481 };
114482
114483 /*--------------------------------------------------------------------------*/
114484
114485 Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
114486 initialize: function($super, element, frequency, callback) {
114487 $super(callback, frequency);
114488 this.element = $(element);
114489 this.lastValue = this.getValue();
114490 },
114491
114492 execute: function() {
114493 var value = this.getValue();
114494 if (Object.isString(this.lastValue) && Object.isString(value) ?
114495 this.lastValue != value : String(this.lastValue) != String(value)) {
114496 this.callback(this.element, value);
114497 this.lastValue = value;
114498 }
114499 }
114500 });
114501
114502 Form.Element.Observer = Class.create(Abstract.TimedObserver, {
114503 getValue: function() {
114504 return Form.Element.getValue(this.element);
114505 }
114506 });
114507
114508 Form.Observer = Class.create(Abstract.TimedObserver, {
114509 getValue: function() {
114510 return Form.serialize(this.element);
114511 }
114512 });
114513
114514 /*--------------------------------------------------------------------------*/
114515
114516 Abstract.EventObserver = Class.create({
114517 initialize: function(element, callback) {
114518 this.element = $(element);
114519 this.callback = callback;
114520
114521 this.lastValue = this.getValue();
114522 if (this.element.tagName.toLowerCase() == 'form')
114523 this.registerFormCallbacks();
114524 else
114525 this.registerCallback(this.element);
114526 },
114527
114528 onElementEvent: function() {
114529 var value = this.getValue();
114530 if (this.lastValue != value) {
114531 this.callback(this.element, value);
114532 this.lastValue = value;
114533 }
114534 },
114535
114536 registerFormCallbacks: function() {
114537 Form.getElements(this.element).each(this.registerCallback, this);
114538 },
114539
114540 registerCallback: function(element) {
114541 if (element.type) {
114542 switch (element.type.toLowerCase()) {
114543 case 'checkbox':
114544 case 'radio':
114545 Event.observe(element, 'click', this.onElementEvent.bind(this));
114546 break;
114547 default:
114548 Event.observe(element, 'change', this.onElementEvent.bind(this));
114549 break;
114550 }
114551 }
114552 }
114553 });
114554
114555 Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
114556 getValue: function() {
114557 return Form.Element.getValue(this.element);
114558 }
114559 });
114560
114561 Form.EventObserver = Class.create(Abstract.EventObserver, {
114562 getValue: function() {
114563 return Form.serialize(this.element);
114564 }
114565 });
114566 if (!window.Event) var Event = { };
114567
114568 Object.extend(Event, {
114569 KEY_BACKSPACE: 8,
114570 KEY_TAB: 9,
114571 KEY_RETURN: 13,
114572 KEY_ESC: 27,
114573 KEY_LEFT: 37,
114574 KEY_UP: 38,
114575 KEY_RIGHT: 39,
114576 KEY_DOWN: 40,
114577 KEY_DELETE: 46,
114578 KEY_HOME: 36,
114579 KEY_END: 35,
114580 KEY_PAGEUP: 33,
114581 KEY_PAGEDOWN: 34,
114582 KEY_INSERT: 45,
114583
114584 cache: { },
114585
114586 relatedTarget: function(event) {
114587 var element;
114588 switch(event.type) {
114589 case 'mouseover': element = event.fromElement; break;
114590 case 'mouseout': element = event.toElement; break;
114591 default: return null;
114592 }
114593 return Element.extend(element);
114594 }
114595 });
114596
114597 Event.Methods = (function() {
114598 var isButton;
114599
114600 if (Prototype.Browser.IE) {
114601 var buttonMap = { 0: 1, 1: 4, 2: 2 };
114602 isButton = function(event, code) {
114603 return event.button == buttonMap[code];
114604 };
114605
114606 } else if (Prototype.Browser.WebKit) {
114607 isButton = function(event, code) {
114608 switch (code) {
114609 case 0: return event.which == 1 && !event.metaKey;
114610 case 1: return event.which == 1 && event.metaKey;
114611 default: return false;
114612 }
114613 };
114614
114615 } else {
114616 isButton = function(event, code) {
114617 return event.which ? (event.which === code + 1) : (event.button === code);
114618 };
114619 }
114620
114621 return {
114622 isLeftClick: function(event) { return isButton(event, 0) },
114623 isMiddleClick: function(event) { return isButton(event, 1) },
114624 isRightClick: function(event) { return isButton(event, 2) },
114625
114626 element: function(event) {
114627 var node = Event.extend(event).target;
114628 return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
114629 },
114630
114631 findElement: function(event, expression) {
114632 var element = Event.element(event);
114633 return element.match(expression) ? element : element.up(expression);
114634 },
114635
114636 pointer: function(event) {
114637 return {
114638 x: event.pageX || (event.clientX +
114639 (document.documentElement.scrollLeft || document.body.scrollLeft)),
114640 y: event.pageY || (event.clientY +
114641 (document.documentElement.scrollTop || document.body.scrollTop))
114642 };
114643 },
114644
114645 pointerX: function(event) { return Event.pointer(event).x },
114646 pointerY: function(event) { return Event.pointer(event).y },
114647
114648 stop: function(event) {
114649 Event.extend(event);
114650 event.preventDefault();
114651 event.stopPropagation();
114652 event.stopped = true;
114653 }
114654 };
114655 })();
114656
114657 Event.extend = (function() {
114658 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
114659 m[name] = Event.Methods[name].methodize();
114660 return m;
114661 });
114662
114663 if (Prototype.Browser.IE) {
114664 Object.extend(methods, {
114665 stopPropagation: function() { this.cancelBubble = true },
114666 preventDefault: function() { this.returnValue = false },
114667 inspect: function() { return "[object Event]" }
114668 });
114669
114670 return function(event) {
114671 if (!event) return false;
114672 if (event._extendedByPrototype) return event;
114673
114674 event._extendedByPrototype = Prototype.emptyFunction;
114675 var pointer = Event.pointer(event);
114676 Object.extend(event, {
114677 target: event.srcElement,
114678 relatedTarget: Event.relatedTarget(event),
114679 pageX: pointer.x,
114680 pageY: pointer.y
114681 });
114682 return Object.extend(event, methods);
114683 };
114684
114685 } else {
114686 Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
114687 Object.extend(Event.prototype, methods);
114688 return Prototype.K;
114689 }
114690 })();
114691
114692 Object.extend(Event, (function() {
114693 var cache = Event.cache;
114694
114695 function getEventID(element) {
114696 if (element._eventID) return element._eventID;
114697 arguments.callee.id = arguments.callee.id || 1;
114698 return element._eventID = ++arguments.callee.id;
114699 }
114700
114701 function getDOMEventName(eventName) {
114702 if (eventName && eventName.include(':')) return "dataavailable";
114703 return eventName;
114704 }
114705
114706 function getCacheForID(id) {
114707 return cache[id] = cache[id] || { };
114708 }
114709
114710 function getWrappersForEventName(id, eventName) {
114711 var c = getCacheForID(id);
114712 return c[eventName] = c[eventName] || [];
114713 }
114714
114715 function createWrapper(element, eventName, handler) {
114716 var id = getEventID(element);
114717 var c = getWrappersForEventName(id, eventName);
114718 if (c.pluck("handler").include(handler)) return false;
114719
114720 var wrapper = function(event) {
114721 if (!Event || !Event.extend ||
114722 (event.eventName && event.eventName != eventName))
114723 return false;
114724
114725 Event.extend(event);
114726 handler.call(element, event)
114727 };
114728
114729 wrapper.handler = handler;
114730 c.push(wrapper);
114731 return wrapper;
114732 }
114733
114734 function findWrapper(id, eventName, handler) {
114735 var c = getWrappersForEventName(id, eventName);
114736 return c.find(function(wrapper) { return wrapper.handler == handler });
114737 }
114738
114739 function destroyWrapper(id, eventName, handler) {
114740 var c = getCacheForID(id);
114741 if (!c[eventName]) return false;
114742 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
114743 }
114744
114745 function destroyCache() {
114746 for (var id in cache)
114747 for (var eventName in cache[id])
114748 cache[id][eventName] = null;
114749 }
114750
114751 if (window.attachEvent) {
114752 window.attachEvent("onunload", destroyCache);
114753 }
114754
114755 return {
114756 observe: function(element, eventName, handler) {
114757 element = $(element);
114758 var name = getDOMEventName(eventName);
114759
114760 var wrapper = createWrapper(element, eventName, handler);
114761 if (!wrapper) return element;
114762
114763 if (element.addEventListener) {
114764 element.addEventListener(name, wrapper, false);
114765 } else {
114766 element.attachEvent("on" + name, wrapper);
114767 }
114768
114769 return element;
114770 },
114771
114772 stopObserving: function(element, eventName, handler) {
114773 element = $(element);
114774 var id = getEventID(element), name = getDOMEventName(eventName);
114775
114776 if (!handler && eventName) {
114777 getWrappersForEventName(id, eventName).each(function(wrapper) {
114778 element.stopObserving(eventName, wrapper.handler);
114779 });
114780 return element;
114781
114782 } else if (!eventName) {
114783 Object.keys(getCacheForID(id)).each(function(eventName) {
114784 element.stopObserving(eventName);
114785 });
114786 return element;
114787 }
114788
114789 var wrapper = findWrapper(id, eventName, handler);
114790 if (!wrapper) return element;
114791
114792 if (element.removeEventListener) {
114793 element.removeEventListener(name, wrapper, false);
114794 } else {
114795 element.detachEvent("on" + name, wrapper);
114796 }
114797
114798 destroyWrapper(id, eventName, handler);
114799
114800 return element;
114801 },
114802
114803 fire: function(element, eventName, memo) {
114804 element = $(element);
114805 if (element == document && document.createEvent && !element.dispatchEvent)
114806 element = document.documentElement;
114807
114808 if (document.createEvent) {
114809 var event = document.createEvent("HTMLEvents");
114810 event.initEvent("dataavailable", true, true);
114811 } else {
114812 var event = document.createEventObject();
114813 event.eventType = "ondataavailable";
114814 }
114815
114816 event.eventName = eventName;
114817 event.memo = memo || { };
114818
114819 if (document.createEvent) {
114820 element.dispatchEvent(event);
114821 } else {
114822 element.fireEvent(event.eventType, event);
114823 }
114824
114825 return event;
114826 }
114827 };
114828 })());
114829
114830 Object.extend(Event, Event.Methods);
114831
114832 Element.addMethods({
114833 fire: Event.fire,
114834 observe: Event.observe,
114835 stopObserving: Event.stopObserving
114836 });
114837
114838 Object.extend(document, {
114839 fire: Element.Methods.fire.methodize(),
114840 observe: Element.Methods.observe.methodize(),
114841 stopObserving: Element.Methods.stopObserving.methodize()
114842 });
114843
114844 (function() {
114845 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
114846 Matthias Miller, Dean Edwards and John Resig. */
114847
114848 var timer, fired = false;
114849
114850 function fireContentLoadedEvent() {
114851 if (fired) return;
114852 if (timer) window.clearInterval(timer);
114853 document.fire("dom:loaded");
114854 fired = true;
114855 }
114856
114857 if (document.addEventListener) {
114858 if (Prototype.Browser.WebKit) {
114859 timer = window.setInterval(function() {
114860 if (/loaded|complete/.test(document.readyState))
114861 fireContentLoadedEvent();
114862 }, 0);
114863
114864 Event.observe(window, "load", fireContentLoadedEvent);
114865
114866 } else {
114867 document.addEventListener("DOMContentLoaded",
114868 fireContentLoadedEvent, false);
114869 }
114870
114871 } else {
114872 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
114873 $("__onDOMContentLoaded").onreadystatechange = function() {
114874 if (this.readyState == "complete") {
114875 this.onreadystatechange = null;
114876 fireContentLoadedEvent();
114877 }
114878 };
114879 }
114880 })();
114881 /*------------------------------- DEPRECATED -------------------------------*/
114882
114883 Hash.toQueryString = Object.toQueryString;
114884
114885 var Toggle = { display: Element.toggle };
114886
114887 Element.Methods.childOf = Element.Methods.descendantOf;
114888
114889 var Insertion = {
114890 Before: function(element, content) {
114891 return Element.insert(element, {before:content});
114892 },
114893
114894 Top: function(element, content) {
114895 return Element.insert(element, {top:content});
114896 },
114897
114898 Bottom: function(element, content) {
114899 return Element.insert(element, {bottom:content});
114900 },
114901
114902 After: function(element, content) {
114903 return Element.insert(element, {after:content});
114904 }
114905 };
114906
114907 var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
114908
114909 // This should be moved to script.aculo.us; notice the deprecated methods
114910 // further below, that map to the newer Element methods.
114911 var Position = {
114912 // set to true if needed, warning: firefox performance problems
114913 // NOT neeeded for page scrolling, only if draggable contained in
114914 // scrollable elements
114915 includeScrollOffsets: false,
114916
114917 // must be called before calling withinIncludingScrolloffset, every time the
114918 // page is scrolled
114919 prepare: function() {
114920 this.deltaX = window.pageXOffset
114921 || document.documentElement.scrollLeft
114922 || document.body.scrollLeft
114923 || 0;
114924 this.deltaY = window.pageYOffset
114925 || document.documentElement.scrollTop
114926 || document.body.scrollTop
114927 || 0;
114928 },
114929
114930 // caches x/y coordinate pair to use with overlap
114931 within: function(element, x, y) {
114932 if (this.includeScrollOffsets)
114933 return this.withinIncludingScrolloffsets(element, x, y);
114934 this.xcomp = x;
114935 this.ycomp = y;
114936 this.offset = Element.cumulativeOffset(element);
114937
114938 return (y >= this.offset[1] &&
114939 y < this.offset[1] + element.offsetHeight &&
114940 x >= this.offset[0] &&
114941 x < this.offset[0] + element.offsetWidth);
114942 },
114943
114944 withinIncludingScrolloffsets: function(element, x, y) {
114945 var offsetcache = Element.cumulativeScrollOffset(element);
114946
114947 this.xcomp = x + offsetcache[0] - this.deltaX;
114948 this.ycomp = y + offsetcache[1] - this.deltaY;
114949 this.offset = Element.cumulativeOffset(element);
114950
114951 return (this.ycomp >= this.offset[1] &&
114952 this.ycomp < this.offset[1] + element.offsetHeight &&
114953 this.xcomp >= this.offset[0] &&
114954 this.xcomp < this.offset[0] + element.offsetWidth);
114955 },
114956
114957 // within must be called directly before
114958 overlap: function(mode, element) {
114959 if (!mode) return 0;
114960 if (mode == 'vertical')
114961 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
114962 element.offsetHeight;
114963 if (mode == 'horizontal')
114964 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
114965 element.offsetWidth;
114966 },
114967
114968 // Deprecation layer -- use newer Element methods now (1.5.2).
114969
114970 cumulativeOffset: Element.Methods.cumulativeOffset,
114971
114972 positionedOffset: Element.Methods.positionedOffset,
114973
114974 absolutize: function(element) {
114975 Position.prepare();
114976 return Element.absolutize(element);
114977 },
114978
114979 relativize: function(element) {
114980 Position.prepare();
114981 return Element.relativize(element);
114982 },
114983
114984 realOffset: Element.Methods.cumulativeScrollOffset,
114985
114986 offsetParent: Element.Methods.getOffsetParent,
114987
114988 page: Element.Methods.viewportOffset,
114989
114990 clone: function(source, target, options) {
114991 options = options || { };
114992 return Element.clonePosition(target, source, options);
114993 }
114994 };
114995
114996 /*--------------------------------------------------------------------------*/
114997
114998 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
114999 function iter(name) {
115000 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
115001 }
115002
115003 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
115004 function(element, className) {
115005 className = className.toString().strip();
115006 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
115007 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
115008 } : function(element, className) {
115009 className = className.toString().strip();
115010 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
115011 if (!classNames && !className) return elements;
115012
115013 var nodes = $(element).getElementsByTagName('*');
115014 className = ' ' + className + ' ';
115015
115016 for (var i = 0, child, cn; child = nodes[i]; i++) {
115017 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
115018 (classNames && classNames.all(function(name) {
115019 return !name.toString().blank() && cn.include(' ' + name + ' ');
115020 }))))
115021 elements.push(Element.extend(child));
115022 }
115023 return elements;
115024 };
115025
115026 return function(className, parentElement) {
115027 return $(parentElement || document.body).getElementsByClassName(className);
115028 };
115029 }(Element.Methods);
115030
115031 /*--------------------------------------------------------------------------*/
115032
115033 Element.ClassNames = Class.create();
115034 Element.ClassNames.prototype = {
115035 initialize: function(element) {
115036 this.element = $(element);
115037 },
115038
115039 _each: function(iterator) {
115040 this.element.className.split(/\s+/).select(function(name) {
115041 return name.length > 0;
115042 })._each(iterator);
115043 },
115044
115045 set: function(className) {
115046 this.element.className = className;
115047 },
115048
115049 add: function(classNameToAdd) {
115050 if (this.include(classNameToAdd)) return;
115051 this.set($A(this).concat(classNameToAdd).join(' '));
115052 },
115053
115054 remove: function(classNameToRemove) {
115055 if (!this.include(classNameToRemove)) return;
115056 this.set($A(this).without(classNameToRemove).join(' '));
115057 },
115058
115059 toString: function() {
115060 return $A(this).join(' ');
115061 }
115062 };
115063
115064 Object.extend(Element.ClassNames.prototype, Enumerable);
115065
115066 /*--------------------------------------------------------------------------*/
115067
115068 Element.addMethods();