Ticket #4265: 4265.diff
File 4265.diff, 65.2 KB (added by , 18 years ago) |
---|
-
wp-includes/js/prototype.js
1 /* Prototype JavaScript framework, version 1.5. 01 /* Prototype JavaScript framework, version 1.5.1 2 2 * (c) 2005-2007 Sam Stephenson 3 3 * 4 4 * Prototype is freely distributable under the terms of an MIT-style license. 5 * For details, see the Prototype web site: http:// prototype.conio.net/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.0', 10 Version: '1.5.1', 11 12 Browser: { 13 IE: !!(window.attachEvent && !window.opera), 14 Opera: !!window.opera, 15 WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, 16 Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 17 }, 18 11 19 BrowserFeatures: { 12 XPath: !!document.evaluate 20 XPath: !!document.evaluate, 21 ElementExtensions: !!window.HTMLElement, 22 SpecificElementExtensions: 23 (document.createElement('div').__proto__ !== 24 document.createElement('form').__proto__) 13 25 }, 14 26 15 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 16 emptyFunction: function() {}, 27 ScriptFragment: '<script[^>]*>([\u0001-\uFFFF]*?)</script>', 28 JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, 29 30 emptyFunction: function() { }, 17 31 K: function(x) { return x } 18 32 } 19 33 … … 46 60 } 47 61 }, 48 62 63 toJSON: function(object) { 64 var type = typeof object; 65 switch(type) { 66 case 'undefined': 67 case 'function': 68 case 'unknown': return; 69 case 'boolean': return object.toString(); 70 } 71 if (object === null) return 'null'; 72 if (object.toJSON) return object.toJSON(); 73 if (object.ownerDocument === document) return; 74 var results = []; 75 for (var property in object) { 76 var value = Object.toJSON(object[property]); 77 if (value !== undefined) 78 results.push(property.toJSON() + ': ' + value); 79 } 80 return '{' + results.join(', ') + '}'; 81 }, 82 49 83 keys: function(object) { 50 84 var keys = []; 51 85 for (var property in object) … … 75 109 Function.prototype.bindAsEventListener = function(object) { 76 110 var __method = this, args = $A(arguments), object = args.shift(); 77 111 return function(event) { 78 return __method.apply(object, [ ( event || window.event)].concat(args).concat($A(arguments)));112 return __method.apply(object, [event || window.event].concat(args)); 79 113 } 80 114 } 81 115 82 116 Object.extend(Number.prototype, { 83 117 toColorPart: function() { 84 var digits = this.toString(16); 85 if (this < 16) return '0' + digits; 86 return digits; 118 return this.toPaddedString(2, 16); 87 119 }, 88 120 89 121 succ: function() { … … 93 125 times: function(iterator) { 94 126 $R(0, this, true).each(iterator); 95 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'; 96 137 } 97 138 }); 98 139 140 Date.prototype.toJSON = function() { 141 return '"' + this.getFullYear() + '-' + 142 (this.getMonth() + 1).toPaddedString(2) + '-' + 143 this.getDate().toPaddedString(2) + 'T' + 144 this.getHours().toPaddedString(2) + ':' + 145 this.getMinutes().toPaddedString(2) + ':' + 146 this.getSeconds().toPaddedString(2) + '"'; 147 }; 148 99 149 var Try = { 100 150 these: function() { 101 151 var returnValue; … … 145 195 } 146 196 } 147 197 } 148 String.interpret = function(value){ 149 return value == null ? '' : String(value); 150 } 198 Object.extend(String, { 199 interpret: function(value) { 200 return value == null ? '' : String(value); 201 }, 202 specialChar: { 203 '\b': '\\b', 204 '\t': '\\t', 205 '\n': '\\n', 206 '\f': '\\f', 207 '\r': '\\r', 208 '\\': '\\\\' 209 } 210 }); 151 211 152 212 Object.extend(String.prototype, { 153 213 gsub: function(pattern, replacement) { … … 213 273 }, 214 274 215 275 escapeHTML: function() { 216 var div = document.createElement('div'); 217 var text = document.createTextNode(this); 218 div.appendChild(text); 219 return div.innerHTML; 276 var self = arguments.callee; 277 self.text.data = this; 278 return self.div.innerHTML; 220 279 }, 221 280 222 281 unescapeHTML: function() { 223 282 var div = document.createElement('div'); 224 283 div.innerHTML = this.stripTags(); 225 284 return div.childNodes[0] ? (div.childNodes.length > 1 ? 226 $A(div.childNodes).inject('', function(memo,node){ return memo+node.nodeValue }) :285 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 227 286 div.childNodes[0].nodeValue) : ''; 228 287 }, 229 288 … … 233 292 234 293 return match[1].split(separator || '&').inject({}, function(hash, pair) { 235 294 if ((pair = pair.split('='))[0]) { 236 var name = decodeURIComponent(pair[0]); 237 var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; 295 var key = decodeURIComponent(pair.shift()); 296 var value = pair.length > 1 ? pair.join('=') : pair[0]; 297 if (value != undefined) value = decodeURIComponent(value); 238 298 239 if (hash[name] !== undefined) { 240 if (hash[name].constructor != Array) 241 hash[name] = [hash[name]]; 242 if (value) hash[name].push(value); 299 if (key in hash) { 300 if (hash[key].constructor != Array) hash[key] = [hash[key]]; 301 hash[key].push(value); 243 302 } 244 else hash[ name] = value;303 else hash[key] = value; 245 304 } 246 305 return hash; 247 306 }); … … 256 315 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 257 316 }, 258 317 318 times: function(count) { 319 var result = ''; 320 for (var i = 0; i < count; i++) result += this; 321 return result; 322 }, 323 259 324 camelize: function() { 260 325 var parts = this.split('-'), len = parts.length; 261 326 if (len == 1) return parts[0]; … … 270 335 return camelized; 271 336 }, 272 337 273 capitalize: function() {338 capitalize: function() { 274 339 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 275 340 }, 276 341 … … 283 348 }, 284 349 285 350 inspect: function(useDoubleQuotes) { 286 var escapedString = this.replace(/\\/g, '\\\\'); 287 if (useDoubleQuotes) 288 return '"' + escapedString.replace(/"/g, '\\"') + '"'; 289 else 290 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 351 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { 352 var character = String.specialChar[match[0]]; 353 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); 354 }); 355 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 356 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 357 }, 358 359 toJSON: function() { 360 return this.inspect(true); 361 }, 362 363 unfilterJSON: function(filter) { 364 return this.sub(filter || Prototype.JSONFilter, '#{1}'); 365 }, 366 367 evalJSON: function(sanitize) { 368 var json = this.unfilterJSON(); 369 try { 370 if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) 371 return eval('(' + json + ')'); 372 } catch (e) { } 373 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 374 }, 375 376 include: function(pattern) { 377 return this.indexOf(pattern) > -1; 378 }, 379 380 startsWith: function(pattern) { 381 return this.indexOf(pattern) === 0; 382 }, 383 384 endsWith: function(pattern) { 385 var d = this.length - pattern.length; 386 return d >= 0 && this.lastIndexOf(pattern) === d; 387 }, 388 389 empty: function() { 390 return this == ''; 391 }, 392 393 blank: function() { 394 return /^\s*$/.test(this); 291 395 } 292 396 }); 293 397 398 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 399 escapeHTML: function() { 400 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 401 }, 402 unescapeHTML: function() { 403 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 404 } 405 }); 406 294 407 String.prototype.gsub.prepareReplacement = function(replacement) { 295 408 if (typeof replacement == 'function') return replacement; 296 409 var template = new Template(replacement); … … 299 412 300 413 String.prototype.parseQuery = String.prototype.toQueryParams; 301 414 415 Object.extend(String.prototype.escapeHTML, { 416 div: document.createElement('div'), 417 text: document.createTextNode('') 418 }); 419 420 with (String.prototype.escapeHTML) div.appendChild(text); 421 302 422 var Template = Class.create(); 303 423 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 304 424 Template.prototype = { … … 316 436 } 317 437 } 318 438 319 var $break = new Object(); 320 var $continue = new Object(); 439 var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 321 440 322 441 var Enumerable = { 323 442 each: function(iterator) { 324 443 var index = 0; 325 444 try { 326 445 this._each(function(value) { 327 try { 328 iterator(value, index++); 329 } catch (e) { 330 if (e != $continue) throw e; 331 } 446 iterator(value, index++); 332 447 }); 333 448 } catch (e) { 334 449 if (e != $break) throw e; … … 530 645 } 531 646 } 532 647 648 if (Prototype.Browser.WebKit) { 649 $A = Array.from = function(iterable) { 650 if (!iterable) return []; 651 if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && 652 iterable.toArray) { 653 return iterable.toArray(); 654 } else { 655 var results = []; 656 for (var i = 0, length = iterable.length; i < length; i++) 657 results.push(iterable[i]); 658 return results; 659 } 660 } 661 } 662 533 663 Object.extend(Array.prototype, Enumerable); 534 664 535 665 if (!Array.prototype._reverse) … … 588 718 return this.length > 1 ? this : this[0]; 589 719 }, 590 720 591 uniq: function() { 592 return this.inject([], function(array, value) { 593 return array.include(value) ? array : array.concat([value]); 721 uniq: function(sorted) { 722 return this.inject([], function(array, value, index) { 723 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 724 array.push(value); 725 return array; 594 726 }); 595 727 }, 596 728 … … 604 736 605 737 inspect: function() { 606 738 return '[' + this.map(Object.inspect).join(', ') + ']'; 739 }, 740 741 toJSON: function() { 742 var results = []; 743 this.each(function(object) { 744 var value = Object.toJSON(object); 745 if (value !== undefined) results.push(value); 746 }); 747 return '[' + results.join(', ') + ']'; 607 748 } 608 749 }); 609 750 610 751 Array.prototype.toArray = Array.prototype.clone; 611 752 612 function $w(string) {753 function $w(string) { 613 754 string = string.strip(); 614 755 return string ? string.split(/\s+/) : []; 615 756 } 616 757 617 if (window.opera){618 Array.prototype.concat = function() {758 if (Prototype.Browser.Opera){ 759 Array.prototype.concat = function() { 619 760 var array = []; 620 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);621 for (var i = 0, length = arguments.length; i < length; i++) {622 if (arguments[i].constructor == Array) {623 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)761 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 762 for (var i = 0, length = arguments.length; i < length; i++) { 763 if (arguments[i].constructor == Array) { 764 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 624 765 array.push(arguments[i][j]); 625 766 } else { 626 767 array.push(arguments[i]); … … 629 770 return array; 630 771 } 631 772 } 632 var Hash = function(obj) { 633 Object.extend(this, obj || {}); 773 var Hash = function(object) { 774 if (object instanceof Hash) this.merge(object); 775 else Object.extend(this, object || {}); 634 776 }; 635 777 636 778 Object.extend(Hash, { 637 779 toQueryString: function(obj) { 638 780 var parts = []; 781 parts.add = arguments.callee.addPair; 639 782 640 783 this.prototype._each.call(obj, function(pair) { 641 784 if (!pair.key) return; 785 var value = pair.value; 642 786 643 if (pair.value && pair.value.constructor == Array) { 644 var values = pair.value.compact(); 645 if (values.length < 2) pair.value = values.reduce(); 646 else { 647 key = encodeURIComponent(pair.key); 648 values.each(function(value) { 649 value = value != undefined ? encodeURIComponent(value) : ''; 650 parts.push(key + '=' + encodeURIComponent(value)); 651 }); 652 return; 653 } 787 if (value && typeof value == 'object') { 788 if (value.constructor == Array) value.each(function(value) { 789 parts.add(pair.key, value); 790 }); 791 return; 654 792 } 655 if (pair.value == undefined) pair[1] = ''; 656 parts.push(pair.map(encodeURIComponent).join('=')); 657 }); 793 parts.add(pair.key, value); 794 }); 658 795 659 796 return parts.join('&'); 797 }, 798 799 toJSON: function(object) { 800 var results = []; 801 this.prototype._each.call(object, function(pair) { 802 var value = Object.toJSON(pair.value); 803 if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); 804 }); 805 return '{' + results.join(', ') + '}'; 660 806 } 661 807 }); 662 808 809 Hash.toQueryString.addPair = function(key, value, prefix) { 810 key = encodeURIComponent(key); 811 if (value === undefined) this.push(key); 812 else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); 813 } 814 663 815 Object.extend(Hash.prototype, Enumerable); 664 816 Object.extend(Hash.prototype, { 665 817 _each: function(iterator) { … … 713 865 return '#<Hash:{' + this.map(function(pair) { 714 866 return pair.map(Object.inspect).join(': '); 715 867 }).join(', ') + '}>'; 868 }, 869 870 toJSON: function() { 871 return Hash.toJSON(this); 716 872 } 717 873 }); 718 874 719 875 function $H(object) { 720 if (object && object.constructor ==Hash) return object;876 if (object instanceof Hash) return object; 721 877 return new Hash(object); 722 878 }; 879 880 // Safari iterates over shadowed properties 881 if (function() { 882 var i = 0, Test = function(value) { this.key = value }; 883 Test.prototype.key = 'foo'; 884 for (var property in new Test('bar')) i++; 885 return i > 1; 886 }()) Hash.prototype._each = function(iterator) { 887 var cache = []; 888 for (var key in this) { 889 var value = this[key]; 890 if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; 891 cache.push(key); 892 var pair = [key, value]; 893 pair.key = key; 894 pair.value = value; 895 iterator(pair); 896 } 897 }; 723 898 ObjectRange = Class.create(); 724 899 Object.extend(ObjectRange.prototype, Enumerable); 725 900 Object.extend(ObjectRange.prototype, { … … 834 1009 request: function(url) { 835 1010 this.url = url; 836 1011 this.method = this.options.method; 837 var params = this.options.parameters;1012 var params = Object.clone(this.options.parameters); 838 1013 839 1014 if (!['get', 'post'].include(this.method)) { 840 1015 // simulate other verbs over post … … 842 1017 this.method = 'post'; 843 1018 } 844 1019 845 params = Hash.toQueryString(params); 846 if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' 1020 this.parameters = params; 847 1021 848 // when GET, append parameters to URL 849 if (this.method == 'get' && params) 850 this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; 1022 if (params = Hash.toQueryString(params)) { 1023 // when GET, append parameters to URL 1024 if (this.method == 'get') 1025 this.url += (this.url.include('?') ? '&' : '?') + params; 1026 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1027 params += '&_='; 1028 } 851 1029 852 1030 try { 1031 if (this.options.onCreate) this.options.onCreate(this.transport); 853 1032 Ajax.Responders.dispatch('onCreate', this, this.transport); 854 1033 855 1034 this.transport.open(this.method.toUpperCase(), this.url, … … 861 1040 this.transport.onreadystatechange = this.onStateChange.bind(this); 862 1041 this.setRequestHeaders(); 863 1042 864 var body = this.method == 'post' ? (this.options.postBody || params) : null; 1043 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 1044 this.transport.send(this.body); 865 1045 866 this.transport.send(body);867 868 1046 /* Force Firefox to handle ready state 4 for synchronous requests */ 869 1047 if (!this.options.asynchronous && this.transport.overrideMimeType) 870 1048 this.onStateChange(); … … 935 1113 this.dispatchException(e); 936 1114 } 937 1115 938 if ((this.getHeader('Content-type') || 'text/javascript').strip(). 1116 var contentType = this.getHeader('Content-type'); 1117 if (contentType && contentType.strip(). 939 1118 match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) 940 1119 this.evalResponse(); 941 1120 } … … 962 1141 evalJSON: function() { 963 1142 try { 964 1143 var json = this.getHeader('X-JSON'); 965 return json ? eval('(' + json + ')') : null;1144 return json ? json.evalJSON() : null; 966 1145 } catch (e) { return null } 967 1146 }, 968 1147 969 1148 evalResponse: function() { 970 1149 try { 971 return eval( this.transport.responseText);1150 return eval((this.transport.responseText || '').unfilterJSON()); 972 1151 } catch (e) { 973 1152 this.dispatchException(e); 974 1153 } … … 1083 1262 results.push(query.snapshotItem(i)); 1084 1263 return results; 1085 1264 }; 1086 }1087 1265 1088 document.getElementsByClassName = function(className, parentElement) { 1089 if (Prototype.BrowserFeatures.XPath) { 1266 document.getElementsByClassName = function(className, parentElement) { 1090 1267 var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; 1091 1268 return document._getElementsByXPath(q, parentElement); 1092 } else {1093 var children = ($(parentElement) || document.body).getElementsByTagName('*');1094 var elements = [], child;1095 for (var i = 0, length = children.length; i < length; i++) {1096 child = children[i];1097 if (Element.hasClassName(child, className))1098 elements.push(Element.extend(child));1099 }1100 return elements;1101 1269 } 1270 1271 } else document.getElementsByClassName = function(className, parentElement) { 1272 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 1273 var elements = [], child; 1274 for (var i = 0, length = children.length; i < length; i++) { 1275 child = children[i]; 1276 if (Element.hasClassName(child, className)) 1277 elements.push(Element.extend(child)); 1278 } 1279 return elements; 1102 1280 }; 1103 1281 1104 1282 /*--------------------------------------------------------------------------*/ 1105 1283 1106 if (!window.Element) 1107 var Element = new Object(); 1284 if (!window.Element) var Element = {}; 1108 1285 1109 1286 Element.extend = function(element) { 1110 if (!element || _nativeExtensions || element.nodeType == 3) return element; 1287 var F = Prototype.BrowserFeatures; 1288 if (!element || !element.tagName || element.nodeType == 3 || 1289 element._extended || F.SpecificElementExtensions || element == window) 1290 return element; 1111 1291 1112 if (!element._extended && element.tagName && element != window) {1113 var methods = Object.clone(Element.Methods), cache = Element.extend.cache;1292 var methods = {}, tagName = element.tagName, cache = Element.extend.cache, 1293 T = Element.Methods.ByTag; 1114 1294 1115 if (element.tagName == 'FORM') 1116 Object.extend(methods, Form.Methods); 1117 if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) 1118 Object.extend(methods, Form.Element.Methods); 1119 1295 // extend methods for all tags (Safari doesn't need this) 1296 if (!F.ElementExtensions) { 1297 Object.extend(methods, Element.Methods), 1120 1298 Object.extend(methods, Element.Methods.Simulated); 1299 } 1121 1300 1122 for (var property in methods) { 1123 var value = methods[property]; 1124 if (typeof value == 'function' && !(property in element)) 1125 element[property] = cache.findOrStore(value); 1126 } 1301 // extend methods for specific tags 1302 if (T[tagName]) Object.extend(methods, T[tagName]); 1303 1304 for (var property in methods) { 1305 var value = methods[property]; 1306 if (typeof value == 'function' && !(property in element)) 1307 element[property] = cache.findOrStore(value); 1127 1308 } 1128 1309 1129 element._extended = true;1310 element._extended = Prototype.emptyFunction; 1130 1311 return element; 1131 1312 }; 1132 1313 … … 1212 1393 }, 1213 1394 1214 1395 descendants: function(element) { 1215 return $A($(element).getElementsByTagName('*')) ;1396 return $A($(element).getElementsByTagName('*')).each(Element.extend); 1216 1397 }, 1217 1398 1399 firstDescendant: function(element) { 1400 element = $(element).firstChild; 1401 while (element && element.nodeType != 1) element = element.nextSibling; 1402 return $(element); 1403 }, 1404 1218 1405 immediateDescendants: function(element) { 1219 1406 if (!(element = $(element).firstChild)) return []; 1220 1407 while (element && element.nodeType != 1) element = element.nextSibling; … … 1242 1429 }, 1243 1430 1244 1431 up: function(element, expression, index) { 1245 return Selector.findElement($(element).ancestors(), expression, index); 1432 element = $(element); 1433 if (arguments.length == 1) return $(element.parentNode); 1434 var ancestors = element.ancestors(); 1435 return expression ? Selector.findElement(ancestors, expression, index) : 1436 ancestors[index || 0]; 1246 1437 }, 1247 1438 1248 1439 down: function(element, expression, index) { 1249 return Selector.findElement($(element).descendants(), expression, index); 1440 element = $(element); 1441 if (arguments.length == 1) return element.firstDescendant(); 1442 var descendants = element.descendants(); 1443 return expression ? Selector.findElement(descendants, expression, index) : 1444 descendants[index || 0]; 1250 1445 }, 1251 1446 1252 1447 previous: function(element, expression, index) { 1253 return Selector.findElement($(element).previousSiblings(), expression, index); 1448 element = $(element); 1449 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 1450 var previousSiblings = element.previousSiblings(); 1451 return expression ? Selector.findElement(previousSiblings, expression, index) : 1452 previousSiblings[index || 0]; 1254 1453 }, 1255 1454 1256 1455 next: function(element, expression, index) { 1257 return Selector.findElement($(element).nextSiblings(), expression, index); 1456 element = $(element); 1457 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 1458 var nextSiblings = element.nextSiblings(); 1459 return expression ? Selector.findElement(nextSiblings, expression, index) : 1460 nextSiblings[index || 0]; 1258 1461 }, 1259 1462 1260 1463 getElementsBySelector: function() { … … 1268 1471 1269 1472 readAttribute: function(element, name) { 1270 1473 element = $(element); 1271 if (document.all && !window.opera) { 1474 if (Prototype.Browser.IE) { 1475 if (!element.attributes) return null; 1272 1476 var t = Element._attributeTranslations; 1273 1477 if (t.values[name]) return t.values[name](element, name); 1274 1478 if (t.names[name]) name = t.names[name]; 1275 1479 var attribute = element.attributes[name]; 1276 if(attribute) return attribute.nodeValue;1480 return attribute ? attribute.nodeValue : null; 1277 1481 } 1278 1482 return element.getAttribute(name); 1279 1483 }, … … 1342 1546 }, 1343 1547 1344 1548 empty: function(element) { 1345 return $(element).innerHTML. match(/^\s*$/);1549 return $(element).innerHTML.blank(); 1346 1550 }, 1347 1551 1348 1552 descendantOf: function(element, ancestor) { … … 1361 1565 1362 1566 getStyle: function(element, style) { 1363 1567 element = $(element); 1364 if (['float','cssFloat'].include(style)) 1365 style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); 1366 style = style.camelize(); 1568 style = style == 'float' ? 'cssFloat' : style.camelize(); 1367 1569 var value = element.style[style]; 1368 1570 if (!value) { 1369 if (document.defaultView && document.defaultView.getComputedStyle) { 1370 var css = document.defaultView.getComputedStyle(element, null); 1371 value = css ? css[style] : null; 1372 } else if (element.currentStyle) { 1373 value = element.currentStyle[style]; 1374 } 1571 var css = document.defaultView.getComputedStyle(element, null); 1572 value = css ? css[style] : null; 1375 1573 } 1574 if (style == 'opacity') return value ? parseFloat(value) : 1.0; 1575 return value == 'auto' ? null : value; 1576 }, 1376 1577 1377 if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) 1378 value = element['offset'+style.capitalize()] + 'px'; 1578 getOpacity: function(element) { 1579 return $(element).getStyle('opacity'); 1580 }, 1379 1581 1380 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) 1381 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; 1382 if(style == 'opacity') { 1383 if(value) return parseFloat(value); 1384 if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 1385 if(value[1]) return parseFloat(value[1]) / 100; 1386 return 1.0; 1387 } 1388 return value == 'auto' ? null : value; 1582 setStyle: function(element, styles, camelized) { 1583 element = $(element); 1584 var elementStyle = element.style; 1585 1586 for (var property in styles) 1587 if (property == 'opacity') element.setOpacity(styles[property]) 1588 else 1589 elementStyle[(property == 'float' || property == 'cssFloat') ? 1590 (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : 1591 (camelized ? property : property.camelize())] = styles[property]; 1592 1593 return element; 1389 1594 }, 1390 1595 1391 set Style: function(element, style) {1596 setOpacity: function(element, value) { 1392 1597 element = $(element); 1393 for (var name in style) { 1394 var value = style[name]; 1395 if(name == 'opacity') { 1396 if (value == 1) { 1397 value = (/Gecko/.test(navigator.userAgent) && 1398 !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; 1399 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1400 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 1401 } else if(value == '') { 1402 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1403 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); 1404 } else { 1405 if(value < 0.00001) value = 0; 1406 if(/MSIE/.test(navigator.userAgent) && !window.opera) 1407 element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + 1408 'alpha(opacity='+value*100+')'; 1409 } 1410 } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; 1411 element.style[name.camelize()] = value; 1412 } 1598 element.style.opacity = (value == 1 || value === '') ? '' : 1599 (value < 0.00001) ? 0 : value; 1413 1600 return element; 1414 1601 }, 1415 1602 … … 1483 1670 } 1484 1671 }; 1485 1672 1486 Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); 1673 Object.extend(Element.Methods, { 1674 childOf: Element.Methods.descendantOf, 1675 childElements: Element.Methods.immediateDescendants 1676 }); 1487 1677 1488 Element._attributeTranslations = {}; 1678 if (Prototype.Browser.Opera) { 1679 Element.Methods._getStyle = Element.Methods.getStyle; 1680 Element.Methods.getStyle = function(element, style) { 1681 switch(style) { 1682 case 'left': 1683 case 'top': 1684 case 'right': 1685 case 'bottom': 1686 if (Element._getStyle(element, 'position') == 'static') return null; 1687 default: return Element._getStyle(element, style); 1688 } 1689 }; 1690 } 1691 else if (Prototype.Browser.IE) { 1692 Element.Methods.getStyle = function(element, style) { 1693 element = $(element); 1694 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); 1695 var value = element.style[style]; 1696 if (!value && element.currentStyle) value = element.currentStyle[style]; 1489 1697 1490 Element._attributeTranslations.names = { 1491 colspan: "colSpan", 1492 rowspan: "rowSpan", 1493 valign: "vAlign", 1494 datetime: "dateTime", 1495 accesskey: "accessKey", 1496 tabindex: "tabIndex", 1497 enctype: "encType", 1498 maxlength: "maxLength", 1499 readonly: "readOnly", 1500 longdesc: "longDesc" 1501 }; 1698 if (style == 'opacity') { 1699 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 1700 if (value[1]) return parseFloat(value[1]) / 100; 1701 return 1.0; 1702 } 1502 1703 1503 Element._attributeTranslations.values = { 1504 _getAttr: function(element, attribute) { 1505 return element.getAttribute(attribute, 2); 1506 }, 1704 if (value == 'auto') { 1705 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 1706 return element['offset'+style.capitalize()] + 'px'; 1707 return null; 1708 } 1709 return value; 1710 }; 1507 1711 1508 _flag: function(element, attribute) { 1509 return $(element).hasAttribute(attribute) ? attribute : null; 1510 }, 1712 Element.Methods.setOpacity = function(element, value) { 1713 element = $(element); 1714 var filter = element.getStyle('filter'), style = element.style; 1715 if (value == 1 || value === '') { 1716 style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); 1717 return element; 1718 } else if (value < 0.00001) value = 0; 1719 style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + 1720 'alpha(opacity=' + (value * 100) + ')'; 1721 return element; 1722 }; 1511 1723 1512 style: function(element) { 1513 return element.style.cssText.toLowerCase(); 1514 }, 1515 1516 title: function(element) { 1517 var node = element.getAttributeNode('title'); 1518 return node.specified ? node.nodeValue : null; 1519 } 1520 }; 1521 1522 Object.extend(Element._attributeTranslations.values, { 1523 href: Element._attributeTranslations.values._getAttr, 1524 src: Element._attributeTranslations.values._getAttr, 1525 disabled: Element._attributeTranslations.values._flag, 1526 checked: Element._attributeTranslations.values._flag, 1527 readonly: Element._attributeTranslations.values._flag, 1528 multiple: Element._attributeTranslations.values._flag 1529 }); 1530 1531 Element.Methods.Simulated = { 1532 hasAttribute: function(element, attribute) { 1533 var t = Element._attributeTranslations; 1534 attribute = t.names[attribute] || attribute; 1535 return $(element).getAttributeNode(attribute).specified; 1536 } 1537 }; 1538 1539 // IE is missing .innerHTML support for TABLE-related elements 1540 if (document.all && !window.opera){ 1724 // IE is missing .innerHTML support for TABLE-related elements 1541 1725 Element.Methods.update = function(element, html) { 1542 1726 element = $(element); 1543 1727 html = typeof html == 'undefined' ? '' : html.toString(); … … 1558 1742 div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>'; 1559 1743 depth = 4; 1560 1744 } 1561 $A(element.childNodes).each(function(node){ 1562 element.removeChild(node) 1563 }); 1564 depth.times(function(){ div = div.firstChild }); 1565 1566 $A(div.childNodes).each( 1567 function(node){ element.appendChild(node) }); 1745 $A(element.childNodes).each(function(node) { element.removeChild(node) }); 1746 depth.times(function() { div = div.firstChild }); 1747 $A(div.childNodes).each(function(node) { element.appendChild(node) }); 1568 1748 } else { 1569 1749 element.innerHTML = html.stripScripts(); 1570 1750 } 1571 setTimeout(function() { html.evalScripts()}, 10);1751 setTimeout(function() { html.evalScripts() }, 10); 1572 1752 return element; 1573 1753 } 1754 } 1755 else if (Prototype.Browser.Gecko) { 1756 Element.Methods.setOpacity = function(element, value) { 1757 element = $(element); 1758 element.style.opacity = (value == 1) ? 0.999999 : 1759 (value === '') ? '' : (value < 0.00001) ? 0 : value; 1760 return element; 1761 }; 1762 } 1763 1764 Element._attributeTranslations = { 1765 names: { 1766 colspan: "colSpan", 1767 rowspan: "rowSpan", 1768 valign: "vAlign", 1769 datetime: "dateTime", 1770 accesskey: "accessKey", 1771 tabindex: "tabIndex", 1772 enctype: "encType", 1773 maxlength: "maxLength", 1774 readonly: "readOnly", 1775 longdesc: "longDesc" 1776 }, 1777 values: { 1778 _getAttr: function(element, attribute) { 1779 return element.getAttribute(attribute, 2); 1780 }, 1781 _flag: function(element, attribute) { 1782 return $(element).hasAttribute(attribute) ? attribute : null; 1783 }, 1784 style: function(element) { 1785 return element.style.cssText.toLowerCase(); 1786 }, 1787 title: function(element) { 1788 var node = element.getAttributeNode('title'); 1789 return node.specified ? node.nodeValue : null; 1790 } 1791 } 1574 1792 }; 1575 1793 1794 (function() { 1795 Object.extend(this, { 1796 href: this._getAttr, 1797 src: this._getAttr, 1798 type: this._getAttr, 1799 disabled: this._flag, 1800 checked: this._flag, 1801 readonly: this._flag, 1802 multiple: this._flag 1803 }); 1804 }).call(Element._attributeTranslations.values); 1805 1806 Element.Methods.Simulated = { 1807 hasAttribute: function(element, attribute) { 1808 var t = Element._attributeTranslations, node; 1809 attribute = t.names[attribute] || attribute; 1810 node = $(element).getAttributeNode(attribute); 1811 return node && node.specified; 1812 } 1813 }; 1814 1815 Element.Methods.ByTag = {}; 1816 1576 1817 Object.extend(Element, Element.Methods); 1577 1818 1578 var _nativeExtensions = false; 1819 if (!Prototype.BrowserFeatures.ElementExtensions && 1820 document.createElement('div').__proto__) { 1821 window.HTMLElement = {}; 1822 window.HTMLElement.prototype = document.createElement('div').__proto__; 1823 Prototype.BrowserFeatures.ElementExtensions = true; 1824 } 1579 1825 1580 if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1581 ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { 1582 var className = 'HTML' + tag + 'Element'; 1583 if(window[className]) return; 1584 var klass = window[className] = {}; 1585 klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; 1586 }); 1826 Element.hasAttribute = function(element, attribute) { 1827 if (element.hasAttribute) return element.hasAttribute(attribute); 1828 return Element.Methods.Simulated.hasAttribute(element, attribute); 1829 }; 1587 1830 1588 1831 Element.addMethods = function(methods) { 1589 Object.extend(Element.Methods, methods || {});1832 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 1590 1833 1834 if (!methods) { 1835 Object.extend(Form, Form.Methods); 1836 Object.extend(Form.Element, Form.Element.Methods); 1837 Object.extend(Element.Methods.ByTag, { 1838 "FORM": Object.clone(Form.Methods), 1839 "INPUT": Object.clone(Form.Element.Methods), 1840 "SELECT": Object.clone(Form.Element.Methods), 1841 "TEXTAREA": Object.clone(Form.Element.Methods) 1842 }); 1843 } 1844 1845 if (arguments.length == 2) { 1846 var tagName = methods; 1847 methods = arguments[1]; 1848 } 1849 1850 if (!tagName) Object.extend(Element.Methods, methods || {}); 1851 else { 1852 if (tagName.constructor == Array) tagName.each(extend); 1853 else extend(tagName); 1854 } 1855 1856 function extend(tagName) { 1857 tagName = tagName.toUpperCase(); 1858 if (!Element.Methods.ByTag[tagName]) 1859 Element.Methods.ByTag[tagName] = {}; 1860 Object.extend(Element.Methods.ByTag[tagName], methods); 1861 } 1862 1591 1863 function copy(methods, destination, onlyIfAbsent) { 1592 1864 onlyIfAbsent = onlyIfAbsent || false; 1593 1865 var cache = Element.extend.cache; … … 1598 1870 } 1599 1871 } 1600 1872 1601 if (typeof HTMLElement != 'undefined') { 1873 function findDOMClass(tagName) { 1874 var klass; 1875 var trans = { 1876 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", 1877 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 1878 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 1879 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", 1880 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": 1881 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": 1882 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 1883 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": 1884 "FrameSet", "IFRAME": "IFrame" 1885 }; 1886 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 1887 if (window[klass]) return window[klass]; 1888 klass = 'HTML' + tagName + 'Element'; 1889 if (window[klass]) return window[klass]; 1890 klass = 'HTML' + tagName.capitalize() + 'Element'; 1891 if (window[klass]) return window[klass]; 1892 1893 window[klass] = {}; 1894 window[klass].prototype = document.createElement(tagName).__proto__; 1895 return window[klass]; 1896 } 1897 1898 if (F.ElementExtensions) { 1602 1899 copy(Element.Methods, HTMLElement.prototype); 1603 1900 copy(Element.Methods.Simulated, HTMLElement.prototype, true); 1604 copy(Form.Methods, HTMLFormElement.prototype);1605 [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {1606 copy(Form.Element.Methods, klass.prototype);1607 });1608 _nativeExtensions = true;1609 1901 } 1610 }1611 1902 1612 var Toggle = new Object(); 1613 Toggle.display = Element.toggle; 1903 if (F.SpecificElementExtensions) { 1904 for (var tag in Element.Methods.ByTag) { 1905 var klass = findDOMClass(tag); 1906 if (typeof klass == "undefined") continue; 1907 copy(T[tag], klass.prototype); 1908 } 1909 } 1614 1910 1911 Object.extend(Element, Element.Methods); 1912 delete Element.ByTag; 1913 }; 1914 1915 var Toggle = { display: Element.toggle }; 1916 1615 1917 /*--------------------------------------------------------------------------*/ 1616 1918 1617 1919 Abstract.Insertion = function(adjacency) { … … 1741 2043 }; 1742 2044 1743 2045 Object.extend(Element.ClassNames.prototype, Enumerable); 2046 /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, 2047 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 2048 * license. Please see http://www.yui-ext.com/ for more information. */ 2049 1744 2050 var Selector = Class.create(); 2051 1745 2052 Selector.prototype = { 1746 2053 initialize: function(expression) { 1747 this.params = {classNames: []}; 1748 this.expression = expression.toString().strip(); 1749 this.parseExpression(); 2054 this.expression = expression.strip(); 1750 2055 this.compileMatcher(); 1751 2056 }, 1752 2057 1753 parseExpression: function() { 1754 function abort(message) { throw 'Parse error in selector: ' + message; } 2058 compileMatcher: function() { 2059 // Selectors with namespaced attributes can't use the XPath version 2060 if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) 2061 return this.compileXPathMatcher(); 1755 2062 1756 if (this.expression == '') abort('empty expression'); 2063 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 2064 c = Selector.criteria, le, p, m; 1757 2065 1758 var params = this.params, expr = this.expression, match, modifier, clause, rest; 1759 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { 1760 params.attributes = params.attributes || []; 1761 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); 1762 expr = match[1]; 2066 if (Selector._cache[e]) { 2067 this.matcher = Selector._cache[e]; return; 1763 2068 } 2069 this.matcher = ["this.matcher = function(root) {", 2070 "var r = root, h = Selector.handlers, c = false, n;"]; 1764 2071 1765 if (expr == '*') return this.params.wildcard = true;1766 1767 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {1768 modifier = match[1], clause = match[2], rest = match[3];1769 switch (modifier) {1770 case '#': params.id = clause; break;1771 case '.': params.classNames.push(clause); break;1772 case '':1773 case undefined: params.tagName = clause.toUpperCase();break;1774 default: abort(expr.inspect());2072 while (e && le != e && (/\S/).test(e)) { 2073 le = e; 2074 for (var i in ps) { 2075 p = ps[i]; 2076 if (m = e.match(p)) { 2077 this.matcher.push(typeof c[i] == 'function' ? c[i](m) : 2078 new Template(c[i]).evaluate(m)); 2079 e = e.replace(m[0], ''); 2080 break; 2081 } 1775 2082 } 1776 expr = rest;1777 2083 } 1778 2084 1779 if (expr.length > 0) abort(expr.inspect()); 2085 this.matcher.push("return h.unique(n);\n}"); 2086 eval(this.matcher.join('\n')); 2087 Selector._cache[this.expression] = this.matcher; 1780 2088 }, 1781 2089 1782 buildMatchExpression: function() { 1783 var params = this.params, conditions = [], clause; 2090 compileXPathMatcher: function() { 2091 var e = this.expression, ps = Selector.patterns, 2092 x = Selector.xpath, le, m; 1784 2093 1785 if (params.wildcard) 1786 conditions.push('true'); 1787 if (clause = params.id) 1788 conditions.push('element.readAttribute("id") == ' + clause.inspect()); 1789 if (clause = params.tagName) 1790 conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); 1791 if ((clause = params.classNames).length > 0) 1792 for (var i = 0, length = clause.length; i < length; i++) 1793 conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); 1794 if (clause = params.attributes) { 1795 clause.each(function(attribute) { 1796 var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; 1797 var splitValueBy = function(delimiter) { 1798 return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; 2094 if (Selector._cache[e]) { 2095 this.xpath = Selector._cache[e]; return; 2096 } 2097 2098 this.matcher = ['.//*']; 2099 while (e && le != e && (/\S/).test(e)) { 2100 le = e; 2101 for (var i in ps) { 2102 if (m = e.match(ps[i])) { 2103 this.matcher.push(typeof x[i] == 'function' ? x[i](m) : 2104 new Template(x[i]).evaluate(m)); 2105 e = e.replace(m[0], ''); 2106 break; 1799 2107 } 2108 } 2109 } 1800 2110 1801 switch (attribute.operator) { 1802 case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; 1803 case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; 1804 case '|=': conditions.push( 1805 splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() 1806 ); break; 1807 case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; 1808 case '': 1809 case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; 1810 default: throw 'Unknown operator ' + attribute.operator + ' in selector'; 2111 this.xpath = this.matcher.join(''); 2112 Selector._cache[this.expression] = this.xpath; 2113 }, 2114 2115 findElements: function(root) { 2116 root = root || document; 2117 if (this.xpath) return document._getElementsByXPath(this.xpath, root); 2118 return this.matcher(root); 2119 }, 2120 2121 match: function(element) { 2122 return this.findElements(document).include(element); 2123 }, 2124 2125 toString: function() { 2126 return this.expression; 2127 }, 2128 2129 inspect: function() { 2130 return "#<Selector:" + this.expression.inspect() + ">"; 2131 } 2132 }; 2133 2134 Object.extend(Selector, { 2135 _cache: {}, 2136 2137 xpath: { 2138 descendant: "//*", 2139 child: "/*", 2140 adjacent: "/following-sibling::*[1]", 2141 laterSibling: '/following-sibling::*', 2142 tagName: function(m) { 2143 if (m[1] == '*') return ''; 2144 return "[local-name()='" + m[1].toLowerCase() + 2145 "' or local-name()='" + m[1].toUpperCase() + "']"; 2146 }, 2147 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 2148 id: "[@id='#{1}']", 2149 attrPresence: "[@#{1}]", 2150 attr: function(m) { 2151 m[3] = m[5] || m[6]; 2152 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); 2153 }, 2154 pseudo: function(m) { 2155 var h = Selector.xpath.pseudos[m[1]]; 2156 if (!h) return ''; 2157 if (typeof h === 'function') return h(m); 2158 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); 2159 }, 2160 operators: { 2161 '=': "[@#{1}='#{3}']", 2162 '!=': "[@#{1}!='#{3}']", 2163 '^=': "[starts-with(@#{1}, '#{3}')]", 2164 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", 2165 '*=': "[contains(@#{1}, '#{3}')]", 2166 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", 2167 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" 2168 }, 2169 pseudos: { 2170 'first-child': '[not(preceding-sibling::*)]', 2171 'last-child': '[not(following-sibling::*)]', 2172 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 2173 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 2174 'checked': "[@checked]", 2175 'disabled': "[@disabled]", 2176 'enabled': "[not(@disabled)]", 2177 'not': function(m) { 2178 var e = m[6], p = Selector.patterns, 2179 x = Selector.xpath, le, m, v; 2180 2181 var exclusion = []; 2182 while (e && le != e && (/\S/).test(e)) { 2183 le = e; 2184 for (var i in p) { 2185 if (m = e.match(p[i])) { 2186 v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); 2187 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 2188 e = e.replace(m[0], ''); 2189 break; 2190 } 2191 } 1811 2192 } 1812 }); 2193 return "[not(" + exclusion.join(" and ") + ")]"; 2194 }, 2195 'nth-child': function(m) { 2196 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); 2197 }, 2198 'nth-last-child': function(m) { 2199 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); 2200 }, 2201 'nth-of-type': function(m) { 2202 return Selector.xpath.pseudos.nth("position() ", m); 2203 }, 2204 'nth-last-of-type': function(m) { 2205 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); 2206 }, 2207 'first-of-type': function(m) { 2208 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); 2209 }, 2210 'last-of-type': function(m) { 2211 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); 2212 }, 2213 'only-of-type': function(m) { 2214 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); 2215 }, 2216 nth: function(fragment, m) { 2217 var mm, formula = m[6], predicate; 2218 if (formula == 'even') formula = '2n+0'; 2219 if (formula == 'odd') formula = '2n+1'; 2220 if (mm = formula.match(/^(\d+)$/)) // digit only 2221 return '[' + fragment + "= " + mm[1] + ']'; 2222 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 2223 if (mm[1] == "-") mm[1] = -1; 2224 var a = mm[1] ? Number(mm[1]) : 1; 2225 var b = mm[2] ? Number(mm[2]) : 0; 2226 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + 2227 "((#{fragment} - #{b}) div #{a} >= 0)]"; 2228 return new Template(predicate).evaluate({ 2229 fragment: fragment, a: a, b: b }); 2230 } 2231 } 1813 2232 } 2233 }, 1814 2234 1815 return conditions.join(' && '); 2235 criteria: { 2236 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', 2237 className: 'n = h.className(n, r, "#{1}", c); c = false;', 2238 id: 'n = h.id(n, r, "#{1}", c); c = false;', 2239 attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', 2240 attr: function(m) { 2241 m[3] = (m[5] || m[6]); 2242 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); 2243 }, 2244 pseudo: function(m) { 2245 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 2246 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); 2247 }, 2248 descendant: 'c = "descendant";', 2249 child: 'c = "child";', 2250 adjacent: 'c = "adjacent";', 2251 laterSibling: 'c = "laterSibling";' 1816 2252 }, 1817 2253 1818 compileMatcher: function() { 1819 this.match = new Function('element', 'if (!element.tagName) return false; \ 1820 element = $(element); \ 1821 return ' + this.buildMatchExpression()); 2254 patterns: { 2255 // combinators must be listed first 2256 // (and descendant needs to be last combinator) 2257 laterSibling: /^\s*~\s*/, 2258 child: /^\s*>\s*/, 2259 adjacent: /^\s*\+\s*/, 2260 descendant: /^\s/, 2261 2262 // selectors follow 2263 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, 2264 id: /^#([\w\-\*]+)(\b|$)/, 2265 className: /^\.([\w\-\*]+)(\b|$)/, 2266 pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, 2267 attrPresence: /^\[([\w]+)\]/, 2268 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ 1822 2269 }, 1823 2270 1824 findElements: function(scope) { 1825 var element; 2271 handlers: { 2272 // UTILITY FUNCTIONS 2273 // joins two collections 2274 concat: function(a, b) { 2275 for (var i = 0, node; node = b[i]; i++) 2276 a.push(node); 2277 return a; 2278 }, 1826 2279 1827 if (element = $(this.params.id)) 1828 if (this.match(element)) 1829 if (!scope || Element.childOf(element, scope)) 1830 return [element]; 2280 // marks an array of nodes for counting 2281 mark: function(nodes) { 2282 for (var i = 0, node; node = nodes[i]; i++) 2283 node._counted = true; 2284 return nodes; 2285 }, 1831 2286 1832 scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); 2287 unmark: function(nodes) { 2288 for (var i = 0, node; node = nodes[i]; i++) 2289 node._counted = undefined; 2290 return nodes; 2291 }, 1833 2292 1834 var results = []; 1835 for (var i = 0, length = scope.length; i < length; i++) 1836 if (this.match(element = scope[i])) 1837 results.push(Element.extend(element)); 2293 // mark each child node with its position (for nth calls) 2294 // "ofType" flag indicates whether we're indexing for nth-of-type 2295 // rather than nth-child 2296 index: function(parentNode, reverse, ofType) { 2297 parentNode._counted = true; 2298 if (reverse) { 2299 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 2300 node = nodes[i]; 2301 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 2302 } 2303 } else { 2304 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 2305 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 2306 } 2307 }, 1838 2308 1839 return results; 2309 // filters out duplicates and extends all nodes 2310 unique: function(nodes) { 2311 if (nodes.length == 0) return nodes; 2312 var results = [], n; 2313 for (var i = 0, l = nodes.length; i < l; i++) 2314 if (!(n = nodes[i])._counted) { 2315 n._counted = true; 2316 results.push(Element.extend(n)); 2317 } 2318 return Selector.handlers.unmark(results); 2319 }, 2320 2321 // COMBINATOR FUNCTIONS 2322 descendant: function(nodes) { 2323 var h = Selector.handlers; 2324 for (var i = 0, results = [], node; node = nodes[i]; i++) 2325 h.concat(results, node.getElementsByTagName('*')); 2326 return results; 2327 }, 2328 2329 child: function(nodes) { 2330 var h = Selector.handlers; 2331 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2332 for (var j = 0, children = [], child; child = node.childNodes[j]; j++) 2333 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 2334 } 2335 return results; 2336 }, 2337 2338 adjacent: function(nodes) { 2339 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2340 var next = this.nextElementSibling(node); 2341 if (next) results.push(next); 2342 } 2343 return results; 2344 }, 2345 2346 laterSibling: function(nodes) { 2347 var h = Selector.handlers; 2348 for (var i = 0, results = [], node; node = nodes[i]; i++) 2349 h.concat(results, Element.nextSiblings(node)); 2350 return results; 2351 }, 2352 2353 nextElementSibling: function(node) { 2354 while (node = node.nextSibling) 2355 if (node.nodeType == 1) return node; 2356 return null; 2357 }, 2358 2359 previousElementSibling: function(node) { 2360 while (node = node.previousSibling) 2361 if (node.nodeType == 1) return node; 2362 return null; 2363 }, 2364 2365 // TOKEN FUNCTIONS 2366 tagName: function(nodes, root, tagName, combinator) { 2367 tagName = tagName.toUpperCase(); 2368 var results = [], h = Selector.handlers; 2369 if (nodes) { 2370 if (combinator) { 2371 // fastlane for ordinary descendant combinators 2372 if (combinator == "descendant") { 2373 for (var i = 0, node; node = nodes[i]; i++) 2374 h.concat(results, node.getElementsByTagName(tagName)); 2375 return results; 2376 } else nodes = this[combinator](nodes); 2377 if (tagName == "*") return nodes; 2378 } 2379 for (var i = 0, node; node = nodes[i]; i++) 2380 if (node.tagName.toUpperCase() == tagName) results.push(node); 2381 return results; 2382 } else return root.getElementsByTagName(tagName); 2383 }, 2384 2385 id: function(nodes, root, id, combinator) { 2386 var targetNode = $(id), h = Selector.handlers; 2387 if (!nodes && root == document) return targetNode ? [targetNode] : []; 2388 if (nodes) { 2389 if (combinator) { 2390 if (combinator == 'child') { 2391 for (var i = 0, node; node = nodes[i]; i++) 2392 if (targetNode.parentNode == node) return [targetNode]; 2393 } else if (combinator == 'descendant') { 2394 for (var i = 0, node; node = nodes[i]; i++) 2395 if (Element.descendantOf(targetNode, node)) return [targetNode]; 2396 } else if (combinator == 'adjacent') { 2397 for (var i = 0, node; node = nodes[i]; i++) 2398 if (Selector.handlers.previousElementSibling(targetNode) == node) 2399 return [targetNode]; 2400 } else nodes = h[combinator](nodes); 2401 } 2402 for (var i = 0, node; node = nodes[i]; i++) 2403 if (node == targetNode) return [targetNode]; 2404 return []; 2405 } 2406 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; 2407 }, 2408 2409 className: function(nodes, root, className, combinator) { 2410 if (nodes && combinator) nodes = this[combinator](nodes); 2411 return Selector.handlers.byClassName(nodes, root, className); 2412 }, 2413 2414 byClassName: function(nodes, root, className) { 2415 if (!nodes) nodes = Selector.handlers.descendant([root]); 2416 var needle = ' ' + className + ' '; 2417 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { 2418 nodeClassName = node.className; 2419 if (nodeClassName.length == 0) continue; 2420 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) 2421 results.push(node); 2422 } 2423 return results; 2424 }, 2425 2426 attrPresence: function(nodes, root, attr) { 2427 var results = []; 2428 for (var i = 0, node; node = nodes[i]; i++) 2429 if (Element.hasAttribute(node, attr)) results.push(node); 2430 return results; 2431 }, 2432 2433 attr: function(nodes, root, attr, value, operator) { 2434 if (!nodes) nodes = root.getElementsByTagName("*"); 2435 var handler = Selector.operators[operator], results = []; 2436 for (var i = 0, node; node = nodes[i]; i++) { 2437 var nodeValue = Element.readAttribute(node, attr); 2438 if (nodeValue === null) continue; 2439 if (handler(nodeValue, value)) results.push(node); 2440 } 2441 return results; 2442 }, 2443 2444 pseudo: function(nodes, name, value, root, combinator) { 2445 if (nodes && combinator) nodes = this[combinator](nodes); 2446 if (!nodes) nodes = root.getElementsByTagName("*"); 2447 return Selector.pseudos[name](nodes, value, root); 2448 } 1840 2449 }, 1841 2450 1842 toString: function() { 1843 return this.expression; 1844 } 1845 } 2451 pseudos: { 2452 'first-child': function(nodes, value, root) { 2453 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2454 if (Selector.handlers.previousElementSibling(node)) continue; 2455 results.push(node); 2456 } 2457 return results; 2458 }, 2459 'last-child': function(nodes, value, root) { 2460 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2461 if (Selector.handlers.nextElementSibling(node)) continue; 2462 results.push(node); 2463 } 2464 return results; 2465 }, 2466 'only-child': function(nodes, value, root) { 2467 var h = Selector.handlers; 2468 for (var i = 0, results = [], node; node = nodes[i]; i++) 2469 if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) 2470 results.push(node); 2471 return results; 2472 }, 2473 'nth-child': function(nodes, formula, root) { 2474 return Selector.pseudos.nth(nodes, formula, root); 2475 }, 2476 'nth-last-child': function(nodes, formula, root) { 2477 return Selector.pseudos.nth(nodes, formula, root, true); 2478 }, 2479 'nth-of-type': function(nodes, formula, root) { 2480 return Selector.pseudos.nth(nodes, formula, root, false, true); 2481 }, 2482 'nth-last-of-type': function(nodes, formula, root) { 2483 return Selector.pseudos.nth(nodes, formula, root, true, true); 2484 }, 2485 'first-of-type': function(nodes, formula, root) { 2486 return Selector.pseudos.nth(nodes, "1", root, false, true); 2487 }, 2488 'last-of-type': function(nodes, formula, root) { 2489 return Selector.pseudos.nth(nodes, "1", root, true, true); 2490 }, 2491 'only-of-type': function(nodes, formula, root) { 2492 var p = Selector.pseudos; 2493 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); 2494 }, 1846 2495 1847 Object.extend(Selector, { 2496 // handles the an+b logic 2497 getIndices: function(a, b, total) { 2498 if (a == 0) return b > 0 ? [b] : []; 2499 return $R(1, total).inject([], function(memo, i) { 2500 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); 2501 return memo; 2502 }); 2503 }, 2504 2505 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type 2506 nth: function(nodes, formula, root, reverse, ofType) { 2507 if (nodes.length == 0) return []; 2508 if (formula == 'even') formula = '2n+0'; 2509 if (formula == 'odd') formula = '2n+1'; 2510 var h = Selector.handlers, results = [], indexed = [], m; 2511 h.mark(nodes); 2512 for (var i = 0, node; node = nodes[i]; i++) { 2513 if (!node.parentNode._counted) { 2514 h.index(node.parentNode, reverse, ofType); 2515 indexed.push(node.parentNode); 2516 } 2517 } 2518 if (formula.match(/^\d+$/)) { // just a number 2519 formula = Number(formula); 2520 for (var i = 0, node; node = nodes[i]; i++) 2521 if (node.nodeIndex == formula) results.push(node); 2522 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 2523 if (m[1] == "-") m[1] = -1; 2524 var a = m[1] ? Number(m[1]) : 1; 2525 var b = m[2] ? Number(m[2]) : 0; 2526 var indices = Selector.pseudos.getIndices(a, b, nodes.length); 2527 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { 2528 for (var j = 0; j < l; j++) 2529 if (node.nodeIndex == indices[j]) results.push(node); 2530 } 2531 } 2532 h.unmark(nodes); 2533 h.unmark(indexed); 2534 return results; 2535 }, 2536 2537 'empty': function(nodes, value, root) { 2538 for (var i = 0, results = [], node; node = nodes[i]; i++) { 2539 // IE treats comments as element nodes 2540 if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; 2541 results.push(node); 2542 } 2543 return results; 2544 }, 2545 2546 'not': function(nodes, selector, root) { 2547 var h = Selector.handlers, selectorType, m; 2548 var exclusions = new Selector(selector).findElements(root); 2549 h.mark(exclusions); 2550 for (var i = 0, results = [], node; node = nodes[i]; i++) 2551 if (!node._counted) results.push(node); 2552 h.unmark(exclusions); 2553 return results; 2554 }, 2555 2556 'enabled': function(nodes, value, root) { 2557 for (var i = 0, results = [], node; node = nodes[i]; i++) 2558 if (!node.disabled) results.push(node); 2559 return results; 2560 }, 2561 2562 'disabled': function(nodes, value, root) { 2563 for (var i = 0, results = [], node; node = nodes[i]; i++) 2564 if (node.disabled) results.push(node); 2565 return results; 2566 }, 2567 2568 'checked': function(nodes, value, root) { 2569 for (var i = 0, results = [], node; node = nodes[i]; i++) 2570 if (node.checked) results.push(node); 2571 return results; 2572 } 2573 }, 2574 2575 operators: { 2576 '=': function(nv, v) { return nv == v; }, 2577 '!=': function(nv, v) { return nv != v; }, 2578 '^=': function(nv, v) { return nv.startsWith(v); }, 2579 '$=': function(nv, v) { return nv.endsWith(v); }, 2580 '*=': function(nv, v) { return nv.include(v); }, 2581 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 2582 '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } 2583 }, 2584 1848 2585 matchElements: function(elements, expression) { 1849 var selector = new Selector(expression); 1850 return elements.select(selector.match.bind(selector)).map(Element.extend); 2586 var matches = new Selector(expression).findElements(), h = Selector.handlers; 2587 h.mark(matches); 2588 for (var i = 0, results = [], element; element = elements[i]; i++) 2589 if (element._counted) results.push(element); 2590 h.unmark(matches); 2591 return results; 1851 2592 }, 1852 2593 1853 2594 findElement: function(elements, expression, index) { 1854 if (typeof expression == 'number') index = expression, expression = false; 2595 if (typeof expression == 'number') { 2596 index = expression; expression = false; 2597 } 1855 2598 return Selector.matchElements(elements, expression || '*')[index || 0]; 1856 2599 }, 1857 2600 1858 2601 findChildElements: function(element, expressions) { 1859 return expressions.map(function(expression) { 1860 return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { 1861 var selector = new Selector(expr); 1862 return results.inject([], function(elements, result) { 1863 return elements.concat(selector.findElements(result || element)); 1864 }); 1865 }); 1866 }).flatten(); 2602 var exprs = expressions.join(','), expressions = []; 2603 exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 2604 expressions.push(m[1].strip()); 2605 }); 2606 var results = [], h = Selector.handlers; 2607 for (var i = 0, l = expressions.length, selector; i < l; i++) { 2608 selector = new Selector(expressions[i].strip()); 2609 h.concat(results, selector.findElements(element)); 2610 } 2611 return (l > 1) ? h.unique(results) : results; 1867 2612 } 1868 2613 }); 1869 2614 … … 1880 2625 var data = elements.inject({}, function(result, element) { 1881 2626 if (!element.disabled && element.name) { 1882 2627 var key = element.name, value = $(element).getValue(); 1883 if (value != undefined) {1884 if (result[key]) {2628 if (value != null) { 2629 if (key in result) { 1885 2630 if (result[key].constructor != Array) result[key] = [result[key]]; 1886 2631 result[key].push(value); 1887 2632 } … … 1928 2673 1929 2674 disable: function(form) { 1930 2675 form = $(form); 1931 form.getElements().each(function(element) { 1932 element.blur(); 1933 element.disabled = 'true'; 1934 }); 2676 Form.getElements(form).invoke('disable'); 1935 2677 return form; 1936 2678 }, 1937 2679 1938 2680 enable: function(form) { 1939 2681 form = $(form); 1940 form.getElements().each(function(element) { 1941 element.disabled = ''; 1942 }); 2682 Form.getElements(form).invoke('enable'); 1943 2683 return form; 1944 2684 }, 1945 2685 … … 1954 2694 form = $(form); 1955 2695 form.findFirstElement().activate(); 1956 2696 return form; 2697 }, 2698 2699 request: function(form, options) { 2700 form = $(form), options = Object.clone(options || {}); 2701 2702 var params = options.parameters; 2703 options.parameters = form.serialize(true); 2704 2705 if (params) { 2706 if (typeof params == 'string') params = params.toQueryParams(); 2707 Object.extend(options.parameters, params); 2708 } 2709 2710 if (form.hasAttribute('method') && !options.method) 2711 options.method = form.method; 2712 2713 return new Ajax.Request(form.readAttribute('action'), options); 1957 2714 } 1958 2715 } 1959 2716 1960 Object.extend(Form, Form.Methods);1961 1962 2717 /*--------------------------------------------------------------------------*/ 1963 2718 1964 2719 Form.Element = { … … 2004 2759 2005 2760 activate: function(element) { 2006 2761 element = $(element); 2007 element.focus(); 2008 if (element.select && ( element.tagName.toLowerCase() != 'input' || 2009 !['button', 'reset', 'submit'].include(element.type) ) ) 2010 element.select(); 2762 try { 2763 element.focus(); 2764 if (element.select && (element.tagName.toLowerCase() != 'input' || 2765 !['button', 'reset', 'submit'].include(element.type))) 2766 element.select(); 2767 } catch (e) {} 2011 2768 return element; 2012 2769 }, 2013 2770 2014 2771 disable: function(element) { 2015 2772 element = $(element); 2773 element.blur(); 2016 2774 element.disabled = true; 2017 2775 return element; 2018 2776 }, 2019 2777 2020 2778 enable: function(element) { 2021 2779 element = $(element); 2022 element.blur();2023 2780 element.disabled = false; 2024 2781 return element; 2025 2782 } 2026 2783 } 2027 2784 2028 Object.extend(Form.Element, Form.Element.Methods); 2785 /*--------------------------------------------------------------------------*/ 2786 2029 2787 var Field = Form.Element; 2030 var $F = Form.Element. getValue;2788 var $F = Form.Element.Methods.getValue; 2031 2789 2032 2790 /*--------------------------------------------------------------------------*/ 2033 2791 … … 2194 2952 KEY_PAGEDOWN: 34, 2195 2953 2196 2954 element: function(event) { 2197 return event.target || event.srcElement;2955 return $(event.target || event.srcElement); 2198 2956 }, 2199 2957 2200 2958 isLeftClick: function(event) { … … 2259 3017 useCapture = useCapture || false; 2260 3018 2261 3019 if (name == 'keypress' && 2262 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 2263 || element.attachEvent)) 3020 (Prototype.Browser.WebKit || element.attachEvent)) 2264 3021 name = 'keydown'; 2265 3022 2266 3023 Event._observeAndCache(element, name, observer, useCapture); … … 2271 3028 useCapture = useCapture || false; 2272 3029 2273 3030 if (name == 'keypress' && 2274 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 2275 || element.detachEvent)) 3031 (Prototype.Browser.WebKit || element.attachEvent)) 2276 3032 name = 'keydown'; 2277 3033 2278 3034 if (element.removeEventListener) { … … 2286 3042 }); 2287 3043 2288 3044 /* prevent memory leaks in IE */ 2289 if ( navigator.appVersion.match(/\bMSIE\b/))3045 if (Prototype.Browser.IE) 2290 3046 Event.observe(window, 'unload', Event.unloadCache, false); 2291 3047 var Position = { 2292 3048 // set to true if needed, warning: firefox performance problems … … 2400 3156 valueL += element.offsetLeft || 0; 2401 3157 2402 3158 // Safari fix 2403 if (element.offsetParent ==document.body)3159 if (element.offsetParent == document.body) 2404 3160 if (Element.getStyle(element,'position')=='absolute') break; 2405 3161 2406 3162 } while (element = element.offsetParent); … … 2496 3252 // Safari returns margins on body which is incorrect if the child is absolutely 2497 3253 // positioned. For performance reasons, redefine Position.cumulativeOffset for 2498 3254 // KHTML/WebKit only. 2499 if ( /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {3255 if (Prototype.Browser.WebKit) { 2500 3256 Position.cumulativeOffset = function(element) { 2501 3257 var valueT = 0, valueL = 0; 2502 3258 do {