Changeset 5913
- Timestamp:
- Mar 21, 2008, 4:28:34 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
OpenPNE/branches/work/ebihara/prj_deco_diary/public_html/js/prototype.js
r1088 r5913 1 /* Prototype JavaScript framework, version 1. 4.02 * (c) 2005 Sam Stephenson <sam@conio.net>1 /* Prototype JavaScript framework, version 1.6.0 2 * (c) 2005-2007 Sam Stephenson 3 3 * 4 4 * Prototype is freely distributable under the terms of an MIT-style license. 5 * For details, see the Prototype web site: http:// prototype.conio.net/5 * For details, see the Prototype web site: http://www.prototypejs.org/ 6 6 * 7 /*--------------------------------------------------------------------------*/7 *--------------------------------------------------------------------------*/ 8 8 9 9 var Prototype = { 10 Version: '1.4.0', 11 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 12 13 emptyFunction: function() {}, 14 K: function(x) {return x} 15 } 16 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 }, 19 20 BrowserFeatures: { 21 XPath: !!document.evaluate, 22 ElementExtensions: !!window.HTMLElement, 23 SpecificElementExtensions: 24 document.createElement('div').__proto__ && 25 document.createElement('div').__proto__ !== 26 document.createElement('form').__proto__ 27 }, 28 29 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', 30 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, 31 32 emptyFunction: function() { }, 33 K: function(x) { return x } 34 }; 35 36 if (Prototype.Browser.MobileSafari) 37 Prototype.BrowserFeatures.SpecificElementExtensions = false; 38 39 if (Prototype.Browser.WebKit) 40 Prototype.BrowserFeatures.XPath = false; 41 42 /* Based on Alex Arnell's inheritance implementation. */ 17 43 var Class = { 18 44 create: function() { 45 var parent = null, properties = $A(arguments); 46 if (Object.isFunction(properties[0])) 47 parent = properties.shift(); 48 49 function klass() { 50 this.initialize.apply(this, arguments); 51 } 52 53 Object.extend(klass, Class.Methods); 54 klass.superclass = parent; 55 klass.subclasses = []; 56 57 if (parent) { 58 var subclass = function() { }; 59 subclass.prototype = parent.prototype; 60 klass.prototype = new subclass; 61 parent.subclasses.push(klass); 62 } 63 64 for (var i = 0; i < properties.length; i++) 65 klass.addMethods(properties[i]); 66 67 if (!klass.prototype.initialize) 68 klass.prototype.initialize = Prototype.emptyFunction; 69 70 klass.prototype.constructor = klass; 71 72 return klass; 73 } 74 }; 75 76 Class.Methods = { 77 addMethods: function(source) { 78 var ancestor = this.superclass && this.superclass.prototype; 79 var properties = Object.keys(source); 80 81 if (!Object.keys({ toString: true }).length) 82 properties.push("toString", "valueOf"); 83 84 for (var i = 0, length = properties.length; i < length; i++) { 85 var property = properties[i], value = source[property]; 86 if (ancestor && Object.isFunction(value) && 87 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 }); 94 } 95 this.prototype[property] = value; 96 } 97 98 return this; 99 } 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) { 112 try { 113 if (object === undefined) return 'undefined'; 114 if (object === null) return 'null'; 115 return object.inspect ? object.inspect() : object.toString(); 116 } catch (e) { 117 if (e instanceof RangeError) return '...'; 118 throw e; 119 } 120 }, 121 122 toJSON: function(object) { 123 var type = typeof object; 124 switch (type) { 125 case 'undefined': 126 case 'function': 127 case 'unknown': return; 128 case 'boolean': return object.toString(); 129 } 130 131 if (object === null) return 'null'; 132 if (object.toJSON) return object.toJSON(); 133 if (Object.isElement(object)) return; 134 135 var results = []; 136 for (var property in object) { 137 var value = Object.toJSON(object[property]); 138 if (value !== undefined) 139 results.push(property.toJSON() + ': ' + value); 140 } 141 142 return '{' + results.join(', ') + '}'; 143 }, 144 145 toQueryString: function(object) { 146 return $H(object).toQueryString(); 147 }, 148 149 toHTML: function(object) { 150 return object && object.toHTML ? object.toHTML() : String.interpret(object); 151 }, 152 153 keys: function(object) { 154 var keys = []; 155 for (var property in object) 156 keys.push(property); 157 return keys; 158 }, 159 160 values: function(object) { 161 var values = []; 162 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) { 180 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"); 203 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(); 19 209 return function() { 20 this.initialize.apply(this, arguments); 21 } 22 } 23 } 24 25 var Abstract = new Object(); 26 27 Object.extend = function(destination, source) { 28 for (property in source) { 29 destination[property] = source[property]; 30 } 31 return destination; 32 } 33 34 Object.inspect = function(object) { 35 try { 36 if (object == undefined) return 'undefined'; 37 if (object == null) return 'null'; 38 return object.inspect ? object.inspect() : object.toString(); 39 } catch (e) { 40 if (e instanceof RangeError) return '...'; 41 throw e; 42 } 43 } 44 45 Function.prototype.bind = function() { 46 var __method = this, args = $A(arguments), object = args.shift(); 47 return function() { 48 return __method.apply(object, args.concat($A(arguments))); 49 } 50 } 51 52 Function.prototype.bindAsEventListener = function(object) { 53 var __method = this; 54 return function(event) { 55 return __method.call(object, event || window.event); 56 } 57 } 58 59 Object.extend(Number.prototype, { 60 toColorPart: function() { 61 var digits = this.toString(16); 62 if (this < 16) return '0' + digits; 63 return digits; 64 }, 65 66 succ: function() { 67 return this + 1; 68 }, 69 70 times: function(iterator) { 71 $R(0, this, true).each(iterator); 72 return this; 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(); 216 return function(event) { 217 return __method.apply(object, [event || window.event].concat(args)); 218 } 219 }, 220 221 curry: function() { 222 if (!arguments.length) return this; 223 var __method = this, args = $A(arguments); 224 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; 231 return window.setTimeout(function() { 232 return __method.apply(__method, args); 233 }, timeout); 234 }, 235 236 wrap: function(wrapper) { 237 var __method = this; 238 return function() { 239 return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 240 } 241 }, 242 243 methodize: function() { 244 if (this._methodized) return this._methodized; 245 var __method = this; 246 return this._methodized = function() { 247 return __method.apply(null, [this].concat($A(arguments))); 248 }; 73 249 } 74 250 }); 251 252 Function.prototype.defer = Function.prototype.delay.curry(0.01); 253 254 Date.prototype.toJSON = function() { 255 return '"' + this.getUTCFullYear() + '-' + 256 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 257 this.getUTCDate().toPaddedString(2) + 'T' + 258 this.getUTCHours().toPaddedString(2) + ':' + 259 this.getUTCMinutes().toPaddedString(2) + ':' + 260 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 261 }; 75 262 76 263 var Try = { … … 78 265 var returnValue; 79 266 80 for (var i = 0 ; i < arguments.length; i++) {267 for (var i = 0, length = arguments.length; i < length; i++) { 81 268 var lambda = arguments[i]; 82 269 try { 83 270 returnValue = lambda(); 84 271 break; 85 } catch (e) { }272 } catch (e) { } 86 273 } 87 274 88 275 return returnValue; 89 276 } 90 } 277 }; 278 279 RegExp.prototype.match = RegExp.prototype.test; 280 281 RegExp.escape = function(str) { 282 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 283 }; 91 284 92 285 /*--------------------------------------------------------------------------*/ 93 286 94 var PeriodicalExecuter = Class.create(); 95 PeriodicalExecuter.prototype = { 287 var PeriodicalExecuter = Class.create({ 96 288 initialize: function(callback, frequency) { 97 289 this.callback = callback; … … 103 295 104 296 registerCallback: function() { 105 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 297 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 298 }, 299 300 execute: function() { 301 this.callback(this); 302 }, 303 304 stop: function() { 305 if (!this.timer) return; 306 clearInterval(this.timer); 307 this.timer = null; 106 308 }, 107 309 … … 110 312 try { 111 313 this.currentlyExecuting = true; 112 this. callback();314 this.execute(); 113 315 } finally { 114 316 this.currentlyExecuting = false; … … 116 318 } 117 319 } 118 } 119 120 /*--------------------------------------------------------------------------*/ 121 122 function $() { 123 var elements = new Array(); 124 125 for (var i = 0; i < arguments.length; i++) { 126 var element = arguments[i]; 127 if (typeof element == 'string') 128 element = document.getElementById(element); 129 130 if (arguments.length == 1) 131 return element; 132 133 elements.push(element); 134 } 135 136 return elements; 137 } 320 }); 321 Object.extend(String, { 322 interpret: function(value) { 323 return value == null ? '' : String(value); 324 }, 325 specialChar: { 326 '\b': '\\b', 327 '\t': '\\t', 328 '\n': '\\n', 329 '\f': '\\f', 330 '\r': '\\r', 331 '\\': '\\\\' 332 } 333 }); 334 138 335 Object.extend(String.prototype, { 336 gsub: function(pattern, replacement) { 337 var result = '', source = this, match; 338 replacement = arguments.callee.prepareReplacement(replacement); 339 340 while (source.length > 0) { 341 if (match = source.match(pattern)) { 342 result += source.slice(0, match.index); 343 result += String.interpret(replacement(match)); 344 source = source.slice(match.index + match[0].length); 345 } else { 346 result += source, source = ''; 347 } 348 } 349 return result; 350 }, 351 352 sub: function(pattern, replacement, count) { 353 replacement = this.gsub.prepareReplacement(replacement); 354 count = count === undefined ? 1 : count; 355 356 return this.gsub(pattern, function(match) { 357 if (--count < 0) return match[0]; 358 return replacement(match); 359 }); 360 }, 361 362 scan: function(pattern, iterator) { 363 this.gsub(pattern, iterator); 364 return String(this); 365 }, 366 367 truncate: function(length, truncation) { 368 length = length || 30; 369 truncation = truncation === undefined ? '...' : truncation; 370 return this.length > length ? 371 this.slice(0, length - truncation.length) + truncation : String(this); 372 }, 373 374 strip: function() { 375 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 376 }, 377 139 378 stripTags: function() { 140 379 return this.replace(/<\/?[^>]+>/gi, ''); … … 154 393 155 394 evalScripts: function() { 156 return this.extractScripts().map( eval);395 return this.extractScripts().map(function(script) { return eval(script) }); 157 396 }, 158 397 159 398 escapeHTML: function() { 160 var div = document.createElement('div'); 161 var text = document.createTextNode(this); 162 div.appendChild(text); 163 return div.innerHTML; 399 var self = arguments.callee; 400 self.text.data = this; 401 return self.div.innerHTML; 164 402 }, 165 403 166 404 unescapeHTML: function() { 167 var div = document.createElement('div');405 var div = new Element('div'); 168 406 div.innerHTML = this.stripTags(); 169 return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; 170 }, 171 172 toQueryParams: function() { 173 var pairs = this.match(/^\??(.*)$/)[1].split('&'); 174 return pairs.inject({}, function(params, pairString) { 175 var pair = pairString.split('='); 176 params[pair[0]] = pair[1]; 177 return params; 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) { 413 var match = this.strip().match(/([^?#]*)(#.*)?$/); 414 if (!match) return { }; 415 416 return match[1].split(separator || '&').inject({ }, function(hash, pair) { 417 if ((pair = pair.split('='))[0]) { 418 var key = decodeURIComponent(pair.shift()); 419 var value = pair.length > 1 ? pair.join('=') : pair[0]; 420 if (value != undefined) value = decodeURIComponent(value); 421 422 if (key in hash) { 423 if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; 424 hash[key].push(value); 425 } 426 else hash[key] = value; 427 } 428 return hash; 178 429 }); 179 430 }, … … 183 434 }, 184 435 436 succ: function() { 437 return this.slice(0, this.length - 1) + 438 String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 439 }, 440 441 times: function(count) { 442 return count < 1 ? '' : new Array(count + 1).join(this); 443 }, 444 185 445 camelize: function() { 186 var oStringList = this.split('-'); 187 if (oStringList.length == 1) return oStringList[0]; 188 189 var camelizedString = this.indexOf('-') == 0 190 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 191 : oStringList[0]; 192 193 for (var i = 1, len = oStringList.length; i < len; i++) { 194 var s = oStringList[i]; 195 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 196 } 197 198 return camelizedString; 199 }, 200 201 inspect: function() { 202 return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; 446 var parts = this.split('-'), len = parts.length; 447 if (len == 1) return parts[0]; 448 449 var camelized = this.charAt(0) == '-' 450 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 451 : parts[0]; 452 453 for (var i = 1; i < len; i++) 454 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 455 456 return camelized; 457 }, 458 459 capitalize: function() { 460 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); 475 }); 476 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 477 return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 478 }, 479 480 toJSON: function() { 481 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, ''); 490 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 491 }, 492 493 evalJSON: function(sanitize) { 494 var json = this.unfilterJSON(); 495 try { 496 if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 497 } catch (e) { } 498 throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 499 }, 500 501 include: function(pattern) { 502 return this.indexOf(pattern) > -1; 503 }, 504 505 startsWith: function(pattern) { 506 return this.indexOf(pattern) === 0; 507 }, 508 509 endsWith: function(pattern) { 510 var d = this.length - pattern.length; 511 return d >= 0 && this.lastIndexOf(pattern) === d; 512 }, 513 514 empty: function() { 515 return this == ''; 516 }, 517 518 blank: function() { 519 return /^\s*$/.test(this); 520 }, 521 522 interpolate: function(object, pattern) { 523 return new Template(this, pattern).evaluate(object); 203 524 } 204 525 }); 205 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 206 542 String.prototype.parseQuery = String.prototype.toQueryParams; 207 543 208 var $break = new Object(); 209 var $continue = new Object(); 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); 550 551 var Template = Class.create({ 552 initialize: function(template, pattern) { 553 this.template = template.toString(); 554 this.pattern = pattern || Template.Pattern; 555 }, 556 557 evaluate: function(object) { 558 if (Object.isFunction(object.toTemplateReplacements)) 559 object = object.toTemplateReplacements(); 560 561 return this.template.gsub(this.pattern, function(match) { 562 if (object == null) return ''; 563 564 var before = match[1] || ''; 565 if (before == '\\') return match[2]; 566 567 var ctx = object, expr = match[3]; 568 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); 569 if (match == null) return before; 570 571 while (match != null) { 572 var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 573 ctx = ctx[comp]; 574 if (null == ctx || '' == match[3]) break; 575 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 576 match = pattern.exec(expr); 577 } 578 579 return before + String.interpret(ctx); 580 }.bind(this)); 581 } 582 }); 583 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 584 585 var $break = { }; 210 586 211 587 var Enumerable = { 212 each: function(iterator ) {588 each: function(iterator, context) { 213 589 var index = 0; 590 iterator = iterator.bind(context); 214 591 try { 215 592 this._each(function(value) { 216 try { 217 iterator(value, index++); 218 } catch (e) { 219 if (e != $continue) throw e; 220 } 593 iterator(value, index++); 221 594 }); 222 595 } catch (e) { 223 596 if (e != $break) throw e; 224 597 } 225 }, 226 227 all: function(iterator) { 598 return this; 599 }, 600 601 eachSlice: function(number, iterator, context) { 602 iterator = iterator ? iterator.bind(context) : Prototype.K; 603 var index = -number, slices = [], array = this.toArray(); 604 while ((index += number) < array.length) 605 slices.push(array.slice(index, index+number)); 606 return slices.collect(iterator, context); 607 }, 608 609 all: function(iterator, context) { 610 iterator = iterator ? iterator.bind(context) : Prototype.K; 228 611 var result = true; 229 612 this.each(function(value, index) { 230 result = result && !! (iterator || Prototype.K)(value, index);613 result = result && !!iterator(value, index); 231 614 if (!result) throw $break; 232 615 }); … … 234 617 }, 235 618 236 any: function(iterator) { 237 var result = true; 619 any: function(iterator, context) { 620 iterator = iterator ? iterator.bind(context) : Prototype.K; 621 var result = false; 238 622 this.each(function(value, index) { 239 if (result = !! (iterator || Prototype.K)(value, index))623 if (result = !!iterator(value, index)) 240 624 throw $break; 241 625 }); … … 243 627 }, 244 628 245 collect: function(iterator) { 629 collect: function(iterator, context) { 630 iterator = iterator ? iterator.bind(context) : Prototype.K; 246 631 var results = []; 247 632 this.each(function(value, index) { … … 251 636 }, 252 637 253 detect: function (iterator) { 638 detect: function(iterator, context) { 639 iterator = iterator.bind(context); 254 640 var result; 255 641 this.each(function(value, index) { … … 262 648 }, 263 649 264 findAll: function(iterator) { 650 findAll: function(iterator, context) { 651 iterator = iterator.bind(context); 265 652 var results = []; 266 653 this.each(function(value, index) { … … 271 658 }, 272 659 273 grep: function(pattern, iterator) { 660 grep: function(filter, iterator, context) { 661 iterator = iterator ? iterator.bind(context) : Prototype.K; 274 662 var results = []; 663 664 if (Object.isString(filter)) 665 filter = new RegExp(filter); 666 275 667 this.each(function(value, index) { 276 var stringValue = value.toString(); 277 if (stringValue.match(pattern)) 278 results.push((iterator || Prototype.K)(value, index)); 279 }) 668 if (filter.match(value)) 669 results.push(iterator(value, index)); 670 }); 280 671 return results; 281 672 }, 282 673 283 674 include: function(object) { 675 if (Object.isFunction(this.indexOf)) 676 if (this.indexOf(object) != -1) return true; 677 284 678 var found = false; 285 679 this.each(function(value) { … … 292 686 }, 293 687 294 inject: function(memo, iterator) { 688 inGroupsOf: function(number, fillWith) { 689 fillWith = fillWith === undefined ? null : fillWith; 690 return this.eachSlice(number, function(slice) { 691 while(slice.length < number) slice.push(fillWith); 692 return slice; 693 }); 694 }, 695 696 inject: function(memo, iterator, context) { 697 iterator = iterator.bind(context); 295 698 this.each(function(value, index) { 296 699 memo = iterator(memo, value, index); … … 301 704 invoke: function(method) { 302 705 var args = $A(arguments).slice(1); 303 return this. collect(function(value) {706 return this.map(function(value) { 304 707 return value[method].apply(value, args); 305 708 }); 306 709 }, 307 710 308 max: function(iterator) { 711 max: function(iterator, context) { 712 iterator = iterator ? iterator.bind(context) : Prototype.K; 309 713 var result; 310 714 this.each(function(value, index) { 311 value = (iterator || Prototype.K)(value, index);312 if ( value >= (result || value))715 value = iterator(value, index); 716 if (result == undefined || value >= result) 313 717 result = value; 314 718 }); … … 316 720 }, 317 721 318 min: function(iterator) { 722 min: function(iterator, context) { 723 iterator = iterator ? iterator.bind(context) : Prototype.K; 319 724 var result; 320 725 this.each(function(value, index) { 321 value = (iterator || Prototype.K)(value, index);322 if ( value <= (result || value))726 value = iterator(value, index); 727 if (result == undefined || value < result) 323 728 result = value; 324 729 }); … … 326 731 }, 327 732 328 partition: function(iterator) { 733 partition: function(iterator, context) { 734 iterator = iterator ? iterator.bind(context) : Prototype.K; 329 735 var trues = [], falses = []; 330 736 this.each(function(value, index) { 331 ( (iterator || Prototype.K)(value, index) ?737 (iterator(value, index) ? 332 738 trues : falses).push(value); 333 739 }); … … 337 743 pluck: function(property) { 338 744 var results = []; 339 this.each(function(value , index) {745 this.each(function(value) { 340 746 results.push(value[property]); 341 747 }); … … 343 749 }, 344 750 345 reject: function(iterator) { 751 reject: function(iterator, context) { 752 iterator = iterator.bind(context); 346 753 var results = []; 347 754 this.each(function(value, index) { … … 352 759 }, 353 760 354 sortBy: function(iterator) { 355 return this.collect(function(value, index) { 761 sortBy: function(iterator, context) { 762 iterator = iterator.bind(context); 763 return this.map(function(value, index) { 356 764 return {value: value, criteria: iterator(value, index)}; 357 765 }).sort(function(left, right) { … … 362 770 363 771 toArray: function() { 364 return this. collect(Prototype.K);772 return this.map(); 365 773 }, 366 774 367 775 zip: function() { 368 776 var iterator = Prototype.K, args = $A(arguments); 369 if ( typeof args.last() == 'function')777 if (Object.isFunction(args.last())) 370 778 iterator = args.pop(); 371 779 372 780 var collections = [this].concat(args).map($A); 373 781 return this.map(function(value, index) { 374 iterator(value = collections.pluck(index)); 375 return value; 782 return iterator(collections.pluck(index)); 376 783 }); 784 }, 785 786 size: function() { 787 return this.toArray().length; 377 788 }, 378 789 … … 380 791 return '#<Enumerable:' + this.toArray().inspect() + '>'; 381 792 } 382 } 793 }; 383 794 384 795 Object.extend(Enumerable, { … … 386 797 find: Enumerable.detect, 387 798 select: Enumerable.findAll, 799 filter: Enumerable.findAll, 388 800 member: Enumerable.include, 389 entries: Enumerable.toArray 801 entries: Enumerable.toArray, 802 every: Enumerable.all, 803 some: Enumerable.any 390 804 }); 391 var $A = Array.from = function(iterable) {805 function $A(iterable) { 392 806 if (!iterable) return []; 393 if (iterable.toArray) { 394 return iterable.toArray(); 395 } else { 396 var results = []; 397 for (var i = 0; i < iterable.length; i++) 398 results.push(iterable[i]); 807 if (iterable.toArray) return iterable.toArray(); 808 var length = iterable.length, results = new Array(length); 809 while (length--) results[length] = iterable[length]; 810 return results; 811 } 812 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]; 399 820 return results; 400 821 } 401 822 } 402 823 824 Array.from = $A; 825 403 826 Object.extend(Array.prototype, Enumerable); 404 827 405 Array.prototype._reverse = Array.prototype.reverse;828 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 406 829 407 830 Object.extend(Array.prototype, { 408 831 _each: function(iterator) { 409 for (var i = 0 ; i < this.length; i++)832 for (var i = 0, length = this.length; i < length; i++) 410 833 iterator(this[i]); 411 834 }, … … 426 849 compact: function() { 427 850 return this.select(function(value) { 428 return value != undefined || value !=null;851 return value != null; 429 852 }); 430 853 }, … … 432 855 flatten: function() { 433 856 return this.inject([], function(array, value) { 434 return array.concat( value.constructor == Array?857 return array.concat(Object.isArray(value) ? 435 858 value.flatten() : [value]); 436 859 }); … … 444 867 }, 445 868 446 indexOf: function(object) {447 for (var i = 0; i < this.length; i++)448 if (this[i] == object) return i;449 return -1;450 },451 452 869 reverse: function(inline) { 453 870 return (inline !== false ? this : this.toArray())._reverse(); 454 871 }, 455 872 456 shift: function() { 457 var result = this[0]; 458 for (var i = 0; i < this.length - 1; i++) 459 this[i] = this[i + 1]; 460 this.length--; 461 return result; 873 reduce: function() { 874 return this.length > 1 ? this : this[0]; 875 }, 876 877 uniq: function(sorted) { 878 return this.inject([], function(array, value, index) { 879 if (0 == index || (sorted ? array.last() != value : !array.include(value))) 880 array.push(value); 881 return array; 882 }); 883 }, 884 885 intersect: function(array) { 886 return this.uniq().findAll(function(item) { 887 return array.detect(function(value) { return item === value }); 888 }); 889 }, 890 891 clone: function() { 892 return [].concat(this); 893 }, 894 895 size: function() { 896 return this.length; 462 897 }, 463 898 464 899 inspect: function() { 465 900 return '[' + this.map(Object.inspect).join(', ') + ']'; 901 }, 902 903 toJSON: function() { 904 var results = []; 905 this.each(function(object) { 906 var value = Object.toJSON(object); 907 if (value !== undefined) results.push(value); 908 }); 909 return '[' + results.join(', ') + ']'; 466 910 } 467 911 }); 468 var Hash = { 469 _each: function(iterator) { 470 for (key in this) { 471 var value = this[key]; 472 if (typeof value == 'function') continue; 473 474 var pair = [key, value]; 475 pair.key = key; 476 pair.value = value; 477 iterator(pair); 478 } 479 }, 480 481 keys: function() { 482 return this.pluck('key'); 483 }, 484 485 values: function() { 486 return this.pluck('value'); 487 }, 488 489 merge: function(hash) { 490 return $H(hash).inject($H(this), function(mergedHash, pair) { 491 mergedHash[pair.key] = pair.value; 492 return mergedHash; 493 }); 494 }, 495 496 toQueryString: function() { 497 return this.map(function(pair) { 498 return pair.map(encodeURIComponent).join('='); 499 }).join('&'); 500 }, 501 502 inspect: function() { 503 return '#<Hash:{' + this.map(function(pair) { 504 return pair.map(Object.inspect).join(': '); 505 }).join(', ') + '}>'; 506 } 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+/) : []; 507 938 } 508 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]); 944 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]); 948 } else { 949 array.push(arguments[i]); 950 } 951 } 952 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 }); 509 982 function $H(object) { 510 var hash = Object.extend({}, object || {}); 511 Object.extend(hash, Enumerable); 512 Object.extend(hash, Hash); 513 return hash; 514 } 515 ObjectRange = Class.create(); 516 Object.extend(ObjectRange.prototype, Enumerable); 517 Object.extend(ObjectRange.prototype, { 983 return new Hash(object); 984 }; 985 986 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 } 1014 } 1015 1016 function toQueryPair(key, value) { 1017 if (Object.isUndefined(value)) return key; 1018 return key + '=' + encodeURIComponent(String.interpret(value)); 1019 } 1020 1021 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 } 1098 })()); 1099 1100 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; 1101 Hash.from = $H; 1102 var ObjectRange = Class.create(Enumerable, { 518 1103 initialize: function(start, end, exclusive) { 519 1104 this.start = start; … … 524 1109 _each: function(iterator) { 525 1110 var value = this.start; 526 do{1111 while (this.include(value)) { 527 1112 iterator(value); 528 1113 value = value.succ(); 529 } while (this.include(value));1114 } 530 1115 }, 531 1116 … … 541 1126 var $R = function(start, end, exclusive) { 542 1127 return new ObjectRange(start, end, exclusive); 543 } 1128 }; 544 1129 545 1130 var Ajax = { 546 1131 getTransport: function() { 547 1132 return Try.these( 1133 function() {return new XMLHttpRequest()}, 548 1134 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, 549 function() {return new ActiveXObject('Microsoft.XMLHTTP')}, 550 function() {return new XMLHttpRequest()} 1135 function() {return new ActiveXObject('Microsoft.XMLHTTP')} 551 1136 ) || false; 552 1137 }, 553 1138 554 1139 activeRequestCount: 0 555 } 1140 }; 556 1141 557 1142 Ajax.Responders = { … … 562 1147 }, 563 1148 564 register: function(responder ToAdd) {565 if (!this.include(responder ToAdd))566 this.responders.push(responder ToAdd);567 }, 568 569 unregister: function(responder ToRemove) {570 this.responders = this.responders.without(responder ToRemove);1149 register: function(responder) { 1150 if (!this.include(responder)) 1151 this.responders.push(responder); 1152 }, 1153 1154 unregister: function(responder) { 1155 this.responders = this.responders.without(responder); 571 1156 }, 572 1157 573 1158 dispatch: function(callback, request, transport, json) { 574 1159 this.each(function(responder) { 575 if ( responder[callback] && typeof responder[callback] == 'function') {1160 if (Object.isFunction(responder[callback])) { 576 1161 try { 577 1162 responder[callback].apply(responder, [request, transport, json]); 578 } catch (e) { }1163 } catch (e) { } 579 1164 } 580 1165 }); … … 585 1170 586 1171 Ajax.Responders.register({ 587 onCreate: function() { 588 Ajax.activeRequestCount++; 589 }, 590 591 onComplete: function() { 592 Ajax.activeRequestCount--; 593 } 1172 onCreate: function() { Ajax.activeRequestCount++ }, 1173 onComplete: function() { Ajax.activeRequestCount-- } 594 1174 }); 595 1175 596 Ajax.Base = function() {}; 597 Ajax.Base.prototype = { 598 setOptions: function(options) { 1176 Ajax.Base = Class.create({ 1177 initialize: function(options) { 599 1178 this.options = { 600 1179 method: 'post', 601 1180 asynchronous: true, 602 parameters: '' 603 } 604 Object.extend(this.options, options || {}); 605 }, 606 607 responseIsSuccess: function() { 608 return this.transport.status == undefined 609 || this.transport.status == 0 610 || (this.transport.status >= 200 && this.transport.status < 300); 611 }, 612 613 responseIsFailure: function() { 614 return !this.responseIsSuccess(); 615 } 616 } 617 618 Ajax.Request = Class.create(); 619 Ajax.Request.Events = 620 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 621 622 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 623 initialize: function(url, options) { 1181 contentType: 'application/x-www-form-urlencoded', 1182 encoding: 'UTF-8', 1183 parameters: '', 1184 evalJSON: true, 1185 evalJS: true 1186 }; 1187 Object.extend(this.options, options || { }); 1188 1189 this.options.method = this.options.method.toLowerCase(); 1190 if (Object.isString(this.options.parameters)) 1191 this.options.parameters = this.options.parameters.toQueryParams(); 1192 } 1193 }); 1194 1195 Ajax.Request = Class.create(Ajax.Base, { 1196 _complete: false, 1197 1198 initialize: function($super, url, options) { 1199 $super(options); 624 1200 this.transport = Ajax.getTransport(); 625 this.setOptions(options);626 1201 this.request(url); 627 1202 }, 628 1203 629 1204 request: function(url) { 630 var parameters = this.options.parameters || ''; 631 if (parameters.length > 0) parameters += '&_='; 1205 this.url = url; 1206 this.method = this.options.method; 1207 var params = Object.clone(this.options.parameters); 1208 1209 if (!['get', 'post'].include(this.method)) { 1210 // simulate other verbs over post 1211 params['_method'] = this.method; 1212 this.method = 'post'; 1213 } 1214 1215 this.parameters = params; 1216 1217 if (params = Object.toQueryString(params)) { 1218 // when GET, append parameters to URL 1219 if (this.method == 'get') 1220 this.url += (this.url.include('?') ? '&' : '?') + params; 1221 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 1222 params += '&_='; 1223 } 632 1224 633 1225 try { 634 this.url = url; 635 if (this.options.method == 'get' && parameters.length > 0) 636 this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; 637 638 Ajax.Responders.dispatch('onCreate', this, this.transport); 639 640 this.transport.open(this.options.method, this.url, 1226 var response = new Ajax.Response(this); 1227 if (this.options.onCreate) this.options.onCreate(response); 1228 Ajax.Responders.dispatch('onCreate', this, response); 1229 1230 this.transport.open(this.method.toUpperCase(), this.url, 641 1231 this.options.asynchronous); 642 1232 643 if (this.options.asynchronous) { 644 this.transport.onreadystatechange = this.onStateChange.bind(this); 645 setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); 646 } 647 1233 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); 1234 1235 this.transport.onreadystatechange = this.onStateChange.bind(this); 648 1236 this.setRequestHeaders(); 649 1237 650 var body = this.options.postBody ? this.options.postBody : parameters; 651 this.transport.send(this.options.method == 'post' ? body : null); 652 1238 this.body = this.method == 'post' ? (this.options.postBody || params) : null; 1239 this.transport.send(this.body); 1240 1241 /* Force Firefox to handle ready state 4 for synchronous requests */ 1242 if (!this.options.asynchronous && this.transport.overrideMimeType) 1243 this.onStateChange(); 1244 1245 } 1246 catch (e) { 1247 this.dispatchException(e); 1248 } 1249 }, 1250 1251 onStateChange: function() { 1252 var readyState = this.transport.readyState; 1253 if (readyState > 1 && !((readyState == 4) && this._complete)) 1254 this.respondToReadyState(this.transport.readyState); 1255 }, 1256 1257 setRequestHeaders: function() { 1258 var headers = { 1259 'X-Requested-With': 'XMLHttpRequest', 1260 'X-Prototype-Version': Prototype.Version, 1261 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 1262 }; 1263 1264 if (this.method == 'post') { 1265 headers['Content-type'] = this.options.contentType + 1266 (this.options.encoding ? '; charset=' + this.options.encoding : ''); 1267 1268 /* Force "Connection: close" for older Mozilla browsers to work 1269 * around a bug where XMLHttpRequest sends an incorrect 1270 * Content-length header. See Mozilla Bugzilla #246651. 1271 */ 1272 if (this.transport.overrideMimeType && 1273 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 1274 headers['Connection'] = 'close'; 1275 } 1276 1277 // user-defined headers 1278 if (typeof this.options.requestHeaders == 'object') { 1279 var extras = this.options.requestHeaders; 1280 1281 if (Object.isFunction(extras.push)) 1282 for (var i = 0, length = extras.length; i < length; i += 2) 1283 headers[extras[i]] = extras[i+1]; 1284 else 1285 $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 1286 } 1287 1288 for (var name in headers) 1289 this.transport.setRequestHeader(name, headers[name]); 1290 }, 1291 1292 success: function() { 1293 var status = this.getStatus(); 1294 return !status || (status >= 200 && status < 300); 1295 }, 1296 1297 getStatus: function() { 1298 try { 1299 return this.transport.status || 0; 1300 } catch (e) { return 0 } 1301 }, 1302 1303 respondToReadyState: function(readyState) { 1304 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); 1305 1306 if (state == 'Complete') { 1307 try { 1308 this._complete = true; 1309 (this.options['on' + response.status] 1310 || this.options['on' + (this.success() ? 'Success' : 'Failure')] 1311 || Prototype.emptyFunction)(response, response.headerJSON); 1312 } catch (e) { 1313 this.dispatchException(e); 1314 } 1315 1316 var contentType = response.getHeader('Content-type'); 1317 if (this.options.evalJS == 'force' 1318 || (this.options.evalJS && contentType 1319 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 1320 this.evalResponse(); 1321 } 1322 1323 try { 1324 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); 1325 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); 653 1326 } catch (e) { 654 1327 this.dispatchException(e); 655 1328 } 656 }, 657 658 setRequestHeaders: function() { 659 var requestHeaders = 660 ['X-Requested-With', 'XMLHttpRequest', 661 'X-Prototype-Version', Prototype.Version]; 662 663 if (this.options.method == 'post') { 664 requestHeaders.push('Content-type', 665 'application/x-www-form-urlencoded'); 666 667 /* Force "Connection: close" for Mozilla browsers to work around 668 * a bug where XMLHttpReqeuest sends an incorrect Content-length 669 * header. See Mozilla Bugzilla #246651. 670 */ 671 if (this.transport.overrideMimeType) 672 requestHeaders.push('Connection', 'close'); 673 } 674 675 if (this.options.requestHeaders) 676 requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); 677 678 for (var i = 0; i < requestHeaders.length; i += 2) 679 this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); 680 }, 681 682 onStateChange: function() { 683 var readyState = this.transport.readyState; 684 if (readyState != 1) 685 this.respondToReadyState(this.transport.readyState); 686 }, 687 688 header: function(name) { 1329 1330 if (state == 'Complete') { 1331 // avoid memory leak in MSIE: clean up 1332 this.transport.onreadystatechange = Prototype.emptyFunction; 1333 } 1334 }, 1335 1336 getHeader: function(name) { 689 1337 try { 690 1338 return this.transport.getResponseHeader(name); 691 } catch (e) {} 692 }, 693 694 evalJSON: function() { 695 try { 696 return eval(this.header('X-JSON')); 697 } catch (e) {} 1339 } catch (e) { return null } 698 1340 }, 699 1341 700 1342 evalResponse: function() { 701 1343 try { 702 return eval( this.transport.responseText);1344 return eval((this.transport.responseText || '').unfilterJSON()); 703 1345 } catch (e) { 704 1346 this.dispatchException(e); 705 1347 } 706 },707 708 respondToReadyState: function(readyState) {709 var event = Ajax.Request.Events[readyState];710 var transport = this.transport, json = this.evalJSON();711 712 if (event == 'Complete') {713 try {714 (this.options['on' + this.transport.status]715 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]716 || Prototype.emptyFunction)(transport, json);717 } catch (e) {718 this.dispatchException(e);719 }720 721 if ((this.header('Content-type') || '').match(/^text\/javascript/i))722 this.evalResponse();723 }724 725 try {726 (this.options['on' + event] || Prototype.emptyFunction)(transport, json);727 Ajax.Responders.dispatch('on' + event, this, transport, json);728 } catch (e) {729 this.dispatchException(e);730 }731 732 /* Avoid memory leak in MSIE: clean up the oncomplete event handler */733 if (event == 'Complete')734 this.transport.onreadystatechange = Prototype.emptyFunction;735 1348 }, 736 1349 … … 741 1354 }); 742 1355 743 Ajax.Updater = Class.create(); 744 745 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 746 initialize: function(container, url, options) { 747 this.containers = { 748 success: container.success ? $(container.success) : $(container), 749 failure: container.failure ? $(container.failure) : 750 (container.success ? null : $(container)) 751 } 752 753 this.transport = Ajax.getTransport(); 754 this.setOptions(options); 755 756 var onComplete = this.options.onComplete || Prototype.emptyFunction; 757 this.options.onComplete = (function(transport, object) { 758 this.updateContent(); 759 onComplete(transport, object); 1356 Ajax.Request.Events = 1357 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 1358 1359 Ajax.Response = Class.create({ 1360 initialize: function(request){ 1361 this.request = request; 1362 var transport = this.transport = request.transport, 1363 readyState = this.readyState = transport.readyState; 1364 1365 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { 1366 this.status = this.getStatus(); 1367 this.statusText = this.getStatusText(); 1368 this.responseText = String.interpret(transport.responseText); 1369 this.headerJSON = this._getHeaderJSON(); 1370 } 1371 1372 if(readyState == 4) { 1373 var xml = transport.responseXML; 1374 this.responseXML = xml === undefined ? null : xml; 1375 this.responseJSON = this._getResponseJSON(); 1376 } 1377 }, 1378 1379 status: 0, 1380 statusText: '', 1381 1382 getStatus: Ajax.Request.prototype.getStatus, 1383 1384 getStatusText: function() { 1385 try { 1386 return this.transport.statusText || ''; 1387 } catch (e) { return '' } 1388 }, 1389 1390 getHeader: Ajax.Request.prototype.getHeader, 1391 1392 getAllHeaders: function() { 1393 try { 1394 return this.getAllResponseHeaders(); 1395 } catch (e) { return null } 1396 }, 1397 1398 getResponseHeader: function(name) { 1399 return this.transport.getResponseHeader(name); 1400 }, 1401 1402 getAllResponseHeaders: function() { 1403 return this.transport.getAllResponseHeaders(); 1404 }, 1405 1406 _getHeaderJSON: function() { 1407 var json = this.getHeader('X-JSON'); 1408 if (!json) return null; 1409 json = decodeURIComponent(escape(json)); 1410 try { 1411 return json.evalJSON(this.request.options.sanitizeJSON); 1412 } catch (e) { 1413 this.request.dispatchException(e); 1414 } 1415 }, 1416 1417 _getResponseJSON: function() { 1418 var options = this.request.options; 1419 if (!options.evalJSON || (options.evalJSON != 'force' && 1420 !(this.getHeader('Content-type') || '').include('application/json'))) 1421 return null; 1422 try { 1423 return this.transport.responseText.evalJSON(options.sanitizeJSON); 1424 } catch (e) { 1425 this.request.dispatchException(e); 1426 } 1427 } 1428 }); 1429 1430 Ajax.Updater = Class.create(Ajax.Request, { 1431 initialize: function($super, container, url, options) { 1432 this.container = { 1433 success: (container.success || container), 1434 failure: (container.failure || (container.success ? null : container)) 1435 }; 1436 1437 options = options || { }; 1438 var onComplete = options.onComplete; 1439 options.onComplete = (function(response, param) { 1440 this.updateContent(response.responseText); 1441 if (Object.isFunction(onComplete)) onComplete(response, param); 760 1442 }).bind(this); 761 1443 762 this.request(url);763 }, 764 765 updateContent: function( ) {766 var receiver = this. responseIsSuccess() ?767 this.containers.success : this.containers.failure;768 var response = this.transport.responseText; 769 770 if (!this.options.evalScripts) 771 response = response.stripScripts();772 773 if (receiver) {774 if (this.options.insertion) {775 new this.options.insertion(receiver, response);776 } else {777 Element.update(receiver, response);778 } 779 }780 781 if (this.responseIsSuccess()) { 782 if (this.onComplete)783 setTimeout(this.onComplete.bind(this), 10);1444 $super(url, options); 1445 }, 1446 1447 updateContent: function(responseText) { 1448 var receiver = this.container[this.success() ? 'success' : 'failure'], 1449 options = this.options; 1450 1451 if (!options.evalScripts) responseText = responseText.stripScripts(); 1452 1453 if (receiver = $(receiver)) { 1454 if (options.insertion) { 1455 if (Object.isString(options.insertion)) { 1456 var insertion = { }; insertion[options.insertion] = responseText; 1457 receiver.insert(insertion); 1458 } 1459 else options.insertion(receiver, responseText); 1460 } 1461 else receiver.update(responseText); 1462 } 1463 1464 if (this.success()) { 1465 if (this.onComplete) this.onComplete.bind(this).defer(); 784 1466 } 785 1467 } 786 1468 }); 787 1469 788 Ajax.PeriodicalUpdater = Class.create(); 789 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { 790 initialize: function(container, url, options) { 791 this.setOptions(options); 1470 Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { 1471 initialize: function($super, container, url, options) { 1472 $super(options); 792 1473 this.onComplete = this.options.onComplete; 793 1474 … … 795 1476 this.decay = (this.options.decay || 1); 796 1477 797 this.updater = { };1478 this.updater = { }; 798 1479 this.container = container; 799 1480 this.url = url; … … 808 1489 809 1490 stop: function() { 810 this.updater.o nComplete = undefined;1491 this.updater.options.onComplete = undefined; 811 1492 clearTimeout(this.timer); 812 1493 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 813 1494 }, 814 1495 815 updateComplete: function(re quest) {1496 updateComplete: function(response) { 816 1497 if (this.options.decay) { 817 this.decay = (re quest.responseText == this.lastText ?1498 this.decay = (response.responseText == this.lastText ? 818 1499 this.decay * this.options.decay : 1); 819 1500 820 this.lastText = request.responseText; 821 } 822 this.timer = setTimeout(this.onTimerEvent.bind(this), 823 this.decay * this.frequency * 1000); 1501 this.lastText = response.responseText; 1502 } 1503 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); 824 1504 }, 825 1505 … … 828 1508 } 829 1509 }); 830 document.getElementsByClassName = function(className, parentElement) { 831 var children = ($(parentElement) || document.body).getElementsByTagName('*'); 832 return $A(children).inject([], function(elements, child) { 833 if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 834 elements.push(child); 1510 function $(element) { 1511 if (arguments.length > 1) { 1512 for (var i = 0, elements = [], length = arguments.length; i < length; i++) 1513 elements.push($(arguments[i])); 835 1514 return elements; 1515 } 1516 if (Object.isString(element)) 1517 element = document.getElementById(element); 1518 return Element.extend(element); 1519 } 1520 1521 if (Prototype.BrowserFeatures.XPath) { 1522 document._getElementsByXPath = function(expression, parentElement) { 1523 var results = []; 1524 var query = document.evaluate(expression, $(parentElement) || document, 1525 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 1526 for (var i = 0, length = query.snapshotLength; i < length; i++) 1527 results.push(Element.extend(query.snapshotItem(i))); 1528 return results; 1529 }; 1530 } 1531 1532 /*--------------------------------------------------------------------------*/ 1533 1534 if (!window.Node) var Node = { }; 1535 1536 if (!Node.ELEMENT_NODE) { 1537 // DOM level 2 ECMAScript Language Binding 1538 Object.extend(Node, { 1539 ELEMENT_NODE: 1, 1540 ATTRIBUTE_NODE: 2, 1541 TEXT_NODE: 3, 1542 CDATA_SECTION_NODE: 4, 1543 ENTITY_REFERENCE_NODE: 5, 1544 ENTITY_NODE: 6, 1545 PROCESSING_INSTRUCTION_NODE: 7, 1546 COMMENT_NODE: 8, 1547 DOCUMENT_NODE: 9, 1548 DOCUMENT_TYPE_NODE: 10, 1549 DOCUMENT_FRAGMENT_NODE: 11, 1550 NOTATION_NODE: 12 836 1551 }); 837 1552 } 838 1553 839 /*--------------------------------------------------------------------------*/ 840 841 if (!window.Element) { 842 var Element = new Object(); 843 } 844 845 Object.extend(Element, { 1554 (function() { 1555 var element = this.Element; 1556 this.Element = function(tagName, attributes) { 1557 attributes = attributes || { }; 1558 tagName = tagName.toLowerCase(); 1559 var cache = Element.cache; 1560 if (Prototype.Browser.IE && attributes.name) { 1561 tagName = '<' + tagName + ' name="' + attributes.name + '">'; 1562 delete attributes.name; 1563 return Element.writeAttribute(document.createElement(tagName), attributes); 1564 } 1565 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 1566 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 1567 }; 1568 Object.extend(this.Element, element || { }); 1569 }).call(window); 1570 1571 Element.cache = { }; 1572 1573 Element.Methods = { 846 1574 visible: function(element) { 847 1575 return $(element).style.display != 'none'; 848 1576 }, 849 1577 850 toggle: function() { 851 for (var i = 0; i < arguments.length; i++) { 852 var element = $(arguments[i]); 853 Element[Element.visible(element) ? 'hide' : 'show'](element); 854 } 855 }, 856 857 hide: function() { 858 for (var i = 0; i < arguments.length; i++) { 859 var element = $(arguments[i]); 860 element.style.display = 'none'; 861 } 862 }, 863 864 show: function() { 865 for (var i = 0; i < arguments.length; i++) { 866 var element = $(arguments[i]); 867 element.style.display = ''; 868 } 1578 toggle: function(element) { 1579 element = $(element); 1580 Element[Element.visible(element) ? 'hide' : 'show'](element); 1581 return element; 1582 }, 1583 1584 hide: function(element) { 1585 $(element).style.display = 'none'; 1586 return element; 1587 }, 1588 1589 show: function(element) { 1590 $(element).style.display = ''; 1591 return element; 869 1592 }, 870 1593 … … 872 1595 element = $(element); 873 1596 element.parentNode.removeChild(element); 874 }, 875 876 update: function(element, html) { 877 $(element).innerHTML = html.stripScripts(); 878 setTimeout(function() {html.evalScripts()}, 10); 1597 return element; 1598 }, 1599 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 }, 1609 1610 replace: function(element, content) { 1611 element = $(element); 1612 if (content && content.toElement) content = content.toElement(); 1613 else if (!Object.isElement(content)) { 1614 content = Object.toHTML(content); 1615 var range = element.ownerDocument.createRange(); 1616 range.selectNode(element); 1617 content.evalScripts.bind(content).defer(); 1618 content = range.createContextualFragment(content.stripScripts()); 1619 } 1620 element.parentNode.replaceChild(content, element); 1621 return element; 1622 }, 1623 1624 insert: function(element, insertions) { 1625 element = $(element); 1626 1627 if (Object.isString(insertions) || Object.isNumber(insertions) || 1628 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 1629 insertions = {bottom:insertions}; 1630 1631 var content, t, range; 1632 1633 for (position in insertions) { 1634 content = insertions[position]; 1635 position = position.toLowerCase(); 1636 t = Element._insertionTranslations[position]; 1637 1638 if (content && content.toElement) content = content.toElement(); 1639 if (Object.isElement(content)) { 1640 t.insert(element, content); 1641 continue; 1642 } 1643 1644 content = Object.toHTML(content); 1645 1646 range = element.ownerDocument.createRange(); 1647 t.initializeRange(element, range); 1648 t.insert(element, range.createContextualFragment(content.stripScripts())); 1649 1650 content.evalScripts.bind(content).defer(); 1651 } 1652 1653 return element; 1654 }, 1655 1656 wrap: function(element, wrapper, attributes) { 1657 element = $(element); 1658 if (Object.isElement(wrapper)) 1659 $(wrapper).writeAttribute(attributes || { }); 1660 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); 1661 else wrapper = new Element('div', wrapper); 1662 if (element.parentNode) 1663 element.parentNode.replaceChild(wrapper, element); 1664 wrapper.appendChild(element); 1665 return wrapper; 1666 }, 1667 1668 inspect: function(element) { 1669 element = $(element); 1670 var result = '<' + element.tagName.toLowerCase(); 1671 $H({'id': 'id', 'className': 'class'}).each(function(pair) { 1672 var property = pair.first(), attribute = pair.last(); 1673 var value = (element[property] || '').toString(); 1674 if (value) result += ' ' + attribute + '=' + value.inspect(true); 1675 }); 1676 return result + '>'; 1677 }, 1678 1679 recursivelyCollect: function(element, property) { 1680 element = $(element); 1681 var elements = []; 1682 while (element = element[property]) 1683 if (element.nodeType == 1) 1684 elements.push(Element.extend(element)); 1685 return elements; 1686 }, 1687 1688 ancestors: function(element) { 1689 return $(element).recursivelyCollect('parentNode'); 1690 }, 1691 1692 descendants: function(element) { 1693 return $A($(element).getElementsByTagName('*')).each(Element.extend); 1694 }, 1695 1696 firstDescendant: function(element) { 1697 element = $(element).firstChild; 1698 while (element && element.nodeType != 1) element = element.nextSibling; 1699 return $(element); 1700 }, 1701 1702 immediateDescendants: function(element) { 1703 if (!(element = $(element).firstChild)) return []; 1704 while (element && element.nodeType != 1) element = element.nextSibling; 1705 if (element) return [element].concat($(element).nextSiblings()); 1706 return []; 1707 }, 1708 1709 previousSiblings: function(element) { 1710 return $(element).recursivelyCollect('previousSibling'); 1711 }, 1712 1713 nextSiblings: function(element) { 1714 return $(element).recursivelyCollect('nextSibling'); 1715 }, 1716 1717 siblings: function(element) { 1718 element = $(element); 1719 return element.previousSiblings().reverse().concat(element.nextSiblings()); 1720 }, 1721 1722 match: function(element, selector) { 1723 if (Object.isString(selector)) 1724 selector = new Selector(selector); 1725 return selector.match($(element)); 1726 }, 1727 1728 up: function(element, expression, index) { 1729 element = $(element); 1730 if (arguments.length == 1) return $(element.parentNode); 1731 var ancestors = element.ancestors(); 1732 return expression ? Selector.findElement(ancestors, expression, index) : 1733 ancestors[index || 0]; 1734 }, 1735 1736 down: function(element, expression, index) { 1737 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]; 1742 }, 1743 1744 previous: function(element, expression, index) { 1745 element = $(element); 1746 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]; 1750 }, 1751 1752 next: function(element, expression, index) { 1753 element = $(element); 1754 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()); 1762 return Selector.findChildElements(element, args); 1763 }, 1764 1765 adjacent: function() { 1766 var args = $A(arguments), element = $(args.shift()); 1767 return Selector.findChildElements(element.parentNode, args).without(element); 1768 }, 1769 1770 identify: function(element) { 1771 element = $(element); 1772 var id = element.readAttribute('id'), self = arguments.callee; 1773 if (id) return id; 1774 do { id = 'anonymous_element_' + self.counter++ } while ($(id)); 1775 element.writeAttribute('id', id); 1776 return id; 1777 }, 1778 1779 readAttribute: function(element, name) { 1780 element = $(element); 1781 if (Prototype.Browser.IE) { 1782 var t = Element._attributeTranslations.read; 1783 if (t.values[name]) return t.values[name](element, name); 1784 if (t.names[name]) name = t.names[name]; 1785 if (name.include(':')) { 1786 return (!element.attributes || !element.attributes[name]) ? null : 1787 element.attributes[name].value; 1788 } 1789 } 1790 return element.getAttribute(name); 1791 }, 1792 1793 writeAttribute: function(element, name, value) { 1794 element = $(element); 1795 var attributes = { }, t = Element._attributeTranslations.write; 1796 1797 if (typeof name == 'object') attributes = name; 1798 else attributes[name] = value === undefined ? true : value; 1799 1800 for (var attr in attributes) { 1801 var name = t.names[attr] || attr, value = attributes[attr]; 1802 if (t.values[attr]) name = t.values[attr](element, value); 1803 if (value === false || value === null) 1804 element.removeAttribute(name); 1805 else if (value === true) 1806 element.setAttribute(name, name); 1807 else element.setAttribute(name, value); 1808 } 1809 return element; 879 1810 }, 880 1811 881 1812 getHeight: function(element) { 882 element = $(element); 883 return element.offsetHeight; 1813 return $(element).getDimensions().height; 1814 }, 1815 1816 getWidth: function(element) { 1817 return $(element).getDimensions().width; 884 1818 }, 885 1819 … … 890 1824 hasClassName: function(element, className) { 891 1825 if (!(element = $(element))) return; 892 return Element.classNames(element).include(className); 1826 var elementClassName = element.className; 1827 return (elementClassName.length > 0 && (elementClassName == className || 1828 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); 893 1829 }, 894 1830 895 1831 addClassName: function(element, className) { 896 1832 if (!(element = $(element))) return; 897 return Element.classNames(element).add(className); 1833 if (!element.hasClassName(className)) 1834 element.className += (element.className ? ' ' : '') + className; 1835 return element; 898 1836 }, 899 1837 900 1838 removeClassName: function(element, className) { 901 1839 if (!(element = $(element))) return; 902 return Element.classNames(element).remove(className); 1840 element.className = element.className.replace( 1841 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); 1842 return element; 1843 }, 1844 1845 toggleClassName: function(element, className) { 1846 if (!(element = $(element))) return; 1847 return element[element.hasClassName(className) ? 1848 'removeClassName' : 'addClassName'](className); 903 1849 }, 904 1850 … … 906 1852 cleanWhitespace: function(element) { 907 1853 element = $(element); 908 for (var i = 0; i < element.childNodes.length; i++) { 909 var node = element.childNodes[i]; 1854 var node = element.firstChild; 1855 while (node) { 1856 var nextNode = node.nextSibling; 910 1857 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 911 Element.remove(node); 912 } 1858 element.removeChild(node); 1859 node = nextNode; 1860 } 1861 return element; 913 1862 }, 914 1863 915 1864 empty: function(element) { 916 return $(element).innerHTML.match(/^\s*$/); 1865 return $(element).innerHTML.blank(); 1866 }, 1867 1868 descendantOf: function(element, ancestor) { 1869 element = $(element), ancestor = $(ancestor); 1870 1871 if (element.compareDocumentPosition) 1872 return (element.compareDocumentPosition(ancestor) & 8) === 8; 1873 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 } 1883 1884 while (element = element.parentNode) 1885 if (element == ancestor) return true; 1886 return false; 917 1887 }, 918 1888 919 1889 scrollTo: function(element) { 920 1890 element = $(element); 921 var x = element.x ? element.x : element.offsetLeft,922 y = element.y ? element.y : element.offsetTop;923 window.scrollTo(x, y);1891 var pos = element.cumulativeOffset(); 1892 window.scrollTo(pos[0], pos[1]); 1893 return element; 924 1894 }, 925 1895 926 1896 getStyle: function(element, style) { 927 1897 element = $(element); 928 var value = element.style[style.camelize()]; 1898 style = style == 'float' ? 'cssFloat' : style.camelize(); 1899 var value = element.style[style]; 929 1900 if (!value) { 930 if (document.defaultView && document.defaultView.getComputedStyle) { 931 var css = document.defaultView.getComputedStyle(element, null); 932 value = css ? css.getPropertyValue(style) : null; 933 } else if (element.currentStyle) { 934 value = element.currentStyle[style.camelize()]; 935 } 936 } 937 938 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) 939 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; 940 1901 var css = document.defaultView.getComputedStyle(element, null); 1902 value = css ? css[style] : null; 1903 } 1904 if (style == 'opacity') return value ? parseFloat(value) : 1.0; 941 1905 return value == 'auto' ? null : value; 942 1906 }, 943 1907 944 setStyle: function(element, style) { 1908 getOpacity: function(element) { 1909 return $(element).getStyle('opacity'); 1910 }, 1911 1912 setStyle: function(element, styles) { 945 1913 element = $(element); 946 for (name in style) 947 element.style[name.camelize()] = style[name]; 1914 var elementStyle = element.style, match; 1915 if (Object.isString(styles)) { 1916 element.style.cssText += ';' + styles; 1917 return styles.include('opacity') ? 1918 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; 1919 } 1920 for (var property in styles) 1921 if (property == 'opacity') element.setOpacity(styles[property]); 1922 else 1923 elementStyle[(property == 'float' || property == 'cssFloat') ? 1924 (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : 1925 property] = styles[property]; 1926 1927 return element; 1928 }, 1929 1930 setOpacity: function(element, value) { 1931 element = $(element); 1932 element.style.opacity = (value == 1 || value === '') ? '' : 1933 (value < 0.00001) ? 0 : value; 1934 return element; 948 1935 }, 949 1936 950 1937 getDimensions: function(element) { 951 1938 element = $(element); 952 if (Element.getStyle(element, 'display') != 'none') 1939 var display = $(element).getStyle('display'); 1940 if (display != 'none' && display != null) // Safari bug 953 1941 return {width: element.offsetWidth, height: element.offsetHeight}; 954 1942 … … 958 1946 var originalVisibility = els.visibility; 959 1947 var originalPosition = els.position; 1948 var originalDisplay = els.display; 960 1949 els.visibility = 'hidden'; 961 1950 els.position = 'absolute'; 962 els.display = ' ';1951 els.display = 'block'; 963 1952 var originalWidth = element.clientWidth; 964 1953 var originalHeight = element.clientHeight; 965 els.display = 'none';1954 els.display = originalDisplay; 966 1955 els.position = originalPosition; 967 1956 els.visibility = originalVisibility; … … 982 1971 } 983 1972 } 1973 return element; 984 1974 }, 985 1975 … … 994 1984 element.style.right = ''; 995 1985 } 1986 return element; 996 1987 }, 997 1988 998 1989 makeClipping: function(element) { 999 1990 element = $(element); 1000 if (element._overflow) return ;1001 element._overflow = element.style.overflow;1002 if ( (Element.getStyle(element, 'overflow') || 'visible') != 'hidden')1991 if (element._overflow) return element; 1992 element._overflow = Element.getStyle(element, 'overflow') || 'auto'; 1993 if (element._overflow !== 'hidden') 1003 1994 element.style.overflow = 'hidden'; 1995 return element; 1004 1996 }, 1005 1997 1006 1998 undoClipping: function(element) { 1007 1999 element = $(element); 1008 if (element._overflow) return; 1009 element.style.overflow = element._overflow; 1010 element._overflow = undefined; 1011 } 2000 if (!element._overflow) return element; 2001 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; 2002 element._overflow = null; 2003 return element; 2004 }, 2005 2006 cumulativeOffset: function(element) { 2007 var valueT = 0, valueL = 0; 2008 do { 2009 valueT += element.offsetTop || 0; 2010 valueL += element.offsetLeft || 0; 2011 element = element.offsetParent; 2012 } while (element); 2013 return Element._returnOffset(valueL, valueT); 2014 }, 2015 2016 positionedOffset: function(element) { 2017 var valueT = 0, valueL = 0; 2018 do { 2019 valueT += element.offsetTop || 0; 2020 valueL += element.offsetLeft || 0; 2021 element = element.offsetParent; 2022 if (element) { 2023 if (element.tagName == 'BODY') break; 2024 var p = Element.getStyle(element, 'position'); 2025 if (p == 'relative' || p == 'absolute') break; 2026 } 2027 } while (element); 2028 return Element._returnOffset(valueL, valueT); 2029 }, 2030 2031 absolutize: function(element) { 2032 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(); 2037 var top = offsets[1]; 2038 var left = offsets[0]; 2039 var width = element.clientWidth; 2040 var height = element.clientHeight; 2041 2042 element._originalLeft = left - parseFloat(element.style.left || 0); 2043 element._originalTop = top - parseFloat(element.style.top || 0); 2044 element._originalWidth = element.style.width; 2045 element._originalHeight = element.style.height; 2046 2047 element.style.position = 'absolute'; 2048 element.style.top = top + 'px'; 2049 element.style.left = left + 'px'; 2050 element.style.width = width + 'px'; 2051 element.style.height = height + 'px'; 2052 return element; 2053 }, 2054 2055 relativize: function(element) { 2056 element = $(element); 2057 if (element.getStyle('position') == 'relative') return; 2058 // Position.prepare(); // To be done manually by Scripty when it needs it. 2059 2060 element.style.position = 'relative'; 2061 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 2062 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 2063 2064 element.style.top = top + 'px'; 2065 element.style.left = left + 'px'; 2066 element.style.height = element._originalHeight; 2067 element.style.width = element._originalWidth; 2068 return element; 2069 }, 2070 2071 cumulativeScrollOffset: function(element) { 2072 var valueT = 0, valueL = 0; 2073 do { 2074 valueT += element.scrollTop || 0; 2075 valueL += element.scrollLeft || 0; 2076 element = element.parentNode; 2077 } while (element); 2078 return Element._returnOffset(valueL, valueT); 2079 }, 2080 2081 getOffsetParent: function(element) { 2082 if (element.offsetParent) return $(element.offsetParent); 2083 if (element == document.body) return $(element); 2084 2085 while ((element = element.parentNode) && element != document.body) 2086 if (Element.getStyle(element, 'position') != 'static') 2087 return $(element); 2088 2089 return $(document.body); 2090 }, 2091 2092 viewportOffset: function(forElement) { 2093 var valueT = 0, valueL = 0; 2094 2095 var element = forElement; 2096 do { 2097 valueT += element.offsetTop || 0; 2098 valueL += element.offsetLeft || 0; 2099 2100 // Safari fix 2101 if (element.offsetParent == document.body && 2102 Element.getStyle(element, 'position') == 'absolute') break; 2103 2104 } while (element = element.offsetParent); 2105 2106 element = forElement; 2107 do { 2108 if (!Prototype.Browser.Opera || element.tagName == 'BODY') { 2109 valueT -= element.scrollTop || 0; 2110 valueL -= element.scrollLeft || 0; 2111 } 2112 } while (element = element.parentNode); 2113 2114 return Element._returnOffset(valueL, valueT); 2115 }, 2116 2117 clonePosition: function(element, source) { 2118 var options = Object.extend({ 2119 setLeft: true, 2120 setTop: true, 2121 setWidth: true, 2122 setHeight: true, 2123 offsetTop: 0, 2124 offsetLeft: 0 2125 }, arguments[2] || { }); 2126 2127 // find page position of source 2128 source = $(source); 2129 var p = source.viewportOffset(); 2130 2131 // find coordinate system to use 2132 element = $(element); 2133 var delta = [0, 0]; 2134 var parent = null; 2135 // delta [0,0] will do fine with position: fixed elements, 2136 // position:absolute needs offsetParent deltas 2137 if (Element.getStyle(element, 'position') == 'absolute') { 2138 parent = element.getOffsetParent(); 2139 delta = parent.viewportOffset(); 2140 } 2141 2142 // correct by body offsets (fixes Safari) 2143 if (parent == document.body) { 2144 delta[0] -= document.body.offsetLeft; 2145 delta[1] -= document.body.offsetTop; 2146 } 2147 2148 // set position 2149 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 2150 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 2151 if (options.setWidth) element.style.width = source.offsetWidth + 'px'; 2152 if (options.setHeight) element.style.height = source.offsetHeight + 'px'; 2153 return element; 2154 } 2155 }; 2156 2157 Element.Methods.identify.counter = 1; 2158 2159 Object.extend(Element.Methods, { 2160 getElementsBySelector: Element.Methods.select, 2161 childElements: Element.Methods.immediateDescendants 1012 2162 }); 1013 2163 1014 var Toggle = new Object(); 1015 Toggle.display = Element.toggle; 1016 1017 /*--------------------------------------------------------------------------*/ 1018 1019 Abstract.Insertion = function(adjacency) { 1020 this.adjacency = adjacency; 2164 Element._attributeTranslations = { 2165 write: { 2166 names: { 2167 className: 'class', 2168 htmlFor: 'for' 2169 }, 2170 values: { } 2171 } 2172 }; 2173 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 insertions = { 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 }; 1021 2212 } 1022 2213 1023 Abstract.Insertion.prototype = { 1024 initialize: function(element, content) { 1025 this.element = $(element); 1026 this.content = content.stripScripts(); 1027 1028 if (this.adjacency && this.element.insertAdjacentHTML) { 1029 try { 1030 this.element.insertAdjacentHTML(this.adjacency, this.content); 1031 } catch (e) { 1032 if (this.element.tagName.toLowerCase() == 'tbody') { 1033 this.insertContent(this.contentFromAnonymousTable()); 1034 } else { 1035 throw e; 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 else if (Prototype.Browser.IE) { 2234 $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { 2235 Element.Methods[method] = Element.Methods[method].wrap( 2236 function(proceed, element) { 2237 element = $(element); 2238 var position = element.getStyle('position'); 2239 if (position != 'static') return proceed(element); 2240 element.setStyle({ position: 'relative' }); 2241 var value = proceed(element); 2242 element.setStyle({ position: position }); 2243 return value; 2244 } 2245 ); 2246 }); 2247 2248 Element.Methods.getStyle = function(element, style) { 2249 element = $(element); 2250 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); 2251 var value = element.style[style]; 2252 if (!value && element.currentStyle) value = element.currentStyle[style]; 2253 2254 if (style == 'opacity') { 2255 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) 2256 if (value[1]) return parseFloat(value[1]) / 100; 2257 return 1.0; 2258 } 2259 2260 if (value == 'auto') { 2261 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) 2262 return element['offset' + style.capitalize()] + 'px'; 2263 return null; 2264 } 2265 return value; 2266 }; 2267 2268 Element.Methods.setOpacity = function(element, value) { 2269 function stripAlpha(filter){ 2270 return filter.replace(/alpha\([^\)]*\)/gi,''); 2271 } 2272 element = $(element); 2273 var currentStyle = element.currentStyle; 2274 if ((currentStyle && !currentStyle.hasLayout) || 2275 (!currentStyle && element.style.zoom == 'normal')) 2276 element.style.zoom = 1; 2277 2278 var filter = element.getStyle('filter'), style = element.style; 2279 if (value == 1 || value === '') { 2280 (filter = stripAlpha(filter)) ? 2281 style.filter = filter : style.removeAttribute('filter'); 2282 return element; 2283 } else if (value < 0.00001) value = 0; 2284 style.filter = stripAlpha(filter) + 2285 'alpha(opacity=' + (value * 100) + ')'; 2286 return element; 2287 }; 2288 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); 2298 }, 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; 1036 2315 } 1037 2316 } 1038 } else { 1039 this.range = this.element.ownerDocument.createRange(); 1040 if (this.initializeRange) this.initializeRange(); 1041 this.insertContent([this.range.createContextualFragment(this.content)]); 1042 } 1043 1044 setTimeout(function() {content.evalScripts()}, 10); 1045 }, 1046 1047 contentFromAnonymousTable: function() { 1048 var div = document.createElement('div'); 1049 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; 1050 return $A(div.childNodes[0].childNodes[0].childNodes); 1051 } 2317 } 2318 }; 2319 2320 Element._attributeTranslations.write = { 2321 names: Object.clone(Element._attributeTranslations.read.names), 2322 values: { 2323 checked: function(element, value) { 2324 element.checked = !!value; 2325 }, 2326 2327 style: function(element, value) { 2328 element.style.cssText = value ? value : ''; 2329 } 2330 } 2331 }; 2332 2333 Element._attributeTranslations.has = {}; 2334 2335 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 2336 'encType maxLength readOnly longDesc').each(function(attr) { 2337 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 2338 Element._attributeTranslations.has[attr.toLowerCase()] = attr; 2339 }); 2340 2341 (function(v) { 2342 Object.extend(v, { 2343 href: v._getAttr, 2344 src: v._getAttr, 2345 type: v._getAttr, 2346 action: v._getAttrNode, 2347 disabled: v._flag, 2348 checked: v._flag, 2349 readonly: v._flag, 2350 multiple: v._flag, 2351 onload: v._getEv, 2352 onunload: v._getEv, 2353 onclick: v._getEv, 2354 ondblclick: v._getEv, 2355 onmousedown: v._getEv, 2356 onmouseup: v._getEv, 2357 onmouseover: v._getEv, 2358 onmousemove: v._getEv, 2359 onmouseout: v._getEv, 2360 onfocus: v._getEv, 2361 onblur: v._getEv, 2362 onkeypress: v._getEv, 2363 onkeydown: v._getEv, 2364 onkeyup: v._getEv, 2365 onsubmit: v._getEv, 2366 onreset: v._getEv, 2367 onselect: v._getEv, 2368 onchange: v._getEv 2369 }); 2370 })(Element._attributeTranslations.read.values); 1052 2371 } 1053 2372 1054 var Insertion = new Object(); 1055 1056 Insertion.Before = Class.create(); 1057 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { 1058 initializeRange: function() { 1059 this.range.setStartBefore(this.element); 1060 }, 1061 1062 insertContent: function(fragments) { 1063 fragments.each((function(fragment) { 1064 this.element.parentNode.insertBefore(fragment, this.element); 1065 }).bind(this)); 2373 else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { 2374 Element.Methods.setOpacity = function(element, value) { 2375 element = $(element); 2376 element.style.opacity = (value == 1) ? 0.999999 : 2377 (value === '') ? '' : (value < 0.00001) ? 0 : value; 2378 return element; 2379 }; 2380 } 2381 2382 else if (Prototype.Browser.WebKit) { 2383 Element.Methods.setOpacity = function(element, value) { 2384 element = $(element); 2385 element.style.opacity = (value == 1 || value === '') ? '' : 2386 (value < 0.00001) ? 0 : value; 2387 2388 if (value == 1) 2389 if(element.tagName == 'IMG' && element.width) { 2390 element.width++; element.width--; 2391 } else try { 2392 var n = document.createTextNode(' '); 2393 element.appendChild(n); 2394 element.removeChild(n); 2395 } catch (e) { } 2396 2397 return element; 2398 }; 2399 2400 // Safari returns margins on body which is incorrect if the child is absolutely 2401 // positioned. For performance reasons, redefine Position.cumulativeOffset for 2402 // KHTML/WebKit only. 2403 Element.Methods.cumulativeOffset = function(element) { 2404 var valueT = 0, valueL = 0; 2405 do { 2406 valueT += element.offsetTop || 0; 2407 valueL += element.offsetLeft || 0; 2408 if (element.offsetParent == document.body) 2409 if (Element.getStyle(element, 'position') == 'absolute') break; 2410 2411 element = element.offsetParent; 2412 } while (element); 2413 2414 return Element._returnOffset(valueL, valueT); 2415 }; 2416 } 2417 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) { 2442 Element.Methods.replace = function(element, content) { 2443 element = $(element); 2444 2445 if (content && content.toElement) content = content.toElement(); 2446 if (Object.isElement(content)) { 2447 element.parentNode.replaceChild(content, element); 2448 return element; 2449 } 2450 2451 content = Object.toHTML(content); 2452 var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); 2453 2454 if (Element._insertionTranslations.tags[tagName]) { 2455 var nextSibling = element.next(); 2456 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 2457 parent.removeChild(element); 2458 if (nextSibling) 2459 fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); 2460 else 2461 fragments.each(function(node) { parent.appendChild(node) }); 2462 } 2463 else element.outerHTML = content.stripScripts(); 2464 2465 content.evalScripts.bind(content).defer(); 2466 return element; 2467 }; 2468 } 2469 2470 Element._returnOffset = function(l, t) { 2471 var result = [l, t]; 2472 result.left = l; 2473 result.top = t; 2474 return result; 2475 }; 2476 2477 Element._getContentFromAnonymousElement = function(tagName, html) { 2478 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 }); 2481 return $A(div.childNodes); 2482 }; 2483 2484 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 } 2518 }, 2519 tags: { 2520 TABLE: ['<table>', '</table>', 1], 2521 TBODY: ['<table><tbody>', '</tbody></table>', 2], 2522 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], 2523 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], 2524 SELECT: ['<select>', '</select>', 1] 2525 } 2526 }; 2527 2528 (function() { 2529 this.bottom.initializeRange = this.top.initializeRange; 2530 Object.extend(this.tags, { 2531 THEAD: this.tags.TBODY, 2532 TFOOT: this.tags.TBODY, 2533 TH: this.tags.TD 2534 }); 2535 }).call(Element._insertionTranslations); 2536 2537 Element.Methods.Simulated = { 2538 hasAttribute: function(element, attribute) { 2539 attribute = Element._attributeTranslations.has[attribute] || attribute; 2540 var node = $(element).getAttributeNode(attribute); 2541 return node && node.specified; 2542 } 2543 }; 2544 2545 Element.Methods.ByTag = { }; 2546 2547 Object.extend(Element, Element.Methods); 2548 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 } 2555 2556 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]; 2574 if (Object.isFunction(value) && !(property in element)) 2575 element[property] = value.methodize(); 2576 } 2577 2578 element._extendedByPrototype = Prototype.emptyFunction; 2579 return element; 2580 2581 }, { 2582 refresh: function() { 2583 // extend methods for all tags (Safari doesn't need this) 2584 if (!Prototype.BrowserFeatures.ElementExtensions) { 2585 Object.extend(Methods, Element.Methods); 2586 Object.extend(Methods, Element.Methods.Simulated); 2587 } 2588 } 2589 }); 2590 2591 extend.refresh(); 2592 return extend; 2593 })(); 2594 2595 Element.hasAttribute = function(element, attribute) { 2596 if (element.hasAttribute) return element.hasAttribute(attribute); 2597 return Element.Methods.Simulated.hasAttribute(element, attribute); 2598 }; 2599 2600 Element.addMethods = function(methods) { 2601 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; 2602 2603 if (!methods) { 2604 Object.extend(Form, Form.Methods); 2605 Object.extend(Form.Element, Form.Element.Methods); 2606 Object.extend(Element.Methods.ByTag, { 2607 "FORM": Object.clone(Form.Methods), 2608 "INPUT": Object.clone(Form.Element.Methods), 2609 "SELECT": Object.clone(Form.Element.Methods), 2610 "TEXTAREA": Object.clone(Form.Element.Methods) 2611 }); 2612 } 2613 2614 if (arguments.length == 2) { 2615 var tagName = methods; 2616 methods = arguments[1]; 2617 } 2618 2619 if (!tagName) Object.extend(Element.Methods, methods || { }); 2620 else { 2621 if (Object.isArray(tagName)) tagName.each(extend); 2622 else extend(tagName); 2623 } 2624 2625 function extend(tagName) { 2626 tagName = tagName.toUpperCase(); 2627 if (!Element.Methods.ByTag[tagName]) 2628 Element.Methods.ByTag[tagName] = { }; 2629 Object.extend(Element.Methods.ByTag[tagName], methods); 2630 } 2631 2632 function copy(methods, destination, onlyIfAbsent) { 2633 onlyIfAbsent = onlyIfAbsent || false; 2634 for (var property in methods) { 2635 var value = methods[property]; 2636 if (!Object.isFunction(value)) continue; 2637 if (!onlyIfAbsent || !(property in destination)) 2638 destination[property] = value.methodize(); 2639 } 2640 } 2641 2642 function findDOMClass(tagName) { 2643 var klass; 2644 var trans = { 2645 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", 2646 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", 2647 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", 2648 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", 2649 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": 2650 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": 2651 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": 2652 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": 2653 "FrameSet", "IFRAME": "IFrame" 2654 }; 2655 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; 2656 if (window[klass]) return window[klass]; 2657 klass = 'HTML' + tagName + 'Element'; 2658 if (window[klass]) return window[klass]; 2659 klass = 'HTML' + tagName.capitalize() + 'Element'; 2660 if (window[klass]) return window[klass]; 2661 2662 window[klass] = { }; 2663 window[klass].prototype = document.createElement(tagName).__proto__; 2664 return window[klass]; 2665 } 2666 2667 if (F.ElementExtensions) { 2668 copy(Element.Methods, HTMLElement.prototype); 2669 copy(Element.Methods.Simulated, HTMLElement.prototype, true); 2670 } 2671 2672 if (F.SpecificElementExtensions) { 2673 for (var tag in Element.Methods.ByTag) { 2674 var klass = findDOMClass(tag); 2675 if (Object.isUndefined(klass)) continue; 2676 copy(T[tag], klass.prototype); 2677 } 2678 } 2679 2680 Object.extend(Element, Element.Methods); 2681 delete Element.ByTag; 2682 2683 if (Element.extend.refresh) Element.extend.refresh(); 2684 Element.cache = { }; 2685 }; 2686 2687 document.viewport = { 2688 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; 2704 }, 2705 2706 getScrollOffsets: function() { 2707 return Element._returnOffset( 2708 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 2709 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 2710 } 2711 }; 2712 /* Portions of the Selector class are derived from Jack Slocum’s DomQuery, 2713 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 2714 * license. Please see http://www.yui-ext.com/ for more information. */ 2715 2716 var Selector = Class.create({ 2717 initialize: function(expression) { 2718 this.expression = expression.strip(); 2719 this.compileMatcher(); 2720 }, 2721 2722 compileMatcher: function() { 2723 // Selectors with namespaced attributes can't use the XPath version 2724 if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression)) 2725 return this.compileXPathMatcher(); 2726 2727 var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 2728 c = Selector.criteria, le, p, m; 2729 2730 if (Selector._cache[e]) { 2731 this.matcher = Selector._cache[e]; 2732 return; 2733 } 2734 2735 this.matcher = ["this.matcher = function(root) {", 2736 "var r = root, h = Selector.handlers, c = false, n;"]; 2737 2738 while (e && le != e && (/\S/).test(e)) { 2739 le = e; 2740 for (var i in ps) { 2741 p = ps[i]; 2742 if (m = e.match(p)) { 2743 this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : 2744 new Template(c[i]).evaluate(m)); 2745 e = e.replace(m[0], ''); 2746 break; 2747 } 2748 } 2749 } 2750 2751 this.matcher.push("return h.unique(n);\n}"); 2752 eval(this.matcher.join('\n')); 2753 Selector._cache[this.expression] = this.matcher; 2754 }, 2755 2756 compileXPathMatcher: function() { 2757 var e = this.expression, ps = Selector.patterns, 2758 x = Selector.xpath, le, m; 2759 2760 if (Selector._cache[e]) { 2761 this.xpath = Selector._cache[e]; return; 2762 } 2763 2764 this.matcher = ['.//*']; 2765 while (e && le != e && (/\S/).test(e)) { 2766 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)); 2771 e = e.replace(m[0], ''); 2772 break; 2773 } 2774 } 2775 } 2776 2777 this.xpath = this.matcher.join(''); 2778 Selector._cache[this.expression] = this.xpath; 2779 }, 2780 2781 findElements: function(root) { 2782 root = root || document; 2783 if (this.xpath) return document._getElementsByXPath(this.xpath, root); 2784 return this.matcher(root); 2785 }, 2786 2787 match: function(element) { 2788 this.tokens = []; 2789 2790 var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 2791 var le, p, m; 2792 2793 while (e && le !== e && (/\S/).test(e)) { 2794 le = e; 2795 for (var i in ps) { 2796 p = ps[i]; 2797 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)]); 2802 e = e.replace(m[0], ''); 2803 } else { 2804 // reluctantly do a document-wide search 2805 // and look for a match in the array 2806 return this.findElements(document).include(element); 2807 } 2808 } 2809 } 2810 } 2811 2812 var match = true, name, matches; 2813 for (var i = 0, token; token = this.tokens[i]; i++) { 2814 name = token[0], matches = token[1]; 2815 if (!Selector.assertions[name](element, matches)) { 2816 match = false; break; 2817 } 2818 } 2819 2820 return match; 2821 }, 2822 2823 toString: function() { 2824 return this.expression; 2825 }, 2826 2827 inspect: function() { 2828 return "#<Selector:" + this.expression.inspect() + ">"; 1066 2829 } 1067 2830 }); 1068 2831 1069 Insertion.Top = Class.create(); 1070 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { 1071 initializeRange: function() { 1072 this.range.selectNodeContents(this.element); 1073 this.range.collapse(true); 1074 }, 1075 1076 insertContent: function(fragments) { 1077 fragments.reverse(false).each((function(fragment) { 1078 this.element.insertBefore(fragment, this.element.firstChild); 1079 }).bind(this)); 2832 Object.extend(Selector, { 2833 _cache: { }, 2834 2835 xpath: { 2836 descendant: "//*", 2837 child: "/*", 2838 adjacent: "/following-sibling::*[1]", 2839 laterSibling: '/following-sibling::*', 2840 tagName: function(m) { 2841 if (m[1] == '*') return ''; 2842 return "[local-name()='" + m[1].toLowerCase() + 2843 "' or local-name()='" + m[1].toUpperCase() + "']"; 2844 }, 2845 className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", 2846 id: "[@id='#{1}']", 2847 attrPresence: "[@#{1}]", 2848 attr: function(m) { 2849 m[3] = m[5] || m[6]; 2850 return new Template(Selector.xpath.operators[m[2]]).evaluate(m); 2851 }, 2852 pseudo: function(m) { 2853 var h = Selector.xpath.pseudos[m[1]]; 2854 if (!h) return ''; 2855 if (Object.isFunction(h)) return h(m); 2856 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); 2857 }, 2858 operators: { 2859 '=': "[@#{1}='#{3}']", 2860 '!=': "[@#{1}!='#{3}']", 2861 '^=': "[starts-with(@#{1}, '#{3}')]", 2862 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", 2863 '*=': "[contains(@#{1}, '#{3}')]", 2864 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", 2865 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" 2866 }, 2867 pseudos: { 2868 'first-child': '[not(preceding-sibling::*)]', 2869 'last-child': '[not(following-sibling::*)]', 2870 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 2871 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 2872 'checked': "[@checked]", 2873 'disabled': "[@disabled]", 2874 'enabled': "[not(@disabled)]", 2875 'not': function(m) { 2876 var e = m[6], p = Selector.patterns, 2877 x = Selector.xpath, le, m, v; 2878 2879 var exclusion = []; 2880 while (e && le != e && (/\S/).test(e)) { 2881 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); 2885 exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 2886 e = e.replace(m[0], ''); 2887 break; 2888 } 2889 } 2890 } 2891 return "[not(" + exclusion.join(" and ") + ")]"; 2892 }, 2893 'nth-child': function(m) { 2894 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); 2895 }, 2896 'nth-last-child': function(m) { 2897 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); 2898 }, 2899 'nth-of-type': function(m) { 2900 return Selector.xpath.pseudos.nth("position() ", m); 2901 }, 2902 'nth-last-of-type': function(m) { 2903 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); 2904 }, 2905 'first-of-type': function(m) { 2906 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); 2907 }, 2908 'last-of-type': function(m) { 2909 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); 2910 }, 2911 'only-of-type': function(m) { 2912 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); 2913 }, 2914 nth: function(fragment, m) { 2915 var mm, formula = m[6], predicate; 2916 if (formula == 'even') formula = '2n+0'; 2917 if (formula == 'odd') formula = '2n+1'; 2918 if (mm = formula.match(/^(\d+)$/)) // digit only 2919 return '[' + fragment + "= " + mm[1] + ']'; 2920 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 2921 if (mm[1] == "-") mm[1] = -1; 2922 var a = mm[1] ? Number(mm[1]) : 1; 2923 var b = mm[2] ? Number(mm[2]) : 0; 2924 predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + 2925 "((#{fragment} - #{b}) div #{a} >= 0)]"; 2926 return new Template(predicate).evaluate({ 2927 fragment: fragment, a: a, b: b }); 2928 } 2929 } 2930 } 2931 }, 2932 2933 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;', 2938 attr: function(m) { 2939 m[3] = (m[5] || m[6]); 2940 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); 2941 }, 2942 pseudo: function(m) { 2943 if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 2944 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); 2945 }, 2946 descendant: 'c = "descendant";', 2947 child: 'c = "child";', 2948 adjacent: 'c = "adjacent";', 2949 laterSibling: 'c = "laterSibling";' 2950 }, 2951 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 2970 assertions: { 2971 tagName: function(element, matches) { 2972 return matches[1].toUpperCase() == element.tagName.toUpperCase(); 2973 }, 2974 2975 className: function(element, matches) { 2976 return Element.hasClassName(element, matches[1]); 2977 }, 2978 2979 id: function(element, matches) { 2980 return element.id === matches[1]; 2981 }, 2982 2983 attrPresence: function(element, matches) { 2984 return Element.hasAttribute(element, matches[1]); 2985 }, 2986 2987 attr: function(element, matches) { 2988 var nodeValue = Element.readAttribute(element, matches[1]); 2989 return Selector.operators[matches[2]](nodeValue, matches[3]); 2990 } 2991 }, 2992 2993 handlers: { 2994 // UTILITY FUNCTIONS 2995 // joins two collections 2996 concat: function(a, b) { 2997 for (var i = 0, node; node = b[i]; i++) 2998 a.push(node); 2999 return a; 3000 }, 3001 3002 // marks an array of nodes for counting 3003 mark: function(nodes) { 3004 for (var i = 0, node; node = nodes[i]; i++) 3005 node._counted = true; 3006 return nodes; 3007 }, 3008 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 3018 index: function(parentNode, reverse, ofType) { 3019 parentNode._counted = true; 3020 if (reverse) { 3021 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 3022 var node = nodes[i]; 3023 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 3024 } 3025 } else { 3026 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 3027 if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 3028 } 3029 }, 3030 3031 // filters out duplicates and extends all nodes 3032 unique: function(nodes) { 3033 if (nodes.length == 0) return nodes; 3034 var results = [], n; 3035 for (var i = 0, l = nodes.length; i < l; i++) 3036 if (!(n = nodes[i])._counted) { 3037 n._counted = true; 3038 results.push(Element.extend(n)); 3039 } 3040 return Selector.handlers.unmark(results); 3041 }, 3042 3043 // COMBINATOR FUNCTIONS 3044 descendant: function(nodes) { 3045 var h = Selector.handlers; 3046 for (var i = 0, results = [], node; node = nodes[i]; i++) 3047 h.concat(results, node.getElementsByTagName('*')); 3048 return results; 3049 }, 3050 3051 child: function(nodes) { 3052 var h = Selector.handlers; 3053 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3054 for (var j = 0, children = [], child; child = node.childNodes[j]; j++) 3055 if (child.nodeType == 1 && child.tagName != '!') results.push(child); 3056 } 3057 return results; 3058 }, 3059 3060 adjacent: function(nodes) { 3061 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3062 var next = this.nextElementSibling(node); 3063 if (next) results.push(next); 3064 } 3065 return results; 3066 }, 3067 3068 laterSibling: function(nodes) { 3069 var h = Selector.handlers; 3070 for (var i = 0, results = [], node; node = nodes[i]; i++) 3071 h.concat(results, Element.nextSiblings(node)); 3072 return results; 3073 }, 3074 3075 nextElementSibling: function(node) { 3076 while (node = node.nextSibling) 3077 if (node.nodeType == 1) return node; 3078 return null; 3079 }, 3080 3081 previousElementSibling: function(node) { 3082 while (node = node.previousSibling) 3083 if (node.nodeType == 1) return node; 3084 return null; 3085 }, 3086 3087 // TOKEN FUNCTIONS 3088 tagName: function(nodes, root, tagName, combinator) { 3089 tagName = tagName.toUpperCase(); 3090 var results = [], h = Selector.handlers; 3091 if (nodes) { 3092 if (combinator) { 3093 // fastlane for ordinary descendant combinators 3094 if (combinator == "descendant") { 3095 for (var i = 0, node; node = nodes[i]; i++) 3096 h.concat(results, node.getElementsByTagName(tagName)); 3097 return results; 3098 } else nodes = this[combinator](nodes); 3099 if (tagName == "*") return nodes; 3100 } 3101 for (var i = 0, node; node = nodes[i]; i++) 3102 if (node.tagName.toUpperCase() == tagName) results.push(node); 3103 return results; 3104 } else return root.getElementsByTagName(tagName); 3105 }, 3106 3107 id: function(nodes, root, id, combinator) { 3108 var targetNode = $(id), h = Selector.handlers; 3109 if (!targetNode) return []; 3110 if (!nodes && root == document) return [targetNode]; 3111 if (nodes) { 3112 if (combinator) { 3113 if (combinator == 'child') { 3114 for (var i = 0, node; node = nodes[i]; i++) 3115 if (targetNode.parentNode == node) return [targetNode]; 3116 } else if (combinator == 'descendant') { 3117 for (var i = 0, node; node = nodes[i]; i++) 3118 if (Element.descendantOf(targetNode, node)) return [targetNode]; 3119 } else if (combinator == 'adjacent') { 3120 for (var i = 0, node; node = nodes[i]; i++) 3121 if (Selector.handlers.previousElementSibling(targetNode) == node) 3122 return [targetNode]; 3123 } else nodes = h[combinator](nodes); 3124 } 3125 for (var i = 0, node; node = nodes[i]; i++) 3126 if (node == targetNode) return [targetNode]; 3127 return []; 3128 } 3129 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; 3130 }, 3131 3132 className: function(nodes, root, className, combinator) { 3133 if (nodes && combinator) nodes = this[combinator](nodes); 3134 return Selector.handlers.byClassName(nodes, root, className); 3135 }, 3136 3137 byClassName: function(nodes, root, className) { 3138 if (!nodes) nodes = Selector.handlers.descendant([root]); 3139 var needle = ' ' + className + ' '; 3140 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { 3141 nodeClassName = node.className; 3142 if (nodeClassName.length == 0) continue; 3143 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) 3144 results.push(node); 3145 } 3146 return results; 3147 }, 3148 3149 attrPresence: function(nodes, root, attr) { 3150 if (!nodes) nodes = root.getElementsByTagName("*"); 3151 var results = []; 3152 for (var i = 0, node; node = nodes[i]; i++) 3153 if (Element.hasAttribute(node, attr)) results.push(node); 3154 return results; 3155 }, 3156 3157 attr: function(nodes, root, attr, value, operator) { 3158 if (!nodes) nodes = root.getElementsByTagName("*"); 3159 var handler = Selector.operators[operator], results = []; 3160 for (var i = 0, node; node = nodes[i]; i++) { 3161 var nodeValue = Element.readAttribute(node, attr); 3162 if (nodeValue === null) continue; 3163 if (handler(nodeValue, value)) results.push(node); 3164 } 3165 return results; 3166 }, 3167 3168 pseudo: function(nodes, name, value, root, combinator) { 3169 if (nodes && combinator) nodes = this[combinator](nodes); 3170 if (!nodes) nodes = root.getElementsByTagName("*"); 3171 return Selector.pseudos[name](nodes, value, root); 3172 } 3173 }, 3174 3175 pseudos: { 3176 'first-child': function(nodes, value, root) { 3177 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3178 if (Selector.handlers.previousElementSibling(node)) continue; 3179 results.push(node); 3180 } 3181 return results; 3182 }, 3183 'last-child': function(nodes, value, root) { 3184 for (var i = 0, results = [], node; node = nodes[i]; i++) { 3185 if (Selector.handlers.nextElementSibling(node)) continue; 3186 results.push(node); 3187 } 3188 return results; 3189 }, 3190 'only-child': function(nodes, value, root) { 3191 var h = Selector.handlers; 3192 for (var i = 0, results = [], node; node = nodes[i]; i++) 3193 if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) 3194 results.push(node); 3195 return results; 3196 }, 3197 'nth-child': function(nodes, formula, root) { 3198 return Selector.pseudos.nth(nodes, formula, root); 3199 }, 3200 'nth-last-child': function(nodes, formula, root) { 3201 return Selector.pseudos.nth(nodes, formula, root, true); 3202 }, 3203 'nth-of-type': function(nodes, formula, root) { 3204 return Selector.pseudos.nth(nodes, formula, root, false, true); 3205 }, 3206 'nth-last-of-type': function(nodes, formula, root) { 3207 return Selector.pseudos.nth(nodes, formula, root, true, true); 3208 }, 3209 'first-of-type': function(nodes, formula, root) { 3210 return Selector.pseudos.nth(nodes, "1", root, false, true); 3211 }, 3212 'last-of-type': function(nodes, formula, root) { 3213 return Selector.pseudos.nth(nodes, "1", root, true, true); 3214 }, 3215 'only-of-type': function(nodes, formula, root) { 3216 var p = Selector.pseudos; 3217 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); 3218 }, 3219 3220 // handles the an+b logic 3221 getIndices: function(a, b, total) { 3222 if (a == 0) return b > 0 ? [b] : []; 3223 return $R(1, total).inject([], function(memo, i) { 3224 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); 3225 return memo; 3226 }); 3227 }, 3228 3229 // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type 3230 nth: function(nodes, formula, root, reverse, ofType) { 3231 if (nodes.length == 0) return []; 3232 if (formula == 'even') formula = '2n+0'; 3233 if (formula == 'odd') formula = '2n+1'; 3234 var h = Selector.handlers, results = [], indexed = [], m; 3235 h.mark(nodes); 3236 for (var i = 0, node; node = nodes[i]; i++) { 3237 if (!node.parentNode._counted) { 3238 h.index(node.parentNode, reverse, ofType); 3239 indexed.push(node.parentNode); 3240 } 3241 } 3242 if (formula.match(/^\d+$/)) { // just a number 3243 formula = Number(formula); 3244 for (var i = 0, node; node = nodes[i]; i++) 3245 if (node.nodeIndex == formula) results.push(node); 3246 } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 3247 if (m[1] == "-") m[1] = -1; 3248 var a = m[1] ? Number(m[1]) : 1; 3249 var b = m[2] ? Number(m[2]) : 0; 3250 var indices = Selector.pseudos.getIndices(a, b, nodes.length); 3251 for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { 3252 for (var j = 0; j < l; j++) 3253 if (node.nodeIndex == indices[j]) results.push(node); 3254 } 3255 } 3256 h.unmark(nodes); 3257 h.unmark(indexed); 3258 return results; 3259 }, 3260 3261 'empty': function(nodes, value, root) { 3262 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; 3265 results.push(node); 3266 } 3267 return results; 3268 }, 3269 3270 'not': function(nodes, selector, root) { 3271 var h = Selector.handlers, selectorType, m; 3272 var exclusions = new Selector(selector).findElements(root); 3273 h.mark(exclusions); 3274 for (var i = 0, results = [], node; node = nodes[i]; i++) 3275 if (!node._counted) results.push(node); 3276 h.unmark(exclusions); 3277 return results; 3278 }, 3279 3280 'enabled': function(nodes, value, root) { 3281 for (var i = 0, results = [], node; node = nodes[i]; i++) 3282 if (!node.disabled) results.push(node); 3283 return results; 3284 }, 3285 3286 'disabled': function(nodes, value, root) { 3287 for (var i = 0, results = [], node; node = nodes[i]; i++) 3288 if (node.disabled) results.push(node); 3289 return results; 3290 }, 3291 3292 'checked': function(nodes, value, root) { 3293 for (var i = 0, results = [], node; node = nodes[i]; i++) 3294 if (node.checked) results.push(node); 3295 return results; 3296 } 3297 }, 3298 3299 operators: { 3300 '=': function(nv, v) { return nv == v; }, 3301 '!=': 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); }, 3305 '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 3306 '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } 3307 }, 3308 3309 matchElements: function(elements, expression) { 3310 var matches = new Selector(expression).findElements(), h = Selector.handlers; 3311 h.mark(matches); 3312 for (var i = 0, results = [], element; element = elements[i]; i++) 3313 if (element._counted) results.push(element); 3314 h.unmark(matches); 3315 return results; 3316 }, 3317 3318 findElement: function(elements, expression, index) { 3319 if (Object.isNumber(expression)) { 3320 index = expression; expression = false; 3321 } 3322 return Selector.matchElements(elements, expression || '*')[index || 0]; 3323 }, 3324 3325 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 }); 3330 var results = [], h = Selector.handlers; 3331 for (var i = 0, l = expressions.length, selector; i < l; i++) { 3332 selector = new Selector(expressions[i].strip()); 3333 h.concat(results, selector.findElements(element)); 3334 } 3335 return (l > 1) ? h.unique(results) : results; 1080 3336 } 1081 3337 }); 1082 3338 1083 Insertion.Bottom = Class.create(); 1084 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { 1085 initializeRange: function() { 1086 this.range.selectNodeContents(this.element); 1087 this.range.collapse(this.element); 1088 }, 1089 1090 insertContent: function(fragments) { 1091 fragments.each((function(fragment) { 1092 this.element.appendChild(fragment); 1093 }).bind(this)); 1094 } 1095 }); 1096 1097 Insertion.After = Class.create(); 1098 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { 1099 initializeRange: function() { 1100 this.range.setStartAfter(this.element); 1101 }, 1102 1103 insertContent: function(fragments) { 1104 fragments.each((function(fragment) { 1105 this.element.parentNode.insertBefore(fragment, 1106 this.element.nextSibling); 1107 }).bind(this)); 1108 } 1109 }); 1110 1111 /*--------------------------------------------------------------------------*/ 1112 1113 Element.ClassNames = Class.create(); 1114 Element.ClassNames.prototype = { 1115 initialize: function(element) { 1116 this.element = $(element); 1117 }, 1118 1119 _each: function(iterator) { 1120 this.element.className.split(/\s+/).select(function(name) { 1121 return name.length > 0; 1122 })._each(iterator); 1123 }, 1124 1125 set: function(className) { 1126 this.element.className = className; 1127 }, 1128 1129 add: function(classNameToAdd) { 1130 if (this.include(classNameToAdd)) return; 1131 this.set(this.toArray().concat(classNameToAdd).join(' ')); 1132 }, 1133 1134 remove: function(classNameToRemove) { 1135 if (!this.include(classNameToRemove)) return; 1136 this.set(this.select(function(className) { 1137 return className != classNameToRemove; 1138 }).join(' ')); 1139 }, 1140 1141 toString: function() { 1142 return this.toArray().join(' '); 1143 } 3339 function $$() { 3340 return Selector.findChildElements(document, $A(arguments)); 1144 3341 } 1145 1146 Object.extend(Element.ClassNames.prototype, Enumerable);1147 var Field = {1148 clear: function() {1149 for (var i = 0; i < arguments.length; i++)1150 $(arguments[i]).value = '';1151 },1152 1153 focus: function(element) {1154 $(element).focus();1155 },1156 1157 present: function() {1158 for (var i = 0; i < arguments.length; i++)1159 if ($(arguments[i]).value == '') return false;1160 return true;1161 },1162 1163 select: function(element) {1164 $(element).select();1165 },1166 1167 activate: function(element) {1168 element = $(element);1169 element.focus();1170 if (element.select)1171 element.select();1172 }1173 }1174 1175 /*--------------------------------------------------------------------------*/1176 1177 3342 var Form = { 1178 serialize: function(form) { 1179 var elements = Form.getElements($(form)); 1180 var queryComponents = new Array(); 1181 1182 for (var i = 0; i < elements.length; i++) { 1183 var queryComponent = Form.Element.serialize(elements[i]); 1184 if (queryComponent) 1185 queryComponents.push(queryComponent); 1186 } 1187 1188 return queryComponents.join('&'); 3343 reset: function(form) { 3344 $(form).reset(); 3345 return form; 3346 }, 3347 3348 serializeElements: function(elements, options) { 3349 if (typeof options != 'object') options = { hash: !!options }; 3350 else if (options.hash === undefined) options.hash = true; 3351 var key, value, submitted = false, submit = options.submit; 3352 3353 var data = elements.inject({ }, function(result, element) { 3354 if (!element.disabled && element.name) { 3355 key = element.name; value = $(element).getValue(); 3356 if (value != null && (element.type != 'submit' || (!submitted && 3357 submit !== false && (!submit || key == submit) && (submitted = true)))) { 3358 if (key in result) { 3359 // a key is already present; construct an array of values 3360 if (!Object.isArray(result[key])) result[key] = [result[key]]; 3361 result[key].push(value); 3362 } 3363 else result[key] = value; 3364 } 3365 } 3366 return result; 3367 }); 3368 3369 return options.hash ? data : Object.toQueryString(data); 3370 } 3371 }; 3372 3373 Form.Methods = { 3374 serialize: function(form, options) { 3375 return Form.serializeElements(Form.getElements(form), options); 1189 3376 }, 1190 3377 1191 3378 getElements: function(form) { 1192 form = $(form); 1193 var elements = new Array(); 1194 1195 for (tagName in Form.Element.Serializers) { 1196 var tagElements = form.getElementsByTagName(tagName); 1197 for (var j = 0; j < tagElements.length; j++) 1198 elements.push(tagElements[j]); 1199 } 1200 return elements; 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 ); 1201 3386 }, 1202 3387 … … 1205 3390 var inputs = form.getElementsByTagName('input'); 1206 3391 1207 if (!typeName && !name) 1208 return inputs; 1209 1210 var matchingInputs = new Array(); 1211 for (var i = 0; i < inputs.length; i++) { 3392 if (!typeName && !name) return $A(inputs).map(Element.extend); 3393 3394 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { 1212 3395 var input = inputs[i]; 1213 if ((typeName && input.type != typeName) || 1214 (name && input.name != name)) 3396 if ((typeName && input.type != typeName) || (name && input.name != name)) 1215 3397 continue; 1216 matchingInputs.push( input);3398 matchingInputs.push(Element.extend(input)); 1217 3399 } 1218 3400 … … 1221 3403 1222 3404 disable: function(form) { 1223 var elements = Form.getElements(form); 1224 for (var i = 0; i < elements.length; i++) { 1225 var element = elements[i]; 1226 element.blur(); 1227 element.disabled = 'true'; 1228 } 3405 form = $(form); 3406 Form.getElements(form).invoke('disable'); 3407 return form; 1229 3408 }, 1230 3409 1231 3410 enable: function(form) { 1232 var elements = Form.getElements(form); 1233 for (var i = 0; i < elements.length; i++) { 1234 var element = elements[i]; 1235 element.disabled = ''; 1236 } 3411 form = $(form); 3412 Form.getElements(form).invoke('enable'); 3413 return form; 1237 3414 }, 1238 3415 1239 3416 findFirstElement: function(form) { 1240 return Form.getElements(form).find(function(element) { 1241 return element.type != 'hidden' && !element.disabled && 1242 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 3417 var elements = $(form).getElements().findAll(function(element) { 3418 return 'hidden' != element.type && !element.disabled; 1243 3419 }); 3420 var firstByIndex = elements.findAll(function(element) { 3421 return element.hasAttribute('tabIndex') && element.tabIndex >= 0; 3422 }).sortBy(function(element) { return element.tabIndex }).first(); 3423 3424 return firstByIndex ? firstByIndex : elements.find(function(element) { 3425 return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 3426 }); 1244 3427 }, 1245 3428 1246 3429 focusFirstElement: function(form) { 1247 Field.activate(Form.findFirstElement(form)); 1248 }, 1249 1250 reset: function(form) { 1251 $(form).reset(); 1252 } 1253 } 3430 form = $(form); 3431 form.findFirstElement().activate(); 3432 return form; 3433 }, 3434 3435 request: function(form, options) { 3436 form = $(form), options = Object.clone(options || { }); 3437 3438 var params = options.parameters, action = form.readAttribute('action') || ''; 3439 if (action.blank()) action = window.location.href; 3440 options.parameters = form.serialize(true); 3441 3442 if (params) { 3443 if (Object.isString(params)) params = params.toQueryParams(); 3444 Object.extend(options.parameters, params); 3445 } 3446 3447 if (form.hasAttribute('method') && !options.method) 3448 options.method = form.method; 3449 3450 return new Ajax.Request(action, options); 3451 } 3452 }; 3453 3454 /*--------------------------------------------------------------------------*/ 1254 3455 1255 3456 Form.Element = { 3457 focus: function(element) { 3458 $(element).focus(); 3459 return element; 3460 }, 3461 3462 select: function(element) { 3463 $(element).select(); 3464 return element; 3465 } 3466 }; 3467 3468 Form.Element.Methods = { 1256 3469 serialize: function(element) { 1257 3470 element = $(element); 1258 var method = element.tagName.toLowerCase(); 1259 var parameter = Form.Element.Serializers[method](element); 1260 1261 if (parameter) { 1262 var key = encodeURIComponent(parameter[0]); 1263 if (key.length == 0) return; 1264 1265 if (parameter[1].constructor != Array) 1266 parameter[1] = [parameter[1]]; 1267 1268 return parameter[1].map(function(value) { 1269 return key + '=' + encodeURIComponent(value); 1270 }).join('&'); 1271 } 3471 if (!element.disabled && element.name) { 3472 var value = element.getValue(); 3473 if (value != undefined) { 3474 var pair = { }; 3475 pair[element.name] = value; 3476 return Object.toQueryString(pair); 3477 } 3478 } 3479 return ''; 1272 3480 }, 1273 3481 … … 1275 3483 element = $(element); 1276 3484 var method = element.tagName.toLowerCase(); 1277 var parameter = Form.Element.Serializers[method](element); 1278 1279 if (parameter) 1280 return parameter[1]; 1281 } 1282 } 3485 return Form.Element.Serializers[method](element); 3486 }, 3487 3488 setValue: function(element, value) { 3489 element = $(element); 3490 var method = element.tagName.toLowerCase(); 3491 Form.Element.Serializers[method](element, value); 3492 return element; 3493 }, 3494 3495 clear: function(element) { 3496 $(element).value = ''; 3497 return element; 3498 }, 3499 3500 present: function(element) { 3501 return $(element).value != ''; 3502 }, 3503 3504 activate: function(element) { 3505 element = $(element); 3506 try { 3507 element.focus(); 3508 if (element.select && (element.tagName.toLowerCase() != 'input' || 3509 !['button', 'reset', 'submit'].include(element.type))) 3510 element.select(); 3511 } catch (e) { } 3512 return element; 3513 }, 3514 3515 disable: function(element) { 3516 element = $(element); 3517 element.blur(); 3518 element.disabled = true; 3519 return element; 3520 }, 3521 3522 enable: function(element) { 3523 element = $(element); 3524 element.disabled = false; 3525 return element; 3526 } 3527 }; 3528 3529 /*--------------------------------------------------------------------------*/ 3530 3531 var Field = Form.Element; 3532 var $F = Form.Element.Methods.getValue; 3533 3534 /*--------------------------------------------------------------------------*/ 1283 3535 1284 3536 Form.Element.Serializers = { 1285 input: function(element ) {3537 input: function(element, value) { 1286 3538 switch (element.type.toLowerCase()) { 1287 case 'submit':1288 case 'hidden':1289 case 'password':1290 case 'text':1291 return Form.Element.Serializers.textarea(element);1292 3539 case 'checkbox': 1293 3540 case 'radio': 1294 return Form.Element.Serializers.inputSelector(element); 1295 } 1296 return false; 1297 }, 1298 1299 inputSelector: function(element) { 1300 if (element.checked) 1301 return [element.name, element.value]; 1302 }, 1303 1304 textarea: function(element) { 1305 return [element.name, element.value]; 1306 }, 1307 1308 select: function(element) { 1309 return Form.Element.Serializers[element.type == 'select-one' ? 1310 'selectOne' : 'selectMany'](element); 3541 return Form.Element.Serializers.inputSelector(element, value); 3542 default: 3543 return Form.Element.Serializers.textarea(element, value); 3544 } 3545 }, 3546 3547 inputSelector: function(element, value) { 3548 if (value === undefined) return element.checked ? element.value : null; 3549 else element.checked = !!value; 3550 }, 3551 3552 textarea: function(element, value) { 3553 if (value === undefined) return element.value; 3554 else element.value = value; 3555 }, 3556 3557 select: function(element, index) { 3558 if (index === undefined) 3559 return this[element.type == 'select-one' ? 3560 'selectOne' : 'selectMany'](element); 3561 else { 3562 var opt, value, single = !Object.isArray(index); 3563 for (var i = 0, length = element.length; i < length; i++) { 3564 opt = element.options[i]; 3565 value = this.optionValue(opt); 3566 if (single) { 3567 if (value == index) { 3568 opt.selected = true; 3569 return; 3570 } 3571 } 3572 else opt.selected = index.include(value); 3573 } 3574 } 1311 3575 }, 1312 3576 1313 3577 selectOne: function(element) { 1314 var value = '', opt, index = element.selectedIndex; 1315 if (index >= 0) { 1316 opt = element.options[index]; 1317 value = opt.value; 1318 if (!value && !('value' in opt)) 1319 value = opt.text; 1320 } 1321 return [element.name, value]; 3578 var index = element.selectedIndex; 3579 return index >= 0 ? this.optionValue(element.options[index]) : null; 1322 3580 }, 1323 3581 1324 3582 selectMany: function(element) { 1325 var value = new Array(); 1326 for (var i = 0; i < element.length; i++) { 3583 var values, length = element.length; 3584 if (!length) return null; 3585 3586 for (var i = 0, values = []; i < length; i++) { 1327 3587 var opt = element.options[i]; 1328 if (opt.selected) {1329 var optValue = opt.value;1330 if (!optValue && !('value' in opt))1331 optValue = opt.text;1332 value.push(optValue); 1333 }1334 }1335 return [element.name, value];1336 } 1337 } 3588 if (opt.selected) values.push(this.optionValue(opt)); 3589 } 3590 return values; 3591 }, 3592 3593 optionValue: function(opt) { 3594 // extend element because hasAttribute may not be native 3595 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 3596 } 3597 }; 1338 3598 1339 3599 /*--------------------------------------------------------------------------*/ 1340 3600 1341 var $F = Form.Element.getValue; 1342 1343 /*--------------------------------------------------------------------------*/ 1344 1345 Abstract.TimedObserver = function() {} 1346 Abstract.TimedObserver.prototype = { 1347 initialize: function(element, frequency, callback) { 1348 this.frequency = frequency; 3601 Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 3602 initialize: function($super, element, frequency, callback) { 3603 $super(callback, frequency); 1349 3604 this.element = $(element); 1350 this.callback = callback;1351 1352 3605 this.lastValue = this.getValue(); 1353 this.registerCallback(); 1354 }, 1355 1356 registerCallback: function() { 1357 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 1358 }, 1359 1360 onTimerEvent: function() { 3606 }, 3607 3608 execute: function() { 1361 3609 var value = this.getValue(); 1362 if (this.lastValue != value) { 3610 if (Object.isString(this.lastValue) && Object.isString(value) ? 3611 this.lastValue != value : String(this.lastValue) != String(value)) { 1363 3612 this.callback(this.element, value); 1364 3613 this.lastValue = value; 1365 3614 } 1366 3615 } 1367 } 1368 1369 Form.Element.Observer = Class.create(); 1370 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 3616 }); 3617 3618 Form.Element.Observer = Class.create(Abstract.TimedObserver, { 1371 3619 getValue: function() { 1372 3620 return Form.Element.getValue(this.element); … … 1374 3622 }); 1375 3623 1376 Form.Observer = Class.create(); 1377 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { 3624 Form.Observer = Class.create(Abstract.TimedObserver, { 1378 3625 getValue: function() { 1379 3626 return Form.serialize(this.element); … … 1383 3630 /*--------------------------------------------------------------------------*/ 1384 3631 1385 Abstract.EventObserver = function() {} 1386 Abstract.EventObserver.prototype = { 3632 Abstract.EventObserver = Class.create({ 1387 3633 initialize: function(element, callback) { 1388 3634 this.element = $(element); … … 1405 3651 1406 3652 registerFormCallbacks: function() { 1407 var elements = Form.getElements(this.element); 1408 for (var i = 0; i < elements.length; i++) 1409 this.registerCallback(elements[i]); 3653 Form.getElements(this.element).each(this.registerCallback, this); 1410 3654 }, 1411 3655 … … 1417 3661 Event.observe(element, 'click', this.onElementEvent.bind(this)); 1418 3662 break; 1419 case 'password': 1420 case 'text': 1421 case 'textarea': 1422 case 'select-one': 1423 case 'select-multiple': 3663 default: 1424 3664 Event.observe(element, 'change', this.onElementEvent.bind(this)); 1425 3665 break; … … 1427 3667 } 1428 3668 } 1429 } 1430 1431 Form.Element.EventObserver = Class.create(); 1432 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 3669 }); 3670 3671 Form.Element.EventObserver = Class.create(Abstract.EventObserver, { 1433 3672 getValue: function() { 1434 3673 return Form.Element.getValue(this.element); … … 1436 3675 }); 1437 3676 1438 Form.EventObserver = Class.create(); 1439 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { 3677 Form.EventObserver = Class.create(Abstract.EventObserver, { 1440 3678 getValue: function() { 1441 3679 return Form.serialize(this.element); 1442 3680 } 1443 3681 }); 1444 if (!window.Event) { 1445 var Event = new Object(); 1446 } 3682 if (!window.Event) var Event = { }; 1447 3683 1448 3684 Object.extend(Event, { … … 1456 3692 KEY_DOWN: 40, 1457 3693 KEY_DELETE: 46, 1458 1459 element: function(event) { 1460 return event.target || event.srcElement; 1461 }, 1462 1463 isLeftClick: function(event) { 1464 return (((event.which) && (event.which == 1)) || 1465 ((event.button) && (event.button == 1))); 1466 }, 1467 1468 pointerX: function(event) { 1469 return event.pageX || (event.clientX + 1470 (document.documentElement.scrollLeft || document.body.scrollLeft)); 1471 }, 1472 1473 pointerY: function(event) { 1474 return event.pageY || (event.clientY + 1475 (document.documentElement.scrollTop || document.body.scrollTop)); 1476 }, 1477 1478 stop: function(event) { 1479 if (event.preventDefault) { 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 3716 if (Prototype.Browser.IE) { 3717 var buttonMap = { 0: 1, 1: 4, 2: 2 }; 3718 isButton = function(event, code) { 3719 return event.button == buttonMap[code]; 3720 }; 3721 3722 } else if (Prototype.Browser.WebKit) { 3723 isButton = function(event, code) { 3724 switch (code) { 3725 case 0: return event.which == 1 && !event.metaKey; 3726 case 1: return event.which == 1 && event.metaKey; 3727 default: return false; 3728 } 3729 }; 3730 3731 } else { 3732 isButton = function(event, code) { 3733 return event.which ? (event.which === code + 1) : (event.button === code); 3734 }; 3735 } 3736 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); 1480 3766 event.preventDefault(); 1481 3767 event.stopPropagation(); 3768 event.stopped = true; 3769 } 3770 }; 3771 })(); 3772 3773 Event.extend = (function() { 3774 var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 3775 m[name] = Event.Methods[name].methodize(); 3776 return m; 3777 }); 3778 3779 if (Prototype.Browser.IE) { 3780 Object.extend(methods, { 3781 stopPropagation: function() { this.cancelBubble = true }, 3782 preventDefault: function() { this.returnValue = false }, 3783 inspect: function() { return "[object Event]" } 3784 }); 3785 3786 return function(event) { 3787 if (!event) return false; 3788 if (event._extendedByPrototype) return event; 3789 3790 event._extendedByPrototype = Prototype.emptyFunction; 3791 var pointer = Event.pointer(event); 3792 Object.extend(event, { 3793 target: event.srcElement, 3794 relatedTarget: Event.relatedTarget(event), 3795 pageX: pointer.x, 3796 pageY: pointer.y 3797 }); 3798 return Object.extend(event, methods); 3799 }; 3800 3801 } else { 3802 Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; 3803 Object.extend(Event.prototype, methods); 3804 return Prototype.K; 3805 } 3806 })(); 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.stopObserving 3952 }); 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 3960 (function() { 3961 /* 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; 3965 3966 function fireContentLoadedEvent() { 3967 if (fired) return; 3968 if (timer) window.clearInterval(timer); 3969 document.fire("dom:loaded"); 3970 fired = true; 3971 } 3972 3973 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 1482 3982 } else { 1483 event.returnValue = false; 1484 event.cancelBubble = true; 1485 } 1486 }, 1487 1488 // find the first node with the given tagName, starting from the 1489 // node the event was triggered on; traverses the DOM upwards 1490 findElement: function(event, tagName) { 1491 var element = Event.element(event); 1492 while (element.parentNode && (!element.tagName || 1493 (element.tagName.toUpperCase() != tagName.toUpperCase()))) 1494 element = element.parentNode; 1495 return element; 1496 }, 1497 1498 observers: false, 1499 1500 _observeAndCache: function(element, name, observer, useCapture) { 1501 if (!this.observers) this.observers = []; 1502 if (element.addEventListener) { 1503 this.observers.push([element, name, observer, useCapture]); 1504 element.addEventListener(name, observer, useCapture); 1505 } else if (element.attachEvent) { 1506 this.observers.push([element, name, observer, useCapture]); 1507 element.attachEvent('on' + name, observer); 1508 } 1509 }, 1510 1511 unloadCache: function() { 1512 if (!Event.observers) return; 1513 for (var i = 0; i < Event.observers.length; i++) { 1514 Event.stopObserving.apply(this, Event.observers[i]); 1515 Event.observers[i][0] = null; 1516 } 1517 Event.observers = false; 1518 }, 1519 1520 observe: function(element, name, observer, useCapture) { 1521 var element = $(element); 1522 useCapture = useCapture || false; 1523 1524 if (name == 'keypress' && 1525 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1526 || element.attachEvent)) 1527 name = 'keydown'; 1528 1529 this._observeAndCache(element, name, observer, useCapture); 1530 }, 1531 1532 stopObserving: function(element, name, observer, useCapture) { 1533 var element = $(element); 1534 useCapture = useCapture || false; 1535 1536 if (name == 'keypress' && 1537 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) 1538 || element.detachEvent)) 1539 name = 'keydown'; 1540 1541 if (element.removeEventListener) { 1542 element.removeEventListener(name, observer, useCapture); 1543 } else if (element.detachEvent) { 1544 element.detachEvent('on' + name, observer); 1545 } 1546 } 1547 }); 1548 1549 /* prevent memory leaks in IE */ 1550 Event.observe(window, 'unload', Event.unloadCache, false); 3983 document.addEventListener("DOMContentLoaded", 3984 fireContentLoadedEvent, false); 3985 } 3986 3987 } 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 } 3996 })(); 3997 /*------------------------------- DEPRECATED -------------------------------*/ 3998 3999 Hash.toQueryString = Object.toQueryString; 4000 4001 var Toggle = { display: Element.toggle }; 4002 4003 Element.Methods.childOf = Element.Methods.descendantOf; 4004 4005 var Insertion = { 4006 Before: function(element, content) { 4007 return Element.insert(element, {before:content}); 4008 }, 4009 4010 Top: function(element, content) { 4011 return Element.insert(element, {top:content}); 4012 }, 4013 4014 Bottom: function(element, content) { 4015 return Element.insert(element, {bottom:content}); 4016 }, 4017 4018 After: function(element, content) { 4019 return Element.insert(element, {after:content}); 4020 } 4021 }; 4022 4023 var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 4024 4025 // This should be moved to script.aculo.us; notice the deprecated methods 4026 // further below, that map to the newer Element methods. 1551 4027 var Position = { 1552 4028 // set to true if needed, warning: firefox performance problems … … 1568 4044 }, 1569 4045 1570 realOffset: function(element) {1571 var valueT = 0, valueL = 0;1572 do {1573 valueT += element.scrollTop || 0;1574 valueL += element.scrollLeft || 0;1575 element = element.parentNode;1576 } while (element);1577 return [valueL, valueT];1578 },1579 1580 cumulativeOffset: function(element) {1581 var valueT = 0, valueL = 0;1582 do {1583 valueT += element.offsetTop || 0;1584 valueL += element.offsetLeft || 0;1585 element = element.offsetParent;1586 } while (element);1587 return [valueL, valueT];1588 },1589 1590 positionedOffset: function(element) {1591 var valueT = 0, valueL = 0;1592 do {1593 valueT += element.offsetTop || 0;1594 valueL += element.offsetLeft || 0;1595 element = element.offsetParent;1596 if (element) {1597 p = Element.getStyle(element, 'position');1598 if (p == 'relative' || p == 'absolute') break;1599 }1600 } while (element);1601 return [valueL, valueT];1602 },1603 1604 offsetParent: function(element) {1605 if (element.offsetParent) return element.offsetParent;1606 if (element == document.body) return element;1607 1608 while ((element = element.parentNode) && element != document.body)1609 if (Element.getStyle(element, 'position') != 'static')1610 return element;1611 1612 return document.body;1613 },1614 1615 4046 // caches x/y coordinate pair to use with overlap 1616 4047 within: function(element, x, y) { … … 1619 4050 this.xcomp = x; 1620 4051 this.ycomp = y; 1621 this.offset = this.cumulativeOffset(element);4052 this.offset = Element.cumulativeOffset(element); 1622 4053 1623 4054 return (y >= this.offset[1] && … … 1628 4059 1629 4060 withinIncludingScrolloffsets: function(element, x, y) { 1630 var offsetcache = this.realOffset(element);4061 var offsetcache = Element.cumulativeScrollOffset(element); 1631 4062 1632 4063 this.xcomp = x + offsetcache[0] - this.deltaX; 1633 4064 this.ycomp = y + offsetcache[1] - this.deltaY; 1634 this.offset = this.cumulativeOffset(element);4065 this.offset = Element.cumulativeOffset(element); 1635 4066 1636 4067 return (this.ycomp >= this.offset[1] && … … 1651 4082 }, 1652 4083 1653 clone: function(source, target) { 1654 source = $(source); 1655 target = $(target); 1656 target.style.position = 'absolute'; 1657 var offsets = this.cumulativeOffset(source); 1658 target.style.top = offsets[1] + 'px'; 1659 target.style.left = offsets[0] + 'px'; 1660 target.style.width = source.offsetWidth + 'px'; 1661 target.style.height = source.offsetHeight + 'px'; 1662 }, 1663 1664 page: function(forElement) { 1665 var valueT = 0, valueL = 0; 1666 1667 var element = forElement; 1668 do { 1669 valueT += element.offsetTop || 0; 1670 valueL += element.offsetLeft || 0; 1671 1672 // Safari fix 1673 if (element.offsetParent==document.body) 1674 if (Element.getStyle(element,'position')=='absolute') break; 1675 1676 } while (element = element.offsetParent); 1677 1678 element = forElement; 1679 do { 1680 valueT -= element.scrollTop || 0; 1681 valueL -= element.scrollLeft || 0; 1682 } while (element = element.parentNode); 1683 1684 return [valueL, valueT]; 1685 }, 1686 1687 clone: function(source, target) { 1688 var options = Object.extend({ 1689 setLeft: true, 1690 setTop: true, 1691 setWidth: true, 1692 setHeight: true, 1693 offsetTop: 0, 1694 offsetLeft: 0 1695 }, arguments[2] || {}) 1696 1697 // find page position of source 1698 source = $(source); 1699 var p = Position.page(source); 1700 1701 // find coordinate system to use 1702 target = $(target); 1703 var delta = [0, 0]; 1704 var parent = null; 1705 // delta [0,0] will do fine with position: fixed elements, 1706 // position:absolute needs offsetParent deltas 1707 if (Element.getStyle(target,'position') == 'absolute') { 1708 parent = Position.offsetParent(target); 1709 delta = Position.page(parent); 1710 } 1711 1712 // correct by body offsets (fixes Safari) 1713 if (parent == document.body) { 1714 delta[0] -= document.body.offsetLeft; 1715 delta[1] -= document.body.offsetTop; 1716 } 1717 1718 // set position 1719 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; 1720 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; 1721 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; 1722 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; 1723 }, 4084 // Deprecation layer -- use newer Element methods now (1.5.2). 4085 4086 cumulativeOffset: Element.Methods.cumulativeOffset, 4087 4088 positionedOffset: Element.Methods.positionedOffset, 1724 4089 1725 4090 absolutize: function(element) { 1726 element = $(element);1727 if (element.style.position == 'absolute') return;1728 4091 Position.prepare(); 1729 1730 var offsets = Position.positionedOffset(element); 1731 var top = offsets[1]; 1732 var left = offsets[0]; 1733 var width = element.clientWidth; 1734 var height = element.clientHeight; 1735 1736 element._originalLeft = left - parseFloat(element.style.left || 0); 1737 element._originalTop = top - parseFloat(element.style.top || 0); 1738 element._originalWidth = element.style.width; 1739 element._originalHeight = element.style.height; 1740 1741 element.style.position = 'absolute'; 1742 element.style.top = top + 'px';; 1743 element.style.left = left + 'px';; 1744 element.style.width = width + 'px';; 1745 element.style.height = height + 'px';; 4092 return Element.absolutize(element); 1746 4093 }, 1747 4094 1748 4095 relativize: function(element) { 1749 element = $(element);1750 if (element.style.position == 'relative') return;1751 4096 Position.prepare(); 1752 1753 element.style.position = 'relative'; 1754 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); 1755 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); 1756 1757 element.style.top = top + 'px'; 1758 element.style.left = left + 'px'; 1759 element.style.height = element._originalHeight; 1760 element.style.width = element._originalWidth; 1761 } 1762 } 1763 1764 // Safari returns margins on body which is incorrect if the child is absolutely 1765 // positioned. For performance reasons, redefine Position.cumulativeOffset for 1766 // KHTML/WebKit only. 1767 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { 1768 Position.cumulativeOffset = function(element) { 1769 var valueT = 0, valueL = 0; 1770 do { 1771 valueT += element.offsetTop || 0; 1772 valueL += element.offsetLeft || 0; 1773 if (element.offsetParent == document.body) 1774 if (Element.getStyle(element, 'position') == 'absolute') break; 1775 1776 element = element.offsetParent; 1777 } while (element); 1778 1779 return [valueL, valueT]; 1780 } 1781 } 4097 return Element.relativize(element); 4098 }, 4099 4100 realOffset: Element.Methods.cumulativeScrollOffset, 4101 4102 offsetParent: Element.Methods.getOffsetParent, 4103 4104 page: Element.Methods.viewportOffset, 4105 4106 clone: function(source, target, options) { 4107 options = options || { }; 4108 return Element.clonePosition(target, source, options); 4109 } 4110 }; 4111 4112 /*--------------------------------------------------------------------------*/ 4113 4114 if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ 4115 function iter(name) { 4116 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; 4117 } 4118 4119 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? 4120 function(element, className) { 4121 className = className.toString().strip(); 4122 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); 4123 return cond ? document._getElementsByXPath('.//*' + cond, element) : []; 4124 } : function(element, className) { 4125 className = className.toString().strip(); 4126 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); 4127 if (!classNames && !className) return elements; 4128 4129 var nodes = $(element).getElementsByTagName('*'); 4130 className = ' ' + className + ' '; 4131 4132 for (var i = 0, child, cn; child = nodes[i]; i++) { 4133 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || 4134 (classNames && classNames.all(function(name) { 4135 return !name.toString().blank() && cn.include(' ' + name + ' '); 4136 })))) 4137 elements.push(Element.extend(child)); 4138 } 4139 return elements; 4140 }; 4141 4142 return function(className, parentElement) { 4143 return $(parentElement || document.body).getElementsByClassName(className); 4144 }; 4145 }(Element.Methods); 4146 4147 /*--------------------------------------------------------------------------*/ 4148 4149 Element.ClassNames = Class.create(); 4150 Element.ClassNames.prototype = { 4151 initialize: function(element) { 4152 this.element = $(element); 4153 }, 4154 4155 _each: function(iterator) { 4156 this.element.className.split(/\s+/).select(function(name) { 4157 return name.length > 0; 4158 })._each(iterator); 4159 }, 4160 4161 set: function(className) { 4162 this.element.className = className; 4163 }, 4164 4165 add: function(classNameToAdd) { 4166 if (this.include(classNameToAdd)) return; 4167 this.set($A(this).concat(classNameToAdd).join(' ')); 4168 }, 4169 4170 remove: function(classNameToRemove) { 4171 if (!this.include(classNameToRemove)) return; 4172 this.set($A(this).without(classNameToRemove).join(' ')); 4173 }, 4174 4175 toString: function() { 4176 return $A(this).join(' '); 4177 } 4178 }; 4179 4180 Object.extend(Element.ClassNames.prototype, Enumerable); 4181 4182 /*--------------------------------------------------------------------------*/ 4183 4184 Element.addMethods();
Note: See TracChangeset
for help on using the changeset viewer.