1/* Prototype JavaScript framework, version 1.6.1 2 * (c) 2005-2009 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 9var Prototype = { 10 Version: '1.6.1', 11 12 Browser: (function(){ 13 var ua = navigator.userAgent; 14 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; 15 return { 16 IE: !!window.attachEvent && !isOpera, 17 Opera: isOpera, 18 WebKit: ua.indexOf('AppleWebKit/') > -1, 19 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, 20 MobileSafari: /Apple.*Mobile.*Safari/.test(ua) 21 } 22 })(), 23 24 BrowserFeatures: { 25 XPath: !!document.evaluate, 26 SelectorsAPI: !!document.querySelector, 27 ElementExtensions: (function() { 28 var constructor = window.Element || window.HTMLElement; 29 return !!(constructor && constructor.prototype); 30 })(), 31 SpecificElementExtensions: (function() { 32 if (typeof window.HTMLDivElement !== 'undefined') 33 return true; 34 35 var div = document.createElement('div'); 36 var form = document.createElement('form'); 37 var isSupported = false; 38 39 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { 40 isSupported = true; 41 } 42 43 div = form = null; 44 45 return isSupported; 46 })() 47 }, 48 49 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', 50 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, 51 52 emptyFunction: function() { }, 53 K: function(x) { return x } 54}; 55 56if (Prototype.Browser.MobileSafari) 57 Prototype.BrowserFeatures.SpecificElementExtensions = false; 58 59 60var Abstract = { }; 61 62 63var Try = { 64 these: function() { 65 var returnValue; 66 67 for (var i = 0, length = arguments.length; i < length; i++) { 68 var lambda = arguments[i]; 69 try { 70 returnValue = lambda(); 71 break; 72 } catch (e) { } 73 } 74 75 return returnValue; 76 } 77}; 78 79/* Based on Alex Arnell's inheritance implementation. */ 80 81var Class = (function() { 82 function subclass() {}; 83 function create() { 84 var parent = null, properties = $A(arguments); 85 if (Object.isFunction(properties[0])) 86 parent = properties.shift(); 87 88 function klass() { 89 this.initialize.apply(this, arguments); 90 } 91 92 Object.extend(klass, Class.Methods); 93 klass.superclass = parent; 94 klass.subclasses = []; 95 96 if (parent) { 97 subclass.prototype = parent.prototype; 98 klass.prototype = new subclass; 99 parent.subclasses.push(klass); 100 } 101 102 for (var i = 0; i < properties.length; i++) 103 klass.addMethods(properties[i]); 104 105 if (!klass.prototype.initialize) 106 klass.prototype.initialize = Prototype.emptyFunction; 107 108 klass.prototype.constructor = klass; 109 return klass; 110 } 111 112 function addMethods(source) { 113 var ancestor = this.superclass && this.superclass.prototype; 114 var properties = Object.keys(source); 115 116 if (!Object.keys({ toString: true }).length) { 117 if (source.toString != Object.prototype.toString) 118 properties.push("toString"); 119 if (source.valueOf != Object.prototype.valueOf) 120 properties.push("valueOf"); 121 } 122 123 for (var i = 0, length = properties.length; i < length; i++) { 124 var property = properties[i], value = source[property]; 125 if (ancestor && Object.isFunction(value) && 126 value.argumentNames().first() == "$super") { 127 var method = value; 128 value = (function(m) { 129 return function() { return ancestor[m].apply(this, arguments); }; 130 })(property).wrap(method); 131 132 value.valueOf = method.valueOf.bind(method); 133 value.toString = method.toString.bind(method); 134 } 135 this.prototype[property] = value; 136 } 137 138 return this; 139 } 140 141 return { 142 create: create, 143 Methods: { 144 addMethods: addMethods 145 } 146 }; 147})(); 148(function() { 149 150 var _toString = Object.prototype.toString; 151 152 function extend(destination, source) { 153 for (var property in source) 154 destination[property] = source[property]; 155 return destination; 156 } 157 158 function inspect(object) { 159 try { 160 if (isUndefined(object)) return 'undefined'; 161 if (object === null) return 'null';
162 return object.inspect ? object.inspect() : String(object); 163 } catch (e) { 164 if (e instanceof RangeError) return '...'; 165 throw e; 166 } 167 } 168 169 function toJSON(object) { 170 var type = typeof object; 171 switch (type) { 172 case 'undefined': 173 case 'function': 174 case 'unknown': return; 175 case 'boolean': return object.toString(); 176 } 177 178 if (object === null) return 'null'; 179 if (object.toJSON) return object.toJSON(); 180 if (isElement(object)) return; 181 182 var results = []; 183 for (var property in object) { 184 var value = toJSON(object[property]); 185 if (!isUndefined(value)) 186 results.push(property.toJSON() + ': ' + value); 187 } 188 189 return '{' + results.join(', ') + '}'; 190 } 191 192 function toQueryString(object) { 193 return $H(object).toQueryString(); 194 } 195 196 function toHTML(object) { 197 return object && object.toHTML ? object.toHTML() : String.interpret(object); 198 } 199 200 function keys(object) { 201 var results = []; 202 for (var property in object) 203 results.push(property); 204 return results; 205 } 206 207 function values(object) { 208 var results = []; 209 for (var property in object) 210 results.push(object[property]); 211 return results; 212 } 213 214 function clone(object) { 215 return extend({ }, object); 216 } 217 218 function isElement(object) { 219 return !!(object && object.nodeType == 1); 220 } 221 222 function isArray(object) { 223 return _toString.call(object) == "[object Array]"; 224 } 225 226 227 function isHash(object) { 228 return object instanceof Hash; 229 } 230 231 function isFunction(object) { 232 return typeof object === "function"; 233 } 234 235 function isString(object) { 236 return _toString.call(object) == "[object String]"; 237 } 238 239 function isNumber(object) { 240 return _toString.call(object) == "[object Number]"; 241 } 242 243 function isUndefined(object) { 244 return typeof object === "undefined"; 245 } 246 247 extend(Object, { 248 extend: extend, 249 inspect: inspect, 250 toJSON: toJSON, 251 toQueryString: toQueryString, 252 toHTML: toHTML, 253 keys: keys, 254 values: values, 255 clone: clone, 256 isElement: isElement, 257 isArray: isArray, 258 isHash: isHash, 259 isFunction: isFunction, 260 isString: isString, 261 isNumber: isNumber, 262 isUndefined: isUndefined 263 }); 264})(); 265Object.extend(Function.prototype, (function() { 266 var slice = Array.prototype.slice; 267 268 function update(array, args) { 269 var arrayLength = array.length, length = args.length; 270 while (length--) array[arrayLength + length] = args[length]; 271 return array; 272 } 273 274 function merge(array, args) { 275 array = slice.call(array, 0); 276 return update(array, args); 277 } 278 279 function argumentNames() { 280 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] 281 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') 282 .replace(/\s+/g, '').split(','); 283 return names.length == 1 && !names[0] ? [] : names; 284 } 285 286 function bind(context) { 287 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 288 var __method = this, args = slice.call(arguments, 1); 289 return function() { 290 var a = merge(args, arguments); 291 return __method.apply(context, a); 292 } 293 } 294 295 function bindAsEventListener(context) { 296 var __method = this, args = slice.call(arguments, 1); 297 return function(event) { 298 var a = update([event || window.event], args); 299 return __method.apply(context, a); 300 } 301 } 302 303 function curry() { 304 if (!arguments.length) return this; 305 var __method = this, args = slice.call(arguments, 0); 306 return function() { 307 var a = merge(args, arguments); 308 return __method.apply(this, a); 309 } 310 } 311 312 function delay(timeout) { 313 var __method = this, args = slice.call(arguments, 1); 314 timeout = timeout * 1000 315 return window.setTimeout(function() { 316 return __method.apply(__method, args); 317 }, timeout); 318 } 319 320 function defer() { 321 var args = update([0.01], arguments); 322 return this.delay.apply(this, args); 323 } 324 325 function wrap(wrapper) { 326 var __method = this; 327 return function() { 328 var a = update([__method.bind(this)], arguments); 329 return wrapper.apply(this, a); 330 } 331 } 332 333 function methodize() { 334 if (this._methodized) return this._methodized; 335 var __method = this; 336 return this._methodized = function() { 337 var a = update([this], arguments); 338 return __method.apply(null, a); 339 }; 340 } 341 342 return { 343 argumentNames: argumentNames, 344 bind: bind, 345 bindAsEventListener: bindAsEventListener, 346 curry: curry, 347 delay: delay, 348 defer: defer, 349 wrap: wrap, 350 methodize: methodize 351 } 352})()); 353 354 355Date.prototype.toJSON = function() { 356 return '"' + this.getUTCFullYear() + '-' + 357 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 358 this.getUTCDate().toPaddedString(2) + 'T' + 359 this.getUTCHours().toPaddedString(2) + ':' + 360 this.getUTCMinutes().toPaddedString(2) + ':' + 361 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 362}; 363 364 365RegExp.prototype.match = RegExp.prototype.test; 366 367RegExp.escape = function(str) { 368 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 369}; 370var PeriodicalExecuter = Class.create({ 371 initialize: function(callback, frequency) { 372 this.callback = callback; 373 this.frequency = frequency; 374 this.currentlyExecuting = false;
375 376 this.registerCallback(); 377 }, 378 379 registerCallback: function() { 380 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 381 }, 382 383 execute: function() { 384 this.callback(this); 385 }, 386 387 stop: function() { 388 if (!this.timer) return; 389 clearInterval(this.timer); 390 this.timer = null; 391 }, 392 393 onTimerEvent: function() { 394 if (!this.currentlyExecuting) { 395 try { 396 this.currentlyExecuting = true; 397 this.execute(); 398 this.currentlyExecuting = false; 399 } catch(e) { 400 this.currentlyExecuting = false; 401 throw e; 402 } 403 } 404 } 405}); 406Object.extend(String, { 407 interpret: function(value) { 408 return value == null ? '' : String(value); 409 }, 410 specialChar: { 411 '\b': '\\b', 412 '\t': '\\t', 413 '\n': '\\n', 414 '\f': '\\f', 415 '\r': '\\r', 416 '\\': '\\\\' 417 } 418}); 419 420Object.extend(String.prototype, (function() { 421 422 function prepareReplacement(replacement) { 423 if (Object.isFunction(replacement)) return replacement; 424 var template = new Template(replacement); 425 return function(match) { return template.evaluate(match) }; 426 } 427 428 function gsub(pattern, replacement) { 429 var result = '', source = this, match; 430 replacement = prepareReplacement(replacement); 431 432 if (Object.isString(pattern)) 433 pattern = RegExp.escape(pattern); 434 435 if (!(pattern.length || pattern.source)) { 436 replacement = replacement(''); 437 return replacement + source.split('').join(replacement) + replacement; 438 } 439 440 while (source.length > 0) { 441 if (match = source.match(pattern)) { 442 result += source.slice(0, match.index); 443 result += String.interpret(replacement(match)); 444 source = source.slice(match.index + match[0].length); 445 } else { 446 result += source, source = ''; 447 } 448 } 449 return result; 450 } 451 452 function sub(pattern, replacement, count) { 453 replacement = prepareReplacement(replacement); 454 count = Object.isUndefined(count) ? 1 : count; 455 456 return this.gsub(pattern, function(match) { 457 if (--count < 0) return match[0]; 458 return replacement(match); 459 }); 460 } 461 462 function scan(pattern, iterator) { 463 this.gsub(pattern, iterator); 464 return String(this); 465 } 466 467 function truncate(length, truncation) { 468 length = length || 30; 469 truncation = Object.isUndefined(truncation) ? '...' : truncation; 470 return this.length > length ? 471 this.slice(0, length - truncation.length) + truncation : String(this); 472 } 473 474 function strip() { 475 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 476 } 477 478 function stripTags() { 479 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); 480 } 481 482 function stripScripts() { 483 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 484 } 485 486 function extractScripts() { 487 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 488 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 489 return (this.match(matchAll) || []).map(function(scriptTag) { 490 return (scriptTag.match(matchOne) || ['', ''])[1]; 491 }); 492 } 493 494 function evalScripts() { 495 return this.extractScripts().map(function(script) { return eval(script) }); 496 } 497 498 function escapeHTML() { 499 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 500 } 501 502 function unescapeHTML() { 503 return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); 504 } 505 506 507 function toQueryParams(separator) { 508 var match = this.strip().match(/([^?#]*)(#.*)?$/); 509 if (!match) return { }; 510 511 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 512 if ((pair = pair.split('='))[0]) { 513 var key = decodeURIComponent(pair.shift()); 514 var value = pair.length > 1 ? pair.join('=') : pair[0]; 515 if (value != undefined) value = decodeURIComponent(value); 516 517 if (key in hash) { 518 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 519 hash[key].push(value); 520 } 521 else hash[key] = value; 522 } 523 return hash; 524 }); 525 } 526 527 function toArray() { 528 return this.split(''); 529 } 530 531 function succ() { 532 return this.slice(0, this.length - 1) + 533 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 534 } 535 536 function times(count) { 537 return count < 1 ? '' : new Array(count + 1).join(this); 538 } 539 540 function camelize() { 541 var parts = this.split('-'), len = parts.length; 542 if (len == 1) return parts[0]; 543 544 var camelized = this.charAt(0) == '-' 545 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 546 : parts[0]; 547 548 for (var i = 1; i < len; i++) 549 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 550 551 return camelized; 552 } 553 554 function capitalize() { 555 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 556 } 557 558 function underscore() { 559 return this.replace(/::/g, '/') 560 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 561 .replace(/([a-z\d])([A-Z])/g, '$1_$2') 562 .replace(/-/g, '_') 563 .toLowerCase(); 564 } 565 566 function dasherize() { 567 return this.replace(/_/g, '-'); 568 } 569 570 function inspect(useDoubleQuotes) { 571 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(ch
571aracter) { 572 if (character in String.specialChar) { 573 return String.specialChar[character]; 574 } 575 return '\\u00' + character.charCodeAt().toPaddedString(2, 16); 576 }); 577 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 578 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 579 } 580 581 function toJSON() { 582 return this.inspect(true); 583 } 584 585 function unfilterJSON(filter) { 586 return this.replace(filter || Prototype.JSONFilter, '$1'); 587 } 588 589 function isJSON() { 590 var str = this; 591 if (str.blank()) return false; 592 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 593 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 594 } 595 596 function evalJSON(sanitize) { 597 var json = this.unfilterJSON(); 598 try { 599 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 600 } catch (e) { } 601 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 602 } 603 604 function include(pattern) { 605 return this.indexOf(pattern) > -1; 606 } 607 608 function startsWith(pattern) { 609 return this.indexOf(pattern) === 0; 610 } 611 612 function endsWith(pattern) { 613 var d = this.length - pattern.length; 614 return d >= 0 && this.lastIndexOf(pattern) === d; 615 } 616 617 function empty() { 618 return this == ''; 619 } 620 621 function blank() { 622 return /^\s*$/.test(this); 623 } 624 625 function interpolate(object, pattern) { 626 return new Template(this, pattern).evaluate(object); 627 } 628 629 return { 630 gsub: gsub, 631 sub: sub, 632 scan: scan, 633 truncate: truncate, 634 strip: String.prototype.trim ? String.prototype.trim : strip, 635 stripTags: stripTags, 636 stripScripts: stripScripts, 637 extractScripts: extractScripts, 638 evalScripts: evalScripts, 639 escapeHTML: escapeHTML, 640 unescapeHTML: unescapeHTML, 641 toQueryParams: toQueryParams, 642 parseQuery: toQueryParams, 643 toArray: toArray, 644 succ: succ, 645 times: times, 646 camelize: camelize, 647 capitalize: capitalize, 648 underscore: underscore, 649 dasherize: dasherize, 650 inspect: inspect, 651 toJSON: toJSON, 652 unfilterJSON: unfilterJSON, 653 isJSON: isJSON, 654 evalJSON: evalJSON, 655 include: include, 656 startsWith: startsWith, 657 endsWith: endsWith, 658 empty: empty, 659 blank: blank, 660 interpolate: interpolate 661 }; 662})()); 663 664var Template = Class.create({ 665 initialize: function(template, pattern) { 666 this.template = template.toString(); 667 this.pattern = pattern || Template.Pattern; 668 }, 669 670 evaluate: function(object) { 671 if (object && Object.isFunction(object.toTemplateReplacements)) 672 object = object.toTemplateReplacements(); 673 674 return this.template.gsub(this.pattern, function(match) { 675 if (object == null) return (match[1] + ''); 676 677 var before = match[1] || ''; 678 if (before == '\\') return match[2]; 679 680 var ctx = object, expr = match[3]; 681 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 682 match = pattern.exec(expr); 683 if (match == null) return before; 684 685 while (match != null) { 686 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; 687 ctx = ctx[comp]; 688 if (null == ctx || '' == match[3]) break; 689 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 690 match = pattern.exec(expr); 691 } 692 693 return before + String.interpret(ctx); 694 }); 695 } 696}); 697Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 698 699var $break = { }; 700 701var Enumerable = (function() { 702 function each(iterator, context) { 703 var index = 0; 704 try { 705 this._each(function(value) { 706 iterator.call(context, value, index++); 707 }); 708 } catch (e) { 709 if (e != $break) throw e; 710 } 711 return this; 712 } 713 714 function eachSlice(number, iterator, context) { 715 var index = -number, slices = [], array = this.toArray(); 716 if (number < 1) return array; 717 while ((index += number) < array.length) 718 slices.push(array.slice(index, index+number)); 719 return slices.collect(iterator, context); 720 } 721 722 function all(iterator, context) { 723 iterator = iterator || Prototype.K; 724 var result = true; 725 this.each(function(value, index) { 726 result = result && !!iterator.call(context, value, index); 727 if (!result) throw $break; 728 }); 729 return result; 730 } 731 732 function any(iterator, context) { 733 iterator = iterator || Prototype.K; 734 var result = false;
735 this.each(function(value, index) { 736 if (result = !!iterator.call(context, value, index)) 737 throw $break; 738 }); 739 return result; 740 } 741 742 function collect(iterator, context) { 743 iterator = iterator || Prototype.K; 744 var results = []; 745 this.each(function(value, index) { 746 results.push(iterator.call(context, value, index)); 747 }); 748 return results; 749 } 750 751 function detect(iterator, context) { 752 var result; 753 this.each(function(value, index) { 754 if (iterator.call(context, value, index)) { 755 result = value; 756 throw $break; 757 } 758 }); 759 return result; 760 } 761 762 function findAll(iterator, context) { 763 var results = []; 764 this.each(function(value, index) { 765 if (iterator.call(context, value, index)) 766 results.push(value); 767 }); 768 return results; 769 } 770 771 function grep(filter, iterator, context) { 772 iterator = iterator || Prototype.K; 773 var results = []; 774 775 if (Object.isString(filter)) 776 filter = new RegExp(RegExp.escape(filter)); 777 778 this.each(function(value, index) { 779 if (filter.match(value)) 780 results.push(iterator.call(context, value, index)); 781 }); 782 return results; 783 } 784 785 function include(object) { 786 if (Object.isFunction(this.indexOf)) 787 if (this.indexOf(object) != -1) return true; 788 789 var found = false; 790 this.each(function(value) { 791 if (value == object) { 792 found = true; 793 throw $break; 794 } 795 }); 796 return found; 797 } 798 799 function inGroupsOf(number, fillWith) { 800 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 801 return this.eachSlice(number, function(slice) { 802 while(slice.length < number) slice.push(fillWith); 803 return slice; 804 }); 805 } 806 807 function inject(memo, iterator, context) { 808 this.each(function(value, index) { 809 memo = iterator.call(context, memo, value, index); 810 }); 811 return memo; 812 } 813 814 function invoke(method) { 815 var args = $A(arguments).slice(1); 816 return this.map(function(value) { 817 return value[method].apply(value, args); 818 }); 819 } 820 821 function max(iterator, context) { 822 iterator = iterator || Prototype.K; 823 var result; 824 this.each(function(value, index) { 825 value = iterator.call(context, value, index); 826 if (result == null || value >= result) 827 result = value; 828 }); 829 return result; 830 } 831 832 function min(iterator, context) { 833 iterator = iterator || Prototype.K; 834 var result; 835 this.each(function(value, index) { 836 value = iterator.call(context, value, index); 837 if (result == null || value < result) 838 result = value; 839 }); 840 return result; 841 } 842 843 function partition(iterator, context) { 844 iterator = iterator || Prototype.K; 845 var trues = [], falses = []; 846 this.each(function(value, index) { 847 (iterator.call(context, value, index) ? 848 trues : falses).push(value); 849 }); 850 return [trues, falses]; 851 } 852 853 function pluck(property) { 854 var results = []; 855 this.each(function(value) { 856 results.push(value[property]); 857 }); 858 return results; 859 } 860 861 function reject(iterator, context) { 862 var results = []; 863 this.each(function(value, index) { 864 if (!iterator.call(context, value, index)) 865 results.push(value); 866 }); 867 return results; 868 } 869 870 function sortBy(iterator, context) { 871 return this.map(function(value, index) { 872 return { 873 value: value, 874 criteria: iterator.call(context, value, index) 875 }; 876 }).sort(function(left, right) { 877 var a = left.criteria, b = right.criteria; 878 return a < b ? -1 : a > b ? 1 : 0; 879 }).pluck('value'); 880 } 881 882 function toArray() { 883 return this.map(); 884 } 885 886 function zip() { 887 var iterator = Prototype.K, args = $A(arguments); 888 if (Object.isFunction(args.last())) 889 iterator = args.pop(); 890 891 var collections = [this].concat(args).map($A); 892 return this.map(function(value, index) { 893 return iterator(collections.pluck(index)); 894 }); 895 } 896 897 function size() { 898 return this.toArray().length; 899 } 900 901 function inspect() { 902 return '#<Enumerable:' + this.toArray().inspect() + '>'; 903 } 904 905 906 907 908 909 910 911 912 913 return { 914 each: each, 915 eachSlice: eachSlice, 916 all: all, 917 every: all, 918 any: any, 919 some: any, 920 collect: collect, 921 map: collect, 922 detect: detect, 923 findAll: findAll, 924 select: findAll, 925 filter: findAll, 926 grep: grep, 927 include: include, 928 member: include, 929 inGroupsOf: inGroupsOf, 930 inject: inject, 931 invoke: invoke, 932 max: max, 933 min: min, 934 partition: partition, 935 pluck: pluck, 936 reject: reject, 937 sortBy: sortBy, 938 toArray: toArray, 939 entries: toArray, 940 zip: zip, 941 size: size, 942 inspect: inspect, 943 find: detect
944 }; 945})(); 946function $A(iterable) { 947 if (!iterable) return []; 948 if ('toArray' in Object(iterable)) return iterable.toArray(); 949 var length = iterable.length || 0, results = new Array(length); 950 while (length--) results[length] = iterable[length]; 951 return results; 952} 953 954function $w(string) { 955 if (!Object.isString(string)) return []; 956 string = string.strip(); 957 return string ? string.split(/\s+/) : []; 958} 959 960Array.from = $A; 961 962 963(function() { 964 var arrayProto = Array.prototype, 965 slice = arrayProto.slice, 966 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available 967 968 function each(iterator) { 969 for (var i = 0, length = this.length; i < length; i++) 970 iterator(this[i]); 971 } 972 if (!_each) _each = each; 973 974 function clear() { 975 this.length = 0; 976 return this; 977 } 978 979 function first() { 980 return this[0]; 981 } 982 983 function last() { 984 return this[this.length - 1]; 985 } 986 987 function compact() { 988 return this.select(function(value) { 989 return value != null; 990 }); 991 } 992 993 function flatten() { 994 return this.inject([], function(array, value) { 995 if (Object.isArray(value)) 996 return array.concat(value.flatten()); 997 array.push(value); 998 return array; 999 }); 1000 } 1001 1002 function without() { 1003 var values = slice.call(arguments, 0); 1004 return this.select(function(value) { 1005 return !values.include(value); 1006 }); 1007 } 1008 1009 function reverse(inline) { 1010 return (inline !== false ? this : this.toArray())._reverse(); 1011 } 1012 1013 function uniq(sorted) { 1014 return this.inject([], function(array, value, index) { 1015 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 1016 array.push(value); 1017 return array; 1018 }); 1019 } 1020 1021 function intersect(array) { 1022 return this.uniq().findAll(function(item) { 1023 return array.detect(function(value) { return item === value }); 1024 }); 1025 } 1026 1027 1028 function clone() { 1029 return slice.call(this, 0); 1030 } 1031 1032 function size() { 1033 return this.length; 1034 } 1035 1036 function inspect() { 1037 return '[' + this.map(Object.inspect).join(', ') + ']'; 1038 } 1039 1040 function toJSON() { 1041 var results = []; 1042 this.each(function(object) { 1043 var value = Object.toJSON(object); 1044 if (!Object.isUndefined(value)) results.push(value); 1045 }); 1046 return '[' + results.join(', ') + ']'; 1047 } 1048 1049 function indexOf(item, i) { 1050 i || (i = 0); 1051 var length = this.length; 1052 if (i < 0) i = length + i; 1053 for (; i < length; i++) 1054 if (this[i] === item) return i; 1055 return -1; 1056 } 1057 1058 function lastIndexOf(item, i) { 1059 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 1060 var n = this.slice(0, i).reverse().indexOf(item); 1061 return (n < 0) ? n : i - n - 1; 1062 } 1063 1064 function concat() { 1065 var array = slice.call(this, 0), item; 1066 for (var i = 0, length = arguments.length; i < length; i++) { 1067 item = arguments[i]; 1068 if (Object.isArray(item) && !('callee' in item)) { 1069 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) 1070 array.push(item[j]); 1071 } else { 1072 array.push(item); 1073 } 1074 } 1075 return array; 1076 } 1077 1078 Object.extend(arrayProto, Enumerable); 1079 1080 if (!arrayProto._reverse) 1081 arrayProto._reverse = arrayProto.reverse; 1082 1083 Object.extend(arrayProto, { 1084 _each: _each, 1085 clear: clear, 1086 first: first, 1087 last: last, 1088 compact: compact, 1089 flatten: flatten, 1090 without: without, 1091 reverse: reverse, 1092 uniq: uniq, 1093 intersect: intersect, 1094 clone: clone, 1095 toArray: clone, 1096 size: size, 1097 inspect: inspect, 1098 toJSON: toJSON 1099 }); 1100 1101 var CONCAT_ARGUMENTS_BUGGY = (function() { 1102 return [].concat(arguments)[0][0] !== 1; 1103 })(1,2) 1104 1105 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; 1106 1107 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; 1108 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; 1109})(); 1110function $H(object) { 1111 return new Hash(object); 1112}; 1113 1114var Hash = Class.create(Enumerable, (function() { 1115 function initialize(object) { 1116 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 1117 } 1118 1119 function _each(iterator) { 1120 for (var key in this._object) { 1121 var value = this._object[key], pair = [key, value]; 1122 pair.key = key; 1123 pair.value = value; 1124 iterator(pair); 1125 } 1126 } 1127 1128 function set(key, value) { 1129 return this._object[key] = value; 1130 } 1131 1132 function get(key) { 1133 if (this._object[key] !== Object.prototype[key]) 1134 return this._object[key]; 1135 } 1136 1137 function unset(key) { 1138 var value = this._object[key]; 1139 delete this._object[key]; 1140 return value; 1141 } 1142 1143 function toObject() { 1144 return Object.clone(this._object); 1145 } 1146 1147 function keys() { 1148 return this.pluck('key'); 1149 } 1150 1151 function values() { 1152 return this.pluck('value'); 1153 } 1154 1155 function index(value) { 1156 var match = this.detect(function(pair) { 1157 return pair.value === value; 1158 }); 1159 return match && match.key; 1160 } 1161 1162 function merge(object) { 1163 return this.clone().update(object); 1164 } 1165 1166 function update(object) { 1167 return new Hash(object).inject(this, function(result, pair) { 1168 result.set(pair.key, pair.value); 1169 return result; 1170 }); 1171 } 1172 1173 function toQueryPair(key, value) { 1174 if (Object.isUndefined(value)) return key; 1175 return key + '=' + encodeURIComponent(String.interpret(value)); 1176 } 1177 1178 function toQueryString() { 1179 return this.inject([], function(results, pair) { 1180 var key = encodeURIComponent(pair.key), values = pair.value; 1181 1182 if (values && typeof values == 'object') { 1183 if (Object.isArray(values)) 1184 return results.concat(values.map(toQueryPair.curry(key))); 1185 } else results.push(toQueryPair(key, values)); 1186 return results; 1187 }).join('&'); 1188 } 1189 1190 function inspect() { 1191 return '#<Hash:{' + this.map(function(pair) { 1192 return pair.map(Object.inspect).join(': '); 1193 }).join(', ') + '}>'; 1194 } 1195 1196 function toJSON() { 1197 return Object.toJSON(this.toObject()); 1198 } 1199 1200 function clone() { 1201 return new Hash(this); 1202 } 1203 1204 return { 1205 initialize: initialize, 1206 _each: _each, 1207 set: set, 1208 get: get, 1209 unset: unset, 1210 toObject: toObject, 1211 toTemplateReplacements: toObject, 1212 keys: keys, 1213 values: values, 1214 index: index, 1215 merge: merge, 1216 update: update, 1217 toQueryString: toQueryString, 1218 inspect: inspect, 1219 toJSON: toJSON, 1220 clone: clone 1221 }; 1222})()); 1223 1224Hash.from = $H; 1225Object.extend(Number.prototype, (function() { 1226 function toColorPart() { 1227 return this.toPaddedString(2, 16); 1228 } 1229 1230 function succ() { 1231 return this + 1; 1232 } 1233 1234 function times(iterator, context) { 1235 $R(0, this, true).each(iterator, context); 1236 return this; 1237 } 1238 1239 function toPaddedString(length, radix) { 1240 var string = this.toString(radix || 10); 1241 return '0'.times(length - string.length) + string; 1242 } 1243 1244 function toJSON() { 1245 return isFinite(this) ? this.toString() : 'null';
1246 } 1247 1248 function abs() { 1249 return Math.abs(this); 1250 } 1251 1252 function round() { 1253 return Math.round(this); 1254 } 1255 1256 function ceil() { 1257 return Math.ceil(this); 1258 } 1259 1260 function floor() { 1261 return Math.floor(this); 1262 } 1263 1264 return { 1265 toColorPart: toColorPart, 1266 succ: succ, 1267 times: times, 1268 toPaddedString: toPaddedString, 1269 toJSON: toJSON, 1270 abs: abs, 1271 round: round, 1272 ceil: ceil, 1273 floor: floor 1274 }; 1275})()); 1276 1277function $R(start, end, exclusive) { 1278 return new ObjectRange(start, end, exclusive); 1279} 1280 1281var ObjectRange = Class.create(Enumerable, (function() { 1282 function initialize(start, end, exclusive) { 1283 this.start = start; 1284 this.end = end; 1285 this.exclusive = exclusive; 1286 } 1287 1288 function _each(iterator) { 1289 var value = this.start; 1290 while (this.include(value)) { 1291 iterator(value); 1292 value = value.succ(); 1293 } 1294 } 1295 1296 function include(value) { 1297 if (value < this.start) 1298 return false; 1299 if (this.exclusive) 1300 return value < this.end; 1301 return value <= this.end; 1302 } 1303 1304 return { 1305 initialize: initialize, 1306 _each: _each, 1307 include: include 1308 }; 1309})()); 1310 1311 1312 1313var Ajax = { 1314 getTransport: function() { 1315 return Try.these( 1316 function() {return new XMLHttpRequest()}, 1317 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 1318 function() {return new ActiveXObject('Microsoft.XMLHTTP')} 1319 ) || false; 1320 }, 1321 1322 activeRequestCount: 0 1323}; 1324 1325Ajax.Responders = { 1326 responders: [], 1327 1328 _each: function(iterator) { 1329 this.responders._each(iterator); 1330 }, 1331 1332 register: function(responder) { 1333 if (!this.include(responder)) 1334 this.responders.push(responder); 1335 }, 1336 1337 unregister: function(responder) { 1338 this.responders = this.responders.without(responder); 1339 }, 1340 1341 dispatch: function(callback, request, transport, json) { 1342 this.each(function(responder) { 1343 if (Object.isFunction(responder[callback])) { 1344 try { 1345 responder[callback].apply(responder, [request, transport, json]); 1346 } catch (e) { } 1347 } 1348 }); 1349 } 1350}; 1351 1352Object.extend(Ajax.Responders, Enumerable); 1353 1354Ajax.Responders.register({ 1355 onCreate: function() { Ajax.activeRequestCount++ },
1356 onComplete: function() { Ajax.activeRequestCount-- } 1357}); 1358Ajax.Base = Class.create({ 1359 initialize: function(options) { 1360 this.options = { 1361 method: 'post', 1362 asynchronous: true, 1363 contentType: 'application/x-www-form-urlencoded', 1364 encoding: 'UTF-8', 1365 parameters: '', 1366 evalJSON: true, 1367 evalJS: true 1368 }; 1369 Object.extend(this.options, options || { }); 1370 1371 this.options.method = this.options.method.toLowerCase(); 1372 1373 if (Object.isString(this.options.parameters)) 1374 this.options.parameters = this.options.parameters.toQueryParams(); 1375 else if (Object.isHash(this.options.parameters)) 1376 this.options.parameters = this.options.parameters.toObject(); 1377 } 1378}); 1379Ajax.Request = Class.create(Ajax.Base, { 1380 _complete: false, 1381 _timeout: false, 1382 1383 initialize: function($super, url, options) { 1384 $super(options); 1385 this.transport = Ajax.getTransport(); 1386 this.request(url); 1387 }, 1388 1389 request: function(url) { 1390 this.url = url; 1391 this.method = this.options.method; 1392 var params = Object.clone(this.options.parameters); 1393 1394 if (!['get', 'post'].include(this.method)) { 1395 params['_method'] = this.method; 1396 this.method = 'post'; 1397 } 1398 1399 this.parameters = params; 1400 1401 if (params = Object.toQueryString(params)) { 1402 if (this.method == 'get') 1403 this.url += (this.url.include('?') ? '&' : '?') + params; 1404 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1405 params += '&_='; 1406 } 1407 1408 try { 1409 var response = new Ajax.Response(this); 1410 if (this.options.onCreate) this.options.onCreate(response); 1411 Ajax.Responders.dispatch('onCreate', this, response); 1412 1413 this.transport.open(this.method.toUpperCase(), this.url, 1414 this.options.asynchronous); 1415 1416 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 1417 1418 this.transport.onreadystatechange = this.onStateChange.bind(this); 1419 this.setRequestHeaders(); 1420 1421 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 1422 this.transport.send(this.body); 1423 1424 /* Force Firefox to handle ready state 4 for synchronous requests */ 1425 if (!this.options.asynchronous && this.transport.overrideMimeType) 1426 this.onStateChange();
1427 if(this.options.timeoutDelay && this.options.onTimeout) 1428 this.startTimer(this.options.timeoutDelay); 1429 } 1430 catch (e) { 1431 this.dispatchException(e); 1432 } 1433 }, 1434 1435 onStateChange: function() { 1436 var readyState = this.transport.readyState; 1437 if (readyState > 1 && !((readyState == 4) && this._complete) && !this._timeout) 1438 this.respondToReadyState(this.transport.readyState); 1439 }, 1440 1441 setRequestHeaders: function() { 1442 var headers = { 1443 'X-Requested-With': 'XMLHttpRequest', 1444 'X-Prototype-Version': Prototype.Version, 1445 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 1446 }; 1447 1448 if (this.method == 'post') { 1449 headers['Content-type'] = this.options.contentType + 1450 (this.options.encoding ? '; charset=' + this.options.encoding : ''); 1451 1452 /* Force "Connection: close" for older Mozilla browsers to work 1453 * around a bug where XMLHttpRequest sends an incorrect 1454 * Content-length header. See Mozilla Bugzilla #246651. 1455 */ 1456 if (this.transport.overrideMimeType && 1457 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 1458 headers['Connection'] = 'close'; 1459 } 1460 1461 if (typeof this.options.requestHeaders == 'object') { 1462 var extras = this.options.requestHeaders; 1463 1464 if (Object.isFunction(extras.push)) 1465 for (var i = 0, length = extras.length; i < length; i += 2) 1466 headers[extras[i]] = extras[i+1]; 1467 else 1468 $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 1469 } 1470 1471 for (var name in headers) 1472 this.transport.setRequestHeader(name, headers[name]); 1473 }, 1474 1475 success: function() { 1476 var status = this.getStatus(); 1477 return !status || (status >= 200 && status < 300); 1478 }, 1479 1480 getStatus: function() { 1481 try { 1482 return this.transport.status || 0; 1483 } catch (e) { return 0 } 1484 }, 1485 clearTimeout : function(){ 1486 clearTimeout(this.timer); 1487 }, 1488 startTimer : function(sec){ 1489 this.timer = setTimeout(this.handleTimeout.bind(this), (sec*1000)); 1490 }, 1491 handleTimeout : function(){
1492 try{ 1493 this.timeout = true; 1494 this.transport.abort(); 1495 this.options.onTimeout(new Ajax.Response(this)); 1496 } 1497 catch (e) { 1498 this.dispatchException(e); 1499 } 1500 }, 1501 1502 respondToReadyState: function(readyState) { 1503 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 1504 1505 if (state == 'Complete') { 1506 try { 1507 this._complete = true; 1508 (this.options['on' + response.status] 1509 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 1510 || Prototype.emptyFunction)(response, response.headerJSON); 1511 } catch (e) { 1512 this.dispatchException(e); 1513 } 1514 1515 var contentType = response.getHeader('Content-type'); 1516 if (this.options.evalJS == 'force' 1517 || (this.options.evalJS && this.isSameOrigin() && contentType 1518 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1519 this.evalResponse(); 1520 } 1521 1522 try { 1523 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 1524 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 1525 } catch (e) { 1526 this.dispatchException(e); 1527 } 1528 1529 if (state == 'Complete') { 1530 this.clearTimeout(); 1531 this.transport.onreadystatechange = Prototype.emptyFunction; 1532 } 1533 }, 1534 1535 isSameOrigin: function() { 1536 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 1537 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 1538 protocol: location.protocol, 1539 domain: document.domain, 1540 port: location.port ? ':' + location.port : '' 1541 })); 1542 }, 1543 1544 getHeader: function(name) { 1545 try { 1546 return this.transport.getResponseHeader(name) || null; 1547 } catch (e) { return null; } 1548 }, 1549 1550 evalResponse: function() { 1551 try { 1552 return eval((this.transport.responseText || '').unfilterJSON()); 1553 } catch (e) { 1554 this.dispatchException(e); 1555 } 1556 }, 1557 1558 dispatchException: function(exception) { 1559 (this.options.onException || Prototype.emptyFunction)(this, exception); 1560 Ajax.Responders.dispatch('onException', this, exception); 1561 } 1562}); 1563 1564Ajax.Request.Events = 1565 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1566 1567 1568 1569 1570 1571 1572 1573 1574Ajax.Response = Class.create({ 1575 initialize: function(request){ 1576 this.request = request; 1577 var transport = this.transport = request.transport, 1578 readyState = this.readyState = transport.readyState; 1579 1580 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 1581 this.status = this.getStatus(); 1582 this.statusText = this.getStatusText(); 1583 this.responseText = String.interpret(transport.responseText); 1584 this.headerJSON = this._getHeaderJSON(); 1585 } 1586 1587 if(readyState == 4) { 1588 var xml = transport.responseXML; 1589 this.responseXML = Object.isUndefined(xml) ? null : xml; 1590 this.responseJSON = this._getResponseJSON(); 1591 } 1592 }, 1593 1594 status: 0, 1595 1596 statusText: '', 1597 1598 getStatus: Ajax.Request.prototype.getStatus, 1599 1600 getStatusText: function() { 1601 try { 1602 return this.transport.statusText || ''; 1603 } catch (e) { return '' } 1604 }, 1605 1606 getHeader: Ajax.Request.prototype.getHeader, 1607 1608 getAllHeaders: function() { 1609 try { 1610 return this.getAllResponseHeaders(); 1611 } catch (e) { return null } 1612 }, 1613 1614 getResponseHeader: function(name) { 1615 return this.transport.getResponseHeader(name); 1616 }, 1617 1618 getAllResponseHeaders: function() { 1619 return this.transport.getAllResponseHeaders(); 1620 }, 1621 1622 _getHeaderJSON: function() { 1623 var json = this.getHeader('X-JSON'); 1624 if (!json) return null; 1625 json = decodeURIComponent(escape(json)); 1626 try { 1627 return json.evalJSON(this.request.options.sanitizeJSON || 1628 !this.request.isSameOrigin()); 1629 } catch (e) { 1630 this.request.dispatchException(e); 1631 } 1632 }, 1633 1634 _getResponseJSON: function() { 1635 var options = this.request.options; 1636 if (!options.evalJSON || (options.evalJSON != 'force' && 1637 !(this.getHeader('Content-type') || '').include('application/json')) || 1638 this.responseText.blank()) 1639 return null; 1640 try { 1641 return this.responseText.evalJSON(options.sanitizeJSON || 1642 !this.request.isSameOrigin()); 1643 } catch (e) { 1644 this.request.dispatchException(e); 1645 } 1646 } 1647}); 1648 1649Ajax.Updater = Class.create(Ajax.Request, { 1650 initialize: function($super, container, url, options) { 1651 this.container = { 1652 success: (container.success || container), 1653 failure: (container.failure || (container.success ? null : container)) 1654 }; 1655 1656 options = Object.clone(options); 1657 var onComplete = options.onComplete; 1658 options.onComplete = (function(response, json) { 1659 this.updateContent(response.responseText); 1660 if (Object.isFunction(onComplete)) onComplete(response, json); 1661 }).bind(this); 1662 1663 $super(url, options); 1664 }, 1665 1666 updateContent: function(responseText) { 1667 var receiver = this.container[this.success() ? 'success' : 'failure'], 1668 options = this.options; 1669 1670 if (!options.evalScripts) responseText = responseText.stripScripts(); 1671 1672 if (receiver = $(receiver)) { 1673 if (options.insertion) { 1674 if (Object.isString(options.insertion)) { 1675 var insertion = { }; insertion[options.insertion] = responseText; 1676 receiver.insert(insertion); 1677 } 1678 else options.insertion(receiver, responseText); 1679 } 1680 else receiver.update(responseText); 1681 } 1682 } 1683}); 1684
1685Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 1686 initialize: function($super, container, url, options) { 1687 $super(options); 1688 this.onComplete = this.options.onComplete; 1689 1690 this.frequency = (this.options.frequency || 2); 1691 this.decay = (this.options.decay || 1); 1692 1693 this.updater = { }; 1694 this.container = container; 1695 this.url = url; 1696 1697 this.start(); 1698 }, 1699 1700 start: function() { 1701 this.options.onComplete = this.updateComplete.bind(this); 1702 this.onTimerEvent(); 1703 }, 1704 1705 stop: function() { 1706 this.updater.options.onComplete = undefined; 1707 clearTimeout(this.timer); 1708 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 1709 }, 1710 1711 updateComplete: function(response) { 1712 if (this.options.decay) { 1713 this.decay = (response.responseText == this.lastText ? 1714 this.decay * this.options.decay : 1); 1715 1716 this.lastText = response.responseText; 1717 } 1718 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 1719 }, 1720 1721 onTimerEvent: function() { 1722 this.updater = new Ajax.Updater(this.container, this.url, this.options); 1723 } 1724}); 1725 1726 1727 1728function $(element) { 1729 if (arguments.length > 1) { 1730 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 1731 elements.push($(arguments[i])); 1732 return elements; 1733 } 1734 if (Object.isString(element)) 1735 element = document.getElementById(element); 1736 return Element.extend(element); 1737} 1738 1739if (Prototype.BrowserFeatures.XPath) { 1740 document._getElementsByXPath = function(expression, parentElement) { 1741 var results = []; 1742 var query = document.evaluate(expression, $(parentElement) || document, 1743 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 1744 for (var i = 0, length = query.snapshotLength; i < length; i++) 1745 results.push(Element.extend(query.snapshotItem(i))); 1746 return results; 1747 }; 1748} 1749 1750/*--------------------------------------------------------------------------*/ 1751 1752if (!window.Node) var Node = { }; 1753 1754if (!Node.ELEMENT_NODE) { 1755 Object.extend(Node, { 1756 ELEMENT_NODE: 1, 1757 ATTRIBUTE_NODE: 2, 1758 TEXT_NODE: 3, 1759 CDATA_SECTION_NODE: 4, 1760 ENTITY_REFERENCE_NODE: 5, 1761 ENTITY_NODE: 6, 1762 PROCESSING_INSTRUCTION_NODE: 7, 1763 COMMENT_NODE: 8, 1764 DOCUMENT_NODE: 9, 1765 DOCUMENT_TYPE_NODE: 10, 1766 DOCUMENT_FRAGMENT_NODE: 11, 1767 NOTATION_NODE: 12 1768 }); 1769} 1770 1771 1772(function(global) { 1773 1774 var SETATTRIBUTE_IGNORES_NAME = (function(){ 1775 var elForm = document.createElement("form"); 1776 var elInput = document.createElement("input"); 1777 var root = document.documentElement; 1778 elInput.setAttribute("name", "test"); 1779 elForm.appendChild(elInput); 1780 root.appendChild(elForm); 1781 var isBuggy = elForm.elements 1782 ? (typeof elForm.elements.test == "undefined") 1783 : null; 1784 root.removeChild(elForm); 1785 elForm = elInput = null; 1786 return isBuggy; 1787 })(); 1788 1789 var element = global.Element; 1790 global.Element = function(tagName, attributes) { 1791 attributes = attributes || { }; 1792 tagName = tagName.toLowerCase(); 1793 var cache = Element.cache; 1794 if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { 1795 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 1796 delete attributes.name; 1797 return Element.writeAttribute(document.createElement(tagName), attributes); 1798 } 1799 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 1800 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 1801 }; 1802 Object.extend(global.Element, element || { }); 1803 if (element) global.Element.prototype = element.prototype; 1804})(this); 1805 1806Element.cache = { }; 1807Element.idCounter = 1; 1808 1809Element.Methods = { 1810 visible: function(element) { 1811 return $(element).style.display != 'none'; 1812 }, 1813 1814 toggle: function(element) { 1815 element = $(element); 1816 Element[Element.visible(element) ? 'hide' : 'show'](element); 1817 return element; 1818 }, 1819 1820 1821 hide: function(element) { 1822 element = $(element); 1823 element.style.display = 'none'; 1824 return element; 1825 }, 1826 1827 show: function(element) { 1828 element = $(element); 1829 element.style.display = ''; 1830 return element; 1831 }, 1832 1833 remove: function(element) { 1834 element = $(element); 1835 element.parentNode.removeChild(element); 1836 return element; 1837 }, 1838 1839 update: (function(){ 1840 1841 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ 1842 var el = document.createElement("select"), 1843 isBuggy = true; 1844 el.innerHTML = "<option value=\"test\">test</option>"; 1845 if (el.options && el.options[0]) { 1846 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; 1847 } 1848 el = null; 1849 return isBuggy; 1850 })(); 1851 1852 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
1853 try { 1854 var el = document.createElement("table"); 1855 if (el && el.tBodies) { 1856 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; 1857 var isBuggy = typeof el.tBodies[0] == "undefined"; 1858 el = null; 1859 return isBuggy; 1860 } 1861 } catch (e) { 1862 return true; 1863 } 1864 })(); 1865 1866 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { 1867 var s = document.createElement("script"), 1868 isBuggy = false; 1869 try { 1870 s.appendChild(document.createTextNode("")); 1871 isBuggy = !s.firstChild || 1872 s.firstChild && s.firstChild.nodeType !== 3; 1873 } catch (e) { 1874 isBuggy = true; 1875 } 1876 s = null; 1877 return isBuggy; 1878 })(); 1879 1880 function update(element, content) { 1881 element = $(element); 1882 1883 if (content && content.toElement) 1884 content = content.toElement(); 1885 1886 if (Object.isElement(content)) 1887 return element.update().insert(content); 1888 1889 content = Object.toHTML(content); 1890 1891 var tagName = element.tagName.toUpperCase(); 1892 1893 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { 1894 element.text = content; 1895 return element; 1896 } 1897 1898 if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { 1899 if (tagName in Element._insertionTranslations.tags) { 1900 while (element.firstChild) { 1901 element.removeChild(element.firstChild); 1902 } 1903 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 1904 .each(function(node) { 1905 element.appendChild(node) 1906 }); 1907 } 1908 else { 1909 element.innerHTML = content.stripScripts(); 1910 } 1911 } 1912 else { 1913 element.innerHTML = content.stripScripts(); 1914 } 1915 1916 content.evalScripts.bind(content).defer(); 1917 return element; 1918 } 1919 1920 return update; 1921 })(), 1922 1923 replace: function(element, content) { 1924 element = $(element); 1925 if (content && content.toElement) content = content.toElement(); 1926 else if (!Object.isElement(content)) { 1927 content = Object.toHTML(content); 1928 var range = element.ownerDocument.createRange(); 1929 range.selectNode(element); 1930 content.evalScripts.bind(content).defer(); 1931 content = range.createContextualFragment(content.stripScripts()); 1932 } 1933 element.parentNode.replaceChild(content, element); 1934 return element; 1935 }, 1936 1937 insert: function(element, insertions) { 1938 element = $(element); 1939 1940 if (Object.isString(insertions) || Object.isNumber(insertions) || 1941 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 1942 insertions = {bottom:insertions}; 1943 1944 var content, insert, tagName, childNodes; 1945 1946 for (var position in insertions) { 1947 content = insertions[position]; 1948 position = position.toLowerCase(); 1949 insert = Element._insertionTranslations[position]; 1950 1951 if (content && content.toElement) content = content.toElement(); 1952 if (Object.isElement(content)) { 1953 insert(element, content); 1954 continue; 1955 } 1956 1957 content = Object.toHTML(content); 1958 1959 tagName = ((position == 'before' || position == 'after') 1960 ? element.parentNode : element).tagName.toUpperCase(); 1961 1962 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 1963 1964 if (position == 'top' || position == 'after') childNodes.reverse(); 1965 childNodes.each(insert.curry(element)); 1966 1967 content.evalScripts.bind(content).defer(); 1968 } 1969 1970 return element; 1971 }, 1972 1973 wrap: function(element, wrapper, attributes) { 1974 element = $(element); 1975 if (Object.isElement(wrapper)) 1976 $(wrapper).writeAttribute(attributes || { }); 1977 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); 1978 else wrapper = new Element('div', wrapper); 1979 if (element.parentNode) 1980 element.parentNode.replaceChild(wrapper, element); 1981 wrapper.appendChild(element); 1982 return wrapper; 1983 }, 1984 1985 inspect: function(element) { 1986 element = $(element); 1987 var result = '<' + element.tagName.toLowerCase(); 1988 $H({'id': 'id', 'className': 'class'}).each(function(pair) { 1989 var property = pair.first(), attribute = pair.last(); 1990 var value = (element[property] || '').toString(); 1991 if (value) result += ' ' + attribute + '=' + value.inspect(true); 1992 }); 1993 return result + '>'; 1994 }, 1995 1996 recursivelyCollect: function(element, property) { 1997 element = $(element); 1998 var elements = []; 1999 while (element = element[property]) 2000 if (element.nodeType == 1) 2001 elements.push(Element.extend(element)); 2002 return elements; 2003 }, 2004 2005 ancestors: function(element) { 2006 return Element.recursivelyCollect(element, 'parentNode'); 2007 }, 2008 2009 descendants: function(element) { 2010 return Element.select(element, "*"); 2011 }, 2012 2013 firstDescendant: function(element) { 2014 element = $(element).firstChild; 2015 while (element && element.nodeType != 1) element = element.nextSibling; 2016 return $(element); 2017 }, 2018 2019 immediateDescendants: function(element) { 2020 if (!(element = $(element).firstChild)) return []; 2021 while (element && element.nodeType != 1) element = element.nextSibling; 2022 if (element) return [element].concat($(element).nextSiblings()); 2023 return []; 2024 }, 2025 2026 previousSiblings: function(element) { 2027 return Element.recursivelyCollect(element, 'previousSibling'); 2028 }, 2029 2030 nextSiblings: function(element) { 2031 return Element.recursivelyCollect(element, 'nextSibling'); 2032 }, 2033 2034 siblings: function(element) { 2035 element = $(element); 2036 return Element.previousSiblings(element).reverse() 2037 .concat(Element.nextSiblings(element)); 2038 }, 2039 2040 match: function(element, selector) { 2041 if (Object.isString(selector)) 2042 selector = new Selector(selector); 2043 return selector.match($(element)); 2044 }, 2045 2046 up: function(element, expression, index) { 2047 element = $(element); 2048 if (arguments.length == 1) return $(element.parentNode); 2049 var ancestors = Element.ancestors(element); 2050 return Object.isNumber(expression) ? ancestors[expression] : 2051 Selector.findElement(ancestors, expression, index); 2052 }, 2053 2054 down: function(element, expression, index) { 2055 element = $(element); 2056 if (arguments.length == 1) return Element.firstDescendant(element); 2057 return Object.isNumber(expression) ? Element.descendants(element)[expression] : 2058 Element.select(element, expression)[index || 0]; 2059 }, 2060 2061 previous: function(element, expression, index) { 2062 element = $(element); 2063 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 2064 var previousSiblings = Element.previousSiblings(element); 2065 return Object.isNumber(expression) ? previousSiblings[expression] : 2066 Selector.findElement(previousSiblings, expression, index); 2067 }, 2068 2069 next: function(element, expression, index) { 2070 element = $(element); 2071 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 2072 var nextSiblings = Element.nextSiblings(element); 2073 return Object.isNumber(expression) ? nextSiblings[expression] : 2074 Selector.findElement(nextSiblings, expression, index); 2075 }, 2076 2077 2078 select: function(element) { 2079 var args = Array.prototype.slice.call(arguments, 1); 2080 return Selector.findChildElements(element, args); 2081 }, 2082 2083 adjacent: function(element) { 2084 var args = Array.prototype.slice.call(arguments, 1); 2085 return Selector.findChildElements(element.parentNode, args).without(element); 2086 }, 2087 2088 identify: function(element) { 2089 element = $(element); 2090 var id = Element.readAttribute(element, 'id'); 2091 if (id) return id; 2092 do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); 2093 Element.writeAttribute(element, 'id', id); 2094 return id; 2095 }, 2096 2097 readAttribute: function(element, name) { 2098 element = $(element); 2099 if (Prototype.Browser.IE) { 2100 var t = Element._attributeTranslations.read; 2101 if (t.values[name]) return t.values[name](element, name); 2102 if (t.names[name]) name = t.names[name]; 2103 if (name.include(':')) { 2104 return (!element.attributes || !element.attributes[name]) ? null : 2105 element.attributes[name].value; 2106 } 2107 } 2108 return element.getAttribute(name); 2109 }, 2110 2111 writeAttribute: function(element, name, value) { 2112 element = $(element); 2113 var attributes = { }, t = Element._attributeTranslations.write; 2114 2115 if (typeof name == 'object') attributes = name; 2116 else attributes[name] = Object.isUndefined(value) ? true : value; 2117 2118 for (var attr in attributes) { 2119 name = t.names[attr] || attr; 2120 value = attributes[attr]; 2121 if (t.values[attr]) name = t.values[attr](element, value); 2122 if (value === false || value === null) 2123 element.removeAttribute(name); 2124 else if (value === true) 2125 element.setAttribute(name, name); 2126 else element.setAttribute(name, value); 2127 } 2128 return element; 2129 }, 2130 2131 getHeight: function(element) { 2132 return Element.getDimensions(element).height; 2133 }, 2134 2135 getWidth: function(element) { 2136 return Element.getDimensions(element).width; 2137 }, 2138 2139 classNames: function(element) { 2140 return new Element.ClassNames(element); 2141 }, 2142 2143 hasClassName: function(element, className) { 2144 if (!(element = $(element))) return; 2145 var elementClassName = element.className; 2146 return (elementClassName.length > 0 && (elementClassName == className || 2147 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); 2148 }, 2149 2150 addClassName: function(element, className) { 2151 if (!(element = $(element))) return; 2152 if (!Element.hasClassName(element, className)) 2153 element.className += (element.className ? ' ' : '') + className; 2154 return element; 2155 }, 2156 2157 removeClassName: function(element, className) { 2158 if (!(element = $(element))) return; 2159 element.className = element.className.replace( 2160 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); 2161 return element; 2162 }, 2163 2164 toggleClassName: function(element, className) { 2165 if (!(element = $(element))) return; 2166 return Element[Element.hasClassName(element, className) ? 2167 'removeClassName' : 'addClassName'](element, className); 2168 }, 2169 2170 cleanWhitespace: function(element) { 2171 element = $(element); 2172 var node = element.firstChild; 2173 while (node) { 2174 var nextNode = node.nextSibling; 2175 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 2176 element.removeChild(node); 2177 node = nextNode; 2178 } 2179 return element; 2180 }, 2181 2182 empty: function(element) { 2183 return $(element).innerHTML.blank(); 2184 }, 2185 2186 descendantOf: function(element, ancestor) { 2187 element = $(element), ancestor = $(ancestor); 2188 2189 if (element.compareDocumentPosition) 2190 return (element.compareDocumentPosition(ancestor) & 8) === 8; 2191 2192 if (ancestor.contains) 2193 return ancestor.contains(element) && ancestor !== element; 2194 2195 while (element = element.parentNode) 2196 if (element == ancestor) return true; 2197 2198 return false;
2199 }, 2200 2201 scrollTo: function(element) { 2202 element = $(element); 2203 var pos = Element.cumulativeOffset(element); 2204 window.scrollTo(pos[0], pos[1]); 2205 return element; 2206 }, 2207 2208 getStyle: function(element, style) { 2209 element = $(element); 2210 style = style == 'float' ? 'cssFloat' : style.camelize(); 2211 var value = element.style[style]; 2212 if (!value || value == 'auto') { 2213 var css = document.defaultView.getComputedStyle(element, null); 2214 value = css ? css[style] : null; 2215 } 2216 if (style == 'opacity') return value ? parseFloat(value) : 1.0; 2217 return value == 'auto' ? null : value; 2218 }, 2219 2220 getOpacity: function(element) { 2221 return $(element).getStyle('opacity'); 2222 }, 2223 2224 setStyle: function(element, styles) { 2225 element = $(element); 2226 var elementStyle = element.style, match; 2227 if (Object.isString(styles)) { 2228 element.style.cssText += ';' + styles; 2229 return styles.include('opacity') ? 2230 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; 2231 } 2232 for (var property in styles) 2233 if (property == 'opacity') element.setOpacity(styles[property]); 2234 else 2235 elementStyle[(property == 'float' || property == 'cssFloat') ? 2236 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : 2237 property] = styles[property]; 2238 2239 return element; 2240 }, 2241 2242 setOpacity: function(element, value) { 2243 element = $(element); 2244 element.style.opacity = (value == 1 || value === '') ? '' : 2245 (value < 0.00001) ? 0 : value; 2246 return element; 2247 }, 2248 2249 getDimensions: function(element) { 2250 element = $(element); 2251 var display = Element.getStyle(element, 'display'); 2252 if (display != 'none' && display != null) // Safari bug 2253 return {width: element.offsetWidth, height: element.offsetHeight}; 2254 2255 var els = element.style; 2256 var originalVisibility = els.visibility; 2257 var originalPosition = els.position; 2258 var originalDisplay = els.display; 2259 els.visibility = 'hidden'; 2260 if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari 2261 els.position = 'absolute'; 2262 els.display = 'block'; 2263 var originalWidth = element.clientWidth; 2264 var originalHeight = element.clientHeight; 2265 els.display = originalDisplay; 2266 els.position = originalPosition; 2267 els.visibility = originalVisibility; 2268 return {width: originalWidth, height: originalHeight}; 2269 }, 2270 2271 makePositioned: function(element) { 2272 element = $(element); 2273 var pos = Element.getStyle(element, 'position'); 2274 if (pos == 'static' || !pos) { 2275 element._madePositioned = true; 2276 element.style.position = 'relative'; 2277 if (Prototype.Browser.Opera) { 2278 element.style.top = 0; 2279 element.style.left = 0; 2280 } 2281 } 2282 return element; 2283 }, 2284 2285 undoPositioned: function(element) { 2286 element = $(element); 2287 if (element._madePositioned) { 2288 element._madePositioned = undefined; 2289 element.style.position = 2290 element.style.top = 2291 element.style.left = 2292 element.style.bottom = 2293 element.style.right = ''; 2294 } 2295 return element; 2296 }, 2297 2298 makeClipping: function(element) { 2299 element = $(element); 2300 if (element._overflow) return element; 2301 element._overflow = Element.getStyle(element, 'overflow') || 'auto'; 2302 if (element._overflow !== 'hidden') 2303 element.style.overflow = 'hidden'; 2304 return element; 2305 }, 2306 2307 undoClipping: function(element) { 2308 element = $(element); 2309 if (!element._overflow) return element; 2310 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; 2311 element._overflow = null; 2312 return element; 2313 }, 2314 2315 cumulativeOffset: function(element) { 2316 var valueT = 0, valueL = 0; 2317 do { 2318 valueT += element.offsetTop || 0; 2319 valueL += element.offsetLeft || 0; 2320 element = element.offsetParent; 2321 } while (element); 2322 return Element._returnOffset(valueL, valueT); 2323 }, 2324 2325 positionedOffset: function(element) { 2326 var valueT = 0, valueL = 0; 2327 do { 2328 valueT += element.offsetTop || 0; 2329 valueL += element.offsetLeft || 0; 2330 element = element.offsetParent; 2331 if (element) { 2332 if (element.tagName.toUpperCase() == 'BODY') break; 2333 var p = Element.getStyle(element, 'position'); 2334 if (p !== 'static') break; 2335 } 2336 } while (element); 2337 return Element._returnOffset(valueL, valueT); 2338 }, 2339 2340 absolutize: function(element) { 2341 element = $(element); 2342 if (Element.getStyle(element, 'position') == 'absolute') return element; 2343 2344 var offsets = Element.positionedOffset(element); 2345 var top = offsets[1]; 2346 var left = offsets[0]; 2347 var width = element.clientWidth; 2348 var height = element.clientHeight; 2349 2350 element._originalLeft = left - parseFloat(element.style.left || 0); 2351 element._originalTop = top - parseFloat(element.style.top || 0); 2352 element._originalWidth = element.style.width; 2353 element._originalHeight = element.style.height; 2354 2355 element.style.position = 'absolute'; 2356 element.style.top = top + 'px'; 2357 element.style.left = left + 'px'; 2358 element.style.width = width + 'px'; 2359 element.style.height = height + 'px'; 2360 return element; 2361 }, 2362 2363 relativize: function(element) { 2364 element = $(element); 2365 if (Element.getStyle(element, 'position') == 'relative') return element; 2366 2367 element.style.position = 'relative'; 2368 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 2369 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 2370 2371 element.style.top = top + 'px'; 2372 element.style.left = left + 'px'; 2373 element.style.height = element._originalHeight; 2374 element.style.width = element._originalWidth; 2375 return element; 2376 }, 2377 2378 cumulativeScrollOffset: function(element) { 2379 var valueT = 0, valueL = 0; 2380 do { 2381 valueT += element.scrollTop || 0; 2382 valueL += element.scrollLeft || 0; 2383 element = element.parentNode; 2384 } while (element); 2385 return Element._returnOffset(valueL, valueT); 2386 }, 2387 2388 getOffsetParent: function(element) { 2389 if (element.offsetParent) return $(element.offsetParent); 2390 if (element == document.body) return $(element); 2391 2392 while ((element = element.parentNode) && element != document.body) 2393 if (Element.getStyle(element, 'position') != 'static') 2394 return $(element); 2395 2396 return $(document.body); 2397 }, 2398 2399 viewportOffset: function(forElement) { 2400 var valueT = 0, valueL = 0; 2401 2402 var element = forElement; 2403 do { 2404 valueT += element.offsetTop || 0; 2405 valueL += element.offsetLeft || 0; 2406 2407 if (element.offsetParent == document.body && 2408 Element.getStyle(element, 'position') == 'absolute') break; 2409 2410 } while (element = element.offsetParent); 2411 2412 element = forElement; 2413 do { 2414 if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { 2415 valueT -= element.scrollTop || 0; 2416 valueL -= element.scrollLeft || 0; 2417 } 2418 } while (element = element.parentNode); 2419 2420 return Element._returnOffset(valueL, valueT); 2421 }, 2422 2423 clonePosition: function(element, source) { 2424 var options = Object.extend({ 2425 setLeft: true, 2426 setTop: true, 2427 setWidth: true, 2428 setHeight: true, 2429 offsetTop: 0, 2430 offsetLeft: 0 2431 }, arguments[2] || { }); 2432 2433 source = $(source); 2434 var p = Element.viewportOffset(source); 2435 2436 element = $(element); 2437 var delta = [0, 0]; 2438 var parent = null; 2439 if (Element.getStyle(element, 'position') == 'absolute') { 2440 parent = Element.getOffsetParent(element); 2441 delta = Element.viewportOffset(parent); 2442 } 2443 2444 if (parent == document.body) { 2445 delta[0] -= document.body.offsetLeft; 2446 delta[1] -= document.body.offsetTop; 2447 } 2448 2449 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 2450 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 2451 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; 2452 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; 2453 return element; 2454 } 2455}; 2456 2457Object.extend(Element.Methods, { 2458 getElementsBySelector: Element.Methods.select, 2459 2460 childElements: Element.Methods.immediateDescendants 2461}); 2462 2463Element._attributeTranslations = { 2464 write: { 2465 names: { 2466 className: 'class', 2467 htmlFor: 'for' 2468 }, 2469 values: { } 2470 } 2471}; 2472 2473if (Prototype.Browser.Opera) { 2474 Element.Methods.getStyle = Element.Methods.getStyle.wrap( 2475 function(proceed, element, style) { 2476 switch (style) { 2477 case 'left': case 'top': case 'right': case 'bottom': 2478 if (proceed(element, 'position') === 'static') return null; 2479 case 'height': case 'width': 2480 if (!Element.visible(element)) return null; 2481 2482 var dim = parseInt(proceed(element, style), 10); 2483 2484 if (dim !== element['offset' + style.capitalize()]) 2485 return dim + 'px'; 2486 2487 var properties; 2488 if (style === 'height') { 2489 properties = ['border-top-width', 'padding-top', 2490 'padding-bottom', 'border-bottom-width']; 2491 } 2492 else { 2493 properties = ['border-left-width', 'padding-left', 2494 'padding-right', 'border-right-width']; 2495 } 2496 return properties.inject(dim, function(memo, property) { 2497 var val = proceed(element, property); 2498 return val === null ? memo : memo - parseInt(val, 10); 2499 }) + 'px'; 2500 default: return proceed(element, style); 2501 } 2502 } 2503 ); 2504 2505 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( 2506 function(proceed, element, attribute) { 2507 if (attribute === 'title') return element.title; 2508 return proceed(element, attribute); 2509 } 2510 ); 2511} 2512 2513else if (Prototype.Browser.IE) { 2514 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( 2515 function(proceed, element) { 2516 element = $(element);
2517 try { element.offsetParent } 2518 catch(e) { return $(document.body) } 2519 var position = element.getStyle('position'); 2520 if (position !== 'static') return proceed(element); 2521 element.setStyle({ position: 'relative' }); 2522 var value = proceed(element); 2523 element.setStyle({ position: position }); 2524 return value; 2525 } 2526 ); 2527 2528 $w('positionedOffset viewportOffset').each(function(method) { 2529 Element.Methods[method] = Element.Methods[method].wrap( 2530 function(proceed, element) { 2531 element = $(element); 2532 try { element.offsetParent } 2533 catch(e) { return Element._returnOffset(0,0) } 2534 var position = element.getStyle('position'); 2535 if (position !== 'static') return proceed(element); 2536 var offsetParent = element.getOffsetParent(); 2537 if (offsetParent && offsetParent.getStyle('position') === 'fixed') 2538 offsetParent.setStyle({ zoom: 1 }); 2539 element.setStyle({ position: 'relative' }); 2540 var value = proceed(element); 2541 element.setStyle({ position: position }); 2542 return value; 2543 } 2544 ); 2545 }); 2546 2547 Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( 2548 function(proceed, element) { 2549 try { element.offsetParent } 2550 catch(e) { return Element._returnOffset(0,0) } 2551 return proceed(element); 2552 } 2553 ); 2554 2555 Element.Methods.getStyle = function(element, style) { 2556 element = $(element); 2557 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); 2558 var value = element.style[style]; 2559 if (!value && element.currentStyle) value = element.currentStyle[style]; 2560 2561 if (style == 'opacity') { 2562 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 2563 if (value[1]) return parseFloat(value[1]) / 100; 2564 return 1.0; 2565 } 2566 2567 if (value == 'auto') { 2568 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 2569 return element['offset' + style.capitalize()] + 'px'; 2570 return null; 2571 } 2572 return value; 2573 }; 2574 2575 Element.Methods.setOpacity = function(element, value) { 2576 function stripAlpha(filter){ 2577 return filter.replace(/alpha\([^\)]*\)/gi,''); 2578 } 2579 element = $(element); 2580 var currentStyle = element.currentStyle; 2581 if ((currentStyle && !currentStyle.hasLayout) || 2582 (!currentStyle && element.style.zoom == 'normal')) 2583 element.style.zoom = 1; 2584 2585 var filter = element.getStyle('filter'), style = element.style; 2586 if (value == 1 || value === '') { 2587 (filter = stripAlpha(filter)) ? 2588 style.filter = filter : style.removeAttribute('filter'); 2589 return element; 2590 } else if (value < 0.00001) value = 0; 2591 style.filter = stripAlpha(filter) + 2592 'alpha(opacity=' + (value * 100) + ')'; 2593 return element; 2594 }; 2595 2596 Element._attributeTranslations = (function(){ 2597 2598 var classProp = 'className'; 2599 var forProp = 'for'; 2600 2601 var el = document.createElement('div'); 2602 2603 el.setAttribute(classProp, 'x'); 2604 2605 if (el.className !== 'x') { 2606 el.setAttribute('class', 'x'); 2607 if (el.className === 'x') { 2608 classProp = 'class'; 2609 } 2610 } 2611 el = null; 2612 2613 el = document.createElement('label'); 2614 el.setAttribute(forProp, 'x'); 2615 if (el.htmlFor !== 'x') { 2616 el.setAttribute('htmlFor', 'x'); 2617 if (el.htmlFor === 'x') { 2618 forProp = 'htmlFor'; 2619 } 2620 } 2621 el = null; 2622 2623 return { 2624 read: { 2625 names: { 2626 'class': classProp, 2627 'className': classProp, 2628 'for': forProp, 2629 'htmlFor': forProp 2630 }, 2631 values: { 2632 _getAttr: function(element, attribute) { 2633 return element.getAttribute(attribute); 2634 }, 2635 _getAttr2: function(element, attribute) { 2636 return element.getAttribute(attribute, 2); 2637 }, 2638 _getAttrNode: function(element, attribute) { 2639 var node = element.getAttributeNode(attribute); 2640 return node ? node.value : ""; 2641 }, 2642 _getEv: (function(){ 2643 2644 var el = document.createElement('div'); 2645 el.onclick = Prototype.emptyFunction; 2646 var value = el.getAttribute('onclick'); 2647 var f; 2648 2649 if (String(value).indexOf('{') > -1) { 2650 f = function(element, attribute) { 2651 attribute = element.getAttribute(attribute); 2652 if (!attribute) return null; 2653 attribute = attribute.toString(); 2654 attribute = attribute.split('{')[1]; 2655 attribute = attribute.split('}')[0]; 2656 return attribute.strip(); 2657 }; 2658 } 2659 else if (value === '') { 2660 f = function(element, attribute) { 2661 attribute = element.getAttribute(attribute); 2662 if (!attribute) return null; 2663 return attribute.strip(); 2664 }; 2665 } 2666 el = null; 2667 return f; 2668 })(), 2669 _flag: function(element, attribute) { 2670 return $(element).hasAttribute(attribute) ? attribute : null; 2671 }, 2672 style: function(element) { 2673 return element.style.cssText.toLowerCase(); 2674 }, 2675 title: function(element) { 2676 return element.title; 2677 } 2678 } 2679 } 2680 } 2681 })(); 2682 2683 Element._attributeTranslations.write = { 2684 names: Object.extend({ 2685 cellpadding: 'cellPadding', 2686 cellspacing: 'cellSpacing' 2687 }, Element._attributeTranslations.read.names), 2688 values: { 2689 checked: function(element, value) { 2690 element.checked = !!value; 2691 }, 2692 2693 style: function(element, value) { 2694 element.style.cssText = value ? value : ''; 2695 } 2696 } 2697 }; 2698 2699 Element._attributeTranslations.has = {}; 2700 2701 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 2702 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { 2703 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 2704 Element._attributeTranslations.has[attr.toLowerCase()] = attr; 2705 }); 2706 2707 (function(v) { 2708 Object.extend(v, { 2709 href: v._getAttr2, 2710 src: v._getAttr2, 2711 type: v._getAttr, 2712 action: v._getAttrNode, 2713 disabled: v._flag, 2714 checked: v._flag, 2715 readonly: v._flag, 2716 multiple: v._flag, 2717 onload: v._getEv, 2718 onunload: v._getEv, 2719 onclick: v._getEv, 2720 ondblclick: v._getEv, 2721 onmousedown: v._getEv, 2722 onmouseup: v._getEv, 2723 onmouseover: v._getEv, 2724 onmousemove: v._getEv, 2725 onmouseout: v._getEv, 2726 onfocus: v._getEv, 2727 onblur: v._getEv, 2728 onkeypress: v._getEv, 2729 onkeydown: v._getEv, 2730 onkeyup: v._getEv, 2731 onsubmit: v._getEv,
2732 onreset: v._getEv, 2733 onselect: v._getEv, 2734 onchange: v._getEv 2735 }); 2736 })(Element._attributeTranslations.read.values); 2737 2738 if (Prototype.BrowserFeatures.ElementExtensions) { 2739 (function() { 2740 function _descendants(element) { 2741 var nodes = element.getElementsByTagName('*'), results = []; 2742 for (var i = 0, node; node = nodes[i]; i++) 2743 if (node.tagName !== "!") // Filter out comment nodes. 2744 results.push(node); 2745 return results; 2746 } 2747 2748 Element.Methods.down = function(element, expression, index) { 2749 element = $(element); 2750 if (arguments.length == 1) return element.firstDescendant(); 2751 return Object.isNumber(expression) ? _descendants(element)[expression] : 2752 Element.select(element, expression)[index || 0]; 2753 } 2754 })(); 2755 } 2756 2757} 2758 2759else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { 2760 Element.Methods.setOpacity = function(element, value) { 2761 element = $(element); 2762 element.style.opacity = (value == 1) ? 0.999999 : 2763 (value === '') ? '' : (value < 0.00001) ? 0 : value; 2764 return element; 2765 }; 2766} 2767 2768else if (Prototype.Browser.WebKit) { 2769 Element.Methods.setOpacity = function(element, value) { 2770 element = $(element); 2771 element.style.opacity = (value == 1 || value === '') ? '' : 2772 (value < 0.00001) ? 0 : value; 2773 2774 if (value == 1) 2775 if(element.tagName.toUpperCase() == 'IMG' && element.width) { 2776 element.width++; element.width--; 2777 } else try { 2778 var n = document.createTextNode(' '); 2779 element.appendChild(n); 2780 element.removeChild(n); 2781 } catch (e) { } 2782 2783 return element; 2784 }; 2785 2786 Element.Methods.cumulativeOffset = function(element) { 2787 var valueT = 0, valueL = 0; 2788 do { 2789 valueT += element.offsetTop || 0; 2790 valueL += element.offsetLeft || 0; 2791 if (element.offsetParent == document.body) 2792 if (Element.getStyle(element, 'position') == 'absolute') break; 2793 2794 element = element.offsetParent; 2795 } while (element); 2796 2797 return Element._returnOffset(valueL, valueT); 2798 }; 2799} 2800 2801if ('outerHTML' in document.documentElement) { 2802 Element.Methods.replace = function(element, content) { 2803 element = $(element); 2804 2805 if (content && content.toElement) content = content.toElement(); 2806 if (Object.isElement(content)) { 2807 element.parentNode.replaceChild(content, element); 2808 return element; 2809 } 2810 2811 content = Object.toHTML(content); 2812 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); 2813 2814 if (Element._insertionTranslations.tags[tagName]) { 2815 var nextSibling = element.next(); 2816 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 2817 parent.removeChild(element); 2818 if (nextSibling) 2819 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); 2820 else 2821 fragments.each(function(node) { parent.appendChild(node) }); 2822 } 2823 else element.outerHTML = content.stripScripts(); 2824 2825 content.evalScripts.bind(content).defer(); 2826 return element; 2827 }; 2828} 2829 2830Element._returnOffset = function(l, t) { 2831 var result = [l, t]; 2832 result.left = l; 2833 result.top = t; 2834 return result; 2835}; 2836 2837Element._getContentFromAnonymousElement = function(tagName, html) { 2838 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 2839 if (t) { 2840 div.innerHTML = t[0] + html + t[1]; 2841 t[2].times(function() { div = div.firstChild }); 2842 } else div.innerHTML = html; 2843 return $A(div.childNodes); 2844}; 2845 2846Element._insertionTranslations = { 2847 before: function(element, node) { 2848 element.parentNode.insertBefore(node, element); 2849 }, 2850 top: function(element, node) { 2851 element.insertBefore(node, element.firstChild); 2852 }, 2853 bottom: function(element, node) { 2854 element.appendChild(node); 2855 }, 2856 after: function(element, node) { 2857 element.parentNode.insertBefore(node, element.nextSibling); 2858 }, 2859 tags: { 2860 TABLE: ['<table>', '</table>', 1], 2861 TBODY: ['<table><tbody>', '</tbody></table>', 2], 2862 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], 2863 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 2864 SELECT: ['<select>', '</select>', 1] 2865 } 2866}; 2867 2868(function() { 2869 var tags = Element._insertionTranslations.tags; 2870 Object.extend(tags, { 2871 THEAD: tags.TBODY, 2872 TFOOT: tags.TBODY, 2873 TH: tags.TD 2874 }); 2875})(); 2876 2877Element.Methods.Simulated = { 2878 hasAttribute: function(element, attribute) { 2879 attribute = Element._attributeTranslations.has[attribute] || attribute; 2880 var node = $(element).getAttributeNode(attribute); 2881 return !!(node && node.specified); 2882 } 2883}; 2884 2885Element.Methods.ByTag = { }; 2886 2887Object.extend(Element, Element.Methods); 2888 2889(function(div) { 2890 2891 if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { 2892 window.HTMLElement = { }; 2893 window.HTMLElement.prototype = div['__proto__']; 2894 Prototype.BrowserFeatures.ElementExtensions = true; 2895 } 2896 2897 div = null; 2898 2899})(document.createElement('div')) 2900 2901Element.extend = (function() { 2902 2903 function checkDeficiency(tagName) { 2904 if (typeof window.Element != 'undefined') { 2905 var proto = window.Element.prototype; 2906 if (proto) { 2907 var id = '_' + (Math.random()+'').slice(2); 2908 var el = document.createElement(tagName); 2909 proto[id] = 'x'; 2910 var isBuggy = (el[id] !== 'x'); 2911 delete proto[id]; 2912 el = null; 2913 return isBuggy; 2914 } 2915 } 2916 return false;
2917 } 2918 2919 function extendElementWith(element, methods) { 2920 for (var property in methods) { 2921 var value = methods[property]; 2922 if (Object.isFunction(value) && !(property in element)) 2923 element[property] = value.methodize(); 2924 } 2925 } 2926 2927 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); 2928 2929 if (Prototype.BrowserFeatures.SpecificElementExtensions) { 2930 if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { 2931 return function(element) { 2932 if (element && typeof element._extendedByPrototype == 'undefined') { 2933 var t = element.tagName; 2934 if (t && (/^(?:object|applet|embed)$/i.test(t))) { 2935 extendElementWith(element, Element.Methods); 2936 extendElementWith(element, Element.Methods.Simulated); 2937 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); 2938 } 2939 } 2940 return element; 2941 } 2942 } 2943 return Prototype.K; 2944 } 2945 2946 var Methods = { }, ByTag = Element.Methods.ByTag; 2947 2948 var extend = Object.extend(function(element) { 2949 if (!element || typeof element._extendedByPrototype != 'undefined' || 2950 element.nodeType != 1 || element == window) return element; 2951 2952 var methods = Object.clone(Methods), 2953 tagName = element.tagName.toUpperCase(); 2954 2955 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 2956 2957 extendElementWith(element, methods); 2958 2959 element._extendedByPrototype = Prototype.emptyFunction; 2960 return element; 2961 2962 }, { 2963 refresh: function() { 2964 if (!Prototype.BrowserFeatures.ElementExtensions) { 2965 Object.extend(Methods, Element.Methods); 2966 Object.extend(Methods, Element.Methods.Simulated); 2967 } 2968 } 2969 }); 2970 2971 extend.refresh(); 2972 return extend; 2973})(); 2974 2975Element.hasAttribute = function(element, attribute) { 2976 if (element.hasAttribute) return element.hasAttribute(attribute); 2977 return Element.Methods.Simulated.hasAttribute(element, attribute); 2978}; 2979 2980Element.addMethods = function(methods) { 2981 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 2982 2983 if (!methods) { 2984 Object.extend(Form, Form.Methods); 2985 Object.extend(Form.Element, Form.Element.Methods); 2986 Object.extend(Element.Methods.ByTag, { 2987 "FORM": Object.clone(Form.Methods), 2988 "INPUT": Object.clone(Form.Element.Methods), 2989 "SELECT": Object.clone(Form.Element.Methods), 2990 "TEXTAREA": Object.clone(Form.Element.Methods) 2991 }); 2992 } 2993 2994 if (arguments.length == 2) { 2995 var tagName = methods; 2996 methods = arguments[1]; 2997 } 2998 2999 if (!tagName) Object.extend(Element.Methods, methods || { }); 3000 else { 3001 if (Object.isArray(tagName)) tagName.each(extend); 3002 else extend(tagName); 3003 } 3004 3005 function extend(tagName) { 3006 tagName = tagName.toUpperCase(); 3007 if (!Element.Methods.ByTag[tagName]) 3008 Element.Methods.ByTag[tagName] = { }; 3009 Object.extend(Element.Methods.ByTag[tagName], methods); 3010 } 3011 3012 function copy(methods, destination, onlyIfAbsent) { 3013 onlyIfAbsent = onlyIfAbsent || false; 3014 for (var property in methods) { 3015 var value = methods[property]; 3016 if (!Object.isFunction(value)) continue; 3017 if (!onlyIfAbsent || !(property in destination)) 3018 destination[property] = value.methodize(); 3019 } 3020 } 3021 3022 function findDOMClass(tagName) { 3023 var klass; 3024 var trans = { 3025 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", 3026 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 3027 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 3028 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", 3029 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": 3030 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": 3031 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 3032 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": 3033 "FrameSet", "IFRAME": "IFrame" 3034 }; 3035 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 3036 if (window[klass]) return window[klass]; 3037 klass = 'HTML' + tagName + 'Element'; 3038 if (window[klass]) return window[klass]; 3039 klass = 'HTML' + tagName.capitalize() + 'Element'; 3040 if (window[klass]) return window[klass]; 3041 3042 var element = document.createElement(tagName); 3043 var proto = element['__proto__'] || element.constructor.prototype; 3044 element = null; 3045 return proto; 3046 } 3047 3048 var elementPrototype = window.HTMLElement ? HTMLElement.prototype : 3049 Element.prototype; 3050 3051 if (F.ElementExtensions) { 3052 copy(Element.Methods, elementPrototype); 3053 copy(Element.Methods.Simulated, elementPrototype, true); 3054 } 3055 3056 if (F.SpecificElementExtensions) { 3057 for (var tag in Element.Methods.ByTag) { 3058 var klass = findDOMClass(tag); 3059 if (Object.isUndefined(klass)) continue; 3060 copy(T[tag], klass.prototype); 3061 } 3062 } 3063 3064 Object.extend(Element, Element.Methods); 3065 delete Element.ByTag; 3066 3067 if (Element.extend.refresh) Element.extend.refresh(); 3068 Element.cache = { }; 3069}; 3070 3071 3072document.viewport = { 3073 3074 getDimensions: function() { 3075 return { width: this.getWidth(), height: this.getHeight() }; 3076 }, 3077 3078 getScrollOffsets: function() { 3079 return Element._returnOffset( 3080 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 3081 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 3082 } 3083}; 3084 3085(function(viewport) { 3086 var B = Prototype.Browser, doc = document, element, property = {}; 3087 3088 function getRootElement() { 3089 if (B.WebKit && !doc.evaluate) 3090 return document; 3091 3092 if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) 3093 return document.body; 3094 3095 return document.documentElement; 3096 } 3097 3098 function define(D) { 3099 if (!element) element = getRootElement(); 3100 3101 property[D] = 'client' + D; 3102 3103 viewport['get' + D] = function() { return element[property[D]] }; 3104 return viewport['get' + D](); 3105 } 3106 3107 viewport.getWidth = define.curry('Width'); 3108 3109 viewport.getHeight = define.curry('Height'); 3110})(document.viewport); 3111 3112 3113Element.Storage = { 3114 UID: 1 3115}; 3116 3117Element.addMethods({
3118 getStorage: function(element) { 3119 if (!(element = $(element))) return; 3120 3121 var uid; 3122 if (element === window) { 3123 uid = 0; 3124 } else { 3125 if (typeof element._prototypeUID === "undefined") 3126 element._prototypeUID = [Element.Storage.UID++]; 3127 uid = element._prototypeUID[0]; 3128 } 3129 3130 if (!Element.Storage[uid]) 3131 Element.Storage[uid] = $H(); 3132 3133 return Element.Storage[uid]; 3134 }, 3135 3136 store: function(element, key, value) { 3137 if (!(element = $(element))) return; 3138 3139 if (arguments.length === 2) { 3140 Element.getStorage(element).update(key); 3141 } else { 3142 Element.getStorage(element).set(key, value); 3143 } 3144 3145 return element; 3146 }, 3147 3148 retrieve: function(element, key, defaultValue) { 3149 if (!(element = $(element))) return; 3150 var hash = Element.getStorage(element), value = hash.get(key); 3151 3152 if (Object.isUndefined(value)) { 3153 hash.set(key, defaultValue); 3154 value = defaultValue; 3155 } 3156 3157 return value; 3158 }, 3159 3160 clone: function(element, deep) { 3161 if (!(element = $(element))) return; 3162 var clone = element.cloneNode(deep); 3163 clone._prototypeUID = void 0; 3164 if (deep) { 3165 var descendants = Element.select(clone, '*'), 3166 i = descendants.length; 3167 while (i--) { 3168 descendants[i]._prototypeUID = void 0; 3169 } 3170 } 3171 return Element.extend(clone); 3172 } 3173}); 3174/* Portions of the Selector class are derived from Jack Slocum's DomQuery, 3175 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 3176 * license. Please see http://www.yui-ext.com/ for more information. */ 3177 3178var Selector = Class.create({ 3179 initialize: function(expression) { 3180 this.expression = expression.strip(); 3181 3182 if (this.shouldUseSelectorsAPI()) { 3183 this.mode = 'selectorsAPI'; 3184 } else if (this.shouldUseXPath()) { 3185 this.mode = 'xpath'; 3186 this.compileXPathMatcher(); 3187 } else { 3188 this.mode = "normal"; 3189 this.compileMatcher(); 3190 } 3191 3192 }, 3193 3194 shouldUseXPath: (function() { 3195 3196 var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ 3197 var isBuggy = false; 3198 if (document.evaluate && window.XPathResult) { 3199 var el = document.createElement('div'); 3200 el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>'; 3201 3202 var xpath = ".//*[local-name()='ul' or local-name()='UL']" + 3203 "//*[local-name()='li' or local-name()='LI']"; 3204 3205 var result = document.evaluate(xpath, el, null, 3206 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 3207 3208 isBuggy = (result.snapshotLength !== 2); 3209 el = null; 3210 } 3211 return isBuggy; 3212 })(); 3213 3214 return function() { 3215 if (!Prototype.BrowserFeatures.XPath) return false; 3216 3217 var e = this.expression; 3218 3219 if (Prototype.Browser.WebKit && 3220 (e.include("-of-type") || e.include(":empty"))) 3221 return false; 3222 3223 if ((/(\[[\w-]*?:|:checked)/).test(e)) 3224 return false; 3225 3226 if (IS_DESCENDANT_SELECTOR_BUGGY) return false; 3227 3228 return true; 3229 } 3230 3231 })(), 3232 3233 shouldUseSelectorsAPI: function() { 3234 if (!Prototype.BrowserFeatures.SelectorsAPI) return false; 3235 3236 if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; 3237 3238 if (!Selector._div) Selector._div = new Element('div'); 3239 3240 try { 3241 Selector._div.querySelector(this.expression); 3242 } catch(e) { 3243 return false; 3244 } 3245 3246 return true; 3247 }, 3248 3249 compileMatcher: function() { 3250 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 3251 c = Selector.criteria, le, p, m, len = ps.length, name; 3252 3253 if (Selector._cache[e]) { 3254 this.matcher = Selector._cache[e]; 3255 return; 3256 } 3257 3258 this.matcher = ["this.matcher = function(root) {", 3259 "var r = root, h = Selector.handlers, c = false, n;"]; 3260 3261 while (e && le != e && (/\S/).test(e)) { 3262 le = e; 3263 for (var i = 0; i<len; i++) { 3264 p = ps[i].re; 3265 name = ps[i].name; 3266 if (m = e.match(p)) { 3267 this.matcher.push(Object.isFunction(c[name]) ? c[name](m) : 3268 new Template(c[name]).evaluate(m)); 3269 e = e.replace(m[0], ''); 3270 break; 3271 } 3272 } 3273 } 3274
3275 this.matcher.push("return h.unique(n);\n}"); 3276 eval(this.matcher.join('\n')); 3277 Selector._cache[this.expression] = this.matcher; 3278 }, 3279 3280 compileXPathMatcher: function() { 3281 var e = this.expression, ps = Selector.patterns, 3282 x = Selector.xpath, le, m, len = ps.length, name; 3283 3284 if (Selector._cache[e]) { 3285 this.xpath = Selector._cache[e]; return; 3286 } 3287 3288 this.matcher = ['.//*']; 3289 while (e && le != e && (/\S/).test(e)) { 3290 le = e; 3291 for (var i = 0; i<len; i++) { 3292 name = ps[i].name; 3293 if (m = e.match(ps[i].re)) { 3294 this.matcher.push(Object.isFunction(x[name]) ? x[name](m) : 3295 new Template(x[name]).evaluate(m)); 3296 e = e.replace(m[0], ''); 3297 break; 3298 } 3299 } 3300 } 3301 3302 this.xpath = this.matcher.join(''); 3303 Selector._cache[this.expression] = this.xpath; 3304 }, 3305 3306 findElements: function(root) { 3307 root = root || document; 3308 var e = this.expression, results; 3309 3310 switch (this.mode) { 3311 case 'selectorsAPI': 3312 if (root !== document) { 3313 var oldId = root.id, id = $(root).identify(); 3314 id = id.replace(/([\.:])/g, "\\$1"); 3315 e = "#" + id + " " + e; 3316 } 3317 3318 results = $A(root.querySelectorAll(e)).map(Element.extend); 3319 root.id = oldId; 3320 3321 return results; 3322 case 'xpath': 3323 return document._getElementsByXPath(this.xpath, root); 3324 default: 3325 return this.matcher(root); 3326 } 3327 }, 3328 3329 match: function(element) { 3330 this.tokens = []; 3331 3332 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 3333 var le, p, m, len = ps.length, name; 3334 3335 while (e && le !== e && (/\S/).test(e)) { 3336 le = e; 3337 for (var i = 0; i<len; i++) { 3338 p = ps[i].re; 3339 name = ps[i].name; 3340 if (m = e.match(p)) { 3341 if (as[name]) { 3342 this.tokens.push([name, Object.clone(m)]); 3343 e = e.replace(m[0], ''); 3344 } else { 3345 return this.findElements(document).include(element); 3346 } 3347 } 3348 } 3349 } 3350 3351 var match = true, name, matches; 3352 for (var i = 0, token; token = this.tokens[i]; i++) { 3353 name = token[0], matches = token[1]; 3354 if (!Selector.assertions[name](element, matches)) { 3355 match = false; break; 3356 } 3357 } 3358 3359 return match; 3360 }, 3361 3362 toString: function() { 3363 return this.expression; 3364 }, 3365 3366 inspect: function() { 3367 return "#<Selector:" + this.expression.inspect() + ">"; 3368 } 3369}); 3370 3371if (Prototype.BrowserFeatures.SelectorsAPI && 3372 document.compatMode === 'BackCompat') { 3373 Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ 3374 var div = document.createElement('div'), 3375 span = document.createElement('span'); 3376 3377 div.id = "prototype_test_id"; 3378 span.className = 'Test'; 3379 div.appendChild(span); 3380 var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); 3381 div = span = null; 3382 return isIgnored; 3383 })(); 3384} 3385 3386Object.extend(Selector, { 3387 _cache: { }, 3388 3389 xpath: { 3390 descendant: "//*", 3391 child: "/*", 3392 adjacent: "/following-sibling::*[1]", 3393 laterSibling: '/following-sibling::*', 3394 tagName: function(m) { 3395 if (m[1] == '*') return ''; 3396 return "[local-name()='" + m[1].toLowerCase() + 3397 "' or local-name()='" + m[1].toUpperCase() + "']"; 3398 }, 3399 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 3400 id: "[@id='#{1}']", 3401 attrPresence: function(m) { 3402 m[1] = m[1].toLowerCase(); 3403 return new Template("[@#{1}]").evaluate(m); 3404 }, 3405 attr: function(m) { 3406 m[1] = m[1].toLowerCase(); 3407 m[3] = m[5] || m[6]; 3408 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); 3409 }, 3410 pseudo: function(m) { 3411 var h = Selector.xpath.pseudos[m[1]]; 3412 if (!h) return ''; 3413 if (Object.isFunction(h)) return h(m); 3414 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); 3415 }, 3416 operators: { 3417 '=': "[@#{1}='#{3}']", 3418 '!=': "[@#{1}!='#{3}']", 3419 '^=': "[starts-with(@#{1}, '#{3}')]", 3420 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", 3421 '*=': "[contains(@#{1}, '#{3}')]", 3422 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", 3423 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" 3424 }, 3425 pseudos: { 3426 'first-child': '[not(preceding-sibling::*)]', 3427 'last-child': '[not(following-sibling::*)]', 3428 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 3429 'empty': "[count(*) = 0 and (count(text()) = 0)]", 3430 'checked': "[@checked]", 3431 'disabled': "[(@disabled) and (@type!='hidden')]", 3432 'enabled': "[not(@disabled) and (@type!='hidden')]", 3433 'not': function(m) { 3434 var e = m[6], p = Selector.patterns, 3435 x = Selector.xpath, le, v, len = p.length, name; 3436 3437 var exclusion = []; 3438 while (e && le != e && (/\S/).test(e)) { 3439 le = e; 3440 for (var i = 0; i<len; i++) { 3441 name = p[i].name 3442 if (m = e.match(p[i].re)) { 3443 v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m); 3444 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 3445 e = e.replace(m[0], ''); 3446 break; 3447 } 3448 } 3449 } 3450 return "[not(" + exclusion.join(" and ") + ")]"; 3451 }, 3452 'nth-child': function(m) { 3453 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); 3454 }, 3455 'nth-last-child': function(m) { 3456 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); 3457 }, 3458 'nth-of-type': function(m) { 3459 return Selector.xpath.pseudos.nth("position() ", m); 3460 }, 3461 'nth-last-of-type': function(m) { 3462 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); 3463 }, 3464 'first-of-type': function(m) { 3465 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); 3466 }, 3467 'last-of-type': function(m) { 3468 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); 3469 }, 3470 'only-of-type': function(m) { 3471 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); 3472 }, 3473 nth: function(fragment, m) { 3474 var mm, formula = m[6], predicate; 3475 if (formula == 'even') formula = '2n+0'; 3476 if (formula == 'odd') formula = '2n+1'; 3477 if (mm = formula.match(/^(\d+)$/)) // digit only 3478 return '[' + fragment + "= " + mm[1] + ']'; 3479 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 3480 if (mm[1] == "-") mm[1] = -1; 3481 var a = mm[1] ? Number(mm[1]) : 1; 3482 var b = mm[2] ? Number(mm[2]) : 0; 3483 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + 3484 "((#{fragment} - #{b}) div #{a} >= 0)]"; 3485 return new Template(predicate).evaluate({ 3486 fragment: fragment, a: a, b: b }); 3487 } 3488 } 3489 } 3490 }, 3491 3492 criteria: { 3493 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', 3494 className: 'n = h.className(n, r, "#{1}", c); c = false;', 3495 id: 'n = h.id(n, r, "#{1}", c); c = false;', 3496 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', 3497 attr: function(m) { 3498 m[3] = (m[5] || m[6]); 3499 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); 3500 }, 3501 pseudo: function(m) { 3502 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 3503 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); 3504 }, 3505 descendant: 'c = "descendant";', 3506 child: 'c = "child";', 3507 adjacent: 'c = "adjacent";', 3508 laterSibling: 'c = "laterSibling";' 3509 }, 3510 3511 patterns: [ 3512 { name: 'laterSibling', re: /^\s*~\s*/ }, 3513 { name: 'child', re: /^\s*>\s*/ }, 3514 { name: 'adjacent', re: /^\s*\+\s*/ }, 3515 { name: 'descendant', re: /^\s/ }, 3516 3517 { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, 3518 { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, 3519 { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, 3520 { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, 3521 { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, 3522 { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } 3523 ], 3524 3525 assertions: { 3526 tagName: function(element, matches) { 3527 return matches[1].toUpperCase() == element.tagName.toUpperCase(); 3528 }, 3529 3530 className: function(element, matches) { 3531 return Element.hasClassName(element, matches[1]); 3532 }, 3533 3534 id: function(element, matches) {
3535 return element.id === matches[1]; 3536 }, 3537 3538 attrPresence: function(element, matches) { 3539 return Element.hasAttribute(element, matches[1]); 3540 }, 3541 3542 attr: function(element, matches) { 3543 var nodeValue = Element.readAttribute(element, matches[1]); 3544 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); 3545 } 3546 }, 3547 3548 handlers: { 3549 concat: function(a, b) { 3550 for (var i = 0, node; node = b[i]; i++) 3551 a.push(node); 3552 return a; 3553 }, 3554 3555 mark: function(nodes) { 3556 var _true = Prototype.emptyFunction; 3557 for (var i = 0, node; node = nodes[i]; i++) 3558 node._countedByPrototype = _true; 3559 return nodes; 3560 }, 3561 3562 unmark: (function(){ 3563 3564 var PROPERTIES_ATTRIBUTES_MAP = (function(){ 3565 var el = document.createElement('div'), 3566 isBuggy = false, 3567 propName = '_countedByPrototype', 3568 value = 'x' 3569 el[propName] = value; 3570 isBuggy = (el.getAttribute(propName) === value); 3571 el = null; 3572 return isBuggy; 3573 })(); 3574 3575 return PROPERTIES_ATTRIBUTES_MAP ? 3576 function(nodes) { 3577 for (var i = 0, node; node = nodes[i]; i++) 3578 node.removeAttribute('_countedByPrototype'); 3579 return nodes; 3580 } : 3581 function(nodes) { 3582 for (var i = 0, node; node = nodes[i]; i++) 3583 node._countedByPrototype = void 0; 3584 return nodes; 3585 } 3586 })(), 3587 3588 index: function(parentNode, reverse, ofType) { 3589 parentNode._countedByPrototype = Prototype.emptyFunction; 3590 if (reverse) { 3591 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 3592 var node = nodes[i]; 3593 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 3594 } 3595 } else { 3596 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 3597 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 3598 } 3599 }, 3600 3601 unique: function(nodes) { 3602 if (nodes.length == 0) return nodes; 3603 var results = [], n; 3604 for (var i = 0, l = nodes.length; i < l; i++) 3605 if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { 3606 n._countedByPrototype = Prototype.emptyFunction; 3607 results.push(Element.extend(n)); 3608 } 3609 return Selector.handlers.unmark(results); 3610 }, 3611 3612 descendant: function(nodes) { 3613 var h = Selector.handlers; 3614 for (var i = 0, results = [], node; node = nodes[i]; i++) 3615 h.concat(results, node.getElementsByTagName('*')); 3616 return results; 3617 }, 3618 3619 child: function(nodes) { 3620 var h = Selector.handlers; 3621 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3622 for (var j = 0, child; child = node.childNodes[j]; j++) 3623 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 3624 } 3625 return results; 3626 }, 3627 3628 adjacent: function(nodes) { 3629 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3630 var next = this.nextElementSibling(node); 3631 if (next) results.push(next); 3632 } 3633 return results; 3634 }, 3635 3636 laterSibling: function(nodes) { 3637 var h = Selector.handlers; 3638 for (var i = 0, results = [], node; node = nodes[i]; i++) 3639 h.concat(results, Element.nextSiblings(node)); 3640 return results; 3641 }, 3642 3643 nextElementSibling: function(node) { 3644 while (node = node.nextSibling) 3645 if (node.nodeType == 1) return node; 3646 return null; 3647 }, 3648 3649 previousElementSibling: function(node) { 3650 while (node = node.previousSibling) 3651 if (node.nodeType == 1) return node; 3652 return null; 3653 }, 3654 3655 tagName: function(nodes, root, tagName, combinator) { 3656 var uTagName = tagName.toUpperCase(); 3657 var results = [], h = Selector.handlers; 3658 if (nodes) { 3659 if (combinator) { 3660 if (combinator == "descendant") { 3661 for (var i = 0, node; node = nodes[i]; i++) 3662 h.concat(results, node.getElementsByTagName(tagName)); 3663 return results; 3664 } else nodes = this[combinator](nodes); 3665 if (tagName == "*") return nodes; 3666 } 3667 for (var i = 0, node; node = nodes[i]; i++) 3668 if (node.tagName.toUpperCase() === uTagName) results.push(node); 3669 return results; 3670 } else return root.getElementsByTagName(tagName); 3671 }, 3672 3673 id: function(nodes, root, id, combinator) { 3674 var targetNode = $(id), h = Selector.handlers; 3675 3676 if (root == document) { 3677 if (!targetNode) return [];
3678 if (!nodes) return [targetNode]; 3679 } else { 3680 if (!root.sourceIndex || root.sourceIndex < 1) { 3681 var nodes = root.getElementsByTagName('*'); 3682 for (var j = 0, node; node = nodes[j]; j++) { 3683 if (node.id === id) return [node]; 3684 } 3685 } 3686 } 3687 3688 if (nodes) { 3689 if (combinator) { 3690 if (combinator == 'child') { 3691 for (var i = 0, node; node = nodes[i]; i++) 3692 if (targetNode.parentNode == node) return [targetNode]; 3693 } else if (combinator == 'descendant') { 3694 for (var i = 0, node; node = nodes[i]; i++) 3695 if (Element.descendantOf(targetNode, node)) return [targetNode]; 3696 } else if (combinator == 'adjacent') { 3697 for (var i = 0, node; node = nodes[i]; i++) 3698 if (Selector.handlers.previousElementSibling(targetNode) == node) 3699 return [targetNode]; 3700 } else nodes = h[combinator](nodes); 3701 } 3702 for (var i = 0, node; node = nodes[i]; i++) 3703 if (node == targetNode) return [targetNode]; 3704 return []; 3705 } 3706 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; 3707 }, 3708 3709 className: function(nodes, root, className, combinator) { 3710 if (nodes && combinator) nodes = this[combinator](nodes); 3711 return Selector.handlers.byClassName(nodes, root, className); 3712 }, 3713 3714 byClassName: function(nodes, root, className) { 3715 if (!nodes) nodes = Selector.handlers.descendant([root]); 3716 var needle = ' ' + className + ' '; 3717 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { 3718 nodeClassName = node.className; 3719 if (nodeClassName.length == 0) continue; 3720 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) 3721 results.push(node); 3722 } 3723 return results; 3724 }, 3725 3726 attrPresence: function(nodes, root, attr, combinator) { 3727 if (!nodes) nodes = root.getElementsByTagName("*"); 3728 if (nodes && combinator) nodes = this[combinator](nodes); 3729 var results = []; 3730 for (var i = 0, node; node = nodes[i]; i++) 3731 if (Element.hasAttribute(node, attr)) results.push(node); 3732 return results; 3733 }, 3734 3735 attr: function(nodes, root, attr, value, operator, combinator) { 3736 if (!nodes) nodes = root.getElementsByTagName("*"); 3737 if (nodes && combinator) nodes = this[combinator](nodes); 3738 var handler = Selector.operators[operator], results = []; 3739 for (var i = 0, node; node = nodes[i]; i++) { 3740 var nodeValue = Element.readAttribute(node, attr); 3741 if (nodeValue === null) continue; 3742 if (handler(nodeValue, value)) results.push(node); 3743 } 3744 return results; 3745 }, 3746 3747 pseudo: function(nodes, name, value, root, combinator) { 3748 if (nodes && combinator) nodes = this[combinator](nodes); 3749 if (!nodes) nodes = root.getElementsByTagName("*"); 3750 return Selector.pseudos[name](nodes, value, root); 3751 } 3752 }, 3753 3754 pseudos: { 3755 'first-child': function(nodes, value, root) { 3756 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3757 if (Selector.handlers.previousElementSibling(node)) continue; 3758 results.push(node); 3759 } 3760 return results; 3761 }, 3762 'last-child': function(nodes, value, root) { 3763 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3764 if (Selector.handlers.nextElementSibling(node)) continue; 3765 results.push(node); 3766 } 3767 return results; 3768 }, 3769 'only-child': function(nodes, value, root) { 3770 var h = Selector.handlers; 3771 for (var i = 0, results = [], node; node = nodes[i]; i++) 3772 if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) 3773 results.push(node); 3774 return results; 3775 }, 3776 'nth-child': function(nodes, formula, root) { 3777 return Selector.pseudos.nth(nodes, formula, root); 3778 }, 3779 'nth-last-child': function(nodes, formula, root) { 3780 return Selector.pseudos.nth(nodes, formula, root, true); 3781 }, 3782 'nth-of-type': function(nodes, formula, root) { 3783 return Selector.pseudos.nth(nodes, formula, root, false, true); 3784 }, 3785 'nth-last-of-type': function(nodes, formula, root) { 3786 return Selector.pseudos.nth(nodes, formula, root, true, true); 3787 }, 3788 'first-of-type': function(nodes, formula, root) { 3789 return Selector.pseudos.nth(nodes, "1", root, false, true); 3790 }, 3791 'last-of-type': function(nodes, formula, root) { 3792 return Selector.pseudos.nth(nodes, "1", root, true, true); 3793 }, 3794 'only-of-type': function(nodes, formula, root) { 3795 var p = Selector.pseudos;
3796 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); 3797 }, 3798 3799 getIndices: function(a, b, total) { 3800 if (a == 0) return b > 0 ? [b] : []; 3801 return $R(1, total).inject([], function(memo, i) { 3802 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); 3803 return memo; 3804 }); 3805 }, 3806 3807 nth: function(nodes, formula, root, reverse, ofType) { 3808 if (nodes.length == 0) return []; 3809 if (formula == 'even') formula = '2n+0'; 3810 if (formula == 'odd') formula = '2n+1'; 3811 var h = Selector.handlers, results = [], indexed = [], m; 3812 h.mark(nodes); 3813 for (var i = 0, node; node = nodes[i]; i++) { 3814 if (!node.parentNode._countedByPrototype) { 3815 h.index(node.parentNode, reverse, ofType); 3816 indexed.push(node.parentNode); 3817 } 3818 } 3819 if (formula.match(/^\d+$/)) { // just a number 3820 formula = Number(formula); 3821 for (var i = 0, node; node = nodes[i]; i++) 3822 if (node.nodeIndex == formula) results.push(node); 3823 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 3824 if (m[1] == "-") m[1] = -1; 3825 var a = m[1] ? Number(m[1]) : 1; 3826 var b = m[2] ? Number(m[2]) : 0; 3827 var indices = Selector.pseudos.getIndices(a, b, nodes.length); 3828 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { 3829 for (var j = 0; j < l; j++) 3830 if (node.nodeIndex == indices[j]) results.push(node); 3831 } 3832 } 3833 h.unmark(nodes); 3834 h.unmark(indexed); 3835 return results; 3836 }, 3837 3838 'empty': function(nodes, value, root) { 3839 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3840 if (node.tagName == '!' || node.firstChild) continue; 3841 results.push(node); 3842 } 3843 return results; 3844 }, 3845 3846 'not': function(nodes, selector, root) { 3847 var h = Selector.handlers, selectorType, m; 3848 var exclusions = new Selector(selector).findElements(root); 3849 h.mark(exclusions); 3850 for (var i = 0, results = [], node; node = nodes[i]; i++) 3851 if (!node._countedByPrototype) results.push(node); 3852 h.unmark(exclusions); 3853 return results; 3854 }, 3855 3856 'enabled': function(nodes, value, root) { 3857 for (var i = 0, results = [], node; node = nodes[i]; i++) 3858 if (!node.disabled && (!node.type || node.type !== 'hidden')) 3859 results.push(node); 3860 return results; 3861 }, 3862 3863 'disabled': function(nodes, value, root) { 3864 for (var i = 0, results = [], node; node = nodes[i]; i++) 3865 if (node.disabled) results.push(node); 3866 return results; 3867 }, 3868 3869 'checked': function(nodes, value, root) { 3870 for (var i = 0, results = [], node; node = nodes[i]; i++) 3871 if (node.checked) results.push(node); 3872 return results; 3873 } 3874 }, 3875 3876 operators: { 3877 '=': function(nv, v) { return nv == v; }, 3878 '!=': function(nv, v) { return nv != v; }, 3879 '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, 3880 '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, 3881 '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, 3882 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 3883 '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + 3884 '-').include('-' + (v || "").toUpperCase() + '-'); } 3885 }, 3886 3887 split: function(expression) { 3888 var expressions = []; 3889 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 3890 expressions.push(m[1].strip()); 3891 }); 3892 return expressions; 3893 }, 3894 3895 matchElements: function(elements, expression) { 3896 var matches = $$(expression), h = Selector.handlers; 3897 h.mark(matches); 3898 for (var i = 0, results = [], element; element = elements[i]; i++) 3899 if (element._countedByPrototype) results.push(element); 3900 h.unmark(matches); 3901 return results; 3902 }, 3903 3904 findElement: function(elements, expression, index) { 3905 if (Object.isNumber(expression)) { 3906 index = expression; expression = false; 3907 } 3908 return Selector.matchElements(elements, expression || '*')[index || 0]; 3909 }, 3910 3911 findChildElements: function(element, expressions) { 3912 expressions = Selector.split(expressions.join(',')); 3913 var results = [], h = Selector.handlers; 3914 for (var i = 0, l = expressions.length, selector; i < l; i++) { 3915 selector = new Selector(expressions[i].strip()); 3916 h.concat(results, selector.findElements(element)); 3917 } 3918 return (l > 1) ? h.unique(results) : results; 3919 } 3920}); 3921 3922if (Prototype.Browser.IE) { 3923 Object.extend(Selector.handlers, { 3924 concat: function(a, b) { 3925 for (var i = 0, node; node = b[i]; i++) 3926 if (node.tagName !== "!") a.push(node); 3927 return a; 3928 } 3929 }); 3930} 3931 3932function $$() { 3933 return Selector.findChildElements(document, $A(arguments)); 3934} 3935 3936var Form = { 3937 reset: function(form) { 3938 form = $(form); 3939 form.reset(); 3940 return form; 3941 }, 3942
3943 serializeElements: function(elements, options) { 3944 if (typeof options != 'object') options = { hash: !!options }; 3945 else if (Object.isUndefined(options.hash)) options.hash = true; 3946 var key, value, submitted = false, submit = options.submit; 3947 3948 var data = elements.inject({ }, function(result, element) { 3949 if (!element.disabled && element.name) { 3950 key = element.name; value = $(element).getValue(); 3951 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && 3952 submit !== false && (!submit || key == submit) && (submitted = true)))) { 3953 if (key in result) { 3954 if (!Object.isArray(result[key])) result[key] = [result[key]]; 3955 result[key].push(value); 3956 } 3957 else result[key] = value; 3958 } 3959 } 3960 return result; 3961 }); 3962 3963 return options.hash ? data : Object.toQueryString(data); 3964 } 3965}; 3966 3967Form.Methods = { 3968 serialize: function(form, options) { 3969 return Form.serializeElements(Form.getElements(form), options); 3970 }, 3971 3972 getElements: function(form) { 3973 var elements = $(form).getElementsByTagName('*'), 3974 element, 3975 arr = [ ], 3976 serializers = Form.Element.Serializers; 3977 for (var i = 0; element = elements[i]; i++) { 3978 arr.push(element); 3979 } 3980 return arr.inject([], function(elements, child) { 3981 if (serializers[child.tagName.toLowerCase()]) 3982 elements.push(Element.extend(child)); 3983 return elements; 3984 }) 3985 }, 3986 3987 getInputs: function(form, typeName, name) { 3988 form = $(form); 3989 var inputs = form.getElementsByTagName('input'); 3990 3991 if (!typeName && !name) return $A(inputs).map(Element.extend); 3992 3993 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { 3994 var input = inputs[i]; 3995 if ((typeName && input.type != typeName) || (name && input.name != name)) 3996 continue; 3997 matchingInputs.push(Element.extend(input)); 3998 } 3999 4000 return matchingInputs; 4001 }, 4002 4003 disable: function(form) { 4004 form = $(form); 4005 Form.getElements(form).invoke('disable'); 4006 return form; 4007 }, 4008 4009 enable: function(form) { 4010 form = $(form); 4011 Form.getElements(form).invoke('enable'); 4012 return form; 4013 }, 4014 4015 findFirstElement: function(form) { 4016 var elements = $(form).getElements().findAll(function(element) { 4017 return 'hidden' != element.type && !element.disabled; 4018 }); 4019 var firstByIndex = elements.findAll(function(element) { 4020 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; 4021 }).sortBy(function(element) { return element.tabIndex }).first(); 4022 4023 return firstByIndex ? firstByIndex : elements.find(function(element) { 4024 return /^(?:input|select|textarea)$/i.test(element.tagName); 4025 }); 4026 }, 4027 4028 focusFirstElement: function(form) { 4029 form = $(form); 4030 form.findFirstElement().activate(); 4031 return form; 4032 }, 4033 4034 request: function(form, options) { 4035 form = $(form), options = Object.clone(options || { }); 4036 4037 var params = options.parameters, action = form.readAttribute('action') || ''; 4038 if (action.blank()) action = window.location.href; 4039 options.parameters = form.serialize(true); 4040 4041 if (params) { 4042 if (Object.isString(params)) params = params.toQueryParams(); 4043 Object.extend(options.parameters, params); 4044 } 4045 4046 if (form.hasAttribute('method') && !options.method) 4047 options.method = form.method; 4048 4049 return new Ajax.Request(action, options); 4050 } 4051}; 4052 4053/*--------------------------------------------------------------------------*/ 4054 4055 4056Form.Element = { 4057 focus: function(element) { 4058 $(element).focus(); 4059 return element; 4060 }, 4061 4062 select: function(element) { 4063 $(element).select(); 4064 return element; 4065 } 4066}; 4067 4068Form.Element.Methods = { 4069 4070 serialize: function(element) { 4071 element = $(element); 4072 if (!element.disabled && element.name) { 4073 var value = element.getValue(); 4074 if (value != undefined) { 4075 var pair = { }; 4076 pair[element.name] = value; 4077 return Object.toQueryString(pair); 4078 } 4079 } 4080 return ''; 4081 }, 4082 4083 getValue: function(element) { 4084 element = $(element); 4085 var method = element.tagName.toLowerCase(); 4086 return Form.Element.Serializers[method](element); 4087 }, 4088 4089 setValue: function(element, value) { 4090 element = $(element); 4091 var method = element.tagName.toLowerCase(); 4092 Form.Element.Serializers[method](element, value); 4093 return element; 4094 }, 4095 4096 clear: function(element) { 4097 $(element).value = ''; 4098 return element; 4099 }, 4100 4101 present: function(element) { 4102 return $(element).value != ''; 4103 }, 4104 4105 activate: function(element) { 4106 element = $(element); 4107 try { 4108 element.focus(); 4109 if (element.select && (element.tagName.toLowerCase() != 'input' || 4110 !(/^(?:button|reset|submit)$/i.test(element.type)))) 4111 element.select(); 4112 } catch (e) { } 4113 return element; 4114 }, 4115 4116 disable: function(element) { 4117 element = $(element); 4118 element.disabled = true; 4119 return element; 4120 }, 4121 4122 enable: function(element) { 4123 element = $(element); 4124 element.disabled = false;
4125 return element; 4126 } 4127}; 4128 4129/*--------------------------------------------------------------------------*/ 4130 4131var Field = Form.Element; 4132 4133var $F = Form.Element.Methods.getValue; 4134 4135/*--------------------------------------------------------------------------*/ 4136 4137Form.Element.Serializers = { 4138 input: function(element, value) { 4139 switch (element.type.toLowerCase()) { 4140 case 'checkbox': 4141 case 'radio': 4142 return Form.Element.Serializers.inputSelector(element, value); 4143 default: 4144 return Form.Element.Serializers.textarea(element, value); 4145 } 4146 }, 4147 4148 inputSelector: function(element, value) { 4149 if (Object.isUndefined(value)) return element.checked ? element.value : null; 4150 else element.checked = !!value; 4151 }, 4152 4153 textarea: function(element, value) { 4154 if (Object.isUndefined(value)) return element.value; 4155 else element.value = value; 4156 }, 4157 4158 select: function(element, value) { 4159 if (Object.isUndefined(value)) 4160 return this[element.type == 'select-one' ? 4161 'selectOne' : 'selectMany'](element); 4162 else { 4163 var opt, currentValue, single = !Object.isArray(value); 4164 for (var i = 0, length = element.length; i < length; i++) { 4165 opt = element.options[i]; 4166 currentValue = this.optionValue(opt); 4167 if (single) { 4168 if (currentValue == value) { 4169 opt.selected = true; 4170 return; 4171 } 4172 } 4173 else opt.selected = value.include(currentValue); 4174 } 4175 } 4176 }, 4177 4178 selectOne: function(element) { 4179 var index = element.selectedIndex; 4180 return index >= 0 ? this.optionValue(element.options[index]) : null; 4181 }, 4182 4183 selectMany: function(element) { 4184 var values, length = element.length; 4185 if (!length) return null; 4186 4187 for (var i = 0, values = []; i < length; i++) { 4188 var opt = element.options[i]; 4189 if (opt.selected) values.push(this.optionValue(opt)); 4190 } 4191 return values; 4192 }, 4193 4194 optionValue: function(opt) { 4195 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 4196 } 4197}; 4198 4199/*--------------------------------------------------------------------------*/ 4200 4201 4202Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 4203 initialize: function($super, element, frequency, callback) { 4204 $super(callback, frequency); 4205 this.element = $(element); 4206 this.lastValue = this.getValue(); 4207 }, 4208 4209 execute: function() { 4210 var value = this.getValue(); 4211 if (Object.isString(this.lastValue) && Object.isString(value) ? 4212 this.lastValue != value : String(this.lastValue) != String(value)) { 4213 this.callback(this.element, value); 4214 this.lastValue = value; 4215 } 4216 } 4217}); 4218 4219Form.Element.Observer = Class.create(Abstract.TimedObserver, { 4220 getValue: function() { 4221 return Form.Element.getValue(this.element); 4222 } 4223}); 4224 4225Form.Observer = Class.create(Abstract.TimedObserver, { 4226 getValue: function() { 4227 return Form.serialize(this.element); 4228 } 4229}); 4230 4231/*--------------------------------------------------------------------------*/ 4232 4233Abstract.EventObserver = Class.create({ 4234 initialize: function(element, callback) { 4235 this.element = $(element); 4236 this.callback = callback; 4237 4238 this.lastValue = this.getValue(); 4239 if (this.element.tagName.toLowerCase() == 'form') 4240 this.registerFormCallbacks(); 4241 else 4242 this.registerCallback(this.element); 4243 }, 4244 4245 onElementEvent: function() { 4246 var value = this.getValue(); 4247 if (this.lastValue != value) { 4248 this.callback(this.element, value); 4249 this.lastValue = value; 4250 } 4251 }, 4252 4253 registerFormCallbacks: function() { 4254 Form.getElements(this.element).each(this.registerCallback, this); 4255 }, 4256 4257 registerCallback: function(element) { 4258 if (element.type) { 4259 switch (element.type.toLowerCase()) { 4260 case 'checkbox': 4261 case 'radio': 4262 Event.observe(element, 'click', this.onElementEvent.bind(this)); 4263 break; 4264 default: 4265 Event.observe(element, 'change', this.onElementEvent.bind(this)); 4266 break; 4267 } 4268 } 4269 } 4270}); 4271 4272Form.Element.EventObserver = Class.create(Abstract.EventObserver, { 4273 getValue: function() { 4274 return Form.Element.getValue(this.element); 4275 } 4276}); 4277 4278Form.EventObserver = Class.create(Abstract.EventObserver, { 4279 getValue: function() { 4280 return Form.serialize(this.element); 4281 } 4282}); 4283(function() { 4284 4285 var Event = { 4286 KEY_BACKSPACE: 8, 4287 KEY_TAB: 9, 4288 KEY_RETURN: 13, 4289 KEY_ESC: 27, 4290 KEY_LEFT: 37, 4291 KEY_UP: 38, 4292 KEY_RIGHT: 39, 4293 KEY_DOWN: 40, 4294 KEY_DELETE: 46, 4295 KEY_HOME: 36, 4296 KEY_END: 35, 4297 KEY_PAGEUP: 33, 4298 KEY_PAGEDOWN: 34, 4299 KEY_INSERT: 45, 4300 4301 cache: {} 4302 }; 4303 4304 var docEl = document.documentElement; 4305 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl 4306 && 'onmouseleave' in docEl; 4307 4308 var _isButton; 4309 if (Prototype.Browser.IE) { 4310 var buttonMap = { 0: 1, 1: 4, 2: 2 }; 4311 _isButton = function(event, code) { 4312 return event.button === buttonMap[code]; 4313 }; 4314 } else if (Prototype.Browser.WebKit) { 4315 _isButton = function(event, code) { 4316 switch (code) { 4317 case 0: return event.which == 1 && !event.metaKey; 4318 case 1: return event.which == 1 && event.metaKey; 4319 default: return false;
4320 } 4321 }; 4322 } else { 4323 _isButton = function(event, code) { 4324 return event.which ? (event.which === code + 1) : (event.button === code); 4325 }; 4326 } 4327 4328 function isLeftClick(event) { return _isButton(event, 0) } 4329 4330 function isMiddleClick(event) { return _isButton(event, 1) } 4331 4332 function isRightClick(event) { return _isButton(event, 2) } 4333 4334 function element(event) { 4335 event = Event.extend(event); 4336 4337 var node = event.target, type = event.type, 4338 currentTarget = event.currentTarget; 4339 4340 if (currentTarget && currentTarget.tagName) { 4341 if (type === 'load' || type === 'error' || 4342 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' 4343 && currentTarget.type === 'radio')) 4344 node = currentTarget; 4345 } 4346 4347 if (node.nodeType == Node.TEXT_NODE) 4348 node = node.parentNode; 4349 4350 return Element.extend(node); 4351 } 4352 4353 function findElement(event, expression) { 4354 var element = Event.element(event); 4355 if (!expression) return element; 4356 var elements = [element].concat(element.ancestors()); 4357 return Selector.findElement(elements, expression, 0); 4358 } 4359 4360 function pointer(event) { 4361 return { x: pointerX(event), y: pointerY(event) }; 4362 } 4363 4364 function pointerX(event) { 4365 var docElement = document.documentElement, 4366 body = document.body || { scrollLeft: 0 }; 4367 4368 return event.pageX || (event.clientX + 4369 (docElement.scrollLeft || body.scrollLeft) - 4370 (docElement.clientLeft || 0)); 4371 } 4372 4373 function pointerY(event) { 4374 var docElement = document.documentElement, 4375 body = document.body || { scrollTop: 0 }; 4376 4377 return event.pageY || (event.clientY + 4378 (docElement.scrollTop || body.scrollTop) - 4379 (docElement.clientTop || 0)); 4380 } 4381 4382 4383 function stop(event) { 4384 Event.extend(event); 4385 event.preventDefault(); 4386 event.stopPropagation(); 4387 4388 event.stopped = true; 4389 } 4390 4391 Event.Methods = { 4392 isLeftClick: isLeftClick, 4393 isMiddleClick: isMiddleClick, 4394 isRightClick: isRightClick, 4395 4396 element: element, 4397 findElement: findElement, 4398 4399 pointer: pointer, 4400 pointerX: pointerX, 4401 pointerY: pointerY, 4402 4403 stop: stop 4404 }; 4405 4406 4407 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 4408 m[name] = Event.Methods[name].methodize(); 4409 return m; 4410 }); 4411 4412 if (Prototype.Browser.IE) { 4413 function _relatedTarget(event) { 4414 var element; 4415 switch (event.type) { 4416 case 'mouseover': element = event.fromElement; break; 4417 case 'mouseout': element = event.toElement; break; 4418 default: return null; 4419 } 4420 return Element.extend(element); 4421 } 4422 4423 Object.extend(methods, { 4424 stopPropagation: function() { this.cancelBubble = true }, 4425 preventDefault: function() { this.returnValue = false }, 4426 inspect: function() { return '[object Event]' } 4427 }); 4428 4429 Event.extend = function(event, element) { 4430 if (!event) return false; 4431 if (event._extendedByPrototype) return event; 4432 4433 event._extendedByPrototype = Prototype.emptyFunction; 4434 var pointer = Event.pointer(event); 4435 4436 Object.extend(event, { 4437 target: event.srcElement || element, 4438 relatedTarget: _relatedTarget(event), 4439 pageX: pointer.x, 4440 pageY: pointer.y 4441 }); 4442 4443 return Object.extend(event, methods); 4444 }; 4445 } else { 4446 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; 4447 Object.extend(Event.prototype, methods); 4448 Event.extend = Prototype.K; 4449 } 4450 4451 function _createResponder(element, eventName, handler) { 4452 var registry = Element.retrieve(element, 'prototype_event_registry'); 4453 4454 if (Object.isUndefined(registry)) { 4455 CACHE.push(element); 4456 registry = Element.retrieve(element, 'prototype_event_registry', $H()); 4457 } 4458 4459 var respondersForEvent = registry.get(eventName); 4460 if (Object.isUndefined(respondersForEvent)) { 4461 respondersForEvent = []; 4462 registry.set(eventName, respondersForEvent); 4463 } 4464 4465 if (respondersForEvent.pluck('handler').include(handler)) return false; 4466 4467 var responder; 4468 if (eventName.include(":")) { 4469 responder = function(event) { 4470 if (Object.isUndefined(event.eventName)) 4471 return false;
4472 4473 if (event.eventName !== eventName) 4474 return false; 4475 4476 Event.extend(event, element); 4477 handler.call(element, event); 4478 }; 4479 } else { 4480 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && 4481 (eventName === "mouseenter" || eventName === "mouseleave")) { 4482 if (eventName === "mouseenter" || eventName === "mouseleave") { 4483 responder = function(event) { 4484 Event.extend(event, element); 4485 4486 var parent = event.relatedTarget; 4487 while (parent && parent !== element) { 4488 try { parent = parent.parentNode; } 4489 catch(e) { parent = element; } 4490 } 4491 4492 if (parent === element) return; 4493 4494 handler.call(element, event); 4495 }; 4496 } 4497 } else { 4498 responder = function(event) { 4499 Event.extend(event, element); 4500 handler.call(element, event); 4501 }; 4502 } 4503 } 4504 4505 responder.handler = handler; 4506 respondersForEvent.push(responder); 4507 return responder; 4508 } 4509 4510 function _destroyCache() { 4511 for (var i = 0, length = CACHE.length; i < length; i++) { 4512 Event.stopObserving(CACHE[i]); 4513 CACHE[i] = null; 4514 } 4515 } 4516 4517 var CACHE = []; 4518 4519 if (Prototype.Browser.IE) 4520 window.attachEvent('onunload', _destroyCache); 4521 4522 if (Prototype.Browser.WebKit) 4523 window.addEventListener('unload', Prototype.emptyFunction, false); 4524 4525 4526 var _getDOMEventName = Prototype.K; 4527 4528 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { 4529 _getDOMEventName = function(eventName) { 4530 var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; 4531 return eventName in translations ? translations[eventName] : eventName; 4532 }; 4533 } 4534 4535 function observe(element, eventName, handler) { 4536 element = $(element); 4537 4538 var responder = _createResponder(element, eventName, handler); 4539 4540 if (!responder) return element; 4541 4542 if (eventName.include(':')) { 4543 if (element.addEventListener) 4544 element.addEventListener("dataavailable", responder, false); 4545 else { 4546 element.attachEvent("ondataavailable", responder); 4547 element.attachEvent("onfilterchange", responder); 4548 } 4549 } else { 4550 var actualEventName = _getDOMEventName(eventName); 4551 4552 if (element.addEventListener) 4553 element.addEventListener(actualEventName, responder, false); 4554 else 4555 element.attachEvent("on" + actualEventName, responder); 4556 } 4557 4558 return element; 4559 } 4560 4561 function stopObserving(element, eventName, handler) { 4562 element = $(element); 4563 4564 var registry = Element.retrieve(element, 'prototype_event_registry'); 4565 4566 if (Object.isUndefined(registry)) return element; 4567 4568 if (eventName && !handler) { 4569 var responders = registry.get(eventName); 4570 4571 if (Object.isUndefined(responders)) return element; 4572 4573 responders.each( function(r) { 4574 Element.stopObserving(element, eventName, r.handler); 4575 }); 4576 return element; 4577 } else if (!eventName) { 4578 registry.each( function(pair) { 4579 var eventName = pair.key, responders = pair.value; 4580 4581 responders.each( function(r) { 4582 Element.stopObserving(element, eventName, r.handler); 4583 }); 4584 }); 4585 return element; 4586 } 4587 4588 var responders = registry.get(eventName); 4589 4590 if (!responders) return; 4591 4592 var responder = responders.find( function(r) { return r.handler === handler; }); 4593 if (!responder) return element; 4594 4595 var actualEventName = _getDOMEventName(eventName); 4596 4597 if (eventName.include(':')) { 4598 if (element.removeEventListener) 4599 element.removeEventListener("dataavailable", responder, false); 4600 else { 4601 element.detachEvent("ondataavailable", responder); 4602 element.detachEvent("onfilterchange", responder); 4603 } 4604 } else { 4605 if (element.removeEventListener) 4606 element.removeEventListener(actualEventName, responder, false); 4607 else 4608 element.detachEvent('on' + actualEventName, responder); 4609 } 4610 4611 registry.set(eventName, responders.without(responder)); 4612 4613 return element; 4614 } 4615 4616 function fire(element, eventName, memo, bubble) { 4617 element = $(element); 4618 4619 if (Object.isUndefined(bubble)) 4620 bubble = true; 4621 4622 if (element == document && document.createEvent && !element.dispatchEvent) 4623 element = document.documentElement; 4624 4625 var event; 4626 if (document.createEvent) { 4627 event = document.createEvent('HTMLEvents'); 4628 event.initEvent('dataavailable', true, true); 4629 } else { 4630 event = document.createEventObject(); 4631 event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; 4632 } 4633 4634 event.eventName = eventName; 4635 event.memo = memo || { }; 4636 4637 if (document.createEvent) 4638 element.dispatchEvent(event); 4639 else 4640 element.fireEvent(event.eventType, event); 4641 4642 return Event.extend(event); 4643 } 4644 4645 4646 Object.extend(Event, Event.Methods); 4647 4648 Object.extend(Event, { 4649 fire: fire, 4650 observe: observe, 4651 stopObserving: stopObserving 4652 }); 4653 4654 Element.addMethods({ 4655 fire: fire, 4656 4657 observe: observe, 4658 4659 stopObserving: stopObserving 4660 }); 4661 4662 Object.extend(document, { 4663 fire: fire.methodize(), 4664 4665 observe: observe.methodize(), 4666 4667 stopObserving: stopObserving.methodize(), 4668 4669 loaded: false 4670 }); 4671 4672 if (window.Event) Object.extend(window.Event, Event); 4673 else window.Event = Event; 4674})(); 4675 4676(function() { 4677 /* Support for the DOMContentLoaded event is based on work by Dan Webb, 4678 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ 4679 4680 var timer; 4681 4682 function fireContentLoadedEvent() { 4683 if (document.loaded) return; 4684 if (timer) window.clearTimeout(timer); 4685 document.loaded = true; 4686 document.fire('dom:loaded'); 4687 } 4688 4689 function checkReadyState() { 4690 if (document.readyState === 'complete') { 4691 document.stopObserving('readystatechange', checkReadyState); 4692 fireContentLoadedEvent(); 4693 } 4694 } 4695 4696 function pollDoScroll() { 4697 try { document.documentElement.doScroll('left'); } 4698 catch(e) { 4699 timer = pollDoScroll.defer(); 4700 return; 4701 } 4702 fireContentLoadedEvent(); 4703 } 4704 4705 if (document.addEventListener) { 4706 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); 4707 } else { 4708 document.observe('readystatechange', checkReadyState); 4709 if (window == top) 4710 timer = pollDoScroll.defer(); 4711 } 4712 4713 Event.observe(window, 'load', fireContentLoadedEvent); 4714})(); 4715 4716Element.addMethods(); 4717 4718/*------------------------------- DEPRECATED -------------------------------*/ 4719 4720Hash.toQueryString = Object.toQueryString; 4721 4722var Toggle = { display: Element.toggle }; 4723 4724Element.Methods.childOf = Element.Methods.descendantOf; 4725 4726var Insertion = { 4727 Before: function(element, content) { 4728 return Element.insert(element, {before:content}); 4729 }, 4730 4731 Top: function(element, content) { 4732 return Element.insert(element, {top:content}); 4733 }, 4734 4735 Bottom: function(element, content) { 4736 return Element.insert(element, {bottom:content}); 4737 }, 4738 4739 After: function(element, content) { 4740 return Element.insert(element, {after:content}); 4741 } 4742}; 4743 4744var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 4745 4746var Position = { 4747 includeScrollOffsets: false, 4748 4749 prepare: function() { 4750 this.deltaX = window.pageXOffset 4751 || document.documentElement.scrollLeft 4752 || document.body.scrollLeft 4753 || 0; 4754 this.deltaY = window.pageYOffset 4755 || document.documentElement.scrollTop 4756 || document.body.scrollTop 4757 || 0; 4758 }, 4759 4760 within: function(element, x, y) { 4761 if (this.includeScrollOffsets) 4762 return this.withinIncludingScrolloffsets(element, x, y); 4763 this.xcomp = x; 4764 this.ycomp = y; 4765 this.offset = Element.cumulativeOffset(element); 4766 4767 return (y >= this.offset[1] && 4768 y < this.offset[1] + element.offsetHeight && 4769 x >= this.offset[0] && 4770 x < this.offset[0] + element.offsetWidth); 4771 }, 4772 4773 withinIncludingScrolloffsets: function(element, x, y) { 4774 var offsetcache = Element.cumulativeScrollOffset(element); 4775 4776 this.xcomp = x + offsetcache[0] - this.deltaX; 4777 this.ycomp = y + offsetcache[1] - this.deltaY; 4778 this.offset = Element.cumulativeOffset(element); 4779 4780 return (this.ycomp >= this.offset[1] && 4781 this.ycomp < this.offset[1] + element.offsetHeight && 4782 this.xcomp >= this.offset[0] && 4783 this.xcomp < this.offset[0] + element.offsetWidth); 4784 }, 4785 4786 overlap: function(mode, element) { 4787 if (!mode) return 0; 4788 if (mode == 'vertical') 4789 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 4790 element.offsetHeight; 4791 if (mode == 'horizontal') 4792 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 4793 element.offsetWidth; 4794 }, 4795 4796 4797 cumulativeOffset: Element.Methods.cumulativeOffset, 4798 4799 positionedOffset: Element.Methods.positionedOffset, 4800 4801 absolutize: function(element) { 4802 Position.prepare(); 4803 return Element.absolutize(element); 4804 }, 4805 4806 relativize: function(element) { 4807 Position.prepare(); 4808 return Element.relativize(element); 4809 }, 4810 4811 realOffset: Element.Methods.cumulativeScrollOffset, 4812 4813 offsetParent: Element.Methods.getOffsetParent, 4814 4815 page: Element.Methods.viewportOffset, 4816 4817 clone: function(source, target, options) { 4818 options = options || { }; 4819 return Element.clonePosition(target, source, options); 4820 } 4821}; 4822 4823/*--------------------------------------------------------------------------*/ 4824 4825if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ 4826 function iter(name) { 4827 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; 4828 } 4829 4830 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? 4831 function(element, className) {
4832 className = className.toString().strip(); 4833 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); 4834 return cond ? document._getElementsByXPath('.//*' + cond, element) : []; 4835 } : function(element, className) { 4836 className = className.toString().strip(); 4837 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); 4838 if (!classNames && !className) return elements; 4839 4840 var nodes = $(element).getElementsByTagName('*'); 4841 className = ' ' + className + ' '; 4842 4843 for (var i = 0, child, cn; child = nodes[i]; i++) { 4844 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || 4845 (classNames && classNames.all(function(name) { 4846 return !name.toString().blank() && cn.include(' ' + name + ' '); 4847 })))) 4848 elements.push(Element.extend(child)); 4849 } 4850 return elements; 4851 }; 4852 4853 return function(className, parentElement) { 4854 return $(parentElement || document.body).getElementsByClassName(className); 4855 }; 4856}(Element.Methods); 4857 4858/*--------------------------------------------------------------------------*/ 4859 4860Element.ClassNames = Class.create(); 4861Element.ClassNames.prototype = { 4862 initialize: function(element) { 4863 this.element = $(element); 4864 }, 4865 4866 _each: function(iterator) { 4867 this.element.className.split(/\s+/).select(function(name) { 4868 return name.length > 0; 4869 })._each(iterator); 4870 }, 4871 4872 set: function(className) { 4873 this.element.className = className; 4874 }, 4875 4876 add: function(classNameToAdd) { 4877 if (this.include(classNameToAdd)) return; 4878 this.set($A(this).concat(classNameToAdd).join(' ')); 4879 }, 4880 4881 remove: function(classNameToRemove) { 4882 if (!this.include(classNameToRemove)) return; 4883 this.set($A(this).without(classNameToRemove).join(' ')); 4884 }, 4885 4886 toString: function() { 4887 return $A(this).join(' '); 4888 } 4889}; 4890 4891Object.extend(Element.ClassNames.prototype, Enumerable); 4892 4893/*--------------------------------------------------------------------------*/
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.