Changeset 12557
- Timestamp:
- 12/27/2009 10:30:58 PM (15 years ago)
- Location:
- trunk/wp-includes
- Files:
-
- 1 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-includes/js/prototype.js
r6512 r12557 1 /* Prototype JavaScript framework, version 1.6. 02 * (c) 2005-200 7Sam Stephenson1 /* Prototype JavaScript framework, version 1.6.1 2 * (c) 2005-2009 Sam Stephenson 3 3 * 4 4 * Prototype is freely distributable under the terms of an MIT-style license. … … 8 8 9 9 var Prototype = { 10 Version: '1.6.0', 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 MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) 18 }, 10 Version: '1.6.1', 11 12 Browser: (function(){ 13 var ua = navigator.userAgent; 14 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; 15 return { 16 IE: !!window.attachEvent && !isOpera, 17 Opera: isOpera, 18 WebKit: ua.indexOf('AppleWebKit/') > -1, 19 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, 20 MobileSafari: /Apple.*Mobile.*Safari/.test(ua) 21 } 22 })(), 19 23 20 24 BrowserFeatures: { 21 25 XPath: !!document.evaluate, 22 ElementExtensions: !!window.HTMLElement, 23 SpecificElementExtensions: 24 document.createElement('div').__proto__ && 25 document.createElement('div').__proto__ !== 26 document.createElement('form').__proto__ 26 SelectorsAPI: !!document.querySelector, 27 ElementExtensions: (function() { 28 var constructor = window.Element || window.HTMLElement; 29 return !!(constructor && constructor.prototype); 30 })(), 31 SpecificElementExtensions: (function() { 32 if (typeof window.HTMLDivElement !== 'undefined') 33 return true; 34 35 var div = document.createElement('div'); 36 var form = document.createElement('form'); 37 var isSupported = false; 38 39 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { 40 isSupported = true; 41 } 42 43 div = form = null; 44 45 return isSupported; 46 })() 27 47 }, 28 48 … … 37 57 Prototype.BrowserFeatures.SpecificElementExtensions = false; 38 58 39 if (Prototype.Browser.WebKit) 40 Prototype.BrowserFeatures.XPath = false; 59 60 var Abstract = { }; 61 62 63 var Try = { 64 these: function() { 65 var returnValue; 66 67 for (var i = 0, length = arguments.length; i < length; i++) { 68 var lambda = arguments[i]; 69 try { 70 returnValue = lambda(); 71 break; 72 } catch (e) { } 73 } 74 75 return returnValue; 76 } 77 }; 41 78 42 79 /* Based on Alex Arnell's inheritance implementation. */ 43 var Class = { 44 create: function() { 80 81 var Class = (function() { 82 function subclass() {}; 83 function create() { 45 84 var parent = null, properties = $A(arguments); 46 85 if (Object.isFunction(properties[0])) … … 56 95 57 96 if (parent) { 58 var subclass = function() { };59 97 subclass.prototype = parent.prototype; 60 98 klass.prototype = new subclass; … … 69 107 70 108 klass.prototype.constructor = klass; 71 72 109 return klass; 73 110 } 74 }; 75 76 Class.Methods = { 77 addMethods: function(source) { 111 112 function addMethods(source) { 78 113 var ancestor = this.superclass && this.superclass.prototype; 79 114 var properties = Object.keys(source); 80 115 81 if (!Object.keys({ toString: true }).length) 82 properties.push("toString", "valueOf"); 116 if (!Object.keys({ toString: true }).length) { 117 if (source.toString != Object.prototype.toString) 118 properties.push("toString"); 119 if (source.valueOf != Object.prototype.valueOf) 120 properties.push("valueOf"); 121 } 83 122 84 123 for (var i = 0, length = properties.length; i < length; i++) { … … 86 125 if (ancestor && Object.isFunction(value) && 87 126 value.argumentNames().first() == "$super") { 88 var method = value, value = Object.extend((function(m) { 89 return function() { return ancestor[m].apply(this, arguments) }; 90 })(property).wrap(method), { 91 valueOf: function() { return method }, 92 toString: function() { return method.toString() } 93 }); 127 var method = value; 128 value = (function(m) { 129 return function() { return ancestor[m].apply(this, arguments); }; 130 })(property).wrap(method); 131 132 value.valueOf = method.valueOf.bind(method); 133 value.toString = method.toString.bind(method); 94 134 } 95 135 this.prototype[property] = value; … … 98 138 return this; 99 139 } 100 }; 101 102 var Abstract = { }; 103 104 Object.extend = function(destination, source) { 105 for (var property in source) 106 destination[property] = source[property]; 107 return destination; 108 }; 109 110 Object.extend(Object, { 111 inspect: function(object) { 140 141 return { 142 create: create, 143 Methods: { 144 addMethods: addMethods 145 } 146 }; 147 })(); 148 (function() { 149 150 var _toString = Object.prototype.toString; 151 152 function extend(destination, source) { 153 for (var property in source) 154 destination[property] = source[property]; 155 return destination; 156 } 157 158 function inspect(object) { 112 159 try { 113 if ( object === undefined) return 'undefined';160 if (isUndefined(object)) return 'undefined'; 114 161 if (object === null) return 'null'; 115 return object.inspect ? object.inspect() : object.toString();162 return object.inspect ? object.inspect() : String(object); 116 163 } catch (e) { 117 164 if (e instanceof RangeError) return '...'; 118 165 throw e; 119 166 } 120 } ,121 122 toJSON: function(object) {167 } 168 169 function toJSON(object) { 123 170 var type = typeof object; 124 171 switch (type) { … … 131 178 if (object === null) return 'null'; 132 179 if (object.toJSON) return object.toJSON(); 133 if ( Object.isElement(object)) return;180 if (isElement(object)) return; 134 181 135 182 var results = []; 136 183 for (var property in object) { 137 var value = Object.toJSON(object[property]);138 if ( value !== undefined)184 var value = toJSON(object[property]); 185 if (!isUndefined(value)) 139 186 results.push(property.toJSON() + ': ' + value); 140 187 } 141 188 142 189 return '{' + results.join(', ') + '}'; 143 } ,144 145 toQueryString: function(object) {190 } 191 192 function toQueryString(object) { 146 193 return $H(object).toQueryString(); 147 } ,148 149 toHTML: function(object) {194 } 195 196 function toHTML(object) { 150 197 return object && object.toHTML ? object.toHTML() : String.interpret(object); 151 } ,152 153 keys: function(object) {154 var keys = [];198 } 199 200 function keys(object) { 201 var results = []; 155 202 for (var property in object) 156 keys.push(property);157 return keys;158 } ,159 160 values: function(object) {161 var values = [];203 results.push(property); 204 return results; 205 } 206 207 function values(object) { 208 var results = []; 162 209 for (var property in object) 163 values.push(object[property]); 164 return values; 165 }, 166 167 clone: function(object) { 168 return Object.extend({ }, object); 169 }, 170 171 isElement: function(object) { 172 return object && object.nodeType == 1; 173 }, 174 175 isArray: function(object) { 176 return object && object.constructor === Array; 177 }, 178 179 isHash: function(object) { 210 results.push(object[property]); 211 return results; 212 } 213 214 function clone(object) { 215 return extend({ }, object); 216 } 217 218 function isElement(object) { 219 return !!(object && object.nodeType == 1); 220 } 221 222 function isArray(object) { 223 return _toString.call(object) == "[object Array]"; 224 } 225 226 227 function isHash(object) { 180 228 return object instanceof Hash; 181 }, 182 183 isFunction: function(object) { 184 return typeof object == "function"; 185 }, 186 187 isString: function(object) { 188 return typeof object == "string"; 189 }, 190 191 isNumber: function(object) { 192 return typeof object == "number"; 193 }, 194 195 isUndefined: function(object) { 196 return typeof object == "undefined"; 197 } 198 }); 199 200 Object.extend(Function.prototype, { 201 argumentNames: function() { 202 var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); 229 } 230 231 function isFunction(object) { 232 return typeof object === "function"; 233 } 234 235 function isString(object) { 236 return _toString.call(object) == "[object String]"; 237 } 238 239 function isNumber(object) { 240 return _toString.call(object) == "[object Number]"; 241 } 242 243 function isUndefined(object) { 244 return typeof object === "undefined"; 245 } 246 247 extend(Object, { 248 extend: extend, 249 inspect: inspect, 250 toJSON: toJSON, 251 toQueryString: toQueryString, 252 toHTML: toHTML, 253 keys: keys, 254 values: values, 255 clone: clone, 256 isElement: isElement, 257 isArray: isArray, 258 isHash: isHash, 259 isFunction: isFunction, 260 isString: isString, 261 isNumber: isNumber, 262 isUndefined: isUndefined 263 }); 264 })(); 265 Object.extend(Function.prototype, (function() { 266 var slice = Array.prototype.slice; 267 268 function update(array, args) { 269 var arrayLength = array.length, length = args.length; 270 while (length--) array[arrayLength + length] = args[length]; 271 return array; 272 } 273 274 function merge(array, args) { 275 array = slice.call(array, 0); 276 return update(array, args); 277 } 278 279 function argumentNames() { 280 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] 281 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') 282 .replace(/\s+/g, '').split(','); 203 283 return names.length == 1 && !names[0] ? [] : names; 204 } ,205 206 bind: function() {207 if (arguments.length < 2 && arguments[0] === undefined) return this;208 var __method = this, args = $A(arguments), object = args.shift();284 } 285 286 function bind(context) { 287 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 288 var __method = this, args = slice.call(arguments, 1); 209 289 return function() { 210 return __method.apply(object, args.concat($A(arguments))); 211 } 212 }, 213 214 bindAsEventListener: function() { 215 var __method = this, args = $A(arguments), object = args.shift(); 290 var a = merge(args, arguments); 291 return __method.apply(context, a); 292 } 293 } 294 295 function bindAsEventListener(context) { 296 var __method = this, args = slice.call(arguments, 1); 216 297 return function(event) { 217 return __method.apply(object, [event || window.event].concat(args)); 218 } 219 }, 220 221 curry: function() { 298 var a = update([event || window.event], args); 299 return __method.apply(context, a); 300 } 301 } 302 303 function curry() { 222 304 if (!arguments.length) return this; 223 var __method = this, args = $A(arguments);305 var __method = this, args = slice.call(arguments, 0); 224 306 return function() { 225 return __method.apply(this, args.concat($A(arguments))); 226 } 227 }, 228 229 delay: function() { 230 var __method = this, args = $A(arguments), timeout = args.shift() * 1000; 307 var a = merge(args, arguments); 308 return __method.apply(this, a); 309 } 310 } 311 312 function delay(timeout) { 313 var __method = this, args = slice.call(arguments, 1); 314 timeout = timeout * 1000 231 315 return window.setTimeout(function() { 232 316 return __method.apply(__method, args); 233 317 }, timeout); 234 }, 235 236 wrap: function(wrapper) { 318 } 319 320 function defer() { 321 var args = update([0.01], arguments); 322 return this.delay.apply(this, args); 323 } 324 325 function wrap(wrapper) { 237 326 var __method = this; 238 327 return function() { 239 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 240 } 241 }, 242 243 methodize: function() { 328 var a = update([__method.bind(this)], arguments); 329 return wrapper.apply(this, a); 330 } 331 } 332 333 function methodize() { 244 334 if (this._methodized) return this._methodized; 245 335 var __method = this; 246 336 return this._methodized = function() { 247 return __method.apply(null, [this].concat($A(arguments))); 337 var a = update([this], arguments); 338 return __method.apply(null, a); 248 339 }; 249 340 } 250 }); 251 252 Function.prototype.defer = Function.prototype.delay.curry(0.01); 341 342 return { 343 argumentNames: argumentNames, 344 bind: bind, 345 bindAsEventListener: bindAsEventListener, 346 curry: curry, 347 delay: delay, 348 defer: defer, 349 wrap: wrap, 350 methodize: methodize 351 } 352 })()); 353 253 354 254 355 Date.prototype.toJSON = function() { … … 261 362 }; 262 363 263 var Try = {264 these: function() {265 var returnValue;266 267 for (var i = 0, length = arguments.length; i < length; i++) {268 var lambda = arguments[i];269 try {270 returnValue = lambda();271 break;272 } catch (e) { }273 }274 275 return returnValue;276 }277 };278 364 279 365 RegExp.prototype.match = RegExp.prototype.test; … … 282 368 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 283 369 }; 284 285 /*--------------------------------------------------------------------------*/286 287 370 var PeriodicalExecuter = Class.create({ 288 371 initialize: function(callback, frequency) { … … 313 396 this.currentlyExecuting = true; 314 397 this.execute(); 315 } finally {316 398 this.currentlyExecuting = false; 399 } catch(e) { 400 this.currentlyExecuting = false; 401 throw e; 317 402 } 318 403 } … … 333 418 }); 334 419 335 Object.extend(String.prototype, { 336 gsub: function(pattern, replacement) { 420 Object.extend(String.prototype, (function() { 421 422 function prepareReplacement(replacement) { 423 if (Object.isFunction(replacement)) return replacement; 424 var template = new Template(replacement); 425 return function(match) { return template.evaluate(match) }; 426 } 427 428 function gsub(pattern, replacement) { 337 429 var result = '', source = this, match; 338 replacement = arguments.callee.prepareReplacement(replacement); 430 replacement = prepareReplacement(replacement); 431 432 if (Object.isString(pattern)) 433 pattern = RegExp.escape(pattern); 434 435 if (!(pattern.length || pattern.source)) { 436 replacement = replacement(''); 437 return replacement + source.split('').join(replacement) + replacement; 438 } 339 439 340 440 while (source.length > 0) { … … 348 448 } 349 449 return result; 350 } ,351 352 sub: function(pattern, replacement, count) {353 replacement = this.gsub.prepareReplacement(replacement);354 count = count === undefined? 1 : count;450 } 451 452 function sub(pattern, replacement, count) { 453 replacement = prepareReplacement(replacement); 454 count = Object.isUndefined(count) ? 1 : count; 355 455 356 456 return this.gsub(pattern, function(match) { … … 358 458 return replacement(match); 359 459 }); 360 } ,361 362 scan: function(pattern, iterator) {460 } 461 462 function scan(pattern, iterator) { 363 463 this.gsub(pattern, iterator); 364 464 return String(this); 365 } ,366 367 truncate: function(length, truncation) {465 } 466 467 function truncate(length, truncation) { 368 468 length = length || 30; 369 truncation = truncation === undefined? '...' : truncation;469 truncation = Object.isUndefined(truncation) ? '...' : truncation; 370 470 return this.length > length ? 371 471 this.slice(0, length - truncation.length) + truncation : String(this); 372 } ,373 374 strip: function() {472 } 473 474 function strip() { 375 475 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 376 } ,377 378 stripTags: function() {379 return this.replace(/<\ /?[^>]+>/gi, '');380 } ,381 382 stripScripts: function() {476 } 477 478 function stripTags() { 479 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); 480 } 481 482 function stripScripts() { 383 483 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 384 } ,385 386 extractScripts: function() {484 } 485 486 function extractScripts() { 387 487 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 388 488 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); … … 390 490 return (scriptTag.match(matchOne) || ['', ''])[1]; 391 491 }); 392 } ,393 394 evalScripts: function() {492 } 493 494 function evalScripts() { 395 495 return this.extractScripts().map(function(script) { return eval(script) }); 396 }, 397 398 escapeHTML: function() { 399 var self = arguments.callee; 400 self.text.data = this; 401 return self.div.innerHTML; 402 }, 403 404 unescapeHTML: function() { 405 var div = new Element('div'); 406 div.innerHTML = this.stripTags(); 407 return div.childNodes[0] ? (div.childNodes.length > 1 ? 408 $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 409 div.childNodes[0].nodeValue) : ''; 410 }, 411 412 toQueryParams: function(separator) { 496 } 497 498 function escapeHTML() { 499 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 500 } 501 502 function unescapeHTML() { 503 return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); 504 } 505 506 507 function toQueryParams(separator) { 413 508 var match = this.strip().match(/([^?#]*)(#.*)?$/); 414 509 if (!match) return { }; … … 428 523 return hash; 429 524 }); 430 } ,431 432 toArray: function() {525 } 526 527 function toArray() { 433 528 return this.split(''); 434 } ,435 436 succ: function() {529 } 530 531 function succ() { 437 532 return this.slice(0, this.length - 1) + 438 533 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 439 } ,440 441 times: function(count) {534 } 535 536 function times(count) { 442 537 return count < 1 ? '' : new Array(count + 1).join(this); 443 } ,444 445 camelize: function() {538 } 539 540 function camelize() { 446 541 var parts = this.split('-'), len = parts.length; 447 542 if (len == 1) return parts[0]; … … 455 550 456 551 return camelized; 457 } ,458 459 capitalize: function() {552 } 553 554 function capitalize() { 460 555 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 461 }, 462 463 underscore: function() { 464 return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); 465 }, 466 467 dasherize: function() { 468 return this.gsub(/_/,'-'); 469 }, 470 471 inspect: function(useDoubleQuotes) { 472 var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { 473 var character = String.specialChar[match[0]]; 474 return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); 556 } 557 558 function underscore() { 559 return this.replace(/::/g, '/') 560 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 561 .replace(/([a-z\d])([A-Z])/g, '$1_$2') 562 .replace(/-/g, '_') 563 .toLowerCase(); 564 } 565 566 function dasherize() { 567 return this.replace(/_/g, '-'); 568 } 569 570 function inspect(useDoubleQuotes) { 571 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { 572 if (character in String.specialChar) { 573 return String.specialChar[character]; 574 } 575 return '\\u00' + character.charCodeAt().toPaddedString(2, 16); 475 576 }); 476 577 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 477 578 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 478 } ,479 480 toJSON: function() {579 } 580 581 function toJSON() { 481 582 return this.inspect(true); 482 }, 483 484 unfilterJSON: function(filter) { 485 return this.sub(filter || Prototype.JSONFilter, '#{1}'); 486 }, 487 488 isJSON: function() { 489 var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 583 } 584 585 function unfilterJSON(filter) { 586 return this.replace(filter || Prototype.JSONFilter, '$1'); 587 } 588 589 function isJSON() { 590 var str = this; 591 if (str.blank()) return false; 592 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 490 593 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 491 } ,492 493 evalJSON: function(sanitize) {594 } 595 596 function evalJSON(sanitize) { 494 597 var json = this.unfilterJSON(); 495 598 try { … … 497 600 } catch (e) { } 498 601 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 499 } ,500 501 include: function(pattern) {602 } 603 604 function include(pattern) { 502 605 return this.indexOf(pattern) > -1; 503 } ,504 505 startsWith: function(pattern) {606 } 607 608 function startsWith(pattern) { 506 609 return this.indexOf(pattern) === 0; 507 } ,508 509 endsWith: function(pattern) {610 } 611 612 function endsWith(pattern) { 510 613 var d = this.length - pattern.length; 511 614 return d >= 0 && this.lastIndexOf(pattern) === d; 512 } ,513 514 empty: function() {615 } 616 617 function empty() { 515 618 return this == ''; 516 } ,517 518 blank: function() {619 } 620 621 function blank() { 519 622 return /^\s*$/.test(this); 520 } ,521 522 interpolate: function(object, pattern) {623 } 624 625 function interpolate(object, pattern) { 523 626 return new Template(this, pattern).evaluate(object); 524 627 } 525 }); 526 527 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 528 escapeHTML: function() { 529 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 530 }, 531 unescapeHTML: function() { 532 return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); 533 } 534 }); 535 536 String.prototype.gsub.prepareReplacement = function(replacement) { 537 if (Object.isFunction(replacement)) return replacement; 538 var template = new Template(replacement); 539 return function(match) { return template.evaluate(match) }; 540 }; 541 542 String.prototype.parseQuery = String.prototype.toQueryParams; 543 544 Object.extend(String.prototype.escapeHTML, { 545 div: document.createElement('div'), 546 text: document.createTextNode('') 547 }); 548 549 with (String.prototype.escapeHTML) div.appendChild(text); 628 629 return { 630 gsub: gsub, 631 sub: sub, 632 scan: scan, 633 truncate: truncate, 634 strip: String.prototype.trim ? String.prototype.trim : strip, 635 stripTags: stripTags, 636 stripScripts: stripScripts, 637 extractScripts: extractScripts, 638 evalScripts: evalScripts, 639 escapeHTML: escapeHTML, 640 unescapeHTML: unescapeHTML, 641 toQueryParams: toQueryParams, 642 parseQuery: toQueryParams, 643 toArray: toArray, 644 succ: succ, 645 times: times, 646 camelize: camelize, 647 capitalize: capitalize, 648 underscore: underscore, 649 dasherize: dasherize, 650 inspect: inspect, 651 toJSON: toJSON, 652 unfilterJSON: unfilterJSON, 653 isJSON: isJSON, 654 evalJSON: evalJSON, 655 include: include, 656 startsWith: startsWith, 657 endsWith: endsWith, 658 empty: empty, 659 blank: blank, 660 interpolate: interpolate 661 }; 662 })()); 550 663 551 664 var Template = Class.create({ … … 556 669 557 670 evaluate: function(object) { 558 if ( Object.isFunction(object.toTemplateReplacements))671 if (object && Object.isFunction(object.toTemplateReplacements)) 559 672 object = object.toTemplateReplacements(); 560 673 561 674 return this.template.gsub(this.pattern, function(match) { 562 if (object == null) return '';675 if (object == null) return (match[1] + ''); 563 676 564 677 var before = match[1] || ''; … … 566 679 567 680 var ctx = object, expr = match[3]; 568 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); 681 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 682 match = pattern.exec(expr); 569 683 if (match == null) return before; 570 684 571 685 while (match != null) { 572 var comp = match[1].startsWith('[') ? match[2]. gsub('\\\\]', ']') : match[1];686 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; 573 687 ctx = ctx[comp]; 574 688 if (null == ctx || '' == match[3]) break; … … 578 692 579 693 return before + String.interpret(ctx); 580 } .bind(this));694 }); 581 695 } 582 696 }); … … 585 699 var $break = { }; 586 700 587 var Enumerable = {588 each: function(iterator, context) {701 var Enumerable = (function() { 702 function each(iterator, context) { 589 703 var index = 0; 590 iterator = iterator.bind(context);591 704 try { 592 705 this._each(function(value) { 593 iterator (value, index++);706 iterator.call(context, value, index++); 594 707 }); 595 708 } catch (e) { … … 597 710 } 598 711 return this; 599 }, 600 601 eachSlice: function(number, iterator, context) { 602 iterator = iterator ? iterator.bind(context) : Prototype.K; 712 } 713 714 function eachSlice(number, iterator, context) { 603 715 var index = -number, slices = [], array = this.toArray(); 716 if (number < 1) return array; 604 717 while ((index += number) < array.length) 605 718 slices.push(array.slice(index, index+number)); 606 719 return slices.collect(iterator, context); 607 } ,608 609 all: function(iterator, context) {610 iterator = iterator ? iterator.bind(context) :Prototype.K;720 } 721 722 function all(iterator, context) { 723 iterator = iterator || Prototype.K; 611 724 var result = true; 612 725 this.each(function(value, index) { 613 result = result && !!iterator (value, index);726 result = result && !!iterator.call(context, value, index); 614 727 if (!result) throw $break; 615 728 }); 616 729 return result; 617 } ,618 619 any: function(iterator, context) {620 iterator = iterator ? iterator.bind(context) :Prototype.K;730 } 731 732 function any(iterator, context) { 733 iterator = iterator || Prototype.K; 621 734 var result = false; 622 735 this.each(function(value, index) { 623 if (result = !!iterator (value, index))736 if (result = !!iterator.call(context, value, index)) 624 737 throw $break; 625 738 }); 626 739 return result; 627 } ,628 629 collect: function(iterator, context) {630 iterator = iterator ? iterator.bind(context) :Prototype.K;740 } 741 742 function collect(iterator, context) { 743 iterator = iterator || Prototype.K; 631 744 var results = []; 632 745 this.each(function(value, index) { 633 results.push(iterator (value, index));746 results.push(iterator.call(context, value, index)); 634 747 }); 635 748 return results; 636 }, 637 638 detect: function(iterator, context) { 639 iterator = iterator.bind(context); 749 } 750 751 function detect(iterator, context) { 640 752 var result; 641 753 this.each(function(value, index) { 642 if (iterator (value, index)) {754 if (iterator.call(context, value, index)) { 643 755 result = value; 644 756 throw $break; … … 646 758 }); 647 759 return result; 648 }, 649 650 findAll: function(iterator, context) { 651 iterator = iterator.bind(context); 760 } 761 762 function findAll(iterator, context) { 652 763 var results = []; 653 764 this.each(function(value, index) { 654 if (iterator (value, index))765 if (iterator.call(context, value, index)) 655 766 results.push(value); 656 767 }); 657 768 return results; 658 } ,659 660 grep: function(filter, iterator, context) {661 iterator = iterator ? iterator.bind(context) :Prototype.K;769 } 770 771 function grep(filter, iterator, context) { 772 iterator = iterator || Prototype.K; 662 773 var results = []; 663 774 664 775 if (Object.isString(filter)) 665 filter = new RegExp( filter);776 filter = new RegExp(RegExp.escape(filter)); 666 777 667 778 this.each(function(value, index) { 668 779 if (filter.match(value)) 669 results.push(iterator (value, index));780 results.push(iterator.call(context, value, index)); 670 781 }); 671 782 return results; 672 } ,673 674 include: function(object) {783 } 784 785 function include(object) { 675 786 if (Object.isFunction(this.indexOf)) 676 787 if (this.indexOf(object) != -1) return true; … … 684 795 }); 685 796 return found; 686 } ,687 688 inGroupsOf: function(number, fillWith) {689 fillWith = fillWith === undefined? null : fillWith;797 } 798 799 function inGroupsOf(number, fillWith) { 800 fillWith = Object.isUndefined(fillWith) ? null : fillWith; 690 801 return this.eachSlice(number, function(slice) { 691 802 while(slice.length < number) slice.push(fillWith); 692 803 return slice; 693 804 }); 694 }, 695 696 inject: function(memo, iterator, context) { 697 iterator = iterator.bind(context); 805 } 806 807 function inject(memo, iterator, context) { 698 808 this.each(function(value, index) { 699 memo = iterator (memo, value, index);809 memo = iterator.call(context, memo, value, index); 700 810 }); 701 811 return memo; 702 } ,703 704 invoke: function(method) {812 } 813 814 function invoke(method) { 705 815 var args = $A(arguments).slice(1); 706 816 return this.map(function(value) { 707 817 return value[method].apply(value, args); 708 818 }); 709 } ,710 711 max: function(iterator, context) {712 iterator = iterator ? iterator.bind(context) :Prototype.K;819 } 820 821 function max(iterator, context) { 822 iterator = iterator || Prototype.K; 713 823 var result; 714 824 this.each(function(value, index) { 715 value = iterator (value, index);716 if (result == undefined|| value >= result)825 value = iterator.call(context, value, index); 826 if (result == null || value >= result) 717 827 result = value; 718 828 }); 719 829 return result; 720 } ,721 722 min: function(iterator, context) {723 iterator = iterator ? iterator.bind(context) :Prototype.K;830 } 831 832 function min(iterator, context) { 833 iterator = iterator || Prototype.K; 724 834 var result; 725 835 this.each(function(value, index) { 726 value = iterator (value, index);727 if (result == undefined|| value < result)836 value = iterator.call(context, value, index); 837 if (result == null || value < result) 728 838 result = value; 729 839 }); 730 840 return result; 731 } ,732 733 partition: function(iterator, context) {734 iterator = iterator ? iterator.bind(context) :Prototype.K;841 } 842 843 function partition(iterator, context) { 844 iterator = iterator || Prototype.K; 735 845 var trues = [], falses = []; 736 846 this.each(function(value, index) { 737 (iterator (value, index) ?847 (iterator.call(context, value, index) ? 738 848 trues : falses).push(value); 739 849 }); 740 850 return [trues, falses]; 741 } ,742 743 pluck: function(property) {851 } 852 853 function pluck(property) { 744 854 var results = []; 745 855 this.each(function(value) { … … 747 857 }); 748 858 return results; 749 }, 750 751 reject: function(iterator, context) { 752 iterator = iterator.bind(context); 859 } 860 861 function reject(iterator, context) { 753 862 var results = []; 754 863 this.each(function(value, index) { 755 if (!iterator (value, index))864 if (!iterator.call(context, value, index)) 756 865 results.push(value); 757 866 }); 758 867 return results; 759 }, 760 761 sortBy: function(iterator, context) { 762 iterator = iterator.bind(context); 868 } 869 870 function sortBy(iterator, context) { 763 871 return this.map(function(value, index) { 764 return {value: value, criteria: iterator(value, index)}; 872 return { 873 value: value, 874 criteria: iterator.call(context, value, index) 875 }; 765 876 }).sort(function(left, right) { 766 877 var a = left.criteria, b = right.criteria; 767 878 return a < b ? -1 : a > b ? 1 : 0; 768 879 }).pluck('value'); 769 } ,770 771 toArray: function() {880 } 881 882 function toArray() { 772 883 return this.map(); 773 } ,774 775 zip: function() {884 } 885 886 function zip() { 776 887 var iterator = Prototype.K, args = $A(arguments); 777 888 if (Object.isFunction(args.last())) … … 782 893 return iterator(collections.pluck(index)); 783 894 }); 784 } ,785 786 size: function() {895 } 896 897 function size() { 787 898 return this.toArray().length; 788 } ,789 790 inspect: function() {899 } 900 901 function inspect() { 791 902 return '#<Enumerable:' + this.toArray().inspect() + '>'; 792 903 } 793 }; 794 795 Object.extend(Enumerable, { 796 map: Enumerable.collect, 797 find: Enumerable.detect, 798 select: Enumerable.findAll, 799 filter: Enumerable.findAll, 800 member: Enumerable.include, 801 entries: Enumerable.toArray, 802 every: Enumerable.all, 803 some: Enumerable.any 804 }); 904 905 906 907 908 909 910 911 912 913 return { 914 each: each, 915 eachSlice: eachSlice, 916 all: all, 917 every: all, 918 any: any, 919 some: any, 920 collect: collect, 921 map: collect, 922 detect: detect, 923 findAll: findAll, 924 select: findAll, 925 filter: findAll, 926 grep: grep, 927 include: include, 928 member: include, 929 inGroupsOf: inGroupsOf, 930 inject: inject, 931 invoke: invoke, 932 max: max, 933 min: min, 934 partition: partition, 935 pluck: pluck, 936 reject: reject, 937 sortBy: sortBy, 938 toArray: toArray, 939 entries: toArray, 940 zip: zip, 941 size: size, 942 inspect: inspect, 943 find: detect 944 }; 945 })(); 805 946 function $A(iterable) { 806 947 if (!iterable) return []; 807 if ( iterable.toArray) return iterable.toArray();808 var length = iterable.length , results = new Array(length);948 if ('toArray' in Object(iterable)) return iterable.toArray(); 949 var length = iterable.length || 0, results = new Array(length); 809 950 while (length--) results[length] = iterable[length]; 810 951 return results; 811 952 } 812 953 813 if (Prototype.Browser.WebKit) { 814 function $A(iterable) { 815 if (!iterable) return []; 816 if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && 817 iterable.toArray) return iterable.toArray(); 818 var length = iterable.length, results = new Array(length); 819 while (length--) results[length] = iterable[length]; 820 return results; 821 } 954 function $w(string) { 955 if (!Object.isString(string)) return []; 956 string = string.strip(); 957 return string ? string.split(/\s+/) : []; 822 958 } 823 959 824 960 Array.from = $A; 825 961 826 Object.extend(Array.prototype, Enumerable); 827 828 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 829 830 Object.extend(Array.prototype, { 831 _each: function(iterator) { 962 963 (function() { 964 var arrayProto = Array.prototype, 965 slice = arrayProto.slice, 966 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available 967 968 function each(iterator) { 832 969 for (var i = 0, length = this.length; i < length; i++) 833 970 iterator(this[i]); 834 }, 835 836 clear: function() { 971 } 972 if (!_each) _each = each; 973 974 function clear() { 837 975 this.length = 0; 838 976 return this; 839 } ,840 841 f irst: function() {977 } 978 979 function first() { 842 980 return this[0]; 843 } ,844 845 last: function() {981 } 982 983 function last() { 846 984 return this[this.length - 1]; 847 } ,848 849 compact: function() {985 } 986 987 function compact() { 850 988 return this.select(function(value) { 851 989 return value != null; 852 990 }); 853 } ,854 855 f latten: function() {991 } 992 993 function flatten() { 856 994 return this.inject([], function(array, value) { 857 return array.concat(Object.isArray(value) ? 858 value.flatten() : [value]); 995 if (Object.isArray(value)) 996 return array.concat(value.flatten()); 997 array.push(value); 998 return array; 859 999 }); 860 } ,861 862 without: function() {863 var values = $A(arguments);1000 } 1001 1002 function without() { 1003 var values = slice.call(arguments, 0); 864 1004 return this.select(function(value) { 865 1005 return !values.include(value); 866 1006 }); 867 } ,868 869 reverse: function(inline) {1007 } 1008 1009 function reverse(inline) { 870 1010 return (inline !== false ? this : this.toArray())._reverse(); 871 }, 872 873 reduce: function() { 874 return this.length > 1 ? this : this[0]; 875 }, 876 877 uniq: function(sorted) { 1011 } 1012 1013 function uniq(sorted) { 878 1014 return this.inject([], function(array, value, index) { 879 1015 if (0 == index || (sorted ? array.last() != value : !array.include(value))) … … 881 1017 return array; 882 1018 }); 883 } ,884 885 intersect: function(array) {1019 } 1020 1021 function intersect(array) { 886 1022 return this.uniq().findAll(function(item) { 887 1023 return array.detect(function(value) { return item === value }); 888 1024 }); 889 }, 890 891 clone: function() { 892 return [].concat(this); 893 }, 894 895 size: function() { 1025 } 1026 1027 1028 function clone() { 1029 return slice.call(this, 0); 1030 } 1031 1032 function size() { 896 1033 return this.length; 897 } ,898 899 inspect: function() {1034 } 1035 1036 function inspect() { 900 1037 return '[' + this.map(Object.inspect).join(', ') + ']'; 901 } ,902 903 toJSON: function() {1038 } 1039 1040 function toJSON() { 904 1041 var results = []; 905 1042 this.each(function(object) { 906 1043 var value = Object.toJSON(object); 907 if ( value !== undefined) results.push(value);1044 if (!Object.isUndefined(value)) results.push(value); 908 1045 }); 909 1046 return '[' + results.join(', ') + ']'; 910 1047 } 911 }); 912 913 // use native browser JS 1.6 implementation if available 914 if (Object.isFunction(Array.prototype.forEach)) 915 Array.prototype._each = Array.prototype.forEach; 916 917 if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { 918 i || (i = 0); 919 var length = this.length; 920 if (i < 0) i = length + i; 921 for (; i < length; i++) 922 if (this[i] === item) return i; 923 return -1; 924 }; 925 926 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { 927 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 928 var n = this.slice(0, i).reverse().indexOf(item); 929 return (n < 0) ? n : i - n - 1; 930 }; 931 932 Array.prototype.toArray = Array.prototype.clone; 933 934 function $w(string) { 935 if (!Object.isString(string)) return []; 936 string = string.strip(); 937 return string ? string.split(/\s+/) : []; 938 } 939 940 if (Prototype.Browser.Opera){ 941 Array.prototype.concat = function() { 942 var array = []; 943 for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 1048 1049 function indexOf(item, i) { 1050 i || (i = 0); 1051 var length = this.length; 1052 if (i < 0) i = length + i; 1053 for (; i < length; i++) 1054 if (this[i] === item) return i; 1055 return -1; 1056 } 1057 1058 function lastIndexOf(item, i) { 1059 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 1060 var n = this.slice(0, i).reverse().indexOf(item); 1061 return (n < 0) ? n : i - n - 1; 1062 } 1063 1064 function concat() { 1065 var array = slice.call(this, 0), item; 944 1066 for (var i = 0, length = arguments.length; i < length; i++) { 945 if (Object.isArray(arguments[i])) { 946 for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 947 array.push(arguments[i][j]); 1067 item = arguments[i]; 1068 if (Object.isArray(item) && !('callee' in item)) { 1069 for (var j = 0, arrayLength = item.length; j < arrayLength; j++) 1070 array.push(item[j]); 948 1071 } else { 949 array.push( arguments[i]);1072 array.push(item); 950 1073 } 951 1074 } 952 1075 return array; 953 }; 954 } 955 Object.extend(Number.prototype, { 956 toColorPart: function() { 957 return this.toPaddedString(2, 16); 958 }, 959 960 succ: function() { 961 return this + 1; 962 }, 963 964 times: function(iterator) { 965 $R(0, this, true).each(iterator); 966 return this; 967 }, 968 969 toPaddedString: function(length, radix) { 970 var string = this.toString(radix || 10); 971 return '0'.times(length - string.length) + string; 972 }, 973 974 toJSON: function() { 975 return isFinite(this) ? this.toString() : 'null'; 976 } 977 }); 978 979 $w('abs round ceil floor').each(function(method){ 980 Number.prototype[method] = Math[method].methodize(); 981 }); 1076 } 1077 1078 Object.extend(arrayProto, Enumerable); 1079 1080 if (!arrayProto._reverse) 1081 arrayProto._reverse = arrayProto.reverse; 1082 1083 Object.extend(arrayProto, { 1084 _each: _each, 1085 clear: clear, 1086 first: first, 1087 last: last, 1088 compact: compact, 1089 flatten: flatten, 1090 without: without, 1091 reverse: reverse, 1092 uniq: uniq, 1093 intersect: intersect, 1094 clone: clone, 1095 toArray: clone, 1096 size: size, 1097 inspect: inspect, 1098 toJSON: toJSON 1099 }); 1100 1101 var CONCAT_ARGUMENTS_BUGGY = (function() { 1102 return [].concat(arguments)[0][0] !== 1; 1103 })(1,2) 1104 1105 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; 1106 1107 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; 1108 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; 1109 })(); 982 1110 function $H(object) { 983 1111 return new Hash(object); … … 985 1113 986 1114 var Hash = Class.create(Enumerable, (function() { 987 if (function() { 988 var i = 0, Test = function(value) { this.key = value }; 989 Test.prototype.key = 'foo'; 990 for (var property in new Test('bar')) i++; 991 return i > 1; 992 }()) { 993 function each(iterator) { 994 var cache = []; 995 for (var key in this._object) { 996 var value = this._object[key]; 997 if (cache.include(key)) continue; 998 cache.push(key); 999 var pair = [key, value]; 1000 pair.key = key; 1001 pair.value = value; 1002 iterator(pair); 1003 } 1004 } 1005 } else { 1006 function each(iterator) { 1007 for (var key in this._object) { 1008 var value = this._object[key], pair = [key, value]; 1009 pair.key = key; 1010 pair.value = value; 1011 iterator(pair); 1012 } 1013 } 1115 function initialize(object) { 1116 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 1117 } 1118 1119 function _each(iterator) { 1120 for (var key in this._object) { 1121 var value = this._object[key], pair = [key, value]; 1122 pair.key = key; 1123 pair.value = value; 1124 iterator(pair); 1125 } 1126 } 1127 1128 function set(key, value) { 1129 return this._object[key] = value; 1130 } 1131 1132 function get(key) { 1133 if (this._object[key] !== Object.prototype[key]) 1134 return this._object[key]; 1135 } 1136 1137 function unset(key) { 1138 var value = this._object[key]; 1139 delete this._object[key]; 1140 return value; 1141 } 1142 1143 function toObject() { 1144 return Object.clone(this._object); 1145 } 1146 1147 function keys() { 1148 return this.pluck('key'); 1149 } 1150 1151 function values() { 1152 return this.pluck('value'); 1153 } 1154 1155 function index(value) { 1156 var match = this.detect(function(pair) { 1157 return pair.value === value; 1158 }); 1159 return match && match.key; 1160 } 1161 1162 function merge(object) { 1163 return this.clone().update(object); 1164 } 1165 1166 function update(object) { 1167 return new Hash(object).inject(this, function(result, pair) { 1168 result.set(pair.key, pair.value); 1169 return result; 1170 }); 1014 1171 } 1015 1172 … … 1019 1176 } 1020 1177 1178 function toQueryString() { 1179 return this.inject([], function(results, pair) { 1180 var key = encodeURIComponent(pair.key), values = pair.value; 1181 1182 if (values && typeof values == 'object') { 1183 if (Object.isArray(values)) 1184 return results.concat(values.map(toQueryPair.curry(key))); 1185 } else results.push(toQueryPair(key, values)); 1186 return results; 1187 }).join('&'); 1188 } 1189 1190 function inspect() { 1191 return '#<Hash:{' + this.map(function(pair) { 1192 return pair.map(Object.inspect).join(': '); 1193 }).join(', ') + '}>'; 1194 } 1195 1196 function toJSON() { 1197 return Object.toJSON(this.toObject()); 1198 } 1199 1200 function clone() { 1201 return new Hash(this); 1202 } 1203 1021 1204 return { 1022 initialize: function(object) { 1023 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 1024 }, 1025 1026 _each: each, 1027 1028 set: function(key, value) { 1029 return this._object[key] = value; 1030 }, 1031 1032 get: function(key) { 1033 return this._object[key]; 1034 }, 1035 1036 unset: function(key) { 1037 var value = this._object[key]; 1038 delete this._object[key]; 1039 return value; 1040 }, 1041 1042 toObject: function() { 1043 return Object.clone(this._object); 1044 }, 1045 1046 keys: function() { 1047 return this.pluck('key'); 1048 }, 1049 1050 values: function() { 1051 return this.pluck('value'); 1052 }, 1053 1054 index: function(value) { 1055 var match = this.detect(function(pair) { 1056 return pair.value === value; 1057 }); 1058 return match && match.key; 1059 }, 1060 1061 merge: function(object) { 1062 return this.clone().update(object); 1063 }, 1064 1065 update: function(object) { 1066 return new Hash(object).inject(this, function(result, pair) { 1067 result.set(pair.key, pair.value); 1068 return result; 1069 }); 1070 }, 1071 1072 toQueryString: function() { 1073 return this.map(function(pair) { 1074 var key = encodeURIComponent(pair.key), values = pair.value; 1075 1076 if (values && typeof values == 'object') { 1077 if (Object.isArray(values)) 1078 return values.map(toQueryPair.curry(key)).join('&'); 1079 } 1080 return toQueryPair(key, values); 1081 }).join('&'); 1082 }, 1083 1084 inspect: function() { 1085 return '#<Hash:{' + this.map(function(pair) { 1086 return pair.map(Object.inspect).join(': '); 1087 }).join(', ') + '}>'; 1088 }, 1089 1090 toJSON: function() { 1091 return Object.toJSON(this.toObject()); 1092 }, 1093 1094 clone: function() { 1095 return new Hash(this); 1096 } 1097 } 1205 initialize: initialize, 1206 _each: _each, 1207 set: set, 1208 get: get, 1209 unset: unset, 1210 toObject: toObject, 1211 toTemplateReplacements: toObject, 1212 keys: keys, 1213 values: values, 1214 index: index, 1215 merge: merge, 1216 update: update, 1217 toQueryString: toQueryString, 1218 inspect: inspect, 1219 toJSON: toJSON, 1220 clone: clone 1221 }; 1098 1222 })()); 1099 1223 1100 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;1101 1224 Hash.from = $H; 1102 var ObjectRange = Class.create(Enumerable, { 1103 initialize: function(start, end, exclusive) { 1225 Object.extend(Number.prototype, (function() { 1226 function toColorPart() { 1227 return this.toPaddedString(2, 16); 1228 } 1229 1230 function succ() { 1231 return this + 1; 1232 } 1233 1234 function times(iterator, context) { 1235 $R(0, this, true).each(iterator, context); 1236 return this; 1237 } 1238 1239 function toPaddedString(length, radix) { 1240 var string = this.toString(radix || 10); 1241 return '0'.times(length - string.length) + string; 1242 } 1243 1244 function toJSON() { 1245 return isFinite(this) ? this.toString() : 'null'; 1246 } 1247 1248 function abs() { 1249 return Math.abs(this); 1250 } 1251 1252 function round() { 1253 return Math.round(this); 1254 } 1255 1256 function ceil() { 1257 return Math.ceil(this); 1258 } 1259 1260 function floor() { 1261 return Math.floor(this); 1262 } 1263 1264 return { 1265 toColorPart: toColorPart, 1266 succ: succ, 1267 times: times, 1268 toPaddedString: toPaddedString, 1269 toJSON: toJSON, 1270 abs: abs, 1271 round: round, 1272 ceil: ceil, 1273 floor: floor 1274 }; 1275 })()); 1276 1277 function $R(start, end, exclusive) { 1278 return new ObjectRange(start, end, exclusive); 1279 } 1280 1281 var ObjectRange = Class.create(Enumerable, (function() { 1282 function initialize(start, end, exclusive) { 1104 1283 this.start = start; 1105 1284 this.end = end; 1106 1285 this.exclusive = exclusive; 1107 } ,1108 1109 _each: function(iterator) {1286 } 1287 1288 function _each(iterator) { 1110 1289 var value = this.start; 1111 1290 while (this.include(value)) { … … 1113 1292 value = value.succ(); 1114 1293 } 1115 } ,1116 1117 include: function(value) {1294 } 1295 1296 function include(value) { 1118 1297 if (value < this.start) 1119 1298 return false; … … 1122 1301 return value <= this.end; 1123 1302 } 1124 }); 1125 1126 var $R = function(start, end, exclusive) { 1127 return new ObjectRange(start, end, exclusive); 1128 }; 1303 1304 return { 1305 initialize: initialize, 1306 _each: _each, 1307 include: include 1308 }; 1309 })()); 1310 1311 1129 1312 1130 1313 var Ajax = { … … 1173 1356 onComplete: function() { Ajax.activeRequestCount-- } 1174 1357 }); 1175 1176 1358 Ajax.Base = Class.create({ 1177 1359 initialize: function(options) { … … 1188 1370 1189 1371 this.options.method = this.options.method.toLowerCase(); 1372 1190 1373 if (Object.isString(this.options.parameters)) 1191 1374 this.options.parameters = this.options.parameters.toQueryParams(); 1375 else if (Object.isHash(this.options.parameters)) 1376 this.options.parameters = this.options.parameters.toObject(); 1192 1377 } 1193 1378 }); 1194 1195 1379 Ajax.Request = Class.create(Ajax.Base, { 1196 1380 _complete: false, … … 1208 1392 1209 1393 if (!['get', 'post'].include(this.method)) { 1210 // simulate other verbs over post1211 1394 params['_method'] = this.method; 1212 1395 this.method = 'post'; … … 1216 1399 1217 1400 if (params = Object.toQueryString(params)) { 1218 // when GET, append parameters to URL1219 1401 if (this.method == 'get') 1220 1402 this.url += (this.url.include('?') ? '&' : '?') + params; … … 1275 1457 } 1276 1458 1277 // user-defined headers1278 1459 if (typeof this.options.requestHeaders == 'object') { 1279 1460 var extras = this.options.requestHeaders; … … 1316 1497 var contentType = response.getHeader('Content-type'); 1317 1498 if (this.options.evalJS == 'force' 1318 || (this.options.evalJS && contentType1499 || (this.options.evalJS && this.isSameOrigin() && contentType 1319 1500 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1320 1501 this.evalResponse(); … … 1329 1510 1330 1511 if (state == 'Complete') { 1331 // avoid memory leak in MSIE: clean up1332 1512 this.transport.onreadystatechange = Prototype.emptyFunction; 1333 1513 } 1514 }, 1515 1516 isSameOrigin: function() { 1517 var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 1518 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 1519 protocol: location.protocol, 1520 domain: document.domain, 1521 port: location.port ? ':' + location.port : '' 1522 })); 1334 1523 }, 1335 1524 1336 1525 getHeader: function(name) { 1337 1526 try { 1338 return this.transport.getResponseHeader(name) ;1339 } catch (e) { return null }1527 return this.transport.getResponseHeader(name) || null; 1528 } catch (e) { return null; } 1340 1529 }, 1341 1530 … … 1357 1546 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1358 1547 1548 1549 1550 1551 1552 1553 1554 1359 1555 Ajax.Response = Class.create({ 1360 1556 initialize: function(request){ … … 1372 1568 if(readyState == 4) { 1373 1569 var xml = transport.responseXML; 1374 this.responseXML = xml === undefined? null : xml;1570 this.responseXML = Object.isUndefined(xml) ? null : xml; 1375 1571 this.responseJSON = this._getResponseJSON(); 1376 1572 } … … 1378 1574 1379 1575 status: 0, 1576 1380 1577 statusText: '', 1381 1578 … … 1409 1606 json = decodeURIComponent(escape(json)); 1410 1607 try { 1411 return json.evalJSON(this.request.options.sanitizeJSON); 1608 return json.evalJSON(this.request.options.sanitizeJSON || 1609 !this.request.isSameOrigin()); 1412 1610 } catch (e) { 1413 1611 this.request.dispatchException(e); … … 1418 1616 var options = this.request.options; 1419 1617 if (!options.evalJSON || (options.evalJSON != 'force' && 1420 !(this.getHeader('Content-type') || '').include('application/json'))) 1421 return null; 1618 !(this.getHeader('Content-type') || '').include('application/json')) || 1619 this.responseText.blank()) 1620 return null; 1422 1621 try { 1423 return this.transport.responseText.evalJSON(options.sanitizeJSON); 1622 return this.responseText.evalJSON(options.sanitizeJSON || 1623 !this.request.isSameOrigin()); 1424 1624 } catch (e) { 1425 1625 this.request.dispatchException(e); … … 1435 1635 }; 1436 1636 1437 options = options || { };1637 options = Object.clone(options); 1438 1638 var onComplete = options.onComplete; 1439 options.onComplete = (function(response, param) {1639 options.onComplete = (function(response, json) { 1440 1640 this.updateContent(response.responseText); 1441 if (Object.isFunction(onComplete)) onComplete(response, param);1641 if (Object.isFunction(onComplete)) onComplete(response, json); 1442 1642 }).bind(this); 1443 1643 … … 1461 1661 else receiver.update(responseText); 1462 1662 } 1463 1464 if (this.success()) {1465 if (this.onComplete) this.onComplete.bind(this).defer();1466 }1467 1663 } 1468 1664 }); … … 1508 1704 } 1509 1705 }); 1706 1707 1708 1510 1709 function $(element) { 1511 1710 if (arguments.length > 1) { … … 1535 1734 1536 1735 if (!Node.ELEMENT_NODE) { 1537 // DOM level 2 ECMAScript Language Binding1538 1736 Object.extend(Node, { 1539 1737 ELEMENT_NODE: 1, … … 1552 1750 } 1553 1751 1554 (function() { 1555 var element = this.Element; 1556 this.Element = function(tagName, attributes) { 1752 1753 (function(global) { 1754 1755 var SETATTRIBUTE_IGNORES_NAME = (function(){ 1756 var elForm = document.createElement("form"); 1757 var elInput = document.createElement("input"); 1758 var root = document.documentElement; 1759 elInput.setAttribute("name", "test"); 1760 elForm.appendChild(elInput); 1761 root.appendChild(elForm); 1762 var isBuggy = elForm.elements 1763 ? (typeof elForm.elements.test == "undefined") 1764 : null; 1765 root.removeChild(elForm); 1766 elForm = elInput = null; 1767 return isBuggy; 1768 })(); 1769 1770 var element = global.Element; 1771 global.Element = function(tagName, attributes) { 1557 1772 attributes = attributes || { }; 1558 1773 tagName = tagName.toLowerCase(); 1559 1774 var cache = Element.cache; 1560 if ( Prototype.Browser.IE && attributes.name) {1775 if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { 1561 1776 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 1562 1777 delete attributes.name; … … 1566 1781 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 1567 1782 }; 1568 Object.extend(this.Element, element || { }); 1569 }).call(window); 1783 Object.extend(global.Element, element || { }); 1784 if (element) global.Element.prototype = element.prototype; 1785 })(this); 1570 1786 1571 1787 Element.cache = { }; 1788 Element.idCounter = 1; 1572 1789 1573 1790 Element.Methods = { … … 1582 1799 }, 1583 1800 1801 1584 1802 hide: function(element) { 1585 $(element).style.display = 'none'; 1803 element = $(element); 1804 element.style.display = 'none'; 1586 1805 return element; 1587 1806 }, 1588 1807 1589 1808 show: function(element) { 1590 $(element).style.display = ''; 1809 element = $(element); 1810 element.style.display = ''; 1591 1811 return element; 1592 1812 }, … … 1598 1818 }, 1599 1819 1600 update: function(element, content) { 1601 element = $(element); 1602 if (content && content.toElement) content = content.toElement(); 1603 if (Object.isElement(content)) return element.update().insert(content); 1604 content = Object.toHTML(content); 1605 element.innerHTML = content.stripScripts(); 1606 content.evalScripts.bind(content).defer(); 1607 return element; 1608 }, 1820 update: (function(){ 1821 1822 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ 1823 var el = document.createElement("select"), 1824 isBuggy = true; 1825 el.innerHTML = "<option value=\"test\">test</option>"; 1826 if (el.options && el.options[0]) { 1827 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; 1828 } 1829 el = null; 1830 return isBuggy; 1831 })(); 1832 1833 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ 1834 try { 1835 var el = document.createElement("table"); 1836 if (el && el.tBodies) { 1837 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; 1838 var isBuggy = typeof el.tBodies[0] == "undefined"; 1839 el = null; 1840 return isBuggy; 1841 } 1842 } catch (e) { 1843 return true; 1844 } 1845 })(); 1846 1847 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { 1848 var s = document.createElement("script"), 1849 isBuggy = false; 1850 try { 1851 s.appendChild(document.createTextNode("")); 1852 isBuggy = !s.firstChild || 1853 s.firstChild && s.firstChild.nodeType !== 3; 1854 } catch (e) { 1855 isBuggy = true; 1856 } 1857 s = null; 1858 return isBuggy; 1859 })(); 1860 1861 function update(element, content) { 1862 element = $(element); 1863 1864 if (content && content.toElement) 1865 content = content.toElement(); 1866 1867 if (Object.isElement(content)) 1868 return element.update().insert(content); 1869 1870 content = Object.toHTML(content); 1871 1872 var tagName = element.tagName.toUpperCase(); 1873 1874 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { 1875 element.text = content; 1876 return element; 1877 } 1878 1879 if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { 1880 if (tagName in Element._insertionTranslations.tags) { 1881 while (element.firstChild) { 1882 element.removeChild(element.firstChild); 1883 } 1884 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 1885 .each(function(node) { 1886 element.appendChild(node) 1887 }); 1888 } 1889 else { 1890 element.innerHTML = content.stripScripts(); 1891 } 1892 } 1893 else { 1894 element.innerHTML = content.stripScripts(); 1895 } 1896 1897 content.evalScripts.bind(content).defer(); 1898 return element; 1899 } 1900 1901 return update; 1902 })(), 1609 1903 1610 1904 replace: function(element, content) { … … 1629 1923 insertions = {bottom:insertions}; 1630 1924 1631 var content, t, range;1632 1633 for ( position in insertions) {1925 var content, insert, tagName, childNodes; 1926 1927 for (var position in insertions) { 1634 1928 content = insertions[position]; 1635 1929 position = position.toLowerCase(); 1636 t = Element._insertionTranslations[position];1930 insert = Element._insertionTranslations[position]; 1637 1931 1638 1932 if (content && content.toElement) content = content.toElement(); 1639 1933 if (Object.isElement(content)) { 1640 t.insert(element, content);1934 insert(element, content); 1641 1935 continue; 1642 1936 } … … 1644 1938 content = Object.toHTML(content); 1645 1939 1646 range = element.ownerDocument.createRange(); 1647 t.initializeRange(element, range); 1648 t.insert(element, range.createContextualFragment(content.stripScripts())); 1940 tagName = ((position == 'before' || position == 'after') 1941 ? element.parentNode : element).tagName.toUpperCase(); 1942 1943 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 1944 1945 if (position == 'top' || position == 'after') childNodes.reverse(); 1946 childNodes.each(insert.curry(element)); 1649 1947 1650 1948 content.evalScripts.bind(content).defer(); … … 1687 1985 1688 1986 ancestors: function(element) { 1689 return $(element).recursivelyCollect('parentNode');1987 return Element.recursivelyCollect(element, 'parentNode'); 1690 1988 }, 1691 1989 1692 1990 descendants: function(element) { 1693 return $A($(element).getElementsByTagName('*')).each(Element.extend);1991 return Element.select(element, "*"); 1694 1992 }, 1695 1993 … … 1708 2006 1709 2007 previousSiblings: function(element) { 1710 return $(element).recursivelyCollect('previousSibling');2008 return Element.recursivelyCollect(element, 'previousSibling'); 1711 2009 }, 1712 2010 1713 2011 nextSiblings: function(element) { 1714 return $(element).recursivelyCollect('nextSibling');2012 return Element.recursivelyCollect(element, 'nextSibling'); 1715 2013 }, 1716 2014 1717 2015 siblings: function(element) { 1718 2016 element = $(element); 1719 return element.previousSiblings().reverse().concat(element.nextSiblings()); 2017 return Element.previousSiblings(element).reverse() 2018 .concat(Element.nextSiblings(element)); 1720 2019 }, 1721 2020 … … 1729 2028 element = $(element); 1730 2029 if (arguments.length == 1) return $(element.parentNode); 1731 var ancestors = element.ancestors();1732 return expression ? Selector.findElement(ancestors, expression, index):1733 ancestors[index || 0];2030 var ancestors = Element.ancestors(element); 2031 return Object.isNumber(expression) ? ancestors[expression] : 2032 Selector.findElement(ancestors, expression, index); 1734 2033 }, 1735 2034 1736 2035 down: function(element, expression, index) { 1737 2036 element = $(element); 1738 if (arguments.length == 1) return element.firstDescendant(); 1739 var descendants = element.descendants(); 1740 return expression ? Selector.findElement(descendants, expression, index) : 1741 descendants[index || 0]; 2037 if (arguments.length == 1) return Element.firstDescendant(element); 2038 return Object.isNumber(expression) ? Element.descendants(element)[expression] : 2039 Element.select(element, expression)[index || 0]; 1742 2040 }, 1743 2041 … … 1745 2043 element = $(element); 1746 2044 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 1747 var previousSiblings = element.previousSiblings();1748 return expression ? Selector.findElement(previousSiblings, expression, index):1749 previousSiblings[index || 0];2045 var previousSiblings = Element.previousSiblings(element); 2046 return Object.isNumber(expression) ? previousSiblings[expression] : 2047 Selector.findElement(previousSiblings, expression, index); 1750 2048 }, 1751 2049 … … 1753 2051 element = $(element); 1754 2052 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); 1755 var nextSiblings = element.nextSiblings(); 1756 return expression ? Selector.findElement(nextSiblings, expression, index) : 1757 nextSiblings[index || 0]; 1758 }, 1759 1760 select: function() { 1761 var args = $A(arguments), element = $(args.shift()); 2053 var nextSiblings = Element.nextSiblings(element); 2054 return Object.isNumber(expression) ? nextSiblings[expression] : 2055 Selector.findElement(nextSiblings, expression, index); 2056 }, 2057 2058 2059 select: function(element) { 2060 var args = Array.prototype.slice.call(arguments, 1); 1762 2061 return Selector.findChildElements(element, args); 1763 2062 }, 1764 2063 1765 adjacent: function( ) {1766 var args = $A(arguments), element = $(args.shift());2064 adjacent: function(element) { 2065 var args = Array.prototype.slice.call(arguments, 1); 1767 2066 return Selector.findChildElements(element.parentNode, args).without(element); 1768 2067 }, … … 1770 2069 identify: function(element) { 1771 2070 element = $(element); 1772 var id = element.readAttribute('id'), self = arguments.callee;2071 var id = Element.readAttribute(element, 'id'); 1773 2072 if (id) return id; 1774 do { id = 'anonymous_element_' + self.counter++ } while ($(id));1775 element.writeAttribute('id', id);2073 do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); 2074 Element.writeAttribute(element, 'id', id); 1776 2075 return id; 1777 2076 }, … … 1796 2095 1797 2096 if (typeof name == 'object') attributes = name; 1798 else attributes[name] = value === undefined? true : value;2097 else attributes[name] = Object.isUndefined(value) ? true : value; 1799 2098 1800 2099 for (var attr in attributes) { 1801 var name = t.names[attr] || attr, value = attributes[attr]; 2100 name = t.names[attr] || attr; 2101 value = attributes[attr]; 1802 2102 if (t.values[attr]) name = t.values[attr](element, value); 1803 2103 if (value === false || value === null) … … 1811 2111 1812 2112 getHeight: function(element) { 1813 return $(element).getDimensions().height;2113 return Element.getDimensions(element).height; 1814 2114 }, 1815 2115 1816 2116 getWidth: function(element) { 1817 return $(element).getDimensions().width;2117 return Element.getDimensions(element).width; 1818 2118 }, 1819 2119 … … 1831 2131 addClassName: function(element, className) { 1832 2132 if (!(element = $(element))) return; 1833 if (! element.hasClassName(className))2133 if (!Element.hasClassName(element, className)) 1834 2134 element.className += (element.className ? ' ' : '') + className; 1835 2135 return element; … … 1845 2145 toggleClassName: function(element, className) { 1846 2146 if (!(element = $(element))) return; 1847 return element[element.hasClassName(className) ? 1848 'removeClassName' : 'addClassName'](className); 1849 }, 1850 1851 // removes whitespace-only text node children 2147 return Element[Element.hasClassName(element, className) ? 2148 'removeClassName' : 'addClassName'](element, className); 2149 }, 2150 1852 2151 cleanWhitespace: function(element) { 1853 2152 element = $(element); … … 1872 2171 return (element.compareDocumentPosition(ancestor) & 8) === 8; 1873 2172 1874 if (element.sourceIndex && !Prototype.Browser.Opera) { 1875 var e = element.sourceIndex, a = ancestor.sourceIndex, 1876 nextAncestor = ancestor.nextSibling; 1877 if (!nextAncestor) { 1878 do { ancestor = ancestor.parentNode; } 1879 while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); 1880 } 1881 if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); 1882 } 2173 if (ancestor.contains) 2174 return ancestor.contains(element) && ancestor !== element; 1883 2175 1884 2176 while (element = element.parentNode) 1885 2177 if (element == ancestor) return true; 2178 1886 2179 return false; 1887 2180 }, … … 1889 2182 scrollTo: function(element) { 1890 2183 element = $(element); 1891 var pos = element.cumulativeOffset();2184 var pos = Element.cumulativeOffset(element); 1892 2185 window.scrollTo(pos[0], pos[1]); 1893 2186 return element; … … 1898 2191 style = style == 'float' ? 'cssFloat' : style.camelize(); 1899 2192 var value = element.style[style]; 1900 if (!value ) {2193 if (!value || value == 'auto') { 1901 2194 var css = document.defaultView.getComputedStyle(element, null); 1902 2195 value = css ? css[style] : null; … … 1922 2215 else 1923 2216 elementStyle[(property == 'float' || property == 'cssFloat') ? 1924 ( elementStyle.styleFloat === undefined? 'cssFloat' : 'styleFloat') :2217 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : 1925 2218 property] = styles[property]; 1926 2219 … … 1937 2230 getDimensions: function(element) { 1938 2231 element = $(element); 1939 var display = $(element).getStyle('display');2232 var display = Element.getStyle(element, 'display'); 1940 2233 if (display != 'none' && display != null) // Safari bug 1941 2234 return {width: element.offsetWidth, height: element.offsetHeight}; 1942 2235 1943 // All *Width and *Height properties give 0 on elements with display none,1944 // so enable the element temporarily1945 2236 var els = element.style; 1946 2237 var originalVisibility = els.visibility; … … 1948 2239 var originalDisplay = els.display; 1949 2240 els.visibility = 'hidden'; 1950 els.position = 'absolute'; 2241 if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari 2242 els.position = 'absolute'; 1951 2243 els.display = 'block'; 1952 2244 var originalWidth = element.clientWidth; … … 1964 2256 element._madePositioned = true; 1965 2257 element.style.position = 'relative'; 1966 // Opera returns the offset relative to the positioning context, when an 1967 // element is position relative but top and left have not been defined 1968 if (window.opera) { 2258 if (Prototype.Browser.Opera) { 1969 2259 element.style.top = 0; 1970 2260 element.style.left = 0; … … 2021 2311 element = element.offsetParent; 2022 2312 if (element) { 2023 if (element.tagName == 'BODY') break;2313 if (element.tagName.toUpperCase() == 'BODY') break; 2024 2314 var p = Element.getStyle(element, 'position'); 2025 if (p == 'relative' || p == 'absolute') break;2315 if (p !== 'static') break; 2026 2316 } 2027 2317 } while (element); … … 2031 2321 absolutize: function(element) { 2032 2322 element = $(element); 2033 if (element.getStyle('position') == 'absolute') return; 2034 // Position.prepare(); // To be done manually by Scripty when it needs it. 2035 2036 var offsets = element.positionedOffset(); 2323 if (Element.getStyle(element, 'position') == 'absolute') return element; 2324 2325 var offsets = Element.positionedOffset(element); 2037 2326 var top = offsets[1]; 2038 2327 var left = offsets[0]; … … 2055 2344 relativize: function(element) { 2056 2345 element = $(element); 2057 if (element.getStyle('position') == 'relative') return; 2058 // Position.prepare(); // To be done manually by Scripty when it needs it. 2346 if (Element.getStyle(element, 'position') == 'relative') return element; 2059 2347 2060 2348 element.style.position = 'relative'; … … 2098 2386 valueL += element.offsetLeft || 0; 2099 2387 2100 // Safari fix2101 2388 if (element.offsetParent == document.body && 2102 2389 Element.getStyle(element, 'position') == 'absolute') break; … … 2106 2393 element = forElement; 2107 2394 do { 2108 if (!Prototype.Browser.Opera || element.tagName == 'BODY') {2395 if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { 2109 2396 valueT -= element.scrollTop || 0; 2110 2397 valueL -= element.scrollLeft || 0; … … 2125 2412 }, arguments[2] || { }); 2126 2413 2127 // find page position of source2128 2414 source = $(source); 2129 var p = source.viewportOffset(); 2130 2131 // find coordinate system to use 2415 var p = Element.viewportOffset(source); 2416 2132 2417 element = $(element); 2133 2418 var delta = [0, 0]; 2134 2419 var parent = null; 2135 // delta [0,0] will do fine with position: fixed elements,2136 // position:absolute needs offsetParent deltas2137 2420 if (Element.getStyle(element, 'position') == 'absolute') { 2138 parent = element.getOffsetParent(); 2139 delta = parent.viewportOffset(); 2140 } 2141 2142 // correct by body offsets (fixes Safari) 2421 parent = Element.getOffsetParent(element); 2422 delta = Element.viewportOffset(parent); 2423 } 2424 2143 2425 if (parent == document.body) { 2144 2426 delta[0] -= document.body.offsetLeft; … … 2146 2428 } 2147 2429 2148 // set position2149 2430 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 2150 2431 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; … … 2155 2436 }; 2156 2437 2157 Element.Methods.identify.counter = 1;2158 2159 2438 Object.extend(Element.Methods, { 2160 2439 getElementsBySelector: Element.Methods.select, 2440 2161 2441 childElements: Element.Methods.immediateDescendants 2162 2442 }); … … 2172 2452 }; 2173 2453 2174 2175 if (!document.createRange || Prototype.Browser.Opera) { 2176 Element.Methods.insert = function(element, insertions) {2177 element = $(element);2178 2179 if (Object.isString(insertions) || Object.isNumber(insertions) ||2180 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))2181 i nsertions = { bottom: insertions };2182 2183 var t = Element._insertionTranslations, content, position, pos, tagName;2184 2185 for (position in insertions) {2186 content = insertions[position];2187 position = position.toLowerCase(); 2188 pos = t[position];2189 2190 if (content && content.toElement) content = content.toElement();2191 if (Object.isElement(content)) {2192 pos.insert(element, content);2193 continue;2194 }2195 2196 content = Object.toHTML(content);2197 tagName = ((position == 'before' || position == 'after')2198 ? element.parentNode : element).tagName.toUpperCase();2199 2200 if (t.tags[tagName]) {2201 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());2202 if (position == 'top' || position == 'after') fragments.reverse();2203 fragments.each(pos.insert.curry(element));2204 }2205 else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); 2206 2207 content.evalScripts.bind(content).defer();2208 }2209 2210 return element;2211 };2454 if (Prototype.Browser.Opera) { 2455 Element.Methods.getStyle = Element.Methods.getStyle.wrap( 2456 function(proceed, element, style) { 2457 switch (style) { 2458 case 'left': case 'top': case 'right': case 'bottom': 2459 if (proceed(element, 'position') === 'static') return null; 2460 case 'height': case 'width': 2461 if (!Element.visible(element)) return null; 2462 2463 var dim = parseInt(proceed(element, style), 10); 2464 2465 if (dim !== element['offset' + style.capitalize()]) 2466 return dim + 'px'; 2467 2468 var properties; 2469 if (style === 'height') { 2470 properties = ['border-top-width', 'padding-top', 2471 'padding-bottom', 'border-bottom-width']; 2472 } 2473 else { 2474 properties = ['border-left-width', 'padding-left', 2475 'padding-right', 'border-right-width']; 2476 } 2477 return properties.inject(dim, function(memo, property) { 2478 var val = proceed(element, property); 2479 return val === null ? memo : memo - parseInt(val, 10); 2480 }) + 'px'; 2481 default: return proceed(element, style); 2482 } 2483 } 2484 ); 2485 2486 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( 2487 function(proceed, element, attribute) { 2488 if (attribute === 'title') return element.title; 2489 return proceed(element, attribute); 2490 } 2491 ); 2212 2492 } 2213 2493 2214 if (Prototype.Browser.Opera) {2215 Element.Methods._getStyle = Element.Methods.getStyle;2216 Element.Methods.getStyle = function(element, style) {2217 switch(style) {2218 case 'left':2219 case 'top':2220 case 'right':2221 case 'bottom':2222 if (Element._getStyle(element, 'position') == 'static') return null;2223 default: return Element._getStyle(element, style);2224 }2225 };2226 Element.Methods._readAttribute = Element.Methods.readAttribute;2227 Element.Methods.readAttribute = function(element, attribute) {2228 if (attribute == 'title') return element.title;2229 return Element._readAttribute(element, attribute);2230 };2231 }2232 2233 2494 else if (Prototype.Browser.IE) { 2234 $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { 2495 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( 2496 function(proceed, element) { 2497 element = $(element); 2498 try { element.offsetParent } 2499 catch(e) { return $(document.body) } 2500 var position = element.getStyle('position'); 2501 if (position !== 'static') return proceed(element); 2502 element.setStyle({ position: 'relative' }); 2503 var value = proceed(element); 2504 element.setStyle({ position: position }); 2505 return value; 2506 } 2507 ); 2508 2509 $w('positionedOffset viewportOffset').each(function(method) { 2235 2510 Element.Methods[method] = Element.Methods[method].wrap( 2236 2511 function(proceed, element) { 2237 2512 element = $(element); 2513 try { element.offsetParent } 2514 catch(e) { return Element._returnOffset(0,0) } 2238 2515 var position = element.getStyle('position'); 2239 if (position != 'static') return proceed(element); 2516 if (position !== 'static') return proceed(element); 2517 var offsetParent = element.getOffsetParent(); 2518 if (offsetParent && offsetParent.getStyle('position') === 'fixed') 2519 offsetParent.setStyle({ zoom: 1 }); 2240 2520 element.setStyle({ position: 'relative' }); 2241 2521 var value = proceed(element); … … 2245 2525 ); 2246 2526 }); 2527 2528 Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( 2529 function(proceed, element) { 2530 try { element.offsetParent } 2531 catch(e) { return Element._returnOffset(0,0) } 2532 return proceed(element); 2533 } 2534 ); 2247 2535 2248 2536 Element.Methods.getStyle = function(element, style) { … … 2287 2575 }; 2288 2576 2289 Element._attributeTranslations = { 2290 read: { 2291 names: { 2292 'class': 'className', 2293 'for': 'htmlFor' 2294 }, 2295 values: { 2296 _getAttr: function(element, attribute) { 2297 return element.getAttribute(attribute, 2); 2577 Element._attributeTranslations = (function(){ 2578 2579 var classProp = 'className'; 2580 var forProp = 'for'; 2581 2582 var el = document.createElement('div'); 2583 2584 el.setAttribute(classProp, 'x'); 2585 2586 if (el.className !== 'x') { 2587 el.setAttribute('class', 'x'); 2588 if (el.className === 'x') { 2589 classProp = 'class'; 2590 } 2591 } 2592 el = null; 2593 2594 el = document.createElement('label'); 2595 el.setAttribute(forProp, 'x'); 2596 if (el.htmlFor !== 'x') { 2597 el.setAttribute('htmlFor', 'x'); 2598 if (el.htmlFor === 'x') { 2599 forProp = 'htmlFor'; 2600 } 2601 } 2602 el = null; 2603 2604 return { 2605 read: { 2606 names: { 2607 'class': classProp, 2608 'className': classProp, 2609 'for': forProp, 2610 'htmlFor': forProp 2298 2611 }, 2299 _getAttrNode: function(element, attribute) { 2300 var node = element.getAttributeNode(attribute); 2301 return node ? node.value : ""; 2302 }, 2303 _getEv: function(element, attribute) { 2304 var attribute = element.getAttribute(attribute); 2305 return attribute ? attribute.toString().slice(23, -2) : null; 2306 }, 2307 _flag: function(element, attribute) { 2308 return $(element).hasAttribute(attribute) ? attribute : null; 2309 }, 2310 style: function(element) { 2311 return element.style.cssText.toLowerCase(); 2312 }, 2313 title: function(element) { 2314 return element.title; 2612 values: { 2613 _getAttr: function(element, attribute) { 2614 return element.getAttribute(attribute); 2615 }, 2616 _getAttr2: function(element, attribute) { 2617 return element.getAttribute(attribute, 2); 2618 }, 2619 _getAttrNode: function(element, attribute) { 2620 var node = element.getAttributeNode(attribute); 2621 return node ? node.value : ""; 2622 }, 2623 _getEv: (function(){ 2624 2625 var el = document.createElement('div'); 2626 el.onclick = Prototype.emptyFunction; 2627 var value = el.getAttribute('onclick'); 2628 var f; 2629 2630 if (String(value).indexOf('{') > -1) { 2631 f = function(element, attribute) { 2632 attribute = element.getAttribute(attribute); 2633 if (!attribute) return null; 2634 attribute = attribute.toString(); 2635 attribute = attribute.split('{')[1]; 2636 attribute = attribute.split('}')[0]; 2637 return attribute.strip(); 2638 }; 2639 } 2640 else if (value === '') { 2641 f = function(element, attribute) { 2642 attribute = element.getAttribute(attribute); 2643 if (!attribute) return null; 2644 return attribute.strip(); 2645 }; 2646 } 2647 el = null; 2648 return f; 2649 })(), 2650 _flag: function(element, attribute) { 2651 return $(element).hasAttribute(attribute) ? attribute : null; 2652 }, 2653 style: function(element) { 2654 return element.style.cssText.toLowerCase(); 2655 }, 2656 title: function(element) { 2657 return element.title; 2658 } 2315 2659 } 2316 2660 } 2317 2661 } 2318 } ;2662 })(); 2319 2663 2320 2664 Element._attributeTranslations.write = { 2321 names: Object.clone(Element._attributeTranslations.read.names), 2665 names: Object.extend({ 2666 cellpadding: 'cellPadding', 2667 cellspacing: 'cellSpacing' 2668 }, Element._attributeTranslations.read.names), 2322 2669 values: { 2323 2670 checked: function(element, value) { … … 2334 2681 2335 2682 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 2336 'encType maxLength readOnly longDesc ').each(function(attr) {2683 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { 2337 2684 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 2338 2685 Element._attributeTranslations.has[attr.toLowerCase()] = attr; … … 2341 2688 (function(v) { 2342 2689 Object.extend(v, { 2343 href: v._getAttr ,2344 src: v._getAttr ,2690 href: v._getAttr2, 2691 src: v._getAttr2, 2345 2692 type: v._getAttr, 2346 2693 action: v._getAttrNode, … … 2369 2716 }); 2370 2717 })(Element._attributeTranslations.read.values); 2718 2719 if (Prototype.BrowserFeatures.ElementExtensions) { 2720 (function() { 2721 function _descendants(element) { 2722 var nodes = element.getElementsByTagName('*'), results = []; 2723 for (var i = 0, node; node = nodes[i]; i++) 2724 if (node.tagName !== "!") // Filter out comment nodes. 2725 results.push(node); 2726 return results; 2727 } 2728 2729 Element.Methods.down = function(element, expression, index) { 2730 element = $(element); 2731 if (arguments.length == 1) return element.firstDescendant(); 2732 return Object.isNumber(expression) ? _descendants(element)[expression] : 2733 Element.select(element, expression)[index || 0]; 2734 } 2735 })(); 2736 } 2737 2371 2738 } 2372 2739 … … 2387 2754 2388 2755 if (value == 1) 2389 if(element.tagName == 'IMG' && element.width) {2756 if(element.tagName.toUpperCase() == 'IMG' && element.width) { 2390 2757 element.width++; element.width--; 2391 2758 } else try { … … 2398 2765 }; 2399 2766 2400 // Safari returns margins on body which is incorrect if the child is absolutely2401 // positioned. For performance reasons, redefine Position.cumulativeOffset for2402 // KHTML/WebKit only.2403 2767 Element.Methods.cumulativeOffset = function(element) { 2404 2768 var valueT = 0, valueL = 0; … … 2416 2780 } 2417 2781 2418 if (Prototype.Browser.IE || Prototype.Browser.Opera) { 2419 // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements 2420 Element.Methods.update = function(element, content) { 2421 element = $(element); 2422 2423 if (content && content.toElement) content = content.toElement(); 2424 if (Object.isElement(content)) return element.update().insert(content); 2425 2426 content = Object.toHTML(content); 2427 var tagName = element.tagName.toUpperCase(); 2428 2429 if (tagName in Element._insertionTranslations.tags) { 2430 $A(element.childNodes).each(function(node) { element.removeChild(node) }); 2431 Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 2432 .each(function(node) { element.appendChild(node) }); 2433 } 2434 else element.innerHTML = content.stripScripts(); 2435 2436 content.evalScripts.bind(content).defer(); 2437 return element; 2438 }; 2439 } 2440 2441 if (document.createElement('div').outerHTML) { 2782 if ('outerHTML' in document.documentElement) { 2442 2783 Element.Methods.replace = function(element, content) { 2443 2784 element = $(element); … … 2477 2818 Element._getContentFromAnonymousElement = function(tagName, html) { 2478 2819 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 2479 div.innerHTML = t[0] + html + t[1]; 2480 t[2].times(function() { div = div.firstChild }); 2820 if (t) { 2821 div.innerHTML = t[0] + html + t[1]; 2822 t[2].times(function() { div = div.firstChild }); 2823 } else div.innerHTML = html; 2481 2824 return $A(div.childNodes); 2482 2825 }; 2483 2826 2484 2827 Element._insertionTranslations = { 2485 before: { 2486 adjacency: 'beforeBegin', 2487 insert: function(element, node) { 2488 element.parentNode.insertBefore(node, element); 2489 }, 2490 initializeRange: function(element, range) { 2491 range.setStartBefore(element); 2492 } 2493 }, 2494 top: { 2495 adjacency: 'afterBegin', 2496 insert: function(element, node) { 2497 element.insertBefore(node, element.firstChild); 2498 }, 2499 initializeRange: function(element, range) { 2500 range.selectNodeContents(element); 2501 range.collapse(true); 2502 } 2503 }, 2504 bottom: { 2505 adjacency: 'beforeEnd', 2506 insert: function(element, node) { 2507 element.appendChild(node); 2508 } 2509 }, 2510 after: { 2511 adjacency: 'afterEnd', 2512 insert: function(element, node) { 2513 element.parentNode.insertBefore(node, element.nextSibling); 2514 }, 2515 initializeRange: function(element, range) { 2516 range.setStartAfter(element); 2517 } 2828 before: function(element, node) { 2829 element.parentNode.insertBefore(node, element); 2830 }, 2831 top: function(element, node) { 2832 element.insertBefore(node, element.firstChild); 2833 }, 2834 bottom: function(element, node) { 2835 element.appendChild(node); 2836 }, 2837 after: function(element, node) { 2838 element.parentNode.insertBefore(node, element.nextSibling); 2518 2839 }, 2519 2840 tags: { … … 2527 2848 2528 2849 (function() { 2529 this.bottom.initializeRange = this.top.initializeRange;2530 Object.extend(t his.tags, {2531 THEAD: t his.tags.TBODY,2532 TFOOT: t his.tags.TBODY,2533 TH: t his.tags.TD2850 var tags = Element._insertionTranslations.tags; 2851 Object.extend(tags, { 2852 THEAD: tags.TBODY, 2853 TFOOT: tags.TBODY, 2854 TH: tags.TD 2534 2855 }); 2535 }) .call(Element._insertionTranslations);2856 })(); 2536 2857 2537 2858 Element.Methods.Simulated = { … … 2539 2860 attribute = Element._attributeTranslations.has[attribute] || attribute; 2540 2861 var node = $(element).getAttributeNode(attribute); 2541 return node && node.specified;2862 return !!(node && node.specified); 2542 2863 } 2543 2864 }; … … 2547 2868 Object.extend(Element, Element.Methods); 2548 2869 2549 if (!Prototype.BrowserFeatures.ElementExtensions && 2550 document.createElement('div').__proto__) { 2551 window.HTMLElement = { }; 2552 window.HTMLElement.prototype = document.createElement('div').__proto__; 2553 Prototype.BrowserFeatures.ElementExtensions = true; 2554 } 2870 (function(div) { 2871 2872 if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { 2873 window.HTMLElement = { }; 2874 window.HTMLElement.prototype = div['__proto__']; 2875 Prototype.BrowserFeatures.ElementExtensions = true; 2876 } 2877 2878 div = null; 2879 2880 })(document.createElement('div')) 2555 2881 2556 2882 Element.extend = (function() { 2557 if (Prototype.BrowserFeatures.SpecificElementExtensions) 2558 return Prototype.K; 2559 2560 var Methods = { }, ByTag = Element.Methods.ByTag; 2561 2562 var extend = Object.extend(function(element) { 2563 if (!element || element._extendedByPrototype || 2564 element.nodeType != 1 || element == window) return element; 2565 2566 var methods = Object.clone(Methods), 2567 tagName = element.tagName, property, value; 2568 2569 // extend methods for specific tags 2570 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 2571 2572 for (property in methods) { 2573 value = methods[property]; 2883 2884 function checkDeficiency(tagName) { 2885 if (typeof window.Element != 'undefined') { 2886 var proto = window.Element.prototype; 2887 if (proto) { 2888 var id = '_' + (Math.random()+'').slice(2); 2889 var el = document.createElement(tagName); 2890 proto[id] = 'x'; 2891 var isBuggy = (el[id] !== 'x'); 2892 delete proto[id]; 2893 el = null; 2894 return isBuggy; 2895 } 2896 } 2897 return false; 2898 } 2899 2900 function extendElementWith(element, methods) { 2901 for (var property in methods) { 2902 var value = methods[property]; 2574 2903 if (Object.isFunction(value) && !(property in element)) 2575 2904 element[property] = value.methodize(); 2576 2905 } 2906 } 2907 2908 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); 2909 2910 if (Prototype.BrowserFeatures.SpecificElementExtensions) { 2911 if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { 2912 return function(element) { 2913 if (element && typeof element._extendedByPrototype == 'undefined') { 2914 var t = element.tagName; 2915 if (t && (/^(?:object|applet|embed)$/i.test(t))) { 2916 extendElementWith(element, Element.Methods); 2917 extendElementWith(element, Element.Methods.Simulated); 2918 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); 2919 } 2920 } 2921 return element; 2922 } 2923 } 2924 return Prototype.K; 2925 } 2926 2927 var Methods = { }, ByTag = Element.Methods.ByTag; 2928 2929 var extend = Object.extend(function(element) { 2930 if (!element || typeof element._extendedByPrototype != 'undefined' || 2931 element.nodeType != 1 || element == window) return element; 2932 2933 var methods = Object.clone(Methods), 2934 tagName = element.tagName.toUpperCase(); 2935 2936 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 2937 2938 extendElementWith(element, methods); 2577 2939 2578 2940 element._extendedByPrototype = Prototype.emptyFunction; … … 2581 2943 }, { 2582 2944 refresh: function() { 2583 // extend methods for all tags (Safari doesn't need this)2584 2945 if (!Prototype.BrowserFeatures.ElementExtensions) { 2585 2946 Object.extend(Methods, Element.Methods); … … 2660 3021 if (window[klass]) return window[klass]; 2661 3022 2662 window[klass] = { }; 2663 window[klass].prototype = document.createElement(tagName).__proto__; 2664 return window[klass]; 2665 } 3023 var element = document.createElement(tagName); 3024 var proto = element['__proto__'] || element.constructor.prototype; 3025 element = null; 3026 return proto; 3027 } 3028 3029 var elementPrototype = window.HTMLElement ? HTMLElement.prototype : 3030 Element.prototype; 2666 3031 2667 3032 if (F.ElementExtensions) { 2668 copy(Element.Methods, HTMLElement.prototype);2669 copy(Element.Methods.Simulated, HTMLElement.prototype, true);3033 copy(Element.Methods, elementPrototype); 3034 copy(Element.Methods.Simulated, elementPrototype, true); 2670 3035 } 2671 3036 … … 2685 3050 }; 2686 3051 3052 2687 3053 document.viewport = { 3054 2688 3055 getDimensions: function() { 2689 var dimensions = { }; 2690 $w('width height').each(function(d) { 2691 var D = d.capitalize(); 2692 dimensions[d] = self['inner' + D] || 2693 (document.documentElement['client' + D] || document.body['client' + D]); 2694 }); 2695 return dimensions; 2696 }, 2697 2698 getWidth: function() { 2699 return this.getDimensions().width; 2700 }, 2701 2702 getHeight: function() { 2703 return this.getDimensions().height; 3056 return { width: this.getWidth(), height: this.getHeight() }; 2704 3057 }, 2705 3058 … … 2707 3060 return Element._returnOffset( 2708 3061 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 2709 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);3062 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 2710 3063 } 2711 3064 }; 2712 /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, 3065 3066 (function(viewport) { 3067 var B = Prototype.Browser, doc = document, element, property = {}; 3068 3069 function getRootElement() { 3070 if (B.WebKit && !doc.evaluate) 3071 return document; 3072 3073 if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) 3074 return document.body; 3075 3076 return document.documentElement; 3077 } 3078 3079 function define(D) { 3080 if (!element) element = getRootElement(); 3081 3082 property[D] = 'client' + D; 3083 3084 viewport['get' + D] = function() { return element[property[D]] }; 3085 return viewport['get' + D](); 3086 } 3087 3088 viewport.getWidth = define.curry('Width'); 3089 3090 viewport.getHeight = define.curry('Height'); 3091 })(document.viewport); 3092 3093 3094 Element.Storage = { 3095 UID: 1 3096 }; 3097 3098 Element.addMethods({ 3099 getStorage: function(element) { 3100 if (!(element = $(element))) return; 3101 3102 var uid; 3103 if (element === window) { 3104 uid = 0; 3105 } else { 3106 if (typeof element._prototypeUID === "undefined") 3107 element._prototypeUID = [Element.Storage.UID++]; 3108 uid = element._prototypeUID[0]; 3109 } 3110 3111 if (!Element.Storage[uid]) 3112 Element.Storage[uid] = $H(); 3113 3114 return Element.Storage[uid]; 3115 }, 3116 3117 store: function(element, key, value) { 3118 if (!(element = $(element))) return; 3119 3120 if (arguments.length === 2) { 3121 Element.getStorage(element).update(key); 3122 } else { 3123 Element.getStorage(element).set(key, value); 3124 } 3125 3126 return element; 3127 }, 3128 3129 retrieve: function(element, key, defaultValue) { 3130 if (!(element = $(element))) return; 3131 var hash = Element.getStorage(element), value = hash.get(key); 3132 3133 if (Object.isUndefined(value)) { 3134 hash.set(key, defaultValue); 3135 value = defaultValue; 3136 } 3137 3138 return value; 3139 }, 3140 3141 clone: function(element, deep) { 3142 if (!(element = $(element))) return; 3143 var clone = element.cloneNode(deep); 3144 clone._prototypeUID = void 0; 3145 if (deep) { 3146 var descendants = Element.select(clone, '*'), 3147 i = descendants.length; 3148 while (i--) { 3149 descendants[i]._prototypeUID = void 0; 3150 } 3151 } 3152 return Element.extend(clone); 3153 } 3154 }); 3155 /* Portions of the Selector class are derived from Jack Slocum's DomQuery, 2713 3156 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 2714 3157 * license. Please see http://www.yui-ext.com/ for more information. */ … … 2717 3160 initialize: function(expression) { 2718 3161 this.expression = expression.strip(); 2719 this.compileMatcher(); 3162 3163 if (this.shouldUseSelectorsAPI()) { 3164 this.mode = 'selectorsAPI'; 3165 } else if (this.shouldUseXPath()) { 3166 this.mode = 'xpath'; 3167 this.compileXPathMatcher(); 3168 } else { 3169 this.mode = "normal"; 3170 this.compileMatcher(); 3171 } 3172 3173 }, 3174 3175 shouldUseXPath: (function() { 3176 3177 var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ 3178 var isBuggy = false; 3179 if (document.evaluate && window.XPathResult) { 3180 var el = document.createElement('div'); 3181 el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>'; 3182 3183 var xpath = ".//*[local-name()='ul' or local-name()='UL']" + 3184 "//*[local-name()='li' or local-name()='LI']"; 3185 3186 var result = document.evaluate(xpath, el, null, 3187 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 3188 3189 isBuggy = (result.snapshotLength !== 2); 3190 el = null; 3191 } 3192 return isBuggy; 3193 })(); 3194 3195 return function() { 3196 if (!Prototype.BrowserFeatures.XPath) return false; 3197 3198 var e = this.expression; 3199 3200 if (Prototype.Browser.WebKit && 3201 (e.include("-of-type") || e.include(":empty"))) 3202 return false; 3203 3204 if ((/(\[[\w-]*?:|:checked)/).test(e)) 3205 return false; 3206 3207 if (IS_DESCENDANT_SELECTOR_BUGGY) return false; 3208 3209 return true; 3210 } 3211 3212 })(), 3213 3214 shouldUseSelectorsAPI: function() { 3215 if (!Prototype.BrowserFeatures.SelectorsAPI) return false; 3216 3217 if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; 3218 3219 if (!Selector._div) Selector._div = new Element('div'); 3220 3221 try { 3222 Selector._div.querySelector(this.expression); 3223 } catch(e) { 3224 return false; 3225 } 3226 3227 return true; 2720 3228 }, 2721 3229 2722 3230 compileMatcher: function() { 2723 // Selectors with namespaced attributes can't use the XPath version2724 if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))2725 return this.compileXPathMatcher();2726 2727 3231 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 2728 c = Selector.criteria, le, p, m ;3232 c = Selector.criteria, le, p, m, len = ps.length, name; 2729 3233 2730 3234 if (Selector._cache[e]) { … … 2738 3242 while (e && le != e && (/\S/).test(e)) { 2739 3243 le = e; 2740 for (var i in ps) { 2741 p = ps[i]; 3244 for (var i = 0; i<len; i++) { 3245 p = ps[i].re; 3246 name = ps[i].name; 2742 3247 if (m = e.match(p)) { 2743 this.matcher.push(Object.isFunction(c[ i]) ? c[i](m) :2744 new Template(c[i]).evaluate(m));3248 this.matcher.push(Object.isFunction(c[name]) ? c[name](m) : 3249 new Template(c[name]).evaluate(m)); 2745 3250 e = e.replace(m[0], ''); 2746 3251 break; … … 2756 3261 compileXPathMatcher: function() { 2757 3262 var e = this.expression, ps = Selector.patterns, 2758 x = Selector.xpath, le, m ;3263 x = Selector.xpath, le, m, len = ps.length, name; 2759 3264 2760 3265 if (Selector._cache[e]) { … … 2765 3270 while (e && le != e && (/\S/).test(e)) { 2766 3271 le = e; 2767 for (var i in ps) { 2768 if (m = e.match(ps[i])) { 2769 this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : 2770 new Template(x[i]).evaluate(m)); 3272 for (var i = 0; i<len; i++) { 3273 name = ps[i].name; 3274 if (m = e.match(ps[i].re)) { 3275 this.matcher.push(Object.isFunction(x[name]) ? x[name](m) : 3276 new Template(x[name]).evaluate(m)); 2771 3277 e = e.replace(m[0], ''); 2772 3278 break; … … 2781 3287 findElements: function(root) { 2782 3288 root = root || document; 2783 if (this.xpath) return document._getElementsByXPath(this.xpath, root); 2784 return this.matcher(root); 3289 var e = this.expression, results; 3290 3291 switch (this.mode) { 3292 case 'selectorsAPI': 3293 if (root !== document) { 3294 var oldId = root.id, id = $(root).identify(); 3295 id = id.replace(/([\.:])/g, "\\$1"); 3296 e = "#" + id + " " + e; 3297 } 3298 3299 results = $A(root.querySelectorAll(e)).map(Element.extend); 3300 root.id = oldId; 3301 3302 return results; 3303 case 'xpath': 3304 return document._getElementsByXPath(this.xpath, root); 3305 default: 3306 return this.matcher(root); 3307 } 2785 3308 }, 2786 3309 … … 2789 3312 2790 3313 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 2791 var le, p, m ;3314 var le, p, m, len = ps.length, name; 2792 3315 2793 3316 while (e && le !== e && (/\S/).test(e)) { 2794 3317 le = e; 2795 for (var i in ps) { 2796 p = ps[i]; 3318 for (var i = 0; i<len; i++) { 3319 p = ps[i].re; 3320 name = ps[i].name; 2797 3321 if (m = e.match(p)) { 2798 // use the Selector.assertions methods unless the selector 2799 // is too complex. 2800 if (as[i]) { 2801 this.tokens.push([i, Object.clone(m)]); 3322 if (as[name]) { 3323 this.tokens.push([name, Object.clone(m)]); 2802 3324 e = e.replace(m[0], ''); 2803 3325 } else { 2804 // reluctantly do a document-wide search2805 // and look for a match in the array2806 3326 return this.findElements(document).include(element); 2807 3327 } … … 2829 3349 } 2830 3350 }); 3351 3352 if (Prototype.BrowserFeatures.SelectorsAPI && 3353 document.compatMode === 'BackCompat') { 3354 Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ 3355 var div = document.createElement('div'), 3356 span = document.createElement('span'); 3357 3358 div.id = "prototype_test_id"; 3359 span.className = 'Test'; 3360 div.appendChild(span); 3361 var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); 3362 div = span = null; 3363 return isIgnored; 3364 })(); 3365 } 2831 3366 2832 3367 Object.extend(Selector, { … … 2845 3380 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 2846 3381 id: "[@id='#{1}']", 2847 attrPresence: "[@#{1}]", 3382 attrPresence: function(m) { 3383 m[1] = m[1].toLowerCase(); 3384 return new Template("[@#{1}]").evaluate(m); 3385 }, 2848 3386 attr: function(m) { 3387 m[1] = m[1].toLowerCase(); 2849 3388 m[3] = m[5] || m[6]; 2850 3389 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); … … 2869 3408 'last-child': '[not(following-sibling::*)]', 2870 3409 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 2871 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",3410 'empty': "[count(*) = 0 and (count(text()) = 0)]", 2872 3411 'checked': "[@checked]", 2873 'disabled': "[ @disabled]",2874 'enabled': "[not(@disabled) ]",3412 'disabled': "[(@disabled) and (@type!='hidden')]", 3413 'enabled': "[not(@disabled) and (@type!='hidden')]", 2875 3414 'not': function(m) { 2876 3415 var e = m[6], p = Selector.patterns, 2877 x = Selector.xpath, le, m, v;3416 x = Selector.xpath, le, v, len = p.length, name; 2878 3417 2879 3418 var exclusion = []; 2880 3419 while (e && le != e && (/\S/).test(e)) { 2881 3420 le = e; 2882 for (var i in p) { 2883 if (m = e.match(p[i])) { 2884 v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); 3421 for (var i = 0; i<len; i++) { 3422 name = p[i].name 3423 if (m = e.match(p[i].re)) { 3424 v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m); 2885 3425 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 2886 3426 e = e.replace(m[0], ''); … … 2932 3472 2933 3473 criteria: { 2934 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',2935 className: 'n = h.className(n, r, "#{1}", c); c = false;',2936 id: 'n = h.id(n, r, "#{1}", c); c = false;',2937 attrPresence: 'n = h.attrPresence(n, r, "#{1}" ); c = false;',3474 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', 3475 className: 'n = h.className(n, r, "#{1}", c); c = false;', 3476 id: 'n = h.id(n, r, "#{1}", c); c = false;', 3477 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', 2938 3478 attr: function(m) { 2939 3479 m[3] = (m[5] || m[6]); 2940 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}" ); c = false;').evaluate(m);3480 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); 2941 3481 }, 2942 3482 pseudo: function(m) { … … 2950 3490 }, 2951 3491 2952 patterns: { 2953 // combinators must be listed first 2954 // (and descendant needs to be last combinator) 2955 laterSibling: /^\s*~\s*/, 2956 child: /^\s*>\s*/, 2957 adjacent: /^\s*\+\s*/, 2958 descendant: /^\s/, 2959 2960 // selectors follow 2961 tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, 2962 id: /^#([\w\-\*]+)(\b|$)/, 2963 className: /^\.([\w\-\*]+)(\b|$)/, 2964 pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/, 2965 attrPresence: /^\[([\w]+)\]/, 2966 attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ 2967 }, 2968 2969 // for Selector.match and Element#match 3492 patterns: [ 3493 { name: 'laterSibling', re: /^\s*~\s*/ }, 3494 { name: 'child', re: /^\s*>\s*/ }, 3495 { name: 'adjacent', re: /^\s*\+\s*/ }, 3496 { name: 'descendant', re: /^\s/ }, 3497 3498 { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, 3499 { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, 3500 { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, 3501 { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, 3502 { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, 3503 { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } 3504 ], 3505 2970 3506 assertions: { 2971 3507 tagName: function(element, matches) { … … 2987 3523 attr: function(element, matches) { 2988 3524 var nodeValue = Element.readAttribute(element, matches[1]); 2989 return Selector.operators[matches[2]](nodeValue, matches[3]);3525 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); 2990 3526 } 2991 3527 }, 2992 3528 2993 3529 handlers: { 2994 // UTILITY FUNCTIONS2995 // joins two collections2996 3530 concat: function(a, b) { 2997 3531 for (var i = 0, node; node = b[i]; i++) … … 3000 3534 }, 3001 3535 3002 // marks an array of nodes for counting3003 3536 mark: function(nodes) { 3537 var _true = Prototype.emptyFunction; 3004 3538 for (var i = 0, node; node = nodes[i]; i++) 3005 node._counted =true;3539 node._countedByPrototype = _true; 3006 3540 return nodes; 3007 3541 }, 3008 3542 3009 unmark: function(nodes) { 3010 for (var i = 0, node; node = nodes[i]; i++) 3011 node._counted = undefined; 3012 return nodes; 3013 }, 3014 3015 // mark each child node with its position (for nth calls) 3016 // "ofType" flag indicates whether we're indexing for nth-of-type 3017 // rather than nth-child 3543 unmark: (function(){ 3544 3545 var PROPERTIES_ATTRIBUTES_MAP = (function(){ 3546 var el = document.createElement('div'), 3547 isBuggy = false, 3548 propName = '_countedByPrototype', 3549 value = 'x' 3550 el[propName] = value; 3551 isBuggy = (el.getAttribute(propName) === value); 3552 el = null; 3553 return isBuggy; 3554 })(); 3555 3556 return PROPERTIES_ATTRIBUTES_MAP ? 3557 function(nodes) { 3558 for (var i = 0, node; node = nodes[i]; i++) 3559 node.removeAttribute('_countedByPrototype'); 3560 return nodes; 3561 } : 3562 function(nodes) { 3563 for (var i = 0, node; node = nodes[i]; i++) 3564 node._countedByPrototype = void 0; 3565 return nodes; 3566 } 3567 })(), 3568 3018 3569 index: function(parentNode, reverse, ofType) { 3019 parentNode._counted = true;3570 parentNode._countedByPrototype = Prototype.emptyFunction; 3020 3571 if (reverse) { 3021 3572 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 3022 3573 var node = nodes[i]; 3023 if (node.nodeType == 1 && (!ofType || node._counted )) node.nodeIndex = j++;3574 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 3024 3575 } 3025 3576 } else { 3026 3577 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 3027 if (node.nodeType == 1 && (!ofType || node._counted )) node.nodeIndex = j++;3578 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 3028 3579 } 3029 3580 }, 3030 3581 3031 // filters out duplicates and extends all nodes3032 3582 unique: function(nodes) { 3033 3583 if (nodes.length == 0) return nodes; 3034 3584 var results = [], n; 3035 3585 for (var i = 0, l = nodes.length; i < l; i++) 3036 if ( !(n = nodes[i])._counted) {3037 n._counted = true;3586 if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { 3587 n._countedByPrototype = Prototype.emptyFunction; 3038 3588 results.push(Element.extend(n)); 3039 3589 } … … 3041 3591 }, 3042 3592 3043 // COMBINATOR FUNCTIONS3044 3593 descendant: function(nodes) { 3045 3594 var h = Selector.handlers; … … 3052 3601 var h = Selector.handlers; 3053 3602 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3054 for (var j = 0, child ren = [], child; child = node.childNodes[j]; j++)3603 for (var j = 0, child; child = node.childNodes[j]; j++) 3055 3604 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 3056 3605 } … … 3075 3624 nextElementSibling: function(node) { 3076 3625 while (node = node.nextSibling) 3077 3626 if (node.nodeType == 1) return node; 3078 3627 return null; 3079 3628 }, … … 3085 3634 }, 3086 3635 3087 // TOKEN FUNCTIONS3088 3636 tagName: function(nodes, root, tagName, combinator) { 3089 tagName = tagName.toUpperCase();3637 var uTagName = tagName.toUpperCase(); 3090 3638 var results = [], h = Selector.handlers; 3091 3639 if (nodes) { 3092 3640 if (combinator) { 3093 // fastlane for ordinary descendant combinators3094 3641 if (combinator == "descendant") { 3095 3642 for (var i = 0, node; node = nodes[i]; i++) … … 3100 3647 } 3101 3648 for (var i = 0, node; node = nodes[i]; i++) 3102 if (node.tagName.toUpperCase() == tagName) results.push(node);3649 if (node.tagName.toUpperCase() === uTagName) results.push(node); 3103 3650 return results; 3104 3651 } else return root.getElementsByTagName(tagName); … … 3107 3654 id: function(nodes, root, id, combinator) { 3108 3655 var targetNode = $(id), h = Selector.handlers; 3109 if (!targetNode) return []; 3110 if (!nodes && root == document) return [targetNode]; 3656 3657 if (root == document) { 3658 if (!targetNode) return []; 3659 if (!nodes) return [targetNode]; 3660 } else { 3661 if (!root.sourceIndex || root.sourceIndex < 1) { 3662 var nodes = root.getElementsByTagName('*'); 3663 for (var j = 0, node; node = nodes[j]; j++) { 3664 if (node.id === id) return [node]; 3665 } 3666 } 3667 } 3668 3111 3669 if (nodes) { 3112 3670 if (combinator) { … … 3147 3705 }, 3148 3706 3149 attrPresence: function(nodes, root, attr ) {3707 attrPresence: function(nodes, root, attr, combinator) { 3150 3708 if (!nodes) nodes = root.getElementsByTagName("*"); 3709 if (nodes && combinator) nodes = this[combinator](nodes); 3151 3710 var results = []; 3152 3711 for (var i = 0, node; node = nodes[i]; i++) … … 3155 3714 }, 3156 3715 3157 attr: function(nodes, root, attr, value, operator ) {3716 attr: function(nodes, root, attr, value, operator, combinator) { 3158 3717 if (!nodes) nodes = root.getElementsByTagName("*"); 3718 if (nodes && combinator) nodes = this[combinator](nodes); 3159 3719 var handler = Selector.operators[operator], results = []; 3160 3720 for (var i = 0, node; node = nodes[i]; i++) { … … 3218 3778 }, 3219 3779 3220 // handles the an+b logic3221 3780 getIndices: function(a, b, total) { 3222 3781 if (a == 0) return b > 0 ? [b] : []; … … 3227 3786 }, 3228 3787 3229 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type3230 3788 nth: function(nodes, formula, root, reverse, ofType) { 3231 3789 if (nodes.length == 0) return []; … … 3235 3793 h.mark(nodes); 3236 3794 for (var i = 0, node; node = nodes[i]; i++) { 3237 if (!node.parentNode._counted ) {3795 if (!node.parentNode._countedByPrototype) { 3238 3796 h.index(node.parentNode, reverse, ofType); 3239 3797 indexed.push(node.parentNode); … … 3261 3819 'empty': function(nodes, value, root) { 3262 3820 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3263 // IE treats comments as element nodes 3264 if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; 3821 if (node.tagName == '!' || node.firstChild) continue; 3265 3822 results.push(node); 3266 3823 } … … 3273 3830 h.mark(exclusions); 3274 3831 for (var i = 0, results = [], node; node = nodes[i]; i++) 3275 if (!node._counted ) results.push(node);3832 if (!node._countedByPrototype) results.push(node); 3276 3833 h.unmark(exclusions); 3277 3834 return results; … … 3280 3837 'enabled': function(nodes, value, root) { 3281 3838 for (var i = 0, results = [], node; node = nodes[i]; i++) 3282 if (!node.disabled) results.push(node); 3839 if (!node.disabled && (!node.type || node.type !== 'hidden')) 3840 results.push(node); 3283 3841 return results; 3284 3842 }, … … 3300 3858 '=': function(nv, v) { return nv == v; }, 3301 3859 '!=': function(nv, v) { return nv != v; }, 3302 '^=': function(nv, v) { return nv .startsWith(v); },3303 '$=': function(nv, v) { return nv .endsWith(v); },3304 '*=': function(nv, v) { return nv .include(v); },3860 '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, 3861 '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, 3862 '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, 3305 3863 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 3306 '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } 3864 '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + 3865 '-').include('-' + (v || "").toUpperCase() + '-'); } 3866 }, 3867 3868 split: function(expression) { 3869 var expressions = []; 3870 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 3871 expressions.push(m[1].strip()); 3872 }); 3873 return expressions; 3307 3874 }, 3308 3875 3309 3876 matchElements: function(elements, expression) { 3310 var matches = new Selector(expression).findElements(), h = Selector.handlers;3877 var matches = $$(expression), h = Selector.handlers; 3311 3878 h.mark(matches); 3312 3879 for (var i = 0, results = [], element; element = elements[i]; i++) 3313 if (element._counted ) results.push(element);3880 if (element._countedByPrototype) results.push(element); 3314 3881 h.unmark(matches); 3315 3882 return results; … … 3324 3891 3325 3892 findChildElements: function(element, expressions) { 3326 var exprs = expressions.join(','), expressions = []; 3327 exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 3328 expressions.push(m[1].strip()); 3329 }); 3893 expressions = Selector.split(expressions.join(',')); 3330 3894 var results = [], h = Selector.handlers; 3331 3895 for (var i = 0, l = expressions.length, selector; i < l; i++) { … … 3337 3901 }); 3338 3902 3903 if (Prototype.Browser.IE) { 3904 Object.extend(Selector.handlers, { 3905 concat: function(a, b) { 3906 for (var i = 0, node; node = b[i]; i++) 3907 if (node.tagName !== "!") a.push(node); 3908 return a; 3909 } 3910 }); 3911 } 3912 3339 3913 function $$() { 3340 3914 return Selector.findChildElements(document, $A(arguments)); 3341 3915 } 3916 3342 3917 var Form = { 3343 3918 reset: function(form) { 3344 $(form).reset(); 3919 form = $(form); 3920 form.reset(); 3345 3921 return form; 3346 3922 }, … … 3348 3924 serializeElements: function(elements, options) { 3349 3925 if (typeof options != 'object') options = { hash: !!options }; 3350 else if ( options.hash === undefined) options.hash = true;3926 else if (Object.isUndefined(options.hash)) options.hash = true; 3351 3927 var key, value, submitted = false, submit = options.submit; 3352 3928 … … 3354 3930 if (!element.disabled && element.name) { 3355 3931 key = element.name; value = $(element).getValue(); 3356 if (value != null && (element.type != 'submit' || (!submitted &&3932 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && 3357 3933 submit !== false && (!submit || key == submit) && (submitted = true)))) { 3358 3934 if (key in result) { 3359 // a key is already present; construct an array of values3360 3935 if (!Object.isArray(result[key])) result[key] = [result[key]]; 3361 3936 result[key].push(value); … … 3377 3952 3378 3953 getElements: function(form) { 3379 return $A($(form).getElementsByTagName('*')).inject([], 3380 function(elements, child) { 3381 if (Form.Element.Serializers[child.tagName.toLowerCase()]) 3382 elements.push(Element.extend(child)); 3383 return elements; 3384 } 3385 ); 3954 var elements = $(form).getElementsByTagName('*'), 3955 element, 3956 arr = [ ], 3957 serializers = Form.Element.Serializers; 3958 for (var i = 0; element = elements[i]; i++) { 3959 arr.push(element); 3960 } 3961 return arr.inject([], function(elements, child) { 3962 if (serializers[child.tagName.toLowerCase()]) 3963 elements.push(Element.extend(child)); 3964 return elements; 3965 }) 3386 3966 }, 3387 3967 … … 3423 4003 3424 4004 return firstByIndex ? firstByIndex : elements.find(function(element) { 3425 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());4005 return /^(?:input|select|textarea)$/i.test(element.tagName); 3426 4006 }); 3427 4007 }, … … 3454 4034 /*--------------------------------------------------------------------------*/ 3455 4035 4036 3456 4037 Form.Element = { 3457 4038 focus: function(element) { … … 3467 4048 3468 4049 Form.Element.Methods = { 4050 3469 4051 serialize: function(element) { 3470 4052 element = $(element); … … 3507 4089 element.focus(); 3508 4090 if (element.select && (element.tagName.toLowerCase() != 'input' || 3509 ! ['button', 'reset', 'submit'].include(element.type)))4091 !(/^(?:button|reset|submit)$/i.test(element.type)))) 3510 4092 element.select(); 3511 4093 } catch (e) { } … … 3515 4097 disable: function(element) { 3516 4098 element = $(element); 3517 element.blur();3518 4099 element.disabled = true; 3519 4100 return element; … … 3530 4111 3531 4112 var Field = Form.Element; 4113 3532 4114 var $F = Form.Element.Methods.getValue; 3533 4115 … … 3546 4128 3547 4129 inputSelector: function(element, value) { 3548 if ( value === undefined) return element.checked ? element.value : null;4130 if (Object.isUndefined(value)) return element.checked ? element.value : null; 3549 4131 else element.checked = !!value; 3550 4132 }, 3551 4133 3552 4134 textarea: function(element, value) { 3553 if ( value === undefined) return element.value;4135 if (Object.isUndefined(value)) return element.value; 3554 4136 else element.value = value; 3555 4137 }, 3556 4138 3557 select: function(element, index) {3558 if ( index === undefined)4139 select: function(element, value) { 4140 if (Object.isUndefined(value)) 3559 4141 return this[element.type == 'select-one' ? 3560 4142 'selectOne' : 'selectMany'](element); 3561 4143 else { 3562 var opt, value, single = !Object.isArray(index);4144 var opt, currentValue, single = !Object.isArray(value); 3563 4145 for (var i = 0, length = element.length; i < length; i++) { 3564 4146 opt = element.options[i]; 3565 value = this.optionValue(opt);4147 currentValue = this.optionValue(opt); 3566 4148 if (single) { 3567 if ( value == index) {4149 if (currentValue == value) { 3568 4150 opt.selected = true; 3569 4151 return; 3570 4152 } 3571 4153 } 3572 else opt.selected = index.include(value);4154 else opt.selected = value.include(currentValue); 3573 4155 } 3574 4156 } … … 3592 4174 3593 4175 optionValue: function(opt) { 3594 // extend element because hasAttribute may not be native3595 4176 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 3596 4177 } … … 3598 4179 3599 4180 /*--------------------------------------------------------------------------*/ 4181 3600 4182 3601 4183 Abstract.TimedObserver = Class.create(PeriodicalExecuter, { … … 3680 4262 } 3681 4263 }); 3682 if (!window.Event) var Event = { }; 3683 3684 Object.extend(Event, { 3685 KEY_BACKSPACE: 8, 3686 KEY_TAB: 9, 3687 KEY_RETURN: 13, 3688 KEY_ESC: 27, 3689 KEY_LEFT: 37, 3690 KEY_UP: 38, 3691 KEY_RIGHT: 39, 3692 KEY_DOWN: 40, 3693 KEY_DELETE: 46, 3694 KEY_HOME: 36, 3695 KEY_END: 35, 3696 KEY_PAGEUP: 33, 3697 KEY_PAGEDOWN: 34, 3698 KEY_INSERT: 45, 3699 3700 cache: { }, 3701 3702 relatedTarget: function(event) { 3703 var element; 3704 switch(event.type) { 3705 case 'mouseover': element = event.fromElement; break; 3706 case 'mouseout': element = event.toElement; break; 3707 default: return null; 3708 } 3709 return Element.extend(element); 3710 } 3711 }); 3712 3713 Event.Methods = (function() { 3714 var isButton; 3715 4264 (function() { 4265 4266 var Event = { 4267 KEY_BACKSPACE: 8, 4268 KEY_TAB: 9, 4269 KEY_RETURN: 13, 4270 KEY_ESC: 27, 4271 KEY_LEFT: 37, 4272 KEY_UP: 38, 4273 KEY_RIGHT: 39, 4274 KEY_DOWN: 40, 4275 KEY_DELETE: 46, 4276 KEY_HOME: 36, 4277 KEY_END: 35, 4278 KEY_PAGEUP: 33, 4279 KEY_PAGEDOWN: 34, 4280 KEY_INSERT: 45, 4281 4282 cache: {} 4283 }; 4284 4285 var docEl = document.documentElement; 4286 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl 4287 && 'onmouseleave' in docEl; 4288 4289 var _isButton; 3716 4290 if (Prototype.Browser.IE) { 3717 4291 var buttonMap = { 0: 1, 1: 4, 2: 2 }; 3718 isButton = function(event, code) {3719 return event.button == buttonMap[code];4292 _isButton = function(event, code) { 4293 return event.button === buttonMap[code]; 3720 4294 }; 3721 3722 4295 } else if (Prototype.Browser.WebKit) { 3723 isButton = function(event, code) {4296 _isButton = function(event, code) { 3724 4297 switch (code) { 3725 4298 case 0: return event.which == 1 && !event.metaKey; … … 3728 4301 } 3729 4302 }; 3730 3731 4303 } else { 3732 isButton = function(event, code) {4304 _isButton = function(event, code) { 3733 4305 return event.which ? (event.which === code + 1) : (event.button === code); 3734 4306 }; 3735 4307 } 3736 4308 3737 return { 3738 isLeftClick: function(event) { return isButton(event, 0) }, 3739 isMiddleClick: function(event) { return isButton(event, 1) }, 3740 isRightClick: function(event) { return isButton(event, 2) }, 3741 3742 element: function(event) { 3743 var node = Event.extend(event).target; 3744 return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); 3745 }, 3746 3747 findElement: function(event, expression) { 3748 var element = Event.element(event); 3749 return element.match(expression) ? element : element.up(expression); 3750 }, 3751 3752 pointer: function(event) { 3753 return { 3754 x: event.pageX || (event.clientX + 3755 (document.documentElement.scrollLeft || document.body.scrollLeft)), 3756 y: event.pageY || (event.clientY + 3757 (document.documentElement.scrollTop || document.body.scrollTop)) 3758 }; 3759 }, 3760 3761 pointerX: function(event) { return Event.pointer(event).x }, 3762 pointerY: function(event) { return Event.pointer(event).y }, 3763 3764 stop: function(event) { 3765 Event.extend(event); 3766 event.preventDefault(); 3767 event.stopPropagation(); 3768 event.stopped = true; 3769 } 4309 function isLeftClick(event) { return _isButton(event, 0) } 4310 4311 function isMiddleClick(event) { return _isButton(event, 1) } 4312 4313 function isRightClick(event) { return _isButton(event, 2) } 4314 4315 function element(event) { 4316 event = Event.extend(event); 4317 4318 var node = event.target, type = event.type, 4319 currentTarget = event.currentTarget; 4320 4321 if (currentTarget && currentTarget.tagName) { 4322 if (type === 'load' || type === 'error' || 4323 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' 4324 && currentTarget.type === 'radio')) 4325 node = currentTarget; 4326 } 4327 4328 if (node.nodeType == Node.TEXT_NODE) 4329 node = node.parentNode; 4330 4331 return Element.extend(node); 4332 } 4333 4334 function findElement(event, expression) { 4335 var element = Event.element(event); 4336 if (!expression) return element; 4337 var elements = [element].concat(element.ancestors()); 4338 return Selector.findElement(elements, expression, 0); 4339 } 4340 4341 function pointer(event) { 4342 return { x: pointerX(event), y: pointerY(event) }; 4343 } 4344 4345 function pointerX(event) { 4346 var docElement = document.documentElement, 4347 body = document.body || { scrollLeft: 0 }; 4348 4349 return event.pageX || (event.clientX + 4350 (docElement.scrollLeft || body.scrollLeft) - 4351 (docElement.clientLeft || 0)); 4352 } 4353 4354 function pointerY(event) { 4355 var docElement = document.documentElement, 4356 body = document.body || { scrollTop: 0 }; 4357 4358 return event.pageY || (event.clientY + 4359 (docElement.scrollTop || body.scrollTop) - 4360 (docElement.clientTop || 0)); 4361 } 4362 4363 4364 function stop(event) { 4365 Event.extend(event); 4366 event.preventDefault(); 4367 event.stopPropagation(); 4368 4369 event.stopped = true; 4370 } 4371 4372 Event.Methods = { 4373 isLeftClick: isLeftClick, 4374 isMiddleClick: isMiddleClick, 4375 isRightClick: isRightClick, 4376 4377 element: element, 4378 findElement: findElement, 4379 4380 pointer: pointer, 4381 pointerX: pointerX, 4382 pointerY: pointerY, 4383 4384 stop: stop 3770 4385 }; 3771 })(); 3772 3773 Event.extend = (function() { 4386 4387 3774 4388 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 3775 4389 m[name] = Event.Methods[name].methodize(); … … 3778 4392 3779 4393 if (Prototype.Browser.IE) { 4394 function _relatedTarget(event) { 4395 var element; 4396 switch (event.type) { 4397 case 'mouseover': element = event.fromElement; break; 4398 case 'mouseout': element = event.toElement; break; 4399 default: return null; 4400 } 4401 return Element.extend(element); 4402 } 4403 3780 4404 Object.extend(methods, { 3781 4405 stopPropagation: function() { this.cancelBubble = true }, 3782 4406 preventDefault: function() { this.returnValue = false }, 3783 inspect: function() { return "[object Event]"}4407 inspect: function() { return '[object Event]' } 3784 4408 }); 3785 4409 3786 return function(event) {4410 Event.extend = function(event, element) { 3787 4411 if (!event) return false; 3788 4412 if (event._extendedByPrototype) return event; … … 3790 4414 event._extendedByPrototype = Prototype.emptyFunction; 3791 4415 var pointer = Event.pointer(event); 4416 3792 4417 Object.extend(event, { 3793 target: event.srcElement ,3794 relatedTarget: Event.relatedTarget(event),4418 target: event.srcElement || element, 4419 relatedTarget: _relatedTarget(event), 3795 4420 pageX: pointer.x, 3796 4421 pageY: pointer.y 3797 4422 }); 4423 3798 4424 return Object.extend(event, methods); 3799 4425 }; 3800 3801 4426 } else { 3802 Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;4427 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; 3803 4428 Object.extend(Event.prototype, methods); 3804 return Prototype.K; 3805 } 4429 Event.extend = Prototype.K; 4430 } 4431 4432 function _createResponder(element, eventName, handler) { 4433 var registry = Element.retrieve(element, 'prototype_event_registry'); 4434 4435 if (Object.isUndefined(registry)) { 4436 CACHE.push(element); 4437 registry = Element.retrieve(element, 'prototype_event_registry', $H()); 4438 } 4439 4440 var respondersForEvent = registry.get(eventName); 4441 if (Object.isUndefined(respondersForEvent)) { 4442 respondersForEvent = []; 4443 registry.set(eventName, respondersForEvent); 4444 } 4445 4446 if (respondersForEvent.pluck('handler').include(handler)) return false; 4447 4448 var responder; 4449 if (eventName.include(":")) { 4450 responder = function(event) { 4451 if (Object.isUndefined(event.eventName)) 4452 return false; 4453 4454 if (event.eventName !== eventName) 4455 return false; 4456 4457 Event.extend(event, element); 4458 handler.call(element, event); 4459 }; 4460 } else { 4461 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && 4462 (eventName === "mouseenter" || eventName === "mouseleave")) { 4463 if (eventName === "mouseenter" || eventName === "mouseleave") { 4464 responder = function(event) { 4465 Event.extend(event, element); 4466 4467 var parent = event.relatedTarget; 4468 while (parent && parent !== element) { 4469 try { parent = parent.parentNode; } 4470 catch(e) { parent = element; } 4471 } 4472 4473 if (parent === element) return; 4474 4475 handler.call(element, event); 4476 }; 4477 } 4478 } else { 4479 responder = function(event) { 4480 Event.extend(event, element); 4481 handler.call(element, event); 4482 }; 4483 } 4484 } 4485 4486 responder.handler = handler; 4487 respondersForEvent.push(responder); 4488 return responder; 4489 } 4490 4491 function _destroyCache() { 4492 for (var i = 0, length = CACHE.length; i < length; i++) { 4493 Event.stopObserving(CACHE[i]); 4494 CACHE[i] = null; 4495 } 4496 } 4497 4498 var CACHE = []; 4499 4500 if (Prototype.Browser.IE) 4501 window.attachEvent('onunload', _destroyCache); 4502 4503 if (Prototype.Browser.WebKit) 4504 window.addEventListener('unload', Prototype.emptyFunction, false); 4505 4506 4507 var _getDOMEventName = Prototype.K; 4508 4509 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { 4510 _getDOMEventName = function(eventName) { 4511 var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; 4512 return eventName in translations ? translations[eventName] : eventName; 4513 }; 4514 } 4515 4516 function observe(element, eventName, handler) { 4517 element = $(element); 4518 4519 var responder = _createResponder(element, eventName, handler); 4520 4521 if (!responder) return element; 4522 4523 if (eventName.include(':')) { 4524 if (element.addEventListener) 4525 element.addEventListener("dataavailable", responder, false); 4526 else { 4527 element.attachEvent("ondataavailable", responder); 4528 element.attachEvent("onfilterchange", responder); 4529 } 4530 } else { 4531 var actualEventName = _getDOMEventName(eventName); 4532 4533 if (element.addEventListener) 4534 element.addEventListener(actualEventName, responder, false); 4535 else 4536 element.attachEvent("on" + actualEventName, responder); 4537 } 4538 4539 return element; 4540 } 4541 4542 function stopObserving(element, eventName, handler) { 4543 element = $(element); 4544 4545 var registry = Element.retrieve(element, 'prototype_event_registry'); 4546 4547 if (Object.isUndefined(registry)) return element; 4548 4549 if (eventName && !handler) { 4550 var responders = registry.get(eventName); 4551 4552 if (Object.isUndefined(responders)) return element; 4553 4554 responders.each( function(r) { 4555 Element.stopObserving(element, eventName, r.handler); 4556 }); 4557 return element; 4558 } else if (!eventName) { 4559 registry.each( function(pair) { 4560 var eventName = pair.key, responders = pair.value; 4561 4562 responders.each( function(r) { 4563 Element.stopObserving(element, eventName, r.handler); 4564 }); 4565 }); 4566 return element; 4567 } 4568 4569 var responders = registry.get(eventName); 4570 4571 if (!responders) return; 4572 4573 var responder = responders.find( function(r) { return r.handler === handler; }); 4574 if (!responder) return element; 4575 4576 var actualEventName = _getDOMEventName(eventName); 4577 4578 if (eventName.include(':')) { 4579 if (element.removeEventListener) 4580 element.removeEventListener("dataavailable", responder, false); 4581 else { 4582 element.detachEvent("ondataavailable", responder); 4583 element.detachEvent("onfilterchange", responder); 4584 } 4585 } else { 4586 if (element.removeEventListener) 4587 element.removeEventListener(actualEventName, responder, false); 4588 else 4589 element.detachEvent('on' + actualEventName, responder); 4590 } 4591 4592 registry.set(eventName, responders.without(responder)); 4593 4594 return element; 4595 } 4596 4597 function fire(element, eventName, memo, bubble) { 4598 element = $(element); 4599 4600 if (Object.isUndefined(bubble)) 4601 bubble = true; 4602 4603 if (element == document && document.createEvent && !element.dispatchEvent) 4604 element = document.documentElement; 4605 4606 var event; 4607 if (document.createEvent) { 4608 event = document.createEvent('HTMLEvents'); 4609 event.initEvent('dataavailable', true, true); 4610 } else { 4611 event = document.createEventObject(); 4612 event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; 4613 } 4614 4615 event.eventName = eventName; 4616 event.memo = memo || { }; 4617 4618 if (document.createEvent) 4619 element.dispatchEvent(event); 4620 else 4621 element.fireEvent(event.eventType, event); 4622 4623 return Event.extend(event); 4624 } 4625 4626 4627 Object.extend(Event, Event.Methods); 4628 4629 Object.extend(Event, { 4630 fire: fire, 4631 observe: observe, 4632 stopObserving: stopObserving 4633 }); 4634 4635 Element.addMethods({ 4636 fire: fire, 4637 4638 observe: observe, 4639 4640 stopObserving: stopObserving 4641 }); 4642 4643 Object.extend(document, { 4644 fire: fire.methodize(), 4645 4646 observe: observe.methodize(), 4647 4648 stopObserving: stopObserving.methodize(), 4649 4650 loaded: false 4651 }); 4652 4653 if (window.Event) Object.extend(window.Event, Event); 4654 else window.Event = Event; 3806 4655 })(); 3807 3808 Object.extend(Event, (function() {3809 var cache = Event.cache;3810 3811 function getEventID(element) {3812 if (element._eventID) return element._eventID;3813 arguments.callee.id = arguments.callee.id || 1;3814 return element._eventID = ++arguments.callee.id;3815 }3816 3817 function getDOMEventName(eventName) {3818 if (eventName && eventName.include(':')) return "dataavailable";3819 return eventName;3820 }3821 3822 function getCacheForID(id) {3823 return cache[id] = cache[id] || { };3824 }3825 3826 function getWrappersForEventName(id, eventName) {3827 var c = getCacheForID(id);3828 return c[eventName] = c[eventName] || [];3829 }3830 3831 function createWrapper(element, eventName, handler) {3832 var id = getEventID(element);3833 var c = getWrappersForEventName(id, eventName);3834 if (c.pluck("handler").include(handler)) return false;3835 3836 var wrapper = function(event) {3837 if (!Event || !Event.extend ||3838 (event.eventName && event.eventName != eventName))3839 return false;3840 3841 Event.extend(event);3842 handler.call(element, event)3843 };3844 3845 wrapper.handler = handler;3846 c.push(wrapper);3847 return wrapper;3848 }3849 3850 function findWrapper(id, eventName, handler) {3851 var c = getWrappersForEventName(id, eventName);3852 return c.find(function(wrapper) { return wrapper.handler == handler });3853 }3854 3855 function destroyWrapper(id, eventName, handler) {3856 var c = getCacheForID(id);3857 if (!c[eventName]) return false;3858 c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));3859 }3860 3861 function destroyCache() {3862 for (var id in cache)3863 for (var eventName in cache[id])3864 cache[id][eventName] = null;3865 }3866 3867 if (window.attachEvent) {3868 window.attachEvent("onunload", destroyCache);3869 }3870 3871 return {3872 observe: function(element, eventName, handler) {3873 element = $(element);3874 var name = getDOMEventName(eventName);3875 3876 var wrapper = createWrapper(element, eventName, handler);3877 if (!wrapper) return element;3878 3879 if (element.addEventListener) {3880 element.addEventListener(name, wrapper, false);3881 } else {3882 element.attachEvent("on" + name, wrapper);3883 }3884 3885 return element;3886 },3887 3888 stopObserving: function(element, eventName, handler) {3889 element = $(element);3890 var id = getEventID(element), name = getDOMEventName(eventName);3891 3892 if (!handler && eventName) {3893 getWrappersForEventName(id, eventName).each(function(wrapper) {3894 element.stopObserving(eventName, wrapper.handler);3895 });3896 return element;3897 3898 } else if (!eventName) {3899 Object.keys(getCacheForID(id)).each(function(eventName) {3900 element.stopObserving(eventName);3901 });3902 return element;3903 }3904 3905 var wrapper = findWrapper(id, eventName, handler);3906 if (!wrapper) return element;3907 3908 if (element.removeEventListener) {3909 element.removeEventListener(name, wrapper, false);3910 } else {3911 element.detachEvent("on" + name, wrapper);3912 }3913 3914 destroyWrapper(id, eventName, handler);3915 3916 return element;3917 },3918 3919 fire: function(element, eventName, memo) {3920 element = $(element);3921 if (element == document && document.createEvent && !element.dispatchEvent)3922 element = document.documentElement;3923 3924 if (document.createEvent) {3925 var event = document.createEvent("HTMLEvents");3926 event.initEvent("dataavailable", true, true);3927 } else {3928 var event = document.createEventObject();3929 event.eventType = "ondataavailable";3930 }3931 3932 event.eventName = eventName;3933 event.memo = memo || { };3934 3935 if (document.createEvent) {3936 element.dispatchEvent(event);3937 } else {3938 element.fireEvent(event.eventType, event);3939 }3940 3941 return event;3942 }3943 };3944 })());3945 3946 Object.extend(Event, Event.Methods);3947 3948 Element.addMethods({3949 fire: Event.fire,3950 observe: Event.observe,3951 stopObserving: Event.stopObserving3952 });3953 3954 Object.extend(document, {3955 fire: Element.Methods.fire.methodize(),3956 observe: Element.Methods.observe.methodize(),3957 stopObserving: Element.Methods.stopObserving.methodize()3958 });3959 4656 3960 4657 (function() { 3961 4658 /* Support for the DOMContentLoaded event is based on work by Dan Webb, 3962 Matthias Miller, Dean Edwards and John Resig. */3963 3964 var timer , fired = false;4659 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ 4660 4661 var timer; 3965 4662 3966 4663 function fireContentLoadedEvent() { 3967 if (fired) return; 3968 if (timer) window.clearInterval(timer); 3969 document.fire("dom:loaded"); 3970 fired = true; 4664 if (document.loaded) return; 4665 if (timer) window.clearTimeout(timer); 4666 document.loaded = true; 4667 document.fire('dom:loaded'); 4668 } 4669 4670 function checkReadyState() { 4671 if (document.readyState === 'complete') { 4672 document.stopObserving('readystatechange', checkReadyState); 4673 fireContentLoadedEvent(); 4674 } 4675 } 4676 4677 function pollDoScroll() { 4678 try { document.documentElement.doScroll('left'); } 4679 catch(e) { 4680 timer = pollDoScroll.defer(); 4681 return; 4682 } 4683 fireContentLoadedEvent(); 3971 4684 } 3972 4685 3973 4686 if (document.addEventListener) { 3974 if (Prototype.Browser.WebKit) { 3975 timer = window.setInterval(function() { 3976 if (/loaded|complete/.test(document.readyState)) 3977 fireContentLoadedEvent(); 3978 }, 0); 3979 3980 Event.observe(window, "load", fireContentLoadedEvent); 3981 3982 } else { 3983 document.addEventListener("DOMContentLoaded", 3984 fireContentLoadedEvent, false); 3985 } 3986 4687 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); 3987 4688 } else { 3988 document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); 3989 $("__onDOMContentLoaded").onreadystatechange = function() { 3990 if (this.readyState == "complete") { 3991 this.onreadystatechange = null; 3992 fireContentLoadedEvent(); 3993 } 3994 }; 3995 } 4689 document.observe('readystatechange', checkReadyState); 4690 if (window == top) 4691 timer = pollDoScroll.defer(); 4692 } 4693 4694 Event.observe(window, 'load', fireContentLoadedEvent); 3996 4695 })(); 4696 4697 Element.addMethods(); 4698 3997 4699 /*------------------------------- DEPRECATED -------------------------------*/ 3998 4700 … … 4023 4725 var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 4024 4726 4025 // This should be moved to script.aculo.us; notice the deprecated methods4026 // further below, that map to the newer Element methods.4027 4727 var Position = { 4028 // set to true if needed, warning: firefox performance problems4029 // NOT neeeded for page scrolling, only if draggable contained in4030 // scrollable elements4031 4728 includeScrollOffsets: false, 4032 4729 4033 // must be called before calling withinIncludingScrolloffset, every time the4034 // page is scrolled4035 4730 prepare: function() { 4036 4731 this.deltaX = window.pageXOffset … … 4044 4739 }, 4045 4740 4046 // caches x/y coordinate pair to use with overlap4047 4741 within: function(element, x, y) { 4048 4742 if (this.includeScrollOffsets) … … 4071 4765 }, 4072 4766 4073 // within must be called directly before4074 4767 overlap: function(mode, element) { 4075 4768 if (!mode) return 0; … … 4082 4775 }, 4083 4776 4084 // Deprecation layer -- use newer Element methods now (1.5.2).4085 4777 4086 4778 cumulativeOffset: Element.Methods.cumulativeOffset, … … 4181 4873 4182 4874 /*--------------------------------------------------------------------------*/ 4183 4184 Element.addMethods(); -
trunk/wp-includes/js/scriptaculous/MIT-LICENSE
r7131 r12557 1 Copyright (c) 2005-200 7Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)1 Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 2 2 3 3 Permission is hereby granted, free of charge, to any person obtaining -
trunk/wp-includes/js/scriptaculous/builder.js
r7131 r12557 1 // script.aculo.us builder.js v1.8. 0, Tue Nov 06 15:01:40 +0300 20071 // script.aculo.us builder.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 2 2 3 // Copyright (c) 2005-200 7Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)3 // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 4 // 5 5 // script.aculo.us is freely distributable under the terms of an MIT-style license. … … 27 27 node: function(elementName) { 28 28 elementName = elementName.toUpperCase(); 29 29 30 30 // try innerHTML approach 31 31 var parentTag = this.NODEMAP[elementName] || 'div'; … … 35 35 } catch(e) {} 36 36 var element = parentElement.firstChild || null; 37 37 38 38 // see if browser added wrapping tags 39 39 if(element && (element.tagName.toUpperCase() != elementName)) 40 40 element = element.getElementsByTagName(elementName)[0]; 41 41 42 42 // fallback to createElement approach 43 43 if(!element) element = document.createElement(elementName); 44 44 45 45 // abort if nothing could be created 46 46 if(!element) return; … … 63 63 if(!element) { 64 64 element = document.createElement(elementName); 65 for(attr in arguments[1]) 65 for(attr in arguments[1]) 66 66 element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; 67 67 } … … 69 69 element = parentElement.getElementsByTagName(elementName)[0]; 70 70 } 71 } 71 } 72 72 73 73 // text, or array of children … … 75 75 this._children(element, arguments[2]); 76 76 77 return element;77 return $(element); 78 78 }, 79 79 _text: function(text) { … … 101 101 children.flatten().each( function(e) { 102 102 if(typeof e=='object') 103 element.appendChild(e) 103 element.appendChild(e); 104 104 else 105 105 if(Builder._isStringOrNumber(e)) … … 118 118 return element.down(); 119 119 }, 120 dump: function(scope) { 121 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 122 120 dump: function(scope) { 121 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 122 123 123 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + 124 124 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + … … 127 127 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ 128 128 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); 129 130 tags.each( function(tag){ 131 scope[tag] = function() { 132 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 133 } 129 130 tags.each( function(tag){ 131 scope[tag] = function() { 132 return Builder.node.apply(Builder, [tag].concat($A(arguments))); 133 }; 134 134 }); 135 135 } 136 } 136 }; -
trunk/wp-includes/js/scriptaculous/controls.js
r7131 r12557 1 // script.aculo.us controls.js v1.8. 0, Tue Nov 06 15:01:40 +0300 20072 3 // Copyright (c) 2005-200 7Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)4 // (c) 2005-200 7Ivan Krstic (http://blogs.law.harvard.edu/ivan)5 // (c) 2005-200 7Jon Tirsen (http://www.tirsen.com)1 // script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 2 3 // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 // (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) 5 // (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) 6 6 // Contributors: 7 7 // Richard Livsey 8 8 // Rahul Bhargava 9 9 // Rob Wills 10 // 10 // 11 11 // script.aculo.us is freely distributable under the terms of an MIT-style license. 12 12 // For details, see the script.aculo.us web site: http://script.aculo.us/ 13 13 14 // Autocompleter.Base handles all the autocompletion functionality 14 // Autocompleter.Base handles all the autocompletion functionality 15 15 // that's independent of the data source for autocompletion. This 16 16 // includes drawing the autocompletion menu, observing keyboard 17 17 // and mouse events, and similar. 18 18 // 19 // Specific autocompleters need to provide, at the very least, 19 // Specific autocompleters need to provide, at the very least, 20 20 // a getUpdatedChoices function that will be invoked every time 21 // the text inside the monitored textbox changes. This method 21 // the text inside the monitored textbox changes. This method 22 22 // should get the text for which to provide autocompletion by 23 23 // invoking this.getToken(), NOT by directly accessing … … 33 33 // Additionally, ',' in the above example can be replaced with 34 34 // a token array, e.g. { tokens: [',', '\n'] } which 35 // enables autocompletion on multiple tokens. This is most 36 // useful when one of the tokens is \n (a newline), as it 35 // enables autocompletion on multiple tokens. This is most 36 // useful when one of the tokens is \n (a newline), as it 37 37 // allows smart autocompletion after linebreaks. 38 38 … … 40 40 throw("controls.js requires including script.aculo.us' effects.js library"); 41 41 42 var Autocompleter = { } 42 var Autocompleter = { }; 43 43 Autocompleter.Base = Class.create({ 44 44 baseInitialize: function(element, update, options) { 45 element = $(element) 46 this.element = element; 47 this.update = $(update); 48 this.hasFocus = false; 49 this.changed = false; 50 this.active = false; 51 this.index = 0; 45 element = $(element); 46 this.element = element; 47 this.update = $(update); 48 this.hasFocus = false; 49 this.changed = false; 50 this.active = false; 51 this.index = 0; 52 52 this.entryCount = 0; 53 53 this.oldElementValue = this.element.value; … … 62 62 this.options.frequency = this.options.frequency || 0.4; 63 63 this.options.minChars = this.options.minChars || 1; 64 this.options.onShow = this.options.onShow || 65 function(element, update){ 64 this.options.onShow = this.options.onShow || 65 function(element, update){ 66 66 if(!update.style.position || update.style.position=='absolute') { 67 67 update.style.position = 'absolute'; 68 68 Position.clone(element, update, { 69 setHeight: false, 69 setHeight: false, 70 70 offsetTop: element.offsetHeight 71 71 }); … … 73 73 Effect.Appear(update,{duration:0.15}); 74 74 }; 75 this.options.onHide = this.options.onHide || 75 this.options.onHide = this.options.onHide || 76 76 function(element, update){ new Effect.Fade(update,{duration:0.15}) }; 77 77 78 if(typeof(this.options.tokens) == 'string') 78 if(typeof(this.options.tokens) == 'string') 79 79 this.options.tokens = new Array(this.options.tokens); 80 80 // Force carriage returns as token delimiters anyway … … 83 83 84 84 this.observer = null; 85 85 86 86 this.element.setAttribute('autocomplete','off'); 87 87 … … 89 89 90 90 Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); 91 Event.observe(this.element, 'key press', this.onKeyPress.bindAsEventListener(this));91 Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); 92 92 }, 93 93 94 94 show: function() { 95 95 if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); 96 if(!this.iefix && 96 if(!this.iefix && 97 97 (Prototype.Browser.IE) && 98 98 (Element.getStyle(this.update, 'position')=='absolute')) { 99 new Insertion.After(this.update, 99 new Insertion.After(this.update, 100 100 '<iframe id="' + this.update.id + '_iefix" '+ 101 101 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + … … 105 105 if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); 106 106 }, 107 107 108 108 fixIEOverlapping: function() { 109 109 Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); … … 145 145 this.markPrevious(); 146 146 this.render(); 147 if(Prototype.Browser.WebKit)Event.stop(event);147 Event.stop(event); 148 148 return; 149 149 case Event.KEY_DOWN: 150 150 this.markNext(); 151 151 this.render(); 152 if(Prototype.Browser.WebKit)Event.stop(event);152 Event.stop(event); 153 153 return; 154 154 } 155 else 156 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 155 else 156 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 157 157 (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; 158 158 … … 161 161 162 162 if(this.observer) clearTimeout(this.observer); 163 this.observer = 163 this.observer = 164 164 setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); 165 165 }, … … 173 173 onHover: function(event) { 174 174 var element = Event.findElement(event, 'LI'); 175 if(this.index != element.autocompleteIndex) 175 if(this.index != element.autocompleteIndex) 176 176 { 177 177 this.index = element.autocompleteIndex; … … 180 180 Event.stop(event); 181 181 }, 182 182 183 183 onClick: function(event) { 184 184 var element = Event.findElement(event, 'LI'); … … 187 187 this.hide(); 188 188 }, 189 189 190 190 onBlur: function(event) { 191 191 // needed to make click events working 192 192 setTimeout(this.hide.bind(this), 250); 193 193 this.hasFocus = false; 194 this.active = false; 195 }, 196 194 this.active = false; 195 }, 196 197 197 render: function() { 198 198 if(this.entryCount > 0) { 199 199 for (var i = 0; i < this.entryCount; i++) 200 this.index==i ? 201 Element.addClassName(this.getEntry(i),"selected") : 200 this.index==i ? 201 Element.addClassName(this.getEntry(i),"selected") : 202 202 Element.removeClassName(this.getEntry(i),"selected"); 203 if(this.hasFocus) { 203 if(this.hasFocus) { 204 204 this.show(); 205 205 this.active = true; … … 210 210 } 211 211 }, 212 212 213 213 markPrevious: function() { 214 if(this.index > 0) this.index-- 214 if(this.index > 0) this.index--; 215 215 else this.index = this.entryCount-1; 216 216 this.getEntry(this.index).scrollIntoView(true); 217 217 }, 218 218 219 219 markNext: function() { 220 if(this.index < this.entryCount-1) this.index++ 220 if(this.index < this.entryCount-1) this.index++; 221 221 else this.index = 0; 222 222 this.getEntry(this.index).scrollIntoView(false); 223 223 }, 224 224 225 225 getEntry: function(index) { 226 226 return this.update.firstChild.childNodes[index]; 227 227 }, 228 228 229 229 getCurrentEntry: function() { 230 230 return this.getEntry(this.index); 231 231 }, 232 232 233 233 selectEntry: function() { 234 234 this.active = false; … … 247 247 } else 248 248 value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); 249 249 250 250 var bounds = this.getTokenBounds(); 251 251 if (bounds[0] != -1) { … … 260 260 this.oldElementValue = this.element.value; 261 261 this.element.focus(); 262 262 263 263 if (this.options.afterUpdateElement) 264 264 this.options.afterUpdateElement(this.element, selectedElement); … … 272 272 273 273 if(this.update.firstChild && this.update.down().childNodes) { 274 this.entryCount = 274 this.entryCount = 275 275 this.update.down().childNodes.length; 276 276 for (var i = 0; i < this.entryCount; i++) { … … 279 279 this.addObservers(entry); 280 280 } 281 } else { 281 } else { 282 282 this.entryCount = 0; 283 283 } … … 285 285 this.stopIndicator(); 286 286 this.index = 0; 287 287 288 288 if(this.entryCount==1 && this.options.autoSelect) { 289 289 this.selectEntry(); … … 301 301 302 302 onObserverEvent: function() { 303 this.changed = false; 303 this.changed = false; 304 304 this.tokenBounds = null; 305 305 if(this.getToken().length>=this.options.minChars) { … … 354 354 getUpdatedChoices: function() { 355 355 this.startIndicator(); 356 357 var entry = encodeURIComponent(this.options.paramName) + '=' + 356 357 var entry = encodeURIComponent(this.options.paramName) + '=' + 358 358 encodeURIComponent(this.getToken()); 359 359 … … 361 361 this.options.callback(this.element, entry) : entry; 362 362 363 if(this.options.defaultParams) 363 if(this.options.defaultParams) 364 364 this.options.parameters += '&' + this.options.defaultParams; 365 365 366 366 new Ajax.Request(this.url, this.options); 367 367 }, … … 385 385 // 386 386 // - partialSearch - If false, the autocompleter will match entered 387 // text only at the beginning of strings in the 387 // text only at the beginning of strings in the 388 388 // autocomplete array. Defaults to true, which will 389 389 // match text at the beginning of any *word* in the … … 402 402 // Defaults to true. 403 403 // 404 // It's possible to pass in a custom function as the 'selector' 404 // It's possible to pass in a custom function as the 'selector' 405 405 // option, if you prefer to write your own autocompletion logic. 406 406 // In that case, the other options above will not apply unless … … 430 430 var count = 0; 431 431 432 for (var i = 0; i < instance.options.array.length && 433 ret.length < instance.options.choices ; i++) { 432 for (var i = 0; i < instance.options.array.length && 433 ret.length < instance.options.choices ; i++) { 434 434 435 435 var elem = instance.options.array[i]; 436 var foundPos = instance.options.ignoreCase ? 437 elem.toLowerCase().indexOf(entry.toLowerCase()) : 436 var foundPos = instance.options.ignoreCase ? 437 elem.toLowerCase().indexOf(entry.toLowerCase()) : 438 438 elem.indexOf(entry); 439 439 440 440 while (foundPos != -1) { 441 if (foundPos == 0 && elem.length != entry.length) { 442 ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 441 if (foundPos == 0 && elem.length != entry.length) { 442 ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 443 443 elem.substr(entry.length) + "</li>"); 444 444 break; 445 } else if (entry.length >= instance.options.partialChars && 445 } else if (entry.length >= instance.options.partialChars && 446 446 instance.options.partialSearch && foundPos != -1) { 447 447 if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { … … 453 453 } 454 454 455 foundPos = instance.options.ignoreCase ? 456 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 455 foundPos = instance.options.ignoreCase ? 456 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 457 457 elem.indexOf(entry, foundPos + 1); 458 458 … … 460 460 } 461 461 if (partial.length) 462 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) 462 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); 463 463 return "<ul>" + ret.join('') + "</ul>"; 464 464 } … … 477 477 Field.activate(field); 478 478 }, 1); 479 } 479 }; 480 480 481 481 Ajax.InPlaceEditor = Class.create({ … … 607 607 }, 608 608 getText: function() { 609 return this.element.innerHTML ;609 return this.element.innerHTML.unescapeHTML(); 610 610 }, 611 611 handleAJAXFailure: function(transport) { … … 783 783 var js = transport.responseText.strip(); 784 784 if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check 785 throw 'Server returned an invalid collection representation.';785 throw('Server returned an invalid collection representation.'); 786 786 this._collection = eval(js); 787 787 this.checkForExternalText(); … … 940 940 }; 941 941 942 // Delayed observer, like Form.Element.Observer, 942 // Delayed observer, like Form.Element.Observer, 943 943 // but waits for delay after last key input 944 944 // Ideal for live-search fields … … 950 950 this.callback = callback; 951 951 this.timer = null; 952 this.lastValue = $F(this.element); 952 this.lastValue = $F(this.element); 953 953 Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); 954 954 }, -
trunk/wp-includes/js/scriptaculous/dragdrop.js
r7131 r12557 1 // script.aculo.us dragdrop.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007 2 3 // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 // (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) 5 // 1 // script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 2 3 // Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 4 // 6 5 // script.aculo.us is freely distributable under the terms of an MIT-style license. 7 6 // For details, see the script.aculo.us web site: http://script.aculo.us/ … … 35 34 } 36 35 } 37 36 38 37 if(options.accept) options.accept = [options.accept].flatten(); 39 38 … … 43 42 this.drops.push(options); 44 43 }, 45 44 46 45 findDeepestChild: function(drops) { 47 46 deepest = drops[0]; 48 47 49 48 for (i = 1; i < drops.length; ++i) 50 49 if (Element.isParent(drops[i].element, deepest.element)) 51 50 deepest = drops[i]; 52 51 53 52 return deepest; 54 53 }, … … 57 56 var containmentNode; 58 57 if(drop.tree) { 59 containmentNode = element.treeNode; 58 containmentNode = element.treeNode; 60 59 } else { 61 60 containmentNode = element.parentNode; … … 63 62 return drop._containers.detect(function(c) { return containmentNode == c }); 64 63 }, 65 64 66 65 isAffected: function(point, element, drop) { 67 66 return ( … … 70 69 this.isContained(element, drop)) && 71 70 ((!drop.accept) || 72 (Element.classNames(element).detect( 71 (Element.classNames(element).detect( 73 72 function(v) { return drop.accept.include(v) } ) )) && 74 73 Position.within(drop.element, point[0], point[1]) ); … … 90 89 if(!this.drops.length) return; 91 90 var drop, affected = []; 92 91 93 92 this.drops.each( function(drop) { 94 93 if(Droppables.isAffected(point, element, drop)) 95 94 affected.push(drop); 96 95 }); 97 96 98 97 if(affected.length>0) 99 98 drop = Droppables.findDeepestChild(affected); … … 104 103 if(drop.onHover) 105 104 drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); 106 105 107 106 if (drop != this.last_active) Droppables.activate(drop); 108 107 } … … 115 114 if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) 116 115 if (this.last_active.onDrop) { 117 this.last_active.onDrop(element, this.last_active.element, event); 118 return true; 116 this.last_active.onDrop(element, this.last_active.element, event); 117 return true; 119 118 } 120 119 }, … … 124 123 this.deactivate(this.last_active); 125 124 } 126 } 125 }; 127 126 128 127 var Draggables = { 129 128 drags: [], 130 129 observers: [], 131 130 132 131 register: function(draggable) { 133 132 if(this.drags.length == 0) { … … 135 134 this.eventMouseMove = this.updateDrag.bindAsEventListener(this); 136 135 this.eventKeypress = this.keyPress.bindAsEventListener(this); 137 136 138 137 Event.observe(document, "mouseup", this.eventMouseUp); 139 138 Event.observe(document, "mousemove", this.eventMouseMove); … … 142 141 this.drags.push(draggable); 143 142 }, 144 143 145 144 unregister: function(draggable) { 146 145 this.drags = this.drags.reject(function(d) { return d==draggable }); … … 151 150 } 152 151 }, 153 152 154 153 activate: function(draggable) { 155 if(draggable.options.delay) { 156 this._timeout = setTimeout(function() { 157 Draggables._timeout = null; 158 window.focus(); 159 Draggables.activeDraggable = draggable; 160 }.bind(this), draggable.options.delay); 154 if(draggable.options.delay) { 155 this._timeout = setTimeout(function() { 156 Draggables._timeout = null; 157 window.focus(); 158 Draggables.activeDraggable = draggable; 159 }.bind(this), draggable.options.delay); 161 160 } else { 162 161 window.focus(); // allows keypress events if window isn't currently focused, fails for Safari … … 164 163 } 165 164 }, 166 165 167 166 deactivate: function() { 168 167 this.activeDraggable = null; 169 168 }, 170 169 171 170 updateDrag: function(event) { 172 171 if(!this.activeDraggable) return; … … 176 175 if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; 177 176 this._lastPointer = pointer; 178 177 179 178 this.activeDraggable.updateDrag(event, pointer); 180 179 }, 181 180 182 181 endDrag: function(event) { 183 if(this._timeout) { 184 clearTimeout(this._timeout); 185 this._timeout = null; 182 if(this._timeout) { 183 clearTimeout(this._timeout); 184 this._timeout = null; 186 185 } 187 186 if(!this.activeDraggable) return; … … 190 189 this.activeDraggable = null; 191 190 }, 192 191 193 192 keyPress: function(event) { 194 193 if(this.activeDraggable) 195 194 this.activeDraggable.keyPress(event); 196 195 }, 197 196 198 197 addObserver: function(observer) { 199 198 this.observers.push(observer); 200 199 this._cacheObserverCallbacks(); 201 200 }, 202 201 203 202 removeObserver: function(element) { // element instead of observer fixes mem leaks 204 203 this.observers = this.observers.reject( function(o) { return o.element==element }); 205 204 this._cacheObserverCallbacks(); 206 205 }, 207 206 208 207 notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' 209 208 if(this[eventName+'Count'] > 0) … … 213 212 if(draggable.options[eventName]) draggable.options[eventName](draggable, event); 214 213 }, 215 214 216 215 _cacheObserverCallbacks: function() { 217 216 ['onStart','onEnd','onDrag'].each( function(eventName) { … … 221 220 }); 222 221 } 223 } 222 }; 224 223 225 224 /*--------------------------------------------------------------------------*/ … … 237 236 endeffect: function(element) { 238 237 var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; 239 new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 238 new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 240 239 queue: {scope:'_draggable', position:'end'}, 241 afterFinish: function(){ 242 Draggable._dragging[element] = false 240 afterFinish: function(){ 241 Draggable._dragging[element] = false 243 242 }