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