Changeset 618
- Timestamp:
- Jun 21, 2008, 6:43:15 PM (16 years ago)
- Location:
- trunk/packages/sipb-xen-www/code
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/sipb-xen-www/code/static/prototype.js
r205 r618 1 /* Prototype JavaScript framework, version 1. 5.1.12 * (c) 2005-200 7Sam Stephenson1 /* Prototype JavaScript framework, version 1.6.0.2 2 * (c) 2005-2008 Sam Stephenson 3 3 * 4 4 * Prototype is freely distributable under the terms of an MIT-style license. 5 5 * For details, see the Prototype web site: http://www.prototypejs.org/ 6 6 * 7 /*--------------------------------------------------------------------------*/7 *--------------------------------------------------------------------------*/ 8 8 9 9 var Prototype = { 10 Version: '1. 5.1.1',10 Version: '1.6.0.2', 11 11 12 12 Browser: { … … 14 14 Opera: !!window.opera, 15 15 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, 16 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 16 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, 17 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) 17 18 }, 18 19 … … 21 22 ElementExtensions: !!window.HTMLElement, 22 23 SpecificElementExtensions: 23 (document.createElement('div').__proto__ !== 24 document.createElement('form').__proto__) 24 document.createElement('div').__proto__ && 25 document.createElement('div').__proto__ !== 26 document.createElement('form').__proto__ 25 27 }, 26 28 … … 30 32 emptyFunction: function() { }, 31 33 K: function(x) { return x } 32 } 33 34 }; 35 36 if (Prototype.Browser.MobileSafari) 37 Prototype.BrowserFeatures.SpecificElementExtensions = false; 38 39 40 /* Based on Alex Arnell's inheritance implementation. */ 34 41 var Class = { 35 42 create: function() { 36 return function() { 43 var parent = null, properties = $A(arguments); 44 if (Object.isFunction(properties[0])) 45 parent = properties.shift(); 46 47 function klass() { 37 48 this.initialize.apply(this, arguments); 38 49 } 39 } 40 } 41 42 var Abstract = new Object(); 50 51 Object.extend(klass, Class.Methods); 52 klass.superclass = parent; 53 klass.subclasses = []; 54 55 if (parent) { 56 var subclass = function() { }; 57 subclass.prototype = parent.prototype; 58 klass.prototype = new subclass; 59 parent.subclasses.push(klass); 60 } 61 62 for (var i = 0; i < properties.length; i++) 63 klass.addMethods(properties[i]); 64 65 if (!klass.prototype.initialize) 66 klass.prototype.initialize = Prototype.emptyFunction; 67 68 klass.prototype.constructor = klass; 69 70 return klass; 71 } 72 }; 73 74 Class.Methods = { 75 addMethods: function(source) { 76 var ancestor = this.superclass && this.superclass.prototype; 77 var properties = Object.keys(source); 78 79 if (!Object.keys({ toString: true }).length) 80 properties.push("toString", "valueOf"); 81 82 for (var i = 0, length = properties.length; i < length; i++) { 83 var property = properties[i], value = source[property]; 84 if (ancestor && Object.isFunction(value) && 85 value.argumentNames().first() == "$super") { 86 var method = value, value = Object.extend((function(m) { 87 return function() { return ancestor[m].apply(this, arguments) }; 88 })(property).wrap(method), { 89 valueOf: function() { return method }, 90 toString: function() { return method.toString() } 91 }); 92 } 93 this.prototype[property] = value; 94 } 95 96 return this; 97 } 98 }; 99 100 var Abstract = { }; 43 101 44 102 Object.extend = function(destination, source) { 45 for (var property in source) {103 for (var property in source) 46 104 destination[property] = source[property]; 47 }48 105 return destination; 49 } 106 }; 50 107 51 108 Object.extend(Object, { 52 109 inspect: function(object) { 53 110 try { 54 if ( object === undefined) return 'undefined';111 if (Object.isUndefined(object)) return 'undefined'; 55 112 if (object === null) return 'null'; 56 return object.inspect ? object.inspect() : object.toString();113 return object.inspect ? object.inspect() : String(object); 57 114 } catch (e) { 58 115 if (e instanceof RangeError) return '...'; … … 63 120 toJSON: function(object) { 64 121 var type = typeof object; 65 switch (type) {122 switch (type) { 66 123 case 'undefined': 67 124 case 'function': … … 69 126 case 'boolean': return object.toString(); 70 127 } 128 71 129 if (object === null) return 'null'; 72 130 if (object.toJSON) return object.toJSON(); 73 if (object.ownerDocument === document) return; 131 if (Object.isElement(object)) return; 132 74 133 var results = []; 75 134 for (var property in object) { 76 135 var value = Object.toJSON(object[property]); 77 if ( value !== undefined)136 if (!Object.isUndefined(value)) 78 137 results.push(property.toJSON() + ': ' + value); 79 138 } 139 80 140 return '{' + results.join(', ') + '}'; 141 }, 142 143 toQueryString: function(object) { 144 return $H(object).toQueryString(); 145 }, 146 147 toHTML: function(object) { 148 return object && object.toHTML ? object.toHTML() : String.interpret(object); 81 149 }, 82 150 … … 96 164 97 165 clone: function(object) { 98 return Object.extend({}, object); 166 return Object.extend({ }, object); 167 }, 168 169 isElement: function(object) { 170 return object && object.nodeType == 1; 171 }, 172 173 isArray: function(object) { 174 return object != null && typeof object == "object" && 175 'splice' in object && 'join' in object; 176 }, 177 178 isHash: function(object) { 179 return object instanceof Hash; 180 }, 181 182 isFunction: function(object) { 183 return typeof object == "function"; 184 }, 185 186 isString: function(object) { 187 return typeof object == "string"; 188 }, 189 190 isNumber: function(object) { 191 return typeof object == "number"; 192 }, 193 194 isUndefined: function(object) { 195 return typeof object == "undefined"; 99 196 } 100 197 }); 101 198 102 Function.prototype.bind = function() { 103 var __method = this, args = $A(arguments), object = args.shift(); 104 return function() { 105 return __method.apply(object, args.concat($A(arguments))); 106 } 107 } 108 109 Function.prototype.bindAsEventListener = function(object) { 110 var __method = this, args = $A(arguments), object = args.shift(); 111 return function(event) { 112 return __method.apply(object, [event || window.event].concat(args)); 113 } 114 } 115 116 Object.extend(Number.prototype, { 117 toColorPart: function() { 118 return this.toPaddedString(2, 16); 119 }, 120 121 succ: function() { 122 return this + 1; 123 }, 124 125 times: function(iterator) { 126 $R(0, this, true).each(iterator); 127 return this; 128 }, 129 130 toPaddedString: function(length, radix) { 131 var string = this.toString(radix || 10); 132 return '0'.times(length - string.length) + string; 133 }, 134 135 toJSON: function() { 136 return isFinite(this) ? this.toString() : 'null'; 199 Object.extend(Function.prototype, { 200 argumentNames: function() { 201 var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); 202 return names.length == 1 && !names[0] ? [] : names; 203 }, 204 205 bind: function() { 206 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 207 var __method = this, args = $A(arguments), object = args.shift(); 208 return function() { 209 return __method.apply(object, args.concat($A(arguments))); 210 } 211 }, 212 213 bindAsEventListener: function() { 214 var __method = this, args = $A(arguments), object = args.shift(); 215 return function(event) { 216 return __method.apply(object, [event || window.event].concat(args)); 217 } 218 }, 219 220 curry: function() { 221 if (!arguments.length) return this; 222 var __method = this, args = $A(arguments); 223 return function() { 224 return __method.apply(this, args.concat($A(arguments))); 225 } 226 }, 227 228 delay: function() { 229 var __method = this, args = $A(arguments), timeout = args.shift() * 1000; 230 return window.setTimeout(function() { 231 return __method.apply(__method, args); 232 }, timeout); 233 }, 234 235 wrap: function(wrapper) { 236 var __method = this; 237 return function() { 238 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 239 } 240 }, 241 242 methodize: function() { 243 if (this._methodized) return this._methodized; 244 var __method = this; 245 return this._methodized = function() { 246 return __method.apply(null, [this].concat($A(arguments))); 247 }; 137 248 } 138 249 }); 139 250 251 Function.prototype.defer = Function.prototype.delay.curry(0.01); 252 140 253 Date.prototype.toJSON = function() { 141 return '"' + this.get FullYear() + '-' +142 (this.get Month() + 1).toPaddedString(2) + '-' +143 this.get Date().toPaddedString(2) + 'T' +144 this.get Hours().toPaddedString(2) + ':' +145 this.get Minutes().toPaddedString(2) + ':' +146 this.get Seconds().toPaddedString(2) + '"';254 return '"' + this.getUTCFullYear() + '-' + 255 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 256 this.getUTCDate().toPaddedString(2) + 'T' + 257 this.getUTCHours().toPaddedString(2) + ':' + 258 this.getUTCMinutes().toPaddedString(2) + ':' + 259 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 147 260 }; 148 261 … … 156 269 returnValue = lambda(); 157 270 break; 158 } catch (e) { }271 } catch (e) { } 159 272 } 160 273 161 274 return returnValue; 162 275 } 163 } 276 }; 277 278 RegExp.prototype.match = RegExp.prototype.test; 279 280 RegExp.escape = function(str) { 281 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 282 }; 164 283 165 284 /*--------------------------------------------------------------------------*/ 166 285 167 var PeriodicalExecuter = Class.create(); 168 PeriodicalExecuter.prototype = { 286 var PeriodicalExecuter = Class.create({ 169 287 initialize: function(callback, frequency) { 170 288 this.callback = callback; … … 179 297 }, 180 298 299 execute: function() { 300 this.callback(this); 301 }, 302 181 303 stop: function() { 182 304 if (!this.timer) return; … … 189 311 try { 190 312 this.currentlyExecuting = true; 191 this. callback(this);313 this.execute(); 192 314 } finally { 193 315 this.currentlyExecuting = false; … … 195 317 } 196 318 } 197 } 319 }); 198 320 Object.extend(String, { 199 321 interpret: function(value) { … … 229 351 sub: function(pattern, replacement, count) { 230 352 replacement = this.gsub.prepareReplacement(replacement); 231 count = count === undefined? 1 : count;353 count = Object.isUndefined(count) ? 1 : count; 232 354 233 355 return this.gsub(pattern, function(match) { … … 239 361 scan: function(pattern, iterator) { 240 362 this.gsub(pattern, iterator); 241 return this;363 return String(this); 242 364 }, 243 365 244 366 truncate: function(length, truncation) { 245 367 length = length || 30; 246 truncation = truncation === undefined? '...' : truncation;368 truncation = Object.isUndefined(truncation) ? '...' : truncation; 247 369 return this.length > length ? 248 this.slice(0, length - truncation.length) + truncation : this;370 this.slice(0, length - truncation.length) + truncation : String(this); 249 371 }, 250 372 … … 280 402 281 403 unescapeHTML: function() { 282 var div = document.createElement('div');404 var div = new Element('div'); 283 405 div.innerHTML = this.stripTags(); 284 406 return div.childNodes[0] ? (div.childNodes.length > 1 ? … … 289 411 toQueryParams: function(separator) { 290 412 var match = this.strip().match(/([^?#]*)(#.*)?$/); 291 if (!match) return { };292 293 return match[1].split(separator || '&').inject({ }, function(hash, pair) {413 if (!match) return { }; 414 415 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 294 416 if ((pair = pair.split('='))[0]) { 295 417 var key = decodeURIComponent(pair.shift()); … … 298 420 299 421 if (key in hash) { 300 if ( hash[key].constructor != Array) hash[key] = [hash[key]];422 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 301 423 hash[key].push(value); 302 424 } … … 317 439 318 440 times: function(count) { 319 var result = ''; 320 for (var i = 0; i < count; i++) result += this; 321 return result; 441 return count < 1 ? '' : new Array(count + 1).join(this); 322 442 }, 323 443 … … 366 486 367 487 isJSON: function() { 368 var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 488 var str = this; 489 if (str.blank()) return false; 490 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 369 491 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 370 492 }, … … 397 519 blank: function() { 398 520 return /^\s*$/.test(this); 521 }, 522 523 interpolate: function(object, pattern) { 524 return new Template(this, pattern).evaluate(object); 399 525 } 400 526 }); … … 410 536 411 537 String.prototype.gsub.prepareReplacement = function(replacement) { 412 if ( typeof replacement == 'function') return replacement;538 if (Object.isFunction(replacement)) return replacement; 413 539 var template = new Template(replacement); 414 540 return function(match) { return template.evaluate(match) }; 415 } 541 }; 416 542 417 543 String.prototype.parseQuery = String.prototype.toQueryParams; … … 424 550 with (String.prototype.escapeHTML) div.appendChild(text); 425 551 426 var Template = Class.create(); 427 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 428 Template.prototype = { 552 var Template = Class.create({ 429 553 initialize: function(template, pattern) { 430 554 this.template = template.toString(); 431 this.pattern 555 this.pattern = pattern || Template.Pattern; 432 556 }, 433 557 434 558 evaluate: function(object) { 559 if (Object.isFunction(object.toTemplateReplacements)) 560 object = object.toTemplateReplacements(); 561 435 562 return this.template.gsub(this.pattern, function(match) { 436 var before = match[1]; 563 if (object == null) return ''; 564 565 var before = match[1] || ''; 437 566 if (before == '\\') return match[2]; 438 return before + String.interpret(object[match[3]]); 567 568 var ctx = object, expr = match[3]; 569 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 570 match = pattern.exec(expr); 571 if (match == null) return before; 572 573 while (match != null) { 574 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 575 ctx = ctx[comp]; 576 if (null == ctx || '' == match[3]) break; 577 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 578 match = pattern.exec(expr); 579 } 580 581 return before + String.interpret(ctx); 439 582 }); 440 583 } 441 } 442 443 var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 584 }); 585 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 586 587 var $break = { }; 444 588 445 589 var Enumerable = { 446 each: function(iterator ) {590 each: function(iterator, context) { 447 591 var index = 0; 592 iterator = iterator.bind(context); 448 593 try { 449 594 this._each(function(value) { … … 456 601 }, 457 602 458 eachSlice: function(number, iterator) { 603 eachSlice: function(number, iterator, context) { 604 iterator = iterator ? iterator.bind(context) : Prototype.K; 459 605 var index = -number, slices = [], array = this.toArray(); 460 606 while ((index += number) < array.length) 461 607 slices.push(array.slice(index, index+number)); 462 return slices.map(iterator); 463 }, 464 465 all: function(iterator) { 608 return slices.collect(iterator, context); 609 }, 610 611 all: function(iterator, context) { 612 iterator = iterator ? iterator.bind(context) : Prototype.K; 466 613 var result = true; 467 614 this.each(function(value, index) { 468 result = result && !! (iterator || Prototype.K)(value, index);615 result = result && !!iterator(value, index); 469 616 if (!result) throw $break; 470 617 }); … … 472 619 }, 473 620 474 any: function(iterator) { 621 any: function(iterator, context) { 622 iterator = iterator ? iterator.bind(context) : Prototype.K; 475 623 var result = false; 476 624 this.each(function(value, index) { 477 if (result = !! (iterator || Prototype.K)(value, index))625 if (result = !!iterator(value, index)) 478 626 throw $break; 479 627 }); … … 481 629 }, 482 630 483 collect: function(iterator) { 631 collect: function(iterator, context) { 632 iterator = iterator ? iterator.bind(context) : Prototype.K; 484 633 var results = []; 485 634 this.each(function(value, index) { 486 results.push( (iterator || Prototype.K)(value, index));635 results.push(iterator(value, index)); 487 636 }); 488 637 return results; 489 638 }, 490 639 491 detect: function(iterator) { 640 detect: function(iterator, context) { 641 iterator = iterator.bind(context); 492 642 var result; 493 643 this.each(function(value, index) { … … 500 650 }, 501 651 502 findAll: function(iterator) { 652 findAll: function(iterator, context) { 653 iterator = iterator.bind(context); 503 654 var results = []; 504 655 this.each(function(value, index) { … … 509 660 }, 510 661 511 grep: function(pattern, iterator) { 662 grep: function(filter, iterator, context) { 663 iterator = iterator ? iterator.bind(context) : Prototype.K; 512 664 var results = []; 665 666 if (Object.isString(filter)) 667 filter = new RegExp(filter); 668 513 669 this.each(function(value, index) { 514 var stringValue = value.toString(); 515 if (stringValue.match(pattern)) 516 results.push((iterator || Prototype.K)(value, index)); 517 }) 670 if (filter.match(value)) 671 results.push(iterator(value, index)); 672 }); 518 673 return results; 519 674 }, 520 675 521 676 include: function(object) { 677 if (Object.isFunction(this.indexOf)) 678 if (this.indexOf(object) != -1) return true; 679 522 680 var found = false; 523 681 this.each(function(value) { … … 531 689 532 690 inGroupsOf: function(number, fillWith) { 533 fillWith = fillWith === undefined? null : fillWith;691 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 534 692 return this.eachSlice(number, function(slice) { 535 693 while(slice.length < number) slice.push(fillWith); … … 538 696 }, 539 697 540 inject: function(memo, iterator) { 698 inject: function(memo, iterator, context) { 699 iterator = iterator.bind(context); 541 700 this.each(function(value, index) { 542 701 memo = iterator(memo, value, index); … … 552 711 }, 553 712 554 max: function(iterator) { 713 max: function(iterator, context) { 714 iterator = iterator ? iterator.bind(context) : Prototype.K; 555 715 var result; 556 716 this.each(function(value, index) { 557 value = (iterator || Prototype.K)(value, index);558 if (result == undefined|| value >= result)717 value = iterator(value, index); 718 if (result == null || value >= result) 559 719 result = value; 560 720 }); … … 562 722 }, 563 723 564 min: function(iterator) { 724 min: function(iterator, context) { 725 iterator = iterator ? iterator.bind(context) : Prototype.K; 565 726 var result; 566 727 this.each(function(value, index) { 567 value = (iterator || Prototype.K)(value, index);568 if (result == undefined|| value < result)728 value = iterator(value, index); 729 if (result == null || value < result) 569 730 result = value; 570 731 }); … … 572 733 }, 573 734 574 partition: function(iterator) { 735 partition: function(iterator, context) { 736 iterator = iterator ? iterator.bind(context) : Prototype.K; 575 737 var trues = [], falses = []; 576 738 this.each(function(value, index) { 577 ( (iterator || Prototype.K)(value, index) ?739 (iterator(value, index) ? 578 740 trues : falses).push(value); 579 741 }); … … 583 745 pluck: function(property) { 584 746 var results = []; 585 this.each(function(value , index) {747 this.each(function(value) { 586 748 results.push(value[property]); 587 749 }); … … 589 751 }, 590 752 591 reject: function(iterator) { 753 reject: function(iterator, context) { 754 iterator = iterator.bind(context); 592 755 var results = []; 593 756 this.each(function(value, index) { … … 598 761 }, 599 762 600 sortBy: function(iterator) { 763 sortBy: function(iterator, context) { 764 iterator = iterator.bind(context); 601 765 return this.map(function(value, index) { 602 766 return {value: value, criteria: iterator(value, index)}; … … 613 777 zip: function() { 614 778 var iterator = Prototype.K, args = $A(arguments); 615 if ( typeof args.last() == 'function')779 if (Object.isFunction(args.last())) 616 780 iterator = args.pop(); 617 781 … … 629 793 return '#<Enumerable:' + this.toArray().inspect() + '>'; 630 794 } 631 } 795 }; 632 796 633 797 Object.extend(Enumerable, { … … 635 799 find: Enumerable.detect, 636 800 select: Enumerable.findAll, 801 filter: Enumerable.findAll, 637 802 member: Enumerable.include, 638 entries: Enumerable.toArray 803 entries: Enumerable.toArray, 804 every: Enumerable.all, 805 some: Enumerable.any 639 806 }); 640 var $A = Array.from = function(iterable) {807 function $A(iterable) { 641 808 if (!iterable) return []; 642 if (iterable.toArray) { 643 return iterable.toArray(); 644 } else { 645 var results = []; 646 for (var i = 0, length = iterable.length; i < length; i++) 647 results.push(iterable[i]); 809 if (iterable.toArray) return iterable.toArray(); 810 var length = iterable.length || 0, results = new Array(length); 811 while (length--) results[length] = iterable[length]; 812 return results; 813 } 814 815 if (Prototype.Browser.WebKit) { 816 $A = function(iterable) { 817 if (!iterable) return []; 818 if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && 819 iterable.toArray) return iterable.toArray(); 820 var length = iterable.length || 0, results = new Array(length); 821 while (length--) results[length] = iterable[length]; 648 822 return results; 649 } 823 }; 650 824 } 651 825 652 if (Prototype.Browser.WebKit) { 653 $A = Array.from = function(iterable) { 654 if (!iterable) return []; 655 if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && 656 iterable.toArray) { 657 return iterable.toArray(); 658 } else { 659 var results = []; 660 for (var i = 0, length = iterable.length; i < length; i++) 661 results.push(iterable[i]); 662 return results; 663 } 664 } 665 } 826 Array.from = $A; 666 827 667 828 Object.extend(Array.prototype, Enumerable); 668 829 669 if (!Array.prototype._reverse) 670 Array.prototype._reverse = Array.prototype.reverse; 830 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 671 831 672 832 Object.extend(Array.prototype, { … … 697 857 flatten: function() { 698 858 return this.inject([], function(array, value) { 699 return array.concat( value && value.constructor == Array?859 return array.concat(Object.isArray(value) ? 700 860 value.flatten() : [value]); 701 861 }); … … 707 867 return !values.include(value); 708 868 }); 709 },710 711 indexOf: function(object) {712 for (var i = 0, length = this.length; i < length; i++)713 if (this[i] == object) return i;714 return -1;715 869 }, 716 870 … … 731 885 }, 732 886 887 intersect: function(array) { 888 return this.uniq().findAll(function(item) { 889 return array.detect(function(value) { return item === value }); 890 }); 891 }, 892 733 893 clone: function() { 734 894 return [].concat(this); … … 747 907 this.each(function(object) { 748 908 var value = Object.toJSON(object); 749 if ( value !== undefined) results.push(value);909 if (!Object.isUndefined(value)) results.push(value); 750 910 }); 751 911 return '[' + results.join(', ') + ']'; … … 753 913 }); 754 914 915 // use native browser JS 1.6 implementation if available 916 if (Object.isFunction(Array.prototype.forEach)) 917 Array.prototype._each = Array.prototype.forEach; 918 919 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { 920 i || (i = 0); 921 var length = this.length; 922 if (i < 0) i = length + i; 923 for (; i < length; i++) 924 if (this[i] === item) return i; 925 return -1; 926 }; 927 928 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { 929 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 930 var n = this.slice(0, i).reverse().indexOf(item); 931 return (n < 0) ? n : i - n - 1; 932 }; 933 755 934 Array.prototype.toArray = Array.prototype.clone; 756 935 757 936 function $w(string) { 937 if (!Object.isString(string)) return []; 758 938 string = string.strip(); 759 939 return string ? string.split(/\s+/) : []; … … 765 945 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 766 946 for (var i = 0, length = arguments.length; i < length; i++) { 767 if ( arguments[i].constructor == Array) {947 if (Object.isArray(arguments[i])) { 768 948 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 769 949 array.push(arguments[i][j]); … … 773 953 } 774 954 return array; 775 } 955 }; 776 956 } 777 var Hash = function(object) { 778 if (object instanceof Hash) this.merge(object); 779 else Object.extend(this, object || {}); 780 }; 781 782 Object.extend(Hash, { 783 toQueryString: function(obj) { 784 var parts = []; 785 parts.add = arguments.callee.addPair; 786 787 this.prototype._each.call(obj, function(pair) { 788 if (!pair.key) return; 789 var value = pair.value; 790 791 if (value && typeof value == 'object') { 792 if (value.constructor == Array) value.each(function(value) { 793 parts.add(pair.key, value); 794 }); 795 return; 796 } 797 parts.add(pair.key, value); 798 }); 799 800 return parts.join('&'); 801 }, 802 803 toJSON: function(object) { 804 var results = []; 805 this.prototype._each.call(object, function(pair) { 806 var value = Object.toJSON(pair.value); 807 if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); 808 }); 809 return '{' + results.join(', ') + '}'; 957 Object.extend(Number.prototype, { 958 toColorPart: function() { 959 return this.toPaddedString(2, 16); 960 }, 961 962 succ: function() { 963 return this + 1; 964 }, 965 966 times: function(iterator) { 967 $R(0, this, true).each(iterator); 968 return this; 969 }, 970 971 toPaddedString: function(length, radix) { 972 var string = this.toString(radix || 10); 973 return '0'.times(length - string.length) + string; 974 }, 975 976 toJSON: function() { 977 return isFinite(this) ? this.toString() : 'null'; 810 978 } 811 979 }); 812 980 813 Hash.toQueryString.addPair = function(key, value, prefix) { 814 key = encodeURIComponent(key); 815 if (value === undefined) this.push(key); 816 else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); 817 } 818 819 Object.extend(Hash.prototype, Enumerable); 820 Object.extend(Hash.prototype, { 821 _each: function(iterator) { 822 for (var key in this) { 823 var value = this[key]; 824 if (value && value == Hash.prototype[key]) continue; 825 826 var pair = [key, value]; 827 pair.key = key; 828 pair.value = value; 829 iterator(pair); 830 } 831 }, 832 833 keys: function() { 834 return this.pluck('key'); 835 }, 836 837 values: function() { 838 return this.pluck('value'); 839 }, 840 841 merge: function(hash) { 842 return $H(hash).inject(this, function(mergedHash, pair) { 843 mergedHash[pair.key] = pair.value; 844 return mergedHash; 845 }); 846 }, 847 848 remove: function() { 849 var result; 850 for(var i = 0, length = arguments.length; i < length; i++) { 851 var value = this[arguments[i]]; 852 if (value !== undefined){ 853 if (result === undefined) result = value; 854 else { 855 if (result.constructor != Array) result = [result]; 856 result.push(value) 857 } 858 } 859 delete this[arguments[i]]; 860 } 861 return result; 862 }, 863 864 toQueryString: function() { 865 return Hash.toQueryString(this); 866 }, 867 868 inspect: function() { 869 return '#<Hash:{' + this.map(function(pair) { 870 return pair.map(Object.inspect).join(': '); 871 }).join(', ') + '}>'; 872 }, 873 874 toJSON: function() { 875 return Hash.toJSON(this); 876 } 981 $w('abs round ceil floor').each(function(method){ 982 Number.prototype[method] = Math[method].methodize(); 877 983 }); 878 879 984 function $H(object) { 880 if (object instanceof Hash) return object;881 985 return new Hash(object); 882 986 }; 883 987 884 // Safari iterates over shadowed properties 885 if (function() { 886 var i = 0, Test = function(value) { this.key = value }; 887 Test.prototype.key = 'foo'; 888 for (var property in new Test('bar')) i++; 889 return i > 1; 890 }()) Hash.prototype._each = function(iterator) { 891 var cache = []; 892 for (var key in this) { 893 var value = this[key]; 894 if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; 895 cache.push(key); 896 var pair = [key, value]; 897 pair.key = key; 898 pair.value = value; 899 iterator(pair); 900 } 901 }; 902 ObjectRange = Class.create(); 903 Object.extend(ObjectRange.prototype, Enumerable); 904 Object.extend(ObjectRange.prototype, { 988 var Hash = Class.create(Enumerable, (function() { 989 990 function toQueryPair(key, value) { 991 if (Object.isUndefined(value)) return key; 992 return key + '=' + encodeURIComponent(String.interpret(value)); 993 } 994 995 return { 996 initialize: function(object) { 997 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 998 }, 999 1000 _each: function(iterator) { 1001 for (var key in this._object) { 1002 var value = this._object[key], pair = [key, value]; 1003 pair.key = key; 1004 pair.value = value; 1005 iterator(pair); 1006 } 1007 }, 1008 1009 set: function(key, value) { 1010 return this._object[key] = value; 1011 }, 1012 1013 get: function(key) { 1014 return this._object[key]; 1015 }, 1016 1017 unset: function(key) { 1018 var value = this._object[key]; 1019 delete this._object[key]; 1020 return value; 1021 }, 1022 1023 toObject: function() { 1024 return Object.clone(this._object); 1025 }, 1026 1027 keys: function() { 1028 return this.pluck('key'); 1029 }, 1030 1031 values: function() { 1032 return this.pluck('value'); 1033 }, 1034 1035 index: function(value) { 1036 var match = this.detect(function(pair) { 1037 return pair.value === value; 1038 }); 1039 return match && match.key; 1040 }, 1041 1042 merge: function(object) { 1043 return this.clone().update(object); 1044 }, 1045 1046 update: function(object) { 1047 return new Hash(object).inject(this, function(result, pair) { 1048 result.set(pair.key, pair.value); 1049 return result; 1050 }); 1051 }, 1052 1053 toQueryString: function() { 1054 return this.map(function(pair) { 1055 var key = encodeURIComponent(pair.key), values = pair.value; 1056 1057 if (values && typeof values == 'object') { 1058 if (Object.isArray(values)) 1059 return values.map(toQueryPair.curry(key)).join('&'); 1060 } 1061 return toQueryPair(key, values); 1062 }).join('&'); 1063 }, 1064 1065 inspect: function() { 1066 return '#<Hash:{' + this.map(function(pair) { 1067 return pair.map(Object.inspect).join(': '); 1068 }).join(', ') + '}>'; 1069 }, 1070 1071 toJSON: function() { 1072 return Object.toJSON(this.toObject()); 1073 }, 1074 1075 clone: function() { 1076 return new Hash(this); 1077 } 1078 } 1079 })()); 1080 1081 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; 1082 Hash.from = $H; 1083 var ObjectRange = Class.create(Enumerable, { 905 1084 initialize: function(start, end, exclusive) { 906 1085 this.start = start; … … 928 1107 var $R = function(start, end, exclusive) { 929 1108 return new ObjectRange(start, end, exclusive); 930 } 1109 }; 931 1110 932 1111 var Ajax = { … … 940 1119 941 1120 activeRequestCount: 0 942 } 1121 }; 943 1122 944 1123 Ajax.Responders = { … … 960 1139 dispatch: function(callback, request, transport, json) { 961 1140 this.each(function(responder) { 962 if ( typeof responder[callback] == 'function') {1141 if (Object.isFunction(responder[callback])) { 963 1142 try { 964 1143 responder[callback].apply(responder, [request, transport, json]); 965 } catch (e) { }1144 } catch (e) { } 966 1145 } 967 1146 }); … … 972 1151 973 1152 Ajax.Responders.register({ 974 onCreate: function() { 975 Ajax.activeRequestCount++; 976 }, 977 onComplete: function() { 978 Ajax.activeRequestCount--; 979 } 1153 onCreate: function() { Ajax.activeRequestCount++ }, 1154 onComplete: function() { Ajax.activeRequestCount-- } 980 1155 }); 981 1156 982 Ajax.Base = function() {}; 983 Ajax.Base.prototype = { 984 setOptions: function(options) { 1157 Ajax.Base = Class.create({ 1158 initialize: function(options) { 985 1159 this.options = { 986 1160 method: 'post', … … 988 1162 contentType: 'application/x-www-form-urlencoded', 989 1163 encoding: 'UTF-8', 990 parameters: '' 991 } 992 Object.extend(this.options, options || {}); 1164 parameters: '', 1165 evalJSON: true, 1166 evalJS: true 1167 }; 1168 Object.extend(this.options, options || { }); 993 1169 994 1170 this.options.method = this.options.method.toLowerCase(); 995 if (typeof this.options.parameters == 'string') 1171 1172 if (Object.isString(this.options.parameters)) 996 1173 this.options.parameters = this.options.parameters.toQueryParams(); 997 } 998 } 999 1000 Ajax.Request = Class.create(); 1001 Ajax.Request.Events = 1002 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1003 1004 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 1174 else if (Object.isHash(this.options.parameters)) 1175 this.options.parameters = this.options.parameters.toObject(); 1176 } 1177 }); 1178 1179 Ajax.Request = Class.create(Ajax.Base, { 1005 1180 _complete: false, 1006 1181 1007 initialize: function(url, options) { 1182 initialize: function($super, url, options) { 1183 $super(options); 1008 1184 this.transport = Ajax.getTransport(); 1009 this.setOptions(options);1010 1185 this.request(url); 1011 1186 }, … … 1024 1199 this.parameters = params; 1025 1200 1026 if (params = Hash.toQueryString(params)) {1201 if (params = Object.toQueryString(params)) { 1027 1202 // when GET, append parameters to URL 1028 1203 if (this.method == 'get') … … 1033 1208 1034 1209 try { 1035 if (this.options.onCreate) this.options.onCreate(this.transport); 1036 Ajax.Responders.dispatch('onCreate', this, this.transport); 1210 var response = new Ajax.Response(this); 1211 if (this.options.onCreate) this.options.onCreate(response); 1212 Ajax.Responders.dispatch('onCreate', this, response); 1037 1213 1038 1214 this.transport.open(this.method.toUpperCase(), this.url, 1039 1215 this.options.asynchronous); 1040 1216 1041 if (this.options.asynchronous) 1042 setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); 1217 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 1043 1218 1044 1219 this.transport.onreadystatechange = this.onStateChange.bind(this); … … 1088 1263 var extras = this.options.requestHeaders; 1089 1264 1090 if ( typeof extras.push == 'function')1265 if (Object.isFunction(extras.push)) 1091 1266 for (var i = 0, length = extras.length; i < length; i += 2) 1092 1267 headers[extras[i]] = extras[i+1]; … … 1100 1275 1101 1276 success: function() { 1102 return !this.transport.status 1103 || (this.transport.status >= 200 && this.transport.status < 300); 1277 var status = this.getStatus(); 1278 return !status || (status >= 200 && status < 300); 1279 }, 1280 1281 getStatus: function() { 1282 try { 1283 return this.transport.status || 0; 1284 } catch (e) { return 0 } 1104 1285 }, 1105 1286 1106 1287 respondToReadyState: function(readyState) { 1107 var state = Ajax.Request.Events[readyState]; 1108 var transport = this.transport, json = this.evalJSON(); 1288 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 1109 1289 1110 1290 if (state == 'Complete') { 1111 1291 try { 1112 1292 this._complete = true; 1113 (this.options['on' + this.transport.status]1293 (this.options['on' + response.status] 1114 1294 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 1115 || Prototype.emptyFunction)( transport, json);1295 || Prototype.emptyFunction)(response, response.headerJSON); 1116 1296 } catch (e) { 1117 1297 this.dispatchException(e); 1118 1298 } 1119 1299 1120 var contentType = this.getHeader('Content-type'); 1121 if (contentType && contentType.strip(). 1122 match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) 1123 this.evalResponse(); 1300 var contentType = response.getHeader('Content-type'); 1301 if (this.options.evalJS == 'force' 1302 || (this.options.evalJS && this.isSameOrigin() && contentType 1303 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1304 this.evalResponse(); 1124 1305 } 1125 1306 1126 1307 try { 1127 (this.options['on' + state] || Prototype.emptyFunction)( transport, json);1128 Ajax.Responders.dispatch('on' + state, this, transport, json);1308 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 1309 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 1129 1310 } catch (e) { 1130 1311 this.dispatchException(e); … … 1137 1318 }, 1138 1319 1320 isSameOrigin: function() { 1321 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 1322 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 1323 protocol: location.protocol, 1324 domain: document.domain, 1325 port: location.port ? ':' + location.port : '' 1326 })); 1327 }, 1328 1139 1329 getHeader: function(name) { 1140 1330 try { 1141 return this.transport.getResponseHeader(name); 1142 } catch (e) { return null } 1143 }, 1144 1145 evalJSON: function() { 1146 try { 1147 var json = this.getHeader('X-JSON'); 1148 return json ? json.evalJSON() : null; 1331 return this.transport.getResponseHeader(name) || null; 1149 1332 } catch (e) { return null } 1150 1333 }, … … 1164 1347 }); 1165 1348 1166 Ajax.Updater = Class.create(); 1167 1168 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 1169 initialize: function(container, url, options) { 1349 Ajax.Request.Events = 1350 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1351 1352 Ajax.Response = Class.create({ 1353 initialize: function(request){ 1354 this.request = request; 1355 var transport = this.transport = request.transport, 1356 readyState = this.readyState = transport.readyState; 1357 1358 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 1359 this.status = this.getStatus(); 1360 this.statusText = this.getStatusText(); 1361 this.responseText = String.interpret(transport.responseText); 1362 this.headerJSON = this._getHeaderJSON(); 1363 } 1364 1365 if(readyState == 4) { 1366 var xml = transport.responseXML; 1367 this.responseXML = Object.isUndefined(xml) ? null : xml; 1368 this.responseJSON = this._getResponseJSON(); 1369 } 1370 }, 1371 1372 status: 0, 1373 statusText: '', 1374 1375 getStatus: Ajax.Request.prototype.getStatus, 1376 1377 getStatusText: function() { 1378 try { 1379 return this.transport.statusText || ''; 1380 } catch (e) { return '' } 1381 }, 1382 1383 getHeader: Ajax.Request.prototype.getHeader, 1384 1385 getAllHeaders: function() { 1386 try { 1387 return this.getAllResponseHeaders(); 1388 } catch (e) { return null } 1389 }, 1390 1391 getResponseHeader: function(name) { 1392 return this.transport.getResponseHeader(name); 1393 }, 1394 1395 getAllResponseHeaders: function() { 1396 return this.transport.getAllResponseHeaders(); 1397 }, 1398 1399 _getHeaderJSON: function() { 1400 var json = this.getHeader('X-JSON'); 1401 if (!json) return null; 1402 json = decodeURIComponent(escape(json)); 1403 try { 1404 return json.evalJSON(this.request.options.sanitizeJSON || 1405 !this.request.isSameOrigin()); 1406 } catch (e) { 1407 this.request.dispatchException(e); 1408 } 1409 }, 1410 1411 _getResponseJSON: function() { 1412 var options = this.request.options; 1413 if (!options.evalJSON || (options.evalJSON != 'force' && 1414 !(this.getHeader('Content-type') || '').include('application/json')) || 1415 this.responseText.blank()) 1416 return null; 1417 try { 1418 return this.responseText.evalJSON(options.sanitizeJSON || 1419 !this.request.isSameOrigin()); 1420 } catch (e) { 1421 this.request.dispatchException(e); 1422 } 1423 } 1424 }); 1425 1426 Ajax.Updater = Class.create(Ajax.Request, { 1427 initialize: function($super, container, url, options) { 1170 1428 this.container = { 1171 1429 success: (container.success || container), 1172 1430 failure: (container.failure || (container.success ? null : container)) 1173 } 1174 1175 this.transport = Ajax.getTransport(); 1176 this.setOptions(options); 1177 1178 var onComplete = this.options.onComplete || Prototype.emptyFunction; 1179 this.options.onComplete = (function(transport, param) { 1180 this.updateContent(); 1181 onComplete(transport, param); 1431 }; 1432 1433 options = Object.clone(options); 1434 var onComplete = options.onComplete; 1435 options.onComplete = (function(response, json) { 1436 this.updateContent(response.responseText); 1437 if (Object.isFunction(onComplete)) onComplete(response, json); 1182 1438 }).bind(this); 1183 1439 1184 this.request(url);1185 }, 1186 1187 updateContent: function( ) {1188 var receiver = this.container[this.success() ? 'success' : 'failure'] ;1189 var response = this.transport.responseText;1190 1191 if (! this.options.evalScripts) response = response.stripScripts();1440 $super(url, options); 1441 }, 1442 1443 updateContent: function(responseText) { 1444 var receiver = this.container[this.success() ? 'success' : 'failure'], 1445 options = this.options; 1446 1447 if (!options.evalScripts) responseText = responseText.stripScripts(); 1192 1448 1193 1449 if (receiver = $(receiver)) { 1194 if (this.options.insertion) 1195 new this.options.insertion(receiver, response); 1196 else 1197 receiver.update(response); 1198 } 1199 1200 if (this.success()) { 1201 if (this.onComplete) 1202 setTimeout(this.onComplete.bind(this), 10); 1450 if (options.insertion) { 1451 if (Object.isString(options.insertion)) { 1452 var insertion = { }; insertion[options.insertion] = responseText; 1453 receiver.insert(insertion); 1454 } 1455 else options.insertion(receiver, responseText); 1456 } 1457 else receiver.update(responseText); 1203 1458 } 1204 1459 } 1205 1460 }); 1206 1461 1207 Ajax.PeriodicalUpdater = Class.create(); 1208 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { 1209 initialize: function(container, url, options) { 1210 this.setOptions(options); 1462 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 1463 initialize: function($super, container, url, options) { 1464 $super(options); 1211 1465 this.onComplete = this.options.onComplete; 1212 1466 … … 1214 1468 this.decay = (this.options.decay || 1); 1215 1469 1216 this.updater = { };1470 this.updater = { }; 1217 1471 this.container = container; 1218 1472 this.url = url; … … 1232 1486 }, 1233 1487 1234 updateComplete: function(re quest) {1488 updateComplete: function(response) { 1235 1489 if (this.options.decay) { 1236 this.decay = (re quest.responseText == this.lastText ?1490 this.decay = (response.responseText == this.lastText ? 1237 1491 this.decay * this.options.decay : 1); 1238 1492 1239 this.lastText = request.responseText; 1240 } 1241 this.timer = setTimeout(this.onTimerEvent.bind(this), 1242 this.decay * this.frequency * 1000); 1493 this.lastText = response.responseText; 1494 } 1495 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 1243 1496 }, 1244 1497 … … 1253 1506 return elements; 1254 1507 } 1255 if ( typeof element == 'string')1508 if (Object.isString(element)) 1256 1509 element = document.getElementById(element); 1257 1510 return Element.extend(element); … … 1264 1517 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 1265 1518 for (var i = 0, length = query.snapshotLength; i < length; i++) 1266 results.push( query.snapshotItem(i));1519 results.push(Element.extend(query.snapshotItem(i))); 1267 1520 return results; 1268 1521 }; 1269 1270 document.getElementsByClassName = function(className, parentElement) { 1271 var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; 1272 return document._getElementsByXPath(q, parentElement); 1273 } 1274 1275 } else document.getElementsByClassName = function(className, parentElement) { 1276 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 1277 var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)"); 1278 for (var i = 0, length = children.length; i < length; i++) { 1279 child = children[i]; 1280 var elementClassName = child.className; 1281 if (elementClassName.length == 0) continue; 1282 if (elementClassName == className || elementClassName.match(pattern)) 1283 elements.push(Element.extend(child)); 1284 } 1285 return elements; 1286 }; 1522 } 1287 1523 1288 1524 /*--------------------------------------------------------------------------*/ 1289 1525 1290 if (!window.Element) var Element = {}; 1291 1292 Element.extend = function(element) { 1293 var F = Prototype.BrowserFeatures; 1294 if (!element || !element.tagName || element.nodeType == 3 || 1295 element._extended || F.SpecificElementExtensions || element == window) 1296 return element; 1297 1298 var methods = {}, tagName = element.tagName, cache = Element.extend.cache, 1299 T = Element.Methods.ByTag; 1300 1301 // extend methods for all tags (Safari doesn't need this) 1302 if (!F.ElementExtensions) { 1303 Object.extend(methods, Element.Methods), 1304 Object.extend(methods, Element.Methods.Simulated); 1305 } 1306 1307 // extend methods for specific tags 1308 if (T[tagName]) Object.extend(methods, T[tagName]); 1309 1310 for (var property in methods) { 1311 var value = methods[property]; 1312 if (typeof value == 'function' && !(property in element)) 1313 element[property] = cache.findOrStore(value); 1314 } 1315 1316 element._extended = Prototype.emptyFunction; 1317 return element; 1318 }; 1319 1320 Element.extend.cache = { 1321 findOrStore: function(value) { 1322 return this[value] = this[value] || function() { 1323 return value.apply(null, [this].concat($A(arguments))); 1324 } 1325 } 1326 }; 1526 if (!window.Node) var Node = { }; 1527 1528 if (!Node.ELEMENT_NODE) { 1529 // DOM level 2 ECMAScript Language Binding 1530 Object.extend(Node, { 1531 ELEMENT_NODE: 1, 1532 ATTRIBUTE_NODE: 2, 1533 TEXT_NODE: 3, 1534 CDATA_SECTION_NODE: 4, 1535 ENTITY_REFERENCE_NODE: 5, 1536 ENTITY_NODE: 6, 1537 PROCESSING_INSTRUCTION_NODE: 7, 1538 COMMENT_NODE: 8, 1539 DOCUMENT_NODE: 9, 1540 DOCUMENT_TYPE_NODE: 10, 1541 DOCUMENT_FRAGMENT_NODE: 11, 1542 NOTATION_NODE: 12 1543 }); 1544 } 1545 1546 (function() { 1547 var element = this.Element; 1548 this.Element = function(tagName, attributes) { 1549 attributes = attributes || { }; 1550 tagName = tagName.toLowerCase(); 1551 var cache = Element.cache; 1552 if (Prototype.Browser.IE && attributes.name) { 1553 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 1554 delete attributes.name; 1555 return Element.writeAttribute(document.createElement(tagName), attributes); 1556 } 1557 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 1558 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 1559 }; 1560 Object.extend(this.Element, element || { }); 1561 }).call(window); 1562 1563 Element.cache = { }; 1327 1564 1328 1565 Element.Methods = { … … 1353 1590 }, 1354 1591 1355 update: function(element, html) { 1356 html = typeof html == 'undefined' ? '' : html.toString(); 1357 $(element).innerHTML = html.stripScripts(); 1358 setTimeout(function() {html.evalScripts()}, 10); 1592 update: function(element, content) { 1593 element = $(element); 1594 if (content && content.toElement) content = content.toElement(); 1595 if (Object.isElement(content)) return element.update().insert(content); 1596 content = Object.toHTML(content); 1597 element.innerHTML = content.stripScripts(); 1598 content.evalScripts.bind(content).defer(); 1359 1599 return element; 1360 1600 }, 1361 1601 1362 replace: function(element, html) {1602 replace: function(element, content) { 1363 1603 element = $(element); 1364 html = typeof html == 'undefined' ? '' : html.toString(); 1365 if (element.outerHTML) { 1366 element.outerHTML = html.stripScripts(); 1367 } else { 1604 if (content && content.toElement) content = content.toElement(); 1605 else if (!Object.isElement(content)) { 1606 content = Object.toHTML(content); 1368 1607 var range = element.ownerDocument.createRange(); 1369 range.selectNode Contents(element);1370 element.parentNode.replaceChild(1371 range.createContextualFragment(html.stripScripts()), element);1372 } 1373 setTimeout(function() {html.evalScripts()}, 10);1608 range.selectNode(element); 1609 content.evalScripts.bind(content).defer(); 1610 content = range.createContextualFragment(content.stripScripts()); 1611 } 1612 element.parentNode.replaceChild(content, element); 1374 1613 return element; 1614 }, 1615 1616 insert: function(element, insertions) { 1617 element = $(element); 1618 1619 if (Object.isString(insertions) || Object.isNumber(insertions) || 1620 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 1621 insertions = {bottom:insertions}; 1622 1623 var content, insert, tagName, childNodes; 1624 1625 for (var position in insertions) { 1626 content = insertions[position]; 1627 position = position.toLowerCase(); 1628 insert = Element._insertionTranslations[position]; 1629 1630 if (content && content.toElement) content = content.toElement(); 1631 if (Object.isElement(content)) { 1632 insert(element, content); 1633 continue; 1634 } 1635 1636 content = Object.toHTML(content); 1637 1638 tagName = ((position == 'before' || position == 'after') 1639 ? element.parentNode : element).tagName.toUpperCase(); 1640 1641 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 1642 1643 if (position == 'top' || position == 'after') childNodes.reverse(); 1644 childNodes.each(insert.curry(element)); 1645 1646 content.evalScripts.bind(content).defer(); 1647 } 1648 1649 return element; 1650 }, 1651 1652 wrap: function(element, wrapper, attributes) { 1653 element = $(element); 1654 if (Object.isElement(wrapper)) 1655 $(wrapper).writeAttribute(attributes || { }); 1656 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); 1657 else wrapper = new Element('div', wrapper); 1658 if (element.parentNode) 1659 element.parentNode.replaceChild(wrapper, element); 1660 wrapper.appendChild(element); 1661 return wrapper; 1375 1662 }, 1376 1663 … … 1400 1687 1401 1688 descendants: function(element) { 1402 return $ A($(element).getElementsByTagName('*')).each(Element.extend);1689 return $(element).select("*"); 1403 1690 }, 1404 1691 … … 1430 1717 1431 1718 match: function(element, selector) { 1432 if ( typeof selector == 'string')1719 if (Object.isString(selector)) 1433 1720 selector = new Selector(selector); 1434 1721 return selector.match($(element)); … … 1439 1726 if (arguments.length == 1) return $(element.parentNode); 1440 1727 var ancestors = element.ancestors(); 1441 return expression ? Selector.findElement(ancestors, expression, index):1442 ancestors[index || 0];1728 return Object.isNumber(expression) ? ancestors[expression] : 1729 Selector.findElement(ancestors, expression, index); 1443 1730 }, 1444 1731 … … 1446 1733 element = $(element); 1447 1734 if (arguments.length == 1) return element.firstDescendant(); 1448 var descendants = element.descendants(); 1449 return expression ? Selector.findElement(descendants, expression, index) : 1450 descendants[index || 0]; 1735 return Object.isNumber(expression) ? element.descendants()[expression] : 1736 element.select(expression)[index || 0]; 1451 1737 }, 1452 1738 … … 1455 1741 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 1456 1742 var previousSiblings = element.previousSiblings(); 1457 return expression ? Selector.findElement(previousSiblings, expression, index):1458 previousSiblings[index || 0];1743 return Object.isNumber(expression) ? previousSiblings[expression] : 1744 Selector.findElement(previousSiblings, expression, index); 1459 1745 }, 1460 1746 … … 1463 1749 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 1464 1750 var nextSiblings = element.nextSiblings(); 1465 return expression ? Selector.findElement(nextSiblings, expression, index):1466 nextSiblings[index || 0];1467 }, 1468 1469 getElementsBySelector: function() {1751 return Object.isNumber(expression) ? nextSiblings[expression] : 1752 Selector.findElement(nextSiblings, expression, index); 1753 }, 1754 1755 select: function() { 1470 1756 var args = $A(arguments), element = $(args.shift()); 1471 1757 return Selector.findChildElements(element, args); 1472 1758 }, 1473 1759 1474 getElementsByClassName: function(element, className) { 1475 return document.getElementsByClassName(className, element); 1760 adjacent: function() { 1761 var args = $A(arguments), element = $(args.shift()); 1762 return Selector.findChildElements(element.parentNode, args).without(element); 1763 }, 1764 1765 identify: function(element) { 1766 element = $(element); 1767 var id = element.readAttribute('id'), self = arguments.callee; 1768 if (id) return id; 1769 do { id = 'anonymous_element_' + self.counter++ } while ($(id)); 1770 element.writeAttribute('id', id); 1771 return id; 1476 1772 }, 1477 1773 … … 1479 1775 element = $(element); 1480 1776 if (Prototype.Browser.IE) { 1481 if (!element.attributes) return null; 1482 var t = Element._attributeTranslations; 1777 var t = Element._attributeTranslations.read; 1483 1778 if (t.values[name]) return t.values[name](element, name); 1484 if (t.names[name]) name = t.names[name]; 1485 var attribute = element.attributes[name]; 1486 return attribute ? attribute.nodeValue : null; 1779 if (t.names[name]) name = t.names[name]; 1780 if (name.include(':')) { 1781 return (!element.attributes || !element.attributes[name]) ? null : 1782 element.attributes[name].value; 1783 } 1487 1784 } 1488 1785 return element.getAttribute(name); 1786 }, 1787 1788 writeAttribute: function(element, name, value) { 1789 element = $(element); 1790 var attributes = { }, t = Element._attributeTranslations.write; 1791 1792 if (typeof name == 'object') attributes = name; 1793 else attributes[name] = Object.isUndefined(value) ? true : value; 1794 1795 for (var attr in attributes) { 1796 name = t.names[attr] || attr; 1797 value = attributes[attr]; 1798 if (t.values[attr]) name = t.values[attr](element, value); 1799 if (value === false || value === null) 1800 element.removeAttribute(name); 1801 else if (value === true) 1802 element.setAttribute(name, name); 1803 else element.setAttribute(name, value); 1804 } 1805 return element; 1489 1806 }, 1490 1807 … … 1504 1821 if (!(element = $(element))) return; 1505 1822 var elementClassName = element.className; 1506 if (elementClassName.length == 0) return false; 1507 if (elementClassName == className || 1508 elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 1509 return true; 1510 return false; 1823 return (elementClassName.length > 0 && (elementClassName == className || 1824 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); 1511 1825 }, 1512 1826 1513 1827 addClassName: function(element, className) { 1514 1828 if (!(element = $(element))) return; 1515 Element.classNames(element).add(className); 1829 if (!element.hasClassName(className)) 1830 element.className += (element.className ? ' ' : '') + className; 1516 1831 return element; 1517 1832 }, … … 1519 1834 removeClassName: function(element, className) { 1520 1835 if (!(element = $(element))) return; 1521 Element.classNames(element).remove(className); 1836 element.className = element.className.replace( 1837 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); 1522 1838 return element; 1523 1839 }, … … 1525 1841 toggleClassName: function(element, className) { 1526 1842 if (!(element = $(element))) return; 1527 Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); 1528 return element; 1529 }, 1530 1531 observe: function() { 1532 Event.observe.apply(Event, arguments); 1533 return $A(arguments).first(); 1534 }, 1535 1536 stopObserving: function() { 1537 Event.stopObserving.apply(Event, arguments); 1538 return $A(arguments).first(); 1843 return element[element.hasClassName(className) ? 1844 'removeClassName' : 'addClassName'](className); 1539 1845 }, 1540 1846 … … 1558 1864 descendantOf: function(element, ancestor) { 1559 1865 element = $(element), ancestor = $(ancestor); 1866 var originalAncestor = ancestor; 1867 1868 if (element.compareDocumentPosition) 1869 return (element.compareDocumentPosition(ancestor) & 8) === 8; 1870 1871 if (element.sourceIndex && !Prototype.Browser.Opera) { 1872 var e = element.sourceIndex, a = ancestor.sourceIndex, 1873 nextAncestor = ancestor.nextSibling; 1874 if (!nextAncestor) { 1875 do { ancestor = ancestor.parentNode; } 1876 while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); 1877 } 1878 if (nextAncestor && nextAncestor.sourceIndex) 1879 return (e > a && e < nextAncestor.sourceIndex); 1880 } 1881 1560 1882 while (element = element.parentNode) 1561 if (element == ancestor) return true;1883 if (element == originalAncestor) return true; 1562 1884 return false; 1563 1885 }, … … 1565 1887 scrollTo: function(element) { 1566 1888 element = $(element); 1567 var pos = Position.cumulativeOffset(element);1889 var pos = element.cumulativeOffset(); 1568 1890 window.scrollTo(pos[0], pos[1]); 1569 1891 return element; … … 1586 1908 }, 1587 1909 1588 setStyle: function(element, styles , camelized) {1910 setStyle: function(element, styles) { 1589 1911 element = $(element); 1590 var elementStyle = element.style; 1591 1912 var elementStyle = element.style, match; 1913 if (Object.isString(styles)) { 1914 element.style.cssText += ';' + styles; 1915 return styles.include('opacity') ? 1916 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; 1917 } 1592 1918 for (var property in styles) 1593 if (property == 'opacity') element.setOpacity(styles[property]) 1919 if (property == 'opacity') element.setOpacity(styles[property]); 1594 1920 else 1595 1921 elementStyle[(property == 'float' || property == 'cssFloat') ? 1596 ( elementStyle.styleFloat === undefined? 'cssFloat' : 'styleFloat') :1597 (camelized ? property : property.camelize())] = styles[property];1922 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : 1923 property] = styles[property]; 1598 1924 1599 1925 return element; … … 1662 1988 element = $(element); 1663 1989 if (element._overflow) return element; 1664 element._overflow = element.style.overflow|| 'auto';1665 if ( (Element.getStyle(element, 'overflow') || 'visible') != 'hidden')1990 element._overflow = Element.getStyle(element, 'overflow') || 'auto'; 1991 if (element._overflow !== 'hidden') 1666 1992 element.style.overflow = 'hidden'; 1667 1993 return element; … … 1674 2000 element._overflow = null; 1675 2001 return element; 2002 }, 2003 2004 cumulativeOffset: function(element) { 2005 var valueT = 0, valueL = 0; 2006 do { 2007 valueT += element.offsetTop || 0; 2008 valueL += element.offsetLeft || 0; 2009 element = element.offsetParent; 2010 } while (element); 2011 return Element._returnOffset(valueL, valueT); 2012 }, 2013 2014 positionedOffset: function(element) { 2015 var valueT = 0, valueL = 0; 2016 do { 2017 valueT += element.offsetTop || 0; 2018 valueL += element.offsetLeft || 0; 2019 element = element.offsetParent; 2020 if (element) { 2021 if (element.tagName == 'BODY') break; 2022 var p = Element.getStyle(element, 'position'); 2023 if (p !== 'static') break; 2024 } 2025 } while (element); 2026 return Element._returnOffset(valueL, valueT); 2027 }, 2028 2029 absolutize: function(element) { 2030 element = $(element); 2031 if (element.getStyle('position') == 'absolute') return; 2032 // Position.prepare(); // To be done manually by Scripty when it needs it. 2033 2034 var offsets = element.positionedOffset(); 2035 var top = offsets[1]; 2036 var left = offsets[0]; 2037 var width = element.clientWidth; 2038 var height = element.clientHeight; 2039 2040 element._originalLeft = left - parseFloat(element.style.left || 0); 2041 element._originalTop = top - parseFloat(element.style.top || 0); 2042 element._originalWidth = element.style.width; 2043 element._originalHeight = element.style.height; 2044 2045 element.style.position = 'absolute'; 2046 element.style.top = top + 'px'; 2047 element.style.left = left + 'px'; 2048 element.style.width = width + 'px'; 2049 element.style.height = height + 'px'; 2050 return element; 2051 }, 2052 2053 relativize: function(element) { 2054 element = $(element); 2055 if (element.getStyle('position') == 'relative') return; 2056 // Position.prepare(); // To be done manually by Scripty when it needs it. 2057 2058 element.style.position = 'relative'; 2059 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 2060 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 2061 2062 element.style.top = top + 'px'; 2063 element.style.left = left + 'px'; 2064 element.style.height = element._originalHeight; 2065 element.style.width = element._originalWidth; 2066 return element; 2067 }, 2068 2069 cumulativeScrollOffset: function(element) { 2070 var valueT = 0, valueL = 0; 2071 do { 2072 valueT += element.scrollTop || 0; 2073 valueL += element.scrollLeft || 0; 2074 element = element.parentNode; 2075 } while (element); 2076 return Element._returnOffset(valueL, valueT); 2077 }, 2078 2079 getOffsetParent: function(element) { 2080 if (element.offsetParent) return $(element.offsetParent); 2081 if (element == document.body) return $(element); 2082 2083 while ((element = element.parentNode) && element != document.body) 2084 if (Element.getStyle(element, 'position') != 'static') 2085 return $(element); 2086 2087 return $(document.body); 2088 }, 2089 2090 viewportOffset: function(forElement) { 2091 var valueT = 0, valueL = 0; 2092 2093 var element = forElement; 2094 do { 2095 valueT += element.offsetTop || 0; 2096 valueL += element.offsetLeft || 0; 2097 2098 // Safari fix 2099 if (element.offsetParent == document.body && 2100 Element.getStyle(element, 'position') == 'absolute') break; 2101 2102 } while (element = element.offsetParent); 2103 2104 element = forElement; 2105 do { 2106 if (!Prototype.Browser.Opera || element.tagName == 'BODY') { 2107 valueT -= element.scrollTop || 0; 2108 valueL -= element.scrollLeft || 0; 2109 } 2110 } while (element = element.parentNode); 2111 2112 return Element._returnOffset(valueL, valueT); 2113 }, 2114 2115 clonePosition: function(element, source) { 2116 var options = Object.extend({ 2117 setLeft: true, 2118 setTop: true, 2119 setWidth: true, 2120 setHeight: true, 2121 offsetTop: 0, 2122 offsetLeft: 0 2123 }, arguments[2] || { }); 2124 2125 // find page position of source 2126 source = $(source); 2127 var p = source.viewportOffset(); 2128 2129 // find coordinate system to use 2130 element = $(element); 2131 var delta = [0, 0]; 2132 var parent = null; 2133 // delta [0,0] will do fine with position: fixed elements, 2134 // position:absolute needs offsetParent deltas 2135 if (Element.getStyle(element, 'position') == 'absolute') { 2136 parent = element.getOffsetParent(); 2137 delta = parent.viewportOffset(); 2138 } 2139 2140 // correct by body offsets (fixes Safari) 2141 if (parent == document.body) { 2142 delta[0] -= document.body.offsetLeft; 2143 delta[1] -= document.body.offsetTop; 2144 } 2145 2146 // set position 2147 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 2148 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 2149 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; 2150 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; 2151 return element; 1676 2152 } 1677 2153 }; 1678 2154 2155 Element.Methods.identify.counter = 1; 2156 1679 2157 Object.extend(Element.Methods, { 1680 childOf: Element.Methods.descendantOf,2158 getElementsBySelector: Element.Methods.select, 1681 2159 childElements: Element.Methods.immediateDescendants 1682 2160 }); 1683 2161 2162 Element._attributeTranslations = { 2163 write: { 2164 names: { 2165 className: 'class', 2166 htmlFor: 'for' 2167 }, 2168 values: { } 2169 } 2170 }; 2171 1684 2172 if (Prototype.Browser.Opera) { 1685 Element.Methods._getStyle = Element.Methods.getStyle; 1686 Element.Methods.getStyle = function(element, style) { 1687 switch(style) { 1688 case 'left': 1689 case 'top': 1690 case 'right': 1691 case 'bottom': 1692 if (Element._getStyle(element, 'position') == 'static') return null; 1693 default: return Element._getStyle(element, style); 1694 } 1695 }; 2173 Element.Methods.getStyle = Element.Methods.getStyle.wrap( 2174 function(proceed, element, style) { 2175 switch (style) { 2176 case 'left': case 'top': case 'right': case 'bottom': 2177 if (proceed(element, 'position') === 'static') return null; 2178 case 'height': case 'width': 2179 // returns '0px' for hidden elements; we want it to return null 2180 if (!Element.visible(element)) return null; 2181 2182 // returns the border-box dimensions rather than the content-box 2183 // dimensions, so we subtract padding and borders from the value 2184 var dim = parseInt(proceed(element, style), 10); 2185 2186 if (dim !== element['offset' + style.capitalize()]) 2187 return dim + 'px'; 2188 2189 var properties; 2190 if (style === 'height') { 2191 properties = ['border-top-width', 'padding-top', 2192 'padding-bottom', 'border-bottom-width']; 2193 } 2194 else { 2195 properties = ['border-left-width', 'padding-left', 2196 'padding-right', 'border-right-width']; 2197 } 2198 return properties.inject(dim, function(memo, property) { 2199 var val = proceed(element, property); 2200 return val === null ? memo : memo - parseInt(val, 10); 2201 }) + 'px'; 2202 default: return proceed(element, style); 2203 } 2204 } 2205 ); 2206 2207 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( 2208 function(proceed, element, attribute) { 2209 if (attribute === 'title') return element.title; 2210 return proceed(element, attribute); 2211 } 2212 ); 1696 2213 } 2214 1697 2215 else if (Prototype.Browser.IE) { 2216 // IE doesn't report offsets correctly for static elements, so we change them 2217 // to "relative" to get the values, then change them back. 2218 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( 2219 function(proceed, element) { 2220 element = $(element); 2221 var position = element.getStyle('position'); 2222 if (position !== 'static') return proceed(element); 2223 element.setStyle({ position: 'relative' }); 2224 var value = proceed(element); 2225 element.setStyle({ position: position }); 2226 return value; 2227 } 2228 ); 2229 2230 $w('positionedOffset viewportOffset').each(function(method) { 2231 Element.Methods[method] = Element.Methods[method].wrap( 2232 function(proceed, element) { 2233 element = $(element); 2234 var position = element.getStyle('position'); 2235 if (position !== 'static') return proceed(element); 2236 // Trigger hasLayout on the offset parent so that IE6 reports 2237 // accurate offsetTop and offsetLeft values for position: fixed. 2238 var offsetParent = element.getOffsetParent(); 2239 if (offsetParent && offsetParent.getStyle('position') === 'fixed') 2240 offsetParent.setStyle({ zoom: 1 }); 2241 element.setStyle({ position: 'relative' }); 2242 var value = proceed(element); 2243 element.setStyle({ position: position }); 2244 return value; 2245 } 2246 ); 2247 }); 2248 1698 2249 Element.Methods.getStyle = function(element, style) { 1699 2250 element = $(element); … … 1710 2261 if (value == 'auto') { 1711 2262 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 1712 return element['offset' +style.capitalize()] + 'px';2263 return element['offset' + style.capitalize()] + 'px'; 1713 2264 return null; 1714 2265 } … … 1717 2268 1718 2269 Element.Methods.setOpacity = function(element, value) { 2270 function stripAlpha(filter){ 2271 return filter.replace(/alpha\([^\)]*\)/gi,''); 2272 } 1719 2273 element = $(element); 2274 var currentStyle = element.currentStyle; 2275 if ((currentStyle && !currentStyle.hasLayout) || 2276 (!currentStyle && element.style.zoom == 'normal')) 2277 element.style.zoom = 1; 2278 1720 2279 var filter = element.getStyle('filter'), style = element.style; 1721 2280 if (value == 1 || value === '') { 1722 style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); 2281 (filter = stripAlpha(filter)) ? 2282 style.filter = filter : style.removeAttribute('filter'); 1723 2283 return element; 1724 2284 } else if (value < 0.00001) value = 0; 1725 style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +2285 style.filter = stripAlpha(filter) + 1726 2286 'alpha(opacity=' + (value * 100) + ')'; 1727 2287 return element; 1728 2288 }; 1729 2289 1730 // IE is missing .innerHTML support for TABLE-related elements 1731 Element.Methods.update = function(element, html) { 1732 element = $(element); 1733 html = typeof html == 'undefined' ? '' : html.toString(); 1734 var tagName = element.tagName.toUpperCase(); 1735 if (['THEAD','TBODY','TR','TD'].include(tagName)) { 1736 var div = document.createElement('div'); 1737 switch (tagName) { 1738 case 'THEAD': 1739 case 'TBODY': 1740 div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>'; 1741 depth = 2; 1742 break; 1743 case 'TR': 1744 div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>'; 1745 depth = 3; 1746 break; 1747 case 'TD': 1748 div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; 1749 depth = 4; 1750 } 1751 $A(element.childNodes).each(function(node) { element.removeChild(node) }); 1752 depth.times(function() { div = div.firstChild }); 1753 $A(div.childNodes).each(function(node) { element.appendChild(node) }); 1754 } else { 1755 element.innerHTML = html.stripScripts(); 1756 } 1757 setTimeout(function() { html.evalScripts() }, 10); 1758 return element; 1759 } 2290 Element._attributeTranslations = { 2291 read: { 2292 names: { 2293 'class': 'className', 2294 'for': 'htmlFor' 2295 }, 2296 values: { 2297 _getAttr: function(element, attribute) { 2298 return element.getAttribute(attribute, 2); 2299 }, 2300 _getAttrNode: function(element, attribute) { 2301 var node = element.getAttributeNode(attribute); 2302 return node ? node.value : ""; 2303 }, 2304 _getEv: function(element, attribute) { 2305 attribute = element.getAttribute(attribute); 2306 return attribute ? attribute.toString().slice(23, -2) : null; 2307 }, 2308 _flag: function(element, attribute) { 2309 return $(element).hasAttribute(attribute) ? attribute : null; 2310 }, 2311 style: function(element) { 2312 return element.style.cssText.toLowerCase(); 2313 }, 2314 title: function(element) { 2315 return element.title; 2316 } 2317 } 2318 } 2319 }; 2320 2321 Element._attributeTranslations.write = { 2322 names: Object.extend({ 2323 cellpadding: 'cellPadding', 2324 cellspacing: 'cellSpacing' 2325 }, Element._attributeTranslations.read.names), 2326 values: { 2327 checked: function(element, value) { 2328 element.checked = !!value; 2329 }, 2330 2331 style: function(element, value) { 2332 element.style.cssText = value ? value : ''; 2333 } 2334 } 2335 }; 2336 2337 Element._attributeTranslations.has = {}; 2338 2339 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 2340 'encType maxLength readOnly longDesc').each(function(attr) { 2341 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 2342 Element._attributeTranslations.has[attr.toLowerCase()] = attr; 2343 }); 2344 2345 (function(v) { 2346 Object.extend(v, { 2347 href: v._getAttr, 2348 src: v._getAttr, 2349 type: v._getAttr, 2350 action: v._getAttrNode, 2351 disabled: v._flag, 2352 checked: v._flag, 2353 readonly: v._flag, 2354 multiple: v._flag, 2355 onload: v._getEv, 2356 onunload: v._getEv, 2357 onclick: v._getEv, 2358 ondblclick: v._getEv, 2359 onmousedown: v._getEv, 2360 onmouseup: v._getEv, 2361 onmouseover: v._getEv, 2362 onmousemove: v._getEv, 2363 onmouseout: v._getEv, 2364 onfocus: v._getEv, 2365 onblur: v._getEv, 2366 onkeypress: v._getEv, 2367 onkeydown: v._getEv, 2368 onkeyup: v._getEv, 2369 onsubmit: v._getEv, 2370 onreset: v._getEv, 2371 onselect: v._getEv, 2372 onchange: v._getEv 2373 }); 2374 })(Element._attributeTranslations.read.values); 1760 2375 } 1761 else if (Prototype.Browser.Gecko) { 2376 2377 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { 1762 2378 Element.Methods.setOpacity = function(element, value) { 1763 2379 element = $(element); … … 1768 2384 } 1769 2385 1770 Element._attributeTranslations = { 1771 names: { 1772 colspan: "colSpan", 1773 rowspan: "rowSpan", 1774 valign: "vAlign", 1775 datetime: "dateTime", 1776 accesskey: "accessKey", 1777 tabindex: "tabIndex", 1778 enctype: "encType", 1779 maxlength: "maxLength", 1780 readonly: "readOnly", 1781 longdesc: "longDesc" 1782 }, 1783 values: { 1784 _getAttr: function(element, attribute) { 1785 return element.getAttribute(attribute, 2); 1786 }, 1787 _flag: function(element, attribute) { 1788 return $(element).hasAttribute(attribute) ? attribute : null; 1789 }, 1790 style: function(element) { 1791 return element.style.cssText.toLowerCase(); 1792 }, 1793 title: function(element) { 1794 var node = element.getAttributeNode('title'); 1795 return node.specified ? node.nodeValue : null; 1796 } 1797 } 2386 else if (Prototype.Browser.WebKit) { 2387 Element.Methods.setOpacity = function(element, value) { 2388 element = $(element); 2389 element.style.opacity = (value == 1 || value === '') ? '' : 2390 (value < 0.00001) ? 0 : value; 2391 2392 if (value == 1) 2393 if(element.tagName == 'IMG' && element.width) { 2394 element.width++; element.width--; 2395 } else try { 2396 var n = document.createTextNode(' '); 2397 element.appendChild(n); 2398 element.removeChild(n); 2399 } catch (e) { } 2400 2401 return element; 2402 }; 2403 2404 // Safari returns margins on body which is incorrect if the child is absolutely 2405 // positioned. For performance reasons, redefine Element#cumulativeOffset for 2406 // KHTML/WebKit only. 2407 Element.Methods.cumulativeOffset = function(element) { 2408 var valueT = 0, valueL = 0; 2409 do { 2410 valueT += element.offsetTop || 0; 2411 valueL += element.offsetLeft || 0; 2412 if (element.offsetParent == document.body) 2413 if (Element.getStyle(element, 'position') == 'absolute') break; 2414 2415 element = element.offsetParent; 2416 } while (element); 2417 2418 return Element._returnOffset(valueL, valueT); 2419 }; 2420 } 2421 2422 if (Prototype.Browser.IE || Prototype.Browser.Opera) { 2423 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements 2424 Element.Methods.update = function(element, content) { 2425 element = $(element); 2426 2427 if (content && content.toElement) content = content.toElement(); 2428 if (Object.isElement(content)) return element.update().insert(content); 2429 2430 content = Object.toHTML(content); 2431 var tagName = element.tagName.toUpperCase(); 2432 2433 if (tagName in Element._insertionTranslations.tags) { 2434 $A(element.childNodes).each(function(node) { element.removeChild(node) }); 2435 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 2436 .each(function(node) { element.appendChild(node) }); 2437 } 2438 else element.innerHTML = content.stripScripts(); 2439 2440 content.evalScripts.bind(content).defer(); 2441 return element; 2442 }; 2443 } 2444 2445 if ('outerHTML' in document.createElement('div')) { 2446 Element.Methods.replace = function(element, content) { 2447 element = $(element); 2448 2449 if (content && content.toElement) content = content.toElement(); 2450 if (Object.isElement(content)) { 2451 element.parentNode.replaceChild(content, element); 2452 return element; 2453 } 2454 2455 content = Object.toHTML(content); 2456 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); 2457 2458 if (Element._insertionTranslations.tags[tagName]) { 2459 var nextSibling = element.next(); 2460 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 2461 parent.removeChild(element); 2462 if (nextSibling) 2463 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); 2464 else 2465 fragments.each(function(node) { parent.appendChild(node) }); 2466 } 2467 else element.outerHTML = content.stripScripts(); 2468 2469 content.evalScripts.bind(content).defer(); 2470 return element; 2471 }; 2472 } 2473 2474 Element._returnOffset = function(l, t) { 2475 var result = [l, t]; 2476 result.left = l; 2477 result.top = t; 2478 return result; 1798 2479 }; 1799 2480 2481 Element._getContentFromAnonymousElement = function(tagName, html) { 2482 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 2483 if (t) { 2484 div.innerHTML = t[0] + html + t[1]; 2485 t[2].times(function() { div = div.firstChild }); 2486 } else div.innerHTML = html; 2487 return $A(div.childNodes); 2488 }; 2489 2490 Element._insertionTranslations = { 2491 before: function(element, node) { 2492 element.parentNode.insertBefore(node, element); 2493 }, 2494 top: function(element, node) { 2495 element.insertBefore(node, element.firstChild); 2496 }, 2497 bottom: function(element, node) { 2498 element.appendChild(node); 2499 }, 2500 after: function(element, node) { 2501 element.parentNode.insertBefore(node, element.nextSibling); 2502 }, 2503 tags: { 2504 TABLE: ['<table>', '</table>', 1], 2505 TBODY: ['<table><tbody>', '</tbody></table>', 2], 2506 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], 2507 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 2508 SELECT: ['<select>', '</select>', 1] 2509 } 2510 }; 2511 1800 2512 (function() { 1801 Object.extend(this, { 1802 href: this._getAttr, 1803 src: this._getAttr, 1804 type: this._getAttr, 1805 disabled: this._flag, 1806 checked: this._flag, 1807 readonly: this._flag, 1808 multiple: this._flag 2513 Object.extend(this.tags, { 2514 THEAD: this.tags.TBODY, 2515 TFOOT: this.tags.TBODY, 2516 TH: this.tags.TD 1809 2517 }); 1810 }).call(Element._ attributeTranslations.values);2518 }).call(Element._insertionTranslations); 1811 2519 1812 2520 Element.Methods.Simulated = { 1813 2521 hasAttribute: function(element, attribute) { 1814 var t = Element._attributeTranslations, node; 1815 attribute = t.names[attribute] || attribute; 1816 node = $(element).getAttributeNode(attribute); 2522 attribute = Element._attributeTranslations.has[attribute] || attribute; 2523 var node = $(element).getAttributeNode(attribute); 1817 2524 return node && node.specified; 1818 2525 } 1819 2526 }; 1820 2527 1821 Element.Methods.ByTag = { };2528 Element.Methods.ByTag = { }; 1822 2529 1823 2530 Object.extend(Element, Element.Methods); 1824 2531 1825 2532 if (!Prototype.BrowserFeatures.ElementExtensions && 1826 document.createElement('div').__proto__) {1827 window.HTMLElement = { };2533 document.createElement('div').__proto__) { 2534 window.HTMLElement = { }; 1828 2535 window.HTMLElement.prototype = document.createElement('div').__proto__; 1829 2536 Prototype.BrowserFeatures.ElementExtensions = true; 1830 2537 } 2538 2539 Element.extend = (function() { 2540 if (Prototype.BrowserFeatures.SpecificElementExtensions) 2541 return Prototype.K; 2542 2543 var Methods = { }, ByTag = Element.Methods.ByTag; 2544 2545 var extend = Object.extend(function(element) { 2546 if (!element || element._extendedByPrototype || 2547 element.nodeType != 1 || element == window) return element; 2548 2549 var methods = Object.clone(Methods), 2550 tagName = element.tagName, property, value; 2551 2552 // extend methods for specific tags 2553 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 2554 2555 for (property in methods) { 2556 value = methods[property]; 2557 if (Object.isFunction(value) && !(property in element)) 2558 element[property] = value.methodize(); 2559 } 2560 2561 element._extendedByPrototype = Prototype.emptyFunction; 2562 return element; 2563 2564 }, { 2565 refresh: function() { 2566 // extend methods for all tags (Safari doesn't need this) 2567 if (!Prototype.BrowserFeatures.ElementExtensions) { 2568 Object.extend(Methods, Element.Methods); 2569 Object.extend(Methods, Element.Methods.Simulated); 2570 } 2571 } 2572 }); 2573 2574 extend.refresh(); 2575 return extend; 2576 })(); 1831 2577 1832 2578 Element.hasAttribute = function(element, attribute) { … … 1854 2600 } 1855 2601 1856 if (!tagName) Object.extend(Element.Methods, methods || { });2602 if (!tagName) Object.extend(Element.Methods, methods || { }); 1857 2603 else { 1858 if ( tagName.constructor == Array) tagName.each(extend);2604 if (Object.isArray(tagName)) tagName.each(extend); 1859 2605 else extend(tagName); 1860 2606 } … … 1863 2609 tagName = tagName.toUpperCase(); 1864 2610 if (!Element.Methods.ByTag[tagName]) 1865 Element.Methods.ByTag[tagName] = { };2611 Element.Methods.ByTag[tagName] = { }; 1866 2612 Object.extend(Element.Methods.ByTag[tagName], methods); 1867 2613 } … … 1869 2615 function copy(methods, destination, onlyIfAbsent) { 1870 2616 onlyIfAbsent = onlyIfAbsent || false; 1871 var cache = Element.extend.cache;1872 2617 for (var property in methods) { 1873 2618 var value = methods[property]; 2619 if (!Object.isFunction(value)) continue; 1874 2620 if (!onlyIfAbsent || !(property in destination)) 1875 destination[property] = cache.findOrStore(value);2621 destination[property] = value.methodize(); 1876 2622 } 1877 2623 } … … 1897 2643 if (window[klass]) return window[klass]; 1898 2644 1899 window[klass] = { };2645 window[klass] = { }; 1900 2646 window[klass].prototype = document.createElement(tagName).__proto__; 1901 2647 return window[klass]; … … 1910 2656 for (var tag in Element.Methods.ByTag) { 1911 2657 var klass = findDOMClass(tag); 1912 if ( typeof klass == "undefined") continue;2658 if (Object.isUndefined(klass)) continue; 1913 2659 copy(T[tag], klass.prototype); 1914 2660 } … … 1917 2663 Object.extend(Element, Element.Methods); 1918 2664 delete Element.ByTag; 2665 2666 if (Element.extend.refresh) Element.extend.refresh(); 2667 Element.cache = { }; 1919 2668 }; 1920 2669 1921 var Toggle = { display: Element.toggle }; 1922 1923 /*--------------------------------------------------------------------------*/ 1924 1925 Abstract.Insertion = function(adjacency) { 1926 this.adjacency = adjacency; 1927 } 1928 1929 Abstract.Insertion.prototype = { 1930 initialize: function(element, content) { 1931 this.element = $(element); 1932 this.content = content.stripScripts(); 1933 1934 if (this.adjacency && this.element.insertAdjacentHTML) { 1935 try { 1936 this.element.insertAdjacentHTML(this.adjacency, this.content); 1937 } catch (e) { 1938 var tagName = this.element.tagName.toUpperCase(); 1939 if (['TBODY', 'TR'].include(tagName)) { 1940 this.insertContent(this.contentFromAnonymousTable()); 1941 } else { 1942 throw e; 1943 } 1944 } 1945 } else { 1946 this.range = this.element.ownerDocument.createRange(); 1947 if (this.initializeRange) this.initializeRange(); 1948 this.insertContent([this.range.createContextualFragment(this.content)]); 1949 } 1950 1951 setTimeout(function() {content.evalScripts()}, 10); 1952 }, 1953 1954 contentFromAnonymousTable: function() { 1955 var div = document.createElement('div'); 1956 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 1957 return $A(div.childNodes[0].childNodes[0].childNodes); 1958 } 1959 } 1960 1961 var Insertion = new Object(); 1962 1963 Insertion.Before = Class.create(); 1964 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 1965 initializeRange: function() { 1966 this.range.setStartBefore(this.element); 1967 }, 1968 1969 insertContent: function(fragments) { 1970 fragments.each((function(fragment) { 1971 this.element.parentNode.insertBefore(fragment, this.element); 1972 }).bind(this)); 1973 } 1974 }); 1975 1976 Insertion.Top = Class.create(); 1977 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 1978 initializeRange: function() { 1979 this.range.selectNodeContents(this.element); 1980 this.range.collapse(true); 1981 }, 1982 1983 insertContent: function(fragments) { 1984 fragments.reverse(false).each((function(fragment) { 1985 this.element.insertBefore(fragment, this.element.firstChild); 1986 }).bind(this)); 1987 } 1988 }); 1989 1990 Insertion.Bottom = Class.create(); 1991 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 1992 initializeRange: function() { 1993 this.range.selectNodeContents(this.element); 1994 this.range.collapse(this.element); 1995 }, 1996 1997 insertContent: function(fragments) { 1998 fragments.each((function(fragment) { 1999 this.element.appendChild(fragment); 2000 }).bind(this)); 2001 } 2002 }); 2003 2004 Insertion.After = Class.create(); 2005 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 2006 initializeRange: function() { 2007 this.range.setStartAfter(this.element); 2008 }, 2009 2010 insertContent: function(fragments) { 2011 fragments.each((function(fragment) { 2012 this.element.parentNode.insertBefore(fragment, 2013 this.element.nextSibling); 2014 }).bind(this)); 2015 } 2016 }); 2017 2018 /*--------------------------------------------------------------------------*/ 2019 2020 Element.ClassNames = Class.create(); 2021 Element.ClassNames.prototype = { 2022 initialize: function(element) { 2023 this.element = $(element); 2024 }, 2025 2026 _each: function(iterator) { 2027 this.element.className.split(/\s+/).select(function(name) { 2028 return name.length > 0; 2029 })._each(iterator); 2030 }, 2031 2032 set: function(className) { 2033 this.element.className = className; 2034 }, 2035 2036 add: function(classNameToAdd) { 2037 if (this.include(classNameToAdd)) return; 2038 this.set($A(this).concat(classNameToAdd).join(' ')); 2039 }, 2040 2041 remove: function(classNameToRemove) { 2042 if (!this.include(classNameToRemove)) return; 2043 this.set($A(this).without(classNameToRemove).join(' ')); 2044 }, 2045 2046 toString: function() { 2047 return $A(this).join(' '); 2670 document.viewport = { 2671 getDimensions: function() { 2672 var dimensions = { }; 2673 var B = Prototype.Browser; 2674 $w('width height').each(function(d) { 2675 var D = d.capitalize(); 2676 dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : 2677 (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; 2678 }); 2679 return dimensions; 2680 }, 2681 2682 getWidth: function() { 2683 return this.getDimensions().width; 2684 }, 2685 2686 getHeight: function() { 2687 return this.getDimensions().height; 2688 }, 2689 2690 getScrollOffsets: function() { 2691 return Element._returnOffset( 2692 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 2693 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 2048 2694 } 2049 2695 }; 2050 2051 Object.extend(Element.ClassNames.prototype, Enumerable);2052 2696 /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, 2053 2697 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 2054 2698 * license. Please see http://www.yui-ext.com/ for more information. */ 2055 2699 2056 var Selector = Class.create(); 2057 2058 Selector.prototype = { 2700 var Selector = Class.create({ 2059 2701 initialize: function(expression) { 2060 2702 this.expression = expression.strip(); … … 2062 2704 }, 2063 2705 2706 shouldUseXPath: function() { 2707 if (!Prototype.BrowserFeatures.XPath) return false; 2708 2709 var e = this.expression; 2710 2711 // Safari 3 chokes on :*-of-type and :empty 2712 if (Prototype.Browser.WebKit && 2713 (e.include("-of-type") || e.include(":empty"))) 2714 return false; 2715 2716 // XPath can't do namespaced attributes, nor can it read 2717 // the "checked" property from DOM nodes 2718 if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) 2719 return false; 2720 2721 return true; 2722 }, 2723 2064 2724 compileMatcher: function() { 2065 // Selectors with namespaced attributes can't use the XPath version 2066 if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) 2725 if (this.shouldUseXPath()) 2067 2726 return this.compileXPathMatcher(); 2068 2727 … … 2071 2730 2072 2731 if (Selector._cache[e]) { 2073 this.matcher = Selector._cache[e]; return; 2074 } 2732 this.matcher = Selector._cache[e]; 2733 return; 2734 } 2735 2075 2736 this.matcher = ["this.matcher = function(root) {", 2076 2737 "var r = root, h = Selector.handlers, c = false, n;"]; … … 2081 2742 p = ps[i]; 2082 2743 if (m = e.match(p)) { 2083 this.matcher.push( typeof c[i] == 'function'? c[i](m) :2744 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : 2084 2745 new Template(c[i]).evaluate(m)); 2085 2746 e = e.replace(m[0], ''); … … 2096 2757 compileXPathMatcher: function() { 2097 2758 var e = this.expression, ps = Selector.patterns, 2098 x = Selector.xpath, le, 2759 x = Selector.xpath, le, m; 2099 2760 2100 2761 if (Selector._cache[e]) { … … 2107 2768 for (var i in ps) { 2108 2769 if (m = e.match(ps[i])) { 2109 this.matcher.push( typeof x[i] == 'function'? x[i](m) :2770 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : 2110 2771 new Template(x[i]).evaluate(m)); 2111 2772 e = e.replace(m[0], ''); … … 2126 2787 2127 2788 match: function(element) { 2128 return this.findElements(document).include(element); 2789 this.tokens = []; 2790 2791 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 2792 var le, p, m; 2793 2794 while (e && le !== e && (/\S/).test(e)) { 2795 le = e; 2796 for (var i in ps) { 2797 p = ps[i]; 2798 if (m = e.match(p)) { 2799 // use the Selector.assertions methods unless the selector 2800 // is too complex. 2801 if (as[i]) { 2802 this.tokens.push([i, Object.clone(m)]); 2803 e = e.replace(m[0], ''); 2804 } else { 2805 // reluctantly do a document-wide search 2806 // and look for a match in the array 2807 return this.findElements(document).include(element); 2808 } 2809 } 2810 } 2811 } 2812 2813 var match = true, name, matches; 2814 for (var i = 0, token; token = this.tokens[i]; i++) { 2815 name = token[0], matches = token[1]; 2816 if (!Selector.assertions[name](element, matches)) { 2817 match = false; break; 2818 } 2819 } 2820 2821 return match; 2129 2822 }, 2130 2823 … … 2136 2829 return "#<Selector:" + this.expression.inspect() + ">"; 2137 2830 } 2138 } ;2831 }); 2139 2832 2140 2833 Object.extend(Selector, { 2141 _cache: { },2834 _cache: { }, 2142 2835 2143 2836 xpath: { … … 2153 2846 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 2154 2847 id: "[@id='#{1}']", 2155 attrPresence: "[@#{1}]", 2848 attrPresence: function(m) { 2849 m[1] = m[1].toLowerCase(); 2850 return new Template("[@#{1}]").evaluate(m); 2851 }, 2156 2852 attr: function(m) { 2853 m[1] = m[1].toLowerCase(); 2157 2854 m[3] = m[5] || m[6]; 2158 2855 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); … … 2161 2858 var h = Selector.xpath.pseudos[m[1]]; 2162 2859 if (!h) return ''; 2163 if ( typeof h === 'function') return h(m);2860 if (Object.isFunction(h)) return h(m); 2164 2861 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); 2165 2862 }, … … 2183 2880 'not': function(m) { 2184 2881 var e = m[6], p = Selector.patterns, 2185 x = Selector.xpath, le, m,v;2882 x = Selector.xpath, le, v; 2186 2883 2187 2884 var exclusion = []; … … 2190 2887 for (var i in p) { 2191 2888 if (m = e.match(p[i])) { 2192 v = typeof x[i] == 'function'? x[i](m) : new Template(x[i]).evaluate(m);2889 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); 2193 2890 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 2194 2891 e = e.replace(m[0], ''); … … 2240 2937 2241 2938 criteria: { 2242 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',2243 className: 'n = h.className(n, r, "#{1}", c); c = false;',2244 id: 'n = h.id(n, r, "#{1}", c); c = false;',2245 attrPresence: 'n = h.attrPresence(n, r, "#{1}" ); c = false;',2939 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', 2940 className: 'n = h.className(n, r, "#{1}", c); c = false;', 2941 id: 'n = h.id(n, r, "#{1}", c); c = false;', 2942 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', 2246 2943 attr: function(m) { 2247 2944 m[3] = (m[5] || m[6]); 2248 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}" ); c = false;').evaluate(m);2249 }, 2250 pseudo: 2945 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); 2946 }, 2947 pseudo: function(m) { 2251 2948 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 2252 2949 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); … … 2270 2967 id: /^#([\w\-\*]+)(\b|$)/, 2271 2968 className: /^\.([\w\-\*]+)(\b|$)/, 2272 pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, 2969 pseudo: 2970 /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, 2273 2971 attrPresence: /^\[([\w]+)\]/, 2274 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ 2972 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ 2973 }, 2974 2975 // for Selector.match and Element#match 2976 assertions: { 2977 tagName: function(element, matches) { 2978 return matches[1].toUpperCase() == element.tagName.toUpperCase(); 2979 }, 2980 2981 className: function(element, matches) { 2982 return Element.hasClassName(element, matches[1]); 2983 }, 2984 2985 id: function(element, matches) { 2986 return element.id === matches[1]; 2987 }, 2988 2989 attrPresence: function(element, matches) { 2990 return Element.hasAttribute(element, matches[1]); 2991 }, 2992 2993 attr: function(element, matches) { 2994 var nodeValue = Element.readAttribute(element, matches[1]); 2995 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); 2996 } 2275 2997 }, 2276 2998 … … 2286 3008 // marks an array of nodes for counting 2287 3009 mark: function(nodes) { 3010 var _true = Prototype.emptyFunction; 2288 3011 for (var i = 0, node; node = nodes[i]; i++) 2289 node._counted =true;3012 node._countedByPrototype = _true; 2290 3013 return nodes; 2291 3014 }, … … 2293 3016 unmark: function(nodes) { 2294 3017 for (var i = 0, node; node = nodes[i]; i++) 2295 node._counted = undefined;3018 node._countedByPrototype = undefined; 2296 3019 return nodes; 2297 3020 }, … … 2301 3024 // rather than nth-child 2302 3025 index: function(parentNode, reverse, ofType) { 2303 parentNode._counted = true;3026 parentNode._countedByPrototype = Prototype.emptyFunction; 2304 3027 if (reverse) { 2305 3028 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 2306 node = nodes[i];2307 if (node.nodeType == 1 && (!ofType || node._counted )) node.nodeIndex = j++;3029 var node = nodes[i]; 3030 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 2308 3031 } 2309 3032 } else { 2310 3033 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 2311 if (node.nodeType == 1 && (!ofType || node._counted )) node.nodeIndex = j++;3034 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 2312 3035 } 2313 3036 }, … … 2318 3041 var results = [], n; 2319 3042 for (var i = 0, l = nodes.length; i < l; i++) 2320 if (!(n = nodes[i])._counted ) {2321 n._counted = true;3043 if (!(n = nodes[i])._countedByPrototype) { 3044 n._countedByPrototype = Prototype.emptyFunction; 2322 3045 results.push(Element.extend(n)); 2323 3046 } … … 2336 3059 var h = Selector.handlers; 2337 3060 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2338 for (var j = 0, child ren = [], child; child = node.childNodes[j]; j++)3061 for (var j = 0, child; child = node.childNodes[j]; j++) 2339 3062 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 2340 3063 } … … 2371 3094 // TOKEN FUNCTIONS 2372 3095 tagName: function(nodes, root, tagName, combinator) { 2373 tagName = tagName.toUpperCase();3096 var uTagName = tagName.toUpperCase(); 2374 3097 var results = [], h = Selector.handlers; 2375 3098 if (nodes) { … … 2384 3107 } 2385 3108 for (var i = 0, node; node = nodes[i]; i++) 2386 if (node.tagName.toUpperCase() == tagName) results.push(node);3109 if (node.tagName.toUpperCase() === uTagName) results.push(node); 2387 3110 return results; 2388 3111 } else return root.getElementsByTagName(tagName); … … 2391 3114 id: function(nodes, root, id, combinator) { 2392 3115 var targetNode = $(id), h = Selector.handlers; 2393 if (!nodes && root == document) return targetNode ? [targetNode] : []; 3116 if (!targetNode) return []; 3117 if (!nodes && root == document) return [targetNode]; 2394 3118 if (nodes) { 2395 3119 if (combinator) { … … 2430 3154 }, 2431 3155 2432 attrPresence: function(nodes, root, attr) { 3156 attrPresence: function(nodes, root, attr, combinator) { 3157 if (!nodes) nodes = root.getElementsByTagName("*"); 3158 if (nodes && combinator) nodes = this[combinator](nodes); 2433 3159 var results = []; 2434 3160 for (var i = 0, node; node = nodes[i]; i++) … … 2437 3163 }, 2438 3164 2439 attr: function(nodes, root, attr, value, operator ) {3165 attr: function(nodes, root, attr, value, operator, combinator) { 2440 3166 if (!nodes) nodes = root.getElementsByTagName("*"); 3167 if (nodes && combinator) nodes = this[combinator](nodes); 2441 3168 var handler = Selector.operators[operator], results = []; 2442 3169 for (var i = 0, node; node = nodes[i]; i++) { … … 2517 3244 h.mark(nodes); 2518 3245 for (var i = 0, node; node = nodes[i]; i++) { 2519 if (!node.parentNode._counted ) {3246 if (!node.parentNode._countedByPrototype) { 2520 3247 h.index(node.parentNode, reverse, ofType); 2521 3248 indexed.push(node.parentNode); … … 2555 3282 h.mark(exclusions); 2556 3283 for (var i = 0, results = [], node; node = nodes[i]; i++) 2557 if (!node._counted ) results.push(node);3284 if (!node._countedByPrototype) results.push(node); 2558 3285 h.unmark(exclusions); 2559 3286 return results; … … 2589 3316 }, 2590 3317 3318 split: function(expression) { 3319 var expressions = []; 3320 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 3321 expressions.push(m[1].strip()); 3322 }); 3323 return expressions; 3324 }, 3325 2591 3326 matchElements: function(elements, expression) { 2592 var matches = new Selector(expression).findElements(), h = Selector.handlers;3327 var matches = $$(expression), h = Selector.handlers; 2593 3328 h.mark(matches); 2594 3329 for (var i = 0, results = [], element; element = elements[i]; i++) 2595 if (element._counted ) results.push(element);3330 if (element._countedByPrototype) results.push(element); 2596 3331 h.unmark(matches); 2597 3332 return results; … … 2599 3334 2600 3335 findElement: function(elements, expression, index) { 2601 if ( typeof expression == 'number') {3336 if (Object.isNumber(expression)) { 2602 3337 index = expression; expression = false; 2603 3338 } … … 2606 3341 2607 3342 findChildElements: function(element, expressions) { 2608 var exprs = expressions.join(','), expressions = []; 2609 exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 2610 expressions.push(m[1].strip()); 2611 }); 3343 expressions = Selector.split(expressions.join(',')); 2612 3344 var results = [], h = Selector.handlers; 2613 3345 for (var i = 0, l = expressions.length, selector; i < l; i++) { … … 2618 3350 } 2619 3351 }); 3352 3353 if (Prototype.Browser.IE) { 3354 Object.extend(Selector.handlers, { 3355 // IE returns comment nodes on getElementsByTagName("*"). 3356 // Filter them out. 3357 concat: function(a, b) { 3358 for (var i = 0, node; node = b[i]; i++) 3359 if (node.tagName !== "!") a.push(node); 3360 return a; 3361 }, 3362 3363 // IE improperly serializes _countedByPrototype in (inner|outer)HTML. 3364 unmark: function(nodes) { 3365 for (var i = 0, node; node = nodes[i]; i++) 3366 node.removeAttribute('_countedByPrototype'); 3367 return nodes; 3368 } 3369 }); 3370 } 2620 3371 2621 3372 function $$() { … … 2628 3379 }, 2629 3380 2630 serializeElements: function(elements, getHash) { 2631 var data = elements.inject({}, function(result, element) { 3381 serializeElements: function(elements, options) { 3382 if (typeof options != 'object') options = { hash: !!options }; 3383 else if (Object.isUndefined(options.hash)) options.hash = true; 3384 var key, value, submitted = false, submit = options.submit; 3385 3386 var data = elements.inject({ }, function(result, element) { 2632 3387 if (!element.disabled && element.name) { 2633 var key = element.name, value = $(element).getValue(); 2634 if (value != null) { 2635 if (key in result) { 2636 if (result[key].constructor != Array) result[key] = [result[key]]; 3388 key = element.name; value = $(element).getValue(); 3389 if (value != null && (element.type != 'submit' || (!submitted && 3390 submit !== false && (!submit || key == submit) && (submitted = true)))) { 3391 if (key in result) { 3392 // a key is already present; construct an array of values 3393 if (!Object.isArray(result[key])) result[key] = [result[key]]; 2637 3394 result[key].push(value); 2638 3395 } … … 2643 3400 }); 2644 3401 2645 return getHash ? data : Hash.toQueryString(data);3402 return options.hash ? data : Object.toQueryString(data); 2646 3403 } 2647 3404 }; 2648 3405 2649 3406 Form.Methods = { 2650 serialize: function(form, getHash) {2651 return Form.serializeElements(Form.getElements(form), getHash);3407 serialize: function(form, options) { 3408 return Form.serializeElements(Form.getElements(form), options); 2652 3409 }, 2653 3410 … … 2691 3448 2692 3449 findFirstElement: function(form) { 2693 return $(form).getElements().find(function(element) { 2694 return element.type != 'hidden' && !element.disabled && 2695 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 3450 var elements = $(form).getElements().findAll(function(element) { 3451 return 'hidden' != element.type && !element.disabled; 3452 }); 3453 var firstByIndex = elements.findAll(function(element) { 3454 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; 3455 }).sortBy(function(element) { return element.tabIndex }).first(); 3456 3457 return firstByIndex ? firstByIndex : elements.find(function(element) { 3458 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 2696 3459 }); 2697 3460 }, … … 2704 3467 2705 3468 request: function(form, options) { 2706 form = $(form), options = Object.clone(options || {}); 2707 2708 var params = options.parameters; 3469 form = $(form), options = Object.clone(options || { }); 3470 3471 var params = options.parameters, action = form.readAttribute('action') || ''; 3472 if (action.blank()) action = window.location.href; 2709 3473 options.parameters = form.serialize(true); 2710 3474 2711 3475 if (params) { 2712 if ( typeof params == 'string') params = params.toQueryParams();3476 if (Object.isString(params)) params = params.toQueryParams(); 2713 3477 Object.extend(options.parameters, params); 2714 3478 } … … 2717 3481 options.method = form.method; 2718 3482 2719 return new Ajax.Request( form.readAttribute('action'), options);2720 } 2721 } 3483 return new Ajax.Request(action, options); 3484 } 3485 }; 2722 3486 2723 3487 /*--------------------------------------------------------------------------*/ … … 2733 3497 return element; 2734 3498 } 2735 } 3499 }; 2736 3500 2737 3501 Form.Element.Methods = { … … 2741 3505 var value = element.getValue(); 2742 3506 if (value != undefined) { 2743 var pair = { };3507 var pair = { }; 2744 3508 pair[element.name] = value; 2745 return Hash.toQueryString(pair);3509 return Object.toQueryString(pair); 2746 3510 } 2747 3511 } … … 2753 3517 var method = element.tagName.toLowerCase(); 2754 3518 return Form.Element.Serializers[method](element); 3519 }, 3520 3521 setValue: function(element, value) { 3522 element = $(element); 3523 var method = element.tagName.toLowerCase(); 3524 Form.Element.Serializers[method](element, value); 3525 return element; 2755 3526 }, 2756 3527 … … 2769 3540 element.focus(); 2770 3541 if (element.select && (element.tagName.toLowerCase() != 'input' || 2771 !['button', 'reset', 'submit'].include(element.type)))3542 !['button', 'reset', 'submit'].include(element.type))) 2772 3543 element.select(); 2773 } catch (e) { }3544 } catch (e) { } 2774 3545 return element; 2775 3546 }, … … 2787 3558 return element; 2788 3559 } 2789 } 3560 }; 2790 3561 2791 3562 /*--------------------------------------------------------------------------*/ … … 2797 3568 2798 3569 Form.Element.Serializers = { 2799 input: function(element ) {3570 input: function(element, value) { 2800 3571 switch (element.type.toLowerCase()) { 2801 3572 case 'checkbox': 2802 3573 case 'radio': 2803 return Form.Element.Serializers.inputSelector(element );3574 return Form.Element.Serializers.inputSelector(element, value); 2804 3575 default: 2805 return Form.Element.Serializers.textarea(element); 2806 } 2807 }, 2808 2809 inputSelector: function(element) { 2810 return element.checked ? element.value : null; 2811 }, 2812 2813 textarea: function(element) { 2814 return element.value; 2815 }, 2816 2817 select: function(element) { 2818 return this[element.type == 'select-one' ? 2819 'selectOne' : 'selectMany'](element); 3576 return Form.Element.Serializers.textarea(element, value); 3577 } 3578 }, 3579 3580 inputSelector: function(element, value) { 3581 if (Object.isUndefined(value)) return element.checked ? element.value : null; 3582 else element.checked = !!value; 3583 }, 3584 3585 textarea: function(element, value) { 3586 if (Object.isUndefined(value)) return element.value; 3587 else element.value = value; 3588 }, 3589 3590 select: function(element, index) { 3591 if (Object.isUndefined(index)) 3592 return this[element.type == 'select-one' ? 3593 'selectOne' : 'selectMany'](element); 3594 else { 3595 var opt, value, single = !Object.isArray(index); 3596 for (var i = 0, length = element.length; i < length; i++) { 3597 opt = element.options[i]; 3598 value = this.optionValue(opt); 3599 if (single) { 3600 if (value == index) { 3601 opt.selected = true; 3602 return; 3603 } 3604 } 3605 else opt.selected = index.include(value); 3606 } 3607 } 2820 3608 }, 2821 3609 … … 2840 3628 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 2841 3629 } 2842 } 3630 }; 2843 3631 2844 3632 /*--------------------------------------------------------------------------*/ 2845 3633 2846 Abstract.TimedObserver = function() {} 2847 Abstract.TimedObserver.prototype = { 2848 initialize: function(element, frequency, callback) { 2849 this.frequency = frequency; 3634 Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 3635 initialize: function($super, element, frequency, callback) { 3636 $super(callback, frequency); 2850 3637 this.element = $(element); 2851 this.callback = callback;2852 2853 3638 this.lastValue = this.getValue(); 2854 this.registerCallback(); 2855 }, 2856 2857 registerCallback: function() { 2858 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 2859 }, 2860 2861 onTimerEvent: function() { 3639 }, 3640 3641 execute: function() { 2862 3642 var value = this.getValue(); 2863 var changed = ('string' == typeof this.lastValue && 'string' == typeof value 2864 ? this.lastValue != value : String(this.lastValue) != String(value)); 2865 if (changed) { 3643 if (Object.isString(this.lastValue) && Object.isString(value) ? 3644 this.lastValue != value : String(this.lastValue) != String(value)) { 2866 3645 this.callback(this.element, value); 2867 3646 this.lastValue = value; 2868 3647 } 2869 3648 } 2870 } 2871 2872 Form.Element.Observer = Class.create(); 2873 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 3649 }); 3650 3651 Form.Element.Observer = Class.create(Abstract.TimedObserver, { 2874 3652 getValue: function() { 2875 3653 return Form.Element.getValue(this.element); … … 2877 3655 }); 2878 3656 2879 Form.Observer = Class.create(); 2880 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 3657 Form.Observer = Class.create(Abstract.TimedObserver, { 2881 3658 getValue: function() { 2882 3659 return Form.serialize(this.element); … … 2886 3663 /*--------------------------------------------------------------------------*/ 2887 3664 2888 Abstract.EventObserver = function() {} 2889 Abstract.EventObserver.prototype = { 3665 Abstract.EventObserver = Class.create({ 2890 3666 initialize: function(element, callback) { 2891 3667 this.element = $(element); … … 2908 3684 2909 3685 registerFormCallbacks: function() { 2910 Form.getElements(this.element).each(this.registerCallback .bind(this));3686 Form.getElements(this.element).each(this.registerCallback, this); 2911 3687 }, 2912 3688 … … 2924 3700 } 2925 3701 } 2926 } 2927 2928 Form.Element.EventObserver = Class.create(); 2929 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 3702 }); 3703 3704 Form.Element.EventObserver = Class.create(Abstract.EventObserver, { 2930 3705 getValue: function() { 2931 3706 return Form.Element.getValue(this.element); … … 2933 3708 }); 2934 3709 2935 Form.EventObserver = Class.create(); 2936 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 3710 Form.EventObserver = Class.create(Abstract.EventObserver, { 2937 3711 getValue: function() { 2938 3712 return Form.serialize(this.element); 2939 3713 } 2940 3714 }); 2941 if (!window.Event) { 2942 var Event = new Object(); 2943 } 3715 if (!window.Event) var Event = { }; 2944 3716 2945 3717 Object.extend(Event, { … … 2957 3729 KEY_PAGEUP: 33, 2958 3730 KEY_PAGEDOWN: 34, 2959 2960 element: function(event) { 2961 return $(event.target || event.srcElement); 2962 }, 2963 2964 isLeftClick: function(event) { 2965 return (((event.which) && (event.which == 1)) || 2966 ((event.button) && (event.button == 1))); 2967 }, 2968 2969 pointerX: function(event) { 2970 return event.pageX || (event.clientX + 2971 (document.documentElement.scrollLeft || document.body.scrollLeft)); 2972 }, 2973 2974 pointerY: function(event) { 2975 return event.pageY || (event.clientY + 2976 (document.documentElement.scrollTop || document.body.scrollTop)); 2977 }, 2978 2979 stop: function(event) { 2980 if (event.preventDefault) { 3731 KEY_INSERT: 45, 3732 3733 cache: { }, 3734 3735 relatedTarget: function(event) { 3736 var element; 3737 switch(event.type) { 3738 case 'mouseover': element = event.fromElement; break; 3739 case 'mouseout': element = event.toElement; break; 3740 default: return null; 3741 } 3742 return Element.extend(element); 3743 } 3744 }); 3745 3746 Event.Methods = (function() { 3747 var isButton; 3748 3749 if (Prototype.Browser.IE) { 3750 var buttonMap = { 0: 1, 1: 4, 2: 2 }; 3751 isButton = function(event, code) { 3752 return event.button == buttonMap[code]; 3753 }; 3754 3755 } else if (Prototype.Browser.WebKit) { 3756 isButton = function(event, code) { 3757 switch (code) { 3758 case 0: return event.which == 1 && !event.metaKey; 3759 case 1: return event.which == 1 && event.metaKey; 3760 default: return false; 3761 } 3762 }; 3763 3764 } else { 3765 isButton = function(event, code) { 3766 return event.which ? (event.which === code + 1) : (event.button === code); 3767 }; 3768 } 3769 3770 return { 3771 isLeftClick: function(event) { return isButton(event, 0) }, 3772 isMiddleClick: function(event) { return isButton(event, 1) }, 3773 isRightClick: function(event) { return isButton(event, 2) }, 3774 3775 element: function(event) { 3776 var node = Event.extend(event).target; 3777 return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); 3778 }, 3779 3780 findElement: function(event, expression) { 3781 var element = Event.element(event); 3782 if (!expression) return element; 3783 var elements = [element].concat(element.ancestors()); 3784 return Selector.findElement(elements, expression, 0); 3785 }, 3786 3787 pointer: function(event) { 3788 return { 3789 x: event.pageX || (event.clientX + 3790 (document.documentElement.scrollLeft || document.body.scrollLeft)), 3791 y: event.pageY || (event.clientY + 3792 (document.documentElement.scrollTop || document.body.scrollTop)) 3793 }; 3794 }, 3795 3796 pointerX: function(event) { return Event.pointer(event).x }, 3797 pointerY: function(event) { return Event.pointer(event).y }, 3798 3799 stop: function(event) { 3800 Event.extend(event); 2981 3801 event.preventDefault(); 2982 3802 event.stopPropagation(); 3803 event.stopped = true; 3804 } 3805 }; 3806 })(); 3807 3808 Event.extend = (function() { 3809 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 3810 m[name] = Event.Methods[name].methodize(); 3811 return m; 3812 }); 3813 3814 if (Prototype.Browser.IE) { 3815 Object.extend(methods, { 3816 stopPropagation: function() { this.cancelBubble = true }, 3817 preventDefault: function() { this.returnValue = false }, 3818 inspect: function() { return "[object Event]" } 3819 }); 3820 3821 return function(event) { 3822 if (!event) return false; 3823 if (event._extendedByPrototype) return event; 3824 3825 event._extendedByPrototype = Prototype.emptyFunction; 3826 var pointer = Event.pointer(event); 3827 Object.extend(event, { 3828 target: event.srcElement, 3829 relatedTarget: Event.relatedTarget(event), 3830 pageX: pointer.x, 3831 pageY: pointer.y 3832 }); 3833 return Object.extend(event, methods); 3834 }; 3835 3836 } else { 3837 Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; 3838 Object.extend(Event.prototype, methods); 3839 return Prototype.K; 3840 } 3841 })(); 3842 3843 Object.extend(Event, (function() { 3844 var cache = Event.cache; 3845 3846 function getEventID(element) { 3847 if (element._prototypeEventID) return element._prototypeEventID[0]; 3848 arguments.callee.id = arguments.callee.id || 1; 3849 return element._prototypeEventID = [++arguments.callee.id]; 3850 } 3851 3852 function getDOMEventName(eventName) { 3853 if (eventName && eventName.include(':')) return "dataavailable"; 3854 return eventName; 3855 } 3856 3857 function getCacheForID(id) { 3858 return cache[id] = cache[id] || { }; 3859 } 3860 3861 function getWrappersForEventName(id, eventName) { 3862 var c = getCacheForID(id); 3863 return c[eventName] = c[eventName] || []; 3864 } 3865 3866 function createWrapper(element, eventName, handler) { 3867 var id = getEventID(element); 3868 var c = getWrappersForEventName(id, eventName); 3869 if (c.pluck("handler").include(handler)) return false; 3870 3871 var wrapper = function(event) { 3872 if (!Event || !Event.extend || 3873 (event.eventName && event.eventName != eventName)) 3874 return false; 3875 3876 Event.extend(event); 3877 handler.call(element, event); 3878 }; 3879 3880 wrapper.handler = handler; 3881 c.push(wrapper); 3882 return wrapper; 3883 } 3884 3885 function findWrapper(id, eventName, handler) { 3886 var c = getWrappersForEventName(id, eventName); 3887 return c.find(function(wrapper) { return wrapper.handler == handler }); 3888 } 3889 3890 function destroyWrapper(id, eventName, handler) { 3891 var c = getCacheForID(id); 3892 if (!c[eventName]) return false; 3893 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); 3894 } 3895 3896 function destroyCache() { 3897 for (var id in cache) 3898 for (var eventName in cache[id]) 3899 cache[id][eventName] = null; 3900 } 3901 3902 if (window.attachEvent) { 3903 window.attachEvent("onunload", destroyCache); 3904 } 3905 3906 return { 3907 observe: function(element, eventName, handler) { 3908 element = $(element); 3909 var name = getDOMEventName(eventName); 3910 3911 var wrapper = createWrapper(element, eventName, handler); 3912 if (!wrapper) return element; 3913 3914 if (element.addEventListener) { 3915 element.addEventListener(name, wrapper, false); 3916 } else { 3917 element.attachEvent("on" + name, wrapper); 3918 } 3919 3920 return element; 3921 }, 3922 3923 stopObserving: function(element, eventName, handler) { 3924 element = $(element); 3925 var id = getEventID(element), name = getDOMEventName(eventName); 3926 3927 if (!handler && eventName) { 3928 getWrappersForEventName(id, eventName).each(function(wrapper) { 3929 element.stopObserving(eventName, wrapper.handler); 3930 }); 3931 return element; 3932 3933 } else if (!eventName) { 3934 Object.keys(getCacheForID(id)).each(function(eventName) { 3935 element.stopObserving(eventName); 3936 }); 3937 return element; 3938 } 3939 3940 var wrapper = findWrapper(id, eventName, handler); 3941 if (!wrapper) return element; 3942 3943 if (element.removeEventListener) { 3944 element.removeEventListener(name, wrapper, false); 3945 } else { 3946 element.detachEvent("on" + name, wrapper); 3947 } 3948 3949 destroyWrapper(id, eventName, handler); 3950 3951 return element; 3952 }, 3953 3954 fire: function(element, eventName, memo) { 3955 element = $(element); 3956 if (element == document && document.createEvent && !element.dispatchEvent) 3957 element = document.documentElement; 3958 3959 var event; 3960 if (document.createEvent) { 3961 event = document.createEvent("HTMLEvents"); 3962 event.initEvent("dataavailable", true, true); 3963 } else { 3964 event = document.createEventObject(); 3965 event.eventType = "ondataavailable"; 3966 } 3967 3968 event.eventName = eventName; 3969 event.memo = memo || { }; 3970 3971 if (document.createEvent) { 3972 element.dispatchEvent(event); 3973 } else { 3974 element.fireEvent(event.eventType, event); 3975 } 3976 3977 return Event.extend(event); 3978 } 3979 }; 3980 })()); 3981 3982 Object.extend(Event, Event.Methods); 3983 3984 Element.addMethods({ 3985 fire: Event.fire, 3986 observe: Event.observe, 3987 stopObserving: Event.stopObserving 3988 }); 3989 3990 Object.extend(document, { 3991 fire: Element.Methods.fire.methodize(), 3992 observe: Element.Methods.observe.methodize(), 3993 stopObserving: Element.Methods.stopObserving.methodize(), 3994 loaded: false 3995 }); 3996 3997 (function() { 3998 /* Support for the DOMContentLoaded event is based on work by Dan Webb, 3999 Matthias Miller, Dean Edwards and John Resig. */ 4000 4001 var timer; 4002 4003 function fireContentLoadedEvent() { 4004 if (document.loaded) return; 4005 if (timer) window.clearInterval(timer); 4006 document.fire("dom:loaded"); 4007 document.loaded = true; 4008 } 4009 4010 if (document.addEventListener) { 4011 if (Prototype.Browser.WebKit) { 4012 timer = window.setInterval(function() { 4013 if (/loaded|complete/.test(document.readyState)) 4014 fireContentLoadedEvent(); 4015 }, 0); 4016 4017 Event.observe(window, "load", fireContentLoadedEvent); 4018 2983 4019 } else { 2984 event.returnValue = false; 2985 event.cancelBubble = true; 2986 } 2987 }, 2988 2989 // find the first node with the given tagName, starting from the 2990 // node the event was triggered on; traverses the DOM upwards 2991 findElement: function(event, tagName) { 2992 var element = Event.element(event); 2993 while (element.parentNode && (!element.tagName || 2994 (element.tagName.toUpperCase() != tagName.toUpperCase()))) 2995 element = element.parentNode; 2996 return element; 2997 }, 2998 2999 observers: false, 3000 3001 _observeAndCache: function(element, name, observer, useCapture) { 3002 if (!this.observers) this.observers = []; 3003 if (element.addEventListener) { 3004 this.observers.push([element, name, observer, useCapture]); 3005 element.addEventListener(name, observer, useCapture); 3006 } else if (element.attachEvent) { 3007 this.observers.push([element, name, observer, useCapture]); 3008 element.attachEvent('on' + name, observer); 3009 } 3010 }, 3011 3012 unloadCache: function() { 3013 if (!Event.observers) return; 3014 for (var i = 0, length = Event.observers.length; i < length; i++) { 3015 Event.stopObserving.apply(this, Event.observers[i]); 3016 Event.observers[i][0] = null; 3017 } 3018 Event.observers = false; 3019 }, 3020 3021 observe: function(element, name, observer, useCapture) { 3022 element = $(element); 3023 useCapture = useCapture || false; 3024 3025 if (name == 'keypress' && 3026 (Prototype.Browser.WebKit || element.attachEvent)) 3027 name = 'keydown'; 3028 3029 Event._observeAndCache(element, name, observer, useCapture); 3030 }, 3031 3032 stopObserving: function(element, name, observer, useCapture) { 3033 element = $(element); 3034 useCapture = useCapture || false; 3035 3036 if (name == 'keypress' && 3037 (Prototype.Browser.WebKit || element.attachEvent)) 3038 name = 'keydown'; 3039 3040 if (element.removeEventListener) { 3041 element.removeEventListener(name, observer, useCapture); 3042 } else if (element.detachEvent) { 3043 try { 3044 element.detachEvent('on' + name, observer); 3045 } catch (e) {} 3046 } 3047 } 3048 }); 3049 3050 /* prevent memory leaks in IE */ 3051 if (Prototype.Browser.IE) 3052 Event.observe(window, 'unload', Event.unloadCache, false); 4020 document.addEventListener("DOMContentLoaded", 4021 fireContentLoadedEvent, false); 4022 } 4023 4024 } else { 4025 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); 4026 $("__onDOMContentLoaded").onreadystatechange = function() { 4027 if (this.readyState == "complete") { 4028 this.onreadystatechange = null; 4029 fireContentLoadedEvent(); 4030 } 4031 }; 4032 } 4033 })(); 4034 /*------------------------------- DEPRECATED -------------------------------*/ 4035 4036 Hash.toQueryString = Object.toQueryString; 4037 4038 var Toggle = { display: Element.toggle }; 4039 4040 Element.Methods.childOf = Element.Methods.descendantOf; 4041 4042 var Insertion = { 4043 Before: function(element, content) { 4044 return Element.insert(element, {before:content}); 4045 }, 4046 4047 Top: function(element, content) { 4048 return Element.insert(element, {top:content}); 4049 }, 4050 4051 Bottom: function(element, content) { 4052 return Element.insert(element, {bottom:content}); 4053 }, 4054 4055 After: function(element, content) { 4056 return Element.insert(element, {after:content}); 4057 } 4058 }; 4059 4060 var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 4061 4062 // This should be moved to script.aculo.us; notice the deprecated methods 4063 // further below, that map to the newer Element methods. 3053 4064 var Position = { 3054 4065 // set to true if needed, warning: firefox performance problems … … 3070 4081 }, 3071 4082 3072 realOffset: function(element) {3073 var valueT = 0, valueL = 0;3074 do {3075 valueT += element.scrollTop || 0;3076 valueL += element.scrollLeft || 0;3077 element = element.parentNode;3078 } while (element);3079 return [valueL, valueT];3080 },3081 3082 cumulativeOffset: function(element) {3083 var valueT = 0, valueL = 0;3084 do {3085 valueT += element.offsetTop || 0;3086 valueL += element.offsetLeft || 0;3087 element = element.offsetParent;3088 } while (element);3089 return [valueL, valueT];3090 },3091 3092 positionedOffset: function(element) {3093 var valueT = 0, valueL = 0;3094 do {3095 valueT += element.offsetTop || 0;3096 valueL += element.offsetLeft || 0;3097 element = element.offsetParent;3098 if (element) {3099 if(element.tagName=='BODY') break;3100 var p = Element.getStyle(element, 'position');3101 if (p == 'relative' || p == 'absolute') break;3102 }3103 } while (element);3104 return [valueL, valueT];3105 },3106 3107 offsetParent: function(element) {3108 if (element.offsetParent) return element.offsetParent;3109 if (element == document.body) return element;3110 3111 while ((element = element.parentNode) && element != document.body)3112 if (Element.getStyle(element, 'position') != 'static')3113 return element;3114 3115 return document.body;3116 },3117 3118 4083 // caches x/y coordinate pair to use with overlap 3119 4084 within: function(element, x, y) { … … 3122 4087 this.xcomp = x; 3123 4088 this.ycomp = y; 3124 this.offset = this.cumulativeOffset(element);4089 this.offset = Element.cumulativeOffset(element); 3125 4090 3126 4091 return (y >= this.offset[1] && … … 3131 4096 3132 4097 withinIncludingScrolloffsets: function(element, x, y) { 3133 var offsetcache = this.realOffset(element);4098 var offsetcache = Element.cumulativeScrollOffset(element); 3134 4099 3135 4100 this.xcomp = x + offsetcache[0] - this.deltaX; 3136 4101 this.ycomp = y + offsetcache[1] - this.deltaY; 3137 this.offset = this.cumulativeOffset(element);4102 this.offset = Element.cumulativeOffset(element); 3138 4103 3139 4104 return (this.ycomp >= this.offset[1] && … … 3154 4119 }, 3155 4120 3156 page: function(forElement) { 3157 var valueT = 0, valueL = 0; 3158 3159 var element = forElement; 3160 do { 3161 valueT += element.offsetTop || 0; 3162 valueL += element.offsetLeft || 0; 3163 3164 // Safari fix 3165 if (element.offsetParent == document.body) 3166 if (Element.getStyle(element,'position')=='absolute') break; 3167 3168 } while (element = element.offsetParent); 3169 3170 element = forElement; 3171 do { 3172 if (!window.opera || element.tagName=='BODY') { 3173 valueT -= element.scrollTop || 0; 3174 valueL -= element.scrollLeft || 0; 3175 } 3176 } while (element = element.parentNode); 3177 3178 return [valueL, valueT]; 3179 }, 3180 3181 clone: function(source, target) { 3182 var options = Object.extend({ 3183 setLeft: true, 3184 setTop: true, 3185 setWidth: true, 3186 setHeight: true, 3187 offsetTop: 0, 3188 offsetLeft: 0 3189 }, arguments[2] || {}) 3190 3191 // find page position of source 3192 source = $(source); 3193 var p = Position.page(source); 3194 3195 // find coordinate system to use 3196 target = $(target); 3197 var delta = [0, 0]; 3198 var parent = null; 3199 // delta [0,0] will do fine with position: fixed elements, 3200 // position:absolute needs offsetParent deltas 3201 if (Element.getStyle(target,'position') == 'absolute') { 3202 parent = Position.offsetParent(target); 3203 delta = Position.page(parent); 3204 } 3205 3206 // correct by body offsets (fixes Safari) 3207 if (parent == document.body) { 3208 delta[0] -= document.body.offsetLeft; 3209 delta[1] -= document.body.offsetTop; 3210 } 3211 3212 // set position 3213 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 3214 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 3215 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; 3216 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; 3217 }, 4121 // Deprecation layer -- use newer Element methods now (1.5.2). 4122 4123 cumulativeOffset: Element.Methods.cumulativeOffset, 4124 4125 positionedOffset: Element.Methods.positionedOffset, 3218 4126 3219 4127 absolutize: function(element) { 3220 element = $(element);3221 if (element.style.position == 'absolute') return;3222 4128 Position.prepare(); 3223 3224 var offsets = Position.positionedOffset(element); 3225 var top = offsets[1]; 3226 var left = offsets[0]; 3227 var width = element.clientWidth; 3228 var height = element.clientHeight; 3229 3230 element._originalLeft = left - parseFloat(element.style.left || 0); 3231 element._originalTop = top - parseFloat(element.style.top || 0); 3232 element._originalWidth = element.style.width; 3233 element._originalHeight = element.style.height; 3234 3235 element.style.position = 'absolute'; 3236 element.style.top = top + 'px'; 3237 element.style.left = left + 'px'; 3238 element.style.width = width + 'px'; 3239 element.style.height = height + 'px'; 4129 return Element.absolutize(element); 3240 4130 }, 3241 4131 3242 4132 relativize: function(element) { 3243 element = $(element);3244 if (element.style.position == 'relative') return;3245 4133 Position.prepare(); 3246 3247 element.style.position = 'relative'; 3248 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 3249 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 3250 3251 element.style.top = top + 'px'; 3252 element.style.left = left + 'px'; 3253 element.style.height = element._originalHeight; 3254 element.style.width = element._originalWidth; 3255 } 3256 } 3257 3258 // Safari returns margins on body which is incorrect if the child is absolutely 3259 // positioned. For performance reasons, redefine Position.cumulativeOffset for 3260 // KHTML/WebKit only. 3261 if (Prototype.Browser.WebKit) { 3262 Position.cumulativeOffset = function(element) { 3263 var valueT = 0, valueL = 0; 3264 do { 3265 valueT += element.offsetTop || 0; 3266 valueL += element.offsetLeft || 0; 3267 if (element.offsetParent == document.body) 3268 if (Element.getStyle(element, 'position') == 'absolute') break; 3269 3270 element = element.offsetParent; 3271 } while (element); 3272 3273 return [valueL, valueT]; 3274 } 3275 } 4134 return Element.relativize(element); 4135 }, 4136 4137 realOffset: Element.Methods.cumulativeScrollOffset, 4138 4139 offsetParent: Element.Methods.getOffsetParent, 4140 4141 page: Element.Methods.viewportOffset, 4142 4143 clone: function(source, target, options) { 4144 options = options || { }; 4145 return Element.clonePosition(target, source, options); 4146 } 4147 }; 4148 4149 /*--------------------------------------------------------------------------*/ 4150 4151 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ 4152 function iter(name) { 4153 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; 4154 } 4155 4156 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? 4157 function(element, className) { 4158 className = className.toString().strip(); 4159 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); 4160 return cond ? document._getElementsByXPath('.//*' + cond, element) : []; 4161 } : function(element, className) { 4162 className = className.toString().strip(); 4163 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); 4164 if (!classNames && !className) return elements; 4165 4166 var nodes = $(element).getElementsByTagName('*'); 4167 className = ' ' + className + ' '; 4168 4169 for (var i = 0, child, cn; child = nodes[i]; i++) { 4170 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || 4171 (classNames && classNames.all(function(name) { 4172 return !name.toString().blank() && cn.include(' ' + name + ' '); 4173 })))) 4174 elements.push(Element.extend(child)); 4175 } 4176 return elements; 4177 }; 4178 4179 return function(className, parentElement) { 4180 return $(parentElement || document.body).getElementsByClassName(className); 4181 }; 4182 }(Element.Methods); 4183 4184 /*--------------------------------------------------------------------------*/ 4185 4186 Element.ClassNames = Class.create(); 4187 Element.ClassNames.prototype = { 4188 initialize: function(element) { 4189 this.element = $(element); 4190 }, 4191 4192 _each: function(iterator) { 4193 this.element.className.split(/\s+/).select(function(name) { 4194 return name.length > 0; 4195 })._each(iterator); 4196 }, 4197 4198 set: function(className) { 4199 this.element.className = className; 4200 }, 4201 4202 add: function(classNameToAdd) { 4203 if (this.include(classNameToAdd)) return; 4204 this.set($A(this).concat(classNameToAdd).join(' ')); 4205 }, 4206 4207 remove: function(classNameToRemove) { 4208 if (!this.include(classNameToRemove)) return; 4209 this.set($A(this).without(classNameToRemove).join(' ')); 4210 }, 4211 4212 toString: function() { 4213 return $A(this).join(' '); 4214 } 4215 }; 4216 4217 Object.extend(Element.ClassNames.prototype, Enumerable); 4218 4219 /*--------------------------------------------------------------------------*/ 3276 4220 3277 4221 Element.addMethods(); -
trunk/packages/sipb-xen-www/code/static/style.css
r435 r618 74 74 font-weight: bold; 75 75 } 76 77 /* Striping applied (by JavaScript) to every other row in /list. */ 78 tr.stripedrow { 79 background-color: #DDF; 80 } -
trunk/packages/sipb-xen-www/code/templates/list.tmpl
r609 r618 119 119 #def machineRow($machine) 120 120 <tr> 121 <td><a href="info?machine_id=$machine.machine_id">$machine.name</a></td>122 <td>${machine.memory}M</td>123 <td>$machine.owner</td>124 <td>$machine.administrator</td>125 #if $machine.nics126 #set $nic = $machine.nics[0]127 <td>$nic.ip</td>128 #else129 <td></td>130 #end if131 <td>#slurp132 #if $machine.uptime133 ${datetime.timedelta(seconds=int(machine.uptime))}#slurp134 #end if135 </td>136 <td>#slurp137 #if $has_vnc[$machine] == True138 <a href="vnc?machine_id=$machine.machine_id">Console</a>#slurp139 #else if $has_vnc[$machine] != 'Off'140 #filter None141 $has_vnc[$machine]142 #end filter143 #end if144 </td>145 121 <td rowspan="2"> 146 122 <form action="command" method="post"> … … 153 129 </form> 154 130 </td> 131 <td><a href="info?machine_id=$machine.machine_id">$machine.name</a></td> 132 <td>${machine.memory}M</td> 133 <td>$machine.owner</td> 134 <td>$machine.administrator</td> 135 #if $machine.nics 136 #set $nic = $machine.nics[0] 137 <td>$nic.ip</td> 138 #else 139 <td></td> 140 #end if 141 <td>#slurp 142 #if $machine.uptime 143 ${datetime.timedelta(seconds=int(machine.uptime))}#slurp 144 #end if 145 </td> 146 <td>#slurp 147 #if $has_vnc[$machine] == True 148 <a href="vnc?machine_id=$machine.machine_id">Console</a>#slurp 149 #else if $has_vnc[$machine] != 'Off' 150 #filter None 151 $has_vnc[$machine] 152 #end filter 153 #end if 154 </td> 155 155 </tr> 156 156 <tr> … … 160 160 161 161 #def machineList($machines) 162 <table >162 <table cellspacing="0" cellpadding="2"> 163 163 <tr> 164 <th></th> 164 165 <th>Name</th> 165 166 <th>Memory</th> … … 177 178 <th>Uptime</th> 178 179 <th>VNC</th> 179 <th></th>180 180 </tr> 181 181 #for $machine in $machines: … … 185 185 #end for 186 186 </table> 187 <script type="text/javascript" src="/static/stripe.js"></script> 188 <script type="text/javascript"> 189 document.observe("dom:loaded", function() { 190 stripe(\$('machinelist').getElementsByTagName('table')[0], 191 'stripedrow'); 192 }); 193 </script> 187 194 #end def 188 195 -
trunk/packages/sipb-xen-www/code/templates/skeleton.tmpl
r543 r618 57 57 <li><a href="vnc?machine_id=$machine.machine_id">Console</a></li> 58 58 #end if 59 <li><a href="help">Help</a></ ul></li>59 <li><a href="help">Help</a></li> 60 60 </ul> 61 61 #end if
Note: See TracChangeset
for help on using the changeset viewer.