[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* Prototype JavaScript framework, version 1.5.0 2 * (c) 2005-2007 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://prototype.conio.net/ 6 * 7 /*--------------------------------------------------------------------------*/ 8 9 var Prototype = { 10 Version: '1.5.0', 11 BrowserFeatures: { 12 XPath: !!document.evaluate 13 }, 14 15 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 16 emptyFunction: function() {}, 17 K: function(x) { return x } 18 } 19 20 var Class = { 21 create: function() { 22 return function() { 23 this.initialize.apply(this, arguments); 24 } 25 } 26 } 27 28 var Abstract = new Object(); 29 30 Object.extend = function(destination, source) { 31 for (var property in source) { 32 destination[property] = source[property]; 33 } 34 return destination; 35 } 36 37 Object.extend(Object, { 38 inspect: function(object) { 39 try { 40 if (object === undefined) return 'undefined'; 41 if (object === null) return 'null'; 42 return object.inspect ? object.inspect() : object.toString(); 43 } catch (e) { 44 if (e instanceof RangeError) return '...'; 45 throw e; 46 } 47 }, 48 49 keys: function(object) { 50 var keys = []; 51 for (var property in object) 52 keys.push(property); 53 return keys; 54 }, 55 56 values: function(object) { 57 var values = []; 58 for (var property in object) 59 values.push(object[property]); 60 return values; 61 }, 62 63 clone: function(object) { 64 return Object.extend({}, object); 65 } 66 }); 67 68 Function.prototype.bind = function() { 69 var __method = this, args = $A(arguments), object = args.shift(); 70 return function() { 71 return __method.apply(object, args.concat($A(arguments))); 72 } 73 } 74 75 Function.prototype.bindAsEventListener = function(object) { 76 var __method = this, args = $A(arguments), object = args.shift(); 77 return function(event) { 78 return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); 79 } 80 } 81 82 Object.extend(Number.prototype, { 83 toColorPart: function() { 84 var digits = this.toString(16); 85 if (this < 16) return '0' + digits; 86 return digits; 87 }, 88 89 succ: function() { 90 return this + 1; 91 }, 92 93 times: function(iterator) { 94 $R(0, this, true).each(iterator); 95 return this; 96 } 97 }); 98 99 var Try = { 100 these: function() { 101 var returnValue; 102 103 for (var i = 0, length = arguments.length; i < length; i++) { 104 var lambda = arguments[i]; 105 try { 106 returnValue = lambda(); 107 break; 108 } catch (e) {} 109 } 110 111 return returnValue; 112 } 113 } 114 115 /*--------------------------------------------------------------------------*/ 116 117 var PeriodicalExecuter = Class.create(); 118 PeriodicalExecuter.prototype = { 119 initialize: function(callback, frequency) { 120 this.callback = callback; 121 this.frequency = frequency; 122 this.currentlyExecuting = false; 123 124 this.registerCallback(); 125 }, 126 127 registerCallback: function() { 128 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 129 }, 130 131 stop: function() { 132 if (!this.timer) return; 133 clearInterval(this.timer); 134 this.timer = null; 135 }, 136 137 onTimerEvent: function() { 138 if (!this.currentlyExecuting) { 139 try { 140 this.currentlyExecuting = true; 141 this.callback(this); 142 } finally { 143 this.currentlyExecuting = false; 144 } 145 } 146 } 147 } 148 String.interpret = function(value){ 149 return value == null ? '' : String(value); 150 } 151 152 Object.extend(String.prototype, { 153 gsub: function(pattern, replacement) { 154 var result = '', source = this, match; 155 replacement = arguments.callee.prepareReplacement(replacement); 156 157 while (source.length > 0) { 158 if (match = source.match(pattern)) { 159 result += source.slice(0, match.index); 160 result += String.interpret(replacement(match)); 161 source = source.slice(match.index + match[0].length); 162 } else { 163 result += source, source = ''; 164 } 165 } 166 return result; 167 }, 168 169 sub: function(pattern, replacement, count) { 170 replacement = this.gsub.prepareReplacement(replacement); 171 count = count === undefined ? 1 : count; 172 173 return this.gsub(pattern, function(match) { 174 if (--count < 0) return match[0]; 175 return replacement(match); 176 }); 177 }, 178 179 scan: function(pattern, iterator) { 180 this.gsub(pattern, iterator); 181 return this; 182 }, 183 184 truncate: function(length, truncation) { 185 length = length || 30; 186 truncation = truncation === undefined ? '...' : truncation; 187 return this.length > length ? 188 this.slice(0, length - truncation.length) + truncation : this; 189 }, 190 191 strip: function() { 192 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 193 }, 194 195 stripTags: function() { 196 return this.replace(/<\/?[^>]+>/gi, ''); 197 }, 198 199 stripScripts: function() { 200 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 201 }, 202 203 extractScripts: function() { 204 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 205 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 206 return (this.match(matchAll) || []).map(function(scriptTag) { 207 return (scriptTag.match(matchOne) || ['', ''])[1]; 208 }); 209 }, 210 211 evalScripts: function() { 212 return this.extractScripts().map(function(script) { return eval(script) }); 213 }, 214 215 escapeHTML: function() { 216 var div = document.createElement('div'); 217 var text = document.createTextNode(this); 218 div.appendChild(text); 219 return div.innerHTML; 220 }, 221 222 unescapeHTML: function() { 223 var div = document.createElement('div'); 224 div.innerHTML = this.stripTags(); 225 return div.childNodes[0] ? (div.childNodes.length > 1 ? 226 $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : 227 div.childNodes[0].nodeValue) : ''; 228 }, 229 230 toQueryParams: function(separator) { 231 var match = this.strip().match(/([^?#]*)(#.*)?$/); 232 if (!match) return {}; 233 234 return match[1].split(separator || '&').inject({}, function(hash, pair) { 235 if ((pair = pair.split('='))[0]) { 236 var name = decodeURIComponent(pair[0]); 237 var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; 238 239 if (hash[name] !== undefined) { 240 if (hash[name].constructor != Array) 241 hash[name] = [hash[name]]; 242 if (value) hash[name].push(value); 243 } 244 else hash[name] = value; 245 } 246 return hash; 247 }); 248 }, 249 250 toArray: function() { 251 return this.split(''); 252 }, 253 254 succ: function() { 255 return this.slice(0, this.length - 1) + 256 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 257 }, 258 259 camelize: function() { 260 var parts = this.split('-'), len = parts.length; 261 if (len == 1) return parts[0]; 262 263 var camelized = this.charAt(0) == '-' 264 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 265 : parts[0]; 266 267 for (var i = 1; i < len; i++) 268 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 269 270 return camelized; 271 }, 272 273 capitalize: function(){ 274 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 275 }, 276 277 underscore: function() { 278 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); 279 }, 280 281 dasherize: function() { 282 return this.gsub(/_/,'-'); 283 }, 284 285 inspect: function(useDoubleQuotes) { 286 var escapedString = this.replace(/\\/g, '\\\\'); 287 if (useDoubleQuotes) 288 return '"' + escapedString.replace(/"/g, '\\"') + '"'; 289 else 290 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 291 } 292 }); 293 294 String.prototype.gsub.prepareReplacement = function(replacement) { 295 if (typeof replacement == 'function') return replacement; 296 var template = new Template(replacement); 297 return function(match) { return template.evaluate(match) }; 298 } 299 300 String.prototype.parseQuery = String.prototype.toQueryParams; 301 302 var Template = Class.create(); 303 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 304 Template.prototype = { 305 initialize: function(template, pattern) { 306 this.template = template.toString(); 307 this.pattern = pattern || Template.Pattern; 308 }, 309 310 evaluate: function(object) { 311 return this.template.gsub(this.pattern, function(match) { 312 var before = match[1]; 313 if (before == '\\') return match[2]; 314 return before + String.interpret(object[match[3]]); 315 }); 316 } 317 } 318 319 var $break = new Object(); 320 var $continue = new Object(); 321 322 var Enumerable = { 323 each: function(iterator) { 324 var index = 0; 325 try { 326 this._each(function(value) { 327 try { 328 iterator(value, index++); 329 } catch (e) { 330 if (e != $continue) throw e; 331 } 332 }); 333 } catch (e) { 334 if (e != $break) throw e; 335 } 336 return this; 337 }, 338 339 eachSlice: function(number, iterator) { 340 var index = -number, slices = [], array = this.toArray(); 341 while ((index += number) < array.length) 342 slices.push(array.slice(index, index+number)); 343 return slices.map(iterator); 344 }, 345 346 all: function(iterator) { 347 var result = true; 348 this.each(function(value, index) { 349 result = result && !!(iterator || Prototype.K)(value, index); 350 if (!result) throw $break; 351 }); 352 return result; 353 }, 354 355 any: function(iterator) { 356 var result = false; 357 this.each(function(value, index) { 358 if (result = !!(iterator || Prototype.K)(value, index)) 359 throw $break; 360 }); 361 return result; 362 }, 363 364 collect: function(iterator) { 365 var results = []; 366 this.each(function(value, index) { 367 results.push((iterator || Prototype.K)(value, index)); 368 }); 369 return results; 370 }, 371 372 detect: function(iterator) { 373 var result; 374 this.each(function(value, index) { 375 if (iterator(value, index)) { 376 result = value; 377 throw $break; 378 } 379 }); 380 return result; 381 }, 382 383 findAll: function(iterator) { 384 var results = []; 385 this.each(function(value, index) { 386 if (iterator(value, index)) 387 results.push(value); 388 }); 389 return results; 390 }, 391 392 grep: function(pattern, iterator) { 393 var results = []; 394 this.each(function(value, index) { 395 var stringValue = value.toString(); 396 if (stringValue.match(pattern)) 397 results.push((iterator || Prototype.K)(value, index)); 398 }) 399 return results; 400 }, 401 402 include: function(object) { 403 var found = false; 404 this.each(function(value) { 405 if (value == object) { 406 found = true; 407 throw $break; 408 } 409 }); 410 return found; 411 }, 412 413 inGroupsOf: function(number, fillWith) { 414 fillWith = fillWith === undefined ? null : fillWith; 415 return this.eachSlice(number, function(slice) { 416 while(slice.length < number) slice.push(fillWith); 417 return slice; 418 }); 419 }, 420 421 inject: function(memo, iterator) { 422 this.each(function(value, index) { 423 memo = iterator(memo, value, index); 424 }); 425 return memo; 426 }, 427 428 invoke: function(method) { 429 var args = $A(arguments).slice(1); 430 return this.map(function(value) { 431 return value[method].apply(value, args); 432 }); 433 }, 434 435 max: function(iterator) { 436 var result; 437 this.each(function(value, index) { 438 value = (iterator || Prototype.K)(value, index); 439 if (result == undefined || value >= result) 440 result = value; 441 }); 442 return result; 443 }, 444 445 min: function(iterator) { 446 var result; 447 this.each(function(value, index) { 448 value = (iterator || Prototype.K)(value, index); 449 if (result == undefined || value < result) 450 result = value; 451 }); 452 return result; 453 }, 454 455 partition: function(iterator) { 456 var trues = [], falses = []; 457 this.each(function(value, index) { 458 ((iterator || Prototype.K)(value, index) ? 459 trues : falses).push(value); 460 }); 461 return [trues, falses]; 462 }, 463 464 pluck: function(property) { 465 var results = []; 466 this.each(function(value, index) { 467 results.push(value[property]); 468 }); 469 return results; 470 }, 471 472 reject: function(iterator) { 473 var results = []; 474 this.each(function(value, index) { 475 if (!iterator(value, index)) 476 results.push(value); 477 }); 478 return results; 479 }, 480 481 sortBy: function(iterator) { 482 return this.map(function(value, index) { 483 return {value: value, criteria: iterator(value, index)}; 484 }).sort(function(left, right) { 485 var a = left.criteria, b = right.criteria; 486 return a < b ? -1 : a > b ? 1 : 0; 487 }).pluck('value'); 488 }, 489 490 toArray: function() { 491 return this.map(); 492 }, 493 494 zip: function() { 495 var iterator = Prototype.K, args = $A(arguments); 496 if (typeof args.last() == 'function') 497 iterator = args.pop(); 498 499 var collections = [this].concat(args).map($A); 500 return this.map(function(value, index) { 501 return iterator(collections.pluck(index)); 502 }); 503 }, 504 505 size: function() { 506 return this.toArray().length; 507 }, 508 509 inspect: function() { 510 return '#<Enumerable:' + this.toArray().inspect() + '>'; 511 } 512 } 513 514 Object.extend(Enumerable, { 515 map: Enumerable.collect, 516 find: Enumerable.detect, 517 select: Enumerable.findAll, 518 member: Enumerable.include, 519 entries: Enumerable.toArray 520 }); 521 var $A = Array.from = function(iterable) { 522 if (!iterable) return []; 523 if (iterable.toArray) { 524 return iterable.toArray(); 525 } else { 526 var results = []; 527 for (var i = 0, length = iterable.length; i < length; i++) 528 results.push(iterable[i]); 529 return results; 530 } 531 } 532 533 Object.extend(Array.prototype, Enumerable); 534 535 if (!Array.prototype._reverse) 536 Array.prototype._reverse = Array.prototype.reverse; 537 538 Object.extend(Array.prototype, { 539 _each: function(iterator) { 540 for (var i = 0, length = this.length; i < length; i++) 541 iterator(this[i]); 542 }, 543 544 clear: function() { 545 this.length = 0; 546 return this; 547 }, 548 549 first: function() { 550 return this[0]; 551 }, 552 553 last: function() { 554 return this[this.length - 1]; 555 }, 556 557 compact: function() { 558 return this.select(function(value) { 559 return value != null; 560 }); 561 }, 562 563 flatten: function() { 564 return this.inject([], function(array, value) { 565 return array.concat(value && value.constructor == Array ? 566 value.flatten() : [value]); 567 }); 568 }, 569 570 without: function() { 571 var values = $A(arguments); 572 return this.select(function(value) { 573 return !values.include(value); 574 }); 575 }, 576 577 indexOf: function(object) { 578 for (var i = 0, length = this.length; i < length; i++) 579 if (this[i] == object) return i; 580 return -1; 581 }, 582 583 reverse: function(inline) { 584 return (inline !== false ? this : this.toArray())._reverse(); 585 }, 586 587 reduce: function() { 588 return this.length > 1 ? this : this[0]; 589 }, 590 591 uniq: function() { 592 return this.inject([], function(array, value) { 593 return array.include(value) ? array : array.concat([value]); 594 }); 595 }, 596 597 clone: function() { 598 return [].concat(this); 599 }, 600 601 size: function() { 602 return this.length; 603 }, 604 605 inspect: function() { 606 return '[' + this.map(Object.inspect).join(', ') + ']'; 607 } 608 }); 609 610 Array.prototype.toArray = Array.prototype.clone; 611 612 function $w(string){ 613 string = string.strip(); 614 return string ? string.split(/\s+/) : []; 615 } 616 617 if(window.opera){ 618 Array.prototype.concat = function(){ 619 var array = []; 620 for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); 621 for(var i = 0, length = arguments.length; i < length; i++) { 622 if(arguments[i].constructor == Array) { 623 for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 624 array.push(arguments[i][j]); 625 } else { 626 array.push(arguments[i]); 627 } 628 } 629 return array; 630 } 631 } 632 var Hash = function(obj) { 633 Object.extend(this, obj || {}); 634 }; 635 636 Object.extend(Hash, { 637 toQueryString: function(obj) { 638 var parts = []; 639 640 this.prototype._each.call(obj, function(pair) { 641 if (!pair.key) return; 642 643 if (pair.value && pair.value.constructor == Array) { 644 var values = pair.value.compact(); 645 if (values.length < 2) pair.value = values.reduce(); 646 else { 647 key = encodeURIComponent(pair.key); 648 values.each(function(value) { 649 value = value != undefined ? encodeURIComponent(value) : ''; 650 parts.push(key + '=' + encodeURIComponent(value)); 651 }); 652 return; 653 } 654 } 655 if (pair.value == undefined) pair[1] = ''; 656 parts.push(pair.map(encodeURIComponent).join('=')); 657 }); 658 659 return parts.join('&'); 660 } 661 }); 662 663 Object.extend(Hash.prototype, Enumerable); 664 Object.extend(Hash.prototype, { 665 _each: function(iterator) { 666 for (var key in this) { 667 var value = this[key]; 668 if (value && value == Hash.prototype[key]) continue; 669 670 var pair = [key, value]; 671 pair.key = key; 672 pair.value = value; 673 iterator(pair); 674 } 675 }, 676 677 keys: function() { 678 return this.pluck('key'); 679 }, 680 681 values: function() { 682 return this.pluck('value'); 683 }, 684 685 merge: function(hash) { 686 return $H(hash).inject(this, function(mergedHash, pair) { 687 mergedHash[pair.key] = pair.value; 688 return mergedHash; 689 }); 690 }, 691 692 remove: function() { 693 var result; 694 for(var i = 0, length = arguments.length; i < length; i++) { 695 var value = this[arguments[i]]; 696 if (value !== undefined){ 697 if (result === undefined) result = value; 698 else { 699 if (result.constructor != Array) result = [result]; 700 result.push(value) 701 } 702 } 703 delete this[arguments[i]]; 704 } 705 return result; 706 }, 707 708 toQueryString: function() { 709 return Hash.toQueryString(this); 710 }, 711 712 inspect: function() { 713 return '#<Hash:{' + this.map(function(pair) { 714 return pair.map(Object.inspect).join(': '); 715 }).join(', ') + '}>'; 716 } 717 }); 718 719 function $H(object) { 720 if (object && object.constructor == Hash) return object; 721 return new Hash(object); 722 }; 723 ObjectRange = Class.create(); 724 Object.extend(ObjectRange.prototype, Enumerable); 725 Object.extend(ObjectRange.prototype, { 726 initialize: function(start, end, exclusive) { 727 this.start = start; 728 this.end = end; 729 this.exclusive = exclusive; 730 }, 731 732 _each: function(iterator) { 733 var value = this.start; 734 while (this.include(value)) { 735 iterator(value); 736 value = value.succ(); 737 } 738 }, 739 740 include: function(value) { 741 if (value < this.start) 742 return false; 743 if (this.exclusive) 744 return value < this.end; 745 return value <= this.end; 746 } 747 }); 748 749 var $R = function(start, end, exclusive) { 750 return new ObjectRange(start, end, exclusive); 751 } 752 753 var Ajax = { 754 getTransport: function() { 755 return Try.these( 756 function() {return new XMLHttpRequest()}, 757 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 758 function() {return new ActiveXObject('Microsoft.XMLHTTP')} 759 ) || false; 760 }, 761 762 activeRequestCount: 0 763 } 764 765 Ajax.Responders = { 766 responders: [], 767 768 _each: function(iterator) { 769 this.responders._each(iterator); 770 }, 771 772 register: function(responder) { 773 if (!this.include(responder)) 774 this.responders.push(responder); 775 }, 776 777 unregister: function(responder) { 778 this.responders = this.responders.without(responder); 779 }, 780 781 dispatch: function(callback, request, transport, json) { 782 this.each(function(responder) { 783 if (typeof responder[callback] == 'function') { 784 try { 785 responder[callback].apply(responder, [request, transport, json]); 786 } catch (e) {} 787 } 788 }); 789 } 790 }; 791 792 Object.extend(Ajax.Responders, Enumerable); 793 794 Ajax.Responders.register({ 795 onCreate: function() { 796 Ajax.activeRequestCount++; 797 }, 798 onComplete: function() { 799 Ajax.activeRequestCount--; 800 } 801 }); 802 803 Ajax.Base = function() {}; 804 Ajax.Base.prototype = { 805 setOptions: function(options) { 806 this.options = { 807 method: 'post', 808 asynchronous: true, 809 contentType: 'application/x-www-form-urlencoded', 810 encoding: 'UTF-8', 811 parameters: '' 812 } 813 Object.extend(this.options, options || {}); 814 815 this.options.method = this.options.method.toLowerCase(); 816 if (typeof this.options.parameters == 'string') 817 this.options.parameters = this.options.parameters.toQueryParams(); 818 } 819 } 820 821 Ajax.Request = Class.create(); 822 Ajax.Request.Events = 823 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 824 825 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 826 _complete: false, 827 828 initialize: function(url, options) { 829 this.transport = Ajax.getTransport(); 830 this.setOptions(options); 831 this.request(url); 832 }, 833 834 request: function(url) { 835 this.url = url; 836 this.method = this.options.method; 837 var params = this.options.parameters; 838 839 if (!['get', 'post'].include(this.method)) { 840 // simulate other verbs over post 841 params['_method'] = this.method; 842 this.method = 'post'; 843 } 844 845 params = Hash.toQueryString(params); 846 if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' 847 848 // when GET, append parameters to URL 849 if (this.method == 'get' && params) 850 this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; 851 852 try { 853 Ajax.Responders.dispatch('onCreate', this, this.transport); 854 855 this.transport.open(this.method.toUpperCase(), this.url, 856 this.options.asynchronous); 857 858 if (this.options.asynchronous) 859 setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); 860 861 this.transport.onreadystatechange = this.onStateChange.bind(this); 862 this.setRequestHeaders(); 863 864 var body = this.method == 'post' ? (this.options.postBody || params) : null; 865 866 this.transport.send(body); 867 868 /* Force Firefox to handle ready state 4 for synchronous requests */ 869 if (!this.options.asynchronous && this.transport.overrideMimeType) 870 this.onStateChange(); 871 872 } 873 catch (e) { 874 this.dispatchException(e); 875 } 876 }, 877 878 onStateChange: function() { 879 var readyState = this.transport.readyState; 880 if (readyState > 1 && !((readyState == 4) && this._complete)) 881 this.respondToReadyState(this.transport.readyState); 882 }, 883 884 setRequestHeaders: function() { 885 var headers = { 886 'X-Requested-With': 'XMLHttpRequest', 887 'X-Prototype-Version': Prototype.Version, 888 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 889 }; 890 891 if (this.method == 'post') { 892 headers['Content-type'] = this.options.contentType + 893 (this.options.encoding ? '; charset=' + this.options.encoding : ''); 894 895 /* Force "Connection: close" for older Mozilla browsers to work 896 * around a bug where XMLHttpRequest sends an incorrect 897 * Content-length header. See Mozilla Bugzilla #246651. 898 */ 899 if (this.transport.overrideMimeType && 900 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 901 headers['Connection'] = 'close'; 902 } 903 904 // user-defined headers 905 if (typeof this.options.requestHeaders == 'object') { 906 var extras = this.options.requestHeaders; 907 908 if (typeof extras.push == 'function') 909 for (var i = 0, length = extras.length; i < length; i += 2) 910 headers[extras[i]] = extras[i+1]; 911 else 912 $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 913 } 914 915 for (var name in headers) 916 this.transport.setRequestHeader(name, headers[name]); 917 }, 918 919 success: function() { 920 return !this.transport.status 921 || (this.transport.status >= 200 && this.transport.status < 300); 922 }, 923 924 respondToReadyState: function(readyState) { 925 var state = Ajax.Request.Events[readyState]; 926 var transport = this.transport, json = this.evalJSON(); 927 928 if (state == 'Complete') { 929 try { 930 this._complete = true; 931 (this.options['on' + this.transport.status] 932 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 933 || Prototype.emptyFunction)(transport, json); 934 } catch (e) { 935 this.dispatchException(e); 936 } 937 938 if ((this.getHeader('Content-type') || 'text/javascript').strip(). 939 match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) 940 this.evalResponse(); 941 } 942 943 try { 944 (this.options['on' + state] || Prototype.emptyFunction)(transport, json); 945 Ajax.Responders.dispatch('on' + state, this, transport, json); 946 } catch (e) { 947 this.dispatchException(e); 948 } 949 950 if (state == 'Complete') { 951 // avoid memory leak in MSIE: clean up 952 this.transport.onreadystatechange = Prototype.emptyFunction; 953 } 954 }, 955 956 getHeader: function(name) { 957 try { 958 return this.transport.getResponseHeader(name); 959 } catch (e) { return null } 960 }, 961 962 evalJSON: function() { 963 try { 964 var json = this.getHeader('X-JSON'); 965 return json ? eval('(' + json + ')') : null; 966 } catch (e) { return null } 967 }, 968 969 evalResponse: function() { 970 try { 971 return eval(this.transport.responseText); 972 } catch (e) { 973 this.dispatchException(e); 974 } 975 }, 976 977 dispatchException: function(exception) { 978 (this.options.onException || Prototype.emptyFunction)(this, exception); 979 Ajax.Responders.dispatch('onException', this, exception); 980 } 981 }); 982 983 Ajax.Updater = Class.create(); 984 985 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 986 initialize: function(container, url, options) { 987 this.container = { 988 success: (container.success || container), 989 failure: (container.failure || (container.success ? null : container)) 990 } 991 992 this.transport = Ajax.getTransport(); 993 this.setOptions(options); 994 995 var onComplete = this.options.onComplete || Prototype.emptyFunction; 996 this.options.onComplete = (function(transport, param) { 997 this.updateContent(); 998 onComplete(transport, param); 999 }).bind(this); 1000 1001 this.request(url); 1002 }, 1003 1004 updateContent: function() { 1005 var receiver = this.container[this.success() ? 'success' : 'failure']; 1006 var response = this.transport.responseText; 1007 1008 if (!this.options.evalScripts) response = response.stripScripts(); 1009 1010 if (receiver = $(receiver)) { 1011 if (this.options.insertion) 1012 new this.options.insertion(receiver, response); 1013 else 1014 receiver.update(response); 1015 } 1016 1017 if (this.success()) { 1018 if (this.onComplete) 1019 setTimeout(this.onComplete.bind(this), 10); 1020 } 1021 } 1022 }); 1023 1024 Ajax.PeriodicalUpdater = Class.create(); 1025 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { 1026 initialize: function(container, url, options) { 1027 this.setOptions(options); 1028 this.onComplete = this.options.onComplete; 1029 1030 this.frequency = (this.options.frequency || 2); 1031 this.decay = (this.options.decay || 1); 1032 1033 this.updater = {}; 1034 this.container = container; 1035 this.url = url; 1036 1037 this.start(); 1038 }, 1039 1040 start: function() { 1041 this.options.onComplete = this.updateComplete.bind(this); 1042 this.onTimerEvent(); 1043 }, 1044 1045 stop: function() { 1046 this.updater.options.onComplete = undefined; 1047 clearTimeout(this.timer); 1048 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 1049 }, 1050 1051 updateComplete: function(request) { 1052 if (this.options.decay) { 1053 this.decay = (request.responseText == this.lastText ? 1054 this.decay * this.options.decay : 1); 1055 1056 this.lastText = request.responseText; 1057 } 1058 this.timer = setTimeout(this.onTimerEvent.bind(this), 1059 this.decay * this.frequency * 1000); 1060 }, 1061 1062 onTimerEvent: function() { 1063 this.updater = new Ajax.Updater(this.container, this.url, this.options); 1064 } 1065 }); 1066 function $(element) { 1067 if (arguments.length > 1) { 1068 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 1069 elements.push($(arguments[i])); 1070 return elements; 1071 } 1072 if (typeof element == 'string') 1073 element = document.getElementById(element); 1074 return Element.extend(element); 1075 } 1076 1077 if (Prototype.BrowserFeatures.XPath) { 1078 document._getElementsByXPath = function(expression, parentElement) { 1079 var results = []; 1080 var query = document.evaluate(expression, $(parentElement) || document, 1081 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 1082 for (var i = 0, length = query.snapshotLength; i < length; i++) 1083 results.push(query.snapshotItem(i)); 1084 return results; 1085 }; 1086 } 1087 1088 document.getElementsByClassName = function(className, parentElement) { 1089 if (Prototype.BrowserFeatures.XPath) { 1090 var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; 1091 return document._getElementsByXPath(q, parentElement); 1092 } else { 1093 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 1094 var elements = [], child; 1095 for (var i = 0, length = children.length; i < length; i++) { 1096 child = children[i]; 1097 if (Element.hasClassName(child, className)) 1098 elements.push(Element.extend(child)); 1099 } 1100 return elements; 1101 } 1102 }; 1103 1104 /*--------------------------------------------------------------------------*/ 1105 1106 if (!window.Element) 1107 var Element = new Object(); 1108 1109 Element.extend = function(element) { 1110 if (!element || _nativeExtensions || element.nodeType == 3) return element; 1111 1112 if (!element._extended && element.tagName && element != window) { 1113 var methods = Object.clone(Element.Methods), cache = Element.extend.cache; 1114 1115 if (element.tagName == 'FORM') 1116 Object.extend(methods, Form.Methods); 1117 if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) 1118 Object.extend(methods, Form.Element.Methods); 1119 1120 Object.extend(methods, Element.Methods.Simulated); 1121 1122 for (var property in methods) { 1123 var value = methods[property]; 1124 if (typeof value == 'function' && !(property in element)) 1125 element[property] = cache.findOrStore(value); 1126 } 1127 } 1128 1129 element._extended = true; 1130 return element; 1131 }; 1132 1133 Element.extend.cache = { 1134 findOrStore: function(value) { 1135 return this[value] = this[value] || function() { 1136 return value.apply(null, [this].concat($A(arguments))); 1137 } 1138 } 1139 }; 1140 1141 Element.Methods = { 1142 visible: function(element) { 1143 return $(element).style.display != 'none'; 1144 }, 1145 1146 toggle: function(element) { 1147 element = $(element); 1148 Element[Element.visible(element) ? 'hide' : 'show'](element); 1149 return element; 1150 }, 1151 1152 hide: function(element) { 1153 $(element).style.display = 'none'; 1154 return element; 1155 }, 1156 1157 show: function(element) { 1158 $(element).style.display = ''; 1159 return element; 1160 }, 1161 1162 remove: function(element) { 1163 element = $(element); 1164 element.parentNode.removeChild(element); 1165 return element; 1166 }, 1167 1168 update: function(element, html) { 1169 html = typeof html == 'undefined' ? '' : html.toString(); 1170 $(element).innerHTML = html.stripScripts(); 1171 setTimeout(function() {html.evalScripts()}, 10); 1172 return element; 1173 }, 1174 1175 replace: function(element, html) { 1176 element = $(element); 1177 html = typeof html == 'undefined' ? '' : html.toString(); 1178 if (element.outerHTML) { 1179 element.outerHTML = html.stripScripts(); 1180 } else { 1181 var range = element.ownerDocument.createRange(); 1182 range.selectNodeContents(element); 1183 element.parentNode.replaceChild( 1184 range.createContextualFragment(html.stripScripts()), element); 1185 } 1186 setTimeout(function() {html.evalScripts()}, 10); 1187 return element; 1188 }, 1189 1190 inspect: function(element) { 1191 element = $(element); 1192 var result = '<' + element.tagName.toLowerCase(); 1193 $H({'id': 'id', 'className': 'class'}).each(function(pair) { 1194 var property = pair.first(), attribute = pair.last(); 1195 var value = (element[property] || '').toString(); 1196 if (value) result += ' ' + attribute + '=' + value.inspect(true); 1197 }); 1198 return result + '>'; 1199 }, 1200 1201 recursivelyCollect: function(element, property) { 1202 element = $(element); 1203 var elements = []; 1204 while (element = element[property]) 1205 if (element.nodeType == 1) 1206 elements.push(Element.extend(element)); 1207 return elements; 1208 }, 1209 1210 ancestors: function(element) { 1211 return $(element).recursivelyCollect('parentNode'); 1212 }, 1213 1214 descendants: function(element) { 1215 return $A($(element).getElementsByTagName('*')); 1216 }, 1217 1218 immediateDescendants: function(element) { 1219 if (!(element = $(element).firstChild)) return []; 1220 while (element && element.nodeType != 1) element = element.nextSibling; 1221 if (element) return [element].concat($(element).nextSiblings()); 1222 return []; 1223 }, 1224 1225 previousSiblings: function(element) { 1226 return $(element).recursivelyCollect('previousSibling'); 1227 }, 1228 1229 nextSiblings: function(element) { 1230 return $(element).recursivelyCollect('nextSibling'); 1231 }, 1232 1233 siblings: function(element) { 1234 element = $(element); 1235 return element.previousSiblings().reverse().concat(element.nextSiblings()); 1236 }, 1237 1238 match: function(element, selector) { 1239 if (typeof selector == 'string') 1240 selector = new Selector(selector); 1241 return selector.match($(element)); 1242 }, 1243 1244 up: function(element, expression, index) { 1245 return Selector.findElement($(element).ancestors(), expression, index); 1246 }, 1247 1248 down: function(element, expression, index) { 1249 return Selector.findElement($(element).descendants(), expression, index); 1250 }, 1251 1252 previous: function(element, expression, index) { 1253 return Selector.findElement($(element).previousSiblings(), expression, index); 1254 }, 1255 1256 next: function(element, expression, index) { 1257 return Selector.findElement($(element).nextSiblings(), expression, index); 1258 }, 1259 1260 getElementsBySelector: function() { 1261 var args = $A(arguments), element = $(args.shift()); 1262 return Selector.findChildElements(element, args); 1263 }, 1264 1265 getElementsByClassName: function(element, className) { 1266 return document.getElementsByClassName(className, element); 1267 }, 1268 1269 readAttribute: function(element, name) { 1270 element = $(element); 1271 if (document.all && !window.opera) { 1272 var t = Element._attributeTranslations; 1273 if (t.values[name]) return t.values[name](element, name); 1274 if (t.names[name]) name = t.names[name]; 1275 var attribute = element.attributes[name]; 1276 if(attribute) return attribute.nodeValue; 1277 } 1278 return element.getAttribute(name); 1279 }, 1280 1281 getHeight: function(element) { 1282 return $(element).getDimensions().height; 1283 }, 1284 1285 getWidth: function(element) { 1286 return $(element).getDimensions().width; 1287 }, 1288 1289 classNames: function(element) { 1290 return new Element.ClassNames(element); 1291 }, 1292 1293 hasClassName: function(element, className) { 1294 if (!(element = $(element))) return; 1295 var elementClassName = element.className; 1296 if (elementClassName.length == 0) return false; 1297 if (elementClassName == className || 1298 elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 1299 return true; 1300 return false; 1301 }, 1302 1303 addClassName: function(element, className) { 1304 if (!(element = $(element))) return; 1305 Element.classNames(element).add(className); 1306 return element; 1307 }, 1308 1309 removeClassName: function(element, className) { 1310 if (!(element = $(element))) return; 1311 Element.classNames(element).remove(className); 1312 return element; 1313 }, 1314 1315 toggleClassName: function(element, className) { 1316 if (!(element = $(element))) return; 1317 Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); 1318 return element; 1319 }, 1320 1321 observe: function() { 1322 Event.observe.apply(Event, arguments); 1323 return $A(arguments).first(); 1324 }, 1325 1326 stopObserving: function() { 1327 Event.stopObserving.apply(Event, arguments); 1328 return $A(arguments).first(); 1329 }, 1330 1331 // removes whitespace-only text node children 1332 cleanWhitespace: function(element) { 1333 element = $(element); 1334 var node = element.firstChild; 1335 while (node) { 1336 var nextNode = node.nextSibling; 1337 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 1338 element.removeChild(node); 1339 node = nextNode; 1340 } 1341 return element; 1342 }, 1343 1344 empty: function(element) { 1345 return $(element).innerHTML.match(/^\s*$/); 1346 }, 1347 1348 descendantOf: function(element, ancestor) { 1349 element = $(element), ancestor = $(ancestor); 1350 while (element = element.parentNode) 1351 if (element == ancestor) return true; 1352 return false; 1353 }, 1354 1355 scrollTo: function(element) { 1356 element = $(element); 1357 var pos = Position.cumulativeOffset(element); 1358 window.scrollTo(pos[0], pos[1]); 1359 return element; 1360 }, 1361 1362 getStyle: function(element, style) { 1363 element = $(element); 1364 if (['float','cssFloat'].include(style)) 1365 style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); 1366 style = style.camelize(); 1367 var value = element.style[style]; 1368 if (!value) { 1369 if (document.defaultView && document.defaultView.getComputedStyle) { 1370 var css = document.defaultView.getComputedStyle(element, null); 1371 value = css ? css[style] : null; 1372 } else if (element.currentStyle) { 1373 value = element.currentStyle[style]; 1374 } 1375 } 1376 1377 if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) 1378 value = element['offset'+style.capitalize()] + 'px'; 1379 1380 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) 1381 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; 1382 if(style == 'opacity') { 1383 if(value) return parseFloat(value); 1384 if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 1385 if(value[1]) return parseFloat(value[1]) / 100; 1386 return 1.0; 1387 } 1388 return value == 'auto' ? null : value; 1389 }, 1390 1391 setStyle: function(element, style) { 1392 element = $(element); 1393 for (var name in style) { 1394 var value = style[name]; 1395 if(name == 'opacity') { 1396 if (value == 1) { 1397 value = (/Gecko/.test(navigator.userAgent) && 1398 !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; 1399 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1400 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 1401 } else if(value === '') { 1402 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1403 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 1404 } else { 1405 if(value < 0.00001) value = 0; 1406 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1407 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + 1408 'alpha(opacity='+value*100+')'; 1409 } 1410 } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; 1411 element.style[name.camelize()] = value; 1412 } 1413 return element; 1414 }, 1415 1416 getDimensions: function(element) { 1417 element = $(element); 1418 var display = $(element).getStyle('display'); 1419 if (display != 'none' && display != null) // Safari bug 1420 return {width: element.offsetWidth, height: element.offsetHeight}; 1421 1422 // All *Width and *Height properties give 0 on elements with display none, 1423 // so enable the element temporarily 1424 var els = element.style; 1425 var originalVisibility = els.visibility; 1426 var originalPosition = els.position; 1427 var originalDisplay = els.display; 1428 els.visibility = 'hidden'; 1429 els.position = 'absolute'; 1430 els.display = 'block'; 1431 var originalWidth = element.clientWidth; 1432 var originalHeight = element.clientHeight; 1433 els.display = originalDisplay; 1434 els.position = originalPosition; 1435 els.visibility = originalVisibility; 1436 return {width: originalWidth, height: originalHeight}; 1437 }, 1438 1439 makePositioned: function(element) { 1440 element = $(element); 1441 var pos = Element.getStyle(element, 'position'); 1442 if (pos == 'static' || !pos) { 1443 element._madePositioned = true; 1444 element.style.position = 'relative'; 1445 // Opera returns the offset relative to the positioning context, when an 1446 // element is position relative but top and left have not been defined 1447 if (window.opera) { 1448 element.style.top = 0; 1449 element.style.left = 0; 1450 } 1451 } 1452 return element; 1453 }, 1454 1455 undoPositioned: function(element) { 1456 element = $(element); 1457 if (element._madePositioned) { 1458 element._madePositioned = undefined; 1459 element.style.position = 1460 element.style.top = 1461 element.style.left = 1462 element.style.bottom = 1463 element.style.right = ''; 1464 } 1465 return element; 1466 }, 1467 1468 makeClipping: function(element) { 1469 element = $(element); 1470 if (element._overflow) return element; 1471 element._overflow = element.style.overflow || 'auto'; 1472 if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') 1473 element.style.overflow = 'hidden'; 1474 return element; 1475 }, 1476 1477 undoClipping: function(element) { 1478 element = $(element); 1479 if (!element._overflow) return element; 1480 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; 1481 element._overflow = null; 1482 return element; 1483 } 1484 }; 1485 1486 Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); 1487 1488 Element._attributeTranslations = {}; 1489 1490 Element._attributeTranslations.names = { 1491 colspan: "colSpan", 1492 rowspan: "rowSpan", 1493 valign: "vAlign", 1494 datetime: "dateTime", 1495 accesskey: "accessKey", 1496 tabindex: "tabIndex", 1497 enctype: "encType", 1498 maxlength: "maxLength", 1499 readonly: "readOnly", 1500 longdesc: "longDesc" 1501 }; 1502 1503 Element._attributeTranslations.values = { 1504 _getAttr: function(element, attribute) { 1505 return element.getAttribute(attribute, 2); 1506 }, 1507 1508 _flag: function(element, attribute) { 1509 return $(element).hasAttribute(attribute) ? attribute : null; 1510 }, 1511 1512 style: function(element) { 1513 return element.style.cssText.toLowerCase(); 1514 }, 1515 1516 title: function(element) { 1517 var node = element.getAttributeNode('title'); 1518 return node.specified ? node.nodeValue : null; 1519 } 1520 }; 1521 1522 Object.extend(Element._attributeTranslations.values, { 1523 href: Element._attributeTranslations.values._getAttr, 1524 src: Element._attributeTranslations.values._getAttr, 1525 disabled: Element._attributeTranslations.values._flag, 1526 checked: Element._attributeTranslations.values._flag, 1527 readonly: Element._attributeTranslations.values._flag, 1528 multiple: Element._attributeTranslations.values._flag 1529 }); 1530 1531 Element.Methods.Simulated = { 1532 hasAttribute: function(element, attribute) { 1533 var t = Element._attributeTranslations; 1534 attribute = t.names[attribute] || attribute; 1535 return $(element).getAttributeNode(attribute).specified; 1536 } 1537 }; 1538 1539 // IE is missing .innerHTML support for TABLE-related elements 1540 if (document.all && !window.opera){ 1541 Element.Methods.update = function(element, html) { 1542 element = $(element); 1543 html = typeof html == 'undefined' ? '' : html.toString(); 1544 var tagName = element.tagName.toUpperCase(); 1545 if (['THEAD','TBODY','TR','TD'].include(tagName)) { 1546 var div = document.createElement('div'); 1547 switch (tagName) { 1548 case 'THEAD': 1549 case 'TBODY': 1550 div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; 1551 depth = 2; 1552 break; 1553 case 'TR': 1554 div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; 1555 depth = 3; 1556 break; 1557 case 'TD': 1558 div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; 1559 depth = 4; 1560 } 1561 $A(element.childNodes).each(function(node){ 1562 element.removeChild(node) 1563 }); 1564 depth.times(function(){ div = div.firstChild }); 1565 1566 $A(div.childNodes).each( 1567 function(node){ element.appendChild(node) }); 1568 } else { 1569 element.innerHTML = html.stripScripts(); 1570 } 1571 setTimeout(function() {html.evalScripts()}, 10); 1572 return element; 1573 } 1574 }; 1575 1576 Object.extend(Element, Element.Methods); 1577 1578 var _nativeExtensions = false; 1579 1580 if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1581 ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { 1582 var className = 'HTML' + tag + 'Element'; 1583 if(window[className]) return; 1584 var klass = window[className] = {}; 1585 klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; 1586 }); 1587 1588 Element.addMethods = function(methods) { 1589 Object.extend(Element.Methods, methods || {}); 1590 1591 function copy(methods, destination, onlyIfAbsent) { 1592 onlyIfAbsent = onlyIfAbsent || false; 1593 var cache = Element.extend.cache; 1594 for (var property in methods) { 1595 var value = methods[property]; 1596 if (!onlyIfAbsent || !(property in destination)) 1597 destination[property] = cache.findOrStore(value); 1598 } 1599 } 1600 1601 if (typeof HTMLElement != 'undefined') { 1602 copy(Element.Methods, HTMLElement.prototype); 1603 copy(Element.Methods.Simulated, HTMLElement.prototype, true); 1604 copy(Form.Methods, HTMLFormElement.prototype); 1605 [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { 1606 copy(Form.Element.Methods, klass.prototype); 1607 }); 1608 _nativeExtensions = true; 1609 } 1610 } 1611 1612 var Toggle = new Object(); 1613 Toggle.display = Element.toggle; 1614 1615 /*--------------------------------------------------------------------------*/ 1616 1617 Abstract.Insertion = function(adjacency) { 1618 this.adjacency = adjacency; 1619 } 1620 1621 Abstract.Insertion.prototype = { 1622 initialize: function(element, content) { 1623 this.element = $(element); 1624 this.content = content.stripScripts(); 1625 1626 if (this.adjacency && this.element.insertAdjacentHTML) { 1627 try { 1628 this.element.insertAdjacentHTML(this.adjacency, this.content); 1629 } catch (e) { 1630 var tagName = this.element.tagName.toUpperCase(); 1631 if (['TBODY', 'TR'].include(tagName)) { 1632 this.insertContent(this.contentFromAnonymousTable()); 1633 } else { 1634 throw e; 1635 } 1636 } 1637 } else { 1638 this.range = this.element.ownerDocument.createRange(); 1639 if (this.initializeRange) this.initializeRange(); 1640 this.insertContent([this.range.createContextualFragment(this.content)]); 1641 } 1642 1643 setTimeout(function() {content.evalScripts()}, 10); 1644 }, 1645 1646 contentFromAnonymousTable: function() { 1647 var div = document.createElement('div'); 1648 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 1649 return $A(div.childNodes[0].childNodes[0].childNodes); 1650 } 1651 } 1652 1653 var Insertion = new Object(); 1654 1655 Insertion.Before = Class.create(); 1656 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 1657 initializeRange: function() { 1658 this.range.setStartBefore(this.element); 1659 }, 1660 1661 insertContent: function(fragments) { 1662 fragments.each((function(fragment) { 1663 this.element.parentNode.insertBefore(fragment, this.element); 1664 }).bind(this)); 1665 } 1666 }); 1667 1668 Insertion.Top = Class.create(); 1669 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 1670 initializeRange: function() { 1671 this.range.selectNodeContents(this.element); 1672 this.range.collapse(true); 1673 }, 1674 1675 insertContent: function(fragments) { 1676 fragments.reverse(false).each((function(fragment) { 1677 this.element.insertBefore(fragment, this.element.firstChild); 1678 }).bind(this)); 1679 } 1680 }); 1681 1682 Insertion.Bottom = Class.create(); 1683 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 1684 initializeRange: function() { 1685 this.range.selectNodeContents(this.element); 1686 this.range.collapse(this.element); 1687 }, 1688 1689 insertContent: function(fragments) { 1690 fragments.each((function(fragment) { 1691 this.element.appendChild(fragment); 1692 }).bind(this)); 1693 } 1694 }); 1695 1696 Insertion.After = Class.create(); 1697 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 1698 initializeRange: function() { 1699 this.range.setStartAfter(this.element); 1700 }, 1701 1702 insertContent: function(fragments) { 1703 fragments.each((function(fragment) { 1704 this.element.parentNode.insertBefore(fragment, 1705 this.element.nextSibling); 1706 }).bind(this)); 1707 } 1708 }); 1709 1710 /*--------------------------------------------------------------------------*/ 1711 1712 Element.ClassNames = Class.create(); 1713 Element.ClassNames.prototype = { 1714 initialize: function(element) { 1715 this.element = $(element); 1716 }, 1717 1718 _each: function(iterator) { 1719 this.element.className.split(/\s+/).select(function(name) { 1720 return name.length > 0; 1721 })._each(iterator); 1722 }, 1723 1724 set: function(className) { 1725 this.element.className = className; 1726 }, 1727 1728 add: function(classNameToAdd) { 1729 if (this.include(classNameToAdd)) return; 1730 this.set($A(this).concat(classNameToAdd).join(' ')); 1731 }, 1732 1733 remove: function(classNameToRemove) { 1734 if (!this.include(classNameToRemove)) return; 1735 this.set($A(this).without(classNameToRemove).join(' ')); 1736 }, 1737 1738 toString: function() { 1739 return $A(this).join(' '); 1740 } 1741 }; 1742 1743 Object.extend(Element.ClassNames.prototype, Enumerable); 1744 var Selector = Class.create(); 1745 Selector.prototype = { 1746 initialize: function(expression) { 1747 this.params = {classNames: []}; 1748 this.expression = expression.toString().strip(); 1749 this.parseExpression(); 1750 this.compileMatcher(); 1751 }, 1752 1753 parseExpression: function() { 1754 function abort(message) { throw 'Parse error in selector: ' + message; } 1755 1756 if (this.expression == '') abort('empty expression'); 1757 1758 var params = this.params, expr = this.expression, match, modifier, clause, rest; 1759 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { 1760 params.attributes = params.attributes || []; 1761 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); 1762 expr = match[1]; 1763 } 1764 1765 if (expr == '*') return this.params.wildcard = true; 1766 1767 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { 1768 modifier = match[1], clause = match[2], rest = match[3]; 1769 switch (modifier) { 1770 case '#': params.id = clause; break; 1771 case '.': params.classNames.push(clause); break; 1772 case '': 1773 case undefined: params.tagName = clause.toUpperCase(); break; 1774 default: abort(expr.inspect()); 1775 } 1776 expr = rest; 1777 } 1778 1779 if (expr.length > 0) abort(expr.inspect()); 1780 }, 1781 1782 buildMatchExpression: function() { 1783 var params = this.params, conditions = [], clause; 1784 1785 if (params.wildcard) 1786 conditions.push('true'); 1787 if (clause = params.id) 1788 conditions.push('element.readAttribute("id") == ' + clause.inspect()); 1789 if (clause = params.tagName) 1790 conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); 1791 if ((clause = params.classNames).length > 0) 1792 for (var i = 0, length = clause.length; i < length; i++) 1793 conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); 1794 if (clause = params.attributes) { 1795 clause.each(function(attribute) { 1796 var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; 1797 var splitValueBy = function(delimiter) { 1798 return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; 1799 } 1800 1801 switch (attribute.operator) { 1802 case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; 1803 case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; 1804 case '|=': conditions.push( 1805 splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() 1806 ); break; 1807 case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; 1808 case '': 1809 case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; 1810 default: throw 'Unknown operator ' + attribute.operator + ' in selector'; 1811 } 1812 }); 1813 } 1814 1815 return conditions.join(' && '); 1816 }, 1817 1818 compileMatcher: function() { 1819 this.match = new Function('element', 'if (!element.tagName) return false; \ 1820 element = $(element); \ 1821 return ' + this.buildMatchExpression()); 1822 }, 1823 1824 findElements: function(scope) { 1825 var element; 1826 1827 if (element = $(this.params.id)) 1828 if (this.match(element)) 1829 if (!scope || Element.childOf(element, scope)) 1830 return [element]; 1831 1832 scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); 1833 1834 var results = []; 1835 for (var i = 0, length = scope.length; i < length; i++) 1836 if (this.match(element = scope[i])) 1837 results.push(Element.extend(element)); 1838 1839 return results; 1840 }, 1841 1842 toString: function() { 1843 return this.expression; 1844 } 1845 } 1846 1847 Object.extend(Selector, { 1848 matchElements: function(elements, expression) { 1849 var selector = new Selector(expression); 1850 return elements.select(selector.match.bind(selector)).map(Element.extend); 1851 }, 1852 1853 findElement: function(elements, expression, index) { 1854 if (typeof expression == 'number') index = expression, expression = false; 1855 return Selector.matchElements(elements, expression || '*')[index || 0]; 1856 }, 1857 1858 findChildElements: function(element, expressions) { 1859 return expressions.map(function(expression) { 1860 return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { 1861 var selector = new Selector(expr); 1862 return results.inject([], function(elements, result) { 1863 return elements.concat(selector.findElements(result || element)); 1864 }); 1865 }); 1866 }).flatten(); 1867 } 1868 }); 1869 1870 function $$() { 1871 return Selector.findChildElements(document, $A(arguments)); 1872 } 1873 var Form = { 1874 reset: function(form) { 1875 $(form).reset(); 1876 return form; 1877 }, 1878 1879 serializeElements: function(elements, getHash) { 1880 var data = elements.inject({}, function(result, element) { 1881 if (!element.disabled && element.name) { 1882 var key = element.name, value = $(element).getValue(); 1883 if (value != undefined) { 1884 if (result[key]) { 1885 if (result[key].constructor != Array) result[key] = [result[key]]; 1886 result[key].push(value); 1887 } 1888 else result[key] = value; 1889 } 1890 } 1891 return result; 1892 }); 1893 1894 return getHash ? data : Hash.toQueryString(data); 1895 } 1896 }; 1897 1898 Form.Methods = { 1899 serialize: function(form, getHash) { 1900 return Form.serializeElements(Form.getElements(form), getHash); 1901 }, 1902 1903 getElements: function(form) { 1904 return $A($(form).getElementsByTagName('*')).inject([], 1905 function(elements, child) { 1906 if (Form.Element.Serializers[child.tagName.toLowerCase()]) 1907 elements.push(Element.extend(child)); 1908 return elements; 1909 } 1910 ); 1911 }, 1912 1913 getInputs: function(form, typeName, name) { 1914 form = $(form); 1915 var inputs = form.getElementsByTagName('input'); 1916 1917 if (!typeName && !name) return $A(inputs).map(Element.extend); 1918 1919 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { 1920 var input = inputs[i]; 1921 if ((typeName && input.type != typeName) || (name && input.name != name)) 1922 continue; 1923 matchingInputs.push(Element.extend(input)); 1924 } 1925 1926 return matchingInputs; 1927 }, 1928 1929 disable: function(form) { 1930 form = $(form); 1931 form.getElements().each(function(element) { 1932 element.blur(); 1933 element.disabled = 'true'; 1934 }); 1935 return form; 1936 }, 1937 1938 enable: function(form) { 1939 form = $(form); 1940 form.getElements().each(function(element) { 1941 element.disabled = ''; 1942 }); 1943 return form; 1944 }, 1945 1946 findFirstElement: function(form) { 1947 return $(form).getElements().find(function(element) { 1948 return element.type != 'hidden' && !element.disabled && 1949 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 1950 }); 1951 }, 1952 1953 focusFirstElement: function(form) { 1954 form = $(form); 1955 form.findFirstElement().activate(); 1956 return form; 1957 } 1958 } 1959 1960 Object.extend(Form, Form.Methods); 1961 1962 /*--------------------------------------------------------------------------*/ 1963 1964 Form.Element = { 1965 focus: function(element) { 1966 $(element).focus(); 1967 return element; 1968 }, 1969 1970 select: function(element) { 1971 $(element).select(); 1972 return element; 1973 } 1974 } 1975 1976 Form.Element.Methods = { 1977 serialize: function(element) { 1978 element = $(element); 1979 if (!element.disabled && element.name) { 1980 var value = element.getValue(); 1981 if (value != undefined) { 1982 var pair = {}; 1983 pair[element.name] = value; 1984 return Hash.toQueryString(pair); 1985 } 1986 } 1987 return ''; 1988 }, 1989 1990 getValue: function(element) { 1991 element = $(element); 1992 var method = element.tagName.toLowerCase(); 1993 return Form.Element.Serializers[method](element); 1994 }, 1995 1996 clear: function(element) { 1997 $(element).value = ''; 1998 return element; 1999 }, 2000 2001 present: function(element) { 2002 return $(element).value != ''; 2003 }, 2004 2005 activate: function(element) { 2006 element = $(element); 2007 element.focus(); 2008 if (element.select && ( element.tagName.toLowerCase() != 'input' || 2009 !['button', 'reset', 'submit'].include(element.type) ) ) 2010 element.select(); 2011 return element; 2012 }, 2013 2014 disable: function(element) { 2015 element = $(element); 2016 element.disabled = true; 2017 return element; 2018 }, 2019 2020 enable: function(element) { 2021 element = $(element); 2022 element.blur(); 2023 element.disabled = false; 2024 return element; 2025 } 2026 } 2027 2028 Object.extend(Form.Element, Form.Element.Methods); 2029 var Field = Form.Element; 2030 var $F = Form.Element.getValue; 2031 2032 /*--------------------------------------------------------------------------*/ 2033 2034 Form.Element.Serializers = { 2035 input: function(element) { 2036 switch (element.type.toLowerCase()) { 2037 case 'checkbox': 2038 case 'radio': 2039 return Form.Element.Serializers.inputSelector(element); 2040 default: 2041 return Form.Element.Serializers.textarea(element); 2042 } 2043 }, 2044 2045 inputSelector: function(element) { 2046 return element.checked ? element.value : null; 2047 }, 2048 2049 textarea: function(element) { 2050 return element.value; 2051 }, 2052 2053 select: function(element) { 2054 return this[element.type == 'select-one' ? 2055 'selectOne' : 'selectMany'](element); 2056 }, 2057 2058 selectOne: function(element) { 2059 var index = element.selectedIndex; 2060 return index >= 0 ? this.optionValue(element.options[index]) : null; 2061 }, 2062 2063 selectMany: function(element) { 2064 var values, length = element.length; 2065 if (!length) return null; 2066 2067 for (var i = 0, values = []; i < length; i++) { 2068 var opt = element.options[i]; 2069 if (opt.selected) values.push(this.optionValue(opt)); 2070 } 2071 return values; 2072 }, 2073 2074 optionValue: function(opt) { 2075 // extend element because hasAttribute may not be native 2076 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 2077 } 2078 } 2079 2080 /*--------------------------------------------------------------------------*/ 2081 2082 Abstract.TimedObserver = function() {} 2083 Abstract.TimedObserver.prototype = { 2084 initialize: function(element, frequency, callback) { 2085 this.frequency = frequency; 2086 this.element = $(element); 2087 this.callback = callback; 2088 2089 this.lastValue = this.getValue(); 2090 this.registerCallback(); 2091 }, 2092 2093 registerCallback: function() { 2094 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 2095 }, 2096 2097 onTimerEvent: function() { 2098 var value = this.getValue(); 2099 var changed = ('string' == typeof this.lastValue && 'string' == typeof value 2100 ? this.lastValue != value : String(this.lastValue) != String(value)); 2101 if (changed) { 2102 this.callback(this.element, value); 2103 this.lastValue = value; 2104 } 2105 } 2106 } 2107 2108 Form.Element.Observer = Class.create(); 2109 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 2110 getValue: function() { 2111 return Form.Element.getValue(this.element); 2112 } 2113 }); 2114 2115 Form.Observer = Class.create(); 2116 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 2117 getValue: function() { 2118 return Form.serialize(this.element); 2119 } 2120 }); 2121 2122 /*--------------------------------------------------------------------------*/ 2123 2124 Abstract.EventObserver = function() {} 2125 Abstract.EventObserver.prototype = { 2126 initialize: function(element, callback) { 2127 this.element = $(element); 2128 this.callback = callback; 2129 2130 this.lastValue = this.getValue(); 2131 if (this.element.tagName.toLowerCase() == 'form') 2132 this.registerFormCallbacks(); 2133 else 2134 this.registerCallback(this.element); 2135 }, 2136 2137 onElementEvent: function() { 2138 var value = this.getValue(); 2139 if (this.lastValue != value) { 2140 this.callback(this.element, value); 2141 this.lastValue = value; 2142 } 2143 }, 2144 2145 registerFormCallbacks: function() { 2146 Form.getElements(this.element).each(this.registerCallback.bind(this)); 2147 }, 2148 2149 registerCallback: function(element) { 2150 if (element.type) { 2151 switch (element.type.toLowerCase()) { 2152 case 'checkbox': 2153 case 'radio': 2154 Event.observe(element, 'click', this.onElementEvent.bind(this)); 2155 break; 2156 default: 2157 Event.observe(element, 'change', this.onElementEvent.bind(this)); 2158 break; 2159 } 2160 } 2161 } 2162 } 2163 2164 Form.Element.EventObserver = Class.create(); 2165 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 2166 getValue: function() { 2167 return Form.Element.getValue(this.element); 2168 } 2169 }); 2170 2171 Form.EventObserver = Class.create(); 2172 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 2173 getValue: function() { 2174 return Form.serialize(this.element); 2175 } 2176 }); 2177 if (!window.Event) { 2178 var Event = new Object(); 2179 } 2180 2181 Object.extend(Event, { 2182 KEY_BACKSPACE: 8, 2183 KEY_TAB: 9, 2184 KEY_RETURN: 13, 2185 KEY_ESC: 27, 2186 KEY_LEFT: 37, 2187 KEY_UP: 38, 2188 KEY_RIGHT: 39, 2189 KEY_DOWN: 40, 2190 KEY_DELETE: 46, 2191 KEY_HOME: 36, 2192 KEY_END: 35, 2193 KEY_PAGEUP: 33, 2194 KEY_PAGEDOWN: 34, 2195 2196 element: function(event) { 2197 return event.target || event.srcElement; 2198 }, 2199 2200 isLeftClick: function(event) { 2201 return (((event.which) && (event.which == 1)) || 2202 ((event.button) && (event.button == 1))); 2203 }, 2204 2205 pointerX: function(event) { 2206 return event.pageX || (event.clientX + 2207 (document.documentElement.scrollLeft || document.body.scrollLeft)); 2208 }, 2209 2210 pointerY: function(event) { 2211 return event.pageY || (event.clientY + 2212 (document.documentElement.scrollTop || document.body.scrollTop)); 2213 }, 2214 2215 stop: function(event) { 2216 if (event.preventDefault) { 2217 event.preventDefault(); 2218 event.stopPropagation(); 2219 } else { 2220 event.returnValue = false; 2221 event.cancelBubble = true; 2222 } 2223 }, 2224 2225 // find the first node with the given tagName, starting from the 2226 // node the event was triggered on; traverses the DOM upwards 2227 findElement: function(event, tagName) { 2228 var element = Event.element(event); 2229 while (element.parentNode && (!element.tagName || 2230 (element.tagName.toUpperCase() != tagName.toUpperCase()))) 2231 element = element.parentNode; 2232 return element; 2233 }, 2234 2235 observers: false, 2236 2237 _observeAndCache: function(element, name, observer, useCapture) { 2238 if (!this.observers) this.observers = []; 2239 if (element.addEventListener) { 2240 this.observers.push([element, name, observer, useCapture]); 2241 element.addEventListener(name, observer, useCapture); 2242 } else if (element.attachEvent) { 2243 this.observers.push([element, name, observer, useCapture]); 2244 element.attachEvent('on' + name, observer); 2245 } 2246 }, 2247 2248 unloadCache: function() { 2249 if (!Event.observers) return; 2250 for (var i = 0, length = Event.observers.length; i < length; i++) { 2251 Event.stopObserving.apply(this, Event.observers[i]); 2252 Event.observers[i][0] = null; 2253 } 2254 Event.observers = false; 2255 }, 2256 2257 observe: function(element, name, observer, useCapture) { 2258 element = $(element); 2259 useCapture = useCapture || false; 2260 2261 if (name == 'keypress' && 2262 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 2263 || element.attachEvent)) 2264 name = 'keydown'; 2265 2266 Event._observeAndCache(element, name, observer, useCapture); 2267 }, 2268 2269 stopObserving: function(element, name, observer, useCapture) { 2270 element = $(element); 2271 useCapture = useCapture || false; 2272 2273 if (name == 'keypress' && 2274 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 2275 || element.detachEvent)) 2276 name = 'keydown'; 2277 2278 if (element.removeEventListener) { 2279 element.removeEventListener(name, observer, useCapture); 2280 } else if (element.detachEvent) { 2281 try { 2282 element.detachEvent('on' + name, observer); 2283 } catch (e) {} 2284 } 2285 } 2286 }); 2287 2288 /* prevent memory leaks in IE */ 2289 if (navigator.appVersion.match(/\bMSIE\b/)) 2290 Event.observe(window, 'unload', Event.unloadCache, false); 2291 var Position = { 2292 // set to true if needed, warning: firefox performance problems 2293 // NOT neeeded for page scrolling, only if draggable contained in 2294 // scrollable elements 2295 includeScrollOffsets: false, 2296 2297 // must be called before calling withinIncludingScrolloffset, every time the 2298 // page is scrolled 2299 prepare: function() { 2300 this.deltaX = window.pageXOffset 2301 || document.documentElement.scrollLeft 2302 || document.body.scrollLeft 2303 || 0; 2304 this.deltaY = window.pageYOffset 2305 || document.documentElement.scrollTop 2306 || document.body.scrollTop 2307 || 0; 2308 }, 2309 2310 realOffset: function(element) { 2311 var valueT = 0, valueL = 0; 2312 do { 2313 valueT += element.scrollTop || 0; 2314 valueL += element.scrollLeft || 0; 2315 element = element.parentNode; 2316 } while (element); 2317 return [valueL, valueT]; 2318 }, 2319 2320 cumulativeOffset: function(element) { 2321 var valueT = 0, valueL = 0; 2322 do { 2323 valueT += element.offsetTop || 0; 2324 valueL += element.offsetLeft || 0; 2325 element = element.offsetParent; 2326 } while (element); 2327 return [valueL, valueT]; 2328 }, 2329 2330 positionedOffset: function(element) { 2331 var valueT = 0, valueL = 0; 2332 do { 2333 valueT += element.offsetTop || 0; 2334 valueL += element.offsetLeft || 0; 2335 element = element.offsetParent; 2336 if (element) { 2337 if(element.tagName=='BODY') break; 2338 var p = Element.getStyle(element, 'position'); 2339 if (p == 'relative' || p == 'absolute') break; 2340 } 2341 } while (element); 2342 return [valueL, valueT]; 2343 }, 2344 2345 offsetParent: function(element) { 2346 if (element.offsetParent) return element.offsetParent; 2347 if (element == document.body) return element; 2348 2349 while ((element = element.parentNode) && element != document.body) 2350 if (Element.getStyle(element, 'position') != 'static') 2351 return element; 2352 2353 return document.body; 2354 }, 2355 2356 // caches x/y coordinate pair to use with overlap 2357 within: function(element, x, y) { 2358 if (this.includeScrollOffsets) 2359 return this.withinIncludingScrolloffsets(element, x, y); 2360 this.xcomp = x; 2361 this.ycomp = y; 2362 this.offset = this.cumulativeOffset(element); 2363 2364 return (y >= this.offset[1] && 2365 y < this.offset[1] + element.offsetHeight && 2366 x >= this.offset[0] && 2367 x < this.offset[0] + element.offsetWidth); 2368 }, 2369 2370 withinIncludingScrolloffsets: function(element, x, y) { 2371 var offsetcache = this.realOffset(element); 2372 2373 this.xcomp = x + offsetcache[0] - this.deltaX; 2374 this.ycomp = y + offsetcache[1] - this.deltaY; 2375 this.offset = this.cumulativeOffset(element); 2376 2377 return (this.ycomp >= this.offset[1] && 2378 this.ycomp < this.offset[1] + element.offsetHeight && 2379 this.xcomp >= this.offset[0] && 2380 this.xcomp < this.offset[0] + element.offsetWidth); 2381 }, 2382 2383 // within must be called directly before 2384 overlap: function(mode, element) { 2385 if (!mode) return 0; 2386 if (mode == 'vertical') 2387 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 2388 element.offsetHeight; 2389 if (mode == 'horizontal') 2390 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 2391 element.offsetWidth; 2392 }, 2393 2394 page: function(forElement) { 2395 var valueT = 0, valueL = 0; 2396 2397 var element = forElement; 2398 do { 2399 valueT += element.offsetTop || 0; 2400 valueL += element.offsetLeft || 0; 2401 2402 // Safari fix 2403 if (element.offsetParent==document.body) 2404 if (Element.getStyle(element,'position')=='absolute') break; 2405 2406 } while (element = element.offsetParent); 2407 2408 element = forElement; 2409 do { 2410 if (!window.opera || element.tagName=='BODY') { 2411 valueT -= element.scrollTop || 0; 2412 valueL -= element.scrollLeft || 0; 2413 } 2414 } while (element = element.parentNode); 2415 2416 return [valueL, valueT]; 2417 }, 2418 2419 clone: function(source, target) { 2420 var options = Object.extend({ 2421 setLeft: true, 2422 setTop: true, 2423 setWidth: true, 2424 setHeight: true, 2425 offsetTop: 0, 2426 offsetLeft: 0 2427 }, arguments[2] || {}) 2428 2429 // find page position of source 2430 source = $(source); 2431 var p = Position.page(source); 2432 2433 // find coordinate system to use 2434 target = $(target); 2435 var delta = [0, 0]; 2436 var parent = null; 2437 // delta [0,0] will do fine with position: fixed elements, 2438 // position:absolute needs offsetParent deltas 2439 if (Element.getStyle(target,'position') == 'absolute') { 2440 parent = Position.offsetParent(target); 2441 delta = Position.page(parent); 2442 } 2443 2444 // correct by body offsets (fixes Safari) 2445 if (parent == document.body) { 2446 delta[0] -= document.body.offsetLeft; 2447 delta[1] -= document.body.offsetTop; 2448 } 2449 2450 // set position 2451 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 2452 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 2453 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; 2454 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; 2455 }, 2456 2457 absolutize: function(element) { 2458 element = $(element); 2459 if (element.style.position == 'absolute') return; 2460 Position.prepare(); 2461 2462 var offsets = Position.positionedOffset(element); 2463 var top = offsets[1]; 2464 var left = offsets[0]; 2465 var width = element.clientWidth; 2466 var height = element.clientHeight; 2467 2468 element._originalLeft = left - parseFloat(element.style.left || 0); 2469 element._originalTop = top - parseFloat(element.style.top || 0); 2470 element._originalWidth = element.style.width; 2471 element._originalHeight = element.style.height; 2472 2473 element.style.position = 'absolute'; 2474 element.style.top = top + 'px'; 2475 element.style.left = left + 'px'; 2476 element.style.width = width + 'px'; 2477 element.style.height = height + 'px'; 2478 }, 2479 2480 relativize: function(element) { 2481 element = $(element); 2482 if (element.style.position == 'relative') return; 2483 Position.prepare(); 2484 2485 element.style.position = 'relative'; 2486 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 2487 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 2488 2489 element.style.top = top + 'px'; 2490 element.style.left = left + 'px'; 2491 element.style.height = element._originalHeight; 2492 element.style.width = element._originalWidth; 2493 } 2494 } 2495 2496 // Safari returns margins on body which is incorrect if the child is absolutely 2497 // positioned. For performance reasons, redefine Position.cumulativeOffset for 2498 // KHTML/WebKit only. 2499 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 2500 Position.cumulativeOffset = function(element) { 2501 var valueT = 0, valueL = 0; 2502 do { 2503 valueT += element.offsetTop || 0; 2504 valueL += element.offsetLeft || 0; 2505 if (element.offsetParent == document.body) 2506 if (Element.getStyle(element, 'position') == 'absolute') break; 2507 2508 element = element.offsetParent; 2509 } while (element); 2510 2511 return [valueL, valueT]; 2512 } 2513 } 2514 2515 Element.addMethods();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |