[ Index ] |
|
Code source de LifeType 1.2.4 |
1 /* Prototype JavaScript framework, version 1.4.0 2 * (c) 2005 Sam Stephenson <sam@conio.net> 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.4.0', 11 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 12 13 emptyFunction: function() {}, 14 K: function(x) {return x} 15 } 16 17 var Class = { 18 create: function() { 19 return function() { 20 this.initialize.apply(this, arguments); 21 } 22 } 23 } 24 25 var Abstract = new Object(); 26 27 Object.extend = function(destination, source) { 28 for (property in source) { 29 destination[property] = source[property]; 30 } 31 return destination; 32 } 33 34 Object.inspect = function(object) { 35 try { 36 if (object == undefined) return 'undefined'; 37 if (object == null) return 'null'; 38 return object.inspect ? object.inspect() : object.toString(); 39 } catch (e) { 40 if (e instanceof RangeError) return '...'; 41 throw e; 42 } 43 } 44 45 Function.prototype.bind = function() { 46 var __method = this, args = $A(arguments), object = args.shift(); 47 return function() { 48 return __method.apply(object, args.concat($A(arguments))); 49 } 50 } 51 52 Function.prototype.bindAsEventListener = function(object) { 53 var __method = this; 54 return function(event) { 55 return __method.call(object, event || window.event); 56 } 57 } 58 59 Object.extend(Number.prototype, { 60 toColorPart: function() { 61 var digits = this.toString(16); 62 if (this < 16) return '0' + digits; 63 return digits; 64 }, 65 66 succ: function() { 67 return this + 1; 68 }, 69 70 times: function(iterator) { 71 $R(0, this, true).each(iterator); 72 return this; 73 } 74 }); 75 76 var Try = { 77 these: function() { 78 var returnValue; 79 80 for (var i = 0; i < arguments.length; i++) { 81 var lambda = arguments[i]; 82 try { 83 returnValue = lambda(); 84 break; 85 } catch (e) {} 86 } 87 88 return returnValue; 89 } 90 } 91 92 /*--------------------------------------------------------------------------*/ 93 94 var PeriodicalExecuter = Class.create(); 95 PeriodicalExecuter.prototype = { 96 initialize: function(callback, frequency) { 97 this.callback = callback; 98 this.frequency = frequency; 99 this.currentlyExecuting = false; 100 101 this.registerCallback(); 102 }, 103 104 registerCallback: function() { 105 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 106 }, 107 108 onTimerEvent: function() { 109 if (!this.currentlyExecuting) { 110 try { 111 this.currentlyExecuting = true; 112 this.callback(); 113 } finally { 114 this.currentlyExecuting = false; 115 } 116 } 117 } 118 } 119 120 /*--------------------------------------------------------------------------*/ 121 122 function $() { 123 var elements = new Array(); 124 125 for (var i = 0; i < arguments.length; i++) { 126 var element = arguments[i]; 127 if (typeof element == 'string') 128 element = document.getElementById(element); 129 130 if (arguments.length == 1) 131 return element; 132 133 elements.push(element); 134 } 135 136 return elements; 137 } 138 Object.extend(String.prototype, { 139 stripTags: function() { 140 return this.replace(/<\/?[^>]+>/gi, ''); 141 }, 142 143 stripScripts: function() { 144 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 145 }, 146 147 extractScripts: function() { 148 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 149 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 150 return (this.match(matchAll) || []).map(function(scriptTag) { 151 return (scriptTag.match(matchOne) || ['', ''])[1]; 152 }); 153 }, 154 155 evalScripts: function() { 156 return this.extractScripts().map(eval); 157 }, 158 159 escapeHTML: function() { 160 var div = document.createElement('div'); 161 var text = document.createTextNode(this); 162 div.appendChild(text); 163 return div.innerHTML; 164 }, 165 166 unescapeHTML: function() { 167 var div = document.createElement('div'); 168 div.innerHTML = this.stripTags(); 169 return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; 170 }, 171 172 toQueryParams: function() { 173 var pairs = this.match(/^\??(.*)$/)[1].split('&'); 174 return pairs.inject({}, function(params, pairString) { 175 var pair = pairString.split('='); 176 params[pair[0]] = pair[1]; 177 return params; 178 }); 179 }, 180 181 toArray: function() { 182 return this.split(''); 183 }, 184 185 camelize: function() { 186 var oStringList = this.split('-'); 187 if (oStringList.length == 1) return oStringList[0]; 188 189 var camelizedString = this.indexOf('-') == 0 190 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 191 : oStringList[0]; 192 193 for (var i = 1, len = oStringList.length; i < len; i++) { 194 var s = oStringList[i]; 195 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 196 } 197 198 return camelizedString; 199 }, 200 201 inspect: function() { 202 return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; 203 } 204 }); 205 206 String.prototype.parseQuery = String.prototype.toQueryParams; 207 208 var $break = new Object(); 209 var $continue = new Object(); 210 211 var Enumerable = { 212 each: function(iterator) { 213 var index = 0; 214 try { 215 this._each(function(value) { 216 try { 217 iterator(value, index++); 218 } catch (e) { 219 if (e != $continue) throw e; 220 } 221 }); 222 } catch (e) { 223 if (e != $break) throw e; 224 } 225 }, 226 227 all: function(iterator) { 228 var result = true; 229 this.each(function(value, index) { 230 result = result && !!(iterator || Prototype.K)(value, index); 231 if (!result) throw $break; 232 }); 233 return result; 234 }, 235 236 any: function(iterator) { 237 var result = true; 238 this.each(function(value, index) { 239 if (result = !!(iterator || Prototype.K)(value, index)) 240 throw $break; 241 }); 242 return result; 243 }, 244 245 collect: function(iterator) { 246 var results = []; 247 this.each(function(value, index) { 248 results.push(iterator(value, index)); 249 }); 250 return results; 251 }, 252 253 detect: function (iterator) { 254 var result; 255 this.each(function(value, index) { 256 if (iterator(value, index)) { 257 result = value; 258 throw $break; 259 } 260 }); 261 return result; 262 }, 263 264 findAll: function(iterator) { 265 var results = []; 266 this.each(function(value, index) { 267 if (iterator(value, index)) 268 results.push(value); 269 }); 270 return results; 271 }, 272 273 grep: function(pattern, iterator) { 274 var results = []; 275 this.each(function(value, index) { 276 var stringValue = value.toString(); 277 if (stringValue.match(pattern)) 278 results.push((iterator || Prototype.K)(value, index)); 279 }) 280 return results; 281 }, 282 283 include: function(object) { 284 var found = false; 285 this.each(function(value) { 286 if (value == object) { 287 found = true; 288 throw $break; 289 } 290 }); 291 return found; 292 }, 293 294 inject: function(memo, iterator) { 295 this.each(function(value, index) { 296 memo = iterator(memo, value, index); 297 }); 298 return memo; 299 }, 300 301 invoke: function(method) { 302 var args = $A(arguments).slice(1); 303 return this.collect(function(value) { 304 return value[method].apply(value, args); 305 }); 306 }, 307 308 max: function(iterator) { 309 var result; 310 this.each(function(value, index) { 311 value = (iterator || Prototype.K)(value, index); 312 if (value >= (result || value)) 313 result = value; 314 }); 315 return result; 316 }, 317 318 min: function(iterator) { 319 var result; 320 this.each(function(value, index) { 321 value = (iterator || Prototype.K)(value, index); 322 if (value <= (result || value)) 323 result = value; 324 }); 325 return result; 326 }, 327 328 partition: function(iterator) { 329 var trues = [], falses = []; 330 this.each(function(value, index) { 331 ((iterator || Prototype.K)(value, index) ? 332 trues : falses).push(value); 333 }); 334 return [trues, falses]; 335 }, 336 337 pluck: function(property) { 338 var results = []; 339 this.each(function(value, index) { 340 results.push(value[property]); 341 }); 342 return results; 343 }, 344 345 reject: function(iterator) { 346 var results = []; 347 this.each(function(value, index) { 348 if (!iterator(value, index)) 349 results.push(value); 350 }); 351 return results; 352 }, 353 354 sortBy: function(iterator) { 355 return this.collect(function(value, index) { 356 return {value: value, criteria: iterator(value, index)}; 357 }).sort(function(left, right) { 358 var a = left.criteria, b = right.criteria; 359 return a < b ? -1 : a > b ? 1 : 0; 360 }).pluck('value'); 361 }, 362 363 toArray: function() { 364 return this.collect(Prototype.K); 365 }, 366 367 zip: function() { 368 var iterator = Prototype.K, args = $A(arguments); 369 if (typeof args.last() == 'function') 370 iterator = args.pop(); 371 372 var collections = [this].concat(args).map($A); 373 return this.map(function(value, index) { 374 iterator(value = collections.pluck(index)); 375 return value; 376 }); 377 }, 378 379 inspect: function() { 380 return '#<Enumerable:' + this.toArray().inspect() + '>'; 381 } 382 } 383 384 Object.extend(Enumerable, { 385 map: Enumerable.collect, 386 find: Enumerable.detect, 387 select: Enumerable.findAll, 388 member: Enumerable.include, 389 entries: Enumerable.toArray 390 }); 391 var $A = Array.from = function(iterable) { 392 if (!iterable) return []; 393 if (iterable.toArray) { 394 return iterable.toArray(); 395 } else { 396 var results = []; 397 for (var i = 0; i < iterable.length; i++) 398 results.push(iterable[i]); 399 return results; 400 } 401 } 402 403 Object.extend(Array.prototype, Enumerable); 404 405 Array.prototype._reverse = Array.prototype.reverse; 406 407 Object.extend(Array.prototype, { 408 _each: function(iterator) { 409 for (var i = 0; i < this.length; i++) 410 iterator(this[i]); 411 }, 412 413 clear: function() { 414 this.length = 0; 415 return this; 416 }, 417 418 first: function() { 419 return this[0]; 420 }, 421 422 last: function() { 423 return this[this.length - 1]; 424 }, 425 426 compact: function() { 427 return this.select(function(value) { 428 return value != undefined || value != null; 429 }); 430 }, 431 432 flatten: function() { 433 return this.inject([], function(array, value) { 434 return array.concat(value.constructor == Array ? 435 value.flatten() : [value]); 436 }); 437 }, 438 439 without: function() { 440 var values = $A(arguments); 441 return this.select(function(value) { 442 return !values.include(value); 443 }); 444 }, 445 446 indexOf: function(object) { 447 for (var i = 0; i < this.length; i++) 448 if (this[i] == object) return i; 449 return -1; 450 }, 451 452 reverse: function(inline) { 453 return (inline !== false ? this : this.toArray())._reverse(); 454 }, 455 456 shift: function() { 457 var result = this[0]; 458 for (var i = 0; i < this.length - 1; i++) 459 this[i] = this[i + 1]; 460 this.length--; 461 return result; 462 }, 463 464 inspect: function() { 465 return '[' + this.map(Object.inspect).join(', ') + ']'; 466 } 467 }); 468 var Hash = { 469 _each: function(iterator) { 470 for (key in this) { 471 var value = this[key]; 472 if (typeof value == 'function') continue; 473 474 var pair = [key, value]; 475 pair.key = key; 476 pair.value = value; 477 iterator(pair); 478 } 479 }, 480 481 keys: function() { 482 return this.pluck('key'); 483 }, 484 485 values: function() { 486 return this.pluck('value'); 487 }, 488 489 merge: function(hash) { 490 return $H(hash).inject($H(this), function(mergedHash, pair) { 491 mergedHash[pair.key] = pair.value; 492 return mergedHash; 493 }); 494 }, 495 496 toQueryString: function() { 497 return this.map(function(pair) { 498 return pair.map(encodeURIComponent).join('='); 499 }).join('&'); 500 }, 501 502 inspect: function() { 503 return '#<Hash:{' + this.map(function(pair) { 504 return pair.map(Object.inspect).join(': '); 505 }).join(', ') + '}>'; 506 } 507 } 508 509 function $H(object) { 510 var hash = Object.extend({}, object || {}); 511 Object.extend(hash, Enumerable); 512 Object.extend(hash, Hash); 513 return hash; 514 } 515 ObjectRange = Class.create(); 516 Object.extend(ObjectRange.prototype, Enumerable); 517 Object.extend(ObjectRange.prototype, { 518 initialize: function(start, end, exclusive) { 519 this.start = start; 520 this.end = end; 521 this.exclusive = exclusive; 522 }, 523 524 _each: function(iterator) { 525 var value = this.start; 526 do { 527 iterator(value); 528 value = value.succ(); 529 } while (this.include(value)); 530 }, 531 532 include: function(value) { 533 if (value < this.start) 534 return false; 535 if (this.exclusive) 536 return value < this.end; 537 return value <= this.end; 538 } 539 }); 540 541 var $R = function(start, end, exclusive) { 542 return new ObjectRange(start, end, exclusive); 543 } 544 545 var Ajax = { 546 getTransport: function() { 547 return Try.these( 548 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 549 function() {return new ActiveXObject('Microsoft.XMLHTTP')}, 550 function() {return new XMLHttpRequest()} 551 ) || false; 552 }, 553 554 activeRequestCount: 0 555 } 556 557 Ajax.Responders = { 558 responders: [], 559 560 _each: function(iterator) { 561 this.responders._each(iterator); 562 }, 563 564 register: function(responderToAdd) { 565 if (!this.include(responderToAdd)) 566 this.responders.push(responderToAdd); 567 }, 568 569 unregister: function(responderToRemove) { 570 this.responders = this.responders.without(responderToRemove); 571 }, 572 573 dispatch: function(callback, request, transport, json) { 574 this.each(function(responder) { 575 if (responder[callback] && typeof responder[callback] == 'function') { 576 try { 577 responder[callback].apply(responder, [request, transport, json]); 578 } catch (e) {} 579 } 580 }); 581 } 582 }; 583 584 Object.extend(Ajax.Responders, Enumerable); 585 586 Ajax.Responders.register({ 587 onCreate: function() { 588 Ajax.activeRequestCount++; 589 }, 590 591 onComplete: function() { 592 Ajax.activeRequestCount--; 593 } 594 }); 595 596 Ajax.Base = function() {}; 597 Ajax.Base.prototype = { 598 setOptions: function(options) { 599 this.options = { 600 method: 'post', 601 asynchronous: true, 602 parameters: '' 603 } 604 Object.extend(this.options, options || {}); 605 }, 606 607 responseIsSuccess: function() { 608 return this.transport.status == undefined 609 || this.transport.status == 0 610 || (this.transport.status >= 200 && this.transport.status < 300); 611 }, 612 613 responseIsFailure: function() { 614 return !this.responseIsSuccess(); 615 } 616 } 617 618 Ajax.Request = Class.create(); 619 Ajax.Request.Events = 620 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 621 622 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 623 initialize: function(url, options) { 624 this.transport = Ajax.getTransport(); 625 this.setOptions(options); 626 this.request(url); 627 }, 628 629 request: function(url) { 630 var parameters = this.options.parameters || ''; 631 if (parameters.length > 0) parameters += '&_='; 632 633 try { 634 this.url = url; 635 if (this.options.method == 'get' && parameters.length > 0) 636 this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; 637 638 Ajax.Responders.dispatch('onCreate', this, this.transport); 639 640 this.transport.open(this.options.method, this.url, 641 this.options.asynchronous); 642 643 if (this.options.asynchronous) { 644 this.transport.onreadystatechange = this.onStateChange.bind(this); 645 setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); 646 } 647 648 this.setRequestHeaders(); 649 650 var body = this.options.postBody ? this.options.postBody : parameters; 651 this.transport.send(this.options.method == 'post' ? body : null); 652 653 } catch (e) { 654 this.dispatchException(e); 655 } 656 }, 657 658 setRequestHeaders: function() { 659 var requestHeaders = 660 ['X-Requested-With', 'XMLHttpRequest', 661 'X-Prototype-Version', Prototype.Version]; 662 663 if (this.options.method == 'post') { 664 requestHeaders.push('Content-type', 665 'application/x-www-form-urlencoded'); 666 667 /* Force "Connection: close" for Mozilla browsers to work around 668 * a bug where XMLHttpReqeuest sends an incorrect Content-length 669 * header. See Mozilla Bugzilla #246651. 670 */ 671 if (this.transport.overrideMimeType) 672 requestHeaders.push('Connection', 'close'); 673 } 674 675 if (this.options.requestHeaders) 676 requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); 677 678 for (var i = 0; i < requestHeaders.length; i += 2) 679 this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); 680 }, 681 682 onStateChange: function() { 683 var readyState = this.transport.readyState; 684 if (readyState != 1) 685 this.respondToReadyState(this.transport.readyState); 686 }, 687 688 header: function(name) { 689 try { 690 return this.transport.getResponseHeader(name); 691 } catch (e) {} 692 }, 693 694 evalJSON: function() { 695 try { 696 return eval(this.header('X-JSON')); 697 } catch (e) {} 698 }, 699 700 evalResponse: function() { 701 try { 702 return eval(this.transport.responseText); 703 } catch (e) { 704 this.dispatchException(e); 705 } 706 }, 707 708 respondToReadyState: function(readyState) { 709 var event = Ajax.Request.Events[readyState]; 710 var transport = this.transport, json = this.evalJSON(); 711 712 if (event == 'Complete') { 713 try { 714 (this.options['on' + this.transport.status] 715 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] 716 || Prototype.emptyFunction)(transport, json); 717 } catch (e) { 718 this.dispatchException(e); 719 } 720 721 if ((this.header('Content-type') || '').match(/^text\/javascript/i)) 722 this.evalResponse(); 723 } 724 725 try { 726 (this.options['on' + event] || Prototype.emptyFunction)(transport, json); 727 Ajax.Responders.dispatch('on' + event, this, transport, json); 728 } catch (e) { 729 this.dispatchException(e); 730 } 731 732 /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ 733 if (event == 'Complete') 734 this.transport.onreadystatechange = Prototype.emptyFunction; 735 }, 736 737 dispatchException: function(exception) { 738 (this.options.onException || Prototype.emptyFunction)(this, exception); 739 Ajax.Responders.dispatch('onException', this, exception); 740 } 741 }); 742 743 Ajax.Updater = Class.create(); 744 745 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 746 initialize: function(container, url, options) { 747 this.containers = { 748 success: container.success ? $(container.success) : $(container), 749 failure: container.failure ? $(container.failure) : 750 (container.success ? null : $(container)) 751 } 752 753 this.transport = Ajax.getTransport(); 754 this.setOptions(options); 755 756 var onComplete = this.options.onComplete || Prototype.emptyFunction; 757 this.options.onComplete = (function(transport, object) { 758 this.updateContent(); 759 onComplete(transport, object); 760 }).bind(this); 761 762 this.request(url); 763 }, 764 765 updateContent: function() { 766 var receiver = this.responseIsSuccess() ? 767 this.containers.success : this.containers.failure; 768 var response = this.transport.responseText; 769 770 if (!this.options.evalScripts) 771 response = response.stripScripts(); 772 773 if (receiver) { 774 if (this.options.insertion) { 775 new this.options.insertion(receiver, response); 776 } else { 777 Element.update(receiver, response); 778 } 779 } 780 781 if (this.responseIsSuccess()) { 782 if (this.onComplete) 783 setTimeout(this.onComplete.bind(this), 10); 784 } 785 } 786 }); 787 788 Ajax.PeriodicalUpdater = Class.create(); 789 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { 790 initialize: function(container, url, options) { 791 this.setOptions(options); 792 this.onComplete = this.options.onComplete; 793 794 this.frequency = (this.options.frequency || 2); 795 this.decay = (this.options.decay || 1); 796 797 this.updater = {}; 798 this.container = container; 799 this.url = url; 800 801 this.start(); 802 }, 803 804 start: function() { 805 this.options.onComplete = this.updateComplete.bind(this); 806 this.onTimerEvent(); 807 }, 808 809 stop: function() { 810 this.updater.onComplete = undefined; 811 clearTimeout(this.timer); 812 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 813 }, 814 815 updateComplete: function(request) { 816 if (this.options.decay) { 817 this.decay = (request.responseText == this.lastText ? 818 this.decay * this.options.decay : 1); 819 820 this.lastText = request.responseText; 821 } 822 this.timer = setTimeout(this.onTimerEvent.bind(this), 823 this.decay * this.frequency * 1000); 824 }, 825 826 onTimerEvent: function() { 827 this.updater = new Ajax.Updater(this.container, this.url, this.options); 828 } 829 }); 830 document.getElementsByClassName = function(className, parentElement) { 831 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 832 return $A(children).inject([], function(elements, child) { 833 if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 834 elements.push(child); 835 return elements; 836 }); 837 } 838 839 /*--------------------------------------------------------------------------*/ 840 841 if (!window.Element) { 842 var Element = new Object(); 843 } 844 845 Object.extend(Element, { 846 visible: function(element) { 847 return $(element).style.display != 'none'; 848 }, 849 850 toggle: function() { 851 for (var i = 0; i < arguments.length; i++) { 852 var element = $(arguments[i]); 853 Element[Element.visible(element) ? 'hide' : 'show'](element); 854 } 855 }, 856 857 hide: function() { 858 for (var i = 0; i < arguments.length; i++) { 859 var element = $(arguments[i]); 860 element.style.display = 'none'; 861 } 862 }, 863 864 show: function() { 865 for (var i = 0; i < arguments.length; i++) { 866 var element = $(arguments[i]); 867 element.style.display = ''; 868 } 869 }, 870 871 remove: function(element) { 872 element = $(element); 873 element.parentNode.removeChild(element); 874 }, 875 876 update: function(element, html) { 877 $(element).innerHTML = html.stripScripts(); 878 setTimeout(function() {html.evalScripts()}, 10); 879 }, 880 881 getHeight: function(element) { 882 element = $(element); 883 return element.offsetHeight; 884 }, 885 886 classNames: function(element) { 887 return new Element.ClassNames(element); 888 }, 889 890 hasClassName: function(element, className) { 891 if (!(element = $(element))) return; 892 return Element.classNames(element).include(className); 893 }, 894 895 addClassName: function(element, className) { 896 if (!(element = $(element))) return; 897 return Element.classNames(element).add(className); 898 }, 899 900 removeClassName: function(element, className) { 901 if (!(element = $(element))) return; 902 return Element.classNames(element).remove(className); 903 }, 904 905 // removes whitespace-only text node children 906 cleanWhitespace: function(element) { 907 element = $(element); 908 for (var i = 0; i < element.childNodes.length; i++) { 909 var node = element.childNodes[i]; 910 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 911 Element.remove(node); 912 } 913 }, 914 915 find: function(element, what) { 916 element = $(element)[what]; 917 while (element.nodeType != 1) element = element[what]; 918 return element; 919 }, 920 921 empty: function(element) { 922 return $(element).innerHTML.match(/^\s*$/); 923 }, 924 925 scrollTo: function(element) { 926 element = $(element); 927 var x = element.x ? element.x : element.offsetLeft, 928 y = element.y ? element.y : element.offsetTop; 929 window.scrollTo(x, y); 930 }, 931 932 getStyle: function(element, style) { 933 element = $(element); 934 var value = element.style[style.camelize()]; 935 if (!value) { 936 if (document.defaultView && document.defaultView.getComputedStyle) { 937 var css = document.defaultView.getComputedStyle(element, null); 938 value = css ? css.getPropertyValue(style) : null; 939 } else if (element.currentStyle) { 940 value = element.currentStyle[style.camelize()]; 941 } 942 } 943 944 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) 945 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; 946 947 return value == 'auto' ? null : value; 948 }, 949 950 setStyle: function(element, style) { 951 element = $(element); 952 for (name in style) 953 element.style[name.camelize()] = style[name]; 954 }, 955 956 getDimensions: function(element) { 957 element = $(element); 958 if (Element.getStyle(element, 'display') != 'none') 959 return {width: element.offsetWidth, height: element.offsetHeight}; 960 961 // All *Width and *Height properties give 0 on elements with display none, 962 // so enable the element temporarily 963 var els = element.style; 964 var originalVisibility = els.visibility; 965 var originalPosition = els.position; 966 els.visibility = 'hidden'; 967 els.position = 'absolute'; 968 els.display = ''; 969 var originalWidth = element.clientWidth; 970 var originalHeight = element.clientHeight; 971 els.display = 'none'; 972 els.position = originalPosition; 973 els.visibility = originalVisibility; 974 return {width: originalWidth, height: originalHeight}; 975 }, 976 977 makePositioned: function(element) { 978 element = $(element); 979 var pos = Element.getStyle(element, 'position'); 980 if (pos == 'static' || !pos) { 981 element._madePositioned = true; 982 element.style.position = 'relative'; 983 // Opera returns the offset relative to the positioning context, when an 984 // element is position relative but top and left have not been defined 985 if (window.opera) { 986 element.style.top = 0; 987 element.style.left = 0; 988 } 989 } 990 }, 991 992 undoPositioned: function(element) { 993 element = $(element); 994 if (element._madePositioned) { 995 element._madePositioned = undefined; 996 element.style.position = 997 element.style.top = 998 element.style.left = 999 element.style.bottom = 1000 element.style.right = ''; 1001 } 1002 }, 1003 1004 makeClipping: function(element) { 1005 element = $(element); 1006 if (element._overflow) return; 1007 element._overflow = element.style.overflow; 1008 if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') 1009 element.style.overflow = 'hidden'; 1010 }, 1011 1012 undoClipping: function(element) { 1013 element = $(element); 1014 if (element._overflow) return; 1015 element.style.overflow = element._overflow; 1016 element._overflow = undefined; 1017 } 1018 }); 1019 1020 var Toggle = new Object(); 1021 Toggle.display = Element.toggle; 1022 1023 /*--------------------------------------------------------------------------*/ 1024 1025 Abstract.Insertion = function(adjacency) { 1026 this.adjacency = adjacency; 1027 } 1028 1029 Abstract.Insertion.prototype = { 1030 initialize: function(element, content) { 1031 this.element = $(element); 1032 this.content = content.stripScripts(); 1033 1034 if (this.adjacency && this.element.insertAdjacentHTML) { 1035 try { 1036 this.element.insertAdjacentHTML(this.adjacency, this.content); 1037 } catch (e) { 1038 if (this.element.tagName.toLowerCase() == 'tbody') { 1039 this.insertContent(this.contentFromAnonymousTable()); 1040 } else { 1041 throw e; 1042 } 1043 } 1044 } else { 1045 this.range = this.element.ownerDocument.createRange(); 1046 if (this.initializeRange) this.initializeRange(); 1047 this.insertContent([this.range.createContextualFragment(this.content)]); 1048 } 1049 1050 setTimeout(function() {content.evalScripts()}, 10); 1051 }, 1052 1053 contentFromAnonymousTable: function() { 1054 var div = document.createElement('div'); 1055 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 1056 return $A(div.childNodes[0].childNodes[0].childNodes); 1057 } 1058 } 1059 1060 var Insertion = new Object(); 1061 1062 Insertion.Before = Class.create(); 1063 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 1064 initializeRange: function() { 1065 this.range.setStartBefore(this.element); 1066 }, 1067 1068 insertContent: function(fragments) { 1069 fragments.each((function(fragment) { 1070 this.element.parentNode.insertBefore(fragment, this.element); 1071 }).bind(this)); 1072 } 1073 }); 1074 1075 Insertion.Top = Class.create(); 1076 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 1077 initializeRange: function() { 1078 this.range.selectNodeContents(this.element); 1079 this.range.collapse(true); 1080 }, 1081 1082 insertContent: function(fragments) { 1083 fragments.reverse(false).each((function(fragment) { 1084 this.element.insertBefore(fragment, this.element.firstChild); 1085 }).bind(this)); 1086 } 1087 }); 1088 1089 Insertion.Bottom = Class.create(); 1090 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 1091 initializeRange: function() { 1092 this.range.selectNodeContents(this.element); 1093 this.range.collapse(this.element); 1094 }, 1095 1096 insertContent: function(fragments) { 1097 fragments.each((function(fragment) { 1098 this.element.appendChild(fragment); 1099 }).bind(this)); 1100 } 1101 }); 1102 1103 Insertion.After = Class.create(); 1104 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 1105 initializeRange: function() { 1106 this.range.setStartAfter(this.element); 1107 }, 1108 1109 insertContent: function(fragments) { 1110 fragments.each((function(fragment) { 1111 this.element.parentNode.insertBefore(fragment, 1112 this.element.nextSibling); 1113 }).bind(this)); 1114 } 1115 }); 1116 1117 /*--------------------------------------------------------------------------*/ 1118 1119 Element.ClassNames = Class.create(); 1120 Element.ClassNames.prototype = { 1121 initialize: function(element) { 1122 this.element = $(element); 1123 }, 1124 1125 _each: function(iterator) { 1126 this.element.className.split(/\s+/).select(function(name) { 1127 return name.length > 0; 1128 })._each(iterator); 1129 }, 1130 1131 set: function(className) { 1132 this.element.className = className; 1133 }, 1134 1135 add: function(classNameToAdd) { 1136 if (this.include(classNameToAdd)) return; 1137 this.set(this.toArray().concat(classNameToAdd).join(' ')); 1138 }, 1139 1140 remove: function(classNameToRemove) { 1141 if (!this.include(classNameToRemove)) return; 1142 this.set(this.select(function(className) { 1143 return className != classNameToRemove; 1144 }).join(' ')); 1145 }, 1146 1147 toString: function() { 1148 return this.toArray().join(' '); 1149 } 1150 } 1151 1152 Object.extend(Element.ClassNames.prototype, Enumerable); 1153 var Field = { 1154 clear: function() { 1155 for (var i = 0; i < arguments.length; i++) 1156 $(arguments[i]).value = ''; 1157 }, 1158 1159 focus: function(element) { 1160 $(element).focus(); 1161 }, 1162 1163 present: function() { 1164 for (var i = 0; i < arguments.length; i++) 1165 if ($(arguments[i]).value == '') return false; 1166 return true; 1167 }, 1168 1169 select: function(element) { 1170 $(element).select(); 1171 }, 1172 1173 activate: function(element) { 1174 element = $(element); 1175 element.focus(); 1176 if (element.select) 1177 element.select(); 1178 } 1179 } 1180 1181 /*--------------------------------------------------------------------------*/ 1182 1183 var Form = { 1184 serialize: function(form) { 1185 var elements = Form.getElements($(form)); 1186 var queryComponents = new Array(); 1187 1188 for (var i = 0; i < elements.length; i++) { 1189 var queryComponent = Form.Element.serialize(elements[i]); 1190 if (queryComponent) 1191 queryComponents.push(queryComponent); 1192 } 1193 1194 return queryComponents.join('&'); 1195 }, 1196 1197 getElements: function(form) { 1198 form = $(form); 1199 var elements = new Array(); 1200 1201 for (tagName in Form.Element.Serializers) { 1202 var tagElements = form.getElementsByTagName(tagName); 1203 for (var j = 0; j < tagElements.length; j++) 1204 elements.push(tagElements[j]); 1205 } 1206 return elements; 1207 }, 1208 1209 getInputs: function(form, typeName, name) { 1210 form = $(form); 1211 var inputs = form.getElementsByTagName('input'); 1212 1213 if (!typeName && !name) 1214 return inputs; 1215 1216 var matchingInputs = new Array(); 1217 for (var i = 0; i < inputs.length; i++) { 1218 var input = inputs[i]; 1219 if ((typeName && input.type != typeName) || 1220 (name && input.name != name)) 1221 continue; 1222 matchingInputs.push(input); 1223 } 1224 1225 return matchingInputs; 1226 }, 1227 1228 disable: function(form) { 1229 var elements = Form.getElements(form); 1230 for (var i = 0; i < elements.length; i++) { 1231 var element = elements[i]; 1232 element.blur(); 1233 element.disabled = 'true'; 1234 } 1235 }, 1236 1237 enable: function(form) { 1238 var elements = Form.getElements(form); 1239 for (var i = 0; i < elements.length; i++) { 1240 var element = elements[i]; 1241 element.disabled = ''; 1242 } 1243 }, 1244 1245 findFirstElement: function(form) { 1246 return Form.getElements(form).find(function(element) { 1247 return element.type != 'hidden' && !element.disabled && 1248 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 1249 }); 1250 }, 1251 1252 focusFirstElement: function(form) { 1253 Field.activate(Form.findFirstElement(form)); 1254 }, 1255 1256 reset: function(form) { 1257 $(form).reset(); 1258 } 1259 } 1260 1261 Form.Element = { 1262 serialize: function(element) { 1263 element = $(element); 1264 var method = element.tagName.toLowerCase(); 1265 var parameter = Form.Element.Serializers[method](element); 1266 1267 if (parameter) { 1268 var key = encodeURIComponent(parameter[0]); 1269 if (key.length == 0) return; 1270 1271 if (parameter[1].constructor != Array) 1272 parameter[1] = [parameter[1]]; 1273 1274 return parameter[1].map(function(value) { 1275 return key + '=' + encodeURIComponent(value); 1276 }).join('&'); 1277 } 1278 }, 1279 1280 getValue: function(element) { 1281 element = $(element); 1282 var method = element.tagName.toLowerCase(); 1283 var parameter = Form.Element.Serializers[method](element); 1284 1285 if (parameter) 1286 return parameter[1]; 1287 } 1288 } 1289 1290 Form.Element.Serializers = { 1291 input: function(element) { 1292 switch (element.type.toLowerCase()) { 1293 case 'submit': 1294 case 'hidden': 1295 case 'password': 1296 case 'text': 1297 return Form.Element.Serializers.textarea(element); 1298 case 'checkbox': 1299 case 'radio': 1300 return Form.Element.Serializers.inputSelector(element); 1301 } 1302 return false; 1303 }, 1304 1305 inputSelector: function(element) { 1306 if (element.checked) 1307 return [element.name, element.value]; 1308 }, 1309 1310 textarea: function(element) { 1311 return [element.name, element.value]; 1312 }, 1313 1314 select: function(element) { 1315 return Form.Element.Serializers[element.type == 'select-one' ? 1316 'selectOne' : 'selectMany'](element); 1317 }, 1318 1319 selectOne: function(element) { 1320 var value = '', opt, index = element.selectedIndex; 1321 if (index >= 0) { 1322 opt = element.options[index]; 1323 value = opt.value; 1324 if (!value && !('value' in opt)) 1325 value = opt.text; 1326 } 1327 return [element.name, value]; 1328 }, 1329 1330 selectMany: function(element) { 1331 var value = new Array(); 1332 for (var i = 0; i < element.length; i++) { 1333 var opt = element.options[i]; 1334 if (opt.selected) { 1335 var optValue = opt.value; 1336 if (!optValue && !('value' in opt)) 1337 optValue = opt.text; 1338 value.push(optValue); 1339 } 1340 } 1341 return [element.name, value]; 1342 } 1343 } 1344 1345 /*--------------------------------------------------------------------------*/ 1346 1347 var $F = Form.Element.getValue; 1348 1349 /*--------------------------------------------------------------------------*/ 1350 1351 Abstract.TimedObserver = function() {} 1352 Abstract.TimedObserver.prototype = { 1353 initialize: function(element, frequency, callback) { 1354 this.frequency = frequency; 1355 this.element = $(element); 1356 this.callback = callback; 1357 1358 this.lastValue = this.getValue(); 1359 this.registerCallback(); 1360 }, 1361 1362 registerCallback: function() { 1363 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 1364 }, 1365 1366 onTimerEvent: function() { 1367 var value = this.getValue(); 1368 if (this.lastValue != value) { 1369 this.callback(this.element, value); 1370 this.lastValue = value; 1371 } 1372 } 1373 } 1374 1375 Form.Element.Observer = Class.create(); 1376 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 1377 getValue: function() { 1378 return Form.Element.getValue(this.element); 1379 } 1380 }); 1381 1382 Form.Observer = Class.create(); 1383 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 1384 getValue: function() { 1385 return Form.serialize(this.element); 1386 } 1387 }); 1388 1389 /*--------------------------------------------------------------------------*/ 1390 1391 Abstract.EventObserver = function() {} 1392 Abstract.EventObserver.prototype = { 1393 initialize: function(element, callback) { 1394 this.element = $(element); 1395 this.callback = callback; 1396 1397 this.lastValue = this.getValue(); 1398 if (this.element.tagName.toLowerCase() == 'form') 1399 this.registerFormCallbacks(); 1400 else 1401 this.registerCallback(this.element); 1402 }, 1403 1404 onElementEvent: function() { 1405 var value = this.getValue(); 1406 if (this.lastValue != value) { 1407 this.callback(this.element, value); 1408 this.lastValue = value; 1409 } 1410 }, 1411 1412 registerFormCallbacks: function() { 1413 var elements = Form.getElements(this.element); 1414 for (var i = 0; i < elements.length; i++) 1415 this.registerCallback(elements[i]); 1416 }, 1417 1418 registerCallback: function(element) { 1419 if (element.type) { 1420 switch (element.type.toLowerCase()) { 1421 case 'checkbox': 1422 case 'radio': 1423 Event.observe(element, 'click', this.onElementEvent.bind(this)); 1424 break; 1425 case 'password': 1426 case 'text': 1427 case 'textarea': 1428 case 'select-one': 1429 case 'select-multiple': 1430 Event.observe(element, 'change', this.onElementEvent.bind(this)); 1431 break; 1432 } 1433 } 1434 } 1435 } 1436 1437 Form.Element.EventObserver = Class.create(); 1438 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 1439 getValue: function() { 1440 return Form.Element.getValue(this.element); 1441 } 1442 }); 1443 1444 Form.EventObserver = Class.create(); 1445 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 1446 getValue: function() { 1447 return Form.serialize(this.element); 1448 } 1449 }); 1450 if (!window.Event) { 1451 var Event = new Object(); 1452 } 1453 1454 Object.extend(Event, { 1455 KEY_BACKSPACE: 8, 1456 KEY_TAB: 9, 1457 KEY_RETURN: 13, 1458 KEY_ESC: 27, 1459 KEY_LEFT: 37, 1460 KEY_UP: 38, 1461 KEY_RIGHT: 39, 1462 KEY_DOWN: 40, 1463 KEY_DELETE: 46, 1464 1465 element: function(event) { 1466 return event.target || event.srcElement; 1467 }, 1468 1469 isLeftClick: function(event) { 1470 return (((event.which) && (event.which == 1)) || 1471 ((event.button) && (event.button == 1))); 1472 }, 1473 1474 pointerX: function(event) { 1475 return event.pageX || (event.clientX + 1476 (document.documentElement.scrollLeft || document.body.scrollLeft)); 1477 }, 1478 1479 pointerY: function(event) { 1480 return event.pageY || (event.clientY + 1481 (document.documentElement.scrollTop || document.body.scrollTop)); 1482 }, 1483 1484 stop: function(event) { 1485 if (event.preventDefault) { 1486 event.preventDefault(); 1487 event.stopPropagation(); 1488 } else { 1489 event.returnValue = false; 1490 event.cancelBubble = true; 1491 } 1492 }, 1493 1494 // find the first node with the given tagName, starting from the 1495 // node the event was triggered on; traverses the DOM upwards 1496 findElement: function(event, tagName) { 1497 var element = Event.element(event); 1498 while (element.parentNode && (!element.tagName || 1499 (element.tagName.toUpperCase() != tagName.toUpperCase()))) 1500 element = element.parentNode; 1501 return element; 1502 }, 1503 1504 observers: false, 1505 1506 _observeAndCache: function(element, name, observer, useCapture) { 1507 if (!this.observers) this.observers = []; 1508 if (element.addEventListener) { 1509 this.observers.push([element, name, observer, useCapture]); 1510 element.addEventListener(name, observer, useCapture); 1511 } else if (element.attachEvent) { 1512 this.observers.push([element, name, observer, useCapture]); 1513 element.attachEvent('on' + name, observer); 1514 } 1515 }, 1516 1517 unloadCache: function() { 1518 if (!Event.observers) return; 1519 for (var i = 0; i < Event.observers.length; i++) { 1520 Event.stopObserving.apply(this, Event.observers[i]); 1521 Event.observers[i][0] = null; 1522 } 1523 Event.observers = false; 1524 }, 1525 1526 observe: function(element, name, observer, useCapture) { 1527 var element = $(element); 1528 useCapture = useCapture || false; 1529 1530 if (name == 'keypress' && 1531 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1532 || element.attachEvent)) 1533 name = 'keydown'; 1534 1535 this._observeAndCache(element, name, observer, useCapture); 1536 }, 1537 1538 stopObserving: function(element, name, observer, useCapture) { 1539 var element = $(element); 1540 useCapture = useCapture || false; 1541 1542 if (name == 'keypress' && 1543 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1544 || element.detachEvent)) 1545 name = 'keydown'; 1546 1547 if (element.removeEventListener) { 1548 element.removeEventListener(name, observer, useCapture); 1549 } else if (element.detachEvent) { 1550 element.detachEvent('on' + name, observer); 1551 } 1552 } 1553 }); 1554 1555 /* prevent memory leaks in IE */ 1556 Event.observe(window, 'unload', Event.unloadCache, false); 1557 var Position = { 1558 // set to true if needed, warning: firefox performance problems 1559 // NOT neeeded for page scrolling, only if draggable contained in 1560 // scrollable elements 1561 includeScrollOffsets: false, 1562 1563 // must be called before calling withinIncludingScrolloffset, every time the 1564 // page is scrolled 1565 prepare: function() { 1566 this.deltaX = window.pageXOffset 1567 || document.documentElement.scrollLeft 1568 || document.body.scrollLeft 1569 || 0; 1570 this.deltaY = window.pageYOffset 1571 || document.documentElement.scrollTop 1572 || document.body.scrollTop 1573 || 0; 1574 }, 1575 1576 realOffset: function(element) { 1577 var valueT = 0, valueL = 0; 1578 do { 1579 valueT += element.scrollTop || 0; 1580 valueL += element.scrollLeft || 0; 1581 element = element.parentNode; 1582 } while (element); 1583 return [valueL, valueT]; 1584 }, 1585 1586 cumulativeOffset: function(element) { 1587 var valueT = 0, valueL = 0; 1588 do { 1589 valueT += element.offsetTop || 0; 1590 valueL += element.offsetLeft || 0; 1591 element = element.offsetParent; 1592 } while (element); 1593 return [valueL, valueT]; 1594 }, 1595 1596 positionedOffset: function(element) { 1597 var valueT = 0, valueL = 0; 1598 do { 1599 valueT += element.offsetTop || 0; 1600 valueL += element.offsetLeft || 0; 1601 element = element.offsetParent; 1602 if (element) { 1603 p = Element.getStyle(element, 'position'); 1604 if (p == 'relative' || p == 'absolute') break; 1605 } 1606 } while (element); 1607 return [valueL, valueT]; 1608 }, 1609 1610 offsetParent: function(element) { 1611 if (element.offsetParent) return element.offsetParent; 1612 if (element == document.body) return element; 1613 1614 while ((element = element.parentNode) && element != document.body) 1615 if (Element.getStyle(element, 'position') != 'static') 1616 return element; 1617 1618 return document.body; 1619 }, 1620 1621 // caches x/y coordinate pair to use with overlap 1622 within: function(element, x, y) { 1623 if (this.includeScrollOffsets) 1624 return this.withinIncludingScrolloffsets(element, x, y); 1625 this.xcomp = x; 1626 this.ycomp = y; 1627 this.offset = this.cumulativeOffset(element); 1628 1629 return (y >= this.offset[1] && 1630 y < this.offset[1] + element.offsetHeight && 1631 x >= this.offset[0] && 1632 x < this.offset[0] + element.offsetWidth); 1633 }, 1634 1635 withinIncludingScrolloffsets: function(element, x, y) { 1636 var offsetcache = this.realOffset(element); 1637 1638 this.xcomp = x + offsetcache[0] - this.deltaX; 1639 this.ycomp = y + offsetcache[1] - this.deltaY; 1640 this.offset = this.cumulativeOffset(element); 1641 1642 return (this.ycomp >= this.offset[1] && 1643 this.ycomp < this.offset[1] + element.offsetHeight && 1644 this.xcomp >= this.offset[0] && 1645 this.xcomp < this.offset[0] + element.offsetWidth); 1646 }, 1647 1648 // within must be called directly before 1649 overlap: function(mode, element) { 1650 if (!mode) return 0; 1651 if (mode == 'vertical') 1652 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 1653 element.offsetHeight; 1654 if (mode == 'horizontal') 1655 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 1656 element.offsetWidth; 1657 }, 1658 1659 clone: function(source, target) { 1660 source = $(source); 1661 target = $(target); 1662 target.style.position = 'absolute'; 1663 var offsets = this.cumulativeOffset(source); 1664 target.style.top = offsets[1] + 'px'; 1665 target.style.left = offsets[0] + 'px'; 1666 target.style.width = source.offsetWidth + 'px'; 1667 target.style.height = source.offsetHeight + 'px'; 1668 }, 1669 1670 page: function(forElement) { 1671 var valueT = 0, valueL = 0; 1672 1673 var element = forElement; 1674 do { 1675 valueT += element.offsetTop || 0; 1676 valueL += element.offsetLeft || 0; 1677 1678 // Safari fix 1679 if (element.offsetParent==document.body) 1680 if (Element.getStyle(element,'position')=='absolute') break; 1681 1682 } while (element = element.offsetParent); 1683 1684 element = forElement; 1685 do { 1686 valueT -= element.scrollTop || 0; 1687 valueL -= element.scrollLeft || 0; 1688 } while (element = element.parentNode); 1689 1690 return [valueL, valueT]; 1691 }, 1692 1693 clone: function(source, target) { 1694 var options = Object.extend({ 1695 setLeft: true, 1696 setTop: true, 1697 setWidth: true, 1698 setHeight: true, 1699 offsetTop: 0, 1700 offsetLeft: 0 1701 }, arguments[2] || {}) 1702 1703 // find page position of source 1704 source = $(source); 1705 var p = Position.page(source); 1706 1707 // find coordinate system to use 1708 target = $(target); 1709 var delta = [0, 0]; 1710 var parent = null; 1711 // delta [0,0] will do fine with position: fixed elements, 1712 // position:absolute needs offsetParent deltas 1713 if (Element.getStyle(target,'position') == 'absolute') { 1714 parent = Position.offsetParent(target); 1715 delta = Position.page(parent); 1716 } 1717 1718 // correct by body offsets (fixes Safari) 1719 if (parent == document.body) { 1720 delta[0] -= document.body.offsetLeft; 1721 delta[1] -= document.body.offsetTop; 1722 } 1723 1724 // set position 1725 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 1726 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 1727 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; 1728 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; 1729 }, 1730 1731 absolutize: function(element) { 1732 element = $(element); 1733 if (element.style.position == 'absolute') return; 1734 Position.prepare(); 1735 1736 var offsets = Position.positionedOffset(element); 1737 var top = offsets[1]; 1738 var left = offsets[0]; 1739 var width = element.clientWidth; 1740 var height = element.clientHeight; 1741 1742 element._originalLeft = left - parseFloat(element.style.left || 0); 1743 element._originalTop = top - parseFloat(element.style.top || 0); 1744 element._originalWidth = element.style.width; 1745 element._originalHeight = element.style.height; 1746 1747 element.style.position = 'absolute'; 1748 element.style.top = top + 'px';; 1749 element.style.left = left + 'px';; 1750 element.style.width = width + 'px';; 1751 element.style.height = height + 'px';; 1752 }, 1753 1754 relativize: function(element) { 1755 element = $(element); 1756 if (element.style.position == 'relative') return; 1757 Position.prepare(); 1758 1759 element.style.position = 'relative'; 1760 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 1761 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 1762 1763 element.style.top = top + 'px'; 1764 element.style.left = left + 'px'; 1765 element.style.height = element._originalHeight; 1766 element.style.width = element._originalWidth; 1767 } 1768 } 1769 1770 // Safari returns margins on body which is incorrect if the child is absolutely 1771 // positioned. For performance reasons, redefine Position.cumulativeOffset for 1772 // KHTML/WebKit only. 1773 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 1774 Position.cumulativeOffset = function(element) { 1775 var valueT = 0, valueL = 0; 1776 do { 1777 valueT += element.offsetTop || 0; 1778 valueL += element.offsetLeft || 0; 1779 if (element.offsetParent == document.body) 1780 if (Element.getStyle(element, 'position') == 'absolute') break; 1781 1782 element = element.offsetParent; 1783 } while (element); 1784 1785 return [valueL, valueT]; 1786 } 1787 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 21:04:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |