[ Index ] |
|
Code source de PRADO 3.0.6 |
1 /* Prototype JavaScript framework, version <%= PROTOTYPE_VERSION %> 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.50', 11 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 12 13 emptyFunction: function() {}, 14 K: function(x) {return x} 15 } 16 17 /* 18 <%= include 'base.js', 'string.js' %> 19 20 <%= include 'enumerable.js', 'array.js', 'hash.js', 'range.js' %> 21 22 <%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'position.js' %> 23 24 */ 25 26 var Class = { 27 create: function() { 28 return function() { 29 this.initialize.apply(this, arguments); 30 } 31 } 32 } 33 34 var Abstract = new Object(); 35 36 Object.extend = function(destination, source) { 37 for (var property in source) { 38 destination[property] = source[property]; 39 } 40 return destination; 41 } 42 43 Object.inspect = function(object) { 44 try { 45 if (object == undefined) return 'undefined'; 46 if (object == null) return 'null'; 47 return object.inspect ? object.inspect() : object.toString(); 48 } catch (e) { 49 if (e instanceof RangeError) return '...'; 50 throw e; 51 } 52 } 53 54 Function.prototype.bind = function() { 55 var __method = this, args = $A(arguments), object = args.shift(); 56 return function() { 57 return __method.apply(object, args.concat($A(arguments))); 58 } 59 } 60 61 Function.prototype.bindAsEventListener = function(object) { 62 var __method = this; 63 return function(event) { 64 return __method.call(object, event || window.event); 65 } 66 } 67 68 Object.extend(Number.prototype, { 69 toColorPart: function() { 70 var digits = this.toString(16); 71 if (this < 16) return '0' + digits; 72 return digits; 73 }, 74 75 succ: function() { 76 return this + 1; 77 }, 78 79 times: function(iterator) { 80 $R(0, this, true).each(iterator); 81 return this; 82 } 83 }); 84 85 var Try = { 86 these: function() { 87 var returnValue; 88 89 for (var i = 0; i < arguments.length; i++) { 90 var lambda = arguments[i]; 91 try { 92 returnValue = lambda(); 93 break; 94 } catch (e) {} 95 } 96 97 return returnValue; 98 } 99 } 100 101 /*--------------------------------------------------------------------------*/ 102 103 var PeriodicalExecuter = Class.create(); 104 PeriodicalExecuter.prototype = { 105 initialize: function(callback, frequency) { 106 this.callback = callback; 107 this.frequency = frequency; 108 this.currentlyExecuting = false; 109 110 this.registerCallback(); 111 }, 112 113 registerCallback: function() { 114 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 115 }, 116 117 onTimerEvent: function() { 118 if (!this.currentlyExecuting) { 119 try { 120 this.currentlyExecuting = true; 121 this.callback(); 122 } finally { 123 this.currentlyExecuting = false; 124 } 125 } 126 } 127 } 128 129 130 131 /** 132 * Similar to bindAsEventLister, but takes additional arguments. 133 */ 134 Function.prototype.bindEvent = function() 135 { 136 var __method = this, args = $A(arguments), object = args.shift(); 137 return function(event) 138 { 139 return __method.apply(object, [event || window.event].concat(args)); 140 } 141 } 142 143 /** 144 * Creates a new function by copying function definition from 145 * the <tt>base</tt> and optional <tt>definition</tt>. 146 * @param function a base function to copy from. 147 * @param array additional definition 148 * @param function return a new function with definition from both 149 * <tt>base</tt> and <tt>definition</tt>. 150 */ 151 Class.extend = function(base, definition) 152 { 153 var component = Class.create(); 154 Object.extend(component.prototype, base.prototype); 155 if(definition) 156 Object.extend(component.prototype, definition); 157 return component; 158 } 159 160 Object.extend(String.prototype, { 161 gsub: function(pattern, replacement) { 162 var result = '', source = this, match; 163 replacement = arguments.callee.prepareReplacement(replacement); 164 165 while (source.length > 0) { 166 if (match = source.match(pattern)) { 167 result += source.slice(0, match.index); 168 result += (replacement(match) || '').toString(); 169 source = source.slice(match.index + match[0].length); 170 } else { 171 result += source, source = ''; 172 } 173 } 174 return result; 175 }, 176 177 sub: function(pattern, replacement, count) { 178 replacement = this.gsub.prepareReplacement(replacement); 179 count = count === undefined ? 1 : count; 180 181 return this.gsub(pattern, function(match) { 182 if (--count < 0) return match[0]; 183 return replacement(match); 184 }); 185 }, 186 187 scan: function(pattern, iterator) { 188 this.gsub(pattern, iterator); 189 return this; 190 }, 191 192 truncate: function(length, truncation) { 193 length = length || 30; 194 truncation = truncation === undefined ? '...' : truncation; 195 return this.length > length ? 196 this.slice(0, length - truncation.length) + truncation : this; 197 }, 198 199 strip: function() { 200 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 201 }, 202 203 stripTags: function() { 204 return this.replace(/<\/?[^>]+>/gi, ''); 205 }, 206 207 stripScripts: function() { 208 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 209 }, 210 211 extractScripts: function() { 212 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 213 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 214 return (this.match(matchAll) || []).map(function(scriptTag) { 215 return (scriptTag.match(matchOne) || ['', ''])[1]; 216 }); 217 }, 218 219 evalScripts: function() { 220 return this.extractScripts().map(function(script) { return eval(script) }); 221 }, 222 223 escapeHTML: function() { 224 var div = document.createElement('div'); 225 var text = document.createTextNode(this); 226 div.appendChild(text); 227 return div.innerHTML; 228 }, 229 230 unescapeHTML: function() { 231 var div = document.createElement('div'); 232 div.innerHTML = this.stripTags(); 233 return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; 234 }, 235 236 toQueryParams: function() { 237 var pairs = this.match(/^\??(.*)$/)[1].split('&'); 238 return pairs.inject({}, function(params, pairString) { 239 var pair = pairString.split('='); 240 params[pair[0]] = pair[1]; 241 return params; 242 }); 243 }, 244 245 toArray: function() { 246 return this.split(''); 247 }, 248 249 camelize: function() { 250 var oStringList = this.split('-'); 251 if (oStringList.length == 1) return oStringList[0]; 252 253 var camelizedString = this.indexOf('-') == 0 254 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 255 : oStringList[0]; 256 257 for (var i = 1, len = oStringList.length; i < len; i++) { 258 var s = oStringList[i]; 259 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 260 } 261 262 return camelizedString; 263 }, 264 265 inspect: function() { 266 return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; 267 } 268 }); 269 270 String.prototype.gsub.prepareReplacement = function(replacement) { 271 if (typeof replacement == 'function') return replacement; 272 var template = new Template(replacement); 273 return function(match) { return template.evaluate(match) }; 274 } 275 276 String.prototype.parseQuery = String.prototype.toQueryParams; 277 278 var Template = Class.create(); 279 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 280 Template.prototype = { 281 initialize: function(template, pattern) { 282 this.template = template.toString(); 283 this.pattern = pattern || Template.Pattern; 284 }, 285 286 evaluate: function(object) { 287 return this.template.gsub(this.pattern, function(match) { 288 var before = match[1]; 289 if (before == '\\') return match[2]; 290 return before + (object[match[3]] || '').toString(); 291 }); 292 } 293 } 294 295 296 /** 297 * @class String extensions 298 */ 299 Object.extend(String.prototype, { 300 /** 301 * @param {String} "left" to pad the string on the left, "right" to pad right. 302 * @param {Number} minimum string length. 303 * @param {String} character(s) to pad 304 * @return {String} padded character(s) on the left or right to satisfy minimum string length 305 */ 306 307 pad : function(side, len, chr) { 308 if (!chr) chr = ' '; 309 var s = this; 310 var left = side.toLowerCase()=='left'; 311 while (s.length<len) s = left? chr + s : s + chr; 312 return s; 313 }, 314 315 /** 316 * @param {Number} minimum string length. 317 * @param {String} character(s) to pad 318 * @return {String} padded character(s) on the left to satisfy minimum string length 319 */ 320 padLeft : function(len, chr) { 321 return this.pad('left',len,chr); 322 }, 323 324 /** 325 * @param {Number} minimum string length. 326 * @param {String} character(s) to pad 327 * @return {String} padded character(s) on the right to satisfy minimum string length 328 */ 329 padRight : function(len, chr) { 330 return this.pad('right',len,chr); 331 }, 332 333 /** 334 * @param {Number} minimum string length. 335 * @return {String} append zeros to the left to satisfy minimum string length. 336 */ 337 zerofill : function(len) { 338 return this.padLeft(len,'0'); 339 }, 340 341 /** 342 * @return {String} removed white spaces from both ends. 343 */ 344 trim : function() { 345 return this.replace(/^\s+|\s+$/g,''); 346 }, 347 348 /** 349 * @return {String} removed white spaces from the left end. 350 */ 351 trimLeft : function() { 352 return this.replace(/^\s+/,''); 353 }, 354 355 /** 356 * @return {String} removed white spaces from the right end. 357 */ 358 trimRight : function() { 359 return this.replace(/\s+$/,''); 360 }, 361 362 /** 363 * Convert period separated function names into a function reference. 364 * e.g. "Prado.AJAX.Callback.Action.setValue".toFunction() will return 365 * the actual function Prado.AJAX.Callback.Action.setValue() 366 * @return {Function} the corresponding function represented by the string. 367 */ 368 toFunction : function() 369 { 370 var commands = this.split(/\./); 371 var command = window; 372 commands.each(function(action) 373 { 374 if(command[new String(action)]) 375 command=command[new String(action)]; 376 }); 377 if(typeof(command) == "function") 378 return command; 379 else 380 { 381 if(typeof Logger != "undefined") 382 Logger.error("Missing function", this); 383 384 throw new Error ("Missing function '"+this+"'"); 385 } 386 }, 387 388 /** 389 * Convert a string into integer, returns null if not integer. 390 * @return {Number} null if string does not represent an integer. 391 */ 392 toInteger : function() 393 { 394 var exp = /^\s*[-\+]?\d+\s*$/; 395 if (this.match(exp) == null) 396 return null; 397 var num = parseInt(this, 10); 398 return (isNaN(num) ? null : num); 399 }, 400 401 /** 402 * Convert a string into a double/float value. <b>Internationalization 403 * is not supported</b> 404 * @param {String} the decimal character 405 * @return {Double} null if string does not represent a float value 406 */ 407 toDouble : function(decimalchar) 408 { 409 if(this.length <= 0) return null; 410 decimalchar = decimalchar || "."; 411 var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$"); 412 var m = this.match(exp); 413 414 if (m == null) 415 return null; 416 m[1] = m[1] || ""; 417 m[2] = m[2] || "0"; 418 m[4] = m[4] || "0"; 419 420 var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4]; 421 var num = parseFloat(cleanInput); 422 return (isNaN(num) ? null : num); 423 }, 424 425 /** 426 * Convert strings that represent a currency value (e.g. a float with grouping 427 * characters) to float. E.g. "10,000.50" will become "10000.50". The number 428 * of dicimal digits, grouping and decimal characters can be specified. 429 * <i>The currency input format is <b>very</b> strict, null will be returned if 430 * the pattern does not match</i>. 431 * @param {String} the grouping character, default is "," 432 * @param {Number} number of decimal digits 433 * @param {String} the decimal character, default is "." 434 * @type {Double} the currency value as float. 435 */ 436 toCurrency : function(groupchar, digits, decimalchar) 437 { 438 groupchar = groupchar || ","; 439 decimalchar = decimalchar || "."; 440 digits = typeof(digits) == "undefined" ? 2 : digits; 441 442 var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)" 443 + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "") 444 + "\\s*$"); 445 var m = this.match(exp); 446 if (m == null) 447 return null; 448 var intermed = m[2] + m[5] ; 449 var cleanInput = m[1] + intermed.replace( 450 new RegExp("(\\" + groupchar + ")", "g"), "") 451 + ((digits > 0) ? "." + m[7] : ""); 452 var num = parseFloat(cleanInput); 453 return (isNaN(num) ? null : num); 454 }, 455 456 /** 457 * Converts the string to a date by finding values that matches the 458 * date format pattern. 459 * @param string date format pattern, e.g. MM-dd-yyyy 460 * @return {Date} the date extracted from the string 461 */ 462 toDate : function(format) 463 { 464 return Date.SimpleParse(this, format); 465 } 466 }); 467 468 var $break = new Object(); 469 var $continue = new Object(); 470 471 var Enumerable = { 472 each: function(iterator) { 473 var index = 0; 474 try { 475 this._each(function(value) { 476 try { 477 iterator(value, index++); 478 } catch (e) { 479 if (e != $continue) throw e; 480 } 481 }); 482 } catch (e) { 483 if (e != $break) throw e; 484 } 485 }, 486 487 all: function(iterator) { 488 var result = true; 489 this.each(function(value, index) { 490 result = result && !!(iterator || Prototype.K)(value, index); 491 if (!result) throw $break; 492 }); 493 return result; 494 }, 495 496 any: function(iterator) { 497 var result = true; 498 this.each(function(value, index) { 499 if (result = !!(iterator || Prototype.K)(value, index)) 500 throw $break; 501 }); 502 return result; 503 }, 504 505 collect: function(iterator) { 506 var results = []; 507 this.each(function(value, index) { 508 results.push(iterator(value, index)); 509 }); 510 return results; 511 }, 512 513 detect: function (iterator) { 514 var result; 515 this.each(function(value, index) { 516 if (iterator(value, index)) { 517 result = value; 518 throw $break; 519 } 520 }); 521 return result; 522 }, 523 524 findAll: function(iterator) { 525 var results = []; 526 this.each(function(value, index) { 527 if (iterator(value, index)) 528 results.push(value); 529 }); 530 return results; 531 }, 532 533 grep: function(pattern, iterator) { 534 var results = []; 535 this.each(function(value, index) { 536 var stringValue = value.toString(); 537 if (stringValue.match(pattern)) 538 results.push((iterator || Prototype.K)(value, index)); 539 }) 540 return results; 541 }, 542 543 include: function(object) { 544 var found = false; 545 this.each(function(value) { 546 if (value == object) { 547 found = true; 548 throw $break; 549 } 550 }); 551 return found; 552 }, 553 554 inject: function(memo, iterator) { 555 this.each(function(value, index) { 556 memo = iterator(memo, value, index); 557 }); 558 return memo; 559 }, 560 561 invoke: function(method) { 562 var args = $A(arguments).slice(1); 563 return this.collect(function(value) { 564 return value[method].apply(value, args); 565 }); 566 }, 567 568 max: function(iterator) { 569 var result; 570 this.each(function(value, index) { 571 value = (iterator || Prototype.K)(value, index); 572 if (result == undefined || value >= result) 573 result = value; 574 }); 575 return result; 576 }, 577 578 min: function(iterator) { 579 var result; 580 this.each(function(value, index) { 581 value = (iterator || Prototype.K)(value, index); 582 if (result == undefined || value < result) 583 result = value; 584 }); 585 return result; 586 }, 587 588 partition: function(iterator) { 589 var trues = [], falses = []; 590 this.each(function(value, index) { 591 ((iterator || Prototype.K)(value, index) ? 592 trues : falses).push(value); 593 }); 594 return [trues, falses]; 595 }, 596 597 pluck: function(property) { 598 var results = []; 599 this.each(function(value, index) { 600 results.push(value[property]); 601 }); 602 return results; 603 }, 604 605 reject: function(iterator) { 606 var results = []; 607 this.each(function(value, index) { 608 if (!iterator(value, index)) 609 results.push(value); 610 }); 611 return results; 612 }, 613 614 sortBy: function(iterator) { 615 return this.collect(function(value, index) { 616 return {value: value, criteria: iterator(value, index)}; 617 }).sort(function(left, right) { 618 var a = left.criteria, b = right.criteria; 619 return a < b ? -1 : a > b ? 1 : 0; 620 }).pluck('value'); 621 }, 622 623 toArray: function() { 624 return this.collect(Prototype.K); 625 }, 626 627 zip: function() { 628 var iterator = Prototype.K, args = $A(arguments); 629 if (typeof args.last() == 'function') 630 iterator = args.pop(); 631 632 var collections = [this].concat(args).map($A); 633 return this.map(function(value, index) { 634 return iterator(collections.pluck(index)); 635 }); 636 }, 637 638 inspect: function() { 639 return '#<Enumerable:' + this.toArray().inspect() + '>'; 640 } 641 } 642 643 Object.extend(Enumerable, { 644 map: Enumerable.collect, 645 find: Enumerable.detect, 646 select: Enumerable.findAll, 647 member: Enumerable.include, 648 entries: Enumerable.toArray 649 }); 650 651 652 var $A = Array.from = function(iterable) { 653 if (!iterable) return []; 654 if (iterable.toArray) { 655 return iterable.toArray(); 656 } else { 657 var results = []; 658 for (var i = 0; i < iterable.length; i++) 659 results.push(iterable[i]); 660 return results; 661 } 662 } 663 664 Object.extend(Array.prototype, Enumerable); 665 666 if (!Array.prototype._reverse) 667 Array.prototype._reverse = Array.prototype.reverse; 668 669 Object.extend(Array.prototype, { 670 _each: function(iterator) { 671 for (var i = 0; i < this.length; i++) 672 iterator(this[i]); 673 }, 674 675 clear: function() { 676 this.length = 0; 677 return this; 678 }, 679 680 first: function() { 681 return this[0]; 682 }, 683 684 last: function() { 685 return this[this.length - 1]; 686 }, 687 688 compact: function() { 689 return this.select(function(value) { 690 return value != undefined || value != null; 691 }); 692 }, 693 694 flatten: function() { 695 return this.inject([], function(array, value) { 696 return array.concat(value && value.constructor == Array ? 697 value.flatten() : [value]); 698 }); 699 }, 700 701 without: function() { 702 var values = $A(arguments); 703 return this.select(function(value) { 704 return !values.include(value); 705 }); 706 }, 707 708 indexOf: function(object) { 709 for (var i = 0; i < this.length; i++) 710 if (this[i] == object) return i; 711 return -1; 712 }, 713 714 reverse: function(inline) { 715 return (inline !== false ? this : this.toArray())._reverse(); 716 }, 717 718 inspect: function() { 719 return '[' + this.map(Object.inspect).join(', ') + ']'; 720 } 721 }); 722 723 724 var Hash = { 725 _each: function(iterator) { 726 for (var key in this) { 727 var value = this[key]; 728 if (typeof value == 'function') continue; 729 730 var pair = [key, value]; 731 pair.key = key; 732 pair.value = value; 733 iterator(pair); 734 } 735 }, 736 737 keys: function() { 738 return this.pluck('key'); 739 }, 740 741 values: function() { 742 return this.pluck('value'); 743 }, 744 745 merge: function(hash) { 746 return $H(hash).inject($H(this), function(mergedHash, pair) { 747 mergedHash[pair.key] = pair.value; 748 return mergedHash; 749 }); 750 }, 751 752 toQueryString: function() { 753 return this.map(function(pair) { 754 return pair.map(encodeURIComponent).join('='); 755 }).join('&'); 756 }, 757 758 inspect: function() { 759 return '#<Hash:{' + this.map(function(pair) { 760 return pair.map(Object.inspect).join(': '); 761 }).join(', ') + '}>'; 762 } 763 } 764 765 function $H(object) { 766 var hash = Object.extend({}, object || {}); 767 Object.extend(hash, Enumerable); 768 Object.extend(hash, Hash); 769 return hash; 770 } 771 772 773 ObjectRange = Class.create(); 774 Object.extend(ObjectRange.prototype, Enumerable); 775 Object.extend(ObjectRange.prototype, { 776 initialize: function(start, end, exclusive) { 777 this.start = start; 778 this.end = end; 779 this.exclusive = exclusive; 780 }, 781 782 _each: function(iterator) { 783 var value = this.start; 784 do { 785 iterator(value); 786 value = value.succ(); 787 } while (this.include(value)); 788 }, 789 790 include: function(value) { 791 if (value < this.start) 792 return false; 793 if (this.exclusive) 794 return value < this.end; 795 return value <= this.end; 796 } 797 }); 798 799 var $R = function(start, end, exclusive) { 800 return new ObjectRange(start, end, exclusive); 801 } 802 803 function $() { 804 var results = [], element; 805 for (var i = 0; i < arguments.length; i++) { 806 element = arguments[i]; 807 if (typeof element == 'string') 808 element = document.getElementById(element); 809 results.push(Element.extend(element)); 810 } 811 return results.length < 2 ? results[0] : results; 812 } 813 814 document.getElementsByClassName = function(className, parentElement) { 815 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 816 return $A(children).inject([], function(elements, child) { 817 if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 818 elements.push(Element.extend(child)); 819 return elements; 820 }); 821 } 822 823 /*--------------------------------------------------------------------------*/ 824 825 if (!window.Element) 826 var Element = new Object(); 827 828 Element.extend = function(element) { 829 if (!element) return; 830 if (_nativeExtensions) return element; 831 832 if (!element._extended && element.tagName && element != window) { 833 var methods = Element.Methods, cache = Element.extend.cache; 834 for (property in methods) { 835 var value = methods[property]; 836 if (typeof value == 'function') 837 element[property] = cache.findOrStore(value); 838 } 839 } 840 841 element._extended = true; 842 return element; 843 } 844 845 Element.extend.cache = { 846 findOrStore: function(value) { 847 return this[value] = this[value] || function() { 848 return value.apply(null, [this].concat($A(arguments))); 849 } 850 } 851 } 852 853 Element.Methods = { 854 visible: function(element) { 855 return $(element).style.display != 'none'; 856 }, 857 858 toggle: function() { 859 for (var i = 0; i < arguments.length; i++) { 860 var element = $(arguments[i]); 861 Element[Element.visible(element) ? 'hide' : 'show'](element); 862 } 863 }, 864 865 hide: function() { 866 for (var i = 0; i < arguments.length; i++) { 867 var element = $(arguments[i]); 868 element.style.display = 'none'; 869 } 870 }, 871 872 show: function() { 873 for (var i = 0; i < arguments.length; i++) { 874 var element = $(arguments[i]); 875 element.style.display = ''; 876 } 877 }, 878 879 remove: function(element) { 880 element = $(element); 881 element.parentNode.removeChild(element); 882 }, 883 884 update: function(element, html) { 885 $(element).innerHTML = html.stripScripts(); 886 setTimeout(function() {html.evalScripts()}, 10); 887 }, 888 889 replace: function(element, html) { 890 element = $(element); 891 if (element.outerHTML) { 892 element.outerHTML = html.stripScripts(); 893 } else { 894 var range = element.ownerDocument.createRange(); 895 range.selectNodeContents(element); 896 element.parentNode.replaceChild( 897 range.createContextualFragment(html.stripScripts()), element); 898 } 899 setTimeout(function() {html.evalScripts()}, 10); 900 }, 901 902 getHeight: function(element) { 903 element = $(element); 904 return element.offsetHeight; 905 }, 906 907 classNames: function(element) { 908 return new Element.ClassNames(element); 909 }, 910 911 hasClassName: function(element, className) { 912 if (!(element = $(element))) return; 913 return Element.classNames(element).include(className); 914 }, 915 916 addClassName: function(element, className) { 917 if (!(element = $(element))) return; 918 return Element.classNames(element).add(className); 919 }, 920 921 removeClassName: function(element, className) { 922 if (!(element = $(element))) return; 923 return Element.classNames(element).remove(className); 924 }, 925 926 // removes whitespace-only text node children 927 cleanWhitespace: function(element) { 928 element = $(element); 929 for (var i = 0; i < element.childNodes.length; i++) { 930 var node = element.childNodes[i]; 931 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 932 Element.remove(node); 933 } 934 }, 935 936 empty: function(element) { 937 return $(element).innerHTML.match(/^\s*$/); 938 }, 939 940 childOf: function(element, ancestor) { 941 element = $(element), ancestor = $(ancestor); 942 while (element = element.parentNode) 943 if (element == ancestor) return true; 944 return false; 945 }, 946 947 scrollTo: function(element) { 948 element = $(element); 949 var x = element.x ? element.x : element.offsetLeft, 950 y = element.y ? element.y : element.offsetTop; 951 window.scrollTo(x, y); 952 }, 953 954 getStyle: function(element, style) { 955 element = $(element); 956 var value = element.style[style.camelize()]; 957 if (!value) { 958 if (document.defaultView && document.defaultView.getComputedStyle) { 959 var css = document.defaultView.getComputedStyle(element, null); 960 value = css ? css.getPropertyValue(style) : null; 961 } else if (element.currentStyle) { 962 value = element.currentStyle[style.camelize()]; 963 } 964 } 965 966 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) 967 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; 968 969 return value == 'auto' ? null : value; 970 }, 971 972 setStyle: function(element, style) { 973 element = $(element); 974 for (var name in style) 975 element.style[name.camelize()] = style[name]; 976 }, 977 978 getDimensions: function(element) { 979 element = $(element); 980 if (Element.getStyle(element, 'display') != 'none') 981 return {width: element.offsetWidth, height: element.offsetHeight}; 982 983 // All *Width and *Height properties give 0 on elements with display none, 984 // so enable the element temporarily 985 var els = element.style; 986 var originalVisibility = els.visibility; 987 var originalPosition = els.position; 988 els.visibility = 'hidden'; 989 els.position = 'absolute'; 990 els.display = ''; 991 var originalWidth = element.clientWidth; 992 var originalHeight = element.clientHeight; 993 els.display = 'none'; 994 els.position = originalPosition; 995 els.visibility = originalVisibility; 996 return {width: originalWidth, height: originalHeight}; 997 }, 998 999 makePositioned: function(element) { 1000 element = $(element); 1001 var pos = Element.getStyle(element, 'position'); 1002 if (pos == 'static' || !pos) { 1003 element._madePositioned = true; 1004 element.style.position = 'relative'; 1005 // Opera returns the offset relative to the positioning context, when an 1006 // element is position relative but top and left have not been defined 1007 if (window.opera) { 1008 element.style.top = 0; 1009 element.style.left = 0; 1010 } 1011 } 1012 }, 1013 1014 undoPositioned: function(element) { 1015 element = $(element); 1016 if (element._madePositioned) { 1017 element._madePositioned = undefined; 1018 element.style.position = 1019 element.style.top = 1020 element.style.left = 1021 element.style.bottom = 1022 element.style.right = ''; 1023 } 1024 }, 1025 1026 makeClipping: function(element) { 1027 element = $(element); 1028 if (element._overflow) return; 1029 element._overflow = element.style.overflow; 1030 if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') 1031 element.style.overflow = 'hidden'; 1032 }, 1033 1034 undoClipping: function(element) { 1035 element = $(element); 1036 if (element._overflow) return; 1037 element.style.overflow = element._overflow; 1038 element._overflow = undefined; 1039 } 1040 } 1041 1042 Object.extend(Element, Element.Methods); 1043 1044 var _nativeExtensions = false; 1045 1046 if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 1047 var HTMLElement = {} 1048 HTMLElement.prototype = document.createElement('div').__proto__; 1049 } 1050 1051 Element.addMethods = function(methods) { 1052 Object.extend(Element.Methods, methods || {}); 1053 1054 if(typeof HTMLElement != 'undefined') { 1055 var methods = Element.Methods, cache = Element.extend.cache; 1056 for (property in methods) { 1057 var value = methods[property]; 1058 if (typeof value == 'function') 1059 HTMLElement.prototype[property] = cache.findOrStore(value); 1060 } 1061 _nativeExtensions = true; 1062 } 1063 } 1064 1065 Element.addMethods(); 1066 1067 var Toggle = new Object(); 1068 Toggle.display = Element.toggle; 1069 1070 /*--------------------------------------------------------------------------*/ 1071 1072 Abstract.Insertion = function(adjacency) { 1073 this.adjacency = adjacency; 1074 } 1075 1076 Abstract.Insertion.prototype = { 1077 initialize: function(element, content) { 1078 this.element = $(element); 1079 this.content = content.stripScripts(); 1080 1081 if (this.adjacency && this.element.insertAdjacentHTML) { 1082 try { 1083 this.element.insertAdjacentHTML(this.adjacency, this.content); 1084 } catch (e) { 1085 var tagName = this.element.tagName.toLowerCase(); 1086 if (tagName == 'tbody' || tagName == 'tr') { 1087 this.insertContent(this.contentFromAnonymousTable()); 1088 } else { 1089 throw e; 1090 } 1091 } 1092 } else { 1093 this.range = this.element.ownerDocument.createRange(); 1094 if (this.initializeRange) this.initializeRange(); 1095 this.insertContent([this.range.createContextualFragment(this.content)]); 1096 } 1097 1098 setTimeout(function() {content.evalScripts()}, 10); 1099 }, 1100 1101 contentFromAnonymousTable: function() { 1102 var div = document.createElement('div'); 1103 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 1104 return $A(div.childNodes[0].childNodes[0].childNodes); 1105 } 1106 } 1107 1108 var Insertion = new Object(); 1109 1110 Insertion.Before = Class.create(); 1111 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 1112 initializeRange: function() { 1113 this.range.setStartBefore(this.element); 1114 }, 1115 1116 insertContent: function(fragments) { 1117 fragments.each((function(fragment) { 1118 this.element.parentNode.insertBefore(fragment, this.element); 1119 }).bind(this)); 1120 } 1121 }); 1122 1123 Insertion.Top = Class.create(); 1124 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 1125 initializeRange: function() { 1126 this.range.selectNodeContents(this.element); 1127 this.range.collapse(true); 1128 }, 1129 1130 insertContent: function(fragments) { 1131 fragments.reverse(false).each((function(fragment) { 1132 this.element.insertBefore(fragment, this.element.firstChild); 1133 }).bind(this)); 1134 } 1135 }); 1136 1137 Insertion.Bottom = Class.create(); 1138 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 1139 initializeRange: function() { 1140 this.range.selectNodeContents(this.element); 1141 this.range.collapse(this.element); 1142 }, 1143 1144 insertContent: function(fragments) { 1145 fragments.each((function(fragment) { 1146 this.element.appendChild(fragment); 1147 }).bind(this)); 1148 } 1149 }); 1150 1151 Insertion.After = Class.create(); 1152 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 1153 initializeRange: function() { 1154 this.range.setStartAfter(this.element); 1155 }, 1156 1157 insertContent: function(fragments) { 1158 fragments.each((function(fragment) { 1159 this.element.parentNode.insertBefore(fragment, 1160 this.element.nextSibling); 1161 }).bind(this)); 1162 } 1163 }); 1164 1165 /*--------------------------------------------------------------------------*/ 1166 1167 Element.ClassNames = Class.create(); 1168 Element.ClassNames.prototype = { 1169 initialize: function(element) { 1170 this.element = $(element); 1171 }, 1172 1173 _each: function(iterator) { 1174 this.element.className.split(/\s+/).select(function(name) { 1175 return name.length > 0; 1176 })._each(iterator); 1177 }, 1178 1179 set: function(className) { 1180 this.element.className = className; 1181 }, 1182 1183 add: function(classNameToAdd) { 1184 if (this.include(classNameToAdd)) return; 1185 this.set(this.toArray().concat(classNameToAdd).join(' ')); 1186 }, 1187 1188 remove: function(classNameToRemove) { 1189 if (!this.include(classNameToRemove)) return; 1190 this.set(this.select(function(className) { 1191 return className != classNameToRemove; 1192 }).join(' ')); 1193 }, 1194 1195 toString: function() { 1196 return this.toArray().join(' '); 1197 } 1198 } 1199 1200 Object.extend(Element.ClassNames.prototype, Enumerable); 1201 1202 1203 var Field = { 1204 clear: function() { 1205 for (var i = 0; i < arguments.length; i++) 1206 $(arguments[i]).value = ''; 1207 }, 1208 1209 focus: function(element) { 1210 $(element).focus(); 1211 }, 1212 1213 present: function() { 1214 for (var i = 0; i < arguments.length; i++) 1215 if ($(arguments[i]).value == '') return false; 1216 return true; 1217 }, 1218 1219 select: function(element) { 1220 $(element).select(); 1221 }, 1222 1223 activate: function(element) { 1224 element = $(element); 1225 element.focus(); 1226 if (element.select) 1227 element.select(); 1228 } 1229 } 1230 1231 /*--------------------------------------------------------------------------*/ 1232 1233 var Form = { 1234 serialize: function(form) { 1235 var elements = Form.getElements($(form)); 1236 var queryComponents = new Array(); 1237 1238 for (var i = 0; i < elements.length; i++) { 1239 var queryComponent = Form.Element.serialize(elements[i]); 1240 if (queryComponent) 1241 queryComponents.push(queryComponent); 1242 } 1243 1244 return queryComponents.join('&'); 1245 }, 1246 1247 getElements: function(form) { 1248 form = $(form); 1249 var elements = new Array(); 1250 1251 for (var tagName in Form.Element.Serializers) { 1252 var tagElements = form.getElementsByTagName(tagName); 1253 for (var j = 0; j < tagElements.length; j++) 1254 elements.push(tagElements[j]); 1255 } 1256 return elements; 1257 }, 1258 1259 getInputs: function(form, typeName, name) { 1260 form = $(form); 1261 var inputs = form.getElementsByTagName('input'); 1262 1263 if (!typeName && !name) 1264 return inputs; 1265 1266 var matchingInputs = new Array(); 1267 for (var i = 0; i < inputs.length; i++) { 1268 var input = inputs[i]; 1269 if ((typeName && input.type != typeName) || 1270 (name && input.name != name)) 1271 continue; 1272 matchingInputs.push(input); 1273 } 1274 1275 return matchingInputs; 1276 }, 1277 1278 disable: function(form) { 1279 var elements = Form.getElements(form); 1280 for (var i = 0; i < elements.length; i++) { 1281 var element = elements[i]; 1282 element.blur(); 1283 element.disabled = 'true'; 1284 } 1285 }, 1286 1287 enable: function(form) { 1288 var elements = Form.getElements(form); 1289 for (var i = 0; i < elements.length; i++) { 1290 var element = elements[i]; 1291 element.disabled = ''; 1292 } 1293 }, 1294 1295 findFirstElement: function(form) { 1296 return Form.getElements(form).find(function(element) { 1297 return element.type != 'hidden' && !element.disabled && 1298 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 1299 }); 1300 }, 1301 1302 focusFirstElement: function(form) { 1303 Field.activate(Form.findFirstElement(form)); 1304 }, 1305 1306 reset: function(form) { 1307 $(form).reset(); 1308 } 1309 } 1310 1311 Form.Element = { 1312 serialize: function(element) { 1313 element = $(element); 1314 var method = element.tagName.toLowerCase(); 1315 var parameter = Form.Element.Serializers[method](element); 1316 1317 if (parameter) { 1318 var key = encodeURIComponent(parameter[0]); 1319 if (key.length == 0) return; 1320 1321 if (parameter[1].constructor != Array) 1322 parameter[1] = [parameter[1]]; 1323 1324 return parameter[1].map(function(value) { 1325 return key + '=' + encodeURIComponent(value); 1326 }).join('&'); 1327 } 1328 }, 1329 1330 getValue: function(element) { 1331 element = $(element); 1332 var method = element.tagName.toLowerCase(); 1333 var parameter = Form.Element.Serializers[method](element); 1334 1335 if (parameter) 1336 return parameter[1]; 1337 } 1338 } 1339 1340 Form.Element.Serializers = { 1341 input: function(element) { 1342 switch (element.type.toLowerCase()) { 1343 case 'submit': 1344 case 'hidden': 1345 case 'password': 1346 case 'text': 1347 return Form.Element.Serializers.textarea(element); 1348 case 'checkbox': 1349 case 'radio': 1350 return Form.Element.Serializers.inputSelector(element); 1351 } 1352 return false; 1353 }, 1354 1355 inputSelector: function(element) { 1356 if (element.checked) 1357 return [element.name, element.value]; 1358 }, 1359 1360 textarea: function(element) { 1361 return [element.name, element.value]; 1362 }, 1363 1364 select: function(element) { 1365 return Form.Element.Serializers[element.type == 'select-one' ? 1366 'selectOne' : 'selectMany'](element); 1367 }, 1368 1369 selectOne: function(element) { 1370 var value = '', opt, index = element.selectedIndex; 1371 if (index >= 0) { 1372 opt = element.options[index]; 1373 value = opt.value || opt.text; 1374 } 1375 return [element.name, value]; 1376 }, 1377 1378 selectMany: function(element) { 1379 var value = []; 1380 for (var i = 0; i < element.length; i++) { 1381 var opt = element.options[i]; 1382 if (opt.selected) 1383 value.push(opt.value || opt.text); 1384 } 1385 return [element.name, value]; 1386 } 1387 } 1388 1389 /*--------------------------------------------------------------------------*/ 1390 1391 var $F = Form.Element.getValue; 1392 1393 /*--------------------------------------------------------------------------*/ 1394 1395 Abstract.TimedObserver = function() {} 1396 Abstract.TimedObserver.prototype = { 1397 initialize: function(element, frequency, callback) { 1398 this.frequency = frequency; 1399 this.element = $(element); 1400 this.callback = callback; 1401 1402 this.lastValue = this.getValue(); 1403 this.registerCallback(); 1404 }, 1405 1406 registerCallback: function() { 1407 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 1408 }, 1409 1410 onTimerEvent: function() { 1411 var value = this.getValue(); 1412 if (this.lastValue != value) { 1413 this.callback(this.element, value); 1414 this.lastValue = value; 1415 } 1416 } 1417 } 1418 1419 Form.Element.Observer = Class.create(); 1420 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 1421 getValue: function() { 1422 return Form.Element.getValue(this.element); 1423 } 1424 }); 1425 1426 Form.Observer = Class.create(); 1427 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 1428 getValue: function() { 1429 return Form.serialize(this.element); 1430 } 1431 }); 1432 1433 /*--------------------------------------------------------------------------*/ 1434 1435 Abstract.EventObserver = function() {} 1436 Abstract.EventObserver.prototype = { 1437 initialize: function(element, callback) { 1438 this.element = $(element); 1439 this.callback = callback; 1440 1441 this.lastValue = this.getValue(); 1442 if (this.element.tagName.toLowerCase() == 'form') 1443 this.registerFormCallbacks(); 1444 else 1445 this.registerCallback(this.element); 1446 }, 1447 1448 onElementEvent: function() { 1449 var value = this.getValue(); 1450 if (this.lastValue != value) { 1451 this.callback(this.element, value); 1452 this.lastValue = value; 1453 } 1454 }, 1455 1456 registerFormCallbacks: function() { 1457 var elements = Form.getElements(this.element); 1458 for (var i = 0; i < elements.length; i++) 1459 this.registerCallback(elements[i]); 1460 }, 1461 1462 registerCallback: function(element) { 1463 if (element.type) { 1464 switch (element.type.toLowerCase()) { 1465 case 'checkbox': 1466 case 'radio': 1467 Event.observe(element, 'click', this.onElementEvent.bind(this)); 1468 break; 1469 case 'password': 1470 case 'text': 1471 case 'textarea': 1472 case 'select-one': 1473 case 'select-multiple': 1474 Event.observe(element, 'change', this.onElementEvent.bind(this)); 1475 break; 1476 } 1477 } 1478 } 1479 } 1480 1481 Form.Element.EventObserver = Class.create(); 1482 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 1483 getValue: function() { 1484 return Form.Element.getValue(this.element); 1485 } 1486 }); 1487 1488 Form.EventObserver = Class.create(); 1489 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 1490 getValue: function() { 1491 return Form.serialize(this.element); 1492 } 1493 }); 1494 1495 1496 1497 if (!window.Event) { 1498 var Event = new Object(); 1499 } 1500 1501 Object.extend(Event, { 1502 KEY_BACKSPACE: 8, 1503 KEY_TAB: 9, 1504 KEY_RETURN: 13, 1505 KEY_ESC: 27, 1506 KEY_LEFT: 37, 1507 KEY_UP: 38, 1508 KEY_RIGHT: 39, 1509 KEY_DOWN: 40, 1510 KEY_DELETE: 46, 1511 KEY_SPACEBAR: 32, 1512 1513 element: function(event) { 1514 return event.target || event.srcElement; 1515 }, 1516 1517 isLeftClick: function(event) { 1518 return (((event.which) && (event.which == 1)) || 1519 ((event.button) && (event.button == 1))); 1520 }, 1521 1522 pointerX: function(event) { 1523 return event.pageX || (event.clientX + 1524 (document.documentElement.scrollLeft || document.body.scrollLeft)); 1525 }, 1526 1527 pointerY: function(event) { 1528 return event.pageY || (event.clientY + 1529 (document.documentElement.scrollTop || document.body.scrollTop)); 1530 }, 1531 1532 stop: function(event) { 1533 if (event.preventDefault) { 1534 event.preventDefault(); 1535 event.stopPropagation(); 1536 } else { 1537 event.returnValue = false; 1538 event.cancelBubble = true; 1539 } 1540 }, 1541 1542 // find the first node with the given tagName, starting from the 1543 // node the event was triggered on; traverses the DOM upwards 1544 findElement: function(event, tagName) { 1545 var element = Event.element(event); 1546 while (element.parentNode && (!element.tagName || 1547 (element.tagName.toUpperCase() != tagName.toUpperCase()))) 1548 element = element.parentNode; 1549 return element; 1550 }, 1551 1552 observers: false, 1553 1554 _observeAndCache: function(element, name, observer, useCapture) { 1555 if (!this.observers) this.observers = []; 1556 if (element.addEventListener) { 1557 this.observers.push([element, name, observer, useCapture]); 1558 element.addEventListener(name, observer, useCapture); 1559 } else if (element.attachEvent) { 1560 this.observers.push([element, name, observer, useCapture]); 1561 element.attachEvent('on' + name, observer); 1562 } 1563 }, 1564 1565 unloadCache: function() { 1566 if (!Event.observers) return; 1567 for (var i = 0; i < Event.observers.length; i++) { 1568 Event.stopObserving.apply(this, Event.observers[i]); 1569 Event.observers[i][0] = null; 1570 } 1571 Event.observers = false; 1572 }, 1573 1574 observe: function(element, name, observer, useCapture) { 1575 var element = $(element); 1576 useCapture = useCapture || false; 1577 1578 if (name == 'keypress' && 1579 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1580 || element.attachEvent)) 1581 name = 'keydown'; 1582 1583 this._observeAndCache(element, name, observer, useCapture); 1584 }, 1585 1586 stopObserving: function(element, name, observer, useCapture) { 1587 var element = $(element); 1588 useCapture = useCapture || false; 1589 1590 if (name == 'keypress' && 1591 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1592 || element.detachEvent)) 1593 name = 'keydown'; 1594 1595 if (element.removeEventListener) { 1596 element.removeEventListener(name, observer, useCapture); 1597 } else if (element.detachEvent) { 1598 element.detachEvent('on' + name, observer); 1599 } 1600 } 1601 }); 1602 1603 /* prevent memory leaks in IE */ 1604 if (navigator.appVersion.match(/\bMSIE\b/)) 1605 Event.observe(window, 'unload', Event.unloadCache, false); 1606 1607 1608 /** 1609 * @class Event extensions. 1610 */ 1611 Object.extend(Event, 1612 { 1613 /** 1614 * Register a function to be executed when the page is loaded. 1615 * Note that the page is only loaded if all resources (e.g. images) 1616 * are loaded. 1617 * 1618 * Example: Show an alert box with message "Page Loaded!" when the 1619 * page finished loading. 1620 * <code> 1621 * Event.OnLoad(function(){ alert("Page Loaded!"); }); 1622 * </code> 1623 * 1624 * @param {Function} function to execute when page is loaded. 1625 */ 1626 OnLoad : function (fn) 1627 { 1628 // opera onload is in document, not window 1629 var w = document.addEventListener && 1630 !window.addEventListener ? document : window; 1631 Event.observe(w,'load',fn); 1632 }, 1633 1634 /** 1635 * @param {Event} a keyboard event 1636 * @return {Number} the Unicode character code generated by the key 1637 * that was struck. 1638 */ 1639 keyCode : function(e) 1640 { 1641 return e.keyCode != null ? e.keyCode : e.charCode 1642 }, 1643 1644 /** 1645 * @param {String} event type or event name. 1646 * @return {Boolean} true if event type is of HTMLEvent, false 1647 * otherwise 1648 */ 1649 isHTMLEvent : function(type) 1650 { 1651 var events = ['abort', 'blur', 'change', 'error', 'focus', 1652 'load', 'reset', 'resize', 'scroll', 'select', 1653 'submit', 'unload']; 1654 return events.include(type); 1655 }, 1656 1657 /** 1658 * @param {String} event type or event name 1659 * @return {Boolean} true if event type is of MouseEvent, 1660 * false otherwise 1661 */ 1662 isMouseEvent : function(type) 1663 { 1664 var events = ['click', 'mousedown', 'mousemove', 'mouseout', 1665 'mouseover', 'mouseup']; 1666 return events.include(type); 1667 }, 1668 1669 /** 1670 * Dispatch the DOM event of a given <tt>type</tt> on a DOM 1671 * <tt>element</tt>. Only HTMLEvent and MouseEvent can be 1672 * dispatched, keyboard events or UIEvent can not be dispatch 1673 * via javascript consistently. 1674 * For the "submit" event the submit() method is called. 1675 * @param {Object} element id string or a DOM element. 1676 * @param {String} event type to dispatch. 1677 */ 1678 fireEvent : function(element,type) 1679 { 1680 element = $(element); 1681 if(type == "submit") 1682 return element.submit(); 1683 if(document.createEvent) 1684 { 1685 if(Event.isHTMLEvent(type)) 1686 { 1687 var event = document.createEvent('HTMLEvents'); 1688 event.initEvent(type, true, true); 1689 } 1690 else if(Event.isMouseEvent(type)) 1691 { 1692 var event = document.createEvent('MouseEvents'); 1693 if (event.initMouseEvent) 1694 { 1695 event.initMouseEvent(type,true,true, 1696 document.defaultView, 1, 0, 0, 0, 0, false, 1697 false, false, false, 0, null); 1698 } 1699 else 1700 { 1701 // Safari 1702 // TODO we should be initialising other mouse-event related attributes here 1703 event.initEvent(type, true, true); 1704 } 1705 } 1706 element.dispatchEvent(event); 1707 } 1708 else if(document.createEventObject) 1709 { 1710 var evObj = document.createEventObject(); 1711 element.fireEvent('on'+type, evObj); 1712 } 1713 else if(typeof(element['on'+type]) == "function") 1714 element['on'+type](); 1715 } 1716 }); 1717 1718 var Position = { 1719 // set to true if needed, warning: firefox performance problems 1720 // NOT neeeded for page scrolling, only if draggable contained in 1721 // scrollable elements 1722 includeScrollOffsets: false, 1723 1724 // must be called before calling withinIncludingScrolloffset, every time the 1725 // page is scrolled 1726 prepare: function() { 1727 this.deltaX = window.pageXOffset 1728 || document.documentElement.scrollLeft 1729 || document.body.scrollLeft 1730 || 0; 1731 this.deltaY = window.pageYOffset 1732 || document.documentElement.scrollTop 1733 || document.body.scrollTop 1734 || 0; 1735 }, 1736 1737 realOffset: function(element) { 1738 var valueT = 0, valueL = 0; 1739 do { 1740 valueT += element.scrollTop || 0; 1741 valueL += element.scrollLeft || 0; 1742 element = element.parentNode; 1743 } while (element); 1744 return [valueL, valueT]; 1745 }, 1746 1747 cumulativeOffset: function(element) { 1748 var valueT = 0, valueL = 0; 1749 do { 1750 valueT += element.offsetTop || 0; 1751 valueL += element.offsetLeft || 0; 1752 element = element.offsetParent; 1753 } while (element); 1754 return [valueL, valueT]; 1755 }, 1756 1757 positionedOffset: function(element) { 1758 var valueT = 0, valueL = 0; 1759 do { 1760 valueT += element.offsetTop || 0; 1761 valueL += element.offsetLeft || 0; 1762 element = element.offsetParent; 1763 if (element) { 1764 p = Element.getStyle(element, 'position'); 1765 if (p == 'relative' || p == 'absolute') break; 1766 } 1767 } while (element); 1768 return [valueL, valueT]; 1769 }, 1770 1771 offsetParent: function(element) { 1772 if (element.offsetParent) return element.offsetParent; 1773 if (element == document.body) return element; 1774 1775 while ((element = element.parentNode) && element != document.body) 1776 if (Element.getStyle(element, 'position') != 'static') 1777 return element; 1778 1779 return document.body; 1780 }, 1781 1782 // caches x/y coordinate pair to use with overlap 1783 within: function(element, x, y) { 1784 if (this.includeScrollOffsets) 1785 return this.withinIncludingScrolloffsets(element, x, y); 1786 this.xcomp = x; 1787 this.ycomp = y; 1788 this.offset = this.cumulativeOffset(element); 1789 1790 return (y >= this.offset[1] && 1791 y < this.offset[1] + element.offsetHeight && 1792 x >= this.offset[0] && 1793 x < this.offset[0] + element.offsetWidth); 1794 }, 1795 1796 withinIncludingScrolloffsets: function(element, x, y) { 1797 var offsetcache = this.realOffset(element); 1798 1799 this.xcomp = x + offsetcache[0] - this.deltaX; 1800 this.ycomp = y + offsetcache[1] - this.deltaY; 1801 this.offset = this.cumulativeOffset(element); 1802 1803 return (this.ycomp >= this.offset[1] && 1804 this.ycomp < this.offset[1] + element.offsetHeight && 1805 this.xcomp >= this.offset[0] && 1806 this.xcomp < this.offset[0] + element.offsetWidth); 1807 }, 1808 1809 // within must be called directly before 1810 overlap: function(mode, element) { 1811 if (!mode) return 0; 1812 if (mode == 'vertical') 1813 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 1814 element.offsetHeight; 1815 if (mode == 'horizontal') 1816 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 1817 element.offsetWidth; 1818 }, 1819 1820 clone: function(source, target) { 1821 source = $(source); 1822 target = $(target); 1823 target.style.position = 'absolute'; 1824 var offsets = this.cumulativeOffset(source); 1825 target.style.top = offsets[1] + 'px'; 1826 target.style.left = offsets[0] + 'px'; 1827 target.style.width = source.offsetWidth + 'px'; 1828 target.style.height = source.offsetHeight + 'px'; 1829 }, 1830 1831 page: function(forElement) { 1832 var valueT = 0, valueL = 0; 1833 1834 var element = forElement; 1835 do { 1836 valueT += element.offsetTop || 0; 1837 valueL += element.offsetLeft || 0; 1838 1839 // Safari fix 1840 if (element.offsetParent==document.body) 1841 if (Element.getStyle(element,'position')=='absolute') break; 1842 1843 } while (element = element.offsetParent); 1844 1845 element = forElement; 1846 do { 1847 valueT -= element.scrollTop || 0; 1848 valueL -= element.scrollLeft || 0; 1849 } while (element = element.parentNode); 1850 1851 return [valueL, valueT]; 1852 }, 1853 1854 clone: function(source, target) { 1855 var options = Object.extend({ 1856 setLeft: true, 1857 setTop: true, 1858 setWidth: true, 1859 setHeight: true, 1860 offsetTop: 0, 1861 offsetLeft: 0 1862 }, arguments[2] || {}) 1863 1864 // find page position of source 1865 source = $(source); 1866 var p = Position.page(source); 1867 1868 // find coordinate system to use 1869 target = $(target); 1870 var delta = [0, 0]; 1871 var parent = null; 1872 // delta [0,0] will do fine with position: fixed elements, 1873 // position:absolute needs offsetParent deltas 1874 if (Element.getStyle(target,'position') == 'absolute') { 1875 parent = Position.offsetParent(target); 1876 delta = Position.page(parent); 1877 } 1878 1879 // correct by body offsets (fixes Safari) 1880 if (parent == document.body) { 1881 delta[0] -= document.body.offsetLeft; 1882 delta[1] -= document.body.offsetTop; 1883 } 1884 1885 // set position 1886 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 1887 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 1888 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; 1889 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; 1890 }, 1891 1892 absolutize: function(element) { 1893 element = $(element); 1894 if (element.style.position == 'absolute') return; 1895 Position.prepare(); 1896 1897 var offsets = Position.positionedOffset(element); 1898 var top = offsets[1]; 1899 var left = offsets[0]; 1900 var width = element.clientWidth; 1901 var height = element.clientHeight; 1902 1903 element._originalLeft = left - parseFloat(element.style.left || 0); 1904 element._originalTop = top - parseFloat(element.style.top || 0); 1905 element._originalWidth = element.style.width; 1906 element._originalHeight = element.style.height; 1907 1908 element.style.position = 'absolute'; 1909 element.style.top = top + 'px';; 1910 element.style.left = left + 'px';; 1911 element.style.width = width + 'px';; 1912 element.style.height = height + 'px';; 1913 }, 1914 1915 relativize: function(element) { 1916 element = $(element); 1917 if (element.style.position == 'relative') return; 1918 Position.prepare(); 1919 1920 element.style.position = 'relative'; 1921 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 1922 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 1923 1924 element.style.top = top + 'px'; 1925 element.style.left = left + 'px'; 1926 element.style.height = element._originalHeight; 1927 element.style.width = element._originalWidth; 1928 } 1929 } 1930 1931 // Safari returns margins on body which is incorrect if the child is absolutely 1932 // positioned. For performance reasons, redefine Position.cumulativeOffset for 1933 // KHTML/WebKit only. 1934 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 1935 Position.cumulativeOffset = function(element) { 1936 var valueT = 0, valueL = 0; 1937 do { 1938 valueT += element.offsetTop || 0; 1939 valueL += element.offsetLeft || 0; 1940 if (element.offsetParent == document.body) 1941 if (Element.getStyle(element, 'position') == 'absolute') break; 1942 1943 element = element.offsetParent; 1944 } while (element); 1945 1946 return [valueL, valueT]; 1947 } 1948 } 1949 1950 1951 1952 1953 var Selector = Class.create(); 1954 Selector.prototype = { 1955 initialize: function(expression) { 1956 this.params = {classNames: []}; 1957 this.expression = expression.toString().strip(); 1958 this.parseExpression(); 1959 this.compileMatcher(); 1960 }, 1961 1962 parseExpression: function() { 1963 function abort(message) { throw 'Parse error in selector: ' + message; } 1964 1965 if (this.expression == '') abort('empty expression'); 1966 1967 var params = this.params, expr = this.expression, match, modifier, clause, rest; 1968 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { 1969 params.attributes = params.attributes || []; 1970 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); 1971 expr = match[1]; 1972 } 1973 1974 if (expr == '*') return this.params.wildcard = true; 1975 1976 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { 1977 modifier = match[1], clause = match[2], rest = match[3]; 1978 switch (modifier) { 1979 case '#': params.id = clause; break; 1980 case '.': params.classNames.push(clause); break; 1981 case '': 1982 case undefined: params.tagName = clause.toUpperCase(); break; 1983 default: abort(expr.inspect()); 1984 } 1985 expr = rest; 1986 } 1987 1988 if (expr.length > 0) abort(expr.inspect()); 1989 }, 1990 1991 buildMatchExpression: function() { 1992 var params = this.params, conditions = [], clause; 1993 1994 if (params.wildcard) 1995 conditions.push('true'); 1996 if (clause = params.id) 1997 conditions.push('element.id == ' + clause.inspect()); 1998 if (clause = params.tagName) 1999 conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); 2000 if ((clause = params.classNames).length > 0) 2001 for (var i = 0; i < clause.length; i++) 2002 conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); 2003 if (clause = params.attributes) { 2004 clause.each(function(attribute) { 2005 var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; 2006 var splitValueBy = function(delimiter) { 2007 return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; 2008 } 2009 2010 switch (attribute.operator) { 2011 case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; 2012 case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; 2013 case '|=': conditions.push( 2014 splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() 2015 ); break; 2016 case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; 2017 case '': 2018 case undefined: conditions.push(value + ' != null'); break; 2019 default: throw 'Unknown operator ' + attribute.operator + ' in selector'; 2020 } 2021 }); 2022 } 2023 2024 return conditions.join(' && '); 2025 }, 2026 2027 compileMatcher: function() { 2028 this.match = new Function('element', 'if (!element.tagName) return false; \ 2029 return ' + this.buildMatchExpression()); 2030 }, 2031 2032 findElements: function(scope) { 2033 var element; 2034 2035 if (element = $(this.params.id)) 2036 if (this.match(element)) 2037 if (!scope || Element.childOf(element, scope)) 2038 return [element]; 2039 2040 scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); 2041 2042 var results = []; 2043 for (var i = 0; i < scope.length; i++) 2044 if (this.match(element = scope[i])) 2045 results.push(Element.extend(element)); 2046 2047 return results; 2048 }, 2049 2050 toString: function() { 2051 return this.expression; 2052 } 2053 } 2054 2055 function $$() { 2056 return $A(arguments).map(function(expression) { 2057 return expression.strip().split(/\s+/).inject([null], function(results, expr) { 2058 var selector = new Selector(expr); 2059 return results.map(selector.findElements.bind(selector)).flatten(); 2060 }); 2061 }).flatten(); 2062 } 2063 2064 2065 // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 2066 // 2067 // See scriptaculous.js for full license. 2068 2069 var Builder = { 2070 NODEMAP: { 2071 AREA: 'map', 2072 CAPTION: 'table', 2073 COL: 'table', 2074 COLGROUP: 'table', 2075 LEGEND: 'fieldset', 2076 OPTGROUP: 'select', 2077 OPTION: 'select', 2078 PARAM: 'object', 2079 TBODY: 'table', 2080 TD: 'table', 2081 TFOOT: 'table', 2082 TH: 'table', 2083 THEAD: 'table', 2084 TR: 'table' 2085 }, 2086 // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, 2087 // due to a Firefox bug 2088 node: function(elementName) { 2089 elementName = elementName.toUpperCase(); 2090 2091 // try innerHTML approach 2092 var parentTag = this.NODEMAP[elementName] || 'div'; 2093 var parentElement = document.createElement(parentTag); 2094 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 2095 parentElement.innerHTML = "<" + elementName + "></" + elementName + ">"; 2096 } catch(e) {} 2097 var element = parentElement.firstChild || null; 2098 2099 // see if browser added wrapping tags 2100 if(element && (element.tagName != elementName)) 2101 element = element.getElementsByTagName(elementName)[0]; 2102 2103 // fallback to createElement approach 2104 if(!element) element = document.createElement(elementName); 2105 2106 // abort if nothing could be created 2107 if(!element) return; 2108 2109 // attributes (or text) 2110 if(arguments[1]) 2111 if(this._isStringOrNumber(arguments[1]) || 2112 (arguments[1] instanceof Array)) { 2113 this._children(element, arguments[1]); 2114 } else { 2115 var attrs = this._attributes(arguments[1]); 2116 if(attrs.length) { 2117 try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 2118 parentElement.innerHTML = "<" +elementName + " " + 2119 attrs + "></" + elementName + ">"; 2120 } catch(e) {} 2121 element = parentElement.firstChild || null; 2122 // workaround firefox 1.0.X bug 2123 if(!element) { 2124 element = document.createElement(elementName); 2125 for(attr in arguments[1]) 2126 element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; 2127 } 2128 if(element.tagName != elementName) 2129 element = parentElement.getElementsByTagName(elementName)[0]; 2130 } 2131 } 2132 2133 // text, or array of children 2134 if(arguments[2]) 2135 this._children(element, arguments[2]); 2136 2137 return element; 2138 }, 2139 _text: function(text) { 2140 return document.createTextNode(text); 2141 }, 2142 _attributes: function(attributes) { 2143 var attrs = []; 2144 for(attribute in attributes) 2145 attrs.push((attribute=='className' ? 'class' : attribute) + 2146 '="' + attributes[attribute].toString().escapeHTML() + '"'); 2147 return attrs.join(" "); 2148 }, 2149 _children: function(element, children) { 2150 if(typeof children=='object') { // array can hold nodes and text 2151 children.flatten().each( function(e) { 2152 if(typeof e=='object') 2153 element.appendChild(e) 2154 else 2155 if(Builder._isStringOrNumber(e)) 2156 element.appendChild(Builder._text(e)); 2157 }); 2158 } else 2159 if(Builder._isStringOrNumber(children)) 2160 element.appendChild(Builder._text(children)); 2161 }, 2162 _isStringOrNumber: function(param) { 2163 return(typeof param=='string' || typeof param=='number'); 2164 } 2165 } 2166 2167 2168 Object.extend(Builder, 2169 { 2170 exportTags:function() 2171 { 2172 var tags=["BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG", "CAPTION"]; 2173 tags.each(function(tag) 2174 { 2175 window[tag]=function() 2176 { 2177 var args=$A(arguments); 2178 if(args.length==0) 2179 return Builder.node(tag,null); 2180 if(args.length==1) 2181 return Builder.node(tag,args[0]); 2182 if(args.length>1) 2183 return Builder.node(tag,args.shift(),args); 2184 2185 }; 2186 }); 2187 } 2188 }); 2189 2190 Builder.exportTags(); 2191 2192 2193 2194 Object.extend(Date.prototype, 2195 { 2196 SimpleFormat: function(format, data) 2197 { 2198 data = data || {}; 2199 var bits = new Array(); 2200 bits['d'] = this.getDate(); 2201 bits['dd'] = String(this.getDate()).zerofill(2); 2202 2203 bits['M'] = this.getMonth()+1; 2204 bits['MM'] = String(this.getMonth()+1).zerofill(2); 2205 if(data.AbbreviatedMonthNames) 2206 bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()]; 2207 if(data.MonthNames) 2208 bits['MMMM'] = data.MonthNames[this.getMonth()]; 2209 var yearStr = "" + this.getFullYear(); 2210 yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr; 2211 bits['yyyy'] = yearStr; 2212 bits['yy'] = bits['yyyy'].toString().substr(2,2); 2213 2214 // do some funky regexs to replace the format string 2215 // with the real values 2216 var frm = new String(format); 2217 for (var sect in bits) 2218 { 2219 var reg = new RegExp("\\b"+sect+"\\b" ,"g"); 2220 frm = frm.replace(reg, bits[sect]); 2221 } 2222 return frm; 2223 }, 2224 2225 toISODate : function() 2226 { 2227 var y = this.getFullYear(); 2228 var m = String(this.getMonth() + 1).zerofill(2); 2229 var d = String(this.getDate()).zerofill(2); 2230 return String(y) + String(m) + String(d); 2231 } 2232 }); 2233 2234 Object.extend(Date, 2235 { 2236 SimpleParse: function(value, format) 2237 { 2238 val=String(value); 2239 format=String(format); 2240 2241 if(val.length <= 0) return null; 2242 2243 if(format.length <= 0) return new Date(value); 2244 2245 var isInteger = function (val) 2246 { 2247 var digits="1234567890"; 2248 for (var i=0; i < val.length; i++) 2249 { 2250 if (digits.indexOf(val.charAt(i))==-1) { return false; } 2251 } 2252 return true; 2253 }; 2254 2255 var getInt = function(str,i,minlength,maxlength) 2256 { 2257 for (var x=maxlength; x>=minlength; x--) 2258 { 2259 var token=str.substring(i,i+x); 2260 if (token.length < minlength) { return null; } 2261 if (isInteger(token)) { return token; } 2262 } 2263 return null; 2264 }; 2265 2266 var i_val=0; 2267 var i_format=0; 2268 var c=""; 2269 var token=""; 2270 var token2=""; 2271 var x,y; 2272 var now=new Date(); 2273 var year=now.getFullYear(); 2274 var month=now.getMonth()+1; 2275 var date=1; 2276 2277 while (i_format < format.length) 2278 { 2279 // Get next token from format string 2280 c=format.charAt(i_format); 2281 token=""; 2282 while ((format.charAt(i_format)==c) && (i_format < format.length)) 2283 { 2284 token += format.charAt(i_format++); 2285 } 2286 2287 // Extract contents of value based on format token 2288 if (token=="yyyy" || token=="yy" || token=="y") 2289 { 2290 if (token=="yyyy") { x=4;y=4; } 2291 if (token=="yy") { x=2;y=2; } 2292 if (token=="y") { x=2;y=4; } 2293 year=getInt(val,i_val,x,y); 2294 if (year==null) { return null; } 2295 i_val += year.length; 2296 if (year.length==2) 2297 { 2298 if (year > 70) { year=1900+(year-0); } 2299 else { year=2000+(year-0); } 2300 } 2301 } 2302 2303 else if (token=="MM"||token=="M") 2304 { 2305 month=getInt(val,i_val,token.length,2); 2306 if(month==null||(month<1)||(month>12)){return null;} 2307 i_val+=month.length; 2308 } 2309 else if (token=="dd"||token=="d") 2310 { 2311 date=getInt(val,i_val,token.length,2); 2312 if(date==null||(date<1)||(date>31)){return null;} 2313 i_val+=date.length; 2314 } 2315 else 2316 { 2317 if (val.substring(i_val,i_val+token.length)!=token) {return null;} 2318 else {i_val+=token.length;} 2319 } 2320 } 2321 2322 // If there are any trailing characters left in the value, it doesn't match 2323 if (i_val != val.length) { return null; } 2324 2325 // Is date valid for month? 2326 if (month==2) 2327 { 2328 // Check for leap year 2329 if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year 2330 if (date > 29){ return null; } 2331 } 2332 else { if (date > 28) { return null; } } 2333 } 2334 2335 if ((month==4)||(month==6)||(month==9)||(month==11)) 2336 { 2337 if (date > 30) { return null; } 2338 } 2339 2340 var newdate=new Date(year,month-1,date, 0, 0, 0); 2341 return newdate; 2342 } 2343 }); 2344 2345 2346 var Prado = 2347 { 2348 Version: '3.0.0', 2349 2350 /** 2351 * Returns browser information. Example 2352 * <code> 2353 * var browser = Prado.Browser(); 2354 * alert(browser.ie); //should ouput true if IE, false otherwise 2355 * </code> 2356 * @param ${parameter} 2357 * @return ${return} 2358 */ 2359 Browser : function() 2360 { 2361 var info = { Version : "1.0" }; 2362 var is_major = parseInt( navigator.appVersion ); 2363 info.nver = is_major; 2364 info.ver = navigator.appVersion; 2365 info.agent = navigator.userAgent; 2366 info.dom = document.getElementById ? 1 : 0; 2367 info.opera = window.opera ? 1 : 0; 2368 info.ie5 = ( info.ver.indexOf( "MSIE 5" ) > -1 && info.dom && !info.opera ) ? 1 : 0; 2369 info.ie6 = ( info.ver.indexOf( "MSIE 6" ) > -1 && info.dom && !info.opera ) ? 1 : 0; 2370 info.ie4 = ( document.all && !info.dom && !info.opera ) ? 1 : 0; 2371 info.ie = info.ie4 || info.ie5 || info.ie6; 2372 info.mac = info.agent.indexOf( "Mac" ) > -1; 2373 info.ns6 = ( info.dom && parseInt( info.ver ) >= 5 ) ? 1 : 0; 2374 info.ie3 = ( info.ver.indexOf( "MSIE" ) && ( is_major < 4 ) ); 2375 info.hotjava = ( info.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0; 2376 info.ns4 = ( document.layers && !info.dom && !info.hotjava ) ? 1 : 0; 2377 info.bw = ( info.ie6 || info.ie5 || info.ie4 || info.ns4 || info.ns6 || info.opera ); 2378 info.ver3 = ( info.hotjava || info.ie3 ); 2379 info.opera7 = ( ( info.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( info.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) ); 2380 info.operaOld = info.opera && !info.opera7; 2381 return info; 2382 }, 2383 2384 ImportCss : function(doc, css_file) 2385 { 2386 if (Prado.Browser().ie) 2387 var styleSheet = doc.createStyleSheet(css_file); 2388 else 2389 { 2390 var elm = doc.createElement("link"); 2391 2392 elm.rel = "stylesheet"; 2393 elm.href = css_file; 2394 2395 if (headArr = doc.getElementsByTagName("head")) 2396 headArr[0].appendChild(elm); 2397 } 2398 } 2399 }; 2400 2401 2402 /*Prado.Focus = Class.create(); 2403 2404 Prado.Focus.setFocus = function(id) 2405 { 2406 var target = document.getElementById ? document.getElementById(id) : document.all[id]; 2407 if(target && !Prado.Focus.canFocusOn(target)) 2408 { 2409 target = Prado.Focus.findTarget(target); 2410 } 2411 if(target) 2412 { 2413 try 2414 { 2415 target.focus(); 2416 target.scrollIntoView(false); 2417 if (window.__smartNav) 2418 { 2419 window.__smartNav.ae = target.id; 2420 } 2421 } 2422 catch (e) 2423 { 2424 } 2425 } 2426 } 2427 2428 Prado.Focus.canFocusOn = function(element) 2429 { 2430 if(!element || !(element.tagName)) 2431 return false; 2432 var tagName = element.tagName.toLowerCase(); 2433 return !element.disabled && (!element.type || element.type.toLowerCase() != "hidden") && Prado.Focus.isFocusableTag(tagName) && Prado.Focus.isVisible(element); 2434 } 2435 2436 Prado.Focus.isFocusableTag = function(tagName) 2437 { 2438 return (tagName == "input" || tagName == "textarea" || tagName == "select" || tagName == "button" || tagName == "a"); 2439 } 2440 2441 2442 Prado.Focus.findTarget = function(element) 2443 { 2444 if(!element || !(element.tagName)) 2445 { 2446 return null; 2447 } 2448 var tagName = element.tagName.toLowerCase(); 2449 if (tagName == "undefined") 2450 { 2451 return null; 2452 } 2453 var children = element.childNodes; 2454 if (children) 2455 { 2456 for(var i=0;i<children.length;i++) 2457 { 2458 try 2459 { 2460 if(Prado.Focus.canFocusOn(children[i])) 2461 { 2462 return children[i]; 2463 } 2464 else 2465 { 2466 var target = Prado.Focus.findTarget(children[i]); 2467 if(target) 2468 { 2469 return target; 2470 } 2471 } 2472 } 2473 catch (e) 2474 { 2475 } 2476 } 2477 } 2478 return null; 2479 } 2480 2481 Prado.Focus.isVisible = function(element) 2482 { 2483 var current = element; 2484 while((typeof(current) != "undefined") && (current != null)) 2485 { 2486 if(current.disabled || (typeof(current.style) != "undefined" && ((typeof(current.style.display) != "undefined" && current.style.display == "none") || (typeof(current.style.visibility) != "undefined" && current.style.visibility == "hidden") ))) 2487 { 2488 return false; 2489 } 2490 if(typeof(current.parentNode) != "undefined" && current.parentNode != null && current.parentNode != current && current.parentNode.tagName.toLowerCase() != "body") 2491 { 2492 current = current.parentNode; 2493 } 2494 else 2495 { 2496 return true; 2497 } 2498 } 2499 return true; 2500 } 2501 */ 2502 2503 2504 Prado.PostBack = function(event,options) 2505 { 2506 var form = $(options['FormID']); 2507 var canSubmit = true; 2508 2509 if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined") 2510 { 2511 if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID']))) 2512 return Event.stop(event); 2513 } 2514 2515 if(options['PostBackUrl'] && options['PostBackUrl'].length > 0) 2516 form.action = options['PostBackUrl']; 2517 2518 if(options['TrackFocus']) 2519 { 2520 var lastFocus = $('PRADO_LASTFOCUS'); 2521 if(lastFocus) 2522 { 2523 var active = document.activeElement; //where did this come from 2524 if(active) 2525 lastFocus.value = active.id; 2526 else 2527 lastFocus.value = options['EventTarget']; 2528 } 2529 } 2530 2531 $('PRADO_POSTBACK_TARGET').value = options['EventTarget']; 2532 $('PRADO_POSTBACK_PARAMETER').value = options['EventParameter']; 2533 /** 2534 * Since google toolbar prevents browser default action, 2535 * we will always disable default client-side browser action 2536 */ 2537 /*if(options['StopEvent']) */ 2538 Event.stop(event); 2539 Event.fireEvent(form,"submit"); 2540 } 2541 2542 /* 2543 2544 Prado.doPostBack = function(formID, eventTarget, eventParameter, performValidation, validationGroup, actionUrl, trackFocus, clientSubmit) 2545 { 2546 if (typeof(performValidation) == 'undefined') 2547 { 2548 var performValidation = false; 2549 var validationGroup = ''; 2550 var actionUrl = null; 2551 var trackFocus = false; 2552 var clientSubmit = true; 2553 } 2554 var theForm = document.getElementById ? document.getElementById(formID) : document.forms[formID]; 2555 var canSubmit = true; 2556 if (performValidation) 2557 { 2558 //canSubmit = Prado.Validation.validate(validationGroup); 2559 * Prado.Validation.ActiveTarget = theForm; 2560 Prado.Validation.CurrentTargetGroup = null; 2561 Prado.Validation.IsGroupValidation = false; 2562 canSubmit = Prado.Validation.IsValid(theForm); 2563 Logger.debug(canSubmit);* 2564 canSubmit = Prado.Validation.IsValid(theForm); 2565 } 2566 if (canSubmit) 2567 { 2568 if (actionUrl != null && (actionUrl.length > 0)) 2569 { 2570 theForm.action = actionUrl; 2571 } 2572 if (trackFocus) 2573 { 2574 var lastFocus = theForm.elements['PRADO_LASTFOCUS']; 2575 if ((typeof(lastFocus) != 'undefined') && (lastFocus != null)) 2576 { 2577 var active = document.activeElement; 2578 if (typeof(active) == 'undefined') 2579 { 2580 lastFocus.value = eventTarget; 2581 } 2582 else 2583 { 2584 if ((active != null) && (typeof(active.id) != 'undefined')) 2585 { 2586 if (active.id.length > 0) 2587 { 2588 lastFocus.value = active.id; 2589 } 2590 else if (typeof(active.name) != 'undefined') 2591 { 2592 lastFocus.value = active.name; 2593 } 2594 } 2595 } 2596 } 2597 } 2598 if (!clientSubmit) 2599 { 2600 canSubmit = false; 2601 } 2602 } 2603 if (canSubmit && (!theForm.onsubmit || theForm.onsubmit())) 2604 { 2605 theForm.PRADO_POSTBACK_TARGET.value = eventTarget; 2606 theForm.PRADO_POSTBACK_PARAMETER.value = eventParameter; 2607 theForm.submit(); 2608 } 2609 } 2610 */ 2611 2612 Prado.Element = 2613 { 2614 /** 2615 * Set the value of a particular element. 2616 * @param string element id 2617 * @param string new element value. 2618 */ 2619 setValue : function(element, value) 2620 { 2621 var el = $(element); 2622 if(el && typeof(el.value) != "undefined") 2623 el.value = value; 2624 }, 2625 2626 select : function(element, method, value) 2627 { 2628 var el = $(element); 2629 var isList = element.indexOf('[]') > -1; 2630 if(!el && !isList) return; 2631 method = isList ? 'check'+method : el.tagName.toLowerCase()+method; 2632 var selection = Prado.Element.Selection; 2633 if(isFunction(selection[method])) 2634 selection[method](isList ? element : el,value); 2635 }, 2636 2637 click : function(element) 2638 { 2639 var el = $(element); 2640 if(el) 2641 Event.fireEvent(el,'click'); 2642 }, 2643 2644 setAttribute : function(element, attribute, value) 2645 { 2646 var el = $(element); 2647 if(attribute == "disabled" && value==false) 2648 el.removeAttribute(attribute); 2649 else 2650 el.setAttribute(attribute, value); 2651 }, 2652 2653 setOptions : function(element, options) 2654 { 2655 var el = $(element); 2656 if(el && el.tagName.toLowerCase() == "select") 2657 { 2658 while(el.length > 0) 2659 el.remove(0); 2660 for(var i = 0; i<options.length; i++) 2661 el.options[el.options.length] = new Option(options[i][0],options[i][1]); 2662 } 2663 }, 2664 2665 /** 2666 * A delayed focus on a particular element 2667 * @param {element} element to apply focus() 2668 */ 2669 focus : function(element) 2670 { 2671 var obj = $(element); 2672 if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined") 2673 setTimeout(function(){ obj.focus(); }, 100); 2674 return false; 2675 } 2676 } 2677 2678 Prado.Element.Selection = 2679 { 2680 inputValue : function(el, value) 2681 { 2682 switch(el.type.toLowerCase()) 2683 { 2684 case 'checkbox': 2685 case 'radio': 2686 return el.checked = value; 2687 } 2688 }, 2689 2690 selectValue : function(el, value) 2691 { 2692 $A(el.options).each(function(option) 2693 { 2694 option.selected = option.value == value; 2695 }); 2696 }, 2697 2698 selectIndex : function(el, index) 2699 { 2700 if(el.type == 'select-one') 2701 el.selectedIndex = index; 2702 else 2703 { 2704 for(var i = 0; i<el.length; i++) 2705 { 2706 if(i == index) 2707 el.options[i].selected = true; 2708 } 2709 } 2710 }, 2711 2712 selectClear : function(el) 2713 { 2714 el.selectedIndex = -1; 2715 }, 2716 2717 selectAll : function(el) 2718 { 2719 $A(el.options).each(function(option) 2720 { 2721 option.selected = true; 2722 Logger.warn(option.value); 2723 }); 2724 }, 2725 2726 selectInvert : function(el) 2727 { 2728 $A(el.options).each(function(option) 2729 { 2730 option.selected = !option.selected; 2731 }); 2732 }, 2733 2734 checkValue : function(name, value) 2735 { 2736 $A(document.getElementsByName(name)).each(function(el) 2737 { 2738 el.checked = el.value == value 2739 }); 2740 }, 2741 2742 checkIndex : function(name, index) 2743 { 2744 var elements = $A(document.getElementsByName(name)); 2745 for(var i = 0; i<elements.length; i++) 2746 { 2747 if(i == index) 2748 elements[i].checked = true; 2749 } 2750 }, 2751 2752 checkClear : function(name) 2753 { 2754 $A(document.getElementsByName(name)).each(function(el) 2755 { 2756 el.checked = false; 2757 }); 2758 }, 2759 2760 checkAll : function(name) 2761 { 2762 $A(document.getElementsByName(name)).each(function(el) 2763 { 2764 el.checked = true; 2765 }); 2766 }, 2767 checkInvert : function(name) 2768 { 2769 $A(document.getElementsByName(name)).each(function(el) 2770 { 2771 el.checked = !el.checked; 2772 }); 2773 } 2774 }; 2775 2776 Prado.WebUI = Class.create(); 2777 2778 //base postback-able controls 2779 /*Prado.WebUI.PostBackControl = Class.create(); 2780 Prado.WebUI.PostBackControl.prototype = 2781 { 2782 initialize : function(options) 2783 { 2784 this.element = $(options['ID']); 2785 2786 /* if(options.CausesValidation && typeof(Prado.Validation) != 'undefined') 2787 { 2788 Prado.Validation.registerTarget(options); 2789 } 2790 2791 //TODO: what do the following options do? 2792 //options['PostBackUrl'] 2793 //options['ClientSubmit'] 2794 2795 if(this.onInit) 2796 this.onInit(options); 2797 } 2798 }; 2799 2800 //short cut to create postback components 2801 Prado.WebUI.createPostBackComponent = function(definition) 2802 { 2803 var component = Class.create(); 2804 Object.extend(component.prototype, Prado.WebUI.PostBackControl.prototype); 2805 if(definition) Object.extend(component.prototype, definition); 2806 return component; 2807 } 2808 2809 Prado.WebUI.TButton = Prado.WebUI.createPostBackComponent(); 2810 */ 2811 Prado.WebUI.PostBackControl = Class.create(); 2812 2813 Prado.WebUI.PostBackControl.prototype = 2814 { 2815 _elementOnClick : null, //capture the element's onclick function 2816 2817 initialize : function(options) 2818 { 2819 this.element = $(options.ID); 2820 if(this.onInit) 2821 this.onInit(options); 2822 }, 2823 2824 onInit : function(options) 2825 { 2826 if(typeof(this.element.onclick)=="function") 2827 { 2828 this._elementOnClick = this.element.onclick; 2829 this.element.onclick = null; 2830 } 2831 Event.observe(this.element, "click", this.onClick.bindEvent(this,options)); 2832 }, 2833 2834 onClick : function(event, options) 2835 { 2836 var src = Event.element(event); 2837 var doPostBack = true; 2838 var onclicked = null; 2839 2840 if(this._elementOnClick) 2841 { 2842 var onclicked = this._elementOnClick(event); 2843 if(typeof(onclicked) == "boolean") 2844 doPostBack = onclicked; 2845 } 2846 if(doPostBack) 2847 this.onPostBack(event,options); 2848 if(typeof(onclicked) == "boolean" && !onclicked) 2849 Event.stop(event); 2850 }, 2851 2852 onPostBack : function(event, options) 2853 { 2854 Prado.PostBack(event,options); 2855 } 2856 }; 2857 2858 Prado.WebUI.TButton = Class.extend(Prado.WebUI.PostBackControl); 2859 Prado.WebUI.TLinkButton = Class.extend(Prado.WebUI.PostBackControl); 2860 Prado.WebUI.TCheckBox = Class.extend(Prado.WebUI.PostBackControl); 2861 Prado.WebUI.TBulletedList = Class.extend(Prado.WebUI.PostBackControl); 2862 Prado.WebUI.TImageMap = Class.extend(Prado.WebUI.PostBackControl); 2863 2864 /** 2865 * TImageButton client-side behaviour. With validation, Firefox needs 2866 * to capture the x,y point of the clicked image in hidden form fields. 2867 */ 2868 Prado.WebUI.TImageButton = Class.extend(Prado.WebUI.PostBackControl); 2869 Object.extend(Prado.WebUI.TImageButton.prototype, 2870 { 2871 /** 2872 * Only add the hidden inputs once. 2873 */ 2874 hasXYInput : false, 2875 2876 /** 2877 * Override parent onPostBack function, tried to add hidden forms 2878 * inputs to capture x,y clicked point. 2879 */ 2880 onPostBack : function(event, options) 2881 { 2882 if(!this.hasXYInput) 2883 { 2884 this.addXYInput(event,options); 2885 this.hasXYInput = true; 2886 } 2887 Prado.PostBack(event, options); 2888 }, 2889 2890 /** 2891 * Add hidden inputs to capture the x,y point clicked on the image. 2892 * @param event DOM click event. 2893 * @param array image button options. 2894 */ 2895 addXYInput : function(event,options) 2896 { 2897 var imagePos = Position.cumulativeOffset(this.element); 2898 var clickedPos = [event.clientX, event.clientY]; 2899 var x = clickedPos[0]-imagePos[0]+1; 2900 var y = clickedPos[1]-imagePos[1]+1; 2901 var id = options['EventTarget']; 2902 var x_input = INPUT({type:'hidden',name:id+'_x',value:x}); 2903 var y_input = INPUT({type:'hidden',name:id+'_y',value:y}); 2904 this.element.parentNode.appendChild(x_input); 2905 this.element.parentNode.appendChild(y_input); 2906 } 2907 }); 2908 2909 2910 /** 2911 * Radio button, only initialize if not already checked. 2912 */ 2913 Prado.WebUI.TRadioButton = Class.extend(Prado.WebUI.PostBackControl); 2914 Prado.WebUI.TRadioButton.prototype.onRadioButtonInitialize = Prado.WebUI.TRadioButton.prototype.initialize; 2915 Object.extend(Prado.WebUI.TRadioButton.prototype, 2916 { 2917 initialize : function(options) 2918 { 2919 this.element = $(options['ID']); 2920 if(!this.element.checked) 2921 this.onRadioButtonInitialize(options); 2922 } 2923 }); 2924 2925 2926 Prado.WebUI.TTextBox = Class.extend(Prado.WebUI.PostBackControl, 2927 { 2928 onInit : function(options) 2929 { 2930 if(options['TextMode'] != 'MultiLine') 2931 Event.observe(this.element, "keydown", this.handleReturnKey.bind(this)); 2932 Event.observe(this.element, "change", Prado.PostBack.bindEvent(this,options)); 2933 }, 2934 2935 handleReturnKey : function(e) 2936 { 2937 if(Event.keyCode(e) == Event.KEY_RETURN) 2938 { 2939 var target = Event.element(e); 2940 if(target) 2941 { 2942 Event.fireEvent(target, "change"); 2943 Event.stop(e); 2944 } 2945 } 2946 } 2947 }); 2948 2949 Prado.WebUI.TListControl = Class.extend(Prado.WebUI.PostBackControl, 2950 { 2951 onInit : function(options) 2952 { 2953 Event.observe(this.element, "change", Prado.PostBack.bindEvent(this,options)); 2954 } 2955 }); 2956 2957 Prado.WebUI.TListBox = Class.extend(Prado.WebUI.TListControl); 2958 Prado.WebUI.TDropDownList = Class.extend(Prado.WebUI.TListControl); 2959 2960 Prado.WebUI.DefaultButton = Class.create(); 2961 Prado.WebUI.DefaultButton.prototype = 2962 { 2963 initialize : function(options) 2964 { 2965 this.options = options; 2966 this._event = this.triggerEvent.bindEvent(this); 2967 Event.observe(options['Panel'], 'keydown', this._event); 2968 }, 2969 2970 triggerEvent : function(ev, target) 2971 { 2972 var enterPressed = Event.keyCode(ev) == Event.KEY_RETURN; 2973 var isTextArea = Event.element(ev).tagName.toLowerCase() == "textarea"; 2974 if(enterPressed && !isTextArea) 2975 { 2976 var defaultButton = $(this.options['Target']); 2977 if(defaultButton) 2978 { 2979 this.triggered = true; 2980 $('PRADO_POSTBACK_TARGET').value = this.options.EventTarget; 2981 Event.fireEvent(defaultButton, this.options['Event']); 2982 Event.stop(ev); 2983 } 2984 } 2985 } 2986 }; 2987 2988 Prado.WebUI.TTextHighlighter=Class.create(); 2989 Prado.WebUI.TTextHighlighter.prototype= 2990 { 2991 initialize:function(id) 2992 { 2993 if(!window.clipboardData) return; 2994 var options = 2995 { 2996 href : 'javascript:;/'+'/copy code to clipboard', 2997 onclick : 'Prado.WebUI.TTextHighlighter.copy(this)', 2998 onmouseover : 'Prado.WebUI.TTextHighlighter.hover(this)', 2999 onmouseout : 'Prado.WebUI.TTextHighlighter.out(this)' 3000 } 3001 var div = DIV({className:'copycode'}, A(options, 'Copy Code')); 3002 document.write(DIV(null,div).innerHTML); 3003 } 3004 }; 3005 3006 Object.extend(Prado.WebUI.TTextHighlighter, 3007 { 3008 copy : function(obj) 3009 { 3010 var parent = obj.parentNode.parentNode.parentNode; 3011 var text = ''; 3012 for(var i = 0; i < parent.childNodes.length; i++) 3013 { 3014 var node = parent.childNodes[i]; 3015 if(node.innerText) 3016 text += node.innerText == 'Copy Code' ? '' : node.innerText; 3017 else 3018 text += node.nodeValue; 3019 } 3020 if(text.length > 0) 3021 window.clipboardData.setData("Text", text); 3022 }, 3023 3024 hover : function(obj) 3025 { 3026 obj.parentNode.className = "copycode copycode_hover"; 3027 }, 3028 3029 out : function(obj) 3030 { 3031 obj.parentNode.className = "copycode"; 3032 } 3033 }); 3034 3035 3036 Prado.WebUI.TRatingList = Class.create(); 3037 Prado.WebUI.TRatingList.prototype = 3038 { 3039 selectedIndex : -1, 3040 3041 initialize : function(options) 3042 { 3043 this.options = options; 3044 this.element = $(options['ID']); 3045 Element.addClassName(this.element,options.cssClass); 3046 this.radios = document.getElementsByName(options.field); 3047 for(var i = 0; i<this.radios.length; i++) 3048 { 3049 Event.observe(this.radios[i].parentNode, "mouseover", this.hover.bindEvent(this,i)); 3050 Event.observe(this.radios[i].parentNode, "mouseout", this.recover.bindEvent(this,i)); 3051 Event.observe(this.radios[i].parentNode, "click", this.click.bindEvent(this, i)); 3052 } 3053 this.caption = CAPTION(); 3054 this.element.appendChild(this.caption); 3055 this.selectedIndex = options.selectedIndex; 3056 this.setRating(this.selectedIndex); 3057 }, 3058 3059 hover : function(ev,index) 3060 { 3061 for(var i = 0; i<this.radios.length; i++) 3062 this.radios[i].parentNode.className = (i<=index) ? "rating_hover" : ""; 3063 this.setCaption(index); 3064 }, 3065 3066 recover : function(ev,index) 3067 { 3068 for(var i = 0; i<=index; i++) 3069 Element.removeClassName(this.radios[i].parentNode, "rating_hover"); 3070 this.setRating(this.selectedIndex); 3071 }, 3072 3073 click : function(ev, index) 3074 { 3075 for(var i = 0; i<this.radios.length; i++) 3076 this.radios[i].checked = (i == index); 3077 this.selectedIndex = index; 3078 this.setRating(index); 3079 if(isFunction(this.options.onChange)) 3080 this.options.onChange(this,index); 3081 }, 3082 3083 setRating: function(index) 3084 { 3085 for(var i = 0; i<=index; i++) 3086 this.radios[i].parentNode.className = "rating_selected"; 3087 this.setCaption(index); 3088 }, 3089 3090 setCaption : function(index) 3091 { 3092 this.caption.innerHTML = index > -1 ? 3093 this.radios[index].value : this.options.caption; 3094 } 3095 } 3096
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |