1/* Prototype JavaScript framework, version 1.7.3 2 * (c) 2005-2010 Sam Stephenson 3 * 4 * Prototype is freely distributable under the terms of an MIT-style license. 5 * For details, see the Prototype web site: http://www.prototypejs.org/ 6 * 7 *--------------------------------------------------------------------------*/ 8 9var Prototype = { 10 11 Version: '1.7.3', 12 13 Browser: (function(){ 14 var ua = navigator.userAgent; 15 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; 16 return { 17 IE: !!window.attachEvent && !isOpera, 18 Opera: isOpera, 19 WebKit: ua.indexOf('AppleWebKit/') > -1, 20 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, 21 MobileSafari: /Apple.*Mobile/.test(ua) 22 } 23 })(), 24 25 BrowserFeatures: { 26 XPath: !!document.evaluate, 27 28 SelectorsAPI: !!document.querySelector, 29 30 ElementExtensions: (function() { 31 var constructor = window.Element || window.HTMLElement; 32 return !!(constructor && constructor.prototype); 33 })(), 34 SpecificElementExtensions: (function() { 35 if (typeof window.HTMLDivElement !== 'undefined') 36 return true; 37 38 var div = document.createElement('div'), 39 form = document.createElement('form'), 40 isSupported = false; 41 42 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { 43 isSupported = true; 44 } 45 46 div = form = null; 47 48 return isSupported; 49 })() 50 }, 51 52 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>', 53 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, 54 55 emptyFunction: function() { }, 56 57 K: function(x) { return x } 58}; 59 60if (Prototype.Browser.MobileSafari) 61 Prototype.BrowserFeatures.SpecificElementExtensions = false; 62/* Based on Alex Arnell's inheritance implementation. */ 63 64var Class = (function() { 65 66 var IS_DONTENUM_BUGGY = (function(){ 67 for (var p in { toString: 1 }) { 68 if (p === 'toString') return false; 69 } 70 return true; 71 })(); 72 73 function subclass() {}; 74 function create() { 75 var parent = null, properties = $A(arguments); 76 if (Object.isFunction(properties[0])) 77 parent = properties.shift(); 78 79 function klass() { 80 this.initialize.apply(this, arguments); 81 } 82 83 Object.extend(klass, Class.Methods); 84 klass.superclass = parent; 85 klass.subclasses = []; 86 87 if (parent) { 88 subclass.prototype = parent.prototype; 89 klass.prototype = new subclass; 90 parent.subclasses.push(klass); 91 } 92 93 for (var i = 0, length = properties.length; i < length; i++) 94 klass.addMethods(properties[i]); 95 96 if (!klass.prototype.initialize) 97 klass.prototype.initialize = Prototype.emptyFunction; 98 99 klass.prototype.constructor = klass; 100 return klass; 101 } 102 103 function addMethods(source) { 104 var ancestor = this.superclass && this.superclass.prototype, 105 properties = Object.keys(source); 106 107 if (IS_DONTENUM_BUGGY) { 108 if (source.toString != Object.prototype.toString) 109 properties.push("toString"); 110 if (source.valueOf != Object.prototype.valueOf) 111 properties.push("valueOf"); 112 } 113 114 for (var i = 0, length = properties.length; i < length; i++) { 115 var property = properties[i], value = source[property]; 116 if (ancestor && Object.isFunction(value) && 117 value.argumentNames()[0] == "$super") { 118 var method = value; 119 value = (function(m) { 120 return function() { return ancestor[m].apply(this, arguments); }; 121 })(property).wrap(method); 122 123 value.valueOf = (function(method) { 124 return function() { return method.valueOf.call(method); }; 125 })(method); 126 127 value.toString = (function(method) { 128 return function() { return method.toString.call(method); }; 129 })(method); 130 } 131 this.prototype[property] = value; 132 } 133 134 return this; 135 } 136 137 return { 138 create: create, 139 Methods: { 140 addMethods: addMethods 141 } 142 }; 143})(); 144(function() { 145 146 var _toString = Object.prototype.toString, 147 _hasOwnProperty = Object.prototype.hasOwnProperty, 148 NULL_TYPE = 'Null', 149 UNDEFINED_TYPE = 'Undefined', 150 BOOLEAN_TYPE = 'Boolean', 151 NUMBER_TYPE = 'Number', 152 STRING_TYPE = 'String', 153 OBJECT_TYPE = 'Object', 154 FUNCTION_CLASS = '[object Function]', 155 BOOLEAN_CLASS = '[object Boolean]', 156 NUMBER_CLASS = '[object Number]', 157 STRING_CLASS = '[object String]', 158 ARRAY_CLASS = '[object Array]', 159 DATE_CLASS = '[object Date]', 160 NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && 161 typeof JSON.stringify === 'function' && 162 JSON.stringify(0) === '0' && 163 typeof JSON.stringify(Prototype.K) === 'undefined'; 164 165 166
167 var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf', 168 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor']; 169 170 var IS_DONTENUM_BUGGY = (function(){ 171 for (var p in { toString: 1 }) { 172 if (p === 'toString') return false; 173 } 174 return true; 175 })(); 176 177 function Type(o) { 178 switch(o) { 179 case null: return NULL_TYPE; 180 case (void 0): return UNDEFINED_TYPE; 181 } 182 var type = typeof o; 183 switch(type) { 184 case 'boolean': return BOOLEAN_TYPE; 185 case 'number': return NUMBER_TYPE; 186 case 'string': return STRING_TYPE; 187 } 188 return OBJECT_TYPE; 189 } 190 191 function extend(destination, source) { 192 for (var property in source) 193 destination[property] = source[property]; 194 return destination; 195 } 196 197 function inspect(object) { 198 try { 199 if (isUndefined(object)) return 'undefined'; 200 if (object === null) return 'null'; 201 return object.inspect ? object.inspect() : String(object); 202 } catch (e) { 203 if (e instanceof RangeError) return '...'; 204 throw e; 205 } 206 } 207 208 function toJSON(value) { 209 return Str('', { '': value }, []); 210 } 211 212 function Str(key, holder, stack) { 213 var value = holder[key]; 214 if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') { 215 value = value.toJSON(key); 216 } 217 218 var _class = _toString.call(value); 219 220 switch (_class) { 221 case NUMBER_CLASS: 222 case BOOLEAN_CLASS: 223 case STRING_CLASS: 224 value = value.valueOf(); 225 } 226 227 switch (value) { 228 case null: return 'null'; 229 case true: return 'true'; 230 case false: return 'false'; 231 } 232 233 var type = typeof value; 234 switch (type) { 235 case 'string': 236 return value.inspect(true); 237 case 'number': 238 return isFinite(value) ? String(value) : 'null'; 239 case 'object': 240 241 for (var i = 0, length = stack.length; i < length; i++) { 242 if (stack[i] === value) { 243 throw new TypeError("Cyclic reference to '" + value + "' in object"); 244 } 245 } 246 stack.push(value); 247 248 var partial = []; 249 if (_class === ARRAY_CLASS) { 250 for (var i = 0, length = value.length; i < length; i++) { 251 var str = Str(i, value, stack); 252 partial.push(typeof str === 'undefined' ? 'null' : str); 253 } 254 partial = '[' + partial.join(',') + ']'; 255 } else { 256 var keys = Object.keys(value); 257 for (var i = 0, length = keys.length; i < length; i++) { 258 var key = keys[i], str = Str(key, value, stack); 259 if (typeof str !== "undefined") { 260 partial.push(key.inspect(true)+ ':' + str); 261 } 262 } 263 partial = '{' + partial.join(',') + '}'; 264 } 265 stack.pop(); 266 return partial; 267 } 268 } 269 270 function stringify(object) { 271 return JSON.stringify(object); 272 } 273 274 function toQueryString(object) { 275 return $H(object).toQueryString(); 276 } 277 278 function toHTML(object) { 279 return object && object.toHTML ? object.toHTML() : String.interpret(object); 280 } 281 282 function keys(object) { 283 if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); } 284 var results = []; 285 for (var property in object) { 286 if (_hasOwnProperty.call(object, property)) 287 results.push(property); 288 } 289 290 if (IS_DONTENUM_BUGGY) { 291 for (var i = 0; property = DONT_ENUMS[i]; i++) { 292 if (_hasOwnProperty.call(object, property)) 293 results.push(property); 294 } 295 } 296 297 return results; 298 } 299 300 function values(object) { 301 var results = []; 302 for (var property in object) 303 results.push(object[property]); 304 return results; 305 } 306 307 function clone(object) { 308 return extend({ }, object); 309 } 310 311 function isElement(object) { 312 return !!(object && object.nodeType == 1); 313 } 314 315 function isArray(object) { 316 return _toString.call(object) === ARRAY_CLASS; 317 } 318 319 var hasNativeIsArray = (typeof Array.isArray == 'function') 320 && Array.isArray([]) && !Array.isArray({}); 321 322 if (hasNativeIsArray) { 323 isArray = Array.isArray; 324 } 325 326 function isHash(object) { 327 return object instanceof Hash; 328 } 329 330 function isFunction(object) { 331 return _toString.call(object) === FUNCTION_CLASS; 332 } 333 334 function isString(object) { 335 return _toString.call(object) === STRING_CLASS; 336 } 337 338 function isNumber(object) { 339 return _toString.call(object) === NUMBER_CLASS; 340 } 341 342 function isDate(object) { 343 return _toString.call(object) === DATE_CLASS; 344 } 345 346 function isUndefined(object) { 347 return typeof object === "undefined"; 348 } 349 350 extend(Object, { 351 extend: extend, 352 inspect: inspect, 353 toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON, 354 toQueryString: toQueryString, 355 toHTML: toHTML, 356 keys: Object.keys || keys, 357 values: values, 358 clone: clone, 359 isElement: isElement, 360 isArray: isArray, 361 isHash: isHash, 362 isFunction: isFunction, 363 isString: isString, 364 isNumber: isNumber, 365 isDate: isDate, 366 isUndefined: isUndefined 367 }); 368})(); 369Object.extend(Function.prototype, (function() { 370 var slice = Array.prototype.slice; 371 372 function update(array, args) { 373 var arrayLength = array.length, length = args.length; 374 while (length--) array[arrayLength + length] = args[length]; 375 return array; 376 } 377 378 function merge(array, args) { 379 array = slice.call(array, 0); 380 return update(array, args); 381 } 382 383 function argumentNames() {
384 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] 385 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') 386 .replace(/\s+/g, '').split(','); 387 return names.length == 1 && !names[0] ? [] : names; 388 } 389 390 391 function bind(context) { 392 if (arguments.length < 2 && Object.isUndefined(arguments[0])) 393 return this; 394 395 if (!Object.isFunction(this)) 396 throw new TypeError("The object is not callable."); 397 398 var nop = function() {}; 399 var __method = this, args = slice.call(arguments, 1); 400 401 var bound = function() { 402 var a = merge(args, arguments); 403 var c = this instanceof bound ? this : context; 404 return __method.apply(c, a); 405 }; 406 407 nop.prototype = this.prototype; 408 bound.prototype = new nop(); 409 410 return bound; 411 } 412 413 function bindAsEventListener(context) { 414 var __method = this, args = slice.call(arguments, 1); 415 return function(event) { 416 var a = update([event || window.event], args); 417 return __method.apply(context, a); 418 } 419 } 420 421 function curry() { 422 if (!arguments.length) return this; 423 var __method = this, args = slice.call(arguments, 0); 424 return function() { 425 var a = merge(args, arguments); 426 return __method.apply(this, a); 427 } 428 } 429 430 function delay(timeout) { 431 var __method = this, args = slice.call(arguments, 1); 432 timeout = timeout * 1000; 433 return window.setTimeout(function() { 434 return __method.apply(__method, args); 435 }, timeout); 436 } 437 438 function defer() { 439 var args = update([0.01], arguments); 440 return this.delay.apply(this, args); 441 } 442 443 function wrap(wrapper) { 444 var __method = this; 445 return function() { 446 var a = update([__method.bind(this)], arguments); 447 return wrapper.apply(this, a); 448 } 449 } 450 451 function methodize() { 452 if (this._methodized) return this._methodized; 453 var __method = this; 454 return this._methodized = function() { 455 var a = update([this], arguments); 456 return __method.apply(null, a); 457 }; 458 } 459 460 var extensions = { 461 argumentNames: argumentNames, 462 bindAsEventListener: bindAsEventListener, 463 curry: curry, 464 delay: delay, 465 defer: defer, 466 wrap: wrap, 467 methodize: methodize 468 }; 469 470 if (!Function.prototype.bind) 471 extensions.bind = bind; 472 473 return extensions; 474})()); 475 476 477 478(function(proto) { 479 480 481 function toISOString() { 482 return this.getUTCFullYear() + '-' + 483 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 484 this.getUTCDate().toPaddedString(2) + 'T' + 485 this.getUTCHours().toPaddedString(2) + ':' + 486 this.getUTCMinutes().toPaddedString(2) + ':' + 487 this.getUTCSeconds().toPaddedString(2) + 'Z'; 488 } 489 490 491 function toJSON() { 492 return this.toISOString(); 493 } 494 495 if (!proto.toISOString) proto.toISOString = toISOString; 496 if (!proto.toJSON) proto.toJSON = toJSON; 497 498})(Date.prototype); 499 500 501RegExp.prototype.match = RegExp.prototype.test; 502 503RegExp.escape = function(str) { 504 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 505}; 506var PeriodicalExecuter = Class.create({ 507 initialize: function(callback, frequency) { 508 this.callback = callback; 509 this.frequency = frequency; 510 this.currentlyExecuting = false; 511 512 this.registerCallback(); 513 }, 514 515 registerCallback: function() { 516 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 517 }, 518 519 execute: function() { 520 this.callback(this); 521 }, 522 523 stop: function() { 524 if (!this.timer) return; 525 clearInterval(this.timer); 526 this.timer = null; 527 }, 528 529 onTimerEvent: function() { 530 if (!this.currentlyExecuting) { 531 try { 532 this.currentlyExecuting = true; 533 this.execute(); 534 this.currentlyExecuting = false; 535 } catch(e) { 536 this.currentlyExecuting = false; 537 throw e; 538 } 539 } 540 } 541}); 542Object.extend(String, { 543 interpret: function(value) { 544 return value == null ? '' : String(value); 545 }, 546 specialChar: { 547 '\b': '\\b', 548 '\t': '\\t', 549 '\n': '\\n', 550 '\f': '\\f', 551 '\r': '\\r', 552 '\\': '\\\\' 553 } 554}); 555 556Object.extend(String.prototype, (function() { 557 var NATIVE_JSON_PARSE_SUPPORT = window.JSON && 558 typeof JSON.parse === 'function' && 559 JSON.parse('{"test": true}').test; 560 561 function prepareReplacement(replacement) { 562 if (Object.isFunction(replacement)) return replacement; 563 var template = new Template(replacement); 564 return function(match) { return template.evaluate(match) }; 565 } 566 567 function isNonEmptyRegExp(regexp) { 568 return regexp.source && regexp.source !== '(?:)'; 569 } 570 571 572 function gsub(pattern, replacement) { 573 var result = '', source = this, match; 574 replacement = prepareReplacement(replacement); 575 576 if (Object.isString(pattern)) 577 pattern = RegExp.escape(pattern); 578 579 if (!(pattern.length || isNonEmptyRegExp(pattern))) { 580 replacement = replacement(''); 581 return replacement + source.split('').join(replacement) + replacement; 582 } 583 584 while (source.length > 0) { 585 match = source.match(pattern) 586 if (match && match[0].length > 0) { 587 result += source.slice(0, match.index); 588 result += String.interpret(replacement(match)); 589 source = source.slice(match.index + match[0].length); 590 } else { 591 result += source, source = ''; 592 } 593 } 594 return result; 595 } 596 597 function sub(pattern, replacement, count) { 598 replacement = prepareReplacement(replacement); 599 count = Object.isUndefined(count) ? 1 : count; 600 601 return this.gsub(pattern, function(match) { 602 if (--count < 0) return match[0]; 603 return replacement(match); 604 }); 605 } 606 607 function scan(pattern, iterator) { 608 this.gsub(pattern, iterator); 609 return String(this); 610 } 611 612 function truncate(length, truncation) { 613 length = length || 30; 614 truncation = Object.isUndefined(truncation) ? '...' : truncation; 615 return this.length > length ? 616 this.slice(0, length - truncation.length) + truncation : String(this); 617 } 618 619 function strip() { 620 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 621 } 622 623 function stripTags() { 624 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, ''); 625 } 626 627 function stripScripts() { 628 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 629 } 630 631 function extractScripts() { 632 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'), 633 matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 634 return (this.match(matchAll) || []).map(function(scriptTag) { 635 return (scriptTag.match(matchOne) || ['', ''])[1]; 636 }); 637 } 638 639 function evalScripts() { 640 return this.extractScripts().map(function(script) { return eval(script); }); 641 } 642 643 function escapeHTML() { 644 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 645 } 646 647 function unescapeHTML() { 648 return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); 649 } 650 651 652 function toQueryParams(separator) { 653 var match = this.strip().match(/([^?#]*)(#.*)?$/); 654 if (!match) return { }; 655 656 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 657 if ((pair = pair.split('='))[0]) { 658 var key = decodeURIComponent(pair.shift()), 659 value = pair.length > 1 ? pair.join('=') : pair[0]; 660 661 if (value != undefined) { 662 value = value.gsub('+', ' '); 663 value = decodeURIComponent(value); 664 } 665 666 if (key in hash) { 667 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 668 hash[key].push(value); 669 } 670 else hash[key] = value; 671 } 672 return hash; 673 }); 674 } 675 676 function toArray() { 677 return this.split(''); 678 } 679 680 function succ() { 681 return this.slice(0, this.length - 1) + 682 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 683 } 684 685 function times(count) { 686 return count < 1 ? '' : new Array(count + 1).join(this); 687 } 688 689 function camelize() { 690 return this.replace(/-+(.)?/g, function(match, chr) { 691 return chr ? chr.toUpperCase() : ''; 692 }); 693 } 694 695 function capitalize() { 696 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 697 } 698 699 function underscore() { 700 return this.replace(/::/g, '/') 701 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 702 .replace(/([a-z\d])([A-Z])/g, '$1_$2') 703 .replace(/-/g, '_') 704 .toLowerCase(); 705 } 706 707 function dasherize() { 708 return this.replace(/_/g, '-'); 709 } 710 711 function inspect(useDoubleQuotes) { 712 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(ch
712aracter) { 713 if (character in String.specialChar) { 714 return String.specialChar[character]; 715 } 716 return '\\u00' + character.charCodeAt().toPaddedString(2, 16); 717 }); 718 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 719 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 720 } 721 722 function unfilterJSON(filter) { 723 return this.replace(filter || Prototype.JSONFilter, '$1'); 724 } 725 726 function isJSON() { 727 var str = this; 728 if (str.blank()) return false; 729 str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); 730 str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); 731 str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 732 return (/^[\],:{}\s]*$/).test(str); 733 } 734 735 function evalJSON(sanitize) { 736 var json = this.unfilterJSON(), 737 cx = /[\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff\u0000]/g; 738 if (cx.test(json)) { 739 json = json.replace(cx, function (a) { 740 return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 741 }); 742 } 743 try { 744 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 745 } catch (e) { } 746 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 747 } 748 749 function parseJSON() { 750 var json = this.unfilterJSON(); 751 return JSON.parse(json); 752 } 753 754 function include(pattern) { 755 return this.indexOf(pattern) > -1; 756 } 757 758 function startsWith(pattern, position) { 759 position = Object.isNumber(position) ? position : 0; 760 return this.lastIndexOf(pattern, position) === position; 761 } 762 763 function endsWith(pattern, position) { 764 pattern = String(pattern); 765 position = Object.isNumber(position) ? position : this.length; 766 if (position < 0) position = 0; 767 if (position > this.length) position = this.length; 768 var d = position - pattern.length; 769 return d >= 0 && this.indexOf(pattern, d) === d; 770 } 771 772 function empty() { 773 return this == ''; 774 } 775 776 function blank() { 777 return /^\s*$/.test(this); 778 } 779 780 function interpolate(object, pattern) { 781 return new Template(this, pattern).evaluate(object); 782 } 783 784 return { 785 gsub: gsub, 786 sub: sub, 787 scan: scan, 788 truncate: truncate, 789 strip: String.prototype.trim || strip, 790 stripTags: stripTags, 791 stripScripts: stripScripts, 792 extractScripts: extractScripts, 793 evalScripts: evalScripts, 794 escapeHTML: escapeHTML, 795 unescapeHTML: unescapeHTML, 796 toQueryParams: toQueryParams, 797 parseQuery: toQueryParams, 798 toArray: toArray, 799 succ: succ, 800 times: times, 801 camelize: camelize, 802 capitalize: capitalize, 803 underscore: underscore, 804 dasherize: dasherize, 805 inspect: inspect, 806 unfilterJSON: unfilterJSON, 807 isJSON: isJSON, 808 evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON, 809 include: include, 810 startsWith: String.prototype.startsWith || startsWith, 811 endsWith: String.prototype.endsWith || endsWith, 812 empty: empty, 813 blank: blank, 814 interpolate: interpolate 815 }; 816})()); 817 818var Template = Class.create({ 819 initialize: function(template, pattern) { 820 this.template = template.toString(); 821 this.pattern = pattern || Template.Pattern; 822 }, 823 824 evaluate: function(object) { 825 if (object && Object.isFunction(object.toTemplateReplacements)) 826 object = object.toTemplateReplacements(); 827 828 return this.template.gsub(this.pattern, function(match) { 829 if (object == null) return (match[1] + ''); 830 831 var before = match[1] || ''; 832 if (before == '\\') return match[2]; 833 834 var ctx = object, expr = match[3], 835 pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 836 837 match = pattern.exec(expr); 838 if (match == null) return before; 839 840 while (match != null) { 841 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; 842 ctx = ctx[comp]; 843 if (null == ctx || '' == match[3]) break; 844 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 845 match = pattern.exec(expr); 846 } 847 848 return before + String.interpret(ctx); 849 }); 850 } 851}); 852Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 853 854var $break = { }; 855 856var Enumerable = (function() { 857 function each(iterator, context) { 858 try { 859 this._each(iterator, context); 860 } catch (e) { 861 if (e != $break) throw e; 862 } 863 return this; 864 } 865 866 function eachSlice(number, iterator, context) {
867 var index = -number, slices = [], array = this.toArray(); 868 if (number < 1) return array; 869 while ((index += number) < array.length) 870 slices.push(array.slice(index, index+number)); 871 return slices.collect(iterator, context); 872 } 873 874 function all(iterator, context) { 875 iterator = iterator || Prototype.K; 876 var result = true; 877 this.each(function(value, index) { 878 result = result && !!iterator.call(context, value, index, this); 879 if (!result) throw $break; 880 }, this); 881 return result; 882 } 883 884 function any(iterator, context) { 885 iterator = iterator || Prototype.K; 886 var result = false; 887 this.each(function(value, index) { 888 if (result = !!iterator.call(context, value, index, this)) 889 throw $break; 890 }, this); 891 return result; 892 } 893 894 function collect(iterator, context) { 895 iterator = iterator || Prototype.K; 896 var results = []; 897 this.each(function(value, index) { 898 results.push(iterator.call(context, value, index, this)); 899 }, this); 900 return results; 901 } 902 903 function detect(iterator, context) { 904 var result; 905 this.each(function(value, index) { 906 if (iterator.call(context, value, index, this)) { 907 result = value; 908 throw $break; 909 } 910 }, this); 911 return result; 912 } 913 914 function findAll(iterator, context) { 915 var results = []; 916 this.each(function(value, index) { 917 if (iterator.call(context, value, index, this)) 918 results.push(value); 919 }, this); 920 return results; 921 } 922 923 function grep(filter, iterator, context) { 924 iterator = iterator || Prototype.K; 925 var results = []; 926 927 if (Object.isString(filter)) 928 filter = new RegExp(RegExp.escape(filter)); 929 930 this.each(function(value, index) { 931 if (filter.match(value)) 932 results.push(iterator.call(context, value, index, this)); 933 }, this); 934 return results; 935 } 936 937 function include(object) { 938 if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1) 939 return true; 940 941 var found = false; 942 this.each(function(value) { 943 if (value == object) { 944 found = true; 945 throw $break; 946 } 947 }); 948 return found; 949 } 950 951 function inGroupsOf(number, fillWith) { 952 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 953 return this.eachSlice(number, function(slice) { 954 while(slice.length < number) slice.push(fillWith); 955 return slice; 956 }); 957 } 958 959 function inject(memo, iterator, context) { 960 this.each(function(value, index) { 961 memo = iterator.call(context, memo, value, index, this); 962 }, this); 963 return memo; 964 } 965 966 function invoke(method) { 967 var args = $A(arguments).slice(1); 968 return this.map(function(value) { 969 return value[method].apply(value, args); 970 }); 971 } 972 973 function max(iterator, context) { 974 iterator = iterator || Prototype.K; 975 var result; 976 this.each(function(value, index) { 977 value = iterator.call(context, value, index, this); 978 if (result == null || value >= result) 979 result = value; 980 }, this); 981 return result; 982 } 983 984 function min(iterator, context) { 985 iterator = iterator || Prototype.K; 986 var result; 987 this.each(function(value, index) { 988 value = iterator.call(context, value, index, this); 989 if (result == null || value < result) 990 result = value; 991 }, this); 992 return result; 993 } 994 995 function partition(iterator, context) { 996 iterator = iterator || Prototype.K; 997 var trues = [], falses = []; 998 this.each(function(value, index) { 999 (iterator.call(context, value, index, this) ? 1000 trues : falses).push(value); 1001 }, this); 1002 return [trues, falses]; 1003 } 1004 1005 function pluck(property) { 1006 var results = []; 1007 this.each(function(value) { 1008 results.push(value[property]); 1009 }); 1010 return results; 1011 } 1012 1013 function reject(iterator, context) { 1014 var results = []; 1015 this.each(function(value, index) { 1016 if (!iterator.call(context, value, index, this)) 1017 results.push(value); 1018 }, this); 1019 return results; 1020 } 1021 1022 function sortBy(iterator, context) { 1023 return this.map(function(value, index) { 1024 return { 1025 value: value, 1026 criteria: iterator.call(context, value, index, this) 1027 }; 1028 }, this).sort(function(left, right) { 1029 var a = left.criteria, b = right.criteria; 1030 return a < b ? -1 : a > b ? 1 : 0; 1031 }).pluck('value'); 1032 } 1033 1034 function toArray() { 1035 return this.map(); 1036 } 1037 1038 function zip() { 1039 var iterator = Prototype.K, args = $A(arguments); 1040 if (Object.isFunction(args.last())) 1041 iterator = args.pop(); 1042 1043 var collections = [this].concat(args).map($A); 1044 return this.map(function(value, index) { 1045 return iterator(collections.pluck(index)); 1046 }); 1047 } 1048 1049 function size() { 1050 return this.toArray().length; 1051 } 1052 1053 function inspect() { 1054 return '#<Enumerable:' + this.toArray().inspect() + '>'; 1055 } 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 return { 1066 each: each, 1067 eachSlice: eachSlice, 1068 all: all, 1069 every: all, 1070 any: any, 1071 some: any, 1072 collect: collect, 1073 map: collect, 1074 detect: detect, 1075 findAll: findAll, 1076 select: findAll, 1077 filter: findAll, 1078 grep: grep, 1079 include: include, 1080 member: include, 1081 inGroupsOf: inGroupsOf, 1082 inject: inject, 1083 invoke: invoke, 1084 max: max, 1085 min: min, 1086 partition: partition, 1087 pluck: pluck, 1088 reject: reject, 1089 sortBy: sortBy, 1090 toArray: toArray, 1091 entries: toArray, 1092 zip: zip, 1093 size: size, 1094 inspect: inspect, 1095 find: detect
1096 }; 1097})(); 1098 1099function $A(iterable) { 1100 if (!iterable) return []; 1101 if ('toArray' in Object(iterable)) return iterable.toArray(); 1102 var length = iterable.length || 0, results = new Array(length); 1103 while (length--) results[length] = iterable[length]; 1104 return results; 1105} 1106 1107 1108function $w(string) { 1109 if (!Object.isString(string)) return []; 1110 string = string.strip(); 1111 return string ? string.split(/\s+/) : []; 1112} 1113 1114//MIM- 1115Array.from = Array.from || $A; 1116 1117(function() { 1118 var arrayProto = Array.prototype, 1119 slice = arrayProto.slice, 1120 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available 1121 1122 function each(iterator, context) { 1123 for (var i = 0, length = this.length >>> 0; i < length; i++) { 1124 if (i in this) iterator.call(context, this[i], i, this); 1125 } 1126 } 1127 if (!_each) _each = each; 1128 1129 function clear() { 1130 this.length = 0; 1131 return this; 1132 } 1133 1134 function first() { 1135 return this[0]; 1136 } 1137 1138 function last() { 1139 return this[this.length - 1]; 1140 } 1141 1142 function compact() { 1143 return this.select(function(value) { 1144 return value != null; 1145 }); 1146 } 1147 1148 function flatten() { 1149 return this.inject([], function(array, value) { 1150 if (Object.isArray(value)) 1151 return array.concat(value.flatten()); 1152 array.push(value); 1153 return array; 1154 }); 1155 } 1156 1157 function without() { 1158 var values = slice.call(arguments, 0); 1159 return this.select(function(value) { 1160 return !values.include(value); 1161 }); 1162 } 1163 1164 function reverse(inline) { 1165 return (inline === false ? this.toArray() : this)._reverse(); 1166 } 1167 1168 function uniq(sorted) { 1169 return this.inject([], function(array, value, index) { 1170 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 1171 array.push(value); 1172 return array; 1173 }); 1174 } 1175 1176 function intersect(array) { 1177 return this.uniq().findAll(function(item) { 1178 return array.indexOf(item) !== -1; 1179 }); 1180 } 1181 1182 1183 function clone() { 1184 return slice.call(this, 0); 1185 } 1186 1187 function size() { 1188 return this.length; 1189 } 1190 1191 function inspect() { 1192 return '[' + this.map(Object.inspect).join(', ') + ']'; 1193 } 1194 1195 function indexOf(item, i) { 1196 if (this == null) throw new TypeError(); 1197 1198 var array = Object(this), length = array.length >>> 0; 1199 if (length === 0) return -1; 1200 1201 i = Number(i); 1202 if (isNaN(i)) { 1203 i = 0; 1204 } else if (i !== 0 && isFinite(i)) { 1205 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i)); 1206 } 1207 1208 if (i > length) return -1; 1209 1210 var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0); 1211 for (; k < length; k++) 1212 if (k in array && array[k] === item) return k; 1213 return -1; 1214 } 1215 1216 1217 function lastIndexOf(item, i) { 1218 if (this == null) throw new TypeError(); 1219 1220 var array = Object(this), length = array.length >>> 0; 1221 if (length === 0) return -1; 1222 1223 if (!Object.isUndefined(i)) { 1224 i = Number(i); 1225 if (isNaN(i)) { 1226 i = 0; 1227 } else if (i !== 0 && isFinite(i)) { 1228 i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i)); 1229 } 1230 } else { 1231 i = length; 1232 } 1233 1234 var k = i >= 0 ? Math.min(i, length - 1) : 1235 length - Math.abs(i); 1236 1237 for (; k >= 0; k--) 1238 if (k in array && array[k] === item) return k; 1239 return -1; 1240 } 1241 1242 function concat(_) { 1243 var array = [], items = slice.call(arguments, 0), item, n = 0; 1244 items.unshift(this); 1245 for (var i = 0, length = items.length; i < length; i++) { 1246 item = items[i]; 1247 if (Object.isArray(item) && !('callee' in item)) { 1248 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) { 1249 if (j in item) array[n] = item[j]; 1250 n++; 1251 } 1252 } else { 1253 array[n++] = item; 1254 } 1255 } 1256 array.length = n; 1257 return array; 1258 } 1259 1260 1261 function wrapNative(method) { 1262 return function() { 1263 if (arguments.length === 0) { 1264 return method.call(this, Prototype.K); 1265 } else if (arguments[0] === undefined) { 1266 var args = slice.call(arguments, 1); 1267 args.unshift(Prototype.K); 1268 return method.apply(this, args); 1269 } else { 1270 return method.apply(this, arguments); 1271 } 1272 }; 1273 } 1274 1275 1276 function map(iterator) { 1277 if (this == null) throw new TypeError(); 1278 iterator = iterator || Prototype.K; 1279 1280 var object = Object(this); 1281 var results = [], context = arguments[1], n = 0; 1282 1283 for (var i = 0, length = object.length >>> 0; i < length; i++) { 1284 if (i in object) { 1285 results[n] = iterator.call(context, object[i], i, object); 1286 } 1287 n++; 1288 } 1289 results.length = n; 1290 return results; 1291 } 1292 1293 if (arrayProto.map) { 1294 map = wrapNative(Array.prototype.map); 1295 } 1296 1297 function filter(iterator) { 1298 if (this == null || !Object.isFunction(iterator)) 1299 throw new TypeError(); 1300 1301 var object = Object(this); 1302 var results = [], context = arguments[1], value; 1303 1304 for (var i = 0, length = object.length >>> 0; i < length; i++) { 1305 if (i in object) { 1306 value = object[i]; 1307 if (iterator.call(context, value, i, object)) { 1308 results.push(value); 1309 } 1310 } 1311 } 1312 return results; 1313 } 1314 1315 if (arrayProto.filter) { 1316 filter = Array.prototype.filter; 1317 } 1318 1319 function some(iterator) { 1320 if (this == null) throw new TypeError(); 1321 iterator = iterator || Prototype.K; 1322 var context = arguments[1]; 1323 1324 var object = Object(this); 1325 for (var i = 0, length = object.length >>> 0; i < length; i++) { 1326 if (i in object && iterator.call(context, object[i], i, object)) { 1327 return true; 1328 } 1329 } 1330 1331 return false;
1332 } 1333 1334 if (arrayProto.some) { 1335 some = wrapNative(Array.prototype.some); 1336 } 1337 1338 function every(iterator) { 1339 if (this == null) throw new TypeError(); 1340 iterator = iterator || Prototype.K; 1341 var context = arguments[1]; 1342 1343 var object = Object(this); 1344 for (var i = 0, length = object.length >>> 0; i < length; i++) { 1345 if (i in object && !iterator.call(context, object[i], i, object)) { 1346 return false; 1347 } 1348 } 1349 1350 return true; 1351 } 1352 1353 if (arrayProto.every) { 1354 every = wrapNative(Array.prototype.every); 1355 } 1356 1357 1358 Object.extend(arrayProto, Enumerable); 1359 1360 if (arrayProto.entries === Enumerable.entries) { 1361 delete arrayProto.entries; 1362 } 1363 1364 if (!arrayProto._reverse) 1365 arrayProto._reverse = arrayProto.reverse; 1366 1367 Object.extend(arrayProto, { 1368 _each: _each, 1369 1370 map: map, 1371 collect: map, 1372 select: filter, 1373 filter: filter, 1374 findAll: filter, 1375 some: some, 1376 any: some, 1377 every: every, 1378 all: every, 1379 1380 clear: clear, 1381 first: first, 1382 last: last, 1383 compact: compact, 1384 flatten: flatten, 1385 without: without, 1386 reverse: reverse, 1387 uniq: uniq, 1388 intersect: intersect, 1389 clone: clone, 1390 toArray: clone, 1391 size: size, 1392 inspect: inspect 1393 }); 1394 1395 var CONCAT_ARGUMENTS_BUGGY = (function() { 1396 return [].concat(arguments)[0][0] !== 1; 1397 })(1,2); 1398 1399 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; 1400 1401 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; 1402 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; 1403})(); 1404function $H(object) { 1405 return new Hash(object); 1406}; 1407 1408var Hash = Class.create(Enumerable, (function() { 1409 function initialize(object) { 1410 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 1411 } 1412 1413 1414 function _each(iterator, context) { 1415 var i = 0; 1416 for (var key in this._object) { 1417 var value = this._object[key], pair = [key, value]; 1418 pair.key = key; 1419 pair.value = value; 1420 iterator.call(context, pair, i); 1421 i++; 1422 } 1423 } 1424 1425 function set(key, value) { 1426 return this._object[key] = value; 1427 } 1428 1429 function get(key) { 1430 if (this._object[key] !== Object.prototype[key]) 1431 return this._object[key]; 1432 } 1433 1434 function unset(key) { 1435 var value = this._object[key]; 1436 delete this._object[key]; 1437 return value; 1438 } 1439 1440 function toObject() { 1441 return Object.clone(this._object); 1442 } 1443 1444 1445 1446 function keys() { 1447 return this.pluck('key'); 1448 } 1449 1450 function values() { 1451 return this.pluck('value'); 1452 } 1453 1454 function index(value) { 1455 var match = this.detect(function(pair) { 1456 return pair.value === value; 1457 }); 1458 return match && match.key; 1459 } 1460 1461 function merge(object) { 1462 return this.clone().update(object); 1463 } 1464 1465 function update(object) { 1466 return new Hash(object).inject(this, function(result, pair) { 1467 result.set(pair.key, pair.value); 1468 return result; 1469 }); 1470 } 1471 1472 function toQueryPair(key, value) { 1473 if (Object.isUndefined(value)) return key; 1474 1475 value = String.interpret(value); 1476 1477 value = value.gsub(/(\r)?\n/, '\r\n'); 1478 value = encodeURIComponent(value); 1479 value = value.gsub(/%20/, '+'); 1480 return key + '=' + value; 1481 } 1482 1483 function toQueryString() { 1484 return this.inject([], function(results, pair) { 1485 var key = encodeURIComponent(pair.key), values = pair.value; 1486 1487 if (values && typeof values == 'object') { 1488 if (Object.isArray(values)) { 1489 var queryValues = []; 1490 for (var i = 0, len = values.length, value; i < len; i++) { 1491 value = values[i]; 1492 queryValues.push(toQueryPair(key, value)); 1493 } 1494 return results.concat(queryValues); 1495 } 1496 } else results.push(toQueryPair(key, values)); 1497 return results; 1498 }).join('&'); 1499 } 1500 1501 function inspect() { 1502 return '#<Hash:{' + this.map(function(pair) { 1503 return pair.map(Object.inspect).join(': '); 1504 }).join(', ') + '}>'; 1505 } 1506 1507 function clone() { 1508 return new Hash(this); 1509 } 1510 1511 return { 1512 initialize: initialize, 1513 _each: _each, 1514 set: set, 1515 get: get, 1516 unset: unset, 1517 toObject: toObject, 1518 toTemplateReplacements: toObject, 1519 keys: keys, 1520 values: values, 1521 index: index, 1522 merge: merge, 1523 update: update, 1524 toQueryString: toQueryString, 1525 inspect: inspect, 1526 toJSON: toObject, 1527 clone: clone 1528 }; 1529})()); 1530 1531Hash.from = $H; 1532Object.extend(Number.prototype, (function() { 1533 function toColorPart() { 1534 return this.toPaddedString(2, 16); 1535 } 1536 1537 function succ() { 1538 return this + 1; 1539 } 1540 1541 function times(iterator, context) { 1542 $R(0, this, true).each(iterator, context); 1543 return this; 1544 } 1545 1546 function toPaddedString(length, radix) { 1547 var string = this.toString(radix || 10); 1548 return '0'.times(length - string.length) + string; 1549 } 1550 1551 function abs() { 1552 return Math.abs(this); 1553 } 1554 1555 function round() { 1556 return Math.round(this); 1557 } 1558 1559 function ceil() { 1560 return Math.ceil(this); 1561 } 1562 1563 function floor() { 1564 return Math.floor(this); 1565 } 1566 1567 return { 1568 toColorPart: toColorPart, 1569 succ: succ, 1570 times: times, 1571 toPaddedString: toPaddedString, 1572 abs: abs, 1573 round: round, 1574 ceil: ceil, 1575 floor: floor 1576 }; 1577})()); 1578 1579function $R(start, end, exclusive) { 1580 return new ObjectRange(start, end, exclusive); 1581} 1582 1583var ObjectRange = Class.create(Enumerable, (function() { 1584 function initialize(start, end, exclusive) { 1585 this.start = start; 1586 this.end = end; 1587 this.exclusive = exclusive; 1588 } 1589 1590 function _each(iterator, context) { 1591 var value = this.start, i; 1592 for (i = 0; this.include(value); i++) { 1593 iterator.call(context, value, i); 1594 value = value.succ(); 1595 } 1596 } 1597 1598 function include(value) { 1599 if (value < this.start) 1600 return false;
1601 if (this.exclusive) 1602 return value < this.end; 1603 return value <= this.end; 1604 } 1605 1606 return { 1607 initialize: initialize, 1608 _each: _each, 1609 include: include 1610 }; 1611})()); 1612 1613 1614 1615var Abstract = { }; 1616 1617 1618var Try = { 1619 these: function() { 1620 var returnValue; 1621 1622 for (var i = 0, length = arguments.length; i < length; i++) { 1623 var lambda = arguments[i]; 1624 try { 1625 returnValue = lambda(); 1626 break; 1627 } catch (e) { } 1628 } 1629 1630 return returnValue; 1631 } 1632}; 1633 1634var Ajax = { 1635 getTransport: function() { 1636 return Try.these( 1637 function() {return new XMLHttpRequest()}, 1638 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 1639 function() {return new ActiveXObject('Microsoft.XMLHTTP')} 1640 ) || false; 1641 }, 1642 1643 activeRequestCount: 0 1644}; 1645 1646Ajax.Responders = { 1647 responders: [], 1648 1649 _each: function(iterator, context) { 1650 this.responders._each(iterator, context); 1651 }, 1652 1653 register: function(responder) { 1654 if (!this.include(responder)) 1655 this.responders.push(responder); 1656 }, 1657 1658 unregister: function(responder) { 1659 this.responders = this.responders.without(responder); 1660 }, 1661 1662 dispatch: function(callback, request, transport, json) { 1663 this.each(function(responder) { 1664 if (Object.isFunction(responder[callback])) { 1665 try { 1666 responder[callback].apply(responder, [request, transport, json]); 1667 } catch (e) { } 1668 } 1669 }); 1670 } 1671}; 1672 1673Object.extend(Ajax.Responders, Enumerable); 1674 1675Ajax.Responders.register({ 1676 onCreate: function() { Ajax.activeRequestCount++ },
1677 onComplete: function() { Ajax.activeRequestCount-- } 1678}); 1679Ajax.Base = Class.create({ 1680 initialize: function(options) { 1681 this.options = { 1682 method: 'post', 1683 asynchronous: true, 1684 contentType: 'application/x-www-form-urlencoded', 1685 encoding: 'UTF-8', 1686 parameters: '', 1687 evalJSON: true, 1688 evalJS: true 1689 }; 1690 Object.extend(this.options, options || { }); 1691 1692 this.options.method = this.options.method.toLowerCase(); 1693 1694 if (Object.isHash(this.options.parameters)) 1695 this.options.parameters = this.options.parameters.toObject(); 1696 } 1697}); 1698Ajax.Request = Class.create(Ajax.Base, { 1699 _complete: false, 1700 1701 initialize: function($super, url, options) { 1702 $super(options); 1703 this.transport = Ajax.getTransport(); 1704 this.request(url); 1705 }, 1706 1707 request: function(url) { 1708 this.url = url; 1709 this.method = this.options.method; 1710 var params = Object.isString(this.options.parameters) ? 1711 this.options.parameters : 1712 Object.toQueryString(this.options.parameters); 1713 1714 if (!['get', 'post'].include(this.method)) { 1715 params += (params ? '&' : '') + "_method=" + this.method; 1716 this.method = 'post'; 1717 } 1718 1719 if (params && this.method === 'get') { 1720 this.url += (this.url.include('?') ? '&' : '?') + params; 1721 } 1722 1723 this.parameters = params.toQueryParams(); 1724 1725 try { 1726 var response = new Ajax.Response(this); 1727 if (this.options.onCreate) this.options.onCreate(response); 1728 Ajax.Responders.dispatch('onCreate', this, response); 1729 1730 this.transport.open(this.method.toUpperCase(), this.url, 1731 this.options.asynchronous); 1732 1733 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 1734 1735 this.transport.onreadystatechange = this.onStateChange.bind(this); 1736 this.setRequestHeaders(); 1737 1738 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 1739 this.transport.send(this.body); 1740 1741 /* Force Firefox to handle ready state 4 for synchronous requests */ 1742 if (!this.options.asynchronous && this.transport.overrideMimeType) 1743 this.onStateChange(); 1744 1745 } 1746 catch (e) { 1747 this.dispatchException(e); 1748 } 1749 }, 1750 1751 onStateChange: function() { 1752 var readyState = this.transport.readyState; 1753 if (readyState > 1 && !((readyState == 4) && this._complete)) 1754 this.respondToReadyState(this.transport.readyState); 1755 }, 1756 1757 setRequestHeaders: function() { 1758 var headers = { 1759 'X-Requested-With': 'XMLHttpRequest', 1760 'X-Prototype-Version': Prototype.Version, 1761 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 1762 }; 1763 1764 if (this.method == 'post') { 1765 headers['Content-type'] = this.options.contentType + 1766 (this.options.encoding ? '; charset=' + this.options.encoding : ''); 1767 1768 /* Force "Connection: close" for older Mozilla browsers to work 1769 * around a bug where XMLHttpRequest sends an incorrect 1770 * Content-length header. See Mozilla Bugzilla #246651. 1771 */ 1772 if (this.transport.overrideMimeType && 1773 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 1774 headers['Connection'] = 'close'; 1775 } 1776 1777 if (typeof this.options.requestHeaders == 'object') { 1778 var extras = this.options.requestHeaders; 1779 1780 if (Object.isFunction(extras.push)) 1781 for (var i = 0, length = extras.length; i < length; i += 2) 1782 headers[extras[i]] = extras[i+1]; 1783 else 1784 $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 1785 } 1786 1787 for (var name in headers) 1788 if (headers[name] != null) 1789 this.transport.setRequestHeader(name, headers[name]); 1790 }, 1791 1792 success: function() { 1793 var status = this.getStatus(); 1794 return !status || (status >= 200 && status < 300) || status == 304; 1795 }, 1796 1797 getStatus: function() { 1798 try { 1799 if (this.transport.status === 1223) return 204; 1800 return this.transport.status || 0; 1801 } catch (e) { return 0 } 1802 }, 1803 1804 respondToReadyState: function(readyState) { 1805 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 1806 1807 if (state == 'Complete') {
1808 try { 1809 this._complete = true; 1810 (this.options['on' + response.status] 1811 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 1812 || Prototype.emptyFunction)(response, response.headerJSON); 1813 } catch (e) { 1814 this.dispatchException(e); 1815 } 1816 1817 var contentType = response.getHeader('Content-type'); 1818 if (this.options.evalJS == 'force' 1819 || (this.options.evalJS && this.isSameOrigin() && contentType 1820 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1821 this.evalResponse(); 1822 } 1823 1824 try { 1825 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 1826 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 1827 } catch (e) { 1828 this.dispatchException(e); 1829 } 1830 1831 if (state == 'Complete') { 1832 this.transport.onreadystatechange = Prototype.emptyFunction; 1833 } 1834 }, 1835 1836 isSameOrigin: function() { 1837 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 1838 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 1839 protocol: location.protocol, 1840 domain: document.domain, 1841 port: location.port ? ':' + location.port : '' 1842 })); 1843 }, 1844 1845 getHeader: function(name) { 1846 try { 1847 return this.transport.getResponseHeader(name) || null; 1848 } catch (e) { return null; } 1849 }, 1850 1851 evalResponse: function() { 1852 try { 1853 return eval((this.transport.responseText || '').unfilterJSON()); 1854 } catch (e) { 1855 this.dispatchException(e); 1856 } 1857 }, 1858 1859 dispatchException: function(exception) { 1860 (this.options.onException || Prototype.emptyFunction)(this, exception); 1861 Ajax.Responders.dispatch('onException', this, exception); 1862 } 1863}); 1864 1865Ajax.Request.Events = 1866 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1867 1868 1869 1870 1871 1872 1873 1874 1875Ajax.Response = Class.create({ 1876 initialize: function(request){ 1877 this.request = request; 1878 var transport = this.transport = request.transport, 1879 readyState = this.readyState = transport.readyState; 1880 1881 if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 1882 this.status = this.getStatus(); 1883 this.statusText = this.getStatusText(); 1884 this.responseText = String.interpret(transport.responseText); 1885 this.headerJSON = this._getHeaderJSON(); 1886 } 1887 1888 if (readyState == 4) { 1889 var xml = transport.responseXML; 1890 this.responseXML = Object.isUndefined(xml) ? null : xml; 1891 this.responseJSON = this._getResponseJSON(); 1892 } 1893 }, 1894 1895 status: 0, 1896 1897 statusText: '', 1898 1899 getStatus: Ajax.Request.prototype.getStatus, 1900 1901 getStatusText: function() { 1902 try { 1903 return this.transport.statusText || ''; 1904 } catch (e) { return '' } 1905 }, 1906 1907 getHeader: Ajax.Request.prototype.getHeader, 1908 1909 getAllHeaders: function() { 1910 try { 1911 return this.getAllResponseHeaders(); 1912 } catch (e) { return null } 1913 }, 1914 1915 getResponseHeader: function(name) { 1916 return this.transport.getResponseHeader(name); 1917 }, 1918 1919 getAllResponseHeaders: function() { 1920 return this.transport.getAllResponseHeaders(); 1921 }, 1922 1923 _getHeaderJSON: function() { 1924 var json = this.getHeader('X-JSON'); 1925 if (!json) return null; 1926 1927 try { 1928 json = decodeURIComponent(escape(json)); 1929 } catch(e) { 1930 } 1931 1932 try { 1933 return json.evalJSON(this.request.options.sanitizeJSON || 1934 !this.request.isSameOrigin()); 1935 } catch (e) { 1936 this.request.dispatchException(e); 1937 } 1938 }, 1939 1940 _getResponseJSON: function() { 1941 var options = this.request.options; 1942 if (!options.evalJSON || (options.evalJSON != 'force' && 1943 !(this.getHeader('Content-type') || '').include('application/json')) || 1944 this.responseText.blank()) 1945 return null; 1946 try { 1947 return this.responseText.evalJSON(options.sanitizeJSON || 1948 !this.request.isSameOrigin()); 1949 } catch (e) { 1950 this.request.dispatchException(e); 1951 } 1952 } 1953}); 1954 1955Ajax.Updater = Class.create(Ajax.Request, { 1956 initialize: function($super, container, url, options) { 1957 this.container = { 1958 success: (container.success || container), 1959 failure: (container.failure || (container.success ? null : container)) 1960 }; 1961 1962 options = Object.clone(options); 1963 var onComplete = options.onComplete; 1964 options.onComplete = (function(response, json) { 1965 this.updateContent(response.responseText); 1966 if (Object.isFunction(onComplete)) onComplete(response, json); 1967 }).bind(this); 1968 1969 $super(url, options); 1970 }, 1971 1972 updateContent: function(responseText) { 1973 var receiver = this.container[this.success() ? 'success' : 'failure'], 1974 options = this.options; 1975 1976 if (!options.evalScripts) responseText = responseText.stripScripts(); 1977 1978 if (receiver = $(receiver)) { 1979 if (options.insertion) { 1980 if (Object.isString(options.insertion)) { 1981 var insertion = { }; insertion[options.insertion] = responseText; 1982 receiver.insert(insertion); 1983 } 1984 else options.insertion(receiver, responseText); 1985 } 1986 else receiver.update(responseText); 1987 } 1988 } 1989}); 1990
1991Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 1992 initialize: function($super, container, url, options) { 1993 $super(options); 1994 this.onComplete = this.options.onComplete; 1995 1996 this.frequency = (this.options.frequency || 2); 1997 this.decay = (this.options.decay || 1); 1998 1999 this.updater = { }; 2000 this.container = container; 2001 this.url = url; 2002 2003 this.start(); 2004 }, 2005 2006 start: function() { 2007 this.options.onComplete = this.updateComplete.bind(this); 2008 this.onTimerEvent(); 2009 }, 2010 2011 stop: function() { 2012 this.updater.options.onComplete = undefined; 2013 clearTimeout(this.timer); 2014 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 2015 }, 2016 2017 updateComplete: function(response) { 2018 if (this.options.decay) { 2019 this.decay = (response.responseText == this.lastText ? 2020 this.decay * this.options.decay : 1); 2021 2022 this.lastText = response.responseText; 2023 } 2024 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 2025 }, 2026 2027 onTimerEvent: function() { 2028 this.updater = new Ajax.Updater(this.container, this.url, this.options); 2029 } 2030}); 2031 2032(function(GLOBAL) { 2033 2034 var UNDEFINED; 2035 var SLICE = Array.prototype.slice; 2036 2037 var DIV = document.createElement('div'); 2038 2039 2040 function $(element) { 2041 if (arguments.length > 1) { 2042 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 2043 elements.push($(arguments[i])); 2044 return elements; 2045 } 2046 2047 if (Object.isString(element)) 2048 element = document.getElementById(element); 2049 return Element.extend(element); 2050 } 2051 2052 GLOBAL.$ = $; 2053 2054 2055 if (!GLOBAL.Node) GLOBAL.Node = {}; 2056 2057 if (!GLOBAL.Node.ELEMENT_NODE) { 2058 Object.extend(GLOBAL.Node, { 2059 ELEMENT_NODE: 1, 2060 ATTRIBUTE_NODE: 2, 2061 TEXT_NODE: 3, 2062 CDATA_SECTION_NODE: 4, 2063 ENTITY_REFERENCE_NODE: 5, 2064 ENTITY_NODE: 6, 2065 PROCESSING_INSTRUCTION_NODE: 7, 2066 COMMENT_NODE: 8, 2067 DOCUMENT_NODE: 9, 2068 DOCUMENT_TYPE_NODE: 10, 2069 DOCUMENT_FRAGMENT_NODE: 11, 2070 NOTATION_NODE: 12 2071 }); 2072 } 2073 2074 var ELEMENT_CACHE = {}; 2075 2076 function shouldUseCreationCache(tagName, attributes) { 2077 if (tagName === 'select') return false; 2078 if ('type' in attributes) return false; 2079 return true; 2080 } 2081 2082 var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){ 2083 try { 2084 var el = document.createElement('<input name="x">'); 2085 return el.tagName.toLowerCase() === 'input' && el.name === 'x'; 2086 } 2087 catch(err) { 2088 return false; 2089 } 2090 })(); 2091 2092 2093 var oldElement = GLOBAL.Element; 2094 function Element(tagName, attributes) { 2095 attributes = attributes || {}; 2096 tagName = tagName.toLowerCase(); 2097 2098 if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) { 2099 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 2100 delete attributes.name; 2101 return Element.writeAttribute(document.createElement(tagName), attributes); 2102 } 2103 2104 if (!ELEMENT_CACHE[tagName]) 2105 ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName)); 2106 2107 var node = shouldUseCreationCache(tagName, attributes) ? 2108 ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName); 2109 2110 return Element.writeAttribute(node, attributes); 2111 } 2112 2113 GLOBAL.Element = Element; 2114 2115 Object.extend(GLOBAL.Element, oldElement || {}); 2116 if (oldElement) GLOBAL.Element.prototype = oldElement.prototype; 2117 2118 Element.Methods = { ByTag: {}, Simulated: {} }; 2119 2120 var methods = {}; 2121 2122 var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' }; 2123 function inspect(element) { 2124 element = $(element); 2125 var result = '<' + element.tagName.toLowerCase(); 2126 2127 var attribute, value; 2128 for (var property in INSPECT_ATTRIBUTES) { 2129 attribute = INSPECT_ATTRIBUTES[property]; 2130 value = (element[property] || '').toString(); 2131 if (value) result += ' ' + attribute + '=' + value.inspect(true); 2132 } 2133 2134 return result + '>'; 2135 } 2136 2137 methods.inspect = inspect; 2138 2139 2140 function visible(element) { 2141 return $(element).getStyle('display') !== 'none'; 2142 } 2143 2144 function toggle(element, bool) { 2145 element = $(element); 2146 if (typeof bool !== 'boolean') 2147 bool = !Element.visible(element); 2148 Element[bool ? 'show' : 'hide'](element); 2149 2150 return element; 2151 } 2152 2153 function hide(element) { 2154 element = $(element); 2155 element.style.display = 'none'; 2156 return element; 2157 } 2158 2159 function show(element) { 2160 element = $(element); 2161 element.style.display = ''; 2162 return element; 2163 } 2164 2165 2166 Object.extend(methods, { 2167 visible: visible, 2168 toggle: toggle, 2169 hide: hide, 2170 show: show 2171 }); 2172 2173 2174 function remove(element) { 2175 element = $(element); 2176 element.parentNode.removeChild(element); 2177 return element; 2178 } 2179 2180 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ 2181 var el = document.createElement("select"), 2182 isBuggy = true; 2183 el.innerHTML = "<option value=\"test\">test</option>"; 2184 if (el.options && el.options[0]) { 2185 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; 2186 } 2187 el = null; 2188 return isBuggy; 2189 })(); 2190 2191 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ 2192 try { 2193 var el = document.createElement("table"); 2194 if (el && el.tBodies) { 2195 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; 2196 var isBuggy = typeof el.tBodies[0] == "undefined"; 2197 el = null; 2198 return isBuggy; 2199 } 2200 } catch (e) { 2201 return true; 2202 } 2203 })(); 2204
2205 var LINK_ELEMENT_INNERHTML_BUGGY = (function() { 2206 try { 2207 var el = document.createElement('div'); 2208 el.innerHTML = "<link />"; 2209 var isBuggy = (el.childNodes.length === 0); 2210 el = null; 2211 return isBuggy; 2212 } catch(e) { 2213 return true; 2214 } 2215 })(); 2216 2217 var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY || 2218 TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY; 2219 2220 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { 2221 var s = document.createElement("script"), 2222 isBuggy = false; 2223 try { 2224 s.appendChild(document.createTextNode("")); 2225 isBuggy = !s.firstChild || 2226 s.firstChild && s.firstChild.nodeType !== 3; 2227 } catch (e) { 2228 isBuggy = true; 2229 } 2230 s = null; 2231 return isBuggy; 2232 })(); 2233 2234 function update(element, content) { 2235 element = $(element); 2236 2237 var descendants = element.getElementsByTagName('*'), 2238 i = descendants.length; 2239 while (i--) purgeElement(descendants[i]); 2240 2241 if (content && content.toElement) 2242 content = content.toElement(); 2243 2244 if (Object.isElement(content)) 2245 return element.update().insert(content); 2246 2247 2248 content = Object.toHTML(content); 2249 var tagName = element.tagName.toUpperCase(); 2250 2251 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { 2252 element.text = content; 2253 return element; 2254 } 2255 2256 if (ANY_INNERHTML_BUGGY) { 2257 if (tagName in INSERTION_TRANSLATIONS.tags) { 2258 while (element.firstChild) 2259 element.removeChild(element.firstChild); 2260 2261 var nodes = getContentFromAnonymousElement(tagName, content.stripScripts()); 2262 for (var i = 0, node; node = nodes[i]; i++) 2263 element.appendChild(node); 2264 2265 } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) { 2266 while (element.firstChild) 2267 element.removeChild(element.firstChild); 2268 2269 var nodes = getContentFromAnonymousElement(tagName, 2270 content.stripScripts(), true); 2271 2272 for (var i = 0, node; node = nodes[i]; i++) 2273 element.appendChild(node); 2274 } else { 2275 element.innerHTML = content.stripScripts(); 2276 } 2277 } else { 2278 element.innerHTML = content.stripScripts(); 2279 } 2280 2281 content.evalScripts.bind(content).defer(); 2282 return element; 2283 } 2284 2285 function replace(element, content) { 2286 element = $(element); 2287 2288 if (content && content.toElement) { 2289 content = content.toElement(); 2290 } else if (!Object.isElement(content)) { 2291 content = Object.toHTML(content); 2292 var range = element.ownerDocument.createRange(); 2293 range.selectNode(element); 2294 content.evalScripts.bind(content).defer(); 2295 content = range.createContextualFragment(content.stripScripts()); 2296 } 2297 2298 element.parentNode.replaceChild(content, element); 2299 return element; 2300 } 2301 2302 var INSERTION_TRANSLATIONS = { 2303 before: function(element, node) { 2304 element.parentNode.insertBefore(node, element); 2305 }, 2306 top: function(element, node) { 2307 element.insertBefore(node, element.firstChild); 2308 }, 2309 bottom: function(element, node) { 2310 element.appendChild(node); 2311 }, 2312 after: function(element, node) { 2313 element.parentNode.insertBefore(node, element.nextSibling); 2314 }, 2315 2316 tags: { 2317 TABLE: ['<table>', '</table>', 1], 2318 TBODY: ['<table><tbody>', '</tbody></table>', 2], 2319 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], 2320 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 2321 SELECT: ['<select>', '</select>', 1] 2322 } 2323 }; 2324 2325 var tags = INSERTION_TRANSLATIONS.tags; 2326 2327 Object.extend(tags, { 2328 THEAD: tags.TBODY, 2329 TFOOT: tags.TBODY, 2330 TH: tags.TD 2331 }); 2332 2333 function replace_IE(element, content) { 2334 element = $(element); 2335 if (content && content.toElement) 2336 content = content.toElement(); 2337 if (Object.isElement(content)) { 2338 element.parentNode.replaceChild(content, element); 2339 return element; 2340 } 2341 2342 content = Object.toHTML(content); 2343 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); 2344 2345 if (tagName in INSERTION_TRANSLATIONS.tags) { 2346 var nextSibling = Element.next(element); 2347 var fragments = getContentFromAnonymousElement( 2348 tagName, content.stripScripts()); 2349 2350 parent.removeChild(element); 2351 2352 var iterator; 2353 if (nextSibling) 2354 iterator = function(node) { parent.insertBefore(node, nextSibling) }; 2355 else 2356 iterator = function(node) { parent.appendChild(node); } 2357 2358 fragments.each(iterator); 2359 } else { 2360 element.outerHTML = content.stripScripts(); 2361 } 2362 2363 content.evalScripts.bind(content).defer(); 2364 return element; 2365 } 2366 2367 if ('outerHTML' in document.documentElement) 2368 replace = replace_IE; 2369 2370 function isContent(content) { 2371 if (Object.isUndefined(content) || content === null) return false;
2372 2373 if (Object.isString(content) || Object.isNumber(content)) return true; 2374 if (Object.isElement(content)) return true; 2375 if (content.toElement || content.toHTML) return true; 2376 2377 return false; 2378 } 2379 2380 function insertContentAt(element, content, position) { 2381 position = position.toLowerCase(); 2382 var method = INSERTION_TRANSLATIONS[position]; 2383 2384 if (content && content.toElement) content = content.toElement(); 2385 if (Object.isElement(content)) { 2386 method(element, content); 2387 return element; 2388 } 2389 2390 content = Object.toHTML(content); 2391 var tagName = ((position === 'before' || position === 'after') ? 2392 element.parentNode : element).tagName.toUpperCase(); 2393 2394 var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts()); 2395 2396 if (position === 'top' || position === 'after') childNodes.reverse(); 2397 2398 for (var i = 0, node; node = childNodes[i]; i++) 2399 method(element, node); 2400 2401 content.evalScripts.bind(content).defer(); 2402 } 2403 2404 function insert(element, insertions) { 2405 element = $(element); 2406 2407 if (isContent(insertions)) 2408 insertions = { bottom: insertions }; 2409 2410 for (var position in insertions) 2411 insertContentAt(element, insertions[position], position); 2412 2413 return element; 2414 } 2415 2416 function wrap(element, wrapper, attributes) { 2417 element = $(element); 2418 2419 if (Object.isElement(wrapper)) { 2420 $(wrapper).writeAttribute(attributes || {}); 2421 } else if (Object.isString(wrapper)) { 2422 wrapper = new Element(wrapper, attributes); 2423 } else { 2424 wrapper = new Element('div', wrapper); 2425 } 2426 2427 if (element.parentNode) 2428 element.parentNode.replaceChild(wrapper, element); 2429 2430 wrapper.appendChild(element); 2431 2432 return wrapper; 2433 } 2434 2435 function cleanWhitespace(element) { 2436 element = $(element); 2437 var node = element.firstChild; 2438 2439 while (node) { 2440 var nextNode = node.nextSibling; 2441 if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue)) 2442 element.removeChild(node); 2443 node = nextNode; 2444 } 2445 return element; 2446 } 2447 2448 function empty(element) { 2449 return $(element).innerHTML.blank(); 2450 } 2451 2452 function getContentFromAnonymousElement(tagName, html, force) { 2453 var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV; 2454 2455 var workaround = !!t; 2456 if (!workaround && force) { 2457 workaround = true; 2458 t = ['', '', 0]; 2459 } 2460 2461 if (workaround) { 2462 div.innerHTML = ' ' + t[0] + html + t[1]; 2463 div.removeChild(div.firstChild); 2464 for (var i = t[2]; i--; ) 2465 div = div.firstChild; 2466 } else { 2467 div.innerHTML = html; 2468 } 2469 2470 return $A(div.childNodes); 2471 } 2472 2473 function clone(element, deep) { 2474 if (!(element = $(element))) return; 2475 var clone = element.cloneNode(deep); 2476 if (!HAS_UNIQUE_ID_PROPERTY) { 2477 clone._prototypeUID = UNDEFINED; 2478 if (deep) { 2479 var descendants = Element.select(clone, '*'), 2480 i = descendants.length; 2481 while (i--) 2482 descendants[i]._prototypeUID = UNDEFINED; 2483 } 2484 } 2485 return Element.extend(clone); 2486 } 2487 2488 function purgeElement(element) { 2489 var uid = getUniqueElementID(element); 2490 if (uid) { 2491 Element.stopObserving(element); 2492 if (!HAS_UNIQUE_ID_PROPERTY) 2493 element._prototypeUID = UNDEFINED; 2494 delete Element.Storage[uid]; 2495 } 2496 } 2497 2498 function purgeCollection(elements) { 2499 var i = elements.length; 2500 while (i--) 2501 purgeElement(elements[i]); 2502 } 2503 2504 function purgeCollection_IE(elements) { 2505 var i = elements.length, element, uid; 2506 while (i--) { 2507 element = elements[i]; 2508 uid = getUniqueElementID(element); 2509 delete Element.Storage[uid]; 2510 delete Event.cache[uid]; 2511 } 2512 } 2513 2514 if (HAS_UNIQUE_ID_PROPERTY) { 2515 purgeCollection = purgeCollection_IE; 2516 } 2517 2518 2519 function purge(element) { 2520 if (!(element = $(element))) return; 2521 purgeElement(element); 2522 2523 var descendants = element.getElementsByTagName('*'), 2524 i = descendants.length; 2525 2526 while (i--) purgeElement(descendants[i]); 2527 2528 return null; 2529 } 2530 2531 Object.extend(methods, { 2532 remove: remove, 2533 update: update, 2534 replace: replace, 2535 insert: insert, 2536 wrap: wrap, 2537 cleanWhitespace: cleanWhitespace, 2538 empty: empty, 2539 clone: clone, 2540 purge: purge 2541 }); 2542 2543 2544 2545 function recursivelyCollect(element, property, maximumLength) { 2546 element = $(element); 2547 maximumLength = maximumLength || -1; 2548 var elements = []; 2549 2550 while (element = element[property]) { 2551 if (element.nodeType === Node.ELEMENT_NODE) 2552 elements.push(Element.extend(element)); 2553 2554 if (elements.length === maximumLength) break; 2555 } 2556 2557 return elements; 2558 } 2559 2560 2561 function ancestors(element) { 2562 return recursivelyCollect(element, 'parentNode'); 2563 } 2564 2565 function descendants(element) { 2566 return Element.select(element, '*'); 2567 } 2568 2569 function firstDescendant(element) { 2570 element = $(element).firstChild; 2571 while (element && element.nodeType !== Node.ELEMENT_NODE) 2572 element = element.nextSibling; 2573 2574 return $(element); 2575 } 2576 2577 function immediateDescendants(element) { 2578 var results = [], child = $(element).firstChild; 2579 2580 while (child) { 2581 if (child.nodeType === Node.ELEMENT_NODE) 2582 results.push(Element.extend(child)); 2583 2584 child = child.nextSibling; 2585 } 2586 2587 return results; 2588 } 2589 2590 function previousSiblings(element) { 2591 return recursivelyCollect(element, 'previousSibling'); 2592 } 2593 2594 function nextSiblings(element) { 2595 return recursivelyCollect(element, 'nextSibling'); 2596 } 2597 2598 function siblings(element) { 2599 element = $(element); 2600 var previous = previousSiblings(element), 2601 next = nextSiblings(element); 2602 return previous.reverse().concat(next); 2603 } 2604 2605 function match(element, selector) { 2606 element = $(element); 2607 2608 if (Object.isString(selector)) 2609 return Prototype.Selector.match(element, selector); 2610 2611 return selector.match(element); 2612 } 2613 2614 2615 function _recursivelyFind(element, property, expression, index) { 2616 element = $(element), expression = expression || 0, index = index || 0; 2617 if (Object.isNumber(expression)) { 2618 index = expression, expression = null; 2619 } 2620 2621 while (element = element[property]) { 2622 if (element.nodeType !== 1) continue; 2623 if (expression && !Prototype.Selector.match(element, expression)) 2624 continue; 2625 if (--index >= 0) continue; 2626 2627 return Element.extend(element); 2628 } 2629 } 2630 2631 2632 function up(element, expression, index) { 2633 element = $(element); 2634 2635 if (arguments.length === 1) return $(element.parentNode); 2636 return _recursivelyFind(element, 'parentNode', expression, index); 2637 } 2638 2639 function down(element, expression, index) { 2640 if (arguments.length === 1) return firstDescendant(element); 2641 element = $(element), expression = expression || 0, index = index || 0; 2642 2643 if (Object.isNumber(expression)) 2644 index = expression, expression = '*'; 2645 2646 var node = Prototype.Selector.select(expression, element)[index]; 2647 return Element.extend(node); 2648 } 2649 2650 function previous(element, expression, index) { 2651 return _recursivelyFind(element, 'previousSibling', expression, index); 2652 } 2653 2654 function next(element, expression, index) { 2655 return _recursivelyFind(element, 'nextSibling', expression, index); 2656 } 2657 2658 function select(element) { 2659 element = $(element); 2660 var expressions = SLICE.call(arguments, 1).join(', '); 2661 return Prototype.Selector.select(expressions, element); 2662 } 2663 2664 function adjacent(element) { 2665 element = $(element); 2666 var expressions = SLICE.call(arguments, 1).join(', '); 2667 var siblings = Element.siblings(element), results = []; 2668 for (var i = 0, sibling; sibling = siblings[i]; i++) { 2669 if (Prototype.Selector.match(sibling, expressions)) 2670 results.push(sibling); 2671 } 2672 2673 return results; 2674 } 2675 2676 function descendantOf_DOM(element, ancestor) { 2677 element = $(element), ancestor = $(ancestor); 2678 if (!element || !ancestor) return false;
2679 while (element = element.parentNode) 2680 if (element === ancestor) return true; 2681 return false; 2682 } 2683 2684 function descendantOf_contains(element, ancestor) { 2685 element = $(element), ancestor = $(ancestor); 2686 if (!element || !ancestor) return false; 2687 if (!ancestor.contains) return descendantOf_DOM(element, ancestor); 2688 return ancestor.contains(element) && ancestor !== element; 2689 } 2690 2691 function descendantOf_compareDocumentPosition(element, ancestor) { 2692 element = $(element), ancestor = $(ancestor); 2693 if (!element || !ancestor) return false; 2694 return (element.compareDocumentPosition(ancestor) & 8) === 8; 2695 } 2696 2697 var descendantOf; 2698 if (DIV.compareDocumentPosition) { 2699 descendantOf = descendantOf_compareDocumentPosition; 2700 } else if (DIV.contains) { 2701 descendantOf = descendantOf_contains; 2702 } else { 2703 descendantOf = descendantOf_DOM; 2704 } 2705 2706 2707 Object.extend(methods, { 2708 recursivelyCollect: recursivelyCollect, 2709 ancestors: ancestors, 2710 descendants: descendants, 2711 firstDescendant: firstDescendant, 2712 immediateDescendants: immediateDescendants, 2713 previousSiblings: previousSiblings, 2714 nextSiblings: nextSiblings, 2715 siblings: siblings, 2716 match: match, 2717 up: up, 2718 down: down, 2719 previous: previous, 2720 next: next, 2721 select: select, 2722 adjacent: adjacent, 2723 descendantOf: descendantOf, 2724 2725 getElementsBySelector: select, 2726 2727 childElements: immediateDescendants 2728 }); 2729 2730 2731 var idCounter = 1; 2732 function identify(element) { 2733 element = $(element); 2734 var id = Element.readAttribute(element, 'id'); 2735 if (id) return id; 2736 2737 do { id = 'anonymous_element_' + idCounter++ } while ($(id)); 2738 2739 Element.writeAttribute(element, 'id', id); 2740 return id; 2741 } 2742 2743 2744 function readAttribute(element, name) { 2745 return $(element).getAttribute(name); 2746 } 2747 2748 function readAttribute_IE(element, name) { 2749 element = $(element); 2750 2751 var table = ATTRIBUTE_TRANSLATIONS.read; 2752 if (table.values[name]) 2753 return table.values[name](element, name); 2754 2755 if (table.names[name]) name = table.names[name]; 2756 2757 if (name.include(':')) { 2758 if (!element.attributes || !element.attributes[name]) return null; 2759 return element.attributes[name].value; 2760 } 2761 2762 return element.getAttribute(name); 2763 } 2764 2765 function readAttribute_Opera(element, name) { 2766 if (name === 'title') return element.title; 2767 return element.getAttribute(name); 2768 } 2769 2770 var PROBLEMATIC_ATTRIBUTE_READING = (function() { 2771 DIV.setAttribute('onclick', []); 2772 var value = DIV.getAttribute('onclick'); 2773 var isFunction = Object.isArray(value); 2774 DIV.removeAttribute('onclick'); 2775 return isFunction; 2776 })(); 2777 2778 if (PROBLEMATIC_ATTRIBUTE_READING) { 2779 readAttribute = readAttribute_IE; 2780 } else if (Prototype.Browser.Opera) { 2781 readAttribute = readAttribute_Opera; 2782 } 2783 2784 2785 function writeAttribute(element, name, value) { 2786 element = $(element); 2787 var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write; 2788 2789 if (typeof name === 'object') { 2790 attributes = name; 2791 } else { 2792 attributes[name] = Object.isUndefined(value) ? true : value; 2793 } 2794 2795 for (var attr in attributes) { 2796 name = table.names[attr] || attr; 2797 value = attributes[attr]; 2798 if (table.values[attr]) { 2799 value = table.values[attr](element, value); 2800 if (Object.isUndefined(value)) continue; 2801 } 2802 if (value === false || value === null) 2803 element.removeAttribute(name); 2804 else if (value === true) 2805 element.setAttribute(name, name); 2806 else element.setAttribute(name, value); 2807 } 2808 2809 return element; 2810 } 2811 2812 var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () { 2813 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) { 2814 return false; 2815 } 2816 var checkbox = document.createElement('<input type="checkbox">'); 2817 checkbox.checked = true; 2818 var node = checkbox.getAttributeNode('checked'); 2819 return !node || !node.specified; 2820 })(); 2821 2822 function hasAttribute(element, attribute) { 2823 attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute; 2824 var node = $(element).getAttributeNode(attribute); 2825 return !!(node && node.specified); 2826 } 2827 2828 function hasAttribute_IE(element, attribute) { 2829 if (attribute === 'checked') { 2830 return element.checked; 2831 } 2832 return hasAttribute(element, attribute); 2833 } 2834 2835 GLOBAL.Element.Methods.Simulated.hasAttribute = 2836 PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ? 2837 hasAttribute_IE : hasAttribute; 2838 2839 function classNames(element) { 2840 return new Element.ClassNames(element); 2841 } 2842 2843 var regExpCache = {}; 2844 function getRegExpForClassName(className) { 2845 if (regExpCache[className]) return regExpCache[className]; 2846 2847 var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)"); 2848 regExpCache[className] = re; 2849 return re; 2850 } 2851 2852 function hasClassName(element, className) { 2853 if (!(element = $(element))) return; 2854 2855 var elementClassName = element.className; 2856 2857 if (elementClassName.length === 0) return false;
2858 if (elementClassName === className) return true; 2859 2860 return getRegExpForClassName(className).test(elementClassName); 2861 } 2862 2863 function addClassName(element, className) { 2864 if (!(element = $(element))) return; 2865 2866 if (!hasClassName(element, className)) 2867 element.className += (element.className ? ' ' : '') + className; 2868 2869 return element; 2870 } 2871 2872 function removeClassName(element, className) { 2873 if (!(element = $(element))) return; 2874 2875 element.className = element.className.replace( 2876 getRegExpForClassName(className), ' ').strip(); 2877 2878 return element; 2879 } 2880 2881 function toggleClassName(element, className, bool) { 2882 if (!(element = $(element))) return; 2883 2884 if (Object.isUndefined(bool)) 2885 bool = !hasClassName(element, className); 2886 2887 var method = Element[bool ? 'addClassName' : 'removeClassName']; 2888 return method(element, className); 2889 } 2890 2891 var ATTRIBUTE_TRANSLATIONS = {}; 2892 2893 var classProp = 'className', forProp = 'for'; 2894 2895 DIV.setAttribute(classProp, 'x'); 2896 if (DIV.className !== 'x') { 2897 DIV.setAttribute('class', 'x'); 2898 if (DIV.className === 'x') 2899 classProp = 'class'; 2900 } 2901 2902 var LABEL = document.createElement('label'); 2903 LABEL.setAttribute(forProp, 'x'); 2904 if (LABEL.htmlFor !== 'x') { 2905 LABEL.setAttribute('htmlFor', 'x'); 2906 if (LABEL.htmlFor === 'x') 2907 forProp = 'htmlFor'; 2908 } 2909 LABEL = null; 2910 2911 function _getAttr(element, attribute) { 2912 return element.getAttribute(attribute); 2913 } 2914 2915 function _getAttr2(element, attribute) { 2916 return element.getAttribute(attribute, 2); 2917 } 2918 2919 function _getAttrNode(element, attribute) { 2920 var node = element.getAttributeNode(attribute); 2921 return node ? node.value : ''; 2922 } 2923 2924 function _getFlag(element, attribute) { 2925 return $(element).hasAttribute(attribute) ? attribute : null; 2926 } 2927 2928 DIV.onclick = Prototype.emptyFunction; 2929 var onclickValue = DIV.getAttribute('onclick'); 2930 2931 var _getEv; 2932 2933 if (String(onclickValue).indexOf('{') > -1) { 2934 _getEv = function(element, attribute) { 2935 var value = element.getAttribute(attribute); 2936 if (!value) return null; 2937 value = value.toString(); 2938 value = value.split('{')[1]; 2939 value = value.split('}')[0]; 2940 return value.strip(); 2941 }; 2942 } 2943 else if (onclickValue === '') { 2944 _getEv = function(element, attribute) { 2945 var value = element.getAttribute(attribute); 2946 if (!value) return null; 2947 return value.strip(); 2948 }; 2949 } 2950 2951 ATTRIBUTE_TRANSLATIONS.read = { 2952 names: { 2953 'class': classProp, 2954 'className': classProp, 2955 'for': forProp, 2956 'htmlFor': forProp 2957 }, 2958 2959 values: { 2960 style: function(element) { 2961 return element.style.cssText.toLowerCase(); 2962 }, 2963 title: function(element) { 2964 return element.title; 2965 } 2966 } 2967 }; 2968 2969 ATTRIBUTE_TRANSLATIONS.write = { 2970 names: { 2971 className: 'class', 2972 htmlFor: 'for', 2973 cellpadding: 'cellPadding', 2974 cellspacing: 'cellSpacing' 2975 }, 2976 2977 values: { 2978 checked: function(element, value) { 2979 value = !!value; 2980 element.checked = value; 2981 return value ? 'checked' : null; 2982 }, 2983 2984 style: function(element, value) { 2985 element.style.cssText = value ? value : ''; 2986 } 2987 } 2988 }; 2989 2990 ATTRIBUTE_TRANSLATIONS.has = { names: {} }; 2991 2992 Object.extend(ATTRIBUTE_TRANSLATIONS.write.names, 2993 ATTRIBUTE_TRANSLATIONS.read.names); 2994 2995 var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' + 2996 'accessKey tabIndex encType maxLength readOnly longDesc frameBorder'); 2997 2998 for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) { 2999 ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr; 3000 ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()] = attr; 3001 } 3002 3003 Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, { 3004 href: _getAttr2, 3005 src: _getAttr2, 3006 type: _getAttr, 3007 action: _getAttrNode, 3008 disabled: _getFlag, 3009 checked: _getFlag, 3010 readonly: _getFlag, 3011 multiple: _getFlag, 3012 onload: _getEv, 3013 onunload: _getEv, 3014 onclick: _getEv, 3015 ondblclick: _getEv, 3016 onmousedown: _getEv, 3017 onmouseup: _getEv, 3018 onmouseover: _getEv, 3019 onmousemove: _getEv, 3020 onmouseout: _getEv, 3021 onfocus: _getEv, 3022 onblur: _getEv, 3023 onkeypress: _getEv, 3024 onkeydown: _getEv, 3025 onkeyup: _getEv, 3026 onsubmit: _getEv,
3027 onreset: _getEv, 3028 onselect: _getEv, 3029 onchange: _getEv 3030 }); 3031 3032 3033 Object.extend(methods, { 3034 identify: identify, 3035 readAttribute: readAttribute, 3036 writeAttribute: writeAttribute, 3037 classNames: classNames, 3038 hasClassName: hasClassName, 3039 addClassName: addClassName, 3040 removeClassName: removeClassName, 3041 toggleClassName: toggleClassName 3042 }); 3043 3044 3045 function normalizeStyleName(style) { 3046 if (style === 'float' || style === 'styleFloat') 3047 return 'cssFloat'; 3048 return style.camelize(); 3049 } 3050 3051 function normalizeStyleName_IE(style) { 3052 if (style === 'float' || style === 'cssFloat') 3053 return 'styleFloat'; 3054 return style.camelize(); 3055 } 3056 3057 function setStyle(element, styles) { 3058 element = $(element); 3059 var elementStyle = element.style, match; 3060 3061 if (Object.isString(styles)) { 3062 elementStyle.cssText += ';' + styles; 3063 if (styles.include('opacity')) { 3064 var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1]; 3065 Element.setOpacity(element, opacity); 3066 } 3067 return element; 3068 } 3069 3070 for (var property in styles) { 3071 if (property === 'opacity') { 3072 Element.setOpacity(element, styles[property]); 3073 } else { 3074 var value = styles[property]; 3075 if (property === 'float' || property === 'cssFloat') { 3076 property = Object.isUndefined(elementStyle.styleFloat) ? 3077 'cssFloat' : 'styleFloat'; 3078 } 3079 elementStyle[property] = value; 3080 } 3081 } 3082 3083 return element; 3084 } 3085 3086 3087 function getStyle(element, style) { 3088 element = $(element); 3089 style = normalizeStyleName(style); 3090 3091 var value = element.style[style]; 3092 if (!value || value === 'auto') { 3093 var css = document.defaultView.getComputedStyle(element, null); 3094 value = css ? css[style] : null; 3095 } 3096 3097 if (style === 'opacity') return value ? parseFloat(value) : 1.0; 3098 return value === 'auto' ? null : value; 3099 } 3100 3101 function getStyle_Opera(element, style) { 3102 switch (style) { 3103 case 'height': case 'width': 3104 if (!Element.visible(element)) return null; 3105 3106 var dim = parseInt(getStyle(element, style), 10); 3107 3108 if (dim !== element['offset' + style.capitalize()]) 3109 return dim + 'px'; 3110 3111 return Element.measure(element, style); 3112 3113 default: return getStyle(element, style); 3114 } 3115 } 3116 3117 function getStyle_IE(element, style) { 3118 element = $(element); 3119 style = normalizeStyleName_IE(style); 3120 3121 var value = element.style[style]; 3122 if (!value && element.currentStyle) { 3123 value = element.currentStyle[style]; 3124 } 3125 3126 if (style === 'opacity') { 3127 if (!STANDARD_CSS_OPACITY_SUPPORTED) 3128 return getOpacity_IE(element); 3129 else return value ? parseFloat(value) : 1.0; 3130 } 3131 3132 if (value === 'auto') { 3133 if ((style === 'width' || style === 'height') && Element.visible(element)) 3134 return Element.measure(element, style) + 'px'; 3135 return null; 3136 } 3137 3138 return value; 3139 } 3140 3141 function stripAlphaFromFilter_IE(filter) { 3142 return (filter || '').replace(/alpha\([^\)]*\)/gi, ''); 3143 } 3144 3145 function hasLayout_IE(element) { 3146 if (!element.currentStyle || !element.currentStyle.hasLayout) 3147 element.style.zoom = 1; 3148 return element; 3149 } 3150 3151 var STANDARD_CSS_OPACITY_SUPPORTED = (function() { 3152 DIV.style.cssText = "opacity:.55"; 3153 return /^0.55/.test(DIV.style.opacity); 3154 })(); 3155 3156 function setOpacity(element, value) { 3157 element = $(element); 3158 if (value == 1 || value === '') value = ''; 3159 else if (value < 0.00001) value = 0; 3160 element.style.opacity = value; 3161 return element; 3162 } 3163 3164 function setOpacity_IE(element, value) { 3165 if (STANDARD_CSS_OPACITY_SUPPORTED) 3166 return setOpacity(element, value); 3167 3168 element = hasLayout_IE($(element)); 3169 var filter = Element.getStyle(element, 'filter'), 3170 style = element.style; 3171 3172 if (value == 1 || value === '') { 3173 filter = stripAlphaFromFilter_IE(filter); 3174 if (filter) style.filter = filter; 3175 else style.removeAttribute('filter'); 3176 return element; 3177 } 3178 3179 if (value < 0.00001) value = 0; 3180 3181 style.filter = stripAlphaFromFilter_IE(filter) + 3182 ' alpha(opacity=' + (value * 100) + ')'; 3183 3184 return element; 3185 } 3186 3187 3188 function getOpacity(element) { 3189 return Element.getStyle(element, 'opacity'); 3190 } 3191 3192 function getOpacity_IE(element) { 3193 if (STANDARD_CSS_OPACITY_SUPPORTED) 3194 return getOpacity(element); 3195 3196 var filter = Element.getStyle(element, 'filter'); 3197 if (filter.length === 0) return 1.0; 3198 var match = (filter || '').match(/alpha\(opacity=(.*)\)/i); 3199 if (match && match[1]) return parseFloat(match[1]) / 100; 3200 return 1.0; 3201 } 3202 3203 3204 Object.extend(methods, { 3205 setStyle: setStyle, 3206 getStyle: getStyle, 3207 setOpacity: setOpacity, 3208 getOpacity: getOpacity 3209 }); 3210 3211 if ('styleFloat' in DIV.style) { 3212 methods.getStyle = getStyle_IE; 3213 methods.setOpacity = setOpacity_IE; 3214 methods.getOpacity = getOpacity_IE; 3215 } 3216 3217 var UID = 0; 3218 3219 GLOBAL.Element.Storage = { UID: 1 }; 3220 3221 function getUniqueElementID(element) { 3222 if (element === window) return 0; 3223 3224 if (typeof element._prototypeUID === 'undefined') 3225 element._prototypeUID = Element.Storage.UID++; 3226 return element._prototypeUID; 3227 } 3228 3229 function getUniqueElementID_IE(element) { 3230 if (element === window) return 0; 3231 if (element == document) return 1; 3232 return element.uniqueID; 3233 } 3234 3235 var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV); 3236 if (HAS_UNIQUE_ID_PROPERTY) 3237 getUniqueElementID = getUniqueElementID_IE; 3238 3239 function getStorage(element) { 3240 if (!(element = $(element))) return; 3241 3242 var uid = getUniqueElementID(element); 3243 3244 if (!Element.Storage[uid]) 3245 Element.Storage[uid] = $H(); 3246 3247 return Element.Storage[uid]; 3248 } 3249 3250 function store(element, key, value) { 3251 if (!(element = $(element))) return; 3252 var storage = getStorage(element); 3253 if (arguments.length === 2) { 3254 storage.update(key); 3255 } else { 3256 storage.set(key, value); 3257 } 3258 return element; 3259 } 3260 3261 function retrieve(element, key, defaultValue) { 3262 if (!(element = $(element))) return; 3263 var storage = getStorage(element), value = storage.get(key); 3264 3265 if (Object.isUndefined(value)) { 3266 storage.set(key, defaultValue); 3267 value = defaultValue; 3268 } 3269 3270 return value; 3271 } 3272 3273 3274 Object.extend(methods, { 3275 getStorage: getStorage, 3276 store: store, 3277 retrieve: retrieve 3278 }); 3279 3280 3281 var Methods = {}, ByTag = Element.Methods.ByTag, 3282 F = Prototype.BrowserFeatures; 3283 3284 if (!F.ElementExtensions && ('__proto__' in DIV)) { 3285 GLOBAL.HTMLElement = {}; 3286 GLOBAL.HTMLElement.prototype = DIV['__proto__']; 3287 F.ElementExtensions = true; 3288 } 3289 3290 function checkElementPrototypeDeficiency(tagName) { 3291 if (typeof window.Element === 'undefined') return false;
3292 if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false; 3293 var proto = window.Element.prototype; 3294 if (proto) { 3295 var id = '_' + (Math.random() + '').slice(2), 3296 el = document.createElement(tagName); 3297 proto[id] = 'x'; 3298 var isBuggy = (el[id] !== 'x'); 3299 delete proto[id]; 3300 el = null; 3301 return isBuggy; 3302 } 3303 3304 return false; 3305 } 3306 3307 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = 3308 checkElementPrototypeDeficiency('object'); 3309 3310 function extendElementWith(element, methods) { 3311 for (var property in methods) { 3312 var value = methods[property]; 3313 if (Object.isFunction(value) && !(property in element)) 3314 element[property] = value.methodize(); 3315 } 3316 } 3317 3318 var EXTENDED = {}; 3319 function elementIsExtended(element) { 3320 var uid = getUniqueElementID(element); 3321 return (uid in EXTENDED); 3322 } 3323 3324 function extend(element) { 3325 if (!element || elementIsExtended(element)) return element; 3326 if (element.nodeType !== Node.ELEMENT_NODE || element == window) 3327 return element; 3328 3329 var methods = Object.clone(Methods), 3330 tagName = element.tagName.toUpperCase(); 3331 3332 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 3333 3334 extendElementWith(element, methods); 3335 EXTENDED[getUniqueElementID(element)] = true; 3336 return element; 3337 } 3338 3339 function extend_IE8(element) { 3340 if (!element || elementIsExtended(element)) return element; 3341 3342 var t = element.tagName; 3343 if (t && (/^(?:object|applet|embed)$/i.test(t))) { 3344 extendElementWith(element, Element.Methods); 3345 extendElementWith(element, Element.Methods.Simulated); 3346 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); 3347 } 3348 3349 return element; 3350 } 3351 3352 if (F.SpecificElementExtensions) { 3353 extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K; 3354 } 3355 3356 function addMethodsToTagName(tagName, methods) { 3357 tagName = tagName.toUpperCase(); 3358 if (!ByTag[tagName]) ByTag[tagName] = {}; 3359 Object.extend(ByTag[tagName], methods); 3360 } 3361 3362 function mergeMethods(destination, methods, onlyIfAbsent) { 3363 if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false; 3364 for (var property in methods) { 3365 var value = methods[property]; 3366 if (!Object.isFunction(value)) continue; 3367 if (!onlyIfAbsent || !(property in destination)) 3368 destination[property] = value.methodize(); 3369 } 3370 } 3371 3372 function findDOMClass(tagName) { 3373 var klass; 3374 var trans = { 3375 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", 3376 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 3377 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 3378 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", 3379 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": 3380 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": 3381 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 3382 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": 3383 "FrameSet", "IFRAME": "IFrame" 3384 }; 3385 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 3386 if (window[klass]) return window[klass]; 3387 klass = 'HTML' + tagName + 'Element'; 3388 if (window[klass]) return window[klass]; 3389 klass = 'HTML' + tagName.capitalize() + 'Element'; 3390 if (window[klass]) return window[klass]; 3391 3392 var element = document.createElement(tagName), 3393 proto = element['__proto__'] || element.constructor.prototype; 3394 3395 element = null; 3396 return proto; 3397 } 3398 3399 function addMethods(methods) { 3400 if (arguments.length === 0) addFormMethods(); 3401 3402 if (arguments.length === 2) { 3403 var tagName = methods; 3404 methods = arguments[1]; 3405 } 3406 3407 if (!tagName) { 3408 Object.extend(Element.Methods, methods || {}); 3409 } else { 3410 if (Object.isArray(tagName)) { 3411 for (var i = 0, tag; tag = tagName[i]; i++) 3412 addMethodsToTagName(tag, methods); 3413 } else { 3414 addMethodsToTagName(tagName, methods); 3415 } 3416 } 3417 3418 var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype : 3419 Element.prototype; 3420 3421 if (F.ElementExtensions) { 3422 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods); 3423 mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true); 3424 } 3425 3426 if (F.SpecificElementExtensions) { 3427 for (var tag in Element.Methods.ByTag) { 3428 var klass = findDOMClass(tag); 3429 if (Object.isUndefined(klass)) continue; 3430 mergeMethods(klass.prototype, ByTag[tag]); 3431 } 3432 } 3433 3434 Object.extend(Element, Element.Methods);
3435 Object.extend(Element, Element.Methods.Simulated); 3436 delete Element.ByTag; 3437 delete Element.Simulated; 3438 3439 Element.extend.refresh(); 3440 3441 ELEMENT_CACHE = {}; 3442 } 3443 3444 Object.extend(GLOBAL.Element, { 3445 extend: extend, 3446 addMethods: addMethods 3447 }); 3448 3449 if (extend === Prototype.K) { 3450 GLOBAL.Element.extend.refresh = Prototype.emptyFunction; 3451 } else { 3452 GLOBAL.Element.extend.refresh = function() { 3453 if (Prototype.BrowserFeatures.ElementExtensions) return; 3454 Object.extend(Methods, Element.Methods); 3455 Object.extend(Methods, Element.Methods.Simulated); 3456 3457 EXTENDED = {}; 3458 }; 3459 } 3460 3461 function addFormMethods() { 3462 Object.extend(Form, Form.Methods); 3463 Object.extend(Form.Element, Form.Element.Methods); 3464 Object.extend(Element.Methods.ByTag, { 3465 "FORM": Object.clone(Form.Methods), 3466 "INPUT": Object.clone(Form.Element.Methods), 3467 "SELECT": Object.clone(Form.Element.Methods), 3468 "TEXTAREA": Object.clone(Form.Element.Methods), 3469 "BUTTON": Object.clone(Form.Element.Methods) 3470 }); 3471 } 3472 3473 Element.addMethods(methods); 3474 3475 function destroyCache_IE() { 3476 DIV = null; 3477 ELEMENT_CACHE = null; 3478 } 3479 3480 if (window.attachEvent) 3481 window.attachEvent('onunload', destroyCache_IE); 3482 3483})(this); 3484(function() { 3485 3486 function toDecimal(pctString) { 3487 var match = pctString.match(/^(\d+)%?$/i); 3488 if (!match) return null; 3489 return (Number(match[1]) / 100); 3490 } 3491 3492 function getRawStyle(element, style) { 3493 element = $(element); 3494 3495 var value = element.style[style]; 3496 if (!value || value === 'auto') { 3497 var css = document.defaultView.getComputedStyle(element, null); 3498 value = css ? css[style] : null; 3499 } 3500 3501 if (style === 'opacity') return value ? parseFloat(value) : 1.0; 3502 return value === 'auto' ? null : value; 3503 } 3504 3505 function getRawStyle_IE(element, style) { 3506 var value = element.style[style]; 3507 if (!value && element.currentStyle) { 3508 value = element.currentStyle[style]; 3509 } 3510 return value; 3511 } 3512 3513 function getContentWidth(element, context) { 3514 var boxWidth = element.offsetWidth; 3515 3516 var bl = getPixelValue(element, 'borderLeftWidth', context) || 0; 3517 var br = getPixelValue(element, 'borderRightWidth', context) || 0; 3518 var pl = getPixelValue(element, 'paddingLeft', context) || 0; 3519 var pr = getPixelValue(element, 'paddingRight', context) || 0; 3520 3521 return boxWidth - bl - br - pl - pr; 3522 } 3523 3524 if (!Object.isUndefined(document.documentElement.currentStyle) && !Prototype.Browser.Opera) { 3525 getRawStyle = getRawStyle_IE; 3526 } 3527 3528 3529 function getPixelValue(value, property, context) { 3530 var element = null; 3531 if (Object.isElement(value)) { 3532 element = value; 3533 value = getRawStyle(element, property); 3534 } 3535 3536 if (value === null || Object.isUndefined(value)) { 3537 return null; 3538 } 3539 3540 if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) { 3541 return window.parseFloat(value); 3542 } 3543 3544 var isPercentage = value.include('%'), isViewport = (context === document.viewport); 3545 3546 if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) { 3547 var style = element.style.left, rStyle = element.runtimeStyle.left; 3548 element.runtimeStyle.left = element.currentStyle.left; 3549 element.style.left = value || 0; 3550 value = element.style.pixelLeft; 3551 element.style.left = style; 3552 element.runtimeStyle.left = rStyle; 3553 3554 return value; 3555 } 3556 3557 if (element && isPercentage) { 3558 context = context || element.parentNode; 3559 var decimal = toDecimal(value), whole = null; 3560 3561 var isHorizontal = property.include('left') || property.include('right') || 3562 property.include('width'); 3563 3564 var isVertical = property.include('top') || property.include('bottom') || 3565 property.include('height'); 3566 3567 if (context === document.viewport) { 3568 if (isHorizontal) { 3569 whole = document.viewport.getWidth(); 3570 } else if (isVertical) { 3571 whole = document.viewport.getHeight(); 3572 } 3573 } else { 3574 if (isHorizontal) { 3575 whole = $(context).measure('width'); 3576 } else if (isVertical) { 3577 whole = $(context).measure('height'); 3578 } 3579 } 3580 3581 return (whole === null) ? 0 : whole * decimal; 3582 } 3583 3584 return 0; 3585 } 3586 3587 function toCSSPixels(number) { 3588 if (Object.isString(number) && number.endsWith('px')) 3589 return number; 3590 return number + 'px'; 3591 } 3592 3593 function isDisplayed(element) { 3594 while (element && element.parentNode) { 3595 var display = element.getStyle('display'); 3596 if (display === 'none') { 3597 return false;
3598 } 3599 element = $(element.parentNode); 3600 } 3601 return true; 3602 } 3603 3604 var hasLayout = Prototype.K; 3605 if ('currentStyle' in document.documentElement) { 3606 hasLayout = function(element) { 3607 if (!element.currentStyle.hasLayout) { 3608 element.style.zoom = 1; 3609 } 3610 return element; 3611 }; 3612 } 3613 3614 function cssNameFor(key) { 3615 if (key.include('border')) key = key + '-width'; 3616 return key.camelize(); 3617 } 3618 3619 Element.Layout = Class.create(Hash, { 3620 initialize: function($super, element, preCompute) { 3621 $super(); 3622 this.element = $(element); 3623 3624 Element.Layout.PROPERTIES.each( function(property) { 3625 this._set(property, null); 3626 }, this); 3627 3628 if (preCompute) { 3629 this._preComputing = true; 3630 this._begin(); 3631 Element.Layout.PROPERTIES.each( this._compute, this ); 3632 this._end(); 3633 this._preComputing = false; 3634 } 3635 }, 3636 3637 _set: function(property, value) { 3638 return Hash.prototype.set.call(this, property, value); 3639 }, 3640 3641 set: function(property, value) { 3642 throw "Properties of Element.Layout are read-only."; 3643 }, 3644 3645 get: function($super, property) { 3646 var value = $super(property); 3647 return value === null ? this._compute(property) : value; 3648 }, 3649 3650 _begin: function() { 3651 if (this._isPrepared()) return; 3652 3653 var element = this.element; 3654 if (isDisplayed(element)) { 3655 this._setPrepared(true); 3656 return; 3657 } 3658 3659 3660 var originalStyles = { 3661 position: element.style.position || '', 3662 width: element.style.width || '', 3663 visibility: element.style.visibility || '', 3664 display: element.style.display || '' 3665 }; 3666 3667 element.store('prototype_original_styles', originalStyles); 3668 3669 var position = getRawStyle(element, 'position'), width = element.offsetWidth; 3670 3671 if (width === 0 || width === null) { 3672 element.style.display = 'block'; 3673 width = element.offsetWidth; 3674 } 3675 3676 var context = (position === 'fixed') ? document.viewport : 3677 element.parentNode; 3678 3679 var tempStyles = { 3680 visibility: 'hidden', 3681 display: 'block' 3682 }; 3683 3684 if (position !== 'fixed') tempStyles.position = 'absolute'; 3685 3686 element.setStyle(tempStyles); 3687 3688 var positionedWidth = element.offsetWidth, newWidth; 3689 if (width && (positionedWidth === width)) { 3690 newWidth = getContentWidth(element, context); 3691 } else if (position === 'absolute' || position === 'fixed') { 3692 newWidth = getContentWidth(element, context); 3693 } else { 3694 var parent = element.parentNode, pLayout = $(parent).getLayout(); 3695 3696 newWidth = pLayout.get('width') - 3697 this.get('margin-left') - 3698 this.get('border-left') - 3699 this.get('padding-left') - 3700 this.get('padding-right') - 3701 this.get('border-right') - 3702 this.get('margin-right'); 3703 } 3704 3705 element.setStyle({ width: newWidth + 'px' }); 3706 3707 this._setPrepared(true); 3708 }, 3709 3710 _end: function() { 3711 var element = this.element; 3712 var originalStyles = element.retrieve('prototype_original_styles'); 3713 element.store('prototype_original_styles', null); 3714 element.setStyle(originalStyles); 3715 this._setPrepared(false); 3716 }, 3717 3718 _compute: function(property) { 3719 var COMPUTATIONS = Element.Layout.COMPUTATIONS; 3720 if (!(property in COMPUTATIONS)) { 3721 throw "Property not found."; 3722 } 3723 3724 return this._set(property, COMPUTATIONS[property].call(this, this.element)); 3725 }, 3726 3727 _isPrepared: function() { 3728 return this.element.retrieve('prototype_element_layout_prepared', false); 3729 }, 3730 3731 _setPrepared: function(bool) { 3732 return this.element.store('prototype_element_layout_prepared', bool); 3733 }, 3734 3735 toObject: function() { 3736 var args = $A(arguments); 3737 var keys = (args.length === 0) ? Element.Layout.PROPERTIES : 3738 args.join(' ').split(' '); 3739 var obj = {}; 3740 keys.each( function(key) { 3741 if (!Element.Layout.PROPERTIES.include(key)) return; 3742 var value = this.get(key); 3743 if (value != null) obj[key] = value; 3744 }, this); 3745 return obj; 3746 }, 3747 3748 toHash: function() { 3749 var obj = this.toObject.apply(this, arguments); 3750 return new Hash(obj); 3751 }, 3752 3753 toCSS: function() { 3754 var args = $A(arguments); 3755 var keys = (args.length === 0) ? Element.Layout.PROPERTIES : 3756 args.join(' ').split(' '); 3757 var css = {}; 3758 3759 keys.each( function(key) { 3760 if (!Element.Layout.PROPERTIES.include(key)) return; 3761 if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return; 3762 3763 var value = this.get(key);
3764 if (value != null) css[cssNameFor(key)] = value + 'px'; 3765 }, this); 3766 return css; 3767 }, 3768 3769 inspect: function() { 3770 return "#<Element.Layout>"; 3771 } 3772 }); 3773 3774 Object.extend(Element.Layout, { 3775 PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'), 3776 3777 COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'), 3778 3779 COMPUTATIONS: { 3780 'height': function(element) { 3781 if (!this._preComputing) this._begin(); 3782 3783 var bHeight = this.get('border-box-height'); 3784 if (bHeight <= 0) { 3785 if (!this._preComputing) this._end(); 3786 return 0; 3787 } 3788 3789 var bTop = this.get('border-top'), 3790 bBottom = this.get('border-bottom'); 3791 3792 var pTop = this.get('padding-top'), 3793 pBottom = this.get('padding-bottom'); 3794 3795 if (!this._preComputing) this._end(); 3796 3797 return bHeight - bTop - bBottom - pTop - pBottom; 3798 }, 3799 3800 'width': function(element) { 3801 if (!this._preComputing) this._begin(); 3802 3803 var bWidth = this.get('border-box-width'); 3804 if (bWidth <= 0) { 3805 if (!this._preComputing) this._end(); 3806 return 0; 3807 } 3808 3809 var bLeft = this.get('border-left'), 3810 bRight = this.get('border-right'); 3811 3812 var pLeft = this.get('padding-left'), 3813 pRight = this.get('padding-right'); 3814 3815 if (!this._preComputing) this._end(); 3816 return bWidth - bLeft - bRight - pLeft - pRight; 3817 }, 3818 3819 'padding-box-height': function(element) { 3820 var height = this.get('height'), 3821 pTop = this.get('padding-top'), 3822 pBottom = this.get('padding-bottom'); 3823 3824 return height + pTop + pBottom; 3825 }, 3826 3827 'padding-box-width': function(element) { 3828 var width = this.get('width'), 3829 pLeft = this.get('padding-left'), 3830 pRight = this.get('padding-right'); 3831 3832 return width + pLeft + pRight; 3833 }, 3834 3835 'border-box-height': function(element) { 3836 if (!this._preComputing) this._begin(); 3837 var height = element.offsetHeight; 3838 if (!this._preComputing) this._end(); 3839 return height; 3840 }, 3841 3842 'border-box-width': function(element) { 3843 if (!this._preComputing) this._begin(); 3844 var width = element.offsetWidth; 3845 if (!this._preComputing) this._end(); 3846 return width; 3847 }, 3848 3849 'margin-box-height': function(element) { 3850 var bHeight = this.get('border-box-height'), 3851 mTop = this.get('margin-top'), 3852 mBottom = this.get('margin-bottom'); 3853 3854 if (bHeight <= 0) return 0; 3855 3856 return bHeight + mTop + mBottom; 3857 }, 3858 3859 'margin-box-width': function(element) { 3860 var bWidth = this.get('border-box-width'), 3861 mLeft = this.get('margin-left'), 3862 mRight = this.get('margin-right'); 3863 3864 if (bWidth <= 0) return 0; 3865 3866 return bWidth + mLeft + mRight; 3867 }, 3868 3869 'top': function(element) { 3870 var offset = element.positionedOffset(); 3871 return offset.top; 3872 }, 3873 3874 'bottom': function(element) { 3875 var offset = element.positionedOffset(), 3876 parent = element.getOffsetParent(), 3877 pHeight = parent.measure('height'); 3878 3879 var mHeight = this.get('border-box-height'); 3880 3881 return pHeight - mHeight - offset.top; 3882 }, 3883 3884 'left': function(element) { 3885 var offset = element.positionedOffset(); 3886 return offset.left; 3887 }, 3888 3889 'right': function(element) { 3890 var offset = element.positionedOffset(), 3891 parent = element.getOffsetParent(), 3892 pWidth = parent.measure('width'); 3893 3894 var mWidth = this.get('border-box-width'); 3895 3896 return pWidth - mWidth - offset.left; 3897 }, 3898 3899 'padding-top': function(element) { 3900 return getPixelValue(element, 'paddingTop'); 3901 }, 3902 3903 'padding-bottom': function(element) { 3904 return getPixelValue(element, 'paddingBottom'); 3905 }, 3906 3907 'padding-left': function(element) { 3908 return getPixelValue(element, 'paddingLeft'); 3909 }, 3910 3911 'padding-right': function(element) { 3912 return getPixelValue(element, 'paddingRight'); 3913 }, 3914 3915 'border-top': function(element) { 3916 return getPixelValue(element, 'borderTopWidth'); 3917 }, 3918 3919 'border-bottom': function(element) { 3920 return getPixelValue(element, 'borderBottomWidth'); 3921 }, 3922 3923 'border-left': function(element) { 3924 return getPixelValue(element, 'borderLeftWidth'); 3925 }, 3926 3927 'border-right': function(element) { 3928 return getPixelValue(element, 'borderRightWidth'); 3929 }, 3930 3931 'margin-top': function(element) { 3932 return getPixelValue(element, 'marginTop'); 3933 }, 3934 3935 'margin-bottom': function(element) { 3936 return getPixelValue(element, 'marginBottom'); 3937 }, 3938 3939 'margin-left': function(element) { 3940 return getPixelValue(element, 'marginLeft'); 3941 }, 3942 3943 'margin-right': function(element) { 3944 return getPixelValue(element, 'marginRight'); 3945 } 3946 } 3947 }); 3948 3949 if ('getBoundingClientRect' in document.documentElement) { 3950 Object.extend(Element.Layout.COMPUTATIONS, { 3951 'right': function(element) { 3952 var parent = hasLayout(element.getOffsetParent()); 3953 var rect = element.getBoundingClientRect(), 3954 pRect = parent.getBoundingClientRect(); 3955 3956 return (pRect.right - rect.right).round(); 3957 }, 3958 3959 'bottom': function(element) { 3960 var parent = hasLayout(element.getOffsetParent()); 3961 var rect = element.getBoundingClientRect(), 3962 pRect = parent.getBoundingClientRect(); 3963 3964 return (pRect.bottom - rect.bottom).round(); 3965 } 3966 }); 3967 } 3968 3969 Element.Offset = Class.create({ 3970 initialize: function(left, top) { 3971 this.left = left.round(); 3972 this.top = top.round(); 3973 3974 this[0] = this.left; 3975 this[1] = this.top; 3976 }, 3977 3978 relativeTo: function(offset) { 3979 return new Element.Offset( 3980 this.left - offset.left, 3981 this.top - offset.top 3982 ); 3983 }, 3984 3985 inspect: function() { 3986 return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this); 3987 }, 3988 3989 toString: function() { 3990 return "[#{left}, #{top}]".interpolate(this); 3991 }, 3992 3993 toArray: function() { 3994 return [this.left, this.top]; 3995 } 3996 }); 3997 3998 function getLayout(element, preCompute) { 3999 return new Element.Layout(element, preCompute); 4000 } 4001 4002 function measure(element, property) { 4003 return $(element).getLayout().get(property); 4004 } 4005 4006 function getHeight(element) { 4007 return Element.getDimensions(element).height; 4008 } 4009 4010 function getWidth(element) { 4011 return Element.getDimensions(element).width; 4012 } 4013 4014 function getDimensions(element) { 4015 element = $(element); 4016 var display = Element.getStyle(element, 'display'); 4017 4018 if (display && display !== 'none') { 4019 return { width: element.offsetWidth, height: element.offsetHeight }; 4020 } 4021 4022 var style = element.style; 4023 var originalStyles = { 4024 visibility: style.visibility, 4025 position: style.position, 4026 display: style.display 4027 }; 4028 4029 var newStyles = { 4030 visibility: 'hidden', 4031 display: 'block' 4032 }; 4033 4034 if (originalStyles.position !== 'fixed') 4035 newStyles.position = 'absolute'; 4036 4037 Element.setStyle(element, newStyles); 4038 4039 var dimensions = { 4040 width: element.offsetWidth, 4041 height: element.offsetHeight 4042 }; 4043 Element.setStyle(element, originalStyles); 4044 4045 return dimensions; 4046 } 4047 4048 function getOffsetParent(element) { 4049 element = $(element); 4050 4051 function selfOrBody(element) { 4052 return isHtml(element) ? $(document.body) : $(element); 4053 } 4054 4055 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) 4056 return $(document.body); 4057
4058 var isInline = (Element.getStyle(element, 'display') === 'inline'); 4059 if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent); 4060 4061 while ((element = element.parentNode) && element !== document.body) { 4062 if (Element.getStyle(element, 'position') !== 'static') { 4063 return selfOrBody(element); 4064 } 4065 } 4066 4067 return $(document.body); 4068 } 4069 4070 4071 function cumulativeOffset(element) { 4072 element = $(element); 4073 var valueT = 0, valueL = 0; 4074 if (element.parentNode) { 4075 do { 4076 valueT += element.offsetTop || 0; 4077 valueL += element.offsetLeft || 0; 4078 element = element.offsetParent; 4079 } while (element); 4080 } 4081 return new Element.Offset(valueL, valueT); 4082 } 4083 4084 function positionedOffset(element) { 4085 element = $(element); 4086 4087 var layout = element.getLayout(); 4088 4089 var valueT = 0, valueL = 0; 4090 do { 4091 valueT += element.offsetTop || 0; 4092 valueL += element.offsetLeft || 0; 4093 element = element.offsetParent; 4094 if (element) { 4095 if (isBody(element)) break; 4096 var p = Element.getStyle(element, 'position'); 4097 if (p !== 'static') break; 4098 } 4099 } while (element); 4100 4101 valueL -= layout.get('margin-left'); 4102 valueT -= layout.get('margin-top'); 4103 4104 return new Element.Offset(valueL, valueT); 4105 } 4106 4107 function cumulativeScrollOffset(element) { 4108 var valueT = 0, valueL = 0; 4109 do { 4110 if (element === document.body) { 4111 var bodyScrollNode = document.documentElement || document.body.parentNode || document.body; 4112 valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0; 4113 valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0; 4114 break; 4115 } else { 4116 valueT += element.scrollTop || 0; 4117 valueL += element.scrollLeft || 0; 4118 element = element.parentNode; 4119 } 4120 } while (element); 4121 return new Element.Offset(valueL, valueT); 4122 } 4123 4124 function viewportOffset(forElement) { 4125 var valueT = 0, valueL = 0, docBody = document.body; 4126 4127 forElement = $(forElement); 4128 var element = forElement; 4129 do { 4130 valueT += element.offsetTop || 0; 4131 valueL += element.offsetLeft || 0; 4132 if (element.offsetParent == docBody && 4133 Element.getStyle(element, 'position') == 'absolute') break; 4134 } while (element = element.offsetParent); 4135 4136 element = forElement; 4137 do { 4138 if (element != docBody) { 4139 valueT -= element.scrollTop || 0; 4140 valueL -= element.scrollLeft || 0; 4141 } 4142 } while (element = element.parentNode); 4143 return new Element.Offset(valueL, valueT); 4144 } 4145 4146 function absolutize(element) { 4147 element = $(element); 4148 4149 if (Element.getStyle(element, 'position') === 'absolute') { 4150 return element; 4151 } 4152 4153 var offsetParent = getOffsetParent(element); 4154 var eOffset = element.viewportOffset(), 4155 pOffset = offsetParent.viewportOffset(); 4156 4157 var offset = eOffset.relativeTo(pOffset); 4158 var layout = element.getLayout(); 4159 4160 element.store('prototype_absolutize_original_styles', { 4161 position: element.getStyle('position'), 4162 left: element.getStyle('left'), 4163 top: element.getStyle('top'), 4164 width: element.getStyle('width'), 4165 height: element.getStyle('height') 4166 }); 4167 4168 element.setStyle({ 4169 position: 'absolute', 4170 top: offset.top + 'px', 4171 left: offset.left + 'px', 4172 width: layout.get('width') + 'px', 4173 height: layout.get('height') + 'px' 4174 }); 4175 4176 return element; 4177 } 4178 4179 function relativize(element) { 4180 element = $(element); 4181 if (Element.getStyle(element, 'position') === 'relative') { 4182 return element; 4183 } 4184 4185 var originalStyles = 4186 element.retrieve('prototype_absolutize_original_styles'); 4187 4188 if (originalStyles) element.setStyle(originalStyles); 4189 return element; 4190 } 4191 4192 4193 function scrollTo(element) { 4194 element = $(element); 4195 var pos = Element.cumulativeOffset(element); 4196 window.scrollTo(pos.left, pos.top); 4197 return element; 4198 } 4199 4200 4201 function makePositioned(element) { 4202 element = $(element); 4203 var position = Element.getStyle(element, 'position'), styles = {}; 4204 if (position === 'static' || !position) { 4205 styles.position = 'relative'; 4206 if (Prototype.Browser.Opera) { 4207 styles.top = 0; 4208 styles.left = 0; 4209 } 4210 Element.setStyle(element, styles); 4211 Element.store(element, 'prototype_made_positioned', true); 4212 } 4213 return element; 4214 } 4215 4216 function undoPositioned(element) { 4217 element = $(element); 4218 var storage = Element.getStorage(element), 4219 madePositioned = storage.get('prototype_made_positioned'); 4220 4221 if (madePositioned) { 4222 storage.unset('prototype_made_positioned'); 4223 Element.setStyle(element, { 4224 position: '', 4225 top: '', 4226 bottom: '', 4227 left: '', 4228 right: '' 4229 }); 4230 } 4231 return element; 4232 } 4233 4234 function makeClipping(element) { 4235 element = $(element); 4236 4237 var storage = Element.getStorage(element), 4238 madeClipping = storage.get('prototype_made_clipping'); 4239 4240 if (Object.isUndefined(madeClipping)) { 4241 var overflow = Element.getStyle(element, 'overflow'); 4242 storage.set('prototype_made_clipping', overflow); 4243 if (overflow !== 'hidden') 4244 element.style.overflow = 'hidden'; 4245 } 4246 4247 return element; 4248 } 4249 4250 function undoClipping(element) { 4251 element = $(element); 4252 var storage = Element.getStorage(element), 4253 overflow = storage.get('prototype_made_clipping'); 4254 4255 if (!Object.isUndefined(overflow)) { 4256 storage.unset('prototype_made_clipping'); 4257 element.style.overflow = overflow || ''; 4258 } 4259 4260 return element; 4261 } 4262 4263 function clonePosition(element, source, options) { 4264 options = Object.extend({ 4265 setLeft: true, 4266 setTop: true, 4267 setWidth: true, 4268 setHeight: true, 4269 offsetTop: 0, 4270 offsetLeft: 0 4271 }, options || {}); 4272 4273 var docEl = document.documentElement; 4274 4275 source = $(source); 4276 element = $(element); 4277 var p, delta, layout, styles = {}; 4278 4279 if (options.setLeft || options.setTop) { 4280 p = Element.viewportOffset(source); 4281 delta = [0, 0]; 4282 if (Element.getStyle(element, 'position') === 'absolute') { 4283 var parent = Element.getOffsetParent(element); 4284 if (parent !== document.body) delta = Element.viewportOffset(parent); 4285 } 4286 } 4287 4288 function pageScrollXY() { 4289 var x = 0, y = 0; 4290 if (Object.isNumber(window.pageXOffset)) { 4291 x = window.pageXOffset; 4292 y = window.pageYOffset; 4293 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 4294 x = document.body.scrollLeft; 4295 y = document.body.scrollTop; 4296 } else if (docEl && (docEl.scrollLeft || docEl.scrollTop)) { 4297 x = docEl.scrollLeft; 4298 y = docEl.scrollTop; 4299 } 4300 return { x: x, y: y }; 4301 } 4302 4303 4304 var pageXY = pageScrollXY(); 4305 if (options.setWidth || options.setHeight) { 4306 layout = Element.getLayout(source); 4307 } 4308 4309 if (options.setLeft) 4310 styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px'; 4311 if (options.setTop) { 4312 if (Element.getStyle(element, 'position') === 'absolute') { 4313 styles.top = '0px'; 4314 } else { 4315 styles.top = (p[1] + pageXY.y - delta[1] + options.offsetTop) + 'px'; 4316 } 4317 } 4318 4319 var currentLayout = element.getLayout(); 4320 if (options.setWidth) { 4321 var padding_left = layout.get('padding-left'); 4322 var padding_right = layout.get('padding-right'); 4323 styles.width = (layout.get('width') + padding_left + padding_right) + 'px'; 4324 } 4325 if (options.setHeight) { 4326 styles.height = layout.get('height') + 'px'; 4327 } 4328 4329 return Element.setStyle(element, styles); 4330 } 4331 4332 4333 if (Prototype.Browser.IE) { 4334 getOffsetParent = getOffsetParent.wrap( 4335 function(proceed, element) { 4336 element = $(element); 4337 4338 if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) 4339 return $(document.body); 4340 4341 var position = element.getStyle('position'); 4342 if (position !== 'static') return proceed(element); 4343 4344 element.setStyle({ position: 'relative' }); 4345 var value = proceed(element); 4346 element.setStyle({ position: position }); 4347 return value; 4348 } 4349 ); 4350 4351 positionedOffset = positionedOffset.wrap(function(proceed, element) { 4352 element = $(element); 4353 if (!element.parentNode) return new Element.Offset(0, 0); 4354 var position = element.getStyle('position'); 4355 if (position !== 'static') return proceed(element); 4356 4357 var offsetParent = element.getOffsetParent(); 4358 if (offsetParent && offsetParent.getStyle('position') === 'fixed') 4359 hasLayout(offsetParent); 4360 4361 element.setStyle({ position: 'relative' }); 4362 var value = proceed(element); 4363 element.setStyle({ position: position }); 4364 return value; 4365 }); 4366 } else if (Prototype.Browser.Webkit) { 4367 cumulativeOffset = function(element) { 4368 element = $(element); 4369 var valueT = 0, valueL = 0; 4370 do { 4371 valueT += element.offsetTop || 0; 4372 valueL += element.offsetLeft || 0; 4373 if (element.offsetParent == document.body) { 4374 if (Element.getStyle(element, 'position') == 'absolute') break; 4375 } 4376 4377 element = element.offsetParent; 4378 } while (element); 4379 4380 return new Element.Offset(valueL, valueT); 4381 }; 4382 } 4383 4384 4385 Element.addMethods({ 4386 getLayout: getLayout, 4387 measure: measure, 4388 getWidth: getWidth, 4389 getHeight: getHeight, 4390 getDimensions: getDimensions, 4391 getOffsetParent: getOffsetParent, 4392 cumulativeOffset: cumulativeOffset, 4393 positionedOffset: positionedOffset, 4394 cumulativeScrollOffset: cumulativeScrollOffset, 4395 viewportOffset: viewportOffset, 4396 absolutize: absolutize, 4397 relativize: relativize, 4398 scrollTo: scrollTo, 4399 makePositioned: makePositioned, 4400 undoPositioned: undoPositioned, 4401 makeClipping: makeClipping, 4402 undoClipping: undoClipping, 4403 clonePosition: clonePosition 4404 }); 4405 4406 function isBody(element) { 4407 return element.nodeName.toUpperCase() === 'BODY'; 4408 } 4409 4410 function isHtml(element) { 4411 return element.nodeName.toUpperCase() === 'HTML'; 4412 } 4413 4414 function isDocument(element) { 4415 return element.nodeType === Node.DOCUMENT_NODE; 4416 } 4417 4418 function isDetached(element) { 4419 return element !== document.body && 4420 !Element.descendantOf(element, document.body); 4421 } 4422 4423 if ('getBoundingClientRect' in document.documentElement) { 4424 Element.addMethods({ 4425 viewportOffset: function(element) { 4426 element = $(element); 4427 if (isDetached(element)) return new Element.Offset(0, 0); 4428 4429 var rect = element.getBoundingClientRect(), 4430 docEl = document.documentElement; 4431 return new Element.Offset(rect.left - docEl.clientLeft, 4432 rect.top - docEl.clientTop); 4433 } 4434 }); 4435 } 4436 4437 4438})(); 4439 4440(function() { 4441 4442 var IS_OLD_OPERA = Prototype.Browser.Opera && 4443 (window.parseFloat(window.opera.version()) < 9.5); 4444 var ROOT = null; 4445 function getRootElement() { 4446 if (ROOT) return ROOT; 4447 ROOT = IS_OLD_OPERA ? document.body : document.documentElement; 4448 return ROOT; 4449 } 4450 4451 function getDimensions() { 4452 return { width: this.getWidth(), height: this.getHeight() }; 4453 } 4454 4455 function getWidth() { 4456 return getRootElement().clientWidth; 4457 } 4458 4459 function getHeight() { 4460 return getRootElement().clientHeight; 4461 } 4462 4463 function getScrollOffsets() { 4464 var x = window.pageXOffset || document.documentElement.scrollLeft || 4465 document.body.scrollLeft; 4466 var y = window.pageYOffset || document.documentElement.scrollTop || 4467 document.body.scrollTop; 4468 4469 return new Element.Offset(x, y); 4470 } 4471 4472 document.viewport = { 4473 getDimensions: getDimensions, 4474 getWidth: getWidth, 4475 getHeight: getHeight, 4476 getScrollOffsets: getScrollOffsets 4477 }; 4478 4479})(); 4480window.$$ = function() { 4481 var expression = $A(arguments).join(', '); 4482 return Prototype.Selector.select(expression, document); 4483}; 4484 4485Prototype.Selector = (function() { 4486 4487 function select() { 4488 throw new Error('Method "Prototype.Selector.select" must be defined.'); 4489 } 4490 4491 function match() { 4492 throw new Error('Method "Prototype.Selector.match" must be defined.'); 4493 } 4494 4495 function find(elements, expression, index) { 4496 index = index || 0; 4497 var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; 4498 4499 for (i = 0; i < length; i++) { 4500 if (match(elements[i], expression) && index == matchIndex++) { 4501 return Element.extend(elements[i]); 4502 } 4503 } 4504 } 4505 4506 function extendElements(elements) { 4507 for (var i = 0, length = elements.length; i < length; i++) { 4508 Element.extend(elements[i]); 4509 } 4510 return elements; 4511 } 4512 4513 4514 var K = Prototype.K; 4515 4516 return { 4517 select: select, 4518 match: match, 4519 find: find, 4520 extendElements: (Element.extend === K) ? K : extendElements, 4521 extendElement: Element.extend 4522 }; 4523})(); 4524Prototype._original_property = window.Sizzle; 4525 4526;(function () { 4527 function fakeDefine(fn) { 4528 Prototype._actual_sizzle = fn(); 4529 } 4530 fakeDefine.amd = true; 4531 4532 if (typeof define !== 'undefined' && define.amd) { 4533 Prototype._original_define = define; 4534 Prototype._actual_sizzle = null; 4535 window.define = fakeDefine; 4536 } 4537})(); 4538 4539/*! 4540 * Sizzle CSS Selector Engine v1.10.18 4541 * http://sizzlejs.com/ 4542 * 4543 * Copyright 2013 jQuery Foundation, Inc. and other contributors 4544 * Released under the MIT license 4545 * http://jquery.org/license 4546 * 4547 * Date: 2014-02-05 4548 */ 4549(function( window ) { 4550 4551var i, 4552 support, 4553 Expr, 4554 getText, 4555 isXML, 4556 compile, 4557 select, 4558 outermostContext, 4559 sortInput, 4560 hasDuplicate, 4561 4562 setDocument, 4563 document, 4564 docElem, 4565 documentIsHTML, 4566 rbuggyQSA, 4567 rbuggyMatches, 4568 matches, 4569 contains, 4570 4571 expando = "sizzle" + -(new Date()), 4572 preferredDoc = window.document, 4573 dirruns = 0, 4574 done = 0, 4575 classCache = createCache(), 4576 tokenCache = createCache(), 4577 compilerCache = createCache(), 4578 sortOrder = function( a, b ) { 4579 if ( a === b ) { 4580 hasDuplicate = true; 4581 } 4582 return 0; 4583 }, 4584 4585 strundefined = typeof undefined, 4586 MAX_NEGATIVE = 1 << 31, 4587 4588 hasOwn = ({}).hasOwnProperty, 4589 arr = [], 4590 pop = arr.pop, 4591 push_native = arr.push, 4592 push = arr.push, 4593 slice = arr.slice, 4594 indexOf = arr.indexOf || function( elem ) { 4595 var i = 0, 4596 len = this.length; 4597 for ( ; i < len; i++ ) { 4598 if ( this[i] === elem ) { 4599 return i; 4600 } 4601 } 4602 return -1; 4603 }, 4604 4605 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 4606 4607 4608 whitespace = "[\\x20\\t\\r\\n\\f]", 4609 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 4610 4611 identifier = characterEncoding.replace( "w", "w#" ), 4612 4613 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + 4614 "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", 4615 4616 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", 4617 4618 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 4619 4620 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 4621 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 4622 4623 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), 4624 4625 rpseudo = new RegExp( pseudos ), 4626 ridentifier = new RegExp( "^" + identifier + "$" ), 4627 4628 matchExpr = { 4629 "ID": new RegExp( "^#(" + characterEncoding + ")" ), 4630 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), 4631 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), 4632 "ATTR": new RegExp( "^" + attributes ), 4633 "PSEUDO": new RegExp( "^" + pseudos ), 4634 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 4635 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 4636 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 4637 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 4638 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 4639 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-
vendor: 38,618 bytes, lines 4639-6195
4639]|$)", "i" ) 4640 }, 4641 4642 rinputs = /^(?:input|select|textarea|button)$/i, 4643 rheader = /^h\d$/i, 4644 4645 rnative = /^[^{]+\{\s*\[native \w/, 4646 4647 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 4648 4649 rsibling = /[+~]/, 4650 rescape = /'|\\/g, 4651 4652 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 4653 funescape = function( _, escaped, escapedWhitespace ) { 4654 var high = "0x" + escaped - 0x10000; 4655 return high !== high || escapedWhitespace ? 4656 escaped : 4657 high < 0 ? 4658 String.fromCharCode( high + 0x10000 ) : 4659 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 4660 }; 4661 4662try { 4663 push.apply( 4664 (arr = slice.call( preferredDoc.childNodes )), 4665 preferredDoc.childNodes 4666 ); 4667 arr[ preferredDoc.childNodes.length ].nodeType; 4668} catch ( e ) { 4669 push = { apply: arr.length ? 4670 4671 function( target, els ) { 4672 push_native.apply( target, slice.call(els) ); 4673 } : 4674 4675 function( target, els ) { 4676 var j = target.length, 4677 i = 0; 4678 while ( (target[j++] = els[i++]) ) {} 4679 target.length = j - 1; 4680 } 4681 }; 4682} 4683 4684function Sizzle( selector, context, results, seed ) { 4685 var match, elem, m, nodeType, 4686 i, groups, old, nid, newContext, newSelector; 4687 4688 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 4689 setDocument( context ); 4690 } 4691 4692 context = context || document; 4693 results = results || []; 4694 4695 if ( !selector || typeof selector !== "string" ) { 4696 return results; 4697 } 4698 4699 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { 4700 return []; 4701 } 4702 4703 if ( documentIsHTML && !seed ) { 4704 4705 if ( (match = rquickExpr.exec( selector )) ) { 4706 if ( (m = match[1]) ) { 4707 if ( nodeType === 9 ) { 4708 elem = context.getElementById( m ); 4709 if ( elem && elem.parentNode ) { 4710 if ( elem.id === m ) { 4711 results.push( elem ); 4712 return results; 4713 } 4714 } else { 4715 return results; 4716 } 4717 } else { 4718 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && 4719 contains( context, elem ) && elem.id === m ) { 4720 results.push( elem ); 4721 return results; 4722 } 4723 } 4724 4725 } else if ( match[2] ) { 4726 push.apply( results, context.getElementsByTagName( selector ) ); 4727 return results; 4728 4729 } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { 4730 push.apply( results, context.getElementsByClassName( m ) ); 4731 return results; 4732 } 4733 } 4734 4735 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { 4736 nid = old = expando; 4737 newContext = context; 4738 newSelector = nodeType === 9 && selector; 4739 4740 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 4741 groups = tokenize( selector ); 4742 4743 if ( (old = context.getAttribute("id")) ) { 4744 nid = old.replace( rescape, "\\$&" ); 4745 } else { 4746 context.setAttribute( "id", nid ); 4747 } 4748 nid = "[id='" + nid + "'] "; 4749 4750 i = groups.length; 4751 while ( i-- ) { 4752 groups[i] = nid + toSelector( groups[i] ); 4753 } 4754 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; 4755 newSelector = groups.join(","); 4756 } 4757 4758 if ( newSelector ) { 4759 try { 4760 push.apply( results, 4761 newContext.querySelectorAll( newSelector ) 4762 ); 4763 return results; 4764 } catch(qsaError) { 4765 } finally { 4766 if ( !old ) { 4767 context.removeAttribute("id"); 4768 } 4769 } 4770 } 4771 } 4772 } 4773 4774 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 4775} 4776 4777/** 4778 * Create key-value caches of limited size 4779 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with 4780 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 4781 * deleting the oldest entry 4782 */ 4783function createCache() { 4784 var keys = []; 4785 4786 function cache( key, value ) { 4787 if ( keys.push( key + " " ) > Expr.cacheLength ) { 4788 delete cache[ keys.shift() ]; 4789 } 4790 return (cache[ key + " " ] = value); 4791 } 4792 return cache; 4793} 4794 4795/** 4796 * Mark a function for special use by Sizzle 4797 * @param {Function} fn The function to mark 4798 */ 4799function markFunction( fn ) { 4800 fn[ expando ] = true; 4801 return fn; 4802} 4803 4804/** 4805 * Support testing using an element 4806 * @param {Function} fn Passed the created div and expects a boolean result 4807 */ 4808function assert( fn ) { 4809 var div = document.createElement("div"); 4810 4811 try { 4812 return !!fn( div ); 4813 } catch (e) { 4814 return false; 4815 } finally { 4816 if ( div.parentNode ) { 4817 div.parentNode.removeChild( div ); 4818 } 4819 div = null; 4820 } 4821} 4822 4823/** 4824 * Adds the same handler for all of the specified attrs 4825 * @param {String} attrs Pipe-separated list of attributes 4826 * @param {Function} handler The method that will be applied 4827 */ 4828function addHandle( attrs, handler ) { 4829 var arr = attrs.split("|"), 4830 i = attrs.length; 4831 4832 while ( i-- ) { 4833 Expr.attrHandle[ arr[i] ] = handler; 4834 } 4835} 4836 4837/** 4838 * Checks document order of two siblings 4839 * @param {Element} a 4840 * @param {Element} b 4841 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 4842 */ 4843function siblingCheck( a, b ) { 4844 var cur = b && a, 4845 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 4846 ( ~b.sourceIndex || MAX_NEGATIVE ) - 4847 ( ~a.sourceIndex || MAX_NEGATIVE ); 4848 4849 if ( diff ) { 4850 return diff; 4851 } 4852 4853 if ( cur ) { 4854 while ( (cur = cur.nextSibling) ) { 4855 if ( cur === b ) { 4856 return -1; 4857 } 4858 } 4859 } 4860 4861 return a ? 1 : -1; 4862} 4863 4864/** 4865 * Returns a function to use in pseudos for input types 4866 * @param {String} type 4867 */ 4868function createInputPseudo( type ) { 4869 return function( elem ) { 4870 var name = elem.nodeName.toLowerCase(); 4871 return name === "input" && elem.type === type; 4872 }; 4873} 4874 4875/** 4876 * Returns a function to use in pseudos for buttons 4877 * @param {String} type 4878 */ 4879function createButtonPseudo( type ) { 4880 return function( elem ) { 4881 var name = elem.nodeName.toLowerCase(); 4882 return (name === "input" || name === "button") && elem.type === type; 4883 }; 4884} 4885 4886/** 4887 * Returns a function to use in pseudos for positionals 4888 * @param {Function} fn 4889 */ 4890function createPositionalPseudo( fn ) { 4891 return markFunction(function( argument ) { 4892 argument = +argument; 4893 return markFunction(function( seed, matches ) { 4894 var j, 4895 matchIndexes = fn( [], seed.length, argument ), 4896 i = matchIndexes.length; 4897 4898 while ( i-- ) { 4899 if ( seed[ (j = matchIndexes[i]) ] ) { 4900 seed[j] = !(matches[j] = seed[j]); 4901 } 4902 } 4903 }); 4904 }); 4905} 4906 4907/** 4908 * Checks a node for validity as a Sizzle context 4909 * @param {Element|Object=} context 4910 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 4911 */ 4912function testContext( context ) { 4913 return context && typeof context.getElementsByTagName !== strundefined && context; 4914} 4915 4916support = Sizzle.support = {}; 4917 4918/** 4919 * Detects XML nodes 4920 * @param {Element|Object} elem An element or a document 4921 * @returns {Boolean} True iff elem is a non-HTML XML node 4922 */ 4923isXML = Sizzle.isXML = function( elem ) { 4924 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 4925 return documentElement ? documentElement.nodeName !== "HTML" : false; 4926}; 4927 4928/** 4929 * Sets document-related variables once based on the current document 4930 * @param {Element|Object} [doc] An element or document object to use to set the document 4931 * @returns {Object} Returns the current document 4932 */ 4933setDocument = Sizzle.setDocument = function( node ) { 4934 var hasCompare, 4935 doc = node ? node.ownerDocument || node : preferredDoc, 4936 parent = doc.defaultView; 4937 4938 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 4939 return document; 4940 } 4941 4942 document = doc; 4943 docElem = doc.documentElement; 4944 4945 documentIsHTML = !isXML( doc ); 4946 4947 if ( parent && parent !== parent.top ) { 4948 if ( parent.addEventListener ) { 4949 parent.addEventListener( "unload", function() { 4950 setDocument(); 4951 }, false ); 4952 } else if ( parent.attachEvent ) { 4953 parent.attachEvent( "onunload", function() { 4954 setDocument(); 4955 }); 4956 } 4957 } 4958 4959 /* Attributes 4960 ---------------------------------------------------------------------- */ 4961 4962 support.attributes = assert(function( div ) { 4963 div.className = "i"; 4964 return !div.getAttribute("className"); 4965 }); 4966 4967 /* getElement(s)By* 4968 ---------------------------------------------------------------------- */ 4969 4970 support.getElementsByTagName = assert(function( div ) { 4971 div.appendChild( doc.createComment("") ); 4972 return !div.getElementsByTagName("*").length; 4973 }); 4974 4975 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { 4976 div.innerHTML = "<div class='a'></div><div class='a i'></div>"; 4977 4978 div.firstChild.className = "i"; 4979 return div.getElementsByClassName("i").length === 2; 4980 }); 4981 4982 support.getById = assert(function( div ) { 4983 docElem.appendChild( div ).id = expando; 4984 return !doc.getElementsByName || !doc.getElementsByName( expando ).length; 4985 }); 4986 4987 if ( support.getById ) { 4988 Expr.find["ID"] = function( id, context ) { 4989 if ( typeof context.getElementById !== strundefined && documentIsHTML ) { 4990 var m = context.getElementById( id ); 4991 return m && m.parentNode ? [m] : []; 4992 } 4993 }; 4994 Expr.filter["ID"] = function( id ) { 4995 var attrId = id.replace( runescape, funescape ); 4996 return function( elem ) { 4997 return elem.getAttribute("id") === attrId; 4998 }; 4999 }; 5000 } else { 5001 delete Expr.find["ID"]; 5002 5003 Expr.filter["ID"] = function( id ) { 5004 var attrId = id.replace( runescape, funescape ); 5005 return function( elem ) { 5006 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); 5007 return node && node.value === attrId; 5008 }; 5009 }; 5010 } 5011 5012 Expr.find["TAG"] = support.getElementsByTagName ? 5013 function( tag, context ) { 5014 if ( typeof context.getElementsByTagName !== strundefined ) { 5015 return context.getElementsByTagName( tag ); 5016 } 5017 } : 5018 function( tag, context ) { 5019 var elem, 5020 tmp = [], 5021 i = 0, 5022 results = context.getElementsByTagName( tag ); 5023 5024 if ( tag === "*" ) { 5025 while ( (elem = results[i++]) ) { 5026 if ( elem.nodeType === 1 ) { 5027 tmp.push( elem ); 5028 } 5029 } 5030 5031 return tmp; 5032 } 5033 return results; 5034 }; 5035 5036 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 5037 if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { 5038 return context.getElementsByClassName( className ); 5039 } 5040 }; 5041 5042 /* QSA/matchesSelector 5043 ---------------------------------------------------------------------- */ 5044 5045 5046 rbuggyMatches = []; 5047 5048 rbuggyQSA = []; 5049 5050 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { 5051 assert(function( div ) { 5052 div.innerHTML = "<select t=''><option selected=''></option></select>"; 5053 5054 if ( div.querySelectorAll("[t^='']").length ) { 5055 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 5056 } 5057 5058 if ( !div.querySelectorAll("[selected]").length ) { 5059 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 5060 } 5061 5062 if ( !div.querySelectorAll(":checked").length ) { 5063 rbuggyQSA.push(":checked"); 5064 } 5065 }); 5066 5067 assert(function( div ) { 5068 var input = doc.createElement("input"); 5069 input.setAttribute( "type", "hidden" ); 5070 div.appendChild( input ).setAttribute( "name", "D" ); 5071 5072 if ( div.querySelectorAll("[name=d]").length ) { 5073 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 5074 } 5075 5076 if ( !div.querySelectorAll(":enabled").length ) { 5077 rbuggyQSA.push( ":enabled", ":disabled" ); 5078 } 5079 5080 div.querySelectorAll("*,:x"); 5081 rbuggyQSA.push(",.*:"); 5082 }); 5083 } 5084 5085 if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || 5086 docElem.mozMatchesSelector || 5087 docElem.oMatchesSelector || 5088 docElem.msMatchesSelector) )) ) { 5089 5090 assert(function( div ) { 5091 support.disconnectedMatch = matches.call( div, "div" ); 5092 5093 matches.call( div, "[s!='']:x" ); 5094 rbuggyMatches.push( "!=", pseudos ); 5095 }); 5096 } 5097 5098 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 5099 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 5100 5101 /* Contains 5102 ---------------------------------------------------------------------- */ 5103 hasCompare = rnative.test( docElem.compareDocumentPosition ); 5104 5105 contains = hasCompare || rnative.test( docElem.contains ) ? 5106 function( a, b ) { 5107 var adown = a.nodeType === 9 ? a.documentElement : a, 5108 bup = b && b.parentNode; 5109 return a === bup || !!( bup && bup.nodeType === 1 && ( 5110 adown.contains ? 5111 adown.contains( bup ) : 5112 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 5113 )); 5114 } : 5115 function( a, b ) { 5116 if ( b ) { 5117 while ( (b = b.parentNode) ) { 5118 if ( b === a ) { 5119 return true; 5120 } 5121 } 5122 } 5123 return false; 5124 }; 5125 5126 /* Sorting 5127 ---------------------------------------------------------------------- */ 5128 5129 sortOrder = hasCompare ? 5130 function( a, b ) { 5131 5132 if ( a === b ) { 5133 hasDuplicate = true; 5134 return 0; 5135 } 5136 5137 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 5138 if ( compare ) { 5139 return compare; 5140 } 5141 5142 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 5143 a.compareDocumentPosition( b ) : 5144 5145 1; 5146 5147 if ( compare & 1 || 5148 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 5149 5150 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 5151 return -1; 5152 } 5153 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 5154 return 1; 5155 } 5156 5157 return sortInput ? 5158 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 5159 0; 5160 } 5161 5162 return compare & 4 ? -1 : 1; 5163 } : 5164 function( a, b ) { 5165 if ( a === b ) { 5166 hasDuplicate = true; 5167 return 0; 5168 } 5169 5170 var cur, 5171 i = 0, 5172 aup = a.parentNode, 5173 bup = b.parentNode, 5174 ap = [ a ], 5175 bp = [ b ]; 5176 5177 if ( !aup || !bup ) { 5178 return a === doc ? -1 : 5179 b === doc ? 1 : 5180 aup ? -1 : 5181 bup ? 1 : 5182 sortInput ? 5183 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 5184 0; 5185 5186 } else if ( aup === bup ) { 5187 return siblingCheck( a, b ); 5188 } 5189 5190 cur = a; 5191 while ( (cur = cur.parentNode) ) { 5192 ap.unshift( cur ); 5193 } 5194 cur = b; 5195 while ( (cur = cur.parentNode) ) { 5196 bp.unshift( cur ); 5197 } 5198 5199 while ( ap[i] === bp[i] ) { 5200 i++; 5201 } 5202 5203 return i ? 5204 siblingCheck( ap[i], bp[i] ) : 5205 5206 ap[i] === preferredDoc ? -1 : 5207 bp[i] === preferredDoc ? 1 : 5208 0; 5209 }; 5210 5211 return doc; 5212}; 5213 5214Sizzle.matches = function( expr, elements ) { 5215 return Sizzle( expr, null, null, elements ); 5216}; 5217 5218Sizzle.matchesSelector = function( elem, expr ) { 5219 if ( ( elem.ownerDocument || elem ) !== document ) { 5220 setDocument( elem ); 5221 } 5222 5223 expr = expr.replace( rattributeQuotes, "='$1']" ); 5224 5225 if ( support.matchesSelector && documentIsHTML && 5226 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 5227 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 5228 5229 try { 5230 var ret = matches.call( elem, expr ); 5231 5232 if ( ret || support.disconnectedMatch || 5233 elem.document && elem.document.nodeType !== 11 ) { 5234 return ret; 5235 } 5236 } catch(e) {} 5237 } 5238 5239 return Sizzle( expr, document, null, [elem] ).length > 0; 5240}; 5241 5242Sizzle.contains = function( context, elem ) { 5243 if ( ( context.ownerDocument || context ) !== document ) { 5244 setDocument( context ); 5245 } 5246 return contains( context, elem ); 5247}; 5248 5249Sizzle.attr = function( elem, name ) { 5250 if ( ( elem.ownerDocument || elem ) !== document ) { 5251 setDocument( elem ); 5252 } 5253 5254 var fn = Expr.attrHandle[ name.toLowerCase() ], 5255 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 5256 fn( elem, name, !documentIsHTML ) : 5257 undefined; 5258 5259 return val !== undefined ? 5260 val : 5261 support.attributes || !documentIsHTML ? 5262 elem.getAttribute( name ) : 5263 (val = elem.getAttributeNode(name)) && val.specified ? 5264 val.value : 5265 null; 5266}; 5267 5268Sizzle.error = function( msg ) { 5269 throw new Error( "Syntax error, unrecognized expression: " + msg ); 5270}; 5271 5272/** 5273 * Document sorting and removing duplicates 5274 * @param {ArrayLike} results 5275 */ 5276Sizzle.uniqueSort = function( results ) { 5277 var elem, 5278 duplicates = [], 5279 j = 0, 5280 i = 0; 5281 5282 hasDuplicate = !support.detectDuplicates; 5283 sortInput = !support.sortStable && results.slice( 0 ); 5284 results.sort( sortOrder ); 5285 5286 if ( hasDuplicate ) { 5287 while ( (elem = results[i++]) ) { 5288 if ( elem === results[ i ] ) { 5289 j = duplicates.push( i ); 5290 } 5291 } 5292 while ( j-- ) { 5293 results.splice( duplicates[ j ], 1 ); 5294 } 5295 } 5296 5297 sortInput = null; 5298 5299 return results; 5300}; 5301 5302/** 5303 * Utility function for retrieving the text value of an array of DOM nodes 5304 * @param {Array|Element} elem 5305 */ 5306getText = Sizzle.getText = function( elem ) { 5307 var node, 5308 ret = "", 5309 i = 0, 5310 nodeType = elem.nodeType; 5311 5312 if ( !nodeType ) { 5313 while ( (node = elem[i++]) ) { 5314 ret += getText( node ); 5315 } 5316 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 5317 if ( typeof elem.textContent === "string" ) { 5318 return elem.textContent; 5319 } else { 5320 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 5321 ret += getText( elem ); 5322 } 5323 } 5324 } else if ( nodeType === 3 || nodeType === 4 ) { 5325 return elem.nodeValue; 5326 } 5327 5328 return ret; 5329}; 5330 5331Expr = Sizzle.selectors = { 5332 5333 cacheLength: 50, 5334 5335 createPseudo: markFunction, 5336 5337 match: matchExpr, 5338 5339 attrHandle: {}, 5340 5341 find: {}, 5342 5343 relative: { 5344 ">": { dir: "parentNode", first: true }, 5345 " ": { dir: "parentNode" }, 5346 "+": { dir: "previousSibling", first: true }, 5347 "~": { dir: "previousSibling" } 5348 }, 5349 5350 preFilter: { 5351 "ATTR": function( match ) { 5352 match[1] = match[1].replace( runescape, funescape ); 5353 5354 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); 5355 5356 if ( match[2] === "~=" ) { 5357 match[3] = " " + match[3] + " "; 5358 } 5359 5360 return match.slice( 0, 4 ); 5361 }, 5362 5363 "CHILD": function( match ) { 5364 /* matches from matchExpr["CHILD"] 5365 1 type (only|nth|...) 5366 2 what (child|of-type) 5367 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 5368 4 xn-component of xn+y argument ([+-]?\d*n|) 5369 5 sign of xn-component 5370 6 x of xn-component 5371 7 sign of y-component 5372 8 y of y-component 5373 */ 5374 match[1] = match[1].toLowerCase(); 5375 5376 if ( match[1].slice( 0, 3 ) === "nth" ) { 5377 if ( !match[3] ) { 5378 Sizzle.error( match[0] ); 5379 } 5380 5381 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 5382 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 5383 5384 } else if ( match[3] ) { 5385 Sizzle.error( match[0] ); 5386 } 5387 5388 return match; 5389 }, 5390 5391 "PSEUDO": function( match ) { 5392 var excess, 5393 unquoted = !match[5] && match[2]; 5394 5395 if ( matchExpr["CHILD"].test( match[0] ) ) { 5396 return null; 5397 } 5398 5399 if ( match[3] && match[4] !== undefined ) { 5400 match[2] = match[4]; 5401 5402 } else if ( unquoted && rpseudo.test( unquoted ) && 5403 (excess = tokenize( unquoted, true )) && 5404 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 5405 5406 match[0] = match[0].slice( 0, excess ); 5407 match[2] = unquoted.slice( 0, excess ); 5408 } 5409 5410 return match.slice( 0, 3 ); 5411 } 5412 }, 5413 5414 filter: { 5415 5416 "TAG": function( nodeNameSelector ) { 5417 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 5418 return nodeNameSelector === "*" ? 5419 function() { return true; } : 5420 function( elem ) { 5421 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 5422 }; 5423 }, 5424 5425 "CLASS": function( className ) { 5426 var pattern = classCache[ className + " " ]; 5427 5428 return pattern || 5429 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 5430 classCache( className, function( elem ) { 5431 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); 5432 }); 5433 }, 5434 5435 "ATTR": function( name, operator, check ) { 5436 return function( elem ) { 5437 var result = Sizzle.attr( elem, name ); 5438 5439 if ( result == null ) { 5440 return operator === "!="; 5441 } 5442 if ( !operator ) { 5443 return true; 5444 } 5445 5446 result += ""; 5447 5448 return operator === "=" ? result === check : 5449 operator === "!=" ? result !== check : 5450 operator === "^=" ? check && result.indexOf( check ) === 0 : 5451 operator === "*=" ? check && result.indexOf( check ) > -1 : 5452 operator === "$=" ? check && result.slice( -check.length ) === check : 5453 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : 5454 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 5455 false; 5456 }; 5457 }, 5458 5459 "CHILD": function( type, what, argument, first, last ) { 5460 var simple = type.slice( 0, 3 ) !== "nth", 5461 forward = type.slice( -4 ) !== "last", 5462 ofType = what === "of-type"; 5463 5464 return first === 1 && last === 0 ? 5465 5466 function( elem ) { 5467 return !!elem.parentNode; 5468 } : 5469 5470 function( elem, context, xml ) { 5471 var cache, outerCache, node, diff, nodeIndex, start, 5472 dir = simple !== forward ? "nextSibling" : "previousSibling", 5473 parent = elem.parentNode, 5474 name = ofType && elem.nodeName.toLowerCase(), 5475 useCache = !xml && !ofType; 5476 5477 if ( parent ) { 5478 5479 if ( simple ) { 5480 while ( dir ) { 5481 node = elem; 5482 while ( (node = node[ dir ]) ) { 5483 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { 5484 return false; 5485 } 5486 } 5487 start = dir = type === "only" && !start && "nextSibling"; 5488 } 5489 return true; 5490 } 5491 5492 start = [ forward ? parent.firstChild : parent.lastChild ]; 5493 5494 if ( forward && useCache ) { 5495 outerCache = parent[ expando ] || (parent[ expando ] = {}); 5496 cache = outerCache[ type ] || []; 5497 nodeIndex = cache[0] === dirruns && cache[1]; 5498 diff = cache[0] === dirruns && cache[2]; 5499 node = nodeIndex && parent.childNodes[ nodeIndex ]; 5500 5501 while ( (node = ++nodeIndex && node && node[ dir ] || 5502 5503 (diff = nodeIndex = 0) || start.pop()) ) { 5504 5505 if ( node.nodeType === 1 && ++diff && node === elem ) { 5506 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 5507 break; 5508 } 5509 } 5510 5511 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { 5512 diff = cache[1]; 5513 5514 } else { 5515 while ( (node = ++nodeIndex && node && node[ dir ] || 5516 (diff = nodeIndex = 0) || start.pop()) ) { 5517 5518 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { 5519 if ( useCache ) { 5520 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; 5521 } 5522 5523 if ( node === elem ) { 5524 break; 5525 } 5526 } 5527 } 5528 } 5529 5530 diff -= last; 5531 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 5532 } 5533 }; 5534 }, 5535 5536 "PSEUDO": function( pseudo, argument ) { 5537 var args, 5538 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 5539 Sizzle.error( "unsupported pseudo: " + pseudo ); 5540 5541 if ( fn[ expando ] ) { 5542 return fn( argument ); 5543 } 5544 5545 if ( fn.length > 1 ) { 5546 args = [ pseudo, pseudo, "", argument ]; 5547 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 5548 markFunction(function( seed, matches ) { 5549 var idx, 5550 matched = fn( seed, argument ), 5551 i = matched.length; 5552 while ( i-- ) { 5553 idx = indexOf.call( seed, matched[i] ); 5554 seed[ idx ] = !( matches[ idx ] = matched[i] ); 5555 } 5556 }) : 5557 function( elem ) { 5558 return fn( elem, 0, args ); 5559 }; 5560 } 5561 5562 return fn; 5563 } 5564 }, 5565 5566 pseudos: { 5567 "not": markFunction(function( selector ) { 5568 var input = [], 5569 results = [], 5570 matcher = compile( selector.replace( rtrim, "$1" ) ); 5571 5572 return matcher[ expando ] ? 5573 markFunction(function( seed, matches, context, xml ) { 5574 var elem, 5575 unmatched = matcher( seed, null, xml, [] ), 5576 i = seed.length; 5577 5578 while ( i-- ) { 5579 if ( (elem = unmatched[i]) ) { 5580 seed[i] = !(matches[i] = elem); 5581 } 5582 } 5583 }) : 5584 function( elem, context, xml ) { 5585 input[0] = elem; 5586 matcher( input, null, xml, results ); 5587 return !results.pop(); 5588 }; 5589 }), 5590 5591 "has": markFunction(function( selector ) { 5592 return function( elem ) { 5593 return Sizzle( selector, elem ).length > 0; 5594 }; 5595 }), 5596 5597 "contains": markFunction(function( text ) { 5598 return function( elem ) { 5599 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 5600 }; 5601 }), 5602 5603 "lang": markFunction( function( lang ) { 5604 if ( !ridentifier.test(lang || "") ) { 5605 Sizzle.error( "unsupported lang: " + lang ); 5606 } 5607 lang = lang.replace( runescape, funescape ).toLowerCase(); 5608 return function( elem ) { 5609 var elemLang; 5610 do { 5611 if ( (elemLang = documentIsHTML ? 5612 elem.lang : 5613 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 5614 5615 elemLang = elemLang.toLowerCase(); 5616 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 5617 } 5618 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 5619 return false; 5620 }; 5621 }), 5622 5623 "target": function( elem ) { 5624 var hash = window.location && window.location.hash; 5625 return hash && hash.slice( 1 ) === elem.id; 5626 }, 5627 5628 "root": function( elem ) { 5629 return elem === docElem; 5630 }, 5631 5632 "focus": function( elem ) { 5633 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 5634 }, 5635 5636 "enabled": function( elem ) { 5637 return elem.disabled === false; 5638 }, 5639 5640 "disabled": function( elem ) { 5641 return elem.disabled === true; 5642 }, 5643 5644 "checked": function( elem ) { 5645 var nodeName = elem.nodeName.toLowerCase(); 5646 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 5647 }, 5648 5649 "selected": function( elem ) { 5650 if ( elem.parentNode ) { 5651 elem.parentNode.selectedIndex; 5652 } 5653 5654 return elem.selected === true; 5655 }, 5656 5657 "empty": function( elem ) { 5658 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 5659 if ( elem.nodeType < 6 ) { 5660 return false; 5661 } 5662 } 5663 return true; 5664 }, 5665 5666 "parent": function( elem ) { 5667 return !Expr.pseudos["empty"]( elem ); 5668 }, 5669 5670 "header": function( elem ) { 5671 return rheader.test( elem.nodeName ); 5672 }, 5673 5674 "input": function( elem ) { 5675 return rinputs.test( elem.nodeName ); 5676 }, 5677 5678 "button": function( elem ) { 5679 var name = elem.nodeName.toLowerCase(); 5680 return name === "input" && elem.type === "button" || name === "button"; 5681 }, 5682 5683 "text": function( elem ) { 5684 var attr; 5685 return elem.nodeName.toLowerCase() === "input" && 5686 elem.type === "text" && 5687 5688 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 5689 }, 5690 5691 "first": createPositionalPseudo(function() { 5692 return [ 0 ]; 5693 }), 5694 5695 "last": createPositionalPseudo(function( matchIndexes, length ) { 5696 return [ length - 1 ]; 5697 }), 5698 5699 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 5700 return [ argument < 0 ? argument + length : argument ]; 5701 }), 5702 5703 "even": createPositionalPseudo(function( matchIndexes, length ) { 5704 var i = 0; 5705 for ( ; i < length; i += 2 ) { 5706 matchIndexes.push( i ); 5707 } 5708 return matchIndexes; 5709 }), 5710 5711 "odd": createPositionalPseudo(function( matchIndexes, length ) { 5712 var i = 1; 5713 for ( ; i < length; i += 2 ) { 5714 matchIndexes.push( i ); 5715 } 5716 return matchIndexes; 5717 }), 5718 5719 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 5720 var i = argument < 0 ? argument + length : argument; 5721 for ( ; --i >= 0; ) { 5722 matchIndexes.push( i ); 5723 } 5724 return matchIndexes; 5725 }), 5726 5727 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 5728 var i = argument < 0 ? argument + length : argument; 5729 for ( ; ++i < length; ) { 5730 matchIndexes.push( i ); 5731 } 5732 return matchIndexes; 5733 }) 5734 } 5735}; 5736 5737Expr.pseudos["nth"] = Expr.pseudos["eq"]; 5738 5739for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 5740 Expr.pseudos[ i ] = createInputPseudo( i ); 5741} 5742for ( i in { submit: true, reset: true } ) { 5743 Expr.pseudos[ i ] = createButtonPseudo( i ); 5744} 5745 5746function setFilters() {} 5747setFilters.prototype = Expr.filters = Expr.pseudos; 5748Expr.setFilters = new setFilters(); 5749 5750function tokenize( selector, parseOnly ) { 5751 var matched, match, tokens, type, 5752 soFar, groups, preFilters, 5753 cached = tokenCache[ selector + " " ]; 5754 5755 if ( cached ) { 5756 return parseOnly ? 0 : cached.slice( 0 ); 5757 } 5758 5759 soFar = selector; 5760 groups = []; 5761 preFilters = Expr.preFilter; 5762 5763 while ( soFar ) { 5764 5765 if ( !matched || (match = rcomma.exec( soFar )) ) { 5766 if ( match ) { 5767 soFar = soFar.slice( match[0].length ) || soFar; 5768 } 5769 groups.push( (tokens = []) ); 5770 } 5771 5772 matched = false; 5773 5774 if ( (match = rcombinators.exec( soFar )) ) { 5775 matched = match.shift(); 5776 tokens.push({ 5777 value: matched, 5778 type: match[0].replace( rtrim, " " ) 5779 }); 5780 soFar = soFar.slice( matched.length ); 5781 } 5782 5783 for ( type in Expr.filter ) { 5784 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 5785 (match = preFilters[ type ]( match ))) ) { 5786 matched = match.shift(); 5787 tokens.push({ 5788 value: matched, 5789 type: type, 5790 matches: match 5791 }); 5792 soFar = soFar.slice( matched.length ); 5793 } 5794 } 5795 5796 if ( !matched ) { 5797 break; 5798 } 5799 } 5800 5801 return parseOnly ? 5802 soFar.length : 5803 soFar ? 5804 Sizzle.error( selector ) : 5805 tokenCache( selector, groups ).slice( 0 ); 5806} 5807 5808function toSelector( tokens ) { 5809 var i = 0, 5810 len = tokens.length, 5811 selector = ""; 5812 for ( ; i < len; i++ ) { 5813 selector += tokens[i].value; 5814 } 5815 return selector; 5816} 5817 5818function addCombinator( matcher, combinator, base ) { 5819 var dir = combinator.dir, 5820 checkNonElements = base && dir === "parentNode", 5821 doneName = done++; 5822 5823 return combinator.first ? 5824 function( elem, context, xml ) { 5825 while ( (elem = elem[ dir ]) ) { 5826 if ( elem.nodeType === 1 || checkNonElements ) { 5827 return matcher( elem, context, xml ); 5828 } 5829 } 5830 } : 5831 5832 function( elem, context, xml ) { 5833 var oldCache, outerCache, 5834 newCache = [ dirruns, doneName ]; 5835 5836 if ( xml ) { 5837 while ( (elem = elem[ dir ]) ) { 5838 if ( elem.nodeType === 1 || checkNonElements ) { 5839 if ( matcher( elem, context, xml ) ) { 5840 return true; 5841 } 5842 } 5843 } 5844 } else { 5845 while ( (elem = elem[ dir ]) ) { 5846 if ( elem.nodeType === 1 || checkNonElements ) { 5847 outerCache = elem[ expando ] || (elem[ expando ] = {}); 5848 if ( (oldCache = outerCache[ dir ]) && 5849 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 5850 5851 return (newCache[ 2 ] = oldCache[ 2 ]); 5852 } else { 5853 outerCache[ dir ] = newCache; 5854 5855 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 5856 return true; 5857 } 5858 } 5859 } 5860 } 5861 } 5862 }; 5863} 5864 5865function elementMatcher( matchers ) { 5866 return matchers.length > 1 ? 5867 function( elem, context, xml ) { 5868 var i = matchers.length; 5869 while ( i-- ) { 5870 if ( !matchers[i]( elem, context, xml ) ) { 5871 return false; 5872 } 5873 } 5874 return true; 5875 } : 5876 matchers[0]; 5877} 5878 5879function multipleContexts( selector, contexts, results ) { 5880 var i = 0, 5881 len = contexts.length; 5882 for ( ; i < len; i++ ) { 5883 Sizzle( selector, contexts[i], results ); 5884 } 5885 return results; 5886} 5887 5888function condense( unmatched, map, filter, context, xml ) { 5889 var elem, 5890 newUnmatched = [], 5891 i = 0, 5892 len = unmatched.length, 5893 mapped = map != null; 5894 5895 for ( ; i < len; i++ ) { 5896 if ( (elem = unmatched[i]) ) { 5897 if ( !filter || filter( elem, context, xml ) ) { 5898 newUnmatched.push( elem ); 5899 if ( mapped ) { 5900 map.push( i ); 5901 } 5902 } 5903 } 5904 } 5905 5906 return newUnmatched; 5907} 5908 5909function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 5910 if ( postFilter && !postFilter[ expando ] ) { 5911 postFilter = setMatcher( postFilter ); 5912 } 5913 if ( postFinder && !postFinder[ expando ] ) { 5914 postFinder = setMatcher( postFinder, postSelector ); 5915 } 5916 return markFunction(function( seed, results, context, xml ) { 5917 var temp, i, elem, 5918 preMap = [], 5919 postMap = [], 5920 preexisting = results.length, 5921 5922 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 5923 5924 matcherIn = preFilter && ( seed || !selector ) ? 5925 condense( elems, preMap, preFilter, context, xml ) : 5926 elems, 5927 5928 matcherOut = matcher ? 5929 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 5930 5931 [] : 5932 5933 results : 5934 matcherIn; 5935 5936 if ( matcher ) { 5937 matcher( matcherIn, matcherOut, context, xml ); 5938 } 5939 5940 if ( postFilter ) { 5941 temp = condense( matcherOut, postMap ); 5942 postFilter( temp, [], context, xml ); 5943 5944 i = temp.length; 5945 while ( i-- ) { 5946 if ( (elem = temp[i]) ) { 5947 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 5948 } 5949 } 5950 } 5951 5952 if ( seed ) { 5953 if ( postFinder || preFilter ) { 5954 if ( postFinder ) { 5955 temp = []; 5956 i = matcherOut.length; 5957 while ( i-- ) { 5958 if ( (elem = matcherOut[i]) ) { 5959 temp.push( (matcherIn[i] = elem) ); 5960 } 5961 } 5962 postFinder( null, (matcherOut = []), temp, xml ); 5963 } 5964 5965 i = matcherOut.length; 5966 while ( i-- ) { 5967 if ( (elem = matcherOut[i]) && 5968 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { 5969 5970 seed[temp] = !(results[temp] = elem); 5971 } 5972 } 5973 } 5974 5975 } else { 5976 matcherOut = condense( 5977 matcherOut === results ? 5978 matcherOut.splice( preexisting, matcherOut.length ) : 5979 matcherOut 5980 ); 5981 if ( postFinder ) { 5982 postFinder( null, results, matcherOut, xml ); 5983 } else { 5984 push.apply( results, matcherOut ); 5985 } 5986 } 5987 }); 5988} 5989 5990function matcherFromTokens( tokens ) { 5991 var checkContext, matcher, j, 5992 len = tokens.length, 5993 leadingRelative = Expr.relative[ tokens[0].type ], 5994 implicitRelative = leadingRelative || Expr.relative[" "], 5995 i = leadingRelative ? 1 : 0, 5996 5997 matchContext = addCombinator( function( elem ) { 5998 return elem === checkContext; 5999 }, implicitRelative, true ), 6000 matchAnyContext = addCombinator( function( elem ) { 6001 return indexOf.call( checkContext, elem ) > -1; 6002 }, implicitRelative, true ), 6003 matchers = [ function( elem, context, xml ) { 6004 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 6005 (checkContext = context).nodeType ? 6006 matchContext( elem, context, xml ) : 6007 matchAnyContext( elem, context, xml ) ); 6008 } ]; 6009 6010 for ( ; i < len; i++ ) { 6011 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 6012 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 6013 } else { 6014 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 6015 6016 if ( matcher[ expando ] ) { 6017 j = ++i; 6018 for ( ; j < len; j++ ) { 6019 if ( Expr.relative[ tokens[j].type ] ) { 6020 break; 6021 } 6022 } 6023 return setMatcher( 6024 i > 1 && elementMatcher( matchers ), 6025 i > 1 && toSelector( 6026 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 6027 ).replace( rtrim, "$1" ), 6028 matcher, 6029 i < j && matcherFromTokens( tokens.slice( i, j ) ), 6030 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 6031 j < len && toSelector( tokens ) 6032 ); 6033 } 6034 matchers.push( matcher ); 6035 } 6036 } 6037 6038 return elementMatcher( matchers ); 6039} 6040 6041function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 6042 var bySet = setMatchers.length > 0, 6043 byElement = elementMatchers.length > 0, 6044 superMatcher = function( seed, context, xml, results, outermost ) { 6045 var elem, j, matcher, 6046 matchedCount = 0, 6047 i = "0", 6048 unmatched = seed && [], 6049 setMatched = [], 6050 contextBackup = outermostContext, 6051 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 6052 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 6053 len = elems.length; 6054 6055 if ( outermost ) { 6056 outermostContext = context !== document && context; 6057 } 6058 6059 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 6060 if ( byElement && elem ) { 6061 j = 0; 6062 while ( (matcher = elementMatchers[j++]) ) { 6063 if ( matcher( elem, context, xml ) ) { 6064 results.push( elem ); 6065 break; 6066 } 6067 } 6068 if ( outermost ) { 6069 dirruns = dirrunsUnique; 6070 } 6071 } 6072 6073 if ( bySet ) { 6074 if ( (elem = !matcher && elem) ) { 6075 matchedCount--; 6076 } 6077 6078 if ( seed ) { 6079 unmatched.push( elem ); 6080 } 6081 } 6082 } 6083 6084 matchedCount += i; 6085 if ( bySet && i !== matchedCount ) { 6086 j = 0; 6087 while ( (matcher = setMatchers[j++]) ) { 6088 matcher( unmatched, setMatched, context, xml ); 6089 } 6090 6091 if ( seed ) { 6092 if ( matchedCount > 0 ) { 6093 while ( i-- ) { 6094 if ( !(unmatched[i] || setMatched[i]) ) { 6095 setMatched[i] = pop.call( results ); 6096 } 6097 } 6098 } 6099 6100 setMatched = condense( setMatched ); 6101 } 6102 6103 push.apply( results, setMatched ); 6104 6105 if ( outermost && !seed && setMatched.length > 0 && 6106 ( matchedCount + setMatchers.length ) > 1 ) { 6107 6108 Sizzle.uniqueSort( results ); 6109 } 6110 } 6111 6112 if ( outermost ) { 6113 dirruns = dirrunsUnique; 6114 outermostContext = contextBackup; 6115 } 6116 6117 return unmatched; 6118 }; 6119 6120 return bySet ? 6121 markFunction( superMatcher ) : 6122 superMatcher; 6123} 6124 6125compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { 6126 var i, 6127 setMatchers = [], 6128 elementMatchers = [], 6129 cached = compilerCache[ selector + " " ]; 6130 6131 if ( !cached ) { 6132 if ( !match ) { 6133 match = tokenize( selector ); 6134 } 6135 i = match.length; 6136 while ( i-- ) { 6137 cached = matcherFromTokens( match[i] ); 6138 if ( cached[ expando ] ) { 6139 setMatchers.push( cached ); 6140 } else { 6141 elementMatchers.push( cached ); 6142 } 6143 } 6144 6145 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 6146 6147 cached.selector = selector; 6148 } 6149 return cached; 6150}; 6151 6152/** 6153 * A low-level selection function that works with Sizzle's compiled 6154 * selector functions 6155 * @param {String|Function} selector A selector or a pre-compiled 6156 * selector function built with Sizzle.compile 6157 * @param {Element} context 6158 * @param {Array} [results] 6159 * @param {Array} [seed] A set of elements to match against 6160 */ 6161select = Sizzle.select = function( selector, context, results, seed ) { 6162 var i, tokens, token, type, find, 6163 compiled = typeof selector === "function" && selector, 6164 match = !seed && tokenize( (selector = compiled.selector || selector) ); 6165 6166 results = results || []; 6167 6168 if ( match.length === 1 ) { 6169 6170 tokens = match[0] = match[0].slice( 0 ); 6171 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 6172 support.getById && context.nodeType === 9 && documentIsHTML && 6173 Expr.relative[ tokens[1].type ] ) { 6174 6175 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 6176 if ( !context ) { 6177 return results; 6178 6179 } else if ( compiled ) { 6180 context = context.parentNode; 6181 } 6182 6183 selector = selector.slice( tokens.shift().value.length ); 6184 } 6185 6186 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 6187 while ( i-- ) { 6188 token = tokens[i]; 6189 6190 if ( Expr.relative[ (type = token.type) ] ) { 6191 break; 6192 } 6193 if ( (find = Expr.find[ type ]) ) { 6194 if ( (seed = find( 6195 token.matches[0].replace( runescape, funescape ),
6196 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 6197 )) ) { 6198 6199 tokens.splice( i, 1 ); 6200 selector = seed.length && toSelector( tokens ); 6201 if ( !selector ) { 6202 push.apply( results, seed ); 6203 return results; 6204 } 6205 6206 break; 6207 } 6208 } 6209 } 6210 } 6211 6212 ( compiled || compile( selector, match ) )( 6213 seed, 6214 context, 6215 !documentIsHTML, 6216 results, 6217 rsibling.test( selector ) && testContext( context.parentNode ) || context 6218 ); 6219 return results; 6220}; 6221 6222 6223support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 6224 6225support.detectDuplicates = !!hasDuplicate; 6226 6227setDocument(); 6228 6229support.sortDetached = assert(function( div1 ) { 6230 return div1.compareDocumentPosition( document.createElement("div") ) & 1; 6231}); 6232 6233if ( !assert(function( div ) { 6234 div.innerHTML = "<a href='#'></a>"; 6235 return div.firstChild.getAttribute("href") === "#" ; 6236}) ) { 6237 addHandle( "type|href|height|width", function( elem, name, isXML ) { 6238 if ( !isXML ) { 6239 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 6240 } 6241 }); 6242} 6243 6244if ( !support.attributes || !assert(function( div ) { 6245 div.innerHTML = "<input/>"; 6246 div.firstChild.setAttribute( "value", "" ); 6247 return div.firstChild.getAttribute( "value" ) === ""; 6248}) ) { 6249 addHandle( "value", function( elem, name, isXML ) { 6250 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 6251 return elem.defaultValue; 6252 } 6253 }); 6254} 6255 6256if ( !assert(function( div ) { 6257 return div.getAttribute("disabled") == null; 6258}) ) { 6259 addHandle( booleans, function( elem, name, isXML ) { 6260 var val; 6261 if ( !isXML ) { 6262 return elem[ name ] === true ? name.toLowerCase() : 6263 (val = elem.getAttributeNode( name )) && val.specified ? 6264 val.value : 6265 null; 6266 } 6267 }); 6268} 6269 6270if ( typeof define === "function" && define.amd ) { 6271 define(function() { return Sizzle; }); 6272} else if ( typeof module !== "undefined" && module.exports ) { 6273 module.exports = Sizzle; 6274} else { 6275 window.Sizzle = Sizzle; 6276} 6277 6278})( window ); 6279 6280;(function() { 6281 if (typeof Sizzle !== 'undefined') { 6282 return; 6283 } 6284 6285 if (typeof define !== 'undefined' && define.amd) { 6286 window.Sizzle = Prototype._actual_sizzle; 6287 window.define = Prototype._original_define; 6288 delete Prototype._actual_sizzle; 6289 delete Prototype._original_define; 6290 } else if (typeof module !== 'undefined' && module.exports) { 6291 window.Sizzle = module.exports; 6292 module.exports = {}; 6293 } 6294})(); 6295 6296;(function(engine) { 6297 var extendElements = Prototype.Selector.extendElements; 6298 6299 function select(selector, scope) { 6300 return extendElements(engine(selector, scope || document)); 6301 } 6302 6303 function match(element, selector) { 6304 return engine.matches(selector, [element]).length == 1; 6305 } 6306 6307 Prototype.Selector.engine = engine; 6308 Prototype.Selector.select = select; 6309 Prototype.Selector.match = match; 6310})(Sizzle); 6311 6312window.Sizzle = Prototype._original_property; 6313delete Prototype._original_property; 6314 6315var Form = { 6316 reset: function(form) { 6317 form = $(form); 6318 form.reset(); 6319 return form; 6320 }, 6321 6322 serializeElements: function(elements, options) { 6323 if (typeof options != 'object') options = { hash: !!options }; 6324 else if (Object.isUndefined(options.hash)) options.hash = true; 6325 var key, value, submitted = false, submit = options.submit, accumulator, initial; 6326 6327 if (options.hash) { 6328 initial = {}; 6329 accumulator = function(result, key, value) { 6330 if (key in result) { 6331 if (!Object.isArray(result[key])) result[key] = [result[key]]; 6332 result[key] = result[key].concat(value); 6333 } else result[key] = value; 6334 return result; 6335 }; 6336 } else { 6337 initial = ''; 6338 accumulator = function(result, key, values) { 6339 if (!Object.isArray(values)) {values = [values];} 6340 if (!values.length) {return result;} 6341 var encodedKey = encodeURIComponent(key).gsub(/%20/, '+'); 6342 return result + (result ? "&" : "") + values.map(function (value) { 6343 value = value.gsub(/(\r)?\n/, '\r\n'); 6344 value = encodeURIComponent(value); 6345 value = value.gsub(/%20/, '+'); 6346 return encodedKey + "=" + value; 6347 }).join("&"); 6348 }; 6349 } 6350 6351 return elements.inject(initial, function(result, element) { 6352 if (!element.disabled && element.name) { 6353 key = element.name; value = $(element).getValue(); 6354 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && 6355 submit !== false && (!submit || key == submit) && (submitted = true)))) { 6356 result = accumulator(result, key, value); 6357 } 6358 } 6359 return result; 6360 }); 6361 } 6362}; 6363 6364Form.Methods = { 6365 serialize: function(form, options) { 6366 return Form.serializeElements(Form.getElements(form), options); 6367 }, 6368 6369 6370 getElements: function(form) { 6371 var elements = $(form).getElementsByTagName('*'); 6372 var element, results = [], serializers = Form.Element.Serializers; 6373 6374 for (var i = 0; element = elements[i]; i++) { 6375 if (serializers[element.tagName.toLowerCase()]) 6376 results.push(Element.extend(element)); 6377 } 6378 return results; 6379 }, 6380 6381 getInputs: function(form, typeName, name) { 6382 form = $(form); 6383 var inputs = form.getElementsByTagName('input'); 6384 6385 if (!typeName && !name) return $A(inputs).map(Element.extend); 6386
6387 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { 6388 var input = inputs[i]; 6389 if ((typeName && input.type != typeName) || (name && input.name != name)) 6390 continue; 6391 matchingInputs.push(Element.extend(input)); 6392 } 6393 6394 return matchingInputs; 6395 }, 6396 6397 disable: function(form) { 6398 form = $(form); 6399 Form.getElements(form).invoke('disable'); 6400 return form; 6401 }, 6402 6403 enable: function(form) { 6404 form = $(form); 6405 Form.getElements(form).invoke('enable'); 6406 return form; 6407 }, 6408 6409 findFirstElement: function(form) { 6410 var elements = $(form).getElements().findAll(function(element) { 6411 return 'hidden' != element.type && !element.disabled; 6412 }); 6413 var firstByIndex = elements.findAll(function(element) { 6414 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; 6415 }).sortBy(function(element) { return element.tabIndex }).first(); 6416 6417 return firstByIndex ? firstByIndex : elements.find(function(element) { 6418 return /^(?:input|select|textarea)$/i.test(element.tagName); 6419 }); 6420 }, 6421 6422 focusFirstElement: function(form) { 6423 form = $(form); 6424 var element = form.findFirstElement(); 6425 if (element) element.activate(); 6426 return form; 6427 }, 6428 6429 request: function(form, options) { 6430 form = $(form), options = Object.clone(options || { }); 6431 6432 var params = options.parameters, action = form.readAttribute('action') || ''; 6433 if (action.blank()) action = window.location.href; 6434 options.parameters = form.serialize(true); 6435 6436 if (params) { 6437 if (Object.isString(params)) params = params.toQueryParams(); 6438 Object.extend(options.parameters, params); 6439 } 6440 6441 if (form.hasAttribute('method') && !options.method) 6442 options.method = form.method; 6443 6444 return new Ajax.Request(action, options); 6445 } 6446}; 6447 6448/*--------------------------------------------------------------------------*/ 6449 6450 6451Form.Element = { 6452 focus: function(element) { 6453 $(element).focus(); 6454 return element; 6455 }, 6456 6457 select: function(element) { 6458 $(element).select(); 6459 return element; 6460 } 6461}; 6462 6463Form.Element.Methods = { 6464 6465 serialize: function(element) { 6466 element = $(element); 6467 if (!element.disabled && element.name) { 6468 var value = element.getValue(); 6469 if (value != undefined) { 6470 var pair = { }; 6471 pair[element.name] = value; 6472 return Object.toQueryString(pair); 6473 } 6474 } 6475 return ''; 6476 }, 6477 6478 getValue: function(element) { 6479 element = $(element); 6480 var method = element.tagName.toLowerCase(); 6481 return Form.Element.Serializers[method](element); 6482 }, 6483 6484 setValue: function(element, value) { 6485 element = $(element); 6486 var method = element.tagName.toLowerCase(); 6487 Form.Element.Serializers[method](element, value); 6488 return element; 6489 }, 6490 6491 clear: function(element) { 6492 $(element).value = ''; 6493 return element; 6494 }, 6495 6496 present: function(element) { 6497 return $(element).value != ''; 6498 }, 6499 6500 activate: function(element) { 6501 element = $(element); 6502 try { 6503 element.focus(); 6504 if (element.select && (element.tagName.toLowerCase() != 'input' || 6505 !(/^(?:button|reset|submit)$/i.test(element.type)))) 6506 element.select(); 6507 } catch (e) { } 6508 return element; 6509 }, 6510 6511 disable: function(element) { 6512 element = $(element); 6513 element.disabled = true; 6514 return element; 6515 }, 6516 6517 enable: function(element) { 6518 element = $(element); 6519 element.disabled = false; 6520 return element; 6521 } 6522}; 6523 6524/*--------------------------------------------------------------------------*/ 6525 6526var Field = Form.Element; 6527 6528var $F = Form.Element.Methods.getValue; 6529 6530/*--------------------------------------------------------------------------*/ 6531 6532Form.Element.Serializers = (function() { 6533 function input(element, value) { 6534 switch (element.type.toLowerCase()) { 6535 case 'checkbox': 6536 case 'radio': 6537 return inputSelector(element, value); 6538 default: 6539 return valueSelector(element, value); 6540 } 6541 } 6542 6543 function inputSelector(element, value) { 6544 if (Object.isUndefined(value)) 6545 return element.checked ? element.value : null; 6546 else element.checked = !!value; 6547 } 6548 6549 function valueSelector(element, value) { 6550 if (Object.isUndefined(value)) return element.value; 6551 else element.value = value; 6552 } 6553 6554 function select(element, value) { 6555 if (Object.isUndefined(value)) 6556 return (element.type === 'select-one' ? selectOne : selectMany)(element); 6557 6558 var opt, currentValue, single = !Object.isArray(value); 6559 for (var i = 0, length = element.length; i < length; i++) { 6560 opt = element.options[i]; 6561 currentValue = this.optionValue(opt); 6562 if (single) { 6563 if (currentValue == value) { 6564 opt.selected = true; 6565 return; 6566 } 6567 } 6568 else opt.selected = value.include(currentValue); 6569 } 6570 } 6571 6572 function selectOne(element) { 6573 var index = element.selectedIndex; 6574 return index >= 0 ? optionValue(element.options[index]) : null; 6575 } 6576 6577 function selectMany(element) { 6578 var values, length = element.length; 6579 if (!length) return null; 6580 6581 for (var i = 0, values = []; i < length; i++) { 6582 var opt = element.options[i]; 6583 if (opt.selected) values.push(optionValue(opt)); 6584 } 6585 return values; 6586 } 6587 6588 function optionValue(opt) { 6589 return Element.hasAttribute(opt, 'value') ? opt.value : opt.text; 6590 } 6591 6592 return { 6593 input: input, 6594 inputSelector: inputSelector, 6595 textarea: valueSelector, 6596 select: select, 6597 selectOne: selectOne, 6598 selectMany: selectMany, 6599 optionValue: optionValue, 6600 button: valueSelector 6601 }; 6602})(); 6603 6604/*--------------------------------------------------------------------------*/ 6605 6606 6607Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 6608 initialize: function($super, element, frequency, callback) { 6609 $super(callback, frequency); 6610 this.element = $(element); 6611 this.lastValue = this.getValue(); 6612 }, 6613 6614 execute: function() { 6615 var value = this.getValue(); 6616 if (Object.isString(this.lastValue) && Object.isString(value) ? 6617 this.lastValue != value : String(this.lastValue) != String(value)) { 6618 this.callback(this.element, value); 6619 this.lastValue = value; 6620 } 6621 } 6622}); 6623 6624Form.Element.Observer = Class.create(Abstract.TimedObserver, { 6625 getValue: function() { 6626 return Form.Element.getValue(this.element); 6627 } 6628}); 6629 6630Form.Observer = Class.create(Abstract.TimedObserver, { 6631 getValue: function() { 6632 return Form.serialize(this.element); 6633 } 6634}); 6635 6636/*--------------------------------------------------------------------------*/ 6637 6638Abstract.EventObserver = Class.create({ 6639 initialize: function(element, callback) { 6640 this.element = $(element); 6641 this.callback = callback; 6642 6643 this.lastValue = this.getValue(); 6644 if (this.element.tagName.toLowerCase() == 'form') 6645 this.registerFormCallbacks(); 6646 else 6647 this.registerCallback(this.element); 6648 }, 6649 6650 onElementEvent: function() { 6651 var value = this.getValue(); 6652 if (this.lastValue != value) { 6653 this.callback(this.element, value); 6654 this.lastValue = value; 6655 } 6656 }, 6657 6658 registerFormCallbacks: function() { 6659 Form.getElements(this.element).each(this.registerCallback, this); 6660 }, 6661 6662 registerCallback: function(element) { 6663 if (element.type) { 6664 switch (element.type.toLowerCase()) { 6665 case 'checkbox': 6666 case 'radio': 6667 Event.observe(element, 'click', this.onElementEvent.bind(this)); 6668 break; 6669 default: 6670 Event.observe(element, 'change', this.onElementEvent.bind(this)); 6671 break; 6672 } 6673 } 6674 } 6675}); 6676 6677Form.Element.EventObserver = Class.create(Abstract.EventObserver, { 6678 getValue: function() { 6679 return Form.Element.getValue(this.element); 6680 } 6681}); 6682 6683Form.EventObserver = Class.create(Abstract.EventObserver, { 6684 getValue: function() { 6685 return Form.serialize(this.element); 6686 } 6687}); 6688(function(GLOBAL) { 6689 var DIV = document.createElement('div'); 6690 var docEl = document.documentElement; 6691 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl 6692 && 'onmouseleave' in docEl; 6693 6694 var Event = { 6695 KEY_BACKSPACE: 8, 6696 KEY_TAB: 9, 6697 KEY_RETURN: 13, 6698 KEY_ESC: 27, 6699 KEY_LEFT: 37, 6700 KEY_UP: 38, 6701 KEY_RIGHT: 39, 6702 KEY_DOWN: 40, 6703 KEY_DELETE: 46, 6704 KEY_HOME: 36, 6705 KEY_END: 35, 6706 KEY_PAGEUP: 33, 6707 KEY_PAGEDOWN: 34, 6708 KEY_INSERT: 45 6709 }; 6710 6711 6712 var isIELegacyEvent = function(event) { return false; }; 6713 6714 if (window.attachEvent) { 6715 if (window.addEventListener) { 6716 isIELegacyEvent = function(event) { 6717 return !(event instanceof window.Event); 6718 }; 6719 } else { 6720 isIELegacyEvent = function(event) { return true; }; 6721 } 6722 } 6723 6724 var _isButton; 6725 6726 function _isButtonForDOMEvents(event, code) { 6727 return event.which ? (event.which === code + 1) : (event.button === code); 6728 } 6729 6730 var legacyButtonMap = { 0: 1, 1: 4, 2: 2 }; 6731 function _isButtonForLegacyEvents(event, code) { 6732 return event.button === legacyButtonMap[code]; 6733 } 6734 6735 function _isButtonForWebKit(event, code) { 6736 switch (code) { 6737 case 0: return event.which == 1 && !event.metaKey; 6738 case 1: return event.which == 2 || (event.which == 1 && event.metaKey); 6739 case 2: return event.which == 3; 6740 default: return false;
6741 } 6742 } 6743 6744 if (window.attachEvent) { 6745 if (!window.addEventListener) { 6746 _isButton = _isButtonForLegacyEvents; 6747 } else { 6748 _isButton = function(event, code) { 6749 return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) : 6750 _isButtonForDOMEvents(event, code); 6751 } 6752 } 6753 } else if (Prototype.Browser.WebKit) { 6754 _isButton = _isButtonForWebKit; 6755 } else { 6756 _isButton = _isButtonForDOMEvents; 6757 } 6758 6759 function isLeftClick(event) { return _isButton(event, 0) } 6760 6761 function isMiddleClick(event) { return _isButton(event, 1) } 6762 6763 function isRightClick(event) { return _isButton(event, 2) } 6764 6765 function element(event) { 6766 return Element.extend(_element(event)); 6767 } 6768 6769 function _element(event) { 6770 event = Event.extend(event); 6771 6772 var node = event.target, type = event.type, 6773 currentTarget = event.currentTarget; 6774 6775 if (currentTarget && currentTarget.tagName) { 6776 if (type === 'load' || type === 'error' || 6777 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' 6778 && currentTarget.type === 'radio')) 6779 node = currentTarget; 6780 } 6781 6782 return node.nodeType == Node.TEXT_NODE ? node.parentNode : node; 6783 } 6784 6785 function findElement(event, expression) { 6786 var element = _element(event), selector = Prototype.Selector; 6787 if (!expression) return Element.extend(element); 6788 while (element) { 6789 if (Object.isElement(element) && selector.match(element, expression)) 6790 return Element.extend(element); 6791 element = element.parentNode; 6792 } 6793 } 6794 6795 function pointer(event) { 6796 return { x: pointerX(event), y: pointerY(event) }; 6797 } 6798 6799 function pointerX(event) { 6800 var docElement = document.documentElement, 6801 body = document.body || { scrollLeft: 0 }; 6802 6803 return event.pageX || (event.clientX + 6804 (docElement.scrollLeft || body.scrollLeft) - 6805 (docElement.clientLeft || 0)); 6806 } 6807 6808 function pointerY(event) { 6809 var docElement = document.documentElement, 6810 body = document.body || { scrollTop: 0 }; 6811 6812 return event.pageY || (event.clientY + 6813 (docElement.scrollTop || body.scrollTop) - 6814 (docElement.clientTop || 0)); 6815 } 6816 6817 6818 function stop(event) { 6819 Event.extend(event); 6820 event.preventDefault(); 6821 event.stopPropagation(); 6822 6823 event.stopped = true; 6824 } 6825 6826 6827 Event.Methods = { 6828 isLeftClick: isLeftClick, 6829 isMiddleClick: isMiddleClick, 6830 isRightClick: isRightClick, 6831 6832 element: element, 6833 findElement: findElement, 6834 6835 pointer: pointer, 6836 pointerX: pointerX, 6837 pointerY: pointerY, 6838 6839 stop: stop 6840 }; 6841 6842 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 6843 m[name] = Event.Methods[name].methodize(); 6844 return m; 6845 }); 6846 6847 if (window.attachEvent) { 6848 function _relatedTarget(event) { 6849 var element; 6850 switch (event.type) { 6851 case 'mouseover': 6852 case 'mouseenter': 6853 element = event.fromElement; 6854 break; 6855 case 'mouseout': 6856 case 'mouseleave': 6857 element = event.toElement; 6858 break; 6859 default: 6860 return null; 6861 } 6862 return Element.extend(element); 6863 } 6864 6865 var additionalMethods = { 6866 stopPropagation: function() { this.cancelBubble = true }, 6867 preventDefault: function() { this.returnValue = false }, 6868 inspect: function() { return '[object Event]' } 6869 }; 6870 6871 Event.extend = function(event, element) { 6872 if (!event) return false; 6873 6874 if (!isIELegacyEvent(event)) return event; 6875 6876 if (event._extendedByPrototype) return event; 6877 event._extendedByPrototype = Prototype.emptyFunction; 6878 6879 var pointer = Event.pointer(event); 6880 6881 Object.extend(event, { 6882 target: event.srcElement || element, 6883 relatedTarget: _relatedTarget(event), 6884 pageX: pointer.x, 6885 pageY: pointer.y 6886 }); 6887 6888 Object.extend(event, methods); 6889 Object.extend(event, additionalMethods); 6890 6891 return event; 6892 }; 6893 } else { 6894 Event.extend = Prototype.K; 6895 } 6896 6897 if (window.addEventListener) { 6898 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; 6899 Object.extend(Event.prototype, methods); 6900 } 6901 6902 var EVENT_TRANSLATIONS = { 6903 mouseenter: 'mouseover', 6904 mouseleave: 'mouseout' 6905 }; 6906 6907 function getDOMEventName(eventName) { 6908 return EVENT_TRANSLATIONS[eventName] || eventName; 6909 } 6910 6911 if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) 6912 getDOMEventName = Prototype.K; 6913 6914 function getUniqueElementID(element) { 6915 if (element === window) return 0; 6916 6917 if (typeof element._prototypeUID === 'undefined') 6918 element._prototypeUID = Element.Storage.UID++; 6919 return element._prototypeUID; 6920 } 6921 6922 function getUniqueElementID_IE(element) { 6923 if (element === window) return 0; 6924 if (element == document) return 1; 6925 return element.uniqueID; 6926 } 6927 6928 if ('uniqueID' in DIV) 6929 getUniqueElementID = getUniqueElementID_IE; 6930 6931 function isCustomEvent(eventName) { 6932 return eventName.include(':'); 6933 } 6934 6935 Event._isCustomEvent = isCustomEvent; 6936 6937 function getOrCreateRegistryFor(element, uid) { 6938 var CACHE = GLOBAL.Event.cache;
6939 if (Object.isUndefined(uid)) 6940 uid = getUniqueElementID(element); 6941 if (!CACHE[uid]) CACHE[uid] = { element: element }; 6942 return CACHE[uid]; 6943 } 6944 6945 function destroyRegistryForElement(element, uid) { 6946 if (Object.isUndefined(uid)) 6947 uid = getUniqueElementID(element); 6948 delete GLOBAL.Event.cache[uid]; 6949 } 6950 6951 6952 function register(element, eventName, handler) { 6953 var registry = getOrCreateRegistryFor(element); 6954 if (!registry[eventName]) registry[eventName] = []; 6955 var entries = registry[eventName]; 6956 6957 var i = entries.length; 6958 while (i--) 6959 if (entries[i].handler === handler) return null; 6960 6961 var uid = getUniqueElementID(element); 6962 var responder = GLOBAL.Event._createResponder(uid, eventName, handler); 6963 var entry = { 6964 responder: responder, 6965 handler: handler 6966 }; 6967 6968 entries.push(entry); 6969 return entry; 6970 } 6971 6972 function unregister(element, eventName, handler) { 6973 var registry = getOrCreateRegistryFor(element); 6974 var entries = registry[eventName] || []; 6975 6976 var i = entries.length, entry; 6977 while (i--) { 6978 if (entries[i].handler === handler) { 6979 entry = entries[i]; 6980 break; 6981 } 6982 } 6983 6984 if (entry) { 6985 var index = entries.indexOf(entry); 6986 entries.splice(index, 1); 6987 } 6988 6989 if (entries.length === 0) { 6990 delete registry[eventName]; 6991 if (Object.keys(registry).length === 1 && ('element' in registry)) 6992 destroyRegistryForElement(element); 6993 } 6994 6995 return entry; 6996 } 6997 6998 6999 function observe(element, eventName, handler) { 7000 element = $(element); 7001 var entry = register(element, eventName, handler); 7002 7003 if (entry === null) return element; 7004 7005 var responder = entry.responder; 7006 if (isCustomEvent(eventName)) 7007 observeCustomEvent(element, eventName, responder); 7008 else 7009 observeStandardEvent(element, eventName, responder); 7010 7011 return element; 7012 } 7013 7014 function observeStandardEvent(element, eventName, responder) { 7015 var actualEventName = getDOMEventName(eventName); 7016 if (element.addEventListener) { 7017 element.addEventListener(actualEventName, responder, false); 7018 } else { 7019 element.attachEvent('on' + actualEventName, responder); 7020 } 7021 } 7022 7023 function observeCustomEvent(element, eventName, responder) { 7024 if (element.addEventListener) { 7025 element.addEventListener('dataavailable', responder, false); 7026 } else { 7027 element.attachEvent('ondataavailable', responder); 7028 element.attachEvent('onlosecapture', responder); 7029 } 7030 } 7031 7032 function stopObserving(element, eventName, handler) { 7033 element = $(element); 7034 var handlerGiven = !Object.isUndefined(handler), 7035 eventNameGiven = !Object.isUndefined(eventName); 7036 7037 if (!eventNameGiven && !handlerGiven) { 7038 stopObservingElement(element); 7039 return element; 7040 } 7041 7042 if (!handlerGiven) { 7043 stopObservingEventName(element, eventName); 7044 return element; 7045 } 7046 7047 var entry = unregister(element, eventName, handler); 7048 7049 if (!entry) return element; 7050 removeEvent(element, eventName, entry.responder); 7051 return element; 7052 } 7053 7054 function stopObservingStandardEvent(element, eventName, responder) { 7055 var actualEventName = getDOMEventName(eventName); 7056 if (element.removeEventListener) { 7057 element.removeEventListener(actualEventName, responder, false); 7058 } else { 7059 element.detachEvent('on' + actualEventName, responder); 7060 } 7061 } 7062 7063 function stopObservingCustomEvent(element, eventName, responder) { 7064 if (element.removeEventListener) { 7065 element.removeEventListener('dataavailable', responder, false); 7066 } else { 7067 element.detachEvent('ondataavailable', responder); 7068 element.detachEvent('onlosecapture', responder); 7069 } 7070 } 7071 7072 7073 7074 function stopObservingElement(element) { 7075 var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid]; 7076 if (!registry) return; 7077 7078 destroyRegistryForElement(element, uid); 7079 7080 var entries, i; 7081 for (var eventName in registry) { 7082 if (eventName === 'element') continue; 7083 7084 entries = registry[eventName]; 7085 i = entries.length; 7086 while (i--) 7087 removeEvent(element, eventName, entries[i].responder); 7088 } 7089 } 7090 7091 function stopObservingEventName(element, eventName) { 7092 var registry = getOrCreateRegistryFor(element); 7093 var entries = registry[eventName]; 7094 if (entries) { 7095 delete registry[eventName]; 7096 } 7097 7098 entries = entries || []; 7099 7100 var i = entries.length; 7101 while (i--) 7102 removeEvent(element, eventName, entries[i].responder); 7103 7104 for (var name in registry) { 7105 if (name === 'element') continue; 7106 return; // There is another registered event 7107 } 7108 7109 destroyRegistryForElement(element); 7110 } 7111 7112 7113 function removeEvent(element, eventName, handler) { 7114 if (isCustomEvent(eventName)) 7115 stopObservingCustomEvent(element, eventName, handler); 7116 else 7117 stopObservingStandardEvent(element, eventName, handler); 7118 } 7119 7120 7121 7122 function getFireTarget(element) { 7123 if (element !== document) return element; 7124 if (document.createEvent && !element.dispatchEvent) 7125 return document.documentElement; 7126 return element; 7127 } 7128 7129 function fire(element, eventName, memo, bubble) { 7130 element = getFireTarget($(element)); 7131 if (Object.isUndefined(bubble)) bubble = true; 7132 memo = memo || {}; 7133 7134 var event = fireEvent(element, eventName, memo, bubble); 7135 return Event.extend(event); 7136 } 7137 7138 function fireEvent_DOM(element, eventName, memo, bubble) { 7139 var event = document.createEvent('HTMLEvents'); 7140 event.initEvent('dataavailable', bubble, true); 7141 7142 event.eventName = eventName; 7143 event.memo = memo; 7144 7145 element.dispatchEvent(event); 7146 return event; 7147 } 7148 7149 function fireEvent_IE(element, eventName, memo, bubble) { 7150 var event = document.createEventObject(); 7151 event.eventType = bubble ? 'ondataavailable' : 'onlosecapture'; 7152 7153 event.eventName = eventName; 7154 event.memo = memo; 7155 7156 element.fireEvent(event.eventType, event); 7157 return event; 7158 } 7159 7160 var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE; 7161 7162 7163 7164 Event.Handler = Class.create({ 7165 initialize: function(element, eventName, selector, callback) { 7166 this.element = $(element); 7167 this.eventName = eventName; 7168 this.selector = selector; 7169 this.callback = callback; 7170 this.handler = this.handleEvent.bind(this); 7171 }, 7172 7173 7174 start: function() { 7175 Event.observe(this.element, this.eventName, this.handler); 7176 return this; 7177 }, 7178 7179 stop: function() { 7180 Event.stopObserving(this.element, this.eventName, this.handler); 7181 return this; 7182 }, 7183 7184 handleEvent: function(event) { 7185 var element = Event.findElement(event, this.selector); 7186 if (element) this.callback.call(this.element, event, element); 7187 } 7188 }); 7189 7190 function on(element, eventName, selector, callback) { 7191 element = $(element); 7192 if (Object.isFunction(selector) && Object.isUndefined(callback)) { 7193 callback = selector, selector = null; 7194 } 7195 7196 return new Event.Handler(element, eventName, selector, callback).start(); 7197 } 7198 7199 Object.extend(Event, Event.Methods); 7200 7201 Object.extend(Event, { 7202 fire: fire, 7203 observe: observe, 7204 stopObserving: stopObserving, 7205 on: on 7206 }); 7207 7208 Element.addMethods({ 7209 fire: fire, 7210 7211 observe: observe, 7212 7213 stopObserving: stopObserving, 7214 7215 on: on 7216 }); 7217 7218 Object.extend(document, { 7219 fire: fire.methodize(), 7220 7221 observe: observe.methodize(), 7222 7223 stopObserving: stopObserving.methodize(), 7224 7225 on: on.methodize(), 7226 7227 loaded: false 7228 }); 7229 7230 if (GLOBAL.Event) Object.extend(window.Event, Event); 7231 else GLOBAL.Event = Event; 7232 7233 GLOBAL.Event.cache = {}; 7234 7235 function destroyCache_IE() { 7236 GLOBAL.Event.cache = null; 7237 } 7238 7239 if (window.attachEvent) 7240 window.attachEvent('onunload', destroyCache_IE); 7241 7242 DIV = null; 7243 docEl = null; 7244})(this); 7245 7246(function(GLOBAL) { 7247 /* Code for creating leak-free event responders is based on work by 7248 John-David Dalton. */ 7249 7250 var docEl = document.documentElement; 7251 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl 7252 && 'onmouseleave' in docEl; 7253 7254 function isSimulatedMouseEnterLeaveEvent(eventName) { 7255 return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && 7256 (eventName === 'mouseenter' || eventName === 'mouseleave'); 7257 } 7258 7259 function createResponder(uid, eventName, handler) { 7260 if (Event._isCustomEvent(eventName)) 7261 return createResponderForCustomEvent(uid, eventName, handler); 7262 if (isSimulatedMouseEnterLeaveEvent(eventName)) 7263 return createMouseEnterLeaveResponder(uid, eventName, handler); 7264 7265 return function(event) { 7266 if (!Event.cache) return; 7267 7268 var element = Event.cache[uid].element; 7269 Event.extend(event, element); 7270 handler.call(element, event); 7271 }; 7272 } 7273 7274 function createResponderForCustomEvent(uid, eventName, handler) { 7275 return function(event) { 7276 var cache = Event.cache[uid]; 7277 var element = cache && cache.element; 7278 7279 if (Object.isUndefined(event.eventName)) 7280 return false;
7281 7282 if (event.eventName !== eventName) 7283 return false; 7284 7285 Event.extend(event, element); 7286 handler.call(element, event); 7287 }; 7288 } 7289 7290 function createMouseEnterLeaveResponder(uid, eventName, handler) { 7291 return function(event) { 7292 var element = Event.cache[uid].element; 7293 7294 Event.extend(event, element); 7295 var parent = event.relatedTarget; 7296 7297 while (parent && parent !== element) { 7298 try { parent = parent.parentNode; } 7299 catch(e) { parent = element; } 7300 } 7301 7302 if (parent === element) return; 7303 handler.call(element, event); 7304 } 7305 } 7306 7307 GLOBAL.Event._createResponder = createResponder; 7308 docEl = null; 7309})(this); 7310 7311(function(GLOBAL) { 7312 /* Support for the DOMContentLoaded event is based on work by Dan Webb, 7313 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ 7314 7315 var TIMER; 7316 7317 function fireContentLoadedEvent() { 7318 if (document.loaded) return; 7319 if (TIMER) window.clearTimeout(TIMER); 7320 document.loaded = true; 7321 document.fire('dom:loaded'); 7322 } 7323 7324 function checkReadyState() { 7325 if (document.readyState === 'complete') { 7326 document.detachEvent('onreadystatechange', checkReadyState); 7327 fireContentLoadedEvent(); 7328 } 7329 } 7330 7331 function pollDoScroll() { 7332 try { 7333 document.documentElement.doScroll('left'); 7334 } catch (e) { 7335 TIMER = pollDoScroll.defer(); 7336 return; 7337 } 7338 7339 fireContentLoadedEvent(); 7340 } 7341 7342 7343 if (document.readyState === 'complete') { 7344 fireContentLoadedEvent(); 7345 return; 7346 } 7347 7348 if (document.addEventListener) { 7349 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); 7350 } else { 7351 document.attachEvent('onreadystatechange', checkReadyState); 7352 if (window == top) TIMER = pollDoScroll.defer(); 7353 } 7354 7355 Event.observe(window, 'load', fireContentLoadedEvent); 7356})(this); 7357 7358 7359Element.addMethods(); 7360/*------------------------------- DEPRECATED -------------------------------*/ 7361 7362Hash.toQueryString = Object.toQueryString; 7363 7364var Toggle = { display: Element.toggle }; 7365 7366Element.addMethods({ 7367 childOf: Element.Methods.descendantOf 7368}); 7369 7370var Insertion = { 7371 Before: function(element, content) { 7372 return Element.insert(element, {before:content}); 7373 }, 7374 7375 Top: function(element, content) { 7376 return Element.insert(element, {top:content}); 7377 }, 7378 7379 Bottom: function(element, content) { 7380 return Element.insert(element, {bottom:content}); 7381 }, 7382 7383 After: function(element, content) { 7384 return Element.insert(element, {after:content}); 7385 } 7386}; 7387 7388var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 7389 7390var Position = { 7391 includeScrollOffsets: false, 7392 7393 prepare: function() { 7394 this.deltaX = window.pageXOffset 7395 || document.documentElement.scrollLeft 7396 || document.body.scrollLeft 7397 || 0; 7398 this.deltaY = window.pageYOffset 7399 || document.documentElement.scrollTop 7400 || document.body.scrollTop 7401 || 0; 7402 }, 7403 7404 within: function(element, x, y) { 7405 if (this.includeScrollOffsets) 7406 return this.withinIncludingScrolloffsets(element, x, y); 7407 this.xcomp = x; 7408 this.ycomp = y; 7409 this.offset = Element.cumulativeOffset(element); 7410 7411 return (y >= this.offset[1] && 7412 y < this.offset[1] + element.offsetHeight && 7413 x >= this.offset[0] && 7414 x < this.offset[0] + element.offsetWidth); 7415 }, 7416 7417 withinIncludingScrolloffsets: function(element, x, y) { 7418 var offsetcache = Element.cumulativeScrollOffset(element); 7419 7420 this.xcomp = x + offsetcache[0] - this.deltaX; 7421 this.ycomp = y + offsetcache[1] - this.deltaY; 7422 this.offset = Element.cumulativeOffset(element); 7423 7424 return (this.ycomp >= this.offset[1] && 7425 this.ycomp < this.offset[1] + element.offsetHeight && 7426 this.xcomp >= this.offset[0] && 7427 this.xcomp < this.offset[0] + element.offsetWidth); 7428 }, 7429 7430 overlap: function(mode, element) { 7431 if (!mode) return 0; 7432 if (mode == 'vertical') 7433 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 7434 element.offsetHeight; 7435 if (mode == 'horizontal') 7436 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 7437 element.offsetWidth; 7438 }, 7439 7440 7441 cumulativeOffset: Element.Methods.cumulativeOffset, 7442 7443 positionedOffset: Element.Methods.positionedOffset, 7444 7445 absolutize: function(element) { 7446 Position.prepare(); 7447 return Element.absolutize(element); 7448 }, 7449 7450 relativize: function(element) { 7451 Position.prepare(); 7452 return Element.relativize(element); 7453 }, 7454 7455 realOffset: Element.Methods.cumulativeScrollOffset, 7456 7457 offsetParent: Element.Methods.getOffsetParent, 7458 7459 page: Element.Methods.viewportOffset, 7460 7461 clone: function(source, target, options) { 7462 options = options || { }; 7463 return Element.clonePosition(target, source, options); 7464 } 7465}; 7466 7467/*--------------------------------------------------------------------------*/ 7468 7469if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ 7470 function iter(name) { 7471 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; 7472 } 7473 7474 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? 7475 function(element, className) {
7476 className = className.toString().strip(); 7477 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); 7478 return cond ? document._getElementsByXPath('.//*' + cond, element) : []; 7479 } : function(element, className) { 7480 className = className.toString().strip(); 7481 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); 7482 if (!classNames && !className) return elements; 7483 7484 var nodes = $(element).getElementsByTagName('*'); 7485 className = ' ' + className + ' '; 7486 7487 for (var i = 0, child, cn; child = nodes[i]; i++) { 7488 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || 7489 (classNames && classNames.all(function(name) { 7490 return !name.toString().blank() && cn.include(' ' + name + ' '); 7491 })))) 7492 elements.push(Element.extend(child)); 7493 } 7494 return elements; 7495 }; 7496 7497 return function(className, parentElement) { 7498 return $(parentElement || document.body).getElementsByClassName(className); 7499 }; 7500}(Element.Methods); 7501 7502/*--------------------------------------------------------------------------*/ 7503 7504Element.ClassNames = Class.create(); 7505Element.ClassNames.prototype = { 7506 initialize: function(element) { 7507 this.element = $(element); 7508 }, 7509 7510 _each: function(iterator, context) { 7511 this.element.className.split(/\s+/).select(function(name) { 7512 return name.length > 0; 7513 })._each(iterator, context); 7514 }, 7515 7516 set: function(className) { 7517 this.element.className = className; 7518 }, 7519 7520 add: function(classNameToAdd) { 7521 if (this.include(classNameToAdd)) return; 7522 this.set($A(this).concat(classNameToAdd).join(' ')); 7523 }, 7524 7525 remove: function(classNameToRemove) { 7526 if (!this.include(classNameToRemove)) return; 7527 this.set($A(this).without(classNameToRemove).join(' ')); 7528 }, 7529 7530 toString: function() { 7531 return $A(this).join(' '); 7532 } 7533}; 7534 7535Object.extend(Element.ClassNames.prototype, Enumerable); 7536 7537/*--------------------------------------------------------------------------*/ 7538 7539(function() { 7540 window.Selector = Class.create({ 7541 initialize: function(expression) { 7542 this.expression = expression.strip(); 7543 }, 7544 7545 findElements: function(rootElement) { 7546 return Prototype.Selector.select(this.expression, rootElement); 7547 }, 7548 7549 match: function(element) { 7550 return Prototype.Selector.match(element, this.expression); 7551 }, 7552 7553 toString: function() { 7554 return this.expression; 7555 }, 7556 7557 inspect: function() { 7558 return "#<Selector: " + this.expression + ">"; 7559 } 7560 }); 7561 7562 Object.extend(Selector, { 7563 matchElements: function(elements, expression) { 7564 var match = Prototype.Selector.match, 7565 results = []; 7566 7567 for (var i = 0, length = elements.length; i < length; i++) { 7568 var element = elements[i]; 7569 if (match(element, expression)) { 7570 results.push(Element.extend(element)); 7571 } 7572 } 7573 return results; 7574 }, 7575 7576 findElement: function(elements, expression, index) { 7577 index = index || 0; 7578 var matchIndex = 0, element; 7579 for (var i = 0, length = elements.length; i < length; i++) { 7580 element = elements[i]; 7581 if (Prototype.Selector.match(element, expression) && index === matchIndex++) { 7582 return Element.extend(element); 7583 } 7584 } 7585 }, 7586 7587 findChildElements: function(element, expressions) { 7588 var selector = expressions.toArray().join(', '); 7589 return Prototype.Selector.select(selector, element || document); 7590 } 7591 }); 7592})(); 7593// script.aculo.us builder.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 7594 7595// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 7596// 7597// script.aculo.us is freely distributable under the terms of an MIT-style license. 7598// For details, see the script.aculo.us web site: http://script.aculo.us/ 7599 7600var Builder = { 7601 NODEMAP: { 7602 AREA: 'map', 7603 CAPTION: 'table', 7604 COL: 'table', 7605 COLGROUP: 'table', 7606 LEGEND: 'fieldset', 7607 OPTGROUP: 'select', 7608 OPTION: 'select', 7609 PARAM: 'object', 7610 TBODY: 'table', 7611 TD: 'table', 7612 TFOOT: 'table', 7613 TH: 'table', 7614 THEAD: 'table', 7615 TR: 'table' 7616 }, 7617 // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, 7618 // due to a Firefox bug 7619 node: function(elementName) { 7620 elementName = elementName.toUpperCase(); 7621 7622 // try innerHTML approach 7623 var parentTag = this.NODEMAP[elementName] || 'div'; 7624 var parentElement = document.createElement(parentTag); 7625 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 7626 parentElement.innerHTML = "<" + elementName + "></" + elementName + ">"; 7627 } catch(e) {} 7628 var element = parentElement.firstChild || null; 7629 7630 // see if browser added wrapping tags 7631 if(element && (element.tagName.toUpperCase() != elementName)) 7632 element = element.getElementsByTagName(elementName)[0]; 7633 7634 // fallback to createElement approach 7635 if(!element) element = document.createElement(elementName); 7636 7637 // abort if nothing could be created 7638 if(!element) return; 7639 7640 // attributes (or text) 7641 if(arguments[1]) 7642 if(this._isStringOrNumber(arguments[1]) || 7643 (arguments[1] instanceof Array) || 7644 arguments[1].tagName) { 7645 this._children(element, arguments[1]); 7646 } else { 7647 var attrs = this._attributes(arguments[1]); 7648 if(attrs.length) { 7649 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 7650 parentElement.innerHTML = "<" +elementName + " " + 7651 attrs + "></" + elementName + ">"; 7652 } catch(e) {} 7653 element = parentElement.firstChild || null; 7654 // workaround firefox 1.0.X bug 7655 if(!element) { 7656 element = document.createElement(elementName); 7657 for(attr in arguments[1]) 7658 element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; 7659 } 7660 if(element.tagName.toUpperCase() != elementName) 7661 element = parentElement.getElementsByTagName(elementName)[0]; 7662 } 7663 } 7664 7665 // text, or array of children 7666 if(arguments[2]) 7667 this._children(element, arguments[2]); 7668 7669 return $(element); 7670 }, 7671 _text: function(text) { 7672 return document.createTextNode(text); 7673 }, 7674 7675 ATTR_MAP: { 7676 'className': 'class', 7677 'htmlFor': 'for' 7678 }, 7679 7680 _attributes: function(attributes) { 7681 var attrs = []; 7682 for(attribute in attributes) 7683 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + 7684 '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); 7685 return attrs.join(" "); 7686 }, 7687 _children: function(element, children) { 7688 if(children.tagName) { 7689 element.appendChild(children); 7690 return; 7691 } 7692 if(typeof children=='object') { // array can hold nodes and text 7693 children.flatten().each( function(e) { 7694 if(typeof e=='object') 7695 element.appendChild(e); 7696 else 7697 if(Builder._isStringOrNumber(e)) 7698 element.appendChild(Builder._text(e)); 7699 }); 7700 } else 7701 if(Builder._isStringOrNumber(children)) 7702 element.appendChild(Builder._text(children)); 7703 }, 7704 _isStringOrNumber: function(param) {
7705 return(typeof param=='string' || typeof param=='number'); 7706 }, 7707 build: function(html) { 7708 var element = this.node('div'); 7709 $(element).update(html.strip()); 7710 return element.down(); 7711 }, 7712 dump: function(scope) { 7713 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 7714 7715 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + 7716 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + 7717 "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ 7718 "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ 7719 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ 7720 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); 7721 7722 tags.each( function(tag){ 7723 scope[tag] = function() { 7724 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 7725 }; 7726 }); 7727 } 7728};// script.aculo.us effects.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 7729 7730// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 7731// Contributors: 7732// Justin Palmer (http://encytemedia.com/) 7733// Mark Pilgrim (http://diveintomark.org/) 7734// Martin Bialasinki 7735// 7736// script.aculo.us is freely distributable under the terms of an MIT-style license. 7737// For details, see the script.aculo.us web site: http://script.aculo.us/ 7738 7739// converts rgb() and #xxx to #xxxxxx format, 7740// returns self (or first argument) if not convertable 7741String.prototype.parseColor = function() { 7742 var color = '#'; 7743 if (this.slice(0,4) == 'rgb(') { 7744 var cols = this.slice(4,this.length-1).split(','); 7745 var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); 7746 } else { 7747 if (this.slice(0,1) == '#') { 7748 if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); 7749 if (this.length==7) color = this.toLowerCase(); 7750 } 7751 } 7752 return (color.length==7 ? color : (arguments[0] || this)); 7753}; 7754 7755/*--------------------------------------------------------------------------*/ 7756 7757Element.collectTextNodes = function(element) { 7758 return $A($(element).childNodes).collect( function(node) { 7759 return (node.nodeType==3 ? node.nodeValue : 7760 (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); 7761 }).flatten().join(''); 7762}; 7763 7764Element.collectTextNodesIgnoreClass = function(element, className) { 7765 return $A($(element).childNodes).collect( function(node) { 7766 return (node.nodeType==3 ? node.nodeValue : 7767 ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 7768 Element.collectTextNodesIgnoreClass(node, className) : '')); 7769 }).flatten().join(''); 7770}; 7771 7772Element.setContentZoom = function(element, percent) { 7773 element = $(element); 7774 element.setStyle({fontSize: (percent/100) + 'em'}); 7775 if (Prototype.Browser.WebKit) window.scrollBy(0,0); 7776 return element; 7777}; 7778 7779Element.getInlineOpacity = function(element){ 7780 return $(element).style.opacity || ''; 7781}; 7782 7783Element.forceRerendering = function(element) { 7784 try { 7785 element = $(element); 7786 var n = document.createTextNode(' '); 7787 element.appendChild(n); 7788 element.removeChild(n); 7789 } catch(e) { } 7790}; 7791 7792/*--------------------------------------------------------------------------*/ 7793 7794var Effect = { 7795 _elementDoesNotExistError: { 7796 name: 'ElementDoesNotExistError', 7797 message: 'The specified DOM element does not exist, but is required for this effect to operate' 7798 }, 7799 Transitions: { 7800 linear: Prototype.K, 7801 sinoidal: function(pos) { 7802 return (-Math.cos(pos*Math.PI)/2) + .5; 7803 }, 7804 reverse: function(pos) { 7805 return 1-pos; 7806 }, 7807 flicker: function(pos) { 7808 var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; 7809 return pos > 1 ? 1 : pos; 7810 }, 7811 wobble: function(pos) { 7812 return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; 7813 }, 7814 pulse: function(pos, pulses) { 7815 return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; 7816 }, 7817 spring: function(pos) { 7818 return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); 7819 }, 7820 none: function(pos) { 7821 return 0; 7822 }, 7823 full: function(pos) { 7824 return 1; 7825 } 7826 }, 7827 DefaultOptions: { 7828 duration: 1.0, // seconds 7829 fps: 100, // 100= assume 66fps max. 7830 sync: false, // true for combining 7831 from: 0.0, 7832 to: 1.0, 7833 delay: 0.0, 7834 queue: 'parallel' 7835 }, 7836 tagifyText: function(element) { 7837 var tagifyStyle = 'position:relative'; 7838 if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; 7839 7840 element = $(element); 7841 $A(element.childNodes).each( function(child) { 7842 if (child.nodeType==3) {
7843 child.nodeValue.toArray().each( function(character) { 7844 element.insertBefore( 7845 new Element('span', {style: tagifyStyle}).update( 7846 character == ' ' ? String.fromCharCode(160) : character), 7847 child); 7848 }); 7849 Element.remove(child); 7850 } 7851 }); 7852 }, 7853 multiple: function(element, effect) { 7854 var elements; 7855 if (((typeof element == 'object') || 7856 Object.isFunction(element)) && 7857 (element.length)) 7858 elements = element; 7859 else 7860 elements = $(element).childNodes; 7861 7862 var options = Object.extend({ 7863 speed: 0.1, 7864 delay: 0.0 7865 }, arguments[2] || { }); 7866 var masterDelay = options.delay; 7867 7868 $A(elements).each( function(element, index) { 7869 new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); 7870 }); 7871 }, 7872 PAIRS: { 7873 'slide': ['SlideDown','SlideUp'], 7874 'blind': ['BlindDown','BlindUp'], 7875 'appear': ['Appear','Fade'] 7876 }, 7877 toggle: function(element, effect, options) { 7878 element = $(element); 7879 effect = (effect || 'appear').toLowerCase(); 7880 7881 return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({ 7882 queue: { position:'end', scope:(element.id || 'global'), limit: 1 } 7883 }, options || {})); 7884 } 7885}; 7886 7887Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; 7888 7889/* ------------- core effects ------------- */ 7890 7891Effect.ScopedQueue = Class.create(Enumerable, { 7892 initialize: function() { 7893 this.effects = []; 7894 this.interval = null; 7895 }, 7896 _each: function(iterator) { 7897 this.effects._each(iterator); 7898 }, 7899 add: function(effect) { 7900 var timestamp = new Date().getTime(); 7901 7902 var position = Object.isString(effect.options.queue) ? 7903 effect.options.queue : effect.options.queue.position; 7904 7905 switch(position) { 7906 case 'front': 7907 // move unstarted effects after this effect 7908 this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { 7909 e.startOn += effect.finishOn; 7910 e.finishOn += effect.finishOn; 7911 }); 7912 break; 7913 case 'with-last': 7914 timestamp = this.effects.pluck('startOn').max() || timestamp; 7915 break; 7916 case 'end': 7917 // start effect after last queued effect has finished 7918 timestamp = this.effects.pluck('finishOn').max() || timestamp; 7919 break; 7920 } 7921 7922 effect.startOn += timestamp; 7923 effect.finishOn += timestamp; 7924 7925 if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) 7926 this.effects.push(effect); 7927 7928 if (!this.interval) 7929 this.interval = setInterval(this.loop.bind(this), 15); 7930 }, 7931 remove: function(effect) { 7932 this.effects = this.effects.reject(function(e) { return e==effect }); 7933 if (this.effects.length == 0) { 7934 clearInterval(this.interval); 7935 this.interval = null; 7936 } 7937 }, 7938 loop: function() { 7939 var timePos = new Date().getTime(); 7940 for(var i=0, len=this.effects.length;i<len;i++) 7941 this.effects[i] && this.effects[i].loop(timePos); 7942 } 7943}); 7944 7945Effect.Queues = { 7946 instances: $H(), 7947 get: function(queueName) { 7948 if (!Object.isString(queueName)) return queueName; 7949 7950 return this.instances.get(queueName) || 7951 this.instances.set(queueName, new Effect.ScopedQueue()); 7952 } 7953}; 7954Effect.Queue = Effect.Queues.get('global'); 7955 7956Effect.Base = Class.create({ 7957 position: null, 7958 start: function(options) { 7959 if (options && options.transition === false) options.transition = Effect.Transitions.linear; 7960 this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); 7961 this.currentFrame = 0; 7962 this.state = 'idle'; 7963 this.startOn = this.options.delay*1000; 7964 this.finishOn = this.startOn+(this.options.duration*1000); 7965 this.fromToDelta = this.options.to-this.options.from; 7966 this.totalTime = this.finishOn-this.startOn; 7967 this.totalFrames = this.options.fps*this.options.duration; 7968 7969 this.render = (function() { 7970 function dispatch(effect, eventName) { 7971 if (effect.options[eventName + 'Internal']) 7972 effect.options[eventName + 'Internal'](effect); 7973 if (effect.options[eventName]) 7974 effect.options[eventName](effect); 7975 } 7976 7977 return function(pos) {
7978 if (this.state === "idle") { 7979 this.state = "running"; 7980 dispatch(this, 'beforeSetup'); 7981 if (this.setup) this.setup(); 7982 dispatch(this, 'afterSetup'); 7983 } 7984 if (this.state === "running") { 7985 pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; 7986 this.position = pos; 7987 dispatch(this, 'beforeUpdate'); 7988 if (this.update) this.update(pos); 7989 dispatch(this, 'afterUpdate'); 7990 } 7991 }; 7992 })(); 7993 7994 this.event('beforeStart'); 7995 if (!this.options.sync) 7996 Effect.Queues.get(Object.isString(this.options.queue) ? 7997 'global' : this.options.queue.scope).add(this); 7998 }, 7999 loop: function(timePos) { 8000 if (timePos >= this.startOn) { 8001 if (timePos >= this.finishOn) { 8002 this.render(1.0); 8003 this.cancel(); 8004 this.event('beforeFinish'); 8005 if (this.finish) this.finish(); 8006 this.event('afterFinish'); 8007 return; 8008 } 8009 var pos = (timePos - this.startOn) / this.totalTime, 8010 frame = (pos * this.totalFrames).round(); 8011 if (frame > this.currentFrame) { 8012 this.render(pos); 8013 this.currentFrame = frame; 8014 } 8015 } 8016 }, 8017 cancel: function() { 8018 if (!this.options.sync) 8019 Effect.Queues.get(Object.isString(this.options.queue) ? 8020 'global' : this.options.queue.scope).remove(this); 8021 this.state = 'finished'; 8022 }, 8023 event: function(eventName) { 8024 if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); 8025 if (this.options[eventName]) this.options[eventName](this); 8026 }, 8027 inspect: function() { 8028 var data = $H(); 8029 for(property in this) 8030 if (!Object.isFunction(this[property])) data.set(property, this[property]); 8031 return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; 8032 } 8033}); 8034 8035Effect.Parallel = Class.create(Effect.Base, { 8036 initialize: function(effects) { 8037 this.effects = effects || []; 8038 this.start(arguments[1]); 8039 }, 8040 update: function(position) { 8041 this.effects.invoke('render', position); 8042 }, 8043 finish: function(position) { 8044 this.effects.each( function(effect) { 8045 effect.render(1.0); 8046 effect.cancel(); 8047 effect.event('beforeFinish'); 8048 if (effect.finish) effect.finish(position); 8049 effect.event('afterFinish'); 8050 }); 8051 } 8052}); 8053 8054Effect.Tween = Class.create(Effect.Base, { 8055 initialize: function(object, from, to) { 8056 object = Object.isString(object) ? $(object) : object; 8057 var args = $A(arguments), method = args.last(), 8058 options = args.length == 5 ? args[3] : null; 8059 this.method = Object.isFunction(method) ? method.bind(object) : 8060 Object.isFunction(object[method]) ? object[method].bind(object) : 8061 function(value) { object[method] = value }; 8062 this.start(Object.extend({ from: from, to: to }, options || { })); 8063 }, 8064 update: function(position) { 8065 this.method(position); 8066 } 8067}); 8068 8069Effect.Event = Class.create(Effect.Base, { 8070 initialize: function() { 8071 this.start(Object.extend({ duration: 0 }, arguments[0] || { })); 8072 }, 8073 update: Prototype.emptyFunction 8074}); 8075 8076Effect.Opacity = Class.create(Effect.Base, { 8077 initialize: function(element) { 8078 this.element = $(element); 8079 if (!this.element) throw(Effect._elementDoesNotExistError); 8080 // make this work on IE on elements without 'layout' 8081 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 8082 this.element.setStyle({zoom: 1}); 8083 var options = Object.extend({ 8084 from: this.element.getOpacity() || 0.0, 8085 to: 1.0 8086 }, arguments[1] || { }); 8087 this.start(options); 8088 }, 8089 update: function(position) { 8090 this.element.setOpacity(position); 8091 } 8092}); 8093 8094Effect.Move = Class.create(Effect.Base, { 8095 initialize: function(element) { 8096 this.element = $(element); 8097 if (!this.element) throw(Effect._elementDoesNotExistError); 8098 var options = Object.extend({ 8099 x: 0, 8100 y: 0, 8101 mode: 'relative' 8102 }, arguments[1] || { }); 8103 this.start(options); 8104 }, 8105 setup: function() { 8106 this.element.makePositioned(); 8107 this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); 8108 this.originalTop = parseFloat(this.element.getStyle('top') || '0'); 8109 if (this.options.mode == 'absolute') { 8110 this.options.x = this.options.x - this.originalLeft; 8111 this.options.y = this.options.y - this.originalTop; 8112 } 8113 }, 8114 update: function(position) { 8115 this.element.setStyle({ 8116 left: (this.options.x * position + this.originalLeft).round() + 'px', 8117 top: (this.options.y * position + this.originalTop).round() + 'px' 8118 }); 8119 } 8120}); 8121 8122// for backwards compatibility 8123Effect.MoveBy = function(element, toTop, toLeft) { 8124 return new Effect.Move(element,
8125 Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); 8126}; 8127 8128Effect.Scale = Class.create(Effect.Base, { 8129 initialize: function(element, percent) { 8130 this.element = $(element); 8131 if (!this.element) throw(Effect._elementDoesNotExistError); 8132 var options = Object.extend({ 8133 scaleX: true, 8134 scaleY: true, 8135 scaleContent: true, 8136 scaleFromCenter: false, 8137 scaleMode: 'box', // 'box' or 'contents' or { } with provided values 8138 scaleFrom: 100.0, 8139 scaleTo: percent 8140 }, arguments[2] || { }); 8141 this.start(options); 8142 }, 8143 setup: function() { 8144 this.restoreAfterFinish = this.options.restoreAfterFinish || false; 8145 this.elementPositioning = this.element.getStyle('position'); 8146 8147 this.originalStyle = { }; 8148 ['top','left','width','height','fontSize'].each( function(k) { 8149 this.originalStyle[k] = this.element.style[k]; 8150 }.bind(this)); 8151 8152 this.originalTop = this.element.offsetTop; 8153 this.originalLeft = this.element.offsetLeft; 8154 8155 var fontSize = this.element.getStyle('font-size') || '100%'; 8156 ['em','px','%','pt'].each( function(fontSizeType) { 8157 if (fontSize.indexOf(fontSizeType)>0) { 8158 this.fontSize = parseFloat(fontSize); 8159 this.fontSizeType = fontSizeType; 8160 } 8161 }.bind(this)); 8162 8163 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; 8164 8165 this.dims = null; 8166 if (this.options.scaleMode=='box') 8167 this.dims = [this.element.offsetHeight, this.element.offsetWidth]; 8168 if (/^content/.test(this.options.scaleMode)) 8169 this.dims = [this.element.scrollHeight, this.element.scrollWidth]; 8170 if (!this.dims) 8171 this.dims = [this.options.scaleMode.originalHeight, 8172 this.options.scaleMode.originalWidth]; 8173 }, 8174 update: function(position) { 8175 var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); 8176 if (this.options.scaleContent && this.fontSize) 8177 this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); 8178 this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); 8179 }, 8180 finish: function(position) { 8181 if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); 8182 }, 8183 setDimensions: function(height, width) { 8184 var d = { }; 8185 if (this.options.scaleX) d.width = width.round() + 'px'; 8186 if (this.options.scaleY) d.height = height.round() + 'px'; 8187 if (this.options.scaleFromCenter) { 8188 var topd = (height - this.dims[0])/2; 8189 var leftd = (width - this.dims[1])/2; 8190 if (this.elementPositioning == 'absolute') { 8191 if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; 8192 if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; 8193 } else { 8194 if (this.options.scaleY) d.top = -topd + 'px'; 8195 if (this.options.scaleX) d.left = -leftd + 'px'; 8196 } 8197 } 8198 this.element.setStyle(d); 8199 } 8200}); 8201 8202Effect.Highlight = Class.create(Effect.Base, { 8203 initialize: function(element) { 8204 this.element = $(element); 8205 if (!this.element) throw(Effect._elementDoesNotExistError); 8206 var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); 8207 this.start(options); 8208 }, 8209 setup: function() { 8210 // Prevent executing on elements not in the layout flow 8211 if (this.element.getStyle('display')=='none') { this.cancel(); return; } 8212 // Disable background image during the effect 8213 this.oldStyle = { }; 8214 if (!this.options.keepBackgroundImage) { 8215 this.oldStyle.backgroundImage = this.element.getStyle('background-image'); 8216 this.element.setStyle({backgroundImage: 'none'}); 8217 } 8218 if (!this.options.endcolor) 8219 this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); 8220 if (!this.options.restorecolor) 8221 this.options.restorecolor = this.element.getStyle('background-color'); 8222 // init color calculations 8223 this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); 8224 this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); 8225 }, 8226 update: function(position) { 8227 this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ 8228 return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); 8229 }, 8230 finish: function() { 8231 this.element.setStyle(Object.extend(this.oldStyle, { 8232 backgroundColor: this.options.restorecolor 8233 })); 8234 } 8235}); 8236 8237Effect.ScrollTo = function(element) { 8238 var options = arguments[1] || { }, 8239 scrollOffsets = document.viewport.getScrollOffsets(), 8240 elementOffsets = $(element).cumulativeOffset(); 8241 8242 if (options.offset) elementOffsets[1] += options.offset; 8243 8244 return new Effect.Tween(null, 8245 scrollOffsets.top, 8246 elementOffsets[1], 8247 options, 8248 function(p){ scrollTo(scrollOffsets.left, p.round()); } 8249 ); 8250}; 8251 8252/* ------------- combination effects ------------- */ 8253 8254Effect.Fade = function(element) { 8255 element = $(element); 8256 var oldOpacity = element.getInlineOpacity(); 8257 var options = Object.extend({ 8258 from: element.getOpacity() || 1.0, 8259 to: 0.0, 8260 afterFinishInternal: function(effect) { 8261 if (effect.options.to!=0) return; 8262 effect.element.hide().setStyle({opacity: oldOpacity}); 8263 } 8264 }, arguments[1] || { }); 8265 return new Effect.Opacity(element,options); 8266}; 8267 8268Effect.Appear = function(element) { 8269 element = $(element); 8270 var options = Object.extend({ 8271 from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), 8272 to: 1.0, 8273 // force Safari to render floated elements properly 8274 afterFinishInternal: function(effect) { 8275 effect.element.forceRerendering(); 8276 }, 8277 beforeSetup: function(effect) { 8278 effect.element.setOpacity(effect.options.from).show(); 8279 }}, arguments[1] || { }); 8280 return new Effect.Opacity(element,options); 8281}; 8282 8283Effect.Puff = function(element) { 8284 element = $(element); 8285 var oldStyle = { 8286 opacity: element.getInlineOpacity(), 8287 position: element.getStyle('position'), 8288 top: element.style.top, 8289 left: element.style.left, 8290 width: element.style.width, 8291 height: element.style.height 8292 }; 8293 return new Effect.Parallel( 8294 [ new Effect.Scale(element, 200, 8295 { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 8296 new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 8297 Object.extend({ duration: 1.0, 8298 beforeSetupInternal: function(effect) { 8299 Position.absolutize(effect.effects[0].element); 8300 }, 8301 afterFinishInternal: function(effect) { 8302 effect.effects[0].element.hide().setStyle(oldStyle); } 8303 }, arguments[1] || { }) 8304 ); 8305}; 8306 8307Effect.BlindUp = function(element) { 8308 element = $(element); 8309 element.makeClipping(); 8310 return new Effect.Scale(element, 0, 8311 Object.extend({ scaleContent: false, 8312 scaleX: false, 8313 restoreAfterFinish: true, 8314 afterFinishInternal: function(effect) { 8315 effect.element.hide().undoClipping(); 8316 } 8317 }, arguments[1] || { }) 8318 ); 8319}; 8320 8321Effect.BlindDown = function(element) { 8322 element = $(element); 8323 var elementDimensions = element.getDimensions(); 8324 return new Effect.Scale(element, 100, Object.extend({ 8325 scaleContent: false, 8326 scaleX: false, 8327 scaleFrom: 0, 8328 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 8329 restoreAfterFinish: true, 8330 afterSetup: function(effect) { 8331 effect.element.makeClipping().setStyle({height: '0px'}).show(); 8332 }, 8333 afterFinishInternal: function(effect) { 8334 effect.element.undoClipping(); 8335 } 8336 }, arguments[1] || { })); 8337}; 8338 8339Effect.SwitchOff = function(element) { 8340 element = $(element); 8341 var oldOpacity = element.getInlineOpacity(); 8342 return new Effect.Appear(element, Object.extend({ 8343 duration: 0.4, 8344 from: 0, 8345 transition: Effect.Transitions.flicker, 8346 afterFinishInternal: function(effect) { 8347 new Effect.Scale(effect.element, 1, { 8348 duration: 0.3, scaleFromCenter: true, 8349 scaleX: false, scaleContent: false, restoreAfterFinish: true, 8350 beforeSetup: function(effect) { 8351 effect.element.makePositioned().makeClipping(); 8352 }, 8353 afterFinishInternal: function(effect) { 8354 effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); 8355 } 8356 }); 8357 } 8358 }, arguments[1] || { })); 8359}; 8360 8361Effect.DropOut = function(element) { 8362 element = $(element); 8363 var oldStyle = { 8364 top: element.getStyle('top'), 8365 left: element.getStyle('left'), 8366 opacity: element.getInlineOpacity() }; 8367 return new Effect.Parallel( 8368 [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 8369 new Effect.Opacity(element, { sync: true, to: 0.0 }) ], 8370 Object.extend( 8371 { duration: 0.5, 8372 beforeSetup: function(effect) { 8373 effect.effects[0].element.makePositioned(); 8374 }, 8375 afterFinishInternal: function(effect) { 8376 effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); 8377 } 8378 }, arguments[1] || { })); 8379}; 8380 8381Effect.Shake = function(element) { 8382 element = $(element); 8383 var options = Object.extend({ 8384 distance: 20, 8385 duration: 0.5 8386 }, arguments[1] || {}); 8387 var distance = parseFloat(options.distance); 8388 var split = parseFloat(options.duration) / 10.0; 8389 var oldStyle = { 8390 top: element.getStyle('top'), 8391 left: element.getStyle('left') }; 8392 return new Effect.Move(element, 8393 { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { 8394 new Effect.Move(effect.element, 8395 { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 8396 new Effect.Move(effect.element, 8397 { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 8398 new Effect.Move(effect.element, 8399 { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 8400 new Effect.Move(effect.element, 8401 { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { 8402 new Effect.Move(effect.element, 8403 { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { 8404 effect.element.undoPositioned().setStyle(oldStyle); 8405 }}); }}); }}); }}); }}); }}); 8406}; 8407 8408Effect.SlideDown = function(element) { 8409 element = $(element).cleanWhitespace(); 8410 // SlideDown need to have the content of the element wrapped in a container element with fixed height! 8411 var oldInnerBottom = element.down().getStyle('bottom'); 8412 var elementDimensions = element.getDimensions(); 8413 return new Effect.Scale(element, 100, Object.extend({ 8414 scaleContent: false, 8415 scaleX: false, 8416 scaleFrom: window.opera ? 0 : 1, 8417 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 8418 restoreAfterFinish: true, 8419 afterSetup: function(effect) { 8420 effect.element.makePositioned(); 8421 effect.element.down().makePositioned(); 8422 if (window.opera) effect.element.setStyle({top: ''}); 8423 effect.element.makeClipping().setStyle({height: '0px'}).show(); 8424 }, 8425 afterUpdateInternal: function(effect) { 8426 effect.element.down().setStyle({bottom: 8427 (effect.dims[0] - effect.element.clientHeight) + 'px' }); 8428 }, 8429 afterFinishInternal: function(effect) { 8430 effect.element.undoClipping().undoPositioned(); 8431 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } 8432 }, arguments[1] || { }) 8433 ); 8434}; 8435 8436Effect.SlideUp = function(element) { 8437 element = $(element).cleanWhitespace(); 8438 var oldInnerBottom = element.down().getStyle('bottom'); 8439 var elementDimensions = element.getDimensions(); 8440 return new Effect.Scale(element, window.opera ? 0 : 1, 8441 Object.extend({ scaleContent: false, 8442 scaleX: false, 8443 scaleMode: 'box', 8444 scaleFrom: 100, 8445 scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, 8446 restoreAfterFinish: true, 8447 afterSetup: function(effect) { 8448 effect.element.makePositioned(); 8449 effect.element.down().makePositioned(); 8450 if (window.opera) effect.element.setStyle({top: ''}); 8451 effect.element.makeClipping().show(); 8452 }, 8453 afterUpdateInternal: function(effect) { 8454 effect.element.down().setStyle({bottom: 8455 (effect.dims[0] - effect.element.clientHeight) + 'px' }); 8456 }, 8457 afterFinishInternal: function(effect) { 8458 effect.element.hide().undoClipping().undoPositioned(); 8459 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); 8460 } 8461 }, arguments[1] || { }) 8462 ); 8463}; 8464 8465// Bug in opera makes the TD containing this element expand for a instance after finish 8466Effect.Squish = function(element) { 8467 return new Effect.Scale(element, window.opera ? 1 : 0, { 8468 restoreAfterFinish: true, 8469 beforeSetup: function(effect) { 8470 effect.element.makeClipping(); 8471 }, 8472 afterFinishInternal: function(effect) { 8473 effect.element.hide().undoClipping(); 8474 } 8475 }); 8476}; 8477 8478Effect.Grow = function(element) { 8479 element = $(element); 8480 var options = Object.extend({ 8481 direction: 'center', 8482 moveTransition: Effect.Transitions.sinoidal, 8483 scaleTransition: Effect.Transitions.sinoidal, 8484 opacityTransition: Effect.Transitions.full 8485 }, arguments[1] || { }); 8486 var oldStyle = { 8487 top: element.style.top, 8488 left: element.style.left, 8489 height: element.style.height, 8490 width: element.style.width, 8491 opacity: element.getInlineOpacity() }; 8492 8493 var dims = element.getDimensions(); 8494 var initialMoveX, initialMoveY; 8495 var moveX, moveY; 8496 8497 switch (options.direction) { 8498 case 'top-left': 8499 initialMoveX = initialMoveY = moveX = moveY = 0; 8500 break; 8501 case 'top-right': 8502 initialMoveX = dims.width; 8503 initialMoveY = moveY = 0; 8504 moveX = -dims.width; 8505 break; 8506 case 'bottom-left': 8507 initialMoveX = moveX = 0; 8508 initialMoveY = dims.height; 8509 moveY = -dims.height; 8510 break; 8511 case 'bottom-right': 8512 initialMoveX = dims.width; 8513 initialMoveY = dims.height; 8514 moveX = -dims.width; 8515 moveY = -dims.height; 8516 break; 8517 case 'center': 8518 initialMoveX = dims.width / 2; 8519 initialMoveY = dims.height / 2; 8520 moveX = -dims.width / 2; 8521 moveY = -dims.height / 2; 8522 break; 8523 } 8524 8525 return new Effect.Move(element, { 8526 x: initialMoveX, 8527 y: initialMoveY, 8528 duration: 0.01, 8529 beforeSetup: function(effect) { 8530 effect.element.hide().makeClipping().makePositioned(); 8531 }, 8532 afterFinishInternal: function(effect) { 8533 new Effect.Parallel( 8534 [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), 8535 new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), 8536 new Effect.Scale(effect.element, 100, { 8537 scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 8538 sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) 8539 ], Object.extend({ 8540 beforeSetup: function(effect) { 8541 effect.effects[0].element.setStyle({height: '0px'}).show(); 8542 }, 8543 afterFinishInternal: function(effect) { 8544 effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); 8545 } 8546 }, options) 8547 ); 8548 } 8549 }); 8550}; 8551 8552Effect.Shrink = function(element) { 8553 element = $(element); 8554 var options = Object.extend({ 8555 direction: 'center', 8556 moveTransition: Effect.Transitions.sinoidal, 8557 scaleTransition: Effect.Transitions.sinoidal, 8558 opacityTransition: Effect.Transitions.none 8559 }, arguments[1] || { }); 8560 var oldStyle = { 8561 top: element.style.top, 8562 left: element.style.left, 8563 height: element.style.height, 8564 width: element.style.width, 8565 opacity: element.getInlineOpacity() }; 8566 8567 var dims = element.getDimensions(); 8568 var moveX, moveY; 8569 8570 switch (options.direction) { 8571 case 'top-left': 8572 moveX = moveY = 0; 8573 break; 8574 case 'top-right': 8575 moveX = dims.width; 8576 moveY = 0; 8577 break; 8578 case 'bottom-left': 8579 moveX = 0; 8580 moveY = dims.height; 8581 break; 8582 case 'bottom-right': 8583 moveX = dims.width; 8584 moveY = dims.height; 8585 break; 8586 case 'center': 8587 moveX = dims.width / 2; 8588 moveY = dims.height / 2; 8589 break; 8590 } 8591 8592 return new Effect.Parallel( 8593 [ new Effect.Opacity(elemen
8593t, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), 8594 new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), 8595 new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) 8596 ], Object.extend({ 8597 beforeStartInternal: function(effect) { 8598 effect.effects[0].element.makePositioned().makeClipping(); 8599 }, 8600 afterFinishInternal: function(effect) { 8601 effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } 8602 }, options) 8603 ); 8604}; 8605 8606Effect.Pulsate = function(element) { 8607 element = $(element); 8608 var options = arguments[1] || { }, 8609 oldOpacity = element.getInlineOpacity(), 8610 transition = options.transition || Effect.Transitions.linear, 8611 reverser = function(pos){ 8612 return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); 8613 }; 8614 8615 return new Effect.Opacity(element, 8616 Object.extend(Object.extend({ duration: 2.0, from: 0, 8617 afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } 8618 }, options), {transition: reverser})); 8619}; 8620 8621Effect.Fold = function(element) { 8622 element = $(element); 8623 var oldStyle = { 8624 top: element.style.top, 8625 left: element.style.left, 8626 width: element.style.width, 8627 height: element.style.height }; 8628 element.makeClipping(); 8629 return new Effect.Scale(element, 5, Object.extend({ 8630 scaleContent: false, 8631 scaleX: false, 8632 afterFinishInternal: function(effect) { 8633 new Effect.Scale(element, 1, { 8634 scaleContent: false, 8635 scaleY: false, 8636 afterFinishInternal: function(effect) { 8637 effect.element.hide().undoClipping().setStyle(oldStyle); 8638 } }); 8639 }}, arguments[1] || { })); 8640}; 8641 8642Effect.Morph = Class.create(Effect.Base, { 8643 initialize: function(element) { 8644 this.element = $(element); 8645 if (!this.element) throw(Effect._elementDoesNotExistError); 8646 var options = Object.extend({ 8647 style: { } 8648 }, arguments[1] || { }); 8649 8650 if (!Object.isString(options.style)) this.style = $H(options.style); 8651 else { 8652 if (options.style.include(':')) 8653 this.style = options.style.parseStyle(); 8654 else { 8655 this.element.addClassName(options.style); 8656 this.style = $H(this.element.getStyles()); 8657 this.element.removeClassName(options.style); 8658 var css = this.element.getStyles(); 8659 this.style = this.style.reject(function(style) { 8660 return style.value == css[style.key]; 8661 }); 8662 options.afterFinishInternal = function(effect) { 8663 effect.element.addClassName(effect.options.style); 8664 effect.transforms.each(function(transform) { 8665 effect.element.style[transform.style] = ''; 8666 }); 8667 }; 8668 } 8669 } 8670 this.start(options); 8671 }, 8672 8673 setup: function(){ 8674 function parseColor(color){ 8675 if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; 8676 color = color.parseColor(); 8677 return $R(0,2).map(function(i){ 8678 return parseInt( color.slice(i*2+1,i*2+3), 16 ); 8679 }); 8680 } 8681 this.transforms = this.style.map(function(pair){ 8682 var property = pair[0], value = pair[1], unit = null; 8683 8684 if (value.parseColor('#zzzzzz') != '#zzzzzz') { 8685 value = value.parseColor(); 8686 unit = 'color'; 8687 } else if (property == 'opacity') { 8688 value = parseFloat(value); 8689 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) 8690 this.element.setStyle({zoom: 1}); 8691 } else if (Element.CSS_LENGTH.test(value)) { 8692 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); 8693 value = parseFloat(components[1]); 8694 unit = (components.length == 3) ? components[2] : null; 8695 } 8696 8697 var originalValue = this.element.getStyle(property); 8698 return { 8699 style: property.camelize(), 8700 originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), 8701 targetValue: unit=='color' ? parseColor(value) : value, 8702 unit: unit 8703 }; 8704 }.bind(this)).reject(function(transform){ 8705 return ( 8706 (transform.originalValue == transform.targetValue) || 8707 ( 8708 transform.unit != 'color' && 8709 (isNaN(transform.originalValue) || isNaN(transform.targetValue)) 8710 ) 8711 ); 8712 }); 8713 }, 8714 update: function(position) { 8715 var style = { }, transform, i = this.transforms.length; 8716 while(i--) 8717 style[(transform = this.transforms[i]).style] = 8718 transform.unit=='color' ? '#'+ 8719 (Math.round(transform.originalValue[0]+ 8720 (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + 8721 (Math.round(transform.originalValue[1]+ 8722 (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + 8723 (Math.round(transform.originalValue[2]+ 8724 (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : 8725 (transform.originalValue + 8726 (transform.targetValue - transform.originalValue) * position).toFixed(3) + 8727 (transform.unit === null ? '' : transform.unit); 8728 this.element.setStyle(style, true); 8729 } 8730}); 8731 8732Effect.Transform = Class.create({ 8733 initialize: function(tracks){ 8734 this.tracks = []; 8735 this.options = arguments[1] || { }; 8736 this.addTracks(tracks); 8737 }, 8738 addTracks: function(tracks){ 8739 tracks.each(function(track){ 8740 track = $H(track); 8741 var data = track.values().first(); 8742 this.tracks.push($H({ 8743 ids: track.keys().first(), 8744 effect: Effect.Morph, 8745 options: { style: data } 8746 })); 8747 }.bind(this)); 8748 return this; 8749 }, 8750 play: function(){ 8751 return new Effect.Parallel( 8752 this.tracks.map(function(track){ 8753 var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); 8754 var elements = [$(ids) || $$(ids)].flatten(); 8755 return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); 8756 }).flatten(), 8757 this.options 8758 ); 8759 } 8760}); 8761 8762Element.CSS_PROPERTIES = $w( 8763 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 8764 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 8765 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 8766 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 8767 'fontSize fontWeight height left letterSpacing lineHeight ' + 8768 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ 8769 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 8770 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 8771 'right textIndent top width wordSpacing zIndex'); 8772 8773Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; 8774 8775String.__parseStyleElement = document.createElement('div'); 8776String.prototype.parseStyle = function(){ 8777 var style, styleRules = $H(); 8778 if (Prototype.Browser.WebKit) 8779 style = new Element('div',{style:this}).style; 8780 else { 8781 String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; 8782 style = String.__parseStyleElement.childNodes[0].style; 8783 } 8784 8785 Element.CSS_PROPERTIES.each(function(property){ 8786 if (style[property]) styleRules.set(property, style[property]); 8787 }); 8788 8789 if (Prototype.Browser.IE && this.include('opacity')) 8790 styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); 8791 8792 return styleRules; 8793}; 8794 8795if (document.defaultView && document.defaultView.getComputedStyle) { 8796 Element.getStyles = function(element) { 8797 var css = document.defaultView.getComputedStyle($(element), null); 8798 return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { 8799 styles[property] = css[property]; 8800 return styles; 8801 }); 8802 }; 8803} else { 8804 Element.getStyles = function(element) { 8805 element = $(element); 8806 var css = element.currentStyle, styles; 8807 styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { 8808 results[property] = css[property]; 8809 return results; 8810 }); 8811 if (!styles.opacity) styles.opacity = element.getOpacity(); 8812 return styles; 8813 }; 8814} 8815 8816Effect.Methods = { 8817 morph: function(element, style) { 8818 element = $(element); 8819 new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); 8820 return element; 8821 }, 8822 visualEffect: function(element, effect, options) { 8823 element = $(element); 8824 var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); 8825 new Effect[klass](element, options); 8826 return element; 8827 }, 8828 highlight: function(element, options) { 8829 element = $(element); 8830 new Effect.Highlight(element, options); 8831 return element; 8832 } 8833}; 8834 8835$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ 8836 'pulsate shake puff squish switchOff dropOut').each( 8837 function(effect) { 8838 Effect.Methods[effect] = function(element, options){ 8839 element = $(element);
8840 Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); 8841 return element; 8842 }; 8843 } 8844); 8845 8846$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( 8847 function(f) { Effect.Methods[f] = Element[f]; } 8848); 8849 8850Element.addMethods(Effect.Methods);// script.aculo.us controls.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 8851 8852// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 8853// (c) 2005-2010 Ivan Krstic (http://blogs.law.harvard.edu/ivan) 8854// (c) 2005-2010 Jon Tirsen (http://www.tirsen.com) 8855// Contributors: 8856// Richard Livsey 8857// Rahul Bhargava 8858// Rob Wills 8859// 8860// script.aculo.us is freely distributable under the terms of an MIT-style license. 8861// For details, see the script.aculo.us web site: http://script.aculo.us/ 8862 8863// Autocompleter.Base handles all the autocompletion functionality 8864// that's independent of the data source for autocompletion. This 8865// includes drawing the autocompletion menu, observing keyboard 8866// and mouse events, and similar. 8867// 8868// Specific autocompleters need to provide, at the very least, 8869// a getUpdatedChoices function that will be invoked every time 8870// the text inside the monitored textbox changes. This method 8871// should get the text for which to provide autocompletion by 8872// invoking this.getToken(), NOT by directly accessing 8873// this.element.value. This is to allow incremental tokenized 8874// autocompletion. Specific auto-completion logic (AJAX, etc) 8875// belongs in getUpdatedChoices. 8876// 8877// Tokenized incremental autocompletion is enabled automatically 8878// when an autocompleter is instantiated with the 'tokens' option 8879// in the options parameter, e.g.: 8880// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); 8881// will incrementally autocomplete with a comma as the token. 8882// Additionally, ',' in the above example can be replaced with 8883// a token array, e.g. { tokens: [',', '\n'] } which 8884// enables autocompletion on multiple tokens. This is most 8885// useful when one of the tokens is \n (a newline), as it 8886// allows smart autocompletion after linebreaks. 8887 8888if(typeof Effect == 'undefined') 8889 throw("controls.js requires including script.aculo.us' effects.js library"); 8890 8891var Autocompleter = { }; 8892Autocompleter.Base = Class.create({ 8893 baseInitialize: function(element, update, options) { 8894 element = $(element); 8895 this.element = element; 8896 this.update = $(update); 8897 this.hasFocus = false; 8898 this.changed = false; 8899 this.active = false; 8900 this.index = 0; 8901 this.entryCount = 0; 8902 this.oldElementValue = this.element.value; 8903 8904 if(this.setOptions) 8905 this.setOptions(options); 8906 else 8907 this.options = options || { }; 8908 8909 this.options.paramName = this.options.paramName || this.element.name; 8910 this.options.tokens = this.options.tokens || []; 8911 this.options.frequency = this.options.frequency || 0.4; 8912 this.options.minChars = this.options.minChars || 1; 8913 this.options.onShow = this.options.onShow || 8914 function(element, update){ 8915 if(!update.style.position || update.style.position=='absolute') { 8916 update.style.position = 'absolute'; 8917 Position.clone(element, update, { 8918 setHeight: false, 8919 offsetTop: element.offsetHeight 8920 }); 8921 } 8922 Effect.Appear(update,{duration:0.15}); 8923 }; 8924 this.options.onHide = this.options.onHide || 8925 function(element, update){ new Effect.Fade(update,{duration:0.15}) }; 8926 8927 if(typeof(this.options.tokens) == 'string') 8928 this.options.tokens = new Array(this.options.tokens); 8929 // Force carriage returns as token delimiters anyway 8930 if (!this.options.tokens.include('\n')) 8931 this.options.tokens.push('\n'); 8932 8933 this.observer = null; 8934 8935 this.element.setAttribute('autocomplete','off'); 8936 8937 Element.hide(this.update); 8938 8939 Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); 8940 Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); 8941 }, 8942 8943 show: function() { 8944 if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); 8945 if(!this.iefix && 8946 (Prototype.Browser.IE) && 8947 (Element.getStyle(this.update, 'position')=='absolute')) { 8948 new Insertion.After(this.update, 8949 '<iframe id="' + this.update.id + '_iefix" '+ 8950 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 8951 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); 8952 this.iefix = $(this.update.id+'_iefix'); 8953 } 8954 if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); 8955 }, 8956 8957 fixIEOverlapping: function() { 8958 Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); 8959 this.iefix.style.zIndex = 1; 8960 this.update.style.zIndex = 2; 8961 Element.show(this.iefix); 8962 }, 8963 8964 hide: function() { 8965 this.stopIndicator(); 8966 if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); 8967 if(this.iefix) Element.hide(this.iefix); 8968 }, 8969 8970 startIndicator: function() { 8971 if(this.options.indicator) Element.show(this.options.indicator); 8972 }, 8973 8974 stopIndicator: function() { 8975 if(this.options.indicator) Element.hide(this.options.indicator); 8976 }, 8977 8978 onKeyPress: function(event) { 8979 var srcElementId = ''; 8980 if (event.srcElement !== undefined && event.srcElement.id !== undefined) { 8981 srcElementId = event.srcElement.id; 8982 } 8983 if(this.active) 8984 switch(event.keyCode) { 8985 case Event.KEY_TAB: 8986 case Event.KEY_RETURN: 8987 this.selectEntry(); 8988 Event.stop(event); 8989 if(srcElementId == 'search_waste'){
8990 onClickRedirectWasteList(); 8991 }else if(srcElementId == 'search_text'){ 8992 onEnterSelect(); 8993 } 8994 case Event.KEY_ESC: 8995 this.hide(); 8996 this.active = false; 8997 Event.stop(event); 8998 return; 8999 case Event.KEY_LEFT: 9000 case Event.KEY_RIGHT: 9001 return; 9002 case Event.KEY_UP: 9003 this.markPrevious(); 9004 this.render(); 9005 9006 Event.stop(event); 9007 return; 9008 case Event.KEY_DOWN: 9009 this.markNext(); 9010 this.render(); 9011 9012 Event.stop(event); 9013 return; 9014 } 9015 else 9016 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 9017 (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; 9018 9019 this.changed = true; 9020 this.hasFocus = true; 9021 9022 if(this.observer) clearTimeout(this.observer); 9023 this.observer = 9024 setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); 9025 }, 9026 9027 activate: function() { 9028 this.changed = false; 9029 this.hasFocus = true; 9030 this.getUpdatedChoices(); 9031 }, 9032 9033 onHover: function(event) { 9034 var element = Event.findElement(event, 'LI'); 9035 if(element !== undefined){ 9036 if(this.index != element.autocompleteIndex) 9037 { 9038 this.index = element.autocompleteIndex; 9039 this.render(); 9040 } 9041 } 9042 Event.stop(event); 9043 }, 9044 9045 onClick: function(event) { 9046 var element = Event.findElement(event, 'LI'); 9047 if(element !== undefined){ 9048 this.index = element.autocompleteIndex; 9049 this.selectEntry(); 9050 this.hide(); 9051 } 9052 }, 9053 9054 onBlur: function(event) { 9055 // needed to make click events working 9056 setTimeout(this.hide.bind(this), 250); 9057 this.hasFocus = false; 9058 this.active = false; 9059 }, 9060 9061 render: function() { 9062 if(this.entryCount > 0) { 9063 for (var i = 0; i < this.entryCount; i++) 9064 this.index==i ? 9065 Element.addClassName(this.getEntry(i),"selected") : 9066 Element.removeClassName(this.getEntry(i),"selected"); 9067 if(this.hasFocus) { 9068 this.show(); 9069 this.active = true; 9070 } 9071 } else { 9072 this.active = false; 9073 this.hide(); 9074 } 9075 }, 9076 9077 markPrevious: function() { 9078 var isNewLayout = false; 9079 if (this.element !== undefined && this.element.id !== undefined && (this.element.id == 'search_waste' || this.element.id == 'search_text')) { 9080 isNewLayout = true; 9081 } 9082 if(this.index > 0) { 9083 this.index--; 9084 } else { 9085 this.index = this.entryCount-1; 9086 } 9087 if (false == isNewLayout){ 9088 this.getEntry(this.index).scrollIntoView(false); 9089 } 9090 }, 9091 9092 markNext: function() { 9093 var isNewLayout = false; 9094 if (this.element !== undefined && this.element.id !== undefined && (this.element.id == 'search_waste' || this.element.id == 'search_text')) { 9095 isNewLayout = true; 9096 } 9097 9098 if (this.index < this.entryCount-1) { 9099 this.index++; 9100 } else { 9101 this.index = 0; 9102 } 9103 if (false == isNewLayout){ 9104 this.getEntry(this.index).scrollIntoView(false); 9105 } 9106 }, 9107 9108 getEntry: function(index) { 9109 return this.update.firstChild.childNodes[index]; 9110 }, 9111 9112 getCurrentEntry: function() { 9113 return this.getEntry(this.index); 9114 }, 9115 9116 selectEntry: function() { 9117 this.active = false; 9118 this.updateElement(this.getCurrentEntry()); 9119 }, 9120 updateElement: function(selectedElement) { 9121 if (this.options.updateElement) { 9122 this.options.updateElement(selectedElement); 9123 return; 9124 } 9125 var value = ''; 9126 if (this.options.select) { 9127 var nodes = $(selectedElement).select('.' + this.options.select) || []; 9128 if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); 9129 } else 9130 value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); 9131 9132 var bounds = this.getTokenBounds(); 9133 if (bounds[0] != -1) { 9134 var newValue = this.element.value.substr(0, bounds[0]); 9135 var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); 9136 if (whitespace) 9137 newValue += whitespace[0]; 9138 this.element.value = newValue + value + this.element.value.substr(bounds[1]); 9139 } else { 9140 this.element.value = value; 9141 } 9142 this.oldElementValue = this.element.value; 9143 this.element.focus(); 9144 9145 if (this.options.afterUpdateElement){ 9146 this.options.afterUpdateElement(this.element, selectedElement);} 9147 }, 9148 9149 updateChoices: function(choices) { 9150 if(!this.changed && this.hasFocus) { 9151 this.update.innerHTML = choices; 9152 Element.cleanWhitespace(this.update); 9153 Element.cleanWhitespace(this.update.down()); 9154 9155 if(this.update.firstChild && this.update.down().childNodes) { 9156 this.entryCount = 9157 this.update.down().childNodes.length; 9158 for (var i = 0; i < this.entryCount; i++) { 9159 var entry = this.getEntry(i); 9160 entry.autocompleteIndex = i; 9161 this.addObservers(entry); 9162 } 9163 } else { 9164 this.entryCount = 0; 9165 } 9166 9167 this.stopIndicator(); 9168 this.index = 0; 9169 9170 if(this.entryCount==1 && this.options.autoSelect) { 9171 this.selectEntry(); 9172 this.hide(); 9173 } else { 9174 this.render(); 9175 } 9176 } 9177 }, 9178 9179 addObservers: function(element) { 9180 Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); 9181 Event.observe(element, "click", this.onClick.bindAsEventListener(this)); 9182 }, 9183 9184 onObserverEvent: function() { 9185 this.changed = false;
9186 this.tokenBounds = null; 9187 if(this.getToken().length>=this.options.minChars) { 9188 this.getUpdatedChoices(); 9189 } else { 9190 this.active = false; 9191 this.hide(); 9192 } 9193 this.oldElementValue = this.element.value; 9194 }, 9195 9196 getToken: function() { 9197 var bounds = this.getTokenBounds(); 9198 return this.element.value.substring(bounds[0], bounds[1]).strip(); 9199 }, 9200 9201 getTokenBounds: function() { 9202 if (null != this.tokenBounds) return this.tokenBounds; 9203 var value = this.element.value; 9204 if (value.strip().empty()) return [-1, 0]; 9205 var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); 9206 var offset = (diff == this.oldElementValue.length ? 1 : 0); 9207 var prevTokenPos = -1, nextTokenPos = value.length; 9208 var tp; 9209 for (var index = 0, l = this.options.tokens.length; index < l; ++index) { 9210 tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); 9211 if (tp > prevTokenPos) prevTokenPos = tp; 9212 tp = value.indexOf(this.options.tokens[index], diff + offset); 9213 if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; 9214 } 9215 return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); 9216 } 9217}); 9218 9219Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { 9220 var boundary = Math.min(newS.length, oldS.length); 9221 for (var index = 0; index < boundary; ++index) 9222 if (newS[index] != oldS[index]) 9223 return index; 9224 return boundary; 9225}; 9226 9227Ajax.Autocompleter = Class.create(Autocompleter.Base, { 9228 initialize: function(element, update, url, options) { 9229 this.baseInitialize(element, update, options); 9230 this.options.asynchronous = true; 9231 this.options.onComplete = this.onComplete.bind(this); 9232 this.options.defaultParams = this.options.parameters || null; 9233 this.url = url; 9234 }, 9235 9236 getUpdatedChoices: function() { 9237 this.startIndicator(); 9238 9239 var entry = encodeURIComponent(this.options.paramName) + '=' + 9240 encodeURIComponent(this.getToken()); 9241 9242 this.options.parameters = this.options.callback ? 9243 this.options.callback(this.element, entry) : entry; 9244 9245 if(this.options.defaultParams) 9246 this.options.parameters += '&' + this.options.defaultParams; 9247 9248 new Ajax.Request(this.url, this.options); 9249 }, 9250 9251 onComplete: function(request) { 9252 this.updateChoices(request.responseText); 9253 } 9254}); 9255 9256// The local array autocompleter. Used when you'd prefer to 9257// inject an array of autocompletion options into the page, rather 9258// than sending out Ajax queries, which can be quite slow sometimes. 9259// 9260// The constructor takes four parameters. The first two are, as usual, 9261// the id of the monitored textbox, and id of the autocompletion menu. 9262// The third is the array you want to autocomplete from, and the fourth 9263// is the options block. 9264// 9265// Extra local autocompletion options: 9266// - choices - How many autocompletion choices to offer 9267//
9268// - partialSearch - If false, the autocompleter will match entered 9269// text only at the beginning of strings in the 9270// autocomplete array. Defaults to true, which will 9271// match text at the beginning of any *word* in the 9272// strings in the autocomplete array. If you want to 9273// search anywhere in the string, additionally set 9274// the option fullSearch to true (default: off). 9275// 9276// - fullSsearch - Search anywhere in autocomplete array strings. 9277// 9278// - partialChars - How many characters to enter before triggering 9279// a partial match (unlike minChars, which defines 9280// how many characters are required to do any match 9281// at all). Defaults to 2. 9282// 9283// - ignoreCase - Whether to ignore case when autocompleting. 9284// Defaults to true. 9285// 9286// It's possible to pass in a custom function as the 'selector' 9287// option, if you prefer to write your own autocompletion logic. 9288// In that case, the other options above will not apply unless 9289// you support them. 9290 9291Autocompleter.Local = Class.create(Autocompleter.Base, { 9292 initialize: function(element, update, array, options) { 9293 this.baseInitialize(element, update, options); 9294 this.options.array = array; 9295 }, 9296 9297 getUpdatedChoices: function() { 9298 this.updateChoices(this.options.selector(this)); 9299 }, 9300 9301 setOptions: function(options) { 9302 this.options = Object.extend({ 9303 choices: 10, 9304 partialSearch: true, 9305 partialChars: 2, 9306 ignoreCase: true, 9307 fullSearch: false, 9308 selector: function(instance) { 9309 var ret = []; // Beginning matches 9310 var partial = []; // Inside matches 9311 var entry = instance.getToken(); 9312 var count = 0; 9313 9314 for (var i = 0; i < instance.options.array.length && 9315 ret.length < instance.options.choices ; i++) { 9316 9317 var elem = instance.options.array[i]; 9318 var foundPos = instance.options.ignoreCase ? 9319 elem.toLowerCase().indexOf(entry.toLowerCase()) : 9320 elem.indexOf(entry); 9321 9322 while (foundPos != -1) { 9323 if (foundPos == 0 && elem.length != entry.length) { 9324 ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 9325 elem.substr(entry.length) + "</li>"); 9326 break; 9327 } else if (entry.length >= instance.options.partialChars && 9328 instance.options.partialSearch && foundPos != -1) { 9329 if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { 9330 partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + 9331 elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( 9332 foundPos + entry.length) + "</li>"); 9333 break; 9334 } 9335 } 9336 9337 foundPos = instance.options.ignoreCase ? 9338 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 9339 elem.indexOf(entry, foundPos + 1); 9340 9341 } 9342 } 9343 if (partial.length) 9344 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); 9345 return "<ul>" + ret.join('') + "</ul>"; 9346 } 9347 }, options || { }); 9348 } 9349}); 9350 9351// AJAX in-place editor and collection editor 9352// Full rewrite by Christophe Porteneuve <[email protected]> (April 2007). 9353 9354// Use this if you notice weird scrolling problems on some browsers, 9355// the DOM might be a bit confused when this gets called so do this 9356// waits 1 ms (with setTimeout) until it does the activation 9357Field.scrollFreeActivate = function(field) { 9358 setTimeout(function() { 9359 Field.activate(field); 9360 }, 1); 9361}; 9362 9363Ajax.InPlaceEditor = Class.create({ 9364 initialize: function(element, url, options) { 9365 this.url = url; 9366 this.element = element = $(element); 9367 this.prepareOptions(); 9368 this._controls = { }; 9369 arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! 9370 Object.extend(this.options, options || { });
9371 if (!this.options.formId && this.element.id) { 9372 this.options.formId = this.element.id + '-inplaceeditor'; 9373 if ($(this.options.formId)) 9374 this.options.formId = ''; 9375 } 9376 if (this.options.externalControl) 9377 this.options.externalControl = $(this.options.externalControl); 9378 if (!this.options.externalControl) 9379 this.options.externalControlOnly = false; 9380 this._originalBackground = this.element.getStyle('background-color') || 'transparent'; 9381 this.element.title = this.options.clickToEditText; 9382 this._boundCancelHandler = this.handleFormCancellation.bind(this); 9383 this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); 9384 this._boundFailureHandler = this.handleAJAXFailure.bind(this); 9385 this._boundSubmitHandler = this.handleFormSubmission.bind(this); 9386 this._boundWrapperHandler = this.wrapUp.bind(this); 9387 this.registerListeners(); 9388 }, 9389 checkForEscapeOrReturn: function(e) { 9390 if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; 9391 if (Event.KEY_ESC == e.keyCode) 9392 this.handleFormCancellation(e); 9393 else if (Event.KEY_RETURN == e.keyCode) 9394 this.handleFormSubmission(e); 9395 }, 9396 createControl: function(mode, handler, extraClasses) { 9397 var control = this.options[mode + 'Control']; 9398 var text = this.options[mode + 'Text']; 9399 if ('button' == control) { 9400 var btn = document.createElement('input'); 9401 btn.type = 'submit'; 9402 btn.value = text; 9403 btn.className = 'editor_' + mode + '_button'; 9404 if ('cancel' == mode) 9405 btn.onclick = this._boundCancelHandler; 9406 this._form.appendChild(btn); 9407 this._controls[mode] = btn; 9408 } else if ('link' == control) { 9409 var link = document.createElement('a'); 9410 link.href = '#'; 9411 link.appendChild(document.createTextNode(text)); 9412 link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; 9413 link.className = 'editor_' + mode + '_link'; 9414 if (extraClasses) 9415 link.className += ' ' + extraClasses; 9416 this._form.appendChild(link); 9417 this._controls[mode] = link; 9418 } 9419 }, 9420 createEditField: function() { 9421 var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); 9422 var fld; 9423 if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { 9424 fld = document.createElement('input'); 9425 fld.type = 'text'; 9426 var size = this.options.size || this.options.cols || 0; 9427 if (0 < size) fld.size = size; 9428 } else { 9429 fld = document.createElement('textarea'); 9430 fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); 9431 fld.cols = this.options.cols || 40; 9432 } 9433 fld.name = this.options.paramName; 9434 fld.value = text; // No HTML breaks conversion anymore 9435 fld.className = 'editor_field'; 9436 if (this.options.submitOnBlur) 9437 fld.onblur = this._boundSubmitHandler; 9438 this._controls.editor = fld; 9439 if (this.options.loadTextURL) 9440 this.loadExternalText(); 9441 this._form.appendChild(this._controls.editor); 9442 }, 9443 createForm: function() { 9444 var ipe = this; 9445 function addText(mode, condition) { 9446 var text = ipe.options['text' + mode + 'Controls']; 9447 if (!text || condition === false) return; 9448 ipe._form.appendChild(document.createTextNode(text)); 9449 }; 9450 this._form = $(document.createElement('form')); 9451 this._form.id = this.options.formId; 9452 this._form.addClassName(this.options.formClassName); 9453 this._form.onsubmit = this._boundSubmitHandler; 9454 this.createEditField(); 9455 if ('textarea' == this._controls.editor.tagName.toLowerCase()) 9456 this._form.appendChild(document.createElement('br')); 9457 if (this.options.onFormCustomization) 9458 this.options.onFormCustomization(this, this._form); 9459 addText('Before', this.options.okControl || this.options.cancelControl); 9460 this.createControl('ok', this._boundSubmitHandler); 9461 addText('Between', this.options.okControl && this.options.cancelControl); 9462 this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); 9463 addText('After', this.options.okControl || this.options.cancelControl); 9464 }, 9465 destroy: function() { 9466 if (this._oldInnerHTML) 9467 this.element.innerHTML = this._oldInnerHTML; 9468 this.leaveEditMode(); 9469 this.unregisterListeners(); 9470 }, 9471 enterEditMode: function(e) { 9472 if (this._saving || this._editing) return; 9473 this._editing = true; 9474 this.triggerCallback('onEnterEditMode'); 9475 if (this.options.externalControl) 9476 this.options.externalControl.hide(); 9477 this.element.hide(); 9478 this.createForm(); 9479 this.element.parentNode.insertBefore(this._form, this.element); 9480 if (!this.options.loadTextURL) 9481 this.postProcessEditField();
9482 if (e) Event.stop(e); 9483 }, 9484 enterHover: function(e) { 9485 if (this.options.hoverClassName) 9486 this.element.addClassName(this.options.hoverClassName); 9487 if (this._saving) return; 9488 this.triggerCallback('onEnterHover'); 9489 }, 9490 getText: function() { 9491 return this.element.innerHTML.unescapeHTML(); 9492 }, 9493 handleAJAXFailure: function(transport) { 9494 this.triggerCallback('onFailure', transport); 9495 if (this._oldInnerHTML) { 9496 this.element.innerHTML = this._oldInnerHTML; 9497 this._oldInnerHTML = null; 9498 } 9499 }, 9500 handleFormCancellation: function(e) { 9501 this.wrapUp(); 9502 if (e) Event.stop(e); 9503 }, 9504 handleFormSubmission: function(e) { 9505 var form = this._form; 9506 var value = $F(this._controls.editor); 9507 this.prepareSubmission(); 9508 var params = this.options.callback(form, value) || ''; 9509 if (Object.isString(params)) 9510 params = params.toQueryParams(); 9511 params.editorId = this.element.id; 9512 if (this.options.htmlResponse) { 9513 var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); 9514 Object.extend(options, { 9515 parameters: params, 9516 onComplete: this._boundWrapperHandler, 9517 onFailure: this._boundFailureHandler 9518 }); 9519 new Ajax.Updater({ success: this.element }, this.url, options); 9520 } else { 9521 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 9522 Object.extend(options, { 9523 parameters: params, 9524 onComplete: this._boundWrapperHandler, 9525 onFailure: this._boundFailureHandler 9526 }); 9527 new Ajax.Request(this.url, options); 9528 } 9529 if (e) Event.stop(e); 9530 }, 9531 leaveEditMode: function() { 9532 this.element.removeClassName(this.options.savingClassName); 9533 this.removeForm(); 9534 this.leaveHover(); 9535 this.element.style.backgroundColor = this._originalBackground; 9536 this.element.show(); 9537 if (this.options.externalControl) 9538 this.options.externalControl.show(); 9539 this._saving = false; 9540 this._editing = false; 9541 this._oldInnerHTML = null; 9542 this.triggerCallback('onLeaveEditMode'); 9543 }, 9544 leaveHover: function(e) { 9545 if (this.options.hoverClassName) 9546 this.element.removeClassName(this.options.hoverClassName); 9547 if (this._saving) return; 9548 this.triggerCallback('onLeaveHover'); 9549 }, 9550 loadExternalText: function() { 9551 this._form.addClassName(this.options.loadingClassName); 9552 this._controls.editor.disabled = true; 9553 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 9554 Object.extend(options, { 9555 parameters: 'editorId=' + encodeURIComponent(this.element.id), 9556 onComplete: Prototype.emptyFunction, 9557 onSuccess: function(transport) { 9558 this._form.removeClassName(this.options.loadingClassName); 9559 var text = transport.responseText; 9560 if (this.options.stripLoadedTextTags) 9561 text = text.stripTags(); 9562 this._controls.editor.value = text; 9563 this._controls.editor.disabled = false; 9564 this.postProcessEditField(); 9565 }.bind(this), 9566 onFailure: this._boundFailureHandler 9567 }); 9568 new Ajax.Request(this.options.loadTextURL, options); 9569 }, 9570 postProcessEditField: function() { 9571 var fpc = this.options.fieldPostCreation; 9572 if (fpc) 9573 $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); 9574 }, 9575 prepareOptions: function() { 9576 this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); 9577 Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); 9578 [this._extraDefaultOptions].flatten().compact().each(function(defs) { 9579 Object.extend(this.options, defs); 9580 }.bind(this)); 9581 }, 9582 prepareSubmission: function() { 9583 this._saving = true; 9584 this.removeForm(); 9585 this.leaveHover(); 9586 this.showSaving(); 9587 }, 9588 registerListeners: function() { 9589 this._listeners = { }; 9590 var listener; 9591 $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { 9592 listener = this[pair.value].bind(this); 9593 this._listeners[pair.key] = listener; 9594 if (!this.options.externalControlOnly) 9595 this.element.observe(pair.key, listener); 9596 if (this.options.externalControl) 9597 this.options.externalControl.observe(pair.key, listener); 9598 }.bind(this)); 9599 }, 9600 removeForm: function() { 9601 if (!this._form) return; 9602 this._form.remove(); 9603 this._form = null; 9604 this._controls = { }; 9605 }, 9606 showSaving: function() { 9607 this._oldInnerHTML = this.element.innerHTML; 9608 this.element.innerHTML = this.options.savingText; 9609 this.element.addClassName(this.options.savingClassName); 9610 this.element.style.backgroundColor = this._originalBackgroun
9610d; 9611 this.element.show(); 9612 }, 9613 triggerCallback: function(cbName, arg) { 9614 if ('function' == typeof this.options[cbName]) { 9615 this.options[cbName](this, arg); 9616 } 9617 }, 9618 unregisterListeners: function() { 9619 $H(this._listeners).each(function(pair) { 9620 if (!this.options.externalControlOnly) 9621 this.element.stopObserving(pair.key, pair.value); 9622 if (this.options.externalControl) 9623 this.options.externalControl.stopObserving(pair.key, pair.value); 9624 }.bind(this)); 9625 }, 9626 wrapUp: function(transport) { 9627 this.leaveEditMode(); 9628 // Can't use triggerCallback due to backward compatibility: requires 9629 // binding + direct element 9630 this._boundComplete(transport, this.element); 9631 } 9632}); 9633 9634Object.extend(Ajax.InPlaceEditor.prototype, { 9635 dispose: Ajax.InPlaceEditor.prototype.destroy 9636}); 9637 9638Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { 9639 initialize: function($super, element, url, options) { 9640 this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; 9641 $super(element, url, options); 9642 }, 9643 9644 createEditField: function() { 9645 var list = document.createElement('select'); 9646 list.name = this.options.paramName; 9647 list.size = 1; 9648 this._controls.editor = list; 9649 this._collection = this.options.collection || []; 9650 if (this.options.loadCollectionURL) 9651 this.loadCollection(); 9652 else 9653 this.checkForExternalText(); 9654 this._form.appendChild(this._controls.editor); 9655 }, 9656 9657 loadCollection: function() { 9658 this._form.addClassName(this.options.loadingClassName); 9659 this.showLoadingText(this.options.loadingCollectionText); 9660 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 9661 Object.extend(options, { 9662 parameters: 'editorId=' + encodeURIComponent(this.element.id), 9663 onComplete: Prototype.emptyFunction, 9664 onSuccess: function(transport) { 9665 var js = transport.responseText.strip(); 9666 if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check 9667 throw('Server returned an invalid collection representation.'); 9668 this._collection = eval(js); 9669 this.checkForExternalText(); 9670 }.bind(this), 9671 onFailure: this.onFailure 9672 }); 9673 new Ajax.Request(this.options.loadCollectionURL, options); 9674 }, 9675 9676 showLoadingText: function(text) { 9677 this._controls.editor.disabled = true; 9678 var tempOption = this._controls.editor.firstChild; 9679 if (!tempOption) { 9680 tempOption = document.createElement('option'); 9681 tempOption.value = ''; 9682 this._controls.editor.appendChild(tempOption); 9683 tempOption.selected = true; 9684 } 9685 tempOption.update((text || '').stripScripts().stripTags()); 9686 }, 9687 9688 checkForExternalText: function() { 9689 this._text = this.getText(); 9690 if (this.options.loadTextURL) 9691 this.loadExternalText(); 9692 else 9693 this.buildOptionList(); 9694 }, 9695 9696 loadExternalText: function() { 9697 this.showLoadingText(this.options.loadingText); 9698 var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); 9699 Object.extend(options, { 9700 parameters: 'editorId=' + encodeURIComponent(this.element.id), 9701 onComplete: Prototype.emptyFunction, 9702 onSuccess: function(transport) { 9703 this._text = transport.responseText.strip(); 9704 this.buildOptionList(); 9705 }.bind(this), 9706 onFailure: this.onFailure 9707 }); 9708 new Ajax.Request(this.options.loadTextURL, options); 9709 }, 9710 9711 buildOptionList: function() { 9712 this._form.removeClassName(this.options.loadingClassName); 9713 this._collection = this._collection.map(function(entry) { 9714 return 2 === entry.length ? entry : [entry, entry].flatten(); 9715 }); 9716 var marker = ('value' in this.options) ? this.options.value : this._text; 9717 var textFound = this._collection.any(function(entry) { 9718 return entry[0] == marker; 9719 }.bind(this)); 9720 this._controls.editor.update(''); 9721 var option; 9722 this._collection.each(function(entry, index) { 9723 option = document.createElement('option'); 9724 option.value = entry[0]; 9725 option.selected = textFound ? entry[0] == marker : 0 == index; 9726 option.appendChild(document.createTextNode(entry[1])); 9727 this._controls.editor.appendChild(option); 9728 }.bind(this)); 9729 this._controls.editor.disabled = false;
9730 Field.scrollFreeActivate(this._controls.editor); 9731 } 9732}); 9733 9734//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** 9735//**** This only exists for a while, in order to let **** 9736//**** users adapt to the new API. Read up on the new **** 9737//**** API and convert your code to it ASAP! **** 9738 9739Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { 9740 if (!options) return; 9741 function fallback(name, expr) { 9742 if (name in options || expr === undefined) return; 9743 options[name] = expr; 9744 }; 9745 fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : 9746 options.cancelLink == options.cancelButton == false ? false : undefined))); 9747 fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : 9748 options.okLink == options.okButton == false ? false : undefined))); 9749 fallback('highlightColor', options.highlightcolor); 9750 fallback('highlightEndColor', options.highlightendcolor); 9751}; 9752 9753Object.extend(Ajax.InPlaceEditor, { 9754 DefaultOptions: { 9755 ajaxOptions: { }, 9756 autoRows: 3, // Use when multi-line w/ rows == 1 9757 cancelControl: 'link', // 'link'|'button'|false 9758 cancelText: 'cancel', 9759 clickToEditText: 'Click to edit', 9760 externalControl: null, // id|elt 9761 externalControlOnly: false, 9762 fieldPostCreation: 'activate', // 'activate'|'focus'|false 9763 formClassName: 'inplaceeditor-form', 9764 formId: null, // id|elt 9765 highlightColor: '#ffff99', 9766 highlightEndColor: '#ffffff', 9767 hoverClassName: '', 9768 htmlResponse: true, 9769 loadingClassName: 'inplaceeditor-loading', 9770 loadingText: 'Loading...', 9771 okControl: 'button', // 'link'|'button'|false 9772 okText: 'ok', 9773 paramName: 'value', 9774 rows: 1, // If 1 and multi-line, uses autoRows 9775 savingClassName: 'inplaceeditor-saving', 9776 savingText: 'Saving...', 9777 size: 0, 9778 stripLoadedTextTags: false, 9779 submitOnBlur: false, 9780 textAfterControls: '', 9781 textBeforeControls: '', 9782 textBetweenControls: '' 9783 }, 9784 DefaultCallbacks: { 9785 callback: function(form) { 9786 return Form.serialize(form); 9787 }, 9788 onComplete: function(transport, element) { 9789 // For backward compatibility, this one is bound to the IPE, and passes 9790 // the element directly. It was too often customized, so we don't break it. 9791 new Effect.Highlight(element, { 9792 startcolor: this.options.highlightColor, keepBackgroundImage: true }); 9793 }, 9794 onEnterEditMode: null, 9795 onEnterHover: function(ipe) { 9796 ipe.element.style.backgroundColor = ipe.options.highlightColor; 9797 if (ipe._effect) 9798 ipe._effect.cancel(); 9799 }, 9800 onFailure: function(transport, ipe) { 9801 alert('Error communication with the server: ' + transport.responseText.stripTags()); 9802 }, 9803 onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. 9804 onLeaveEditMode: null, 9805 onLeaveHover: function(ipe) { 9806 ipe._effect = new Effect.Highlight(ipe.element, { 9807 startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, 9808 restorecolor: ipe._originalBackground, keepBackgroundImage: true 9809 }); 9810 } 9811 }, 9812 Listeners: { 9813 click: 'enterEditMode', 9814 keydown: 'checkForEscapeOrReturn', 9815 mouseover: 'enterHover', 9816 mouseout: 'leaveHover' 9817 } 9818}); 9819 9820Ajax.InPlaceCollectionEditor.DefaultOptions = { 9821 loadingCollectionText: 'Loading options...' 9822}; 9823 9824// Delayed observer, like Form.Element.Observer, 9825// but waits for delay after last key input 9826// Ideal for live-search fields 9827 9828Form.Element.DelayedObserver = Class.create({ 9829 initialize: function(element, delay, callback) { 9830 this.delay = delay || 0.5; 9831 this.element = $(element); 9832 this.callback = callback; 9833 this.timer = null; 9834 this.lastValue = $F(this.element); 9835 Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); 9836 }, 9837 delayedListener: function(event) { 9838 if(this.lastValue == $F(this.element)) return; 9839 if(this.timer) clearTimeout(this.timer); 9840 this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); 9841 this.lastValue = $F(this.element); 9842 },
9843 onTimerEvent: function() { 9844 this.timer = null; 9845 this.callback(this.element, $F(this.element)); 9846 } 9847});// script.aculo.us dragdrop.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 9848 9849// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 9850// 9851// script.aculo.us is freely distributable under the terms of an MIT-style license. 9852// For details, see the script.aculo.us web site: http://script.aculo.us/ 9853 9854if(Object.isUndefined(Effect)) 9855 throw("dragdrop.js requires including script.aculo.us' effects.js library"); 9856 9857var Droppables = { 9858 drops: [], 9859 9860 remove: function(element) { 9861 this.drops = this.drops.reject(function(d) { return d.element==$(element) }); 9862 }, 9863 9864 add: function(element) { 9865 element = $(element); 9866 var options = Object.extend({ 9867 greedy: true, 9868 hoverclass: null, 9869 tree: false 9870 }, arguments[1] || { }); 9871 9872 // cache containers 9873 if(options.containment) { 9874 options._containers = []; 9875 var containment = options.containment; 9876 if(Object.isArray(containment)) { 9877 containment.each( function(c) { options._containers.push($(c)) }); 9878 } else { 9879 options._containers.push($(containment)); 9880 } 9881 } 9882 9883 if(options.accept) options.accept = [options.accept].flatten(); 9884 9885 Element.makePositioned(element); // fix IE 9886 options.element = element; 9887 9888 this.drops.push(options); 9889 }, 9890 9891 findDeepestChild: function(drops) { 9892 deepest = drops[0]; 9893 9894 for (i = 1; i < drops.length; ++i) 9895 if (Element.isParent(drops[i].element, deepest.element)) 9896 deepest = drops[i]; 9897 9898 return deepest; 9899 }, 9900 9901 isContained: function(element, drop) { 9902 var containmentNode; 9903 if(drop.tree) { 9904 containmentNode = element.treeNode; 9905 } else { 9906 containmentNode = element.parentNode; 9907 } 9908 return drop._containers.detect(function(c) { return containmentNode == c }); 9909 }, 9910 9911 isAffected: function(point, element, drop) { 9912 return ( 9913 (drop.element!=element) && 9914 ((!drop._containers) || 9915 this.isContained(element, drop)) && 9916 ((!drop.accept) || 9917 (Element.classNames(element).detect( 9918 function(v) { return drop.accept.include(v) } ) )) && 9919 Position.within(drop.element, point[0], point[1]) ); 9920 }, 9921 9922 deactivate: function(drop) { 9923 if(drop.hoverclass) 9924 Element.removeClassName(drop.element, drop.hoverclass); 9925 this.last_active = null; 9926 }, 9927 9928 activate: function(drop) { 9929 if(drop.hoverclass) 9930 Element.addClassName(drop.element, drop.hoverclass); 9931 this.last_active = drop; 9932 }, 9933 9934 show: function(point, element) { 9935 if(!this.drops.length) return; 9936 var drop, affected = []; 9937 9938 this.drops.each( function(drop) { 9939 if(Droppables.isAffected(point, element, drop)) 9940 affected.push(drop); 9941 }); 9942 9943 if(affected.length>0) 9944 drop = Droppables.findDeepestChild(affected); 9945 9946 if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); 9947 if (drop) { 9948 Position.within(drop.element, point[0], point[1]); 9949 if(drop.onHover) 9950 drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); 9951 9952 if (drop != this.last_active) Droppables.activate(drop); 9953 } 9954 }, 9955 9956 fire: function(event, element) { 9957 if(!this.last_active) return; 9958 Position.prepare(); 9959 9960 if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) 9961 if (this.last_active.onDrop) { 9962 this.last_active.onDrop(element, this.last_active.element, event); 9963 return true; 9964 } 9965 }, 9966 9967 reset: function() { 9968 if(this.last_active) 9969 this.deactivate(this.last_active); 9970 } 9971}; 9972 9973var Draggables = { 9974 drags: [], 9975 observers: [], 9976 9977 register: function(draggable) { 9978 if(this.drags.length == 0) { 9979 this.eventMouseUp = this.endDrag.bindAsEventListener(this); 9980 this.eventMouseMove = this.updateDrag.bindAsEventListener(this); 9981 this.eventKeypress = this.keyPress.bindAsEventListener(this); 9982 9983 Event.observe(document, "mouseup", this.eventMouseUp); 9984 Event.observe(document, "mousemove", this.eventMouseMove); 9985 Event.observe(document, "keypress", this.eventKeypress); 9986 } 9987 this.drags.push(draggable); 9988 }, 9989 9990 unregister: function(draggable) { 9991 this.drags = this.drags.reject(function(d) { return d==draggable }); 9992 if(this.drags.length == 0) { 9993 Event.stopObserving(document, "mouseup", this.eventMouseUp); 9994 Event.stopObserving(document, "mousemove", this.eventMouseMove); 9995 Event.stopObserving(document, "keypress", this.eventKeypress); 9996 } 9997 }, 9998 9999 activate: function(draggable) {
10000 if(draggable.options.delay) { 10001 this._timeout = setTimeout(function() { 10002 Draggables._timeout = null; 10003 window.focus(); 10004 Draggables.activeDraggable = draggable; 10005 }.bind(this), draggable.options.delay); 10006 } else { 10007 window.focus(); // allows keypress events if window isn't currently focused, fails for Safari 10008 this.activeDraggable = draggable; 10009 } 10010 }, 10011 10012 deactivate: function() { 10013 this.activeDraggable = null; 10014 }, 10015 10016 updateDrag: function(event) { 10017 if(!this.activeDraggable) return; 10018 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 10019 // Mozilla-based browsers fire successive mousemove events with 10020 // the same coordinates, prevent needless redrawing (moz bug?) 10021 if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; 10022 this._lastPointer = pointer; 10023 10024 this.activeDraggable.updateDrag(event, pointer); 10025 }, 10026 10027 endDrag: function(event) { 10028 if(this._timeout) { 10029 clearTimeout(this._timeout); 10030 this._timeout = null; 10031 } 10032 if(!this.activeDraggable) return; 10033 this._lastPointer = null; 10034 this.activeDraggable.endDrag(event); 10035 this.activeDraggable = null; 10036 }, 10037 10038 keyPress: function(event) { 10039 if(this.activeDraggable) 10040 this.activeDraggable.keyPress(event); 10041 }, 10042 10043 addObserver: function(observer) { 10044 this.observers.push(observer); 10045 this._cacheObserverCallbacks(); 10046 }, 10047 10048 removeObserver: function(element) { // element instead of observer fixes mem leaks 10049 this.observers = this.observers.reject( function(o) { return o.element==element }); 10050 this._cacheObserverCallbacks(); 10051 }, 10052 10053 notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' 10054 if(this[eventName+'Count'] > 0) 10055 this.observers.each( function(o) { 10056 if(o[eventName]) o[eventName](eventName, draggable, event); 10057 }); 10058 if(draggable.options[eventName]) draggable.options[eventName](draggable, event); 10059 }, 10060 10061 _cacheObserverCallbacks: function() { 10062 ['onStart','onEnd','onDrag'].each( function(eventName) { 10063 Draggables[eventName+'Count'] = Draggables.observers.select( 10064 function(o) { return o[eventName]; } 10065 ).length; 10066 }); 10067 } 10068}; 10069 10070/*--------------------------------------------------------------------------*/ 10071 10072var Draggable = Class.create({ 10073 initialize: function(element) { 10074 var defaults = { 10075 handle: false, 10076 reverteffect: function(element, top_offset, left_offset) { 10077 var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; 10078 new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, 10079 queue: {scope:'_draggable', position:'end'} 10080 }); 10081 }, 10082 endeffect: function(element) { 10083 var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; 10084 new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 10085 queue: {scope:'_draggable', position:'end'}, 10086 afterFinish: function(){ 10087 Draggable._dragging[element] = false 10088 } 10089 }); 10090 }, 10091 zindex: 1000, 10092 revert: false, 10093 quiet: false, 10094 scroll: false, 10095 scrollSensitivity: 20, 10096 scrollSpeed: 15, 10097 snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } 10098 delay: 0 10099 }; 10100 10101 if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) 10102 Object.extend(defaults, { 10103 starteffect: function(element) { 10104 element._opacity = Element.getOpacity(element); 10105 Draggable._dragging[element] = true; 10106 new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 10107 } 10108 }); 10109 10110 var options = Object.extend(defaults, arguments[1] || { }); 10111 10112 this.element = $(element); 10113 10114 if(options.handle && Object.isString(options.handle)) 10115 this.handle = this.element.down('.'+options.handle, 0); 10116 10117 if(!this.handle) this.handle = $(options.handle); 10118 if(!this.handle) this.handle = this.element; 10119 10120 if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { 10121 options.scroll = $(options.scroll); 10122 this._isScrollChild = Element.childOf(this.element, options.scroll); 10123 } 10124 10125 Element.makePositioned(this.element); // fix IE 10126 10127 this.options = options; 10128 this.dragging = false;
10129 10130 this.eventMouseDown = this.initDrag.bindAsEventListener(this); 10131 Event.observe(this.handle, "mousedown", this.eventMouseDown); 10132 10133 Draggables.register(this); 10134 }, 10135 10136 destroy: function() { 10137 Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); 10138 Draggables.unregister(this); 10139 }, 10140 10141 currentDelta: function() { 10142 return([ 10143 parseInt(Element.getStyle(this.element,'left') || '0'), 10144 parseInt(Element.getStyle(this.element,'top') || '0')]); 10145 }, 10146 10147 initDrag: function(event) { 10148 if(!Object.isUndefined(Draggable._dragging[this.element]) && 10149 Draggable._dragging[this.element]) return; 10150 if(Event.isLeftClick(event)) { 10151 // abort on form elements, fixes a Firefox issue 10152 var src = Event.element(event); 10153 if((tag_name = src.tagName.toUpperCase()) && ( 10154 tag_name=='INPUT' || 10155 tag_name=='SELECT' || 10156 tag_name=='OPTION' || 10157 tag_name=='BUTTON' || 10158 tag_name=='TEXTAREA')) return; 10159 10160 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 10161 var pos = this.element.cumulativeOffset(); 10162 this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); 10163 10164 Draggables.activate(this); 10165 Event.stop(event); 10166 } 10167 }, 10168 10169 startDrag: function(event) { 10170 this.dragging = true; 10171 if(!this.delta) 10172 this.delta = this.currentDelta(); 10173 10174 if(this.options.zindex) { 10175 this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); 10176 this.element.style.zIndex = this.options.zindex; 10177 } 10178 10179 if(this.options.ghosting) { 10180 this._clone = this.element.cloneNode(true); 10181 this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); 10182 if (!this._originallyAbsolute) 10183 Position.absolutize(this.element); 10184 this.element.parentNode.insertBefore(this._clone, this.element); 10185 } 10186 10187 if(this.options.scroll) { 10188 if (this.options.scroll == window) { 10189 var where = this._getWindowScroll(this.options.scroll); 10190 this.originalScrollLeft = where.left; 10191 this.originalScrollTop = where.top; 10192 } else { 10193 this.originalScrollLeft = this.options.scroll.scrollLeft; 10194 this.originalScrollTop = this.options.scroll.scrollTop; 10195 } 10196 } 10197 10198 Draggables.notify('onStart', this, event); 10199 10200 if(this.options.starteffect) this.options.starteffect(this.element); 10201 }, 10202 10203 updateDrag: function(event, pointer) { 10204 if(!this.dragging) this.startDrag(event); 10205 10206 if(!this.options.quiet){ 10207 Position.prepare(); 10208 Droppables.show(pointer, this.element); 10209 } 10210 10211 Draggables.notify('onDrag', this, event); 10212 10213 this.draw(pointer); 10214 if(this.options.change) this.options.change(this); 10215 10216 if(this.options.scroll) { 10217 this.stopScrolling(); 10218 10219 var p; 10220 if (this.options.scroll == window) { 10221 with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } 10222 } else { 10223 p = Position.page(this.options.scroll).toArray(); 10224 p[0] += this.options.scroll.scrollLeft + Position.deltaX; 10225 p[1] += this.options.scroll.scrollTop + Position.deltaY; 10226 p.push(p[0]+this.options.scroll.offsetWidth); 10227 p.push(p[1]+this.options.scroll.offsetHeight); 10228 } 10229 var speed = [0,0]; 10230 if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); 10231 if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); 10232 if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); 10233 if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); 10234 this.startScrolling(speed); 10235 } 10236 10237 // fix AppleWebKit rendering 10238 if(Prototype.Browser.WebKit) window.scrollBy(0,0); 10239 10240 Event.stop(event); 10241 }, 10242 10243 finishDrag: function(event, success) { 10244 this.dragging = false; 10245 10246 if(this.options.quiet){ 10247 Position.prepare(); 10248 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 10249 Droppables.show(pointer, this.element); 10250 } 10251 10252 if(this.options.ghosting) { 10253 if (!this._originallyAbsolute) 10254 Position.relativize(this.element); 10255 delete this._originallyAbsolute; 10256 Element.remove(this._clone); 10257 this._clone = null; 10258 } 10259 10260 var dropped = false;
10261 if(success) { 10262 dropped = Droppables.fire(event, this.element); 10263 if (!dropped) dropped = false; 10264 } 10265 if(dropped && this.options.onDropped) this.options.onDropped(this.element); 10266 Draggables.notify('onEnd', this, event); 10267 10268 var revert = this.options.revert; 10269 if(revert && Object.isFunction(revert)) revert = revert(this.element); 10270 10271 var d = this.currentDelta(); 10272 if(revert && this.options.reverteffect) { 10273 if (dropped == 0 || revert != 'failure') 10274 this.options.reverteffect(this.element, 10275 d[1]-this.delta[1], d[0]-this.delta[0]); 10276 } else { 10277 this.delta = d; 10278 } 10279 10280 if(this.options.zindex) 10281 this.element.style.zIndex = this.originalZ; 10282 10283 if(this.options.endeffect) 10284 this.options.endeffect(this.element); 10285 10286 Draggables.deactivate(this); 10287 Droppables.reset(); 10288 }, 10289 10290 keyPress: function(event) { 10291 if(event.keyCode!=Event.KEY_ESC) return; 10292 this.finishDrag(event, false); 10293 Event.stop(event); 10294 }, 10295 10296 endDrag: function(event) { 10297 if(!this.dragging) return; 10298 this.stopScrolling(); 10299 this.finishDrag(event, true); 10300 Event.stop(event); 10301 }, 10302 10303 draw: function(point) { 10304 var pos = this.element.cumulativeOffset(); 10305 if(this.options.ghosting) { 10306 var r = Position.realOffset(this.element); 10307 pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; 10308 } 10309 10310 var d = this.currentDelta(); 10311 pos[0] -= d[0]; pos[1] -= d[1]; 10312 10313 if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { 10314 pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; 10315 pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; 10316 } 10317 10318 var p = [0,1].map(function(i){ 10319 return (point[i]-pos[i]-this.offset[i]) 10320 }.bind(this)); 10321 10322 if(this.options.snap) { 10323 if(Object.isFunction(this.options.snap)) { 10324 p = this.options.snap(p[0],p[1],this); 10325 } else { 10326 if(Object.isArray(this.options.snap)) { 10327 p = p.map( function(v, i) { 10328 return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); 10329 } else { 10330 p = p.map( function(v) { 10331 return (v/this.options.snap).round()*this.options.snap }.bind(this)); 10332 } 10333 }} 10334 10335 var style = this.element.style; 10336 if((!this.options.constraint) || (this.options.constraint=='horizontal')) 10337 style.left = p[0] + "px"; 10338 if((!this.options.constraint) || (this.options.constraint=='vertical')) 10339 style.top = p[1] + "px"; 10340 10341 if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering 10342 }, 10343 10344 stopScrolling: function() { 10345 if(this.scrollInterval) { 10346 clearInterval(this.scrollInterval); 10347 this.scrollInterval = null; 10348 Draggables._lastScrollPointer = null; 10349 } 10350 }, 10351 10352 startScrolling: function(speed) { 10353 if(!(speed[0] || speed[1])) return; 10354 this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; 10355 this.lastScrolled = new Date(); 10356 this.scrollInterval = setInterval(this.scroll.bind(this), 10); 10357 }, 10358 10359 scroll: function() { 10360 var current = new Date(); 10361 var delta = current - this.lastScrolled; 10362 this.lastScrolled = current; 10363 if(this.options.scroll == window) { 10364 with (this._getWindowScroll(this.options.scroll)) { 10365 if (this.scrollSpeed[0] || this.scrollSpeed[1]) { 10366 var d = delta / 1000; 10367 this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); 10368 } 10369 } 10370 } else { 10371 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; 10372 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; 10373 } 10374 10375 Position.prepare(); 10376 Droppables.show(Draggables._lastPointer, this.element); 10377 Draggables.notify('onDrag', this); 10378 if (this._isScrollChild) { 10379 Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); 10380 Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; 10381 Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; 10382 if (Draggables._lastScrollPointer[0] < 0) 10383 Draggables._lastScrollPointer[0] = 0; 10384 if (Draggables._lastScrollPointer[1] < 0) 10385 Draggables._lastScrollPointer[1] = 0; 10386 this.draw(Draggables._lastScrollPointer); 10387 } 10388 10389 if(this.options.change) this.options.change(this); 10390 }, 10391 10392 _getWindowScroll: function(w) { 10393 var T, L, W, H; 10394 with (w.document) { 10395 if (w.document.documentElement && documentElement.scrollTop) { 10396 T = documentElement.scrollTop; 10397 L = documentElement.scrollLeft; 10398 } else if (w.document.body) { 10399 T = body.scrollTop; 10400 L = body.scrollLeft; 10401 } 10402 if (w.innerWidth) { 10403 W = w.innerWidth; 10404 H = w.innerHeight; 10405 } else if (w.document.documentElement && documentElement.clientWidth) { 10406 W = documentElement.clientWidth; 10407 H = documentElement.clientHeight; 10408 } else { 10409 W = body.offsetWidth; 10410 H = body.offsetHeight; 10411 } 10412 } 10413 return { top: T, left: L, width: W, height: H }; 10414 } 10415}); 10416 10417Draggable._dragging = { }; 10418 10419/*--------------------------------------------------------------------------*/ 10420 10421var SortableObserver = Class.create({ 10422 initialize: function(element, observer) { 10423 this.element = $(element); 10424 this.observer = observer; 10425 this.lastValue = Sortable.serialize(this.element); 10426 }, 10427 10428 onStart: function() { 10429 this.lastValue = Sortable.serialize(this.element); 10430 }, 10431 10432 onEnd: function() { 10433 Sortable.unmark(); 10434 if(this.lastValue != Sortable.serialize(this.element)) 10435 this.observer(this.element) 10436 } 10437}); 10438 10439var Sortable = { 10440 SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, 10441 10442 sortables: { }, 10443 10444 _findRootElement: function(element) { 10445 while (element.tagName.toUpperCase() != "BODY") {
10446 if(element.id && Sortable.sortables[element.id]) return element; 10447 element = element.parentNode; 10448 } 10449 }, 10450 10451 options: function(element) { 10452 element = Sortable._findRootElement($(element)); 10453 if(!element) return; 10454 return Sortable.sortables[element.id]; 10455 }, 10456 10457 destroy: function(element){ 10458 element = $(element); 10459 var s = Sortable.sortables[element.id]; 10460 10461 if(s) { 10462 Draggables.removeObserver(s.element); 10463 s.droppables.each(function(d){ Droppables.remove(d) }); 10464 s.draggables.invoke('destroy'); 10465 10466 delete Sortable.sortables[s.element.id]; 10467 } 10468 }, 10469 10470 create: function(element) { 10471 element = $(element); 10472 var options = Object.extend({ 10473 element: element, 10474 tag: 'li', // assumes li children, override with tag: 'tagname' 10475 dropOnEmpty: false, 10476 tree: false, 10477 treeTag: 'ul', 10478 overlap: 'vertical', // one of 'vertical', 'horizontal' 10479 constraint: 'vertical', // one of 'vertical', 'horizontal', false 10480 containment: element, // also takes array of elements (or id's); or false 10481 handle: false, // or a CSS class 10482 only: false, 10483 delay: 0, 10484 hoverclass: null, 10485 ghosting: false, 10486 quiet: false, 10487 scroll: false, 10488 scrollSensitivity: 20, 10489 scrollSpeed: 15, 10490 format: this.SERIALIZE_RULE, 10491 10492 // these take arrays of elements or ids and can be 10493 // used for better initialization performance 10494 elements: false, 10495 handles: false, 10496 10497 onChange: Prototype.emptyFunction, 10498 onUpdate: Prototype.emptyFunction 10499 }, arguments[1] || { }); 10500 10501 // clear any old sortable with same element 10502 this.destroy(element); 10503 10504 // build options for the draggables 10505 var options_for_draggable = { 10506 revert: true, 10507 quiet: options.quiet, 10508 scroll: options.scroll, 10509 scrollSpeed: options.scrollSpeed, 10510 scrollSensitivity: options.scrollSensitivity, 10511 delay: options.delay, 10512 ghosting: options.ghosting, 10513 constraint: options.constraint, 10514 handle: options.handle }; 10515 10516 if(options.starteffect) 10517 options_for_draggable.starteffect = options.starteffect; 10518 10519 if(options.reverteffect) 10520 options_for_draggable.reverteffect = options.reverteffect; 10521 else 10522 if(options.ghosting) options_for_draggable.reverteffect = function(element) { 10523 element.style.top = 0; 10524 element.style.left = 0; 10525 }; 10526 10527 if(options.endeffect) 10528 options_for_draggable.endeffect = options.endeffect; 10529 10530 if(options.zindex) 10531 options_for_draggable.zindex = options.zindex; 10532 10533 // build options for the droppables 10534 var options_for_droppable = { 10535 overlap: options.overlap, 10536 containment: options.containment, 10537 tree: options.tree, 10538 hoverclass: options.hoverclass, 10539 onHover: Sortable.onHover 10540 }; 10541 10542 var options_for_tree = { 10543 onHover: Sortable.onEmptyHover, 10544 overlap: options.overlap, 10545 containment: options.containment, 10546 hoverclass: options.hoverclass 10547 }; 10548 10549 // fix for gecko engine 10550 Element.cleanWhitespace(element); 10551 10552 options.draggables = []; 10553 options.droppables = []; 10554 10555 // drop on empty handling 10556 if(options.dropOnEmpty || options.tree) { 10557 Droppables.add(element, options_for_tree); 10558 options.droppables.push(element); 10559 } 10560 10561 (options.elements || this.findElements(element, options) || []).each( function(e,i) { 10562 var handle = options.handles ? $(options.handles[i]) : 10563 (options.handle ? $(e).select('.' + options.handle)[0] : e); 10564 options.draggables.push( 10565 new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); 10566 Droppables.add(e, options_for_droppable); 10567 if(options.tree) e.treeNode = element; 10568 options.droppables.push(e); 10569 }); 10570 10571 if(options.tree) { 10572 (Sortable.findTreeElements(element, options) || []).each( function(e) { 10573 Droppables.add(e, options_for_tree); 10574 e.treeNode = element; 10575 options.droppables.push(e); 10576 }); 10577 } 10578 10579 // keep reference
10580 this.sortables[element.identify()] = options; 10581 10582 // for onupdate 10583 Draggables.addObserver(new SortableObserver(element, options.onUpdate)); 10584 10585 }, 10586 10587 // return all suitable-for-sortable elements in a guaranteed order 10588 findElements: function(element, options) { 10589 return Element.findChildren( 10590 element, options.only, options.tree ? true : false, options.tag); 10591 }, 10592 10593 findTreeElements: function(element, options) { 10594 return Element.findChildren( 10595 element, options.only, options.tree ? true : false, options.treeTag); 10596 }, 10597 10598 onHover: function(element, dropon, overlap) { 10599 if(Element.isParent(dropon, element)) return; 10600 10601 if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { 10602 return; 10603 } else if(overlap>0.5) { 10604 Sortable.mark(dropon, 'before'); 10605 if(dropon.previousSibling != element) { 10606 var oldParentNode = element.parentNode; 10607 element.style.visibility = "hidden"; // fix gecko rendering 10608 dropon.parentNode.insertBefore(element, dropon); 10609 if(dropon.parentNode!=oldParentNode) 10610 Sortable.options(oldParentNode).onChange(element); 10611 Sortable.options(dropon.parentNode).onChange(element); 10612 } 10613 } else { 10614 Sortable.mark(dropon, 'after'); 10615 var nextElement = dropon.nextSibling || null; 10616 if(nextElement != element) { 10617 var oldParentNode = element.parentNode; 10618 element.style.visibility = "hidden"; // fix gecko rendering 10619 dropon.parentNode.insertBefore(element, nextElement); 10620 if(dropon.parentNode!=oldParentNode) 10621 Sortable.options(oldParentNode).onChange(element); 10622 Sortable.options(dropon.parentNode).onChange(element); 10623 } 10624 } 10625 }, 10626 10627 onEmptyHover: function(element, dropon, overlap) { 10628 var oldParentNode = element.parentNode; 10629 var droponOptions = Sortable.options(dropon); 10630 10631 if(!Element.isParent(dropon, element)) { 10632 var index; 10633 10634 var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); 10635 var child = null; 10636 10637 if(children) { 10638 var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); 10639 10640 for (index = 0; index < children.length; index += 1) { 10641 if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { 10642 offset -= Element.offsetSize (children[index], droponOptions.overlap); 10643 } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { 10644 child = index + 1 < children.length ? children[index + 1] : null; 10645 break; 10646 } else { 10647 child = children[index]; 10648 break; 10649 } 10650 } 10651 } 10652 10653 dropon.insertBefore(element, child); 10654 10655 Sortable.options(oldParentNode).onChange(element); 10656 droponOptions.onChange(element); 10657 } 10658 }, 10659 10660 unmark: function() { 10661 if(Sortable._marker) Sortable._marker.hide(); 10662 }, 10663 10664 mark: function(dropon, position) { 10665 // mark on ghosting only 10666 var sortable = Sortable.options(dropon.parentNode); 10667 if(sortable && !sortable.ghosting) return; 10668 10669 if(!Sortable._marker) { 10670 Sortable._marker = 10671 ($('dropmarker') || Element.extend(document.createElement('DIV'))). 10672 hide().addClassName('dropmarker').setStyle({position:'absolute'}); 10673 document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); 10674 } 10675 var offsets = dropon.cumulativeOffset(); 10676 Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); 10677 10678 if(position=='after') 10679 if(sortable.overlap == 'horizontal') 10680 Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); 10681 else 10682 Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); 10683 10684 Sortable._marker.show(); 10685 }, 10686 10687 _tree: function(element, options, parent) { 10688 var children = Sortable.findElements(element, options) || []; 10689 10690 for (var i = 0; i < children.length; ++i) { 10691 var match = children[i].id.match(options.format); 10692 10693 if (!match) continue; 10694 10695 var child = { 10696 id: encodeURIComponent(match ? match[1] : null),
10697 element: element, 10698 parent: parent, 10699 children: [], 10700 position: parent.children.length, 10701 container: $(children[i]).down(options.treeTag) 10702 }; 10703 10704 /* Get the element containing the children and recurse over it */ 10705 if (child.container) 10706 this._tree(child.container, options, child); 10707 10708 parent.children.push (child); 10709 } 10710 10711 return parent; 10712 }, 10713 10714 tree: function(element) { 10715 element = $(element); 10716 var sortableOptions = this.options(element); 10717 var options = Object.extend({ 10718 tag: sortableOptions.tag, 10719 treeTag: sortableOptions.treeTag, 10720 only: sortableOptions.only, 10721 name: element.id, 10722 format: sortableOptions.format 10723 }, arguments[1] || { }); 10724 10725 var root = { 10726 id: null, 10727 parent: null, 10728 children: [], 10729 container: element, 10730 position: 0 10731 }; 10732 10733 return Sortable._tree(element, options, root); 10734 }, 10735 10736 /* Construct a [i] index for a particular node */ 10737 _constructIndex: function(node) { 10738 var index = ''; 10739 do { 10740 if (node.id) index = '[' + node.position + ']' + index; 10741 } while ((node = node.parent) != null); 10742 return index; 10743 }, 10744 10745 sequence: function(element) { 10746 element = $(element); 10747 var options = Object.extend(this.options(element), arguments[1] || { }); 10748 10749 return $(this.findElements(element, options) || []).map( function(item) { 10750 return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; 10751 }); 10752 }, 10753 10754 setSequence: function(element, new_sequence) { 10755 element = $(element); 10756 var options = Object.extend(this.options(element), arguments[2] || { }); 10757 10758 var nodeMap = { }; 10759 this.findElements(element, options).each( function(n) { 10760 if (n.id.match(options.format)) 10761 nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; 10762 n.parentNode.removeChild(n); 10763 }); 10764 10765 new_sequence.each(function(ident) { 10766 var n = nodeMap[ident]; 10767 if (n) { 10768 n[1].appendChild(n[0]); 10769 delete nodeMap[ident]; 10770 } 10771 }); 10772 }, 10773 10774 serialize: function(element) { 10775 element = $(element); 10776 var options = Object.extend(Sortable.options(element), arguments[1] || { }); 10777 var name = encodeURIComponent( 10778 (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); 10779 10780 if (options.tree) { 10781 return Sortable.tree(element, arguments[1]).children.map( function (item) { 10782 return [name + Sortable._constructIndex(item) + "[id]=" + 10783 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); 10784 }).flatten().join('&'); 10785 } else { 10786 return Sortable.sequence(element, arguments[1]).map( function(item) { 10787 return name + "[]=" + encodeURIComponent(item); 10788 }).join('&'); 10789 } 10790 } 10791}; 10792 10793// Returns true if child is contained within element 10794Element.isParent = function(child, element) { 10795 if (!child.parentNode || child == element) return false; 10796 if (child.parentNode == element) return true; 10797 return Element.isParent(child.parentNode, element); 10798}; 10799 10800Element.findChildren = function(element, only, recursive, tagName) { 10801 if(!element.hasChildNodes()) return null; 10802 tagName = tagName.toUpperCase(); 10803 if(only) only = [only].flatten(); 10804 var elements = []; 10805 $A(element.childNodes).each( function(e) { 10806 if(e.tagName && e.tagName.toUpperCase()==tagName && 10807 (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) 10808 elements.push(e); 10809 if(recursive) { 10810 var grandchildren = Element.findChildren(e, only, recursive, tagName); 10811 if(grandchildren) elements.push(grandchildren); 10812 } 10813 }); 10814 10815 return (elements.length>0 ? elements.flatten() : []); 10816}; 10817 10818Element.offsetSize = function (element, type) { 10819 return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; 10820}; 10821Ajax.AutocompleterExtended = Class.create(); 10822Object.extend(Object.extend(Ajax.AutocompleterExtended.prototype, Autocompleter.Base.prototype), { 10823 initialize: function(element, update, url, options, extra_params, static_params) { 10824 this.baseInitialize(element, update, options); 10825 this.options.asynchronous = true; 10826 this.options.onComplete = this.onComplete.bind(this); 10827 this.options.defaultParams = this.options.parameters || null; 10828 this.url = url; 10829 this.extra_params = extra_params; 10830 this.static_params = static_params; 10831 }, 10832 10833 getUpdatedChoices: function() { 10834 entry = encodeURIComponent(this.options.paramName) + '=' + 10835 encodeURIComponent(this.getToken()); 10836 10837 this.options.parameters = this.options.callback ? 10838 this.options.callback(this.element, entry) : entry; 10839 10840 if(this.options.defaultParams) 10841 this.options.parameters += '&' + this.options.defaultParams; 10842 10843 var tmp = ""; 10844 if (this.extra_params && this.extra_params.length > 0) { 10845 //tmp += "?"; 10846 for (i=0;i<this.extra_params.length;i++) { 10847 if (i > 0) { 10848 tmp+="&"; 10849 } 10850 for(j=0;j<this.element.form.elements.length;j++) { 10851 if (this.element.form.elements[j].name == this.extra_params[i]) { 10852 if (this.element.form.elements[j].type == "text" || this.element.form.elements[j].type == "hidden") { 10853 tmp += encodeURIComponent(this.extra_params[i]) + "=" + encodeURIComponent(this.element.form.elements[j].value); 10854 } 10855 } 10856 } 10857 } 10858 this.options.parameters += '&' + tmp; 10859 } 10860 var tmp = ""; 10861 if (this.static_params && this.static_params.length > 0) { 10862 for (sp in this.static_params) { 10863 if (this.static_params.propertyIsEnumerable(sp)) { 10864 //alert(sp); 10865 tmp += "&" + encodeURIComponent(sp) + "=" + encodeURIComponent(this.static_params[sp]); 10866 } 10867 } 10868 this.options.parameters += '&' + tmp; 10869 } 10870 10871 new Ajax.Request(this.url, this.options); 10872 }, 10873 10874 onComplete: function(request) { 10875 this.updateChoices(request.responseText); 10876 } 10877}); 10878 10879// script.aculo.us slider.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 10880 10881// Copyright (c) 2005-2010 Marty Haught, Thomas Fuchs 10882// 10883// script.aculo.us is freely distributable under the terms of an MIT
10883-style license. 10884// For details, see the script.aculo.us web site: http://script.aculo.us/ 10885 10886if (!Control) var Control = { }; 10887 10888// options: 10889// axis: 'vertical', or 'horizontal' (default) 10890// 10891// callbacks: 10892// onChange(value) 10893// onSlide(value) 10894Control.Slider = Class.create({ 10895 initialize: function(handle, track, options) { 10896 var slider = this; 10897 10898 if (Object.isArray(handle)) { 10899 this.handles = handle.collect( function(e) { return $(e) }); 10900 } else { 10901 this.handles = [$(handle)]; 10902 } 10903 10904 this.track = $(track); 10905 this.options = options || { }; 10906 10907 this.axis = this.options.axis || 'horizontal'; 10908 this.increment = this.options.increment || 1; 10909 this.step = parseInt(this.options.step || '1'); 10910 this.range = this.options.range || $R(0,1); 10911 10912 this.value = 0; // assure backwards compat 10913 this.values = this.handles.map( function() { return 0 }); 10914 this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false; 10915 this.options.startSpan = $(this.options.startSpan || null); 10916 this.options.endSpan = $(this.options.endSpan || null); 10917 10918 this.restricted = this.options.restricted || false; 10919 10920 this.maximum = this.options.maximum || this.range.end; 10921 this.minimum = this.options.minimum || this.range.start; 10922 10923 // Will be used to align the handle onto the track, if necessary 10924 this.alignX = parseInt(this.options.alignX || '0'); 10925 this.alignY = parseInt(this.options.alignY || '0'); 10926 10927 this.trackLength = this.maximumOffset() - this.minimumOffset(); 10928 10929 this.handleLength = this.isVertical() ? 10930 (this.handles[0].offsetHeight != 0 ? 10931 this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 10932 (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 10933 this.handles[0].style.width.replace(/px$/,"")); 10934 10935 this.active = false; 10936 this.dragging = false; 10937 this.disabled = false; 10938 10939 if (this.options.disabled) this.setDisabled(); 10940 10941 // Allowed values array 10942 this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; 10943 if (this.allowedValues) { 10944 this.minimum = this.allowedValues.min(); 10945 this.maximum = this.allowedValues.max(); 10946 } 10947 10948 this.eventMouseDown = this.startDrag.bindAsEventListener(this); 10949 this.eventMouseUp = this.endDrag.bindAsEventListener(this); 10950 this.eventMouseMove = this.update.bindAsEventListener(this); 10951 10952 // Initialize handles in reverse (make sure first handle is active) 10953 this.handles.each( function(h,i) { 10954 i = slider.handles.length-1-i; 10955 slider.setValue(parseFloat( 10956 (Object.isArray(slider.options.sliderValue) ? 10957 slider.options.sliderValue[i] : slider.options.sliderValue) || 10958 slider.range.start), i); 10959 h.makePositioned().observe("mousedown", slider.eventMouseDown); 10960 }); 10961 10962 this.track.observe("mousedown", this.eventMouseDown); 10963 document.observe("mouseup", this.eventMouseUp); 10964 document.observe("mousemove", this.eventMouseMove); 10965 10966 this.initialized = true; 10967 }, 10968 dispose: function() { 10969 var slider = this; 10970 Event.stopObserving(this.track, "mousedown", this.eventMouseDown); 10971 Event.stopObserving(document, "mouseup", this.eventMouseUp); 10972 Event.stopObserving(document, "mousemove", this.eventMouseMove); 10973 this.handles.each( function(h) { 10974 Event.stopObserving(h, "mousedown", slider.eventMouseDown); 10975 }); 10976 }, 10977 setDisabled: function(){ 10978 this.disabled = true; 10979 }, 10980 setEnabled: function(){ 10981 this.disabled = false; 10982 }, 10983 getNearestValue: function(value){ 10984 if (this.allowedValues){ 10985 if (value >= this.allowedValues.max()) return(this.allowedValues.max()); 10986 if (value <= this.allowedValues.min()) return(this.allowedValues.min()); 10987 10988 var offset = Math.abs(this.allowedValues[0] - value); 10989 var newValue = this.allowedValues[0]; 10990 this.allowedValues.each( function(v) { 10991 var currentOffset = Math.abs(v - value); 10992 if (currentOffset <= offset){ 10993 newValue = v; 10994 offset = currentOffset; 10995 } 10996 }); 10997 return newValue; 10998 } 10999 if (value > this.range.end) return this.range.end; 11000 if (value < this.range.start) return this.range.start; 11001 return value; 11002 }, 11003 setValue: function(sliderValue, handleIdx){ 11004 if (!this.active) { 11005 this.activeHandleIdx = handleIdx || 0; 11006 this.activeHandle = this.handles[this.activeHandleIdx]; 11007 this.updateStyles(); 11008 } 11009 handleIdx = handleIdx || this.activeHandleIdx || 0; 11010 if (this.initialized && this.restricted) { 11011 if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1])) 11012 sliderValue = this.values[handleIdx-1]; 11013 if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1])) 11014 sliderValue = this.values[handleIdx+1]; 11015 } 11016 sliderValue = this.getNearestValue(sliderValue); 11017 this.values[handleIdx] = sliderValue; 11018 this.value = this.values[0]; // assure backwards compat 11019 11020 this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 11021 this.translateToPx(sliderValue); 11022 11023 this.drawSpans(); 11024 if (!this.dragging || !this.event) this.updateFinished(); 11025 }, 11026 setValueBy: function(delta, handleIdx) { 11027 this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 11028 handleIdx || this.activeHandleIdx || 0); 11029 }, 11030 translateToPx: function(value) { 11031 return Math.round( 11032 ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 11033 (value - this.range.start)) + "px"; 11034 }, 11035 translateToValue: function(offset) { 11036 return ((offset/(this.trackLength-this.handleLength) * 11037 (this.range.end-this.range.start)) + this.range.start); 11038 }, 11039 getRange: function(range) { 11040 var v = this.values.sortBy(Prototype.K); 11041 range = range || 0; 11042 return $R(v[range],v[range+1]); 11043 }, 11044 minimumOffset: function(){ 11045 return(this.isVertical() ? this.alignY : this.alignX); 11046 }, 11047 maximumOffset: function(){ 11048 return(this.isVertical() ? 11049 (this.track.offsetHeight != 0 ? this.track.offsetHeight : 11050 this.track.style.height.replace(/px$/,"")) - this.alignY : 11051 (this.track.offsetWidth != 0 ? this.track.offsetWidth : 11052 this.track.style.width.replace(/px$/,"")) - this.alignX); 11053 }, 11054 isVertical: function(){ 11055 return (this.axis == 'vertical'); 11056 }, 11057 drawSpans: function() { 11058 var slider = this; 11059 if (this.spans) 11060 $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) }); 11061 if (this.options.startSpan) 11062 this.setSpan(this.options.startSpan, 11063 $R(0, this.values.length>1 ? this.getRange(0).min() : this.value )); 11064 if (this.options.endSpan) 11065 this.setSpan(this.options.endSpan, 11066 $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum)); 11067 }, 11068 setSpan: function(span, range) { 11069 if (this.isVertical()) { 11070 span.style.top = this.translateToPx(range.start); 11071 span.style.height = this.translateToPx(range.end - range.start + this.range.start); 11072 } else { 11073 span.style.left = this.translateToPx(range.start); 11074 span.style.width = this.translateToPx(range.end - range.start + this.range.start); 11075 } 11076 }, 11077 updateStyles: function() { 11078 this.handles.each( function(h){ Element.removeClassName(h, 'selected') }); 11079 Element.addClassName(this.activeHandle, 'selected'); 11080 }, 11081 startDrag: function(event) { 11082 if (Event.isLeftClick(event)) { 11083 if (!this.disabled){ 11084 this.active = true; 11085 11086 var handle = Event.element(event); 11087 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 11088 var track = handle; 11089 if (track==this.track) { 11090 var offsets = this.track.cumulativeOffset(); 11091 this.event = event; 11092 this.setValue(this.translateToValue( 11093 (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2) 11094 )); 11095 var offsets = this.activeHandle.cumulativeOffset(); 11096 this.offsetX = (pointer[0] - offsets[0]); 11097 this.offsetY = (pointer[1] - offsets[1]); 11098 } else { 11099 // find the handle (prevents issues with Safari) 11100 while((this.handles.indexOf(handle) == -1) && handle.parentNode) 11101 handle = handle.parentNode; 11102 11103 if (this.handles.indexOf(handle)!=-1) { 11104 this.activeHandle = handle; 11105 this.activeHandleIdx = this.handles.indexOf(this.activeHandle); 11106 this.updateStyles(); 11107 11108 var offsets = this.activeHandle.cumulativeOffset(); 11109 this.offsetX = (pointer[0] - offsets[0]); 11110 this.offsetY = (pointer[1] - offsets[1]); 11111 } 11112 } 11113 } 11114 Event.stop(event); 11115 } 11116 }, 11117 update: function(event) { 11118 if (this.active) { 11119 if (!this.dragging) this.dragging = true; 11120 this.draw(event); 11121 if (Prototype.Browser.WebKit) window.scrollBy(0,0); 11122 Event.stop(event); 11123 } 11124 }, 11125 draw: function(event) { 11126 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 11127 var offsets = this.track.cumulativeOffset(); 11128 pointer[0] -= this.offsetX + offsets[0]; 11129 pointer[1] -= this.offsetY + offsets[1]; 11130 this.event = event; 11131 this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] )); 11132 if (this.initialized && this.options.onSlide) 11133 this.options.onSlide(this.values.length>1 ? this.values : this.value, this); 11134 }, 11135 endDrag: function(event) { 11136 if (this.active && this.dragging) { 11137 this.finishDrag(event, true); 11138 Event.stop(event); 11139 } 11140 this.active = false;
11141 this.dragging = false; 11142 }, 11143 finishDrag: function(event, success) { 11144 this.active = false; 11145 this.dragging = false; 11146 this.updateFinished(); 11147 }, 11148 updateFinished: function() { 11149 if (this.initialized && this.options.onChange) 11150 this.options.onChange(this.values.length>1 ? this.values : this.value, this); 11151 this.event = null; 11152 } 11153});// script.aculo.us sound.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010 11154 11155// Copyright (c) 2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 11156// 11157// Based on code created by Jules Gravinese (http://www.webveteran.com/) 11158// 11159// script.aculo.us is freely distributable under the terms of an MIT-style license. 11160// For details, see the script.aculo.us web site: http://script.aculo.us/ 11161 11162Sound = { 11163 tracks: {}, 11164 _enabled: true, 11165 template: 11166 new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'), 11167 enable: function(){ 11168 Sound._enabled = true; 11169 }, 11170 disable: function(){ 11171 Sound._enabled = false; 11172 }, 11173 play: function(url){ 11174 if(!Sound._enabled) return; 11175 var options = Object.extend({ 11176 track: 'global', url: url, replace: false 11177 }, arguments[1] || {}); 11178 11179 if(options.replace && this.tracks[options.track]) { 11180 $R(0, this.tracks[options.track].id).each(function(id){ 11181 var sound = $('sound_'+options.track+'_'+id); 11182 sound.Stop && sound.Stop(); 11183 sound.remove(); 11184 }); 11185 this.tracks[options.track] = null; 11186 } 11187 11188 if(!this.tracks[options.track]) 11189 this.tracks[options.track] = { id: 0 }; 11190 else 11191 this.tracks[options.track].id++; 11192 11193 options.id = this.tracks[options.track].id; 11194 $$('body')[0].insert( 11195 Prototype.Browser.IE ? new Element('bgsound',{ 11196 id: 'sound_'+options.track+'_'+options.id, 11197 src: options.url, loop: 1, autostart: true 11198 }) : Sound.template.evaluate(options)); 11199 } 11200}; 11201 11202if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){ 11203 if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 })) 11204 Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>'); 11205 else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('Windows Media') != -1 })) 11206 Sound.template = new Template('<object id="sound_#{track}_#{id}" type="application/x-mplayer2" data="#{url}"></object>'); 11207 else if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('RealPlayer') != -1 })) 11208 Sound.template = new Template('<embed type="audio/x-pn-realaudio-plugin" style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'); 11209 else 11210 Sound.play = function(){}; 11211}
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.