WordPress.org

Make WordPress Core

Ticket #11594: porototype.update.to.1.6.1.patch

File porototype.update.to.1.6.1.patch, 139.8 KB (added by Simek, 6 years ago)
  • prototype.js

     
    1 /*  Prototype JavaScript framework, version 1.6.0 
    2  *  (c) 2005-2007 Sam Stephenson 
     1/*  Prototype JavaScript framework, version 1.6.1 
     2 *  (c) 2005-2009 Sam Stephenson 
    33 * 
    44 *  Prototype is freely distributable under the terms of an MIT-style license. 
    55 *  For details, see the Prototype web site: http://www.prototypejs.org/ 
     
    77 *--------------------------------------------------------------------------*/ 
    88 
    99var Prototype = { 
    10   Version: '1.6.0', 
     10  Version: '1.6.1', 
    1111 
    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   }, 
     12  Browser: (function(){ 
     13    var ua = navigator.userAgent; 
     14    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; 
     15    return { 
     16      IE:             !!window.attachEvent && !isOpera, 
     17      Opera:          isOpera, 
     18      WebKit:         ua.indexOf('AppleWebKit/') > -1, 
     19      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, 
     20      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua) 
     21    } 
     22  })(), 
    1923 
    2024  BrowserFeatures: { 
    2125    XPath: !!document.evaluate, 
    22     ElementExtensions: !!window.HTMLElement, 
    23     SpecificElementExtensions: 
    24       document.createElement('div').__proto__ && 
    25       document.createElement('div').__proto__ !== 
    26         document.createElement('form').__proto__ 
     26    SelectorsAPI: !!document.querySelector, 
     27    ElementExtensions: (function() { 
     28      var constructor = window.Element || window.HTMLElement; 
     29      return !!(constructor && constructor.prototype); 
     30    })(), 
     31    SpecificElementExtensions: (function() { 
     32      if (typeof window.HTMLDivElement !== 'undefined') 
     33        return true; 
     34 
     35      var div = document.createElement('div'); 
     36      var form = document.createElement('form'); 
     37      var isSupported = false; 
     38 
     39      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { 
     40        isSupported = true; 
     41      } 
     42 
     43      div = form = null; 
     44 
     45      return isSupported; 
     46    })() 
    2747  }, 
    2848 
    2949  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', 
     
    3656if (Prototype.Browser.MobileSafari) 
    3757  Prototype.BrowserFeatures.SpecificElementExtensions = false; 
    3858 
    39 if (Prototype.Browser.WebKit) 
    40   Prototype.BrowserFeatures.XPath = false; 
    4159 
     60var Abstract = { }; 
     61 
     62 
     63var Try = { 
     64  these: function() { 
     65    var returnValue; 
     66 
     67    for (var i = 0, length = arguments.length; i < length; i++) { 
     68      var lambda = arguments[i]; 
     69      try { 
     70        returnValue = lambda(); 
     71        break; 
     72      } catch (e) { } 
     73    } 
     74 
     75    return returnValue; 
     76  } 
     77}; 
     78 
    4279/* Based on Alex Arnell's inheritance implementation. */ 
    43 var Class = { 
    44   create: function() { 
     80 
     81var Class = (function() { 
     82  function subclass() {}; 
     83  function create() { 
    4584    var parent = null, properties = $A(arguments); 
    4685    if (Object.isFunction(properties[0])) 
    4786      parent = properties.shift(); 
     
    5594    klass.subclasses = []; 
    5695 
    5796    if (parent) { 
    58       var subclass = function() { }; 
    5997      subclass.prototype = parent.prototype; 
    6098      klass.prototype = new subclass; 
    6199      parent.subclasses.push(klass); 
     
    68106      klass.prototype.initialize = Prototype.emptyFunction; 
    69107 
    70108    klass.prototype.constructor = klass; 
    71  
    72109    return klass; 
    73110  } 
    74 }; 
    75111 
    76 Class.Methods = { 
    77   addMethods: function(source) { 
     112  function addMethods(source) { 
    78113    var ancestor   = this.superclass && this.superclass.prototype; 
    79114    var properties = Object.keys(source); 
    80115 
    81     if (!Object.keys({ toString: true }).length) 
    82       properties.push("toString", "valueOf"); 
     116    if (!Object.keys({ toString: true }).length) { 
     117      if (source.toString != Object.prototype.toString) 
     118        properties.push("toString"); 
     119      if (source.valueOf != Object.prototype.valueOf) 
     120        properties.push("valueOf"); 
     121    } 
    83122 
    84123    for (var i = 0, length = properties.length; i < length; i++) { 
    85124      var property = properties[i], value = source[property]; 
    86125      if (ancestor && Object.isFunction(value) && 
    87126          value.argumentNames().first() == "$super") { 
    88         var method = value, value = Object.extend((function(m) { 
    89           return function() { return ancestor[m].apply(this, arguments) }; 
    90         })(property).wrap(method), { 
    91           valueOf:  function() { return method }, 
    92           toString: function() { return method.toString() } 
    93         }); 
     127        var method = value; 
     128        value = (function(m) { 
     129          return function() { return ancestor[m].apply(this, arguments); }; 
     130        })(property).wrap(method); 
     131 
     132        value.valueOf = method.valueOf.bind(method); 
     133        value.toString = method.toString.bind(method); 
    94134      } 
    95135      this.prototype[property] = value; 
    96136    } 
    97137 
    98138    return this; 
    99139  } 
    100 }; 
    101140 
    102 var Abstract = { }; 
     141  return { 
     142    create: create, 
     143    Methods: { 
     144      addMethods: addMethods 
     145    } 
     146  }; 
     147})(); 
     148(function() { 
    103149 
    104 Object.extend = function(destination, source) { 
    105   for (var property in source) 
    106     destination[property] = source[property]; 
    107   return destination; 
    108 }; 
     150  var _toString = Object.prototype.toString; 
    109151 
    110 Object.extend(Object, { 
    111   inspect: function(object) { 
     152  function extend(destination, source) { 
     153    for (var property in source) 
     154      destination[property] = source[property]; 
     155    return destination; 
     156  } 
     157 
     158  function inspect(object) { 
    112159    try { 
    113       if (object === undefined) return 'undefined'; 
     160      if (isUndefined(object)) return 'undefined'; 
    114161      if (object === null) return 'null'; 
    115       return object.inspect ? object.inspect() : object.toString(); 
     162      return object.inspect ? object.inspect() : String(object); 
    116163    } catch (e) { 
    117164      if (e instanceof RangeError) return '...'; 
    118165      throw e; 
    119166    } 
    120   }, 
     167  } 
    121168 
    122   toJSON: function(object) { 
     169  function toJSON(object) { 
    123170    var type = typeof object; 
    124171    switch (type) { 
    125172      case 'undefined': 
     
    130177 
    131178    if (object === null) return 'null'; 
    132179    if (object.toJSON) return object.toJSON(); 
    133     if (Object.isElement(object)) return; 
     180    if (isElement(object)) return; 
    134181 
    135182    var results = []; 
    136183    for (var property in object) { 
    137       var value = Object.toJSON(object[property]); 
    138       if (value !== undefined) 
     184      var value = toJSON(object[property]); 
     185      if (!isUndefined(value)) 
    139186        results.push(property.toJSON() + ': ' + value); 
    140187    } 
    141188 
    142189    return '{' + results.join(', ') + '}'; 
    143   }, 
     190  } 
    144191 
    145   toQueryString: function(object) { 
     192  function toQueryString(object) { 
    146193    return $H(object).toQueryString(); 
    147   }, 
     194  } 
    148195 
    149   toHTML: function(object) { 
     196  function toHTML(object) { 
    150197    return object && object.toHTML ? object.toHTML() : String.interpret(object); 
    151   }, 
     198  } 
    152199 
    153   keys: function(object) { 
    154     var keys = []; 
     200  function keys(object) { 
     201    var results = []; 
    155202    for (var property in object) 
    156       keys.push(property); 
    157     return keys; 
    158   }, 
     203      results.push(property); 
     204    return results; 
     205  } 
    159206 
    160   values: function(object) { 
    161     var values = []; 
     207  function values(object) { 
     208    var results = []; 
    162209    for (var property in object) 
    163       values.push(object[property]); 
    164     return values; 
    165   }, 
     210      results.push(object[property]); 
     211    return results; 
     212  } 
    166213 
    167   clone: function(object) { 
    168     return Object.extend({ }, object); 
    169   }, 
     214  function clone(object) { 
     215    return extend({ }, object); 
     216  } 
    170217 
    171   isElement: function(object) { 
    172     return object && object.nodeType == 1; 
    173   }, 
     218  function isElement(object) { 
     219    return !!(object && object.nodeType == 1); 
     220  } 
    174221 
    175   isArray: function(object) { 
    176     return object && object.constructor === Array; 
    177   }, 
     222  function isArray(object) { 
     223    return _toString.call(object) == "[object Array]"; 
     224  } 
    178225 
    179   isHash: function(object) { 
     226 
     227  function isHash(object) { 
    180228    return object instanceof Hash; 
    181   }, 
     229  } 
    182230 
    183   isFunction: function(object) { 
    184     return typeof object == "function"; 
    185   }, 
     231  function isFunction(object) { 
     232    return typeof object === "function"; 
     233  } 
    186234 
    187   isString: function(object) { 
    188     return typeof object == "string"; 
    189   }, 
     235  function isString(object) { 
     236    return _toString.call(object) == "[object String]"; 
     237  } 
    190238 
    191   isNumber: function(object) { 
    192     return typeof object == "number"; 
    193   }, 
     239  function isNumber(object) { 
     240    return _toString.call(object) == "[object Number]"; 
     241  } 
    194242 
    195   isUndefined: function(object) { 
    196     return typeof object == "undefined"; 
     243  function isUndefined(object) { 
     244    return typeof object === "undefined"; 
    197245  } 
    198 }); 
    199246 
    200 Object.extend(Function.prototype, { 
    201   argumentNames: function() { 
    202     var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); 
     247  extend(Object, { 
     248    extend:        extend, 
     249    inspect:       inspect, 
     250    toJSON:        toJSON, 
     251    toQueryString: toQueryString, 
     252    toHTML:        toHTML, 
     253    keys:          keys, 
     254    values:        values, 
     255    clone:         clone, 
     256    isElement:     isElement, 
     257    isArray:       isArray, 
     258    isHash:        isHash, 
     259    isFunction:    isFunction, 
     260    isString:      isString, 
     261    isNumber:      isNumber, 
     262    isUndefined:   isUndefined 
     263  }); 
     264})(); 
     265Object.extend(Function.prototype, (function() { 
     266  var slice = Array.prototype.slice; 
     267 
     268  function update(array, args) { 
     269    var arrayLength = array.length, length = args.length; 
     270    while (length--) array[arrayLength + length] = args[length]; 
     271    return array; 
     272  } 
     273 
     274  function merge(array, args) { 
     275    array = slice.call(array, 0); 
     276    return update(array, args); 
     277  } 
     278 
     279  function argumentNames() { 
     280    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] 
     281      .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') 
     282      .replace(/\s+/g, '').split(','); 
    203283    return names.length == 1 && !names[0] ? [] : names; 
    204   }, 
     284  } 
    205285 
    206   bind: function() { 
    207     if (arguments.length < 2 && arguments[0] === undefined) return this; 
    208     var __method = this, args = $A(arguments), object = args.shift(); 
     286  function bind(context) { 
     287    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; 
     288    var __method = this, args = slice.call(arguments, 1); 
    209289    return function() { 
    210       return __method.apply(object, args.concat($A(arguments))); 
     290      var a = merge(args, arguments); 
     291      return __method.apply(context, a); 
    211292    } 
    212   }, 
     293  } 
    213294 
    214   bindAsEventListener: function() { 
    215     var __method = this, args = $A(arguments), object = args.shift(); 
     295  function bindAsEventListener(context) { 
     296    var __method = this, args = slice.call(arguments, 1); 
    216297    return function(event) { 
    217       return __method.apply(object, [event || window.event].concat(args)); 
     298      var a = update([event || window.event], args); 
     299      return __method.apply(context, a); 
    218300    } 
    219   }, 
     301  } 
    220302 
    221   curry: function() { 
     303  function curry() { 
    222304    if (!arguments.length) return this; 
    223     var __method = this, args = $A(arguments); 
     305    var __method = this, args = slice.call(arguments, 0); 
    224306    return function() { 
    225       return __method.apply(this, args.concat($A(arguments))); 
     307      var a = merge(args, arguments); 
     308      return __method.apply(this, a); 
    226309    } 
    227   }, 
     310  } 
    228311 
    229   delay: function() { 
    230     var __method = this, args = $A(arguments), timeout = args.shift() * 1000; 
     312  function delay(timeout) { 
     313    var __method = this, args = slice.call(arguments, 1); 
     314    timeout = timeout * 1000 
    231315    return window.setTimeout(function() { 
    232316      return __method.apply(__method, args); 
    233317    }, timeout); 
    234   }, 
     318  } 
    235319 
    236   wrap: function(wrapper) { 
     320  function defer() { 
     321    var args = update([0.01], arguments); 
     322    return this.delay.apply(this, args); 
     323  } 
     324 
     325  function wrap(wrapper) { 
    237326    var __method = this; 
    238327    return function() { 
    239       return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); 
     328      var a = update([__method.bind(this)], arguments); 
     329      return wrapper.apply(this, a); 
    240330    } 
    241   }, 
     331  } 
    242332 
    243   methodize: function() { 
     333  function methodize() { 
    244334    if (this._methodized) return this._methodized; 
    245335    var __method = this; 
    246336    return this._methodized = function() { 
    247       return __method.apply(null, [this].concat($A(arguments))); 
     337      var a = update([this], arguments); 
     338      return __method.apply(null, a); 
    248339    }; 
    249340  } 
    250 }); 
    251341 
    252 Function.prototype.defer = Function.prototype.delay.curry(0.01); 
     342  return { 
     343    argumentNames:       argumentNames, 
     344    bind:                bind, 
     345    bindAsEventListener: bindAsEventListener, 
     346    curry:               curry, 
     347    delay:               delay, 
     348    defer:               defer, 
     349    wrap:                wrap, 
     350    methodize:           methodize 
     351  } 
     352})()); 
    253353 
     354 
    254355Date.prototype.toJSON = function() { 
    255356  return '"' + this.getUTCFullYear() + '-' + 
    256357    (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 
     
    260361    this.getUTCSeconds().toPaddedString(2) + 'Z"'; 
    261362}; 
    262363 
    263 var Try = { 
    264   these: function() { 
    265     var returnValue; 
    266364 
    267     for (var i = 0, length = arguments.length; i < length; i++) { 
    268       var lambda = arguments[i]; 
    269       try { 
    270         returnValue = lambda(); 
    271         break; 
    272       } catch (e) { } 
    273     } 
    274  
    275     return returnValue; 
    276   } 
    277 }; 
    278  
    279365RegExp.prototype.match = RegExp.prototype.test; 
    280366 
    281367RegExp.escape = function(str) { 
    282368  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 
    283369}; 
    284  
    285 /*--------------------------------------------------------------------------*/ 
    286  
    287370var PeriodicalExecuter = Class.create({ 
    288371  initialize: function(callback, frequency) { 
    289372    this.callback = callback; 
     
    312395      try { 
    313396        this.currentlyExecuting = true; 
    314397        this.execute(); 
    315       } finally { 
    316398        this.currentlyExecuting = false; 
     399      } catch(e) { 
     400        this.currentlyExecuting = false; 
     401        throw e; 
    317402      } 
    318403    } 
    319404  } 
     
    332417  } 
    333418}); 
    334419 
    335 Object.extend(String.prototype, { 
    336   gsub: function(pattern, replacement) { 
     420Object.extend(String.prototype, (function() { 
     421 
     422  function prepareReplacement(replacement) { 
     423    if (Object.isFunction(replacement)) return replacement; 
     424    var template = new Template(replacement); 
     425    return function(match) { return template.evaluate(match) }; 
     426  } 
     427 
     428  function gsub(pattern, replacement) { 
    337429    var result = '', source = this, match; 
    338     replacement = arguments.callee.prepareReplacement(replacement); 
     430    replacement = prepareReplacement(replacement); 
    339431 
     432    if (Object.isString(pattern)) 
     433      pattern = RegExp.escape(pattern); 
     434 
     435    if (!(pattern.length || pattern.source)) { 
     436      replacement = replacement(''); 
     437      return replacement + source.split('').join(replacement) + replacement; 
     438    } 
     439 
    340440    while (source.length > 0) { 
    341441      if (match = source.match(pattern)) { 
    342442        result += source.slice(0, match.index); 
     
    347447      } 
    348448    } 
    349449    return result; 
    350   }, 
     450  } 
    351451 
    352   sub: function(pattern, replacement, count) { 
    353     replacement = this.gsub.prepareReplacement(replacement); 
    354     count = count === undefined ? 1 : count; 
     452  function sub(pattern, replacement, count) { 
     453    replacement = prepareReplacement(replacement); 
     454    count = Object.isUndefined(count) ? 1 : count; 
    355455 
    356456    return this.gsub(pattern, function(match) { 
    357457      if (--count < 0) return match[0]; 
    358458      return replacement(match); 
    359459    }); 
    360   }, 
     460  } 
    361461 
    362   scan: function(pattern, iterator) { 
     462  function scan(pattern, iterator) { 
    363463    this.gsub(pattern, iterator); 
    364464    return String(this); 
    365   }, 
     465  } 
    366466 
    367   truncate: function(length, truncation) { 
     467  function truncate(length, truncation) { 
    368468    length = length || 30; 
    369     truncation = truncation === undefined ? '...' : truncation; 
     469    truncation = Object.isUndefined(truncation) ? '...' : truncation; 
    370470    return this.length > length ? 
    371471      this.slice(0, length - truncation.length) + truncation : String(this); 
    372   }, 
     472  } 
    373473 
    374   strip: function() { 
     474  function strip() { 
    375475    return this.replace(/^\s+/, '').replace(/\s+$/, ''); 
    376   }, 
     476  } 
    377477 
    378   stripTags: function() { 
    379     return this.replace(/<\/?[^>]+>/gi, ''); 
    380   }, 
     478  function stripTags() { 
     479    return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); 
     480  } 
    381481 
    382   stripScripts: function() { 
     482  function stripScripts() { 
    383483    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); 
    384   }, 
     484  } 
    385485 
    386   extractScripts: function() { 
     486  function extractScripts() { 
    387487    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); 
    388488    var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); 
    389489    return (this.match(matchAll) || []).map(function(scriptTag) { 
    390490      return (scriptTag.match(matchOne) || ['', ''])[1]; 
    391491    }); 
    392   }, 
     492  } 
    393493 
    394   evalScripts: function() { 
     494  function evalScripts() { 
    395495    return this.extractScripts().map(function(script) { return eval(script) }); 
    396   }, 
     496  } 
    397497 
    398   escapeHTML: function() { 
    399     var self = arguments.callee; 
    400     self.text.data = this; 
    401     return self.div.innerHTML; 
    402   }, 
     498  function escapeHTML() { 
     499    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); 
     500  } 
    403501 
    404   unescapeHTML: function() { 
    405     var div = new Element('div'); 
    406     div.innerHTML = this.stripTags(); 
    407     return div.childNodes[0] ? (div.childNodes.length > 1 ? 
    408       $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 
    409       div.childNodes[0].nodeValue) : ''; 
    410   }, 
     502  function unescapeHTML() { 
     503    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&'); 
     504  } 
    411505 
    412   toQueryParams: function(separator) { 
     506 
     507  function toQueryParams(separator) { 
    413508    var match = this.strip().match(/([^?#]*)(#.*)?$/); 
    414509    if (!match) return { }; 
    415510 
     
    427522      } 
    428523      return hash; 
    429524    }); 
    430   }, 
     525  } 
    431526 
    432   toArray: function() { 
     527  function toArray() { 
    433528    return this.split(''); 
    434   }, 
     529  } 
    435530 
    436   succ: function() { 
     531  function succ() { 
    437532    return this.slice(0, this.length - 1) + 
    438533      String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 
    439   }, 
     534  } 
    440535 
    441   times: function(count) { 
     536  function times(count) { 
    442537    return count < 1 ? '' : new Array(count + 1).join(this); 
    443   }, 
     538  } 
    444539 
    445   camelize: function() { 
     540  function camelize() { 
    446541    var parts = this.split('-'), len = parts.length; 
    447542    if (len == 1) return parts[0]; 
    448543 
     
    454549      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 
    455550 
    456551    return camelized; 
    457   }, 
     552  } 
    458553 
    459   capitalize: function() { 
     554  function capitalize() { 
    460555    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 
    461   }, 
     556  } 
    462557 
    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   }, 
     558  function underscore() { 
     559    return this.replace(/::/g, '/') 
     560               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') 
     561               .replace(/([a-z\d])([A-Z])/g, '$1_$2') 
     562               .replace(/-/g, '_') 
     563               .toLowerCase(); 
     564  } 
    466565 
    467   dasherize: function() { 
    468     return this.gsub(/_/,'-'); 
    469   }, 
     566  function dasherize() { 
     567    return this.replace(/_/g, '-'); 
     568  } 
    470569 
    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); 
     570  function inspect(useDoubleQuotes) { 
     571    var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { 
     572      if (character in String.specialChar) { 
     573        return String.specialChar[character]; 
     574      } 
     575      return '\\u00' + character.charCodeAt().toPaddedString(2, 16); 
    475576    }); 
    476577    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; 
    477578    return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 
    478   }, 
     579  } 
    479580 
    480   toJSON: function() { 
     581  function toJSON() { 
    481582    return this.inspect(true); 
    482   }, 
     583  } 
    483584 
    484   unfilterJSON: function(filter) { 
    485     return this.sub(filter || Prototype.JSONFilter, '#{1}'); 
    486   }, 
     585  function unfilterJSON(filter) { 
     586    return this.replace(filter || Prototype.JSONFilter, '$1'); 
     587  } 
    487588 
    488   isJSON: function() { 
    489     var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 
     589  function isJSON() { 
     590    var str = this; 
     591    if (str.blank()) return false; 
     592    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); 
    490593    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); 
    491   }, 
     594  } 
    492595 
    493   evalJSON: function(sanitize) { 
     596  function evalJSON(sanitize) { 
    494597    var json = this.unfilterJSON(); 
    495598    try { 
    496599      if (!sanitize || json.isJSON()) return eval('(' + json + ')'); 
    497600    } catch (e) { } 
    498601    throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); 
    499   }, 
     602  } 
    500603 
    501   include: function(pattern) { 
     604  function include(pattern) { 
    502605    return this.indexOf(pattern) > -1; 
    503   }, 
     606  } 
    504607 
    505   startsWith: function(pattern) { 
     608  function startsWith(pattern) { 
    506609    return this.indexOf(pattern) === 0; 
    507   }, 
     610  } 
    508611 
    509   endsWith: function(pattern) { 
     612  function endsWith(pattern) { 
    510613    var d = this.length - pattern.length; 
    511614    return d >= 0 && this.lastIndexOf(pattern) === d; 
    512   }, 
     615  } 
    513616 
    514   empty: function() { 
     617  function empty() { 
    515618    return this == ''; 
    516   }, 
     619  } 
    517620 
    518   blank: function() { 
     621  function blank() { 
    519622    return /^\s*$/.test(this); 
    520   }, 
     623  } 
    521624 
    522   interpolate: function(object, pattern) { 
     625  function interpolate(object, pattern) { 
    523626    return new Template(this, pattern).evaluate(object); 
    524627  } 
    525 }); 
    526628 
    527 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 
    528   escapeHTML: function() { 
    529     return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); 
    530   }, 
    531   unescapeHTML: function() { 
    532     return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>'); 
    533   } 
    534 }); 
     629  return { 
     630    gsub:           gsub, 
     631    sub:            sub, 
     632    scan:           scan, 
     633    truncate:       truncate, 
     634    strip:          String.prototype.trim ? String.prototype.trim : strip, 
     635    stripTags:      stripTags, 
     636    stripScripts:   stripScripts, 
     637    extractScripts: extractScripts, 
     638    evalScripts:    evalScripts, 
     639    escapeHTML:     escapeHTML, 
     640    unescapeHTML:   unescapeHTML, 
     641    toQueryParams:  toQueryParams, 
     642    parseQuery:     toQueryParams, 
     643    toArray:        toArray, 
     644    succ:           succ, 
     645    times:          times, 
     646    camelize:       camelize, 
     647    capitalize:     capitalize, 
     648    underscore:     underscore, 
     649    dasherize:      dasherize, 
     650    inspect:        inspect, 
     651    toJSON:         toJSON, 
     652    unfilterJSON:   unfilterJSON, 
     653    isJSON:         isJSON, 
     654    evalJSON:       evalJSON, 
     655    include:        include, 
     656    startsWith:     startsWith, 
     657    endsWith:       endsWith, 
     658    empty:          empty, 
     659    blank:          blank, 
     660    interpolate:    interpolate 
     661  }; 
     662})()); 
    535663 
    536 String.prototype.gsub.prepareReplacement = function(replacement) { 
    537   if (Object.isFunction(replacement)) return replacement; 
    538   var template = new Template(replacement); 
    539   return function(match) { return template.evaluate(match) }; 
    540 }; 
    541  
    542 String.prototype.parseQuery = String.prototype.toQueryParams; 
    543  
    544 Object.extend(String.prototype.escapeHTML, { 
    545   div:  document.createElement('div'), 
    546   text: document.createTextNode('') 
    547 }); 
    548  
    549 with (String.prototype.escapeHTML) div.appendChild(text); 
    550  
    551664var Template = Class.create({ 
    552665  initialize: function(template, pattern) { 
    553666    this.template = template.toString(); 
     
    555668  }, 
    556669 
    557670  evaluate: function(object) { 
    558     if (Object.isFunction(object.toTemplateReplacements)) 
     671    if (object && Object.isFunction(object.toTemplateReplacements)) 
    559672      object = object.toTemplateReplacements(); 
    560673 
    561674    return this.template.gsub(this.pattern, function(match) { 
    562       if (object == null) return ''; 
     675      if (object == null) return (match[1] + ''); 
    563676 
    564677      var before = match[1] || ''; 
    565678      if (before == '\\') return match[2]; 
    566679 
    567680      var ctx = object, expr = match[3]; 
    568       var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); 
     681      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 
     682      match = pattern.exec(expr); 
    569683      if (match == null) return before; 
    570684 
    571685      while (match != null) { 
    572         var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; 
     686        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; 
    573687        ctx = ctx[comp]; 
    574688        if (null == ctx || '' == match[3]) break; 
    575689        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 
     
    577691      } 
    578692 
    579693      return before + String.interpret(ctx); 
    580     }.bind(this)); 
     694    }); 
    581695  } 
    582696}); 
    583697Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; 
    584698 
    585699var $break = { }; 
    586700 
    587 var Enumerable = { 
    588   each: function(iterator, context) { 
     701var Enumerable = (function() { 
     702  function each(iterator, context) { 
    589703    var index = 0; 
    590     iterator = iterator.bind(context); 
    591704    try { 
    592705      this._each(function(value) { 
    593         iterator(value, index++); 
     706        iterator.call(context, value, index++); 
    594707      }); 
    595708    } catch (e) { 
    596709      if (e != $break) throw e; 
    597710    } 
    598711    return this; 
    599   }, 
     712  } 
    600713 
    601   eachSlice: function(number, iterator, context) { 
    602     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     714  function eachSlice(number, iterator, context) { 
    603715    var index = -number, slices = [], array = this.toArray(); 
     716    if (number < 1) return array; 
    604717    while ((index += number) < array.length) 
    605718      slices.push(array.slice(index, index+number)); 
    606719    return slices.collect(iterator, context); 
    607   }, 
     720  } 
    608721 
    609   all: function(iterator, context) { 
    610     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     722  function all(iterator, context) { 
     723    iterator = iterator || Prototype.K; 
    611724    var result = true; 
    612725    this.each(function(value, index) { 
    613       result = result && !!iterator(value, index); 
     726      result = result && !!iterator.call(context, value, index); 
    614727      if (!result) throw $break; 
    615728    }); 
    616729    return result; 
    617   }, 
     730  } 
    618731 
    619   any: function(iterator, context) { 
    620     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     732  function any(iterator, context) { 
     733    iterator = iterator || Prototype.K; 
    621734    var result = false; 
    622735    this.each(function(value, index) { 
    623       if (result = !!iterator(value, index)) 
     736      if (result = !!iterator.call(context, value, index)) 
    624737        throw $break; 
    625738    }); 
    626739    return result; 
    627   }, 
     740  } 
    628741 
    629   collect: function(iterator, context) { 
    630     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     742  function collect(iterator, context) { 
     743    iterator = iterator || Prototype.K; 
    631744    var results = []; 
    632745    this.each(function(value, index) { 
    633       results.push(iterator(value, index)); 
     746      results.push(iterator.call(context, value, index)); 
    634747    }); 
    635748    return results; 
    636   }, 
     749  } 
    637750 
    638   detect: function(iterator, context) { 
    639     iterator = iterator.bind(context); 
     751  function detect(iterator, context) { 
    640752    var result; 
    641753    this.each(function(value, index) { 
    642       if (iterator(value, index)) { 
     754      if (iterator.call(context, value, index)) { 
    643755        result = value; 
    644756        throw $break; 
    645757      } 
    646758    }); 
    647759    return result; 
    648   }, 
     760  } 
    649761 
    650   findAll: function(iterator, context) { 
    651     iterator = iterator.bind(context); 
     762  function findAll(iterator, context) { 
    652763    var results = []; 
    653764    this.each(function(value, index) { 
    654       if (iterator(value, index)) 
     765      if (iterator.call(context, value, index)) 
    655766        results.push(value); 
    656767    }); 
    657768    return results; 
    658   }, 
     769  } 
    659770 
    660   grep: function(filter, iterator, context) { 
    661     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     771  function grep(filter, iterator, context) { 
     772    iterator = iterator || Prototype.K; 
    662773    var results = []; 
    663774 
    664775    if (Object.isString(filter)) 
    665       filter = new RegExp(filter); 
     776      filter = new RegExp(RegExp.escape(filter)); 
    666777 
    667778    this.each(function(value, index) { 
    668779      if (filter.match(value)) 
    669         results.push(iterator(value, index)); 
     780        results.push(iterator.call(context, value, index)); 
    670781    }); 
    671782    return results; 
    672   }, 
     783  } 
    673784 
    674   include: function(object) { 
     785  function include(object) { 
    675786    if (Object.isFunction(this.indexOf)) 
    676787      if (this.indexOf(object) != -1) return true; 
    677788 
     
    683794      } 
    684795    }); 
    685796    return found; 
    686   }, 
     797  } 
    687798 
    688   inGroupsOf: function(number, fillWith) { 
    689     fillWith = fillWith === undefined ? null : fillWith; 
     799  function inGroupsOf(number, fillWith) { 
     800    fillWith = Object.isUndefined(fillWith) ? null : fillWith; 
    690801    return this.eachSlice(number, function(slice) { 
    691802      while(slice.length < number) slice.push(fillWith); 
    692803      return slice; 
    693804    }); 
    694   }, 
     805  } 
    695806 
    696   inject: function(memo, iterator, context) { 
    697     iterator = iterator.bind(context); 
     807  function inject(memo, iterator, context) { 
    698808    this.each(function(value, index) { 
    699       memo = iterator(memo, value, index); 
     809      memo = iterator.call(context, memo, value, index); 
    700810    }); 
    701811    return memo; 
    702   }, 
     812  } 
    703813 
    704   invoke: function(method) { 
     814  function invoke(method) { 
    705815    var args = $A(arguments).slice(1); 
    706816    return this.map(function(value) { 
    707817      return value[method].apply(value, args); 
    708818    }); 
    709   }, 
     819  } 
    710820 
    711   max: function(iterator, context) { 
    712     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     821  function max(iterator, context) { 
     822    iterator = iterator || Prototype.K; 
    713823    var result; 
    714824    this.each(function(value, index) { 
    715       value = iterator(value, index); 
    716       if (result == undefined || value >= result) 
     825      value = iterator.call(context, value, index); 
     826      if (result == null || value >= result) 
    717827        result = value; 
    718828    }); 
    719829    return result; 
    720   }, 
     830  } 
    721831 
    722   min: function(iterator, context) { 
    723     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     832  function min(iterator, context) { 
     833    iterator = iterator || Prototype.K; 
    724834    var result; 
    725835    this.each(function(value, index) { 
    726       value = iterator(value, index); 
    727       if (result == undefined || value < result) 
     836      value = iterator.call(context, value, index); 
     837      if (result == null || value < result) 
    728838        result = value; 
    729839    }); 
    730840    return result; 
    731   }, 
     841  } 
    732842 
    733   partition: function(iterator, context) { 
    734     iterator = iterator ? iterator.bind(context) : Prototype.K; 
     843  function partition(iterator, context) { 
     844    iterator = iterator || Prototype.K; 
    735845    var trues = [], falses = []; 
    736846    this.each(function(value, index) { 
    737       (iterator(value, index) ? 
     847      (iterator.call(context, value, index) ? 
    738848        trues : falses).push(value); 
    739849    }); 
    740850    return [trues, falses]; 
    741   }, 
     851  } 
    742852 
    743   pluck: function(property) { 
     853  function pluck(property) { 
    744854    var results = []; 
    745855    this.each(function(value) { 
    746856      results.push(value[property]); 
    747857    }); 
    748858    return results; 
    749   }, 
     859  } 
    750860 
    751   reject: function(iterator, context) { 
    752     iterator = iterator.bind(context); 
     861  function reject(iterator, context) { 
    753862    var results = []; 
    754863    this.each(function(value, index) { 
    755       if (!iterator(value, index)) 
     864      if (!iterator.call(context, value, index)) 
    756865        results.push(value); 
    757866    }); 
    758867    return results; 
    759   }, 
     868  } 
    760869 
    761   sortBy: function(iterator, context) { 
    762     iterator = iterator.bind(context); 
     870  function sortBy(iterator, context) { 
    763871    return this.map(function(value, index) { 
    764       return {value: value, criteria: iterator(value, index)}; 
     872      return { 
     873        value: value, 
     874        criteria: iterator.call(context, value, index) 
     875      }; 
    765876    }).sort(function(left, right) { 
    766877      var a = left.criteria, b = right.criteria; 
    767878      return a < b ? -1 : a > b ? 1 : 0; 
    768879    }).pluck('value'); 
    769   }, 
     880  } 
    770881 
    771   toArray: function() { 
     882  function toArray() { 
    772883    return this.map(); 
    773   }, 
     884  } 
    774885 
    775   zip: function() { 
     886  function zip() { 
    776887    var iterator = Prototype.K, args = $A(arguments); 
    777888    if (Object.isFunction(args.last())) 
    778889      iterator = args.pop(); 
     
    781892    return this.map(function(value, index) { 
    782893      return iterator(collections.pluck(index)); 
    783894    }); 
    784   }, 
     895  } 
    785896 
    786   size: function() { 
     897  function size() { 
    787898    return this.toArray().length; 
    788   }, 
     899  } 
    789900 
    790   inspect: function() { 
     901  function inspect() { 
    791902    return '#<Enumerable:' + this.toArray().inspect() + '>'; 
    792903  } 
    793 }; 
    794904 
    795 Object.extend(Enumerable, { 
    796   map:     Enumerable.collect, 
    797   find:    Enumerable.detect, 
    798   select:  Enumerable.findAll, 
    799   filter:  Enumerable.findAll, 
    800   member:  Enumerable.include, 
    801   entries: Enumerable.toArray, 
    802   every:   Enumerable.all, 
    803   some:    Enumerable.any 
    804 }); 
     905 
     906 
     907 
     908 
     909 
     910 
     911 
     912 
     913  return { 
     914    each:       each, 
     915    eachSlice:  eachSlice, 
     916    all:        all, 
     917    every:      all, 
     918    any:        any, 
     919    some:       any, 
     920    collect:    collect, 
     921    map:        collect, 
     922    detect:     detect, 
     923    findAll:    findAll, 
     924    select:     findAll, 
     925    filter:     findAll, 
     926    grep:       grep, 
     927    include:    include, 
     928    member:     include, 
     929    inGroupsOf: inGroupsOf, 
     930    inject:     inject, 
     931    invoke:     invoke, 
     932    max:        max, 
     933    min:        min, 
     934    partition:  partition, 
     935    pluck:      pluck, 
     936    reject:     reject, 
     937    sortBy:     sortBy, 
     938    toArray:    toArray, 
     939    entries:    toArray, 
     940    zip:        zip, 
     941    size:       size, 
     942    inspect:    inspect, 
     943    find:       detect 
     944  }; 
     945})(); 
    805946function $A(iterable) { 
    806947  if (!iterable) return []; 
    807   if (iterable.toArray) return iterable.toArray(); 
    808   var length = iterable.length, results = new Array(length); 
     948  if ('toArray' in Object(iterable)) return iterable.toArray(); 
     949  var length = iterable.length || 0, results = new Array(length); 
    809950  while (length--) results[length] = iterable[length]; 
    810951  return results; 
    811952} 
    812953 
    813 if (Prototype.Browser.WebKit) { 
    814   function $A(iterable) { 
    815     if (!iterable) return []; 
    816     if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && 
    817         iterable.toArray) return iterable.toArray(); 
    818     var length = iterable.length, results = new Array(length); 
    819     while (length--) results[length] = iterable[length]; 
    820     return results; 
    821   } 
     954function $w(string) { 
     955  if (!Object.isString(string)) return []; 
     956  string = string.strip(); 
     957  return string ? string.split(/\s+/) : []; 
    822958} 
    823959 
    824960Array.from = $A; 
    825961 
    826 Object.extend(Array.prototype, Enumerable); 
    827962 
    828 if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; 
     963(function() { 
     964  var arrayProto = Array.prototype, 
     965      slice = arrayProto.slice, 
     966      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available 
    829967 
    830 Object.extend(Array.prototype, { 
    831   _each: function(iterator) { 
     968  function each(iterator) { 
    832969    for (var i = 0, length = this.length; i < length; i++) 
    833970      iterator(this[i]); 
    834   }, 
     971  } 
     972  if (!_each) _each = each; 
    835973 
    836   clear: function() { 
     974  function clear() { 
    837975    this.length = 0; 
    838976    return this; 
    839   }, 
     977  } 
    840978 
    841   first: function() { 
     979  function first() { 
    842980    return this[0]; 
    843   }, 
     981  } 
    844982 
    845   last: function() { 
     983  function last() { 
    846984    return this[this.length - 1]; 
    847   }, 
     985  } 
    848986 
    849   compact: function() { 
     987  function compact() { 
    850988    return this.select(function(value) { 
    851989      return value != null; 
    852990    }); 
    853   }, 
     991  } 
    854992 
    855   flatten: function() { 
     993  function flatten() { 
    856994    return this.inject([], function(array, value) { 
    857       return array.concat(Object.isArray(value) ? 
    858         value.flatten() : [value]); 
     995      if (Object.isArray(value)) 
     996        return array.concat(value.flatten()); 
     997      array.push(value); 
     998      return array; 
    859999    }); 
    860   }, 
     1000  } 
    8611001 
    862   without: function() { 
    863     var values = $A(arguments); 
     1002  function without() { 
     1003    var values = slice.call(arguments, 0); 
    8641004    return this.select(function(value) { 
    8651005      return !values.include(value); 
    8661006    }); 
    867   }, 
     1007  } 
    8681008 
    869   reverse: function(inline) { 
     1009  function reverse(inline) { 
    8701010    return (inline !== false ? this : this.toArray())._reverse(); 
    871   }, 
     1011  } 
    8721012 
    873   reduce: function() { 
    874     return this.length > 1 ? this : this[0]; 
    875   }, 
    876  
    877   uniq: function(sorted) { 
     1013  function uniq(sorted) { 
    8781014    return this.inject([], function(array, value, index) { 
    8791015      if (0 == index || (sorted ? array.last() != value : !array.include(value))) 
    8801016        array.push(value); 
    8811017      return array; 
    8821018    }); 
    883   }, 
     1019  } 
    8841020 
    885   intersect: function(array) { 
     1021  function intersect(array) { 
    8861022    return this.uniq().findAll(function(item) { 
    8871023      return array.detect(function(value) { return item === value }); 
    8881024    }); 
    889   }, 
     1025  } 
    8901026 
    891   clone: function() { 
    892     return [].concat(this); 
    893   }, 
    8941027 
    895   size: function() { 
     1028  function clone() { 
     1029    return slice.call(this, 0); 
     1030  } 
     1031 
     1032  function size() { 
    8961033    return this.length; 
    897   }, 
     1034  } 
    8981035 
    899   inspect: function() { 
     1036  function inspect() { 
    9001037    return '[' + this.map(Object.inspect).join(', ') + ']'; 
    901   }, 
     1038  } 
    9021039 
    903   toJSON: function() { 
     1040  function toJSON() { 
    9041041    var results = []; 
    9051042    this.each(function(object) { 
    9061043      var value = Object.toJSON(object); 
    907       if (value !== undefined) results.push(value); 
     1044      if (!Object.isUndefined(value)) results.push(value); 
    9081045    }); 
    9091046    return '[' + results.join(', ') + ']'; 
    9101047  } 
    911 }); 
    9121048 
    913 // use native browser JS 1.6 implementation if available 
    914 if (Object.isFunction(Array.prototype.forEach)) 
    915   Array.prototype._each = Array.prototype.forEach; 
     1049  function indexOf(item, i) { 
     1050    i || (i = 0); 
     1051    var length = this.length; 
     1052    if (i < 0) i = length + i; 
     1053    for (; i < length; i++) 
     1054      if (this[i] === item) return i; 
     1055    return -1; 
     1056  } 
    9161057 
    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 }; 
     1058  function lastIndexOf(item, i) { 
     1059    i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 
     1060    var n = this.slice(0, i).reverse().indexOf(item); 
     1061    return (n < 0) ? n : i - n - 1; 
     1062  } 
    9251063 
    926 if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { 
    927   i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; 
    928   var n = this.slice(0, i).reverse().indexOf(item); 
    929   return (n < 0) ? n : i - n - 1; 
    930 }; 
    931  
    932 Array.prototype.toArray = Array.prototype.clone; 
    933  
    934 function $w(string) { 
    935   if (!Object.isString(string)) return []; 
    936   string = string.strip(); 
    937   return string ? string.split(/\s+/) : []; 
    938 } 
    939  
    940 if (Prototype.Browser.Opera){ 
    941   Array.prototype.concat = function() { 
    942     var array = []; 
    943     for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); 
     1064  function concat() { 
     1065    var array = slice.call(this, 0), item; 
    9441066    for (var i = 0, length = arguments.length; i < length; i++) { 
    945       if (Object.isArray(arguments[i])) { 
    946         for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 
    947           array.push(arguments[i][j]); 
     1067      item = arguments[i]; 
     1068      if (Object.isArray(item) && !('callee' in item)) { 
     1069        for (var j = 0, arrayLength = item.length; j < arrayLength; j++) 
     1070          array.push(item[j]); 
    9481071      } else { 
    949         array.push(arguments[i]); 
     1072        array.push(item); 
    9501073      } 
    9511074    } 
    9521075    return array; 
    953   }; 
    954 } 
    955 Object.extend(Number.prototype, { 
    956   toColorPart: function() { 
    957     return this.toPaddedString(2, 16); 
    958   }, 
     1076  } 
    9591077 
    960   succ: function() { 
    961     return this + 1; 
    962   }, 
     1078  Object.extend(arrayProto, Enumerable); 
    9631079 
    964   times: function(iterator) { 
    965     $R(0, this, true).each(iterator); 
    966     return this; 
    967   }, 
     1080  if (!arrayProto._reverse) 
     1081    arrayProto._reverse = arrayProto.reverse; 
    9681082 
    969   toPaddedString: function(length, radix) { 
    970     var string = this.toString(radix || 10); 
    971     return '0'.times(length - string.length) + string; 
    972   }, 
     1083  Object.extend(arrayProto, { 
     1084    _each:     _each, 
     1085    clear:     clear, 
     1086    first:     first, 
     1087    last:      last, 
     1088    compact:   compact, 
     1089    flatten:   flatten, 
     1090    without:   without, 
     1091    reverse:   reverse, 
     1092    uniq:      uniq, 
     1093    intersect: intersect, 
     1094    clone:     clone, 
     1095    toArray:   clone, 
     1096    size:      size, 
     1097    inspect:   inspect, 
     1098    toJSON:    toJSON 
     1099  }); 
    9731100 
    974   toJSON: function() { 
    975     return isFinite(this) ? this.toString() : 'null'; 
    976   } 
    977 }); 
     1101  var CONCAT_ARGUMENTS_BUGGY = (function() { 
     1102    return [].concat(arguments)[0][0] !== 1; 
     1103  })(1,2) 
    9781104 
    979 $w('abs round ceil floor').each(function(method){ 
    980   Number.prototype[method] = Math[method].methodize(); 
    981 }); 
     1105  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; 
     1106 
     1107  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; 
     1108  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; 
     1109})(); 
    9821110function $H(object) { 
    9831111  return new Hash(object); 
    9841112}; 
    9851113 
    9861114var 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       } 
     1115  function initialize(object) { 
     1116    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 
     1117  } 
     1118 
     1119  function _each(iterator) { 
     1120    for (var key in this._object) { 
     1121      var value = this._object[key], pair = [key, value]; 
     1122      pair.key = key; 
     1123      pair.value = value; 
     1124      iterator(pair); 
    10041125    } 
    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     } 
    10141126  } 
    10151127 
     1128  function set(key, value) { 
     1129    return this._object[key] = value; 
     1130  } 
     1131 
     1132  function get(key) { 
     1133    if (this._object[key] !== Object.prototype[key]) 
     1134      return this._object[key]; 
     1135  } 
     1136 
     1137  function unset(key) { 
     1138    var value = this._object[key]; 
     1139    delete this._object[key]; 
     1140    return value; 
     1141  } 
     1142 
     1143  function toObject() { 
     1144    return Object.clone(this._object); 
     1145  } 
     1146 
     1147  function keys() { 
     1148    return this.pluck('key'); 
     1149  } 
     1150 
     1151  function values() { 
     1152    return this.pluck('value'); 
     1153  } 
     1154 
     1155  function index(value) { 
     1156    var match = this.detect(function(pair) { 
     1157      return pair.value === value; 
     1158    }); 
     1159    return match && match.key; 
     1160  } 
     1161 
     1162  function merge(object) { 
     1163    return this.clone().update(object); 
     1164  } 
     1165 
     1166  function update(object) { 
     1167    return new Hash(object).inject(this, function(result, pair) { 
     1168      result.set(pair.key, pair.value); 
     1169      return result; 
     1170    }); 
     1171  } 
     1172 
    10161173  function toQueryPair(key, value) { 
    10171174    if (Object.isUndefined(value)) return key; 
    10181175    return key + '=' + encodeURIComponent(String.interpret(value)); 
    10191176  } 
    10201177 
    1021   return { 
    1022     initialize: function(object) { 
    1023       this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); 
    1024     }, 
     1178  function toQueryString() { 
     1179    return this.inject([], function(results, pair) { 
     1180      var key = encodeURIComponent(pair.key), values = pair.value; 
    10251181 
    1026     _each: each, 
     1182      if (values && typeof values == 'object') { 
     1183        if (Object.isArray(values)) 
     1184          return results.concat(values.map(toQueryPair.curry(key))); 
     1185      } else results.push(toQueryPair(key, values)); 
     1186      return results; 
     1187    }).join('&'); 
     1188  } 
    10271189 
    1028     set: function(key, value) { 
    1029       return this._object[key] = value; 
    1030     }, 
     1190  function inspect() { 
     1191    return '#<Hash:{' + this.map(function(pair) { 
     1192      return pair.map(Object.inspect).join(': '); 
     1193    }).join(', ') + '}>'; 
     1194  } 
    10311195 
    1032     get: function(key) { 
    1033       return this._object[key]; 
    1034     }, 
     1196  function toJSON() { 
     1197    return Object.toJSON(this.toObject()); 
     1198  } 
    10351199 
    1036     unset: function(key) { 
    1037       var value = this._object[key]; 
    1038       delete this._object[key]; 
    1039       return value; 
    1040     }, 
     1200  function clone() { 
     1201    return new Hash(this); 
     1202  } 
    10411203 
    1042     toObject: function() { 
    1043       return Object.clone(this._object); 
    1044     }, 
     1204  return { 
     1205    initialize:             initialize, 
     1206    _each:                  _each, 
     1207    set:                    set, 
     1208    get:                    get, 
     1209    unset:                  unset, 
     1210    toObject:               toObject, 
     1211    toTemplateReplacements: toObject, 
     1212    keys:                   keys, 
     1213    values:                 values, 
     1214    index:                  index, 
     1215    merge:                  merge, 
     1216    update:                 update, 
     1217    toQueryString:          toQueryString, 
     1218    inspect:                inspect, 
     1219    toJSON:                 toJSON, 
     1220    clone:                  clone 
     1221  }; 
     1222})()); 
    10451223 
    1046     keys: function() { 
    1047       return this.pluck('key'); 
    1048     }, 
     1224Hash.from = $H; 
     1225Object.extend(Number.prototype, (function() { 
     1226  function toColorPart() { 
     1227    return this.toPaddedString(2, 16); 
     1228  } 
    10491229 
    1050     values: function() { 
    1051       return this.pluck('value'); 
    1052     }, 
     1230  function succ() { 
     1231    return this + 1; 
     1232  } 
    10531233 
    1054     index: function(value) { 
    1055       var match = this.detect(function(pair) { 
    1056         return pair.value === value; 
    1057       }); 
    1058       return match && match.key; 
    1059     }, 
     1234  function times(iterator, context) { 
     1235    $R(0, this, true).each(iterator, context); 
     1236    return this; 
     1237  } 
    10601238 
    1061     merge: function(object) { 
    1062       return this.clone().update(object); 
    1063     }, 
     1239  function toPaddedString(length, radix) { 
     1240    var string = this.toString(radix || 10); 
     1241    return '0'.times(length - string.length) + string; 
     1242  } 
    10641243 
    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     }, 
     1244  function toJSON() { 
     1245    return isFinite(this) ? this.toString() : 'null'; 
     1246  } 
    10711247 
    1072     toQueryString: function() { 
    1073       return this.map(function(pair) { 
    1074         var key = encodeURIComponent(pair.key), values = pair.value; 
     1248  function abs() { 
     1249    return Math.abs(this); 
     1250  } 
    10751251 
    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     }, 
     1252  function round() { 
     1253    return Math.round(this); 
     1254  } 
    10831255 
    1084     inspect: function() { 
    1085       return '#<Hash:{' + this.map(function(pair) { 
    1086         return pair.map(Object.inspect).join(': '); 
    1087       }).join(', ') + '}>'; 
    1088     }, 
     1256  function ceil() { 
     1257    return Math.ceil(this); 
     1258  } 
    10891259 
    1090     toJSON: function() { 
    1091       return Object.toJSON(this.toObject()); 
    1092     }, 
     1260  function floor() { 
     1261    return Math.floor(this); 
     1262  } 
    10931263 
    1094     clone: function() { 
    1095       return new Hash(this); 
    1096     } 
    1097   } 
     1264  return { 
     1265    toColorPart:    toColorPart, 
     1266    succ:           succ, 
     1267    times:          times, 
     1268    toPaddedString: toPaddedString, 
     1269    toJSON:         toJSON, 
     1270    abs:            abs, 
     1271    round:          round, 
     1272    ceil:           ceil, 
     1273    floor:          floor 
     1274  }; 
    10981275})()); 
    10991276 
    1100 Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; 
    1101 Hash.from = $H; 
    1102 var ObjectRange = Class.create(Enumerable, { 
    1103   initialize: function(start, end, exclusive) { 
     1277function $R(start, end, exclusive) { 
     1278  return new ObjectRange(start, end, exclusive); 
     1279} 
     1280 
     1281var ObjectRange = Class.create(Enumerable, (function() { 
     1282  function initialize(start, end, exclusive) { 
    11041283    this.start = start; 
    11051284    this.end = end; 
    11061285    this.exclusive = exclusive; 
    1107   }, 
     1286  } 
    11081287 
    1109   _each: function(iterator) { 
     1288  function _each(iterator) { 
    11101289    var value = this.start; 
    11111290    while (this.include(value)) { 
    11121291      iterator(value); 
    11131292      value = value.succ(); 
    11141293    } 
    1115   }, 
     1294  } 
    11161295 
    1117   include: function(value) { 
     1296  function include(value) { 
    11181297    if (value < this.start) 
    11191298      return false; 
    11201299    if (this.exclusive) 
    11211300      return value < this.end; 
    11221301    return value <= this.end; 
    11231302  } 
    1124 }); 
    11251303 
    1126 var $R = function(start, end, exclusive) { 
    1127   return new ObjectRange(start, end, exclusive); 
    1128 }; 
     1304  return { 
     1305    initialize: initialize, 
     1306    _each:      _each, 
     1307    include:    include 
     1308  }; 
     1309})()); 
    11291310 
     1311 
     1312 
    11301313var Ajax = { 
    11311314  getTransport: function() { 
    11321315    return Try.these( 
     
    11721355  onCreate:   function() { Ajax.activeRequestCount++ }, 
    11731356  onComplete: function() { Ajax.activeRequestCount-- } 
    11741357}); 
    1175  
    11761358Ajax.Base = Class.create({ 
    11771359  initialize: function(options) { 
    11781360    this.options = { 
     
    11871369    Object.extend(this.options, options || { }); 
    11881370 
    11891371    this.options.method = this.options.method.toLowerCase(); 
     1372 
    11901373    if (Object.isString(this.options.parameters)) 
    11911374      this.options.parameters = this.options.parameters.toQueryParams(); 
     1375    else if (Object.isHash(this.options.parameters)) 
     1376      this.options.parameters = this.options.parameters.toObject(); 
    11921377  } 
    11931378}); 
    1194  
    11951379Ajax.Request = Class.create(Ajax.Base, { 
    11961380  _complete: false, 
    11971381 
     
    12071391    var params = Object.clone(this.options.parameters); 
    12081392 
    12091393    if (!['get', 'post'].include(this.method)) { 
    1210       // simulate other verbs over post 
    12111394      params['_method'] = this.method; 
    12121395      this.method = 'post'; 
    12131396    } 
     
    12151398    this.parameters = params; 
    12161399 
    12171400    if (params = Object.toQueryString(params)) { 
    1218       // when GET, append parameters to URL 
    12191401      if (this.method == 'get') 
    12201402        this.url += (this.url.include('?') ? '&' : '?') + params; 
    12211403      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 
     
    12741456            headers['Connection'] = 'close'; 
    12751457    } 
    12761458 
    1277     // user-defined headers 
    12781459    if (typeof this.options.requestHeaders == 'object') { 
    12791460      var extras = this.options.requestHeaders; 
    12801461 
     
    13151496 
    13161497      var contentType = response.getHeader('Content-type'); 
    13171498      if (this.options.evalJS == 'force' 
    1318           || (this.options.evalJS && contentType 
     1499          || (this.options.evalJS && this.isSameOrigin() && contentType 
    13191500          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) 
    13201501        this.evalResponse(); 
    13211502    } 
     
    13281509    } 
    13291510 
    13301511    if (state == 'Complete') { 
    1331       // avoid memory leak in MSIE: clean up 
    13321512      this.transport.onreadystatechange = Prototype.emptyFunction; 
    13331513    } 
    13341514  }, 
    13351515 
     1516  isSameOrigin: function() { 
     1517    var m = this.url.match(/^\s*https?:\/\/[^\/]*/); 
     1518    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ 
     1519      protocol: location.protocol, 
     1520      domain: document.domain, 
     1521      port: location.port ? ':' + location.port : '' 
     1522    })); 
     1523  }, 
     1524 
    13361525  getHeader: function(name) { 
    13371526    try { 
    1338       return this.transport.getResponseHeader(name); 
    1339     } catch (e) { return null } 
     1527      return this.transport.getResponseHeader(name) || null; 
     1528    } catch (e) { return null; } 
    13401529  }, 
    13411530 
    13421531  evalResponse: function() { 
     
    13561545Ajax.Request.Events = 
    13571546  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; 
    13581547 
     1548 
     1549 
     1550 
     1551 
     1552 
     1553 
     1554 
    13591555Ajax.Response = Class.create({ 
    13601556  initialize: function(request){ 
    13611557    this.request = request; 
     
    13711567 
    13721568    if(readyState == 4) { 
    13731569      var xml = transport.responseXML; 
    1374       this.responseXML  = xml === undefined ? null : xml; 
     1570      this.responseXML  = Object.isUndefined(xml) ? null : xml; 
    13751571      this.responseJSON = this._getResponseJSON(); 
    13761572    } 
    13771573  }, 
    13781574 
    13791575  status:      0, 
     1576 
    13801577  statusText: '', 
    13811578 
    13821579  getStatus: Ajax.Request.prototype.getStatus, 
     
    14081605    if (!json) return null; 
    14091606    json = decodeURIComponent(escape(json)); 
    14101607    try { 
    1411       return json.evalJSON(this.request.options.sanitizeJSON); 
     1608      return json.evalJSON(this.request.options.sanitizeJSON || 
     1609        !this.request.isSameOrigin()); 
    14121610    } catch (e) { 
    14131611      this.request.dispatchException(e); 
    14141612    } 
     
    14171615  _getResponseJSON: function() { 
    14181616    var options = this.request.options; 
    14191617    if (!options.evalJSON || (options.evalJSON != 'force' && 
    1420       !(this.getHeader('Content-type') || '').include('application/json'))) 
    1421         return null; 
     1618      !(this.getHeader('Content-type') || '').include('application/json')) || 
     1619        this.responseText.blank()) 
     1620          return null; 
    14221621    try { 
    1423       return this.transport.responseText.evalJSON(options.sanitizeJSON); 
     1622      return this.responseText.evalJSON(options.sanitizeJSON || 
     1623        !this.request.isSameOrigin()); 
    14241624    } catch (e) { 
    14251625      this.request.dispatchException(e); 
    14261626    } 
     
    14341634      failure: (container.failure || (container.success ? null : container)) 
    14351635    }; 
    14361636 
    1437     options = options || { }; 
     1637    options = Object.clone(options); 
    14381638    var onComplete = options.onComplete; 
    1439     options.onComplete = (function(response, param) { 
     1639    options.onComplete = (function(response, json) { 
    14401640      this.updateContent(response.responseText); 
    1441       if (Object.isFunction(onComplete)) onComplete(response, param); 
     1641      if (Object.isFunction(onComplete)) onComplete(response, json); 
    14421642    }).bind(this); 
    14431643 
    14441644    $super(url, options); 
     
    14601660      } 
    14611661      else receiver.update(responseText); 
    14621662    } 
    1463  
    1464     if (this.success()) { 
    1465       if (this.onComplete) this.onComplete.bind(this).defer(); 
    1466     } 
    14671663  } 
    14681664}); 
    14691665 
     
    15071703    this.updater = new Ajax.Updater(this.container, this.url, this.options); 
    15081704  } 
    15091705}); 
     1706 
     1707 
     1708 
    15101709function $(element) { 
    15111710  if (arguments.length > 1) { 
    15121711    for (var i = 0, elements = [], length = arguments.length; i < length; i++) 
     
    15341733if (!window.Node) var Node = { }; 
    15351734 
    15361735if (!Node.ELEMENT_NODE) { 
    1537   // DOM level 2 ECMAScript Language Binding 
    15381736  Object.extend(Node, { 
    15391737    ELEMENT_NODE: 1, 
    15401738    ATTRIBUTE_NODE: 2, 
     
    15511749  }); 
    15521750} 
    15531751 
    1554 (function() { 
    1555   var element = this.Element; 
    1556   this.Element = function(tagName, attributes) { 
     1752 
     1753(function(global) { 
     1754 
     1755  var SETATTRIBUTE_IGNORES_NAME = (function(){ 
     1756    var elForm = document.createElement("form"); 
     1757    var elInput = document.createElement("input"); 
     1758    var root = document.documentElement; 
     1759    elInput.setAttribute("name", "test"); 
     1760    elForm.appendChild(elInput); 
     1761    root.appendChild(elForm); 
     1762    var isBuggy = elForm.elements 
     1763      ? (typeof elForm.elements.test == "undefined") 
     1764      : null; 
     1765    root.removeChild(elForm); 
     1766    elForm = elInput = null; 
     1767    return isBuggy; 
     1768  })(); 
     1769 
     1770  var element = global.Element; 
     1771  global.Element = function(tagName, attributes) { 
    15571772    attributes = attributes || { }; 
    15581773    tagName = tagName.toLowerCase(); 
    15591774    var cache = Element.cache; 
    1560     if (Prototype.Browser.IE && attributes.name) { 
     1775    if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { 
    15611776      tagName = '<' + tagName + ' name="' + attributes.name + '">'; 
    15621777      delete attributes.name; 
    15631778      return Element.writeAttribute(document.createElement(tagName), attributes); 
     
    15651780    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); 
    15661781    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); 
    15671782  }; 
    1568   Object.extend(this.Element, element || { }); 
    1569 }).call(window); 
     1783  Object.extend(global.Element, element || { }); 
     1784  if (element) global.Element.prototype = element.prototype; 
     1785})(this); 
    15701786 
    15711787Element.cache = { }; 
     1788Element.idCounter = 1; 
    15721789 
    15731790Element.Methods = { 
    15741791  visible: function(element) { 
     
    15811798    return element; 
    15821799  }, 
    15831800 
     1801 
    15841802  hide: function(element) { 
    1585     $(element).style.display = 'none'; 
     1803    element = $(element); 
     1804    element.style.display = 'none'; 
    15861805    return element; 
    15871806  }, 
    15881807 
    15891808  show: function(element) { 
    1590     $(element).style.display = ''; 
     1809    element = $(element); 
     1810    element.style.display = ''; 
    15911811    return element; 
    15921812  }, 
    15931813 
     
    15971817    return element; 
    15981818  }, 
    15991819 
    1600   update: function(element, content) { 
    1601     element = $(element); 
    1602     if (content && content.toElement) content = content.toElement(); 
    1603     if (Object.isElement(content)) return element.update().insert(content); 
    1604     content = Object.toHTML(content); 
    1605     element.innerHTML = content.stripScripts(); 
    1606     content.evalScripts.bind(content).defer(); 
    1607     return element; 
    1608   }, 
     1820  update: (function(){ 
    16091821 
     1822    var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ 
     1823      var el = document.createElement("select"), 
     1824          isBuggy = true; 
     1825      el.innerHTML = "<option value=\"test\">test</option>"; 
     1826      if (el.options && el.options[0]) { 
     1827        isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; 
     1828      } 
     1829      el = null; 
     1830      return isBuggy; 
     1831    })(); 
     1832 
     1833    var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ 
     1834      try { 
     1835        var el = document.createElement("table"); 
     1836        if (el && el.tBodies) { 
     1837          el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; 
     1838          var isBuggy = typeof el.tBodies[0] == "undefined"; 
     1839          el = null; 
     1840          return isBuggy; 
     1841        } 
     1842      } catch (e) { 
     1843        return true; 
     1844      } 
     1845    })(); 
     1846 
     1847    var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { 
     1848      var s = document.createElement("script"), 
     1849          isBuggy = false; 
     1850      try { 
     1851        s.appendChild(document.createTextNode("")); 
     1852        isBuggy = !s.firstChild || 
     1853          s.firstChild && s.firstChild.nodeType !== 3; 
     1854      } catch (e) { 
     1855        isBuggy = true; 
     1856      } 
     1857      s = null; 
     1858      return isBuggy; 
     1859    })(); 
     1860 
     1861    function update(element, content) { 
     1862      element = $(element); 
     1863 
     1864      if (content && content.toElement) 
     1865        content = content.toElement(); 
     1866 
     1867      if (Object.isElement(content)) 
     1868        return element.update().insert(content); 
     1869 
     1870      content = Object.toHTML(content); 
     1871 
     1872      var tagName = element.tagName.toUpperCase(); 
     1873 
     1874      if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { 
     1875        element.text = content; 
     1876        return element; 
     1877      } 
     1878 
     1879      if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { 
     1880        if (tagName in Element._insertionTranslations.tags) { 
     1881          while (element.firstChild) { 
     1882            element.removeChild(element.firstChild); 
     1883          } 
     1884          Element._getContentFromAnonymousElement(tagName, content.stripScripts()) 
     1885            .each(function(node) { 
     1886              element.appendChild(node) 
     1887            }); 
     1888        } 
     1889        else { 
     1890          element.innerHTML = content.stripScripts(); 
     1891        } 
     1892      } 
     1893      else { 
     1894        element.innerHTML = content.stripScripts(); 
     1895      } 
     1896 
     1897      content.evalScripts.bind(content).defer(); 
     1898      return element; 
     1899    } 
     1900 
     1901    return update; 
     1902  })(), 
     1903 
    16101904  replace: function(element, content) { 
    16111905    element = $(element); 
    16121906    if (content && content.toElement) content = content.toElement(); 
     
    16281922        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 
    16291923          insertions = {bottom:insertions}; 
    16301924 
    1631     var content, t, range; 
     1925    var content, insert, tagName, childNodes; 
    16321926 
    1633     for (position in insertions) { 
     1927    for (var position in insertions) { 
    16341928      content  = insertions[position]; 
    16351929      position = position.toLowerCase(); 
    1636       t = Element._insertionTranslations[position]; 
     1930      insert = Element._insertionTranslations[position]; 
    16371931 
    16381932      if (content && content.toElement) content = content.toElement(); 
    16391933      if (Object.isElement(content)) { 
    1640         t.insert(element, content); 
     1934        insert(element, content); 
    16411935        continue; 
    16421936      } 
    16431937 
    16441938      content = Object.toHTML(content); 
    16451939 
    1646       range = element.ownerDocument.createRange(); 
    1647       t.initializeRange(element, range); 
    1648       t.insert(element, range.createContextualFragment(content.stripScripts())); 
     1940      tagName = ((position == 'before' || position == 'after') 
     1941        ? element.parentNode : element).tagName.toUpperCase(); 
    16491942 
     1943      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); 
     1944 
     1945      if (position == 'top' || position == 'after') childNodes.reverse(); 
     1946      childNodes.each(insert.curry(element)); 
     1947 
    16501948      content.evalScripts.bind(content).defer(); 
    16511949    } 
    16521950 
     
    16861984  }, 
    16871985 
    16881986  ancestors: function(element) { 
    1689     return $(element).recursivelyCollect('parentNode'); 
     1987    return Element.recursivelyCollect(element, 'parentNode'); 
    16901988  }, 
    16911989 
    16921990  descendants: function(element) { 
    1693     return $A($(element).getElementsByTagName('*')).each(Element.extend); 
     1991    return Element.select(element, "*"); 
    16941992  }, 
    16951993 
    16961994  firstDescendant: function(element) { 
     
    17072005  }, 
    17082006 
    17092007  previousSiblings: function(element) { 
    1710     return $(element).recursivelyCollect('previousSibling'); 
     2008    return Element.recursivelyCollect(element, 'previousSibling'); 
    17112009  }, 
    17122010 
    17132011  nextSiblings: function(element) { 
    1714     return $(element).recursivelyCollect('nextSibling'); 
     2012    return Element.recursivelyCollect(element, 'nextSibling'); 
    17152013  }, 
    17162014 
    17172015  siblings: function(element) { 
    17182016    element = $(element); 
    1719     return element.previousSiblings().reverse().concat(element.nextSiblings()); 
     2017    return Element.previousSiblings(element).reverse() 
     2018      .concat(Element.nextSiblings(element)); 
    17202019  }, 
    17212020 
    17222021  match: function(element, selector) { 
     
    17282027  up: function(element, expression, index) { 
    17292028    element = $(element); 
    17302029    if (arguments.length == 1) return $(element.parentNode); 
    1731     var ancestors = element.ancestors(); 
    1732     return expression ? Selector.findElement(ancestors, expression, index) : 
    1733       ancestors[index || 0]; 
     2030    var ancestors = Element.ancestors(element); 
     2031    return Object.isNumber(expression) ? ancestors[expression] : 
     2032      Selector.findElement(ancestors, expression, index); 
    17342033  }, 
    17352034 
    17362035  down: function(element, expression, index) { 
    17372036    element = $(element); 
    1738     if (arguments.length == 1) return element.firstDescendant(); 
    1739     var descendants = element.descendants(); 
    1740     return expression ? Selector.findElement(descendants, expression, index) : 
    1741       descendants[index || 0]; 
     2037    if (arguments.length == 1) return Element.firstDescendant(element); 
     2038    return Object.isNumber(expression) ? Element.descendants(element)[expression] : 
     2039      Element.select(element, expression)[index || 0]; 
    17422040  }, 
    17432041 
    17442042  previous: function(element, expression, index) { 
    17452043    element = $(element); 
    17462044    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); 
    1747     var previousSiblings = element.previousSiblings(); 
    1748     return expression ? Selector.findElement(previousSiblings, expression, index) : 
    1749       previousSiblings[index || 0]; 
     2045    var previousSiblings = Element.previousSiblings(element); 
     2046    return Object.isNumber(expression) ? previousSiblings[expression] : 
     2047      Selector.findElement(previousSiblings, expression, index); 
    17502048  }, 
    17512049 
    17522050  next: function(element, expression, index) { 
    17532051    element = $(element); 
    17542052    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]; 
     2053    var nextSiblings = Element.nextSiblings(element); 
     2054    return Object.isNumber(expression) ? nextSiblings[expression] : 
     2055      Selector.findElement(nextSiblings, expression, index); 
    17582056  }, 
    17592057 
    1760   select: function() { 
    1761     var args = $A(arguments), element = $(args.shift()); 
     2058 
     2059  select: function(element) { 
     2060    var args = Array.prototype.slice.call(arguments, 1); 
    17622061    return Selector.findChildElements(element, args); 
    17632062  }, 
    17642063 
    1765   adjacent: function() { 
    1766     var args = $A(arguments), element = $(args.shift()); 
     2064  adjacent: function(element) { 
     2065    var args = Array.prototype.slice.call(arguments, 1); 
    17672066    return Selector.findChildElements(element.parentNode, args).without(element); 
    17682067  }, 
    17692068 
    17702069  identify: function(element) { 
    17712070    element = $(element); 
    1772     var id = element.readAttribute('id'), self = arguments.callee; 
     2071    var id = Element.readAttribute(element, 'id'); 
    17732072    if (id) return id; 
    1774     do { id = 'anonymous_element_' + self.counter++ } while ($(id)); 
    1775     element.writeAttribute('id', id); 
     2073    do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); 
     2074    Element.writeAttribute(element, 'id', id); 
    17762075    return id; 
    17772076  }, 
    17782077 
     
    17952094    var attributes = { }, t = Element._attributeTranslations.write; 
    17962095 
    17972096    if (typeof name == 'object') attributes = name; 
    1798     else attributes[name] = value === undefined ? true : value; 
     2097    else attributes[name] = Object.isUndefined(value) ? true : value; 
    17992098 
    18002099    for (var attr in attributes) { 
    1801       var name = t.names[attr] || attr, value = attributes[attr]; 
     2100      name = t.names[attr] || attr; 
     2101      value = attributes[attr]; 
    18022102      if (t.values[attr]) name = t.values[attr](element, value); 
    18032103      if (value === false || value === null) 
    18042104        element.removeAttribute(name); 
     
    18102110  }, 
    18112111 
    18122112  getHeight: function(element) { 
    1813     return $(element).getDimensions().height; 
     2113    return Element.getDimensions(element).height; 
    18142114  }, 
    18152115 
    18162116  getWidth: function(element) { 
    1817     return $(element).getDimensions().width; 
     2117    return Element.getDimensions(element).width; 
    18182118  }, 
    18192119 
    18202120  classNames: function(element) { 
     
    18302130 
    18312131  addClassName: function(element, className) { 
    18322132    if (!(element = $(element))) return; 
    1833     if (!element.hasClassName(className)) 
     2133    if (!Element.hasClassName(element, className)) 
    18342134      element.className += (element.className ? ' ' : '') + className; 
    18352135    return element; 
    18362136  }, 
     
    18442144 
    18452145  toggleClassName: function(element, className) { 
    18462146    if (!(element = $(element))) return; 
    1847     return element[element.hasClassName(className) ? 
    1848       'removeClassName' : 'addClassName'](className); 
     2147    return Element[Element.hasClassName(element, className) ? 
     2148      'removeClassName' : 'addClassName'](element, className); 
    18492149  }, 
    18502150 
    1851   // removes whitespace-only text node children 
    18522151  cleanWhitespace: function(element) { 
    18532152    element = $(element); 
    18542153    var node = element.firstChild; 
     
    18712170    if (element.compareDocumentPosition) 
    18722171      return (element.compareDocumentPosition(ancestor) & 8) === 8; 
    18732172 
    1874     if (element.sourceIndex && !Prototype.Browser.Opera) { 
    1875       var e = element.sourceIndex, a = ancestor.sourceIndex, 
    1876        nextAncestor = ancestor.nextSibling; 
    1877       if (!nextAncestor) { 
    1878         do { ancestor = ancestor.parentNode; } 
    1879         while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); 
    1880       } 
    1881       if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex); 
    1882     } 
     2173    if (ancestor.contains) 
     2174      return ancestor.contains(element) && ancestor !== element; 
    18832175 
    18842176    while (element = element.parentNode) 
    18852177      if (element == ancestor) return true; 
     2178 
    18862179    return false; 
    18872180  }, 
    18882181 
    18892182  scrollTo: function(element) { 
    18902183    element = $(element); 
    1891     var pos = element.cumulativeOffset(); 
     2184    var pos = Element.cumulativeOffset(element); 
    18922185    window.scrollTo(pos[0], pos[1]); 
    18932186    return element; 
    18942187  }, 
     
    18972190    element = $(element); 
    18982191    style = style == 'float' ? 'cssFloat' : style.camelize(); 
    18992192    var value = element.style[style]; 
    1900     if (!value) { 
     2193    if (!value || value == 'auto') { 
    19012194      var css = document.defaultView.getComputedStyle(element, null); 
    19022195      value = css ? css[style] : null; 
    19032196    } 
     
    19212214      if (property == 'opacity') element.setOpacity(styles[property]); 
    19222215      else 
    19232216        elementStyle[(property == 'float' || property == 'cssFloat') ? 
    1924           (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : 
     2217          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : 
    19252218            property] = styles[property]; 
    19262219 
    19272220    return element; 
     
    19362229 
    19372230  getDimensions: function(element) { 
    19382231    element = $(element); 
    1939     var display = $(element).getStyle('display'); 
     2232    var display = Element.getStyle(element, 'display'); 
    19402233    if (display != 'none' && display != null) // Safari bug 
    19412234      return {width: element.offsetWidth, height: element.offsetHeight}; 
    19422235 
    1943     // All *Width and *Height properties give 0 on elements with display none, 
    1944     // so enable the element temporarily 
    19452236    var els = element.style; 
    19462237    var originalVisibility = els.visibility; 
    19472238    var originalPosition = els.position; 
    19482239    var originalDisplay = els.display; 
    19492240    els.visibility = 'hidden'; 
    1950     els.position = 'absolute'; 
     2241    if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari 
     2242      els.position = 'absolute'; 
    19512243    els.display = 'block'; 
    19522244    var originalWidth = element.clientWidth; 
    19532245    var originalHeight = element.clientHeight; 
     
    19632255    if (pos == 'static' || !pos) { 
    19642256      element._madePositioned = true; 
    19652257      element.style.position = 'relative'; 
    1966       // Opera returns the offset relative to the positioning context, when an 
    1967       // element is position relative but top and left have not been defined 
    1968       if (window.opera) { 
     2258      if (Prototype.Browser.Opera) { 
    19692259        element.style.top = 0; 
    19702260        element.style.left = 0; 
    19712261      } 
     
    20202310      valueL += element.offsetLeft || 0; 
    20212311      element = element.offsetParent; 
    20222312      if (element) { 
    2023         if (element.tagName == 'BODY') break; 
     2313        if (element.tagName.toUpperCase() == 'BODY') break; 
    20242314        var p = Element.getStyle(element, 'position'); 
    2025         if (p == 'relative' || p == 'absolute') break; 
     2315        if (p !== 'static') break; 
    20262316      } 
    20272317    } while (element); 
    20282318    return Element._returnOffset(valueL, valueT); 
     
    20302320 
    20312321  absolutize: function(element) { 
    20322322    element = $(element); 
    2033     if (element.getStyle('position') == 'absolute') return; 
    2034     // Position.prepare(); // To be done manually by Scripty when it needs it. 
     2323    if (Element.getStyle(element, 'position') == 'absolute') return element; 
    20352324 
    2036     var offsets = element.positionedOffset(); 
     2325    var offsets = Element.positionedOffset(element); 
    20372326    var top     = offsets[1]; 
    20382327    var left    = offsets[0]; 
    20392328    var width   = element.clientWidth; 
     
    20542343 
    20552344  relativize: function(element) { 
    20562345    element = $(element); 
    2057     if (element.getStyle('position') == 'relative') return; 
    2058     // Position.prepare(); // To be done manually by Scripty when it needs it. 
     2346    if (Element.getStyle(element, 'position') == 'relative') return element; 
    20592347 
    20602348    element.style.position = 'relative'; 
    20612349    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0); 
     
    20972385      valueT += element.offsetTop  || 0; 
    20982386      valueL += element.offsetLeft || 0; 
    20992387 
    2100       // Safari fix 
    21012388      if (element.offsetParent == document.body && 
    21022389        Element.getStyle(element, 'position') == 'absolute') break; 
    21032390 
     
    21052392 
    21062393    element = forElement; 
    21072394    do { 
    2108       if (!Prototype.Browser.Opera || element.tagName == 'BODY') { 
     2395      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { 
    21092396        valueT -= element.scrollTop  || 0; 
    21102397        valueL -= element.scrollLeft || 0; 
    21112398      } 
     
    21242411      offsetLeft: 0 
    21252412    }, arguments[2] || { }); 
    21262413 
    2127     // find page position of source 
    21282414    source = $(source); 
    2129     var p = source.viewportOffset(); 
     2415    var p = Element.viewportOffset(source); 
    21302416 
    2131     // find coordinate system to use 
    21322417    element = $(element); 
    21332418    var delta = [0, 0]; 
    21342419    var parent = null; 
    2135     // delta [0,0] will do fine with position: fixed elements, 
    2136     // position:absolute needs offsetParent deltas 
    21372420    if (Element.getStyle(element, 'position') == 'absolute') { 
    2138       parent = element.getOffsetParent(); 
    2139       delta = parent.viewportOffset(); 
     2421      parent = Element.getOffsetParent(element); 
     2422      delta = Element.viewportOffset(parent); 
    21402423    } 
    21412424 
    2142     // correct by body offsets (fixes Safari) 
    21432425    if (parent == document.body) { 
    21442426      delta[0] -= document.body.offsetLeft; 
    21452427      delta[1] -= document.body.offsetTop; 
    21462428    } 
    21472429 
    2148     // set position 
    21492430    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px'; 
    21502431    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px'; 
    21512432    if (options.setWidth)  element.style.width = source.offsetWidth + 'px'; 
     
    21542435  } 
    21552436}; 
    21562437 
    2157 Element.Methods.identify.counter = 1; 
    2158  
    21592438Object.extend(Element.Methods, { 
    21602439  getElementsBySelector: Element.Methods.select, 
     2440 
    21612441  childElements: Element.Methods.immediateDescendants 
    21622442}); 
    21632443 
     
    21712451  } 
    21722452}; 
    21732453 
     2454if (Prototype.Browser.Opera) { 
     2455  Element.Methods.getStyle = Element.Methods.getStyle.wrap( 
     2456    function(proceed, element, style) { 
     2457      switch (style) { 
     2458        case 'left': case 'top': case 'right': case 'bottom': 
     2459          if (proceed(element, 'position') === 'static') return null; 
     2460        case 'height': case 'width': 
     2461          if (!Element.visible(element)) return null; 
    21742462 
    2175 if (!document.createRange || Prototype.Browser.Opera) { 
    2176   Element.Methods.insert = function(element, insertions) { 
    2177     element = $(element); 
     2463          var dim = parseInt(proceed(element, style), 10); 
    21782464 
    2179     if (Object.isString(insertions) || Object.isNumber(insertions) || 
    2180         Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) 
    2181           insertions = { bottom: insertions }; 
     2465          if (dim !== element['offset' + style.capitalize()]) 
     2466            return dim + 'px'; 
    21822467 
    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; 
     2468          var properties; 
     2469          if (style === 'height') { 
     2470            properties = ['border-top-width', 'padding-top', 
     2471             'padding-bottom', 'border-bottom-width']; 
     2472          } 
     2473          else { 
     2474            properties = ['border-left-width', 'padding-left', 
     2475             'padding-right', 'border-right-width']; 
     2476          } 
     2477          return properties.inject(dim, function(memo, property) { 
     2478            var val = proceed(element, property); 
     2479            return val === null ? memo : memo - parseInt(val, 10); 
     2480          }) + 'px'; 
     2481        default: return proceed(element, style); 
    21942482      } 
     2483    } 
     2484  ); 
    21952485 
    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(); 
     2486  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( 
     2487    function(proceed, element, attribute) { 
     2488      if (attribute === 'title') return element.title; 
     2489      return proceed(element, attribute); 
    22082490    } 
    2209  
    2210     return element; 
    2211   }; 
     2491  ); 
    22122492} 
    22132493 
    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); 
     2494else if (Prototype.Browser.IE) { 
     2495  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( 
     2496    function(proceed, element) { 
     2497      element = $(element); 
     2498      try { element.offsetParent } 
     2499      catch(e) { return $(document.body) } 
     2500      var position = element.getStyle('position'); 
     2501      if (position !== 'static') return proceed(element); 
     2502      element.setStyle({ position: 'relative' }); 
     2503      var value = proceed(element); 
     2504      element.setStyle({ position: position }); 
     2505      return value; 
    22242506    } 
    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 } 
     2507  ); 
    22322508 
    2233 else if (Prototype.Browser.IE) { 
    2234   $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { 
     2509  $w('positionedOffset viewportOffset').each(function(method) { 
    22352510    Element.Methods[method] = Element.Methods[method].wrap( 
    22362511      function(proceed, element) { 
    22372512        element = $(element); 
     2513        try { element.offsetParent } 
     2514        catch(e) { return Element._returnOffset(0,0) } 
    22382515        var position = element.getStyle('position'); 
    2239         if (position != 'static') return proceed(element); 
     2516        if (position !== 'static') return proceed(element); 
     2517        var offsetParent = element.getOffsetParent(); 
     2518        if (offsetParent && offsetParent.getStyle('position') === 'fixed') 
     2519          offsetParent.setStyle({ zoom: 1 }); 
    22402520        element.setStyle({ position: 'relative' }); 
    22412521        var value = proceed(element); 
    22422522        element.setStyle({ position: position }); 
     
    22452525    ); 
    22462526  }); 
    22472527 
     2528  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( 
     2529    function(proceed, element) { 
     2530      try { element.offsetParent } 
     2531      catch(e) { return Element._returnOffset(0,0) } 
     2532      return proceed(element); 
     2533    } 
     2534  ); 
     2535 
    22482536  Element.Methods.getStyle = function(element, style) { 
    22492537    element = $(element); 
    22502538    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); 
     
    22862574    return element; 
    22872575  }; 
    22882576 
    2289   Element._attributeTranslations = { 
    2290     read: { 
    2291       names: { 
    2292         'class': 'className', 
    2293         'for':   'htmlFor' 
    2294       }, 
    2295       values: { 
    2296         _getAttr: function(element, attribute) { 
    2297           return element.getAttribute(attribute, 2); 
     2577  Element._attributeTranslations = (function(){ 
     2578 
     2579    var classProp = 'className'; 
     2580    var forProp = 'for'; 
     2581 
     2582    var el = document.createElement('div'); 
     2583 
     2584    el.setAttribute(classProp, 'x'); 
     2585 
     2586    if (el.className !== 'x') { 
     2587      el.setAttribute('class', 'x'); 
     2588      if (el.className === 'x') { 
     2589        classProp = 'class'; 
     2590      } 
     2591    } 
     2592    el = null; 
     2593 
     2594    el = document.createElement('label'); 
     2595    el.setAttribute(forProp, 'x'); 
     2596    if (el.htmlFor !== 'x') { 
     2597      el.setAttribute('htmlFor', 'x'); 
     2598      if (el.htmlFor === 'x') { 
     2599        forProp = 'htmlFor'; 
     2600      } 
     2601    } 
     2602    el = null; 
     2603 
     2604    return { 
     2605      read: { 
     2606        names: { 
     2607          'class':      classProp, 
     2608          'className':  classProp, 
     2609          'for':        forProp, 
     2610          'htmlFor':    forProp 
    22982611        }, 
    2299         _getAttrNode: function(element, attribute) { 
    2300           var node = element.getAttributeNode(attribute); 
    2301           return node ? node.value : ""; 
    2302         }, 
    2303         _getEv: function(element, attribute) { 
    2304           var attribute = element.getAttribute(attribute); 
    2305           return attribute ? attribute.toString().slice(23, -2) : null; 
    2306         }, 
    2307         _flag: function(element, attribute) { 
    2308           return $(element).hasAttribute(attribute) ? attribute : null; 
    2309         }, 
    2310         style: function(element) { 
    2311           return element.style.cssText.toLowerCase(); 
    2312         }, 
    2313         title: function(element) { 
    2314           return element.title; 
     2612        values: { 
     2613          _getAttr: function(element, attribute) { 
     2614            return element.getAttribute(attribute); 
     2615          }, 
     2616          _getAttr2: function(element, attribute) { 
     2617            return element.getAttribute(attribute, 2); 
     2618          }, 
     2619          _getAttrNode: function(element, attribute) { 
     2620            var node = element.getAttributeNode(attribute); 
     2621            return node ? node.value : ""; 
     2622          }, 
     2623          _getEv: (function(){ 
     2624 
     2625            var el = document.createElement('div'); 
     2626            el.onclick = Prototype.emptyFunction; 
     2627            var value = el.getAttribute('onclick'); 
     2628            var f; 
     2629 
     2630            if (String(value).indexOf('{') > -1) { 
     2631              f = function(element, attribute) { 
     2632                attribute = element.getAttribute(attribute); 
     2633                if (!attribute) return null; 
     2634                attribute = attribute.toString(); 
     2635                attribute = attribute.split('{')[1]; 
     2636                attribute = attribute.split('}')[0]; 
     2637                return attribute.strip(); 
     2638              }; 
     2639            } 
     2640            else if (value === '') { 
     2641              f = function(element, attribute) { 
     2642                attribute = element.getAttribute(attribute); 
     2643                if (!attribute) return null; 
     2644                return attribute.strip(); 
     2645              }; 
     2646            } 
     2647            el = null; 
     2648            return f; 
     2649          })(), 
     2650          _flag: function(element, attribute) { 
     2651            return $(element).hasAttribute(attribute) ? attribute : null; 
     2652          }, 
     2653          style: function(element) { 
     2654            return element.style.cssText.toLowerCase(); 
     2655          }, 
     2656          title: function(element) { 
     2657            return element.title; 
     2658          } 
    23152659        } 
    23162660      } 
    23172661    } 
    2318   }; 
     2662  })(); 
    23192663 
    23202664  Element._attributeTranslations.write = { 
    2321     names: Object.clone(Element._attributeTranslations.read.names), 
     2665    names: Object.extend({ 
     2666      cellpadding: 'cellPadding', 
     2667      cellspacing: 'cellSpacing' 
     2668    }, Element._attributeTranslations.read.names), 
    23222669    values: { 
    23232670      checked: function(element, value) { 
    23242671        element.checked = !!value; 
     
    23332680  Element._attributeTranslations.has = {}; 
    23342681 
    23352682  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 
    2336       'encType maxLength readOnly longDesc').each(function(attr) { 
     2683      'encType maxLength readOnly longDesc frameBorder').each(function(attr) { 
    23372684    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; 
    23382685    Element._attributeTranslations.has[attr.toLowerCase()] = attr; 
    23392686  }); 
    23402687 
    23412688  (function(v) { 
    23422689    Object.extend(v, { 
    2343       href:        v._getAttr, 
    2344       src:         v._getAttr, 
     2690      href:        v._getAttr2, 
     2691      src:         v._getAttr2, 
    23452692      type:        v._getAttr, 
    23462693      action:      v._getAttrNode, 
    23472694      disabled:    v._flag, 
     
    23682715      onchange:    v._getEv 
    23692716    }); 
    23702717  })(Element._attributeTranslations.read.values); 
     2718 
     2719  if (Prototype.BrowserFeatures.ElementExtensions) { 
     2720    (function() { 
     2721      function _descendants(element) { 
     2722        var nodes = element.getElementsByTagName('*'), results = []; 
     2723        for (var i = 0, node; node = nodes[i]; i++) 
     2724          if (node.tagName !== "!") // Filter out comment nodes. 
     2725            results.push(node); 
     2726        return results; 
     2727      } 
     2728 
     2729      Element.Methods.down = function(element, expression, index) { 
     2730        element = $(element); 
     2731        if (arguments.length == 1) return element.firstDescendant(); 
     2732        return Object.isNumber(expression) ? _descendants(element)[expression] : 
     2733          Element.select(element, expression)[index || 0]; 
     2734      } 
     2735    })(); 
     2736  } 
     2737 
    23712738} 
    23722739 
    23732740else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { 
     
    23862753      (value < 0.00001) ? 0 : value; 
    23872754 
    23882755    if (value == 1) 
    2389       if(element.tagName == 'IMG' && element.width) { 
     2756      if(element.tagName.toUpperCase() == 'IMG' && element.width) { 
    23902757        element.width++; element.width--; 
    23912758      } else try { 
    23922759        var n = document.createTextNode(' '); 
     
    23972764    return element; 
    23982765  }; 
    23992766 
    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. 
    24032767  Element.Methods.cumulativeOffset = function(element) { 
    24042768    var valueT = 0, valueL = 0; 
    24052769    do { 
     
    24152779  }; 
    24162780} 
    24172781 
    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) { 
     2782if ('outerHTML' in document.documentElement) { 
    24422783  Element.Methods.replace = function(element, content) { 
    24432784    element = $(element); 
    24442785 
     
    24762817 
    24772818Element._getContentFromAnonymousElement = function(tagName, html) { 
    24782819  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; 
    2479   div.innerHTML = t[0] + html + t[1]; 
    2480   t[2].times(function() { div = div.firstChild }); 
     2820  if (t) { 
     2821    div.innerHTML = t[0] + html + t[1]; 
     2822    t[2].times(function() { div = div.firstChild }); 
     2823  } else div.innerHTML = html; 
    24812824  return $A(div.childNodes); 
    24822825}; 
    24832826 
    24842827Element._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     } 
     2828  before: function(element, node) { 
     2829    element.parentNode.insertBefore(node, element); 
    24932830  }, 
    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     } 
     2831  top: function(element, node) { 
     2832    element.insertBefore(node, element.firstChild); 
    25032833  }, 
    2504   bottom: { 
    2505     adjacency: 'beforeEnd', 
    2506     insert: function(element, node) { 
    2507       element.appendChild(node); 
    2508     } 
     2834  bottom: function(element, node) { 
     2835    element.appendChild(node); 
    25092836  }, 
    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     } 
     2837  after: function(element, node) { 
     2838    element.parentNode.insertBefore(node, element.nextSibling); 
    25182839  }, 
    25192840  tags: { 
    25202841    TABLE:  ['<table>',                '</table>',                   1], 
     
    25262847}; 
    25272848 
    25282849(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 
     2850  var tags = Element._insertionTranslations.tags; 
     2851  Object.extend(tags, { 
     2852    THEAD: tags.TBODY, 
     2853    TFOOT: tags.TBODY, 
     2854    TH:    tags.TD 
    25342855  }); 
    2535 }).call(Element._insertionTranslations); 
     2856})(); 
    25362857 
    25372858Element.Methods.Simulated = { 
    25382859  hasAttribute: function(element, attribute) { 
    25392860    attribute = Element._attributeTranslations.has[attribute] || attribute; 
    25402861    var node = $(element).getAttributeNode(attribute); 
    2541     return node && node.specified; 
     2862    return !!(node && node.specified); 
    25422863  } 
    25432864}; 
    25442865 
     
    25462867 
    25472868Object.extend(Element, Element.Methods); 
    25482869 
    2549 if (!Prototype.BrowserFeatures.ElementExtensions && 
    2550     document.createElement('div').__proto__) { 
    2551   window.HTMLElement = { }; 
    2552   window.HTMLElement.prototype = document.createElement('div').__proto__; 
    2553   Prototype.BrowserFeatures.ElementExtensions = true; 
    2554 } 
     2870(function(div) { 
    25552871 
     2872  if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { 
     2873    window.HTMLElement = { }; 
     2874    window.HTMLElement.prototype = div['__proto__']; 
     2875    Prototype.BrowserFeatures.ElementExtensions = true; 
     2876  } 
     2877 
     2878  div = null; 
     2879 
     2880})(document.createElement('div')) 
     2881 
    25562882Element.extend = (function() { 
    2557   if (Prototype.BrowserFeatures.SpecificElementExtensions) 
     2883 
     2884  function checkDeficiency(tagName) { 
     2885    if (typeof window.Element != 'undefined') { 
     2886      var proto = window.Element.prototype; 
     2887      if (proto) { 
     2888        var id = '_' + (Math.random()+'').slice(2); 
     2889        var el = document.createElement(tagName); 
     2890        proto[id] = 'x'; 
     2891        var isBuggy = (el[id] !== 'x'); 
     2892        delete proto[id]; 
     2893        el = null; 
     2894        return isBuggy; 
     2895      } 
     2896    } 
     2897    return false; 
     2898  } 
     2899 
     2900  function extendElementWith(element, methods) { 
     2901    for (var property in methods) { 
     2902      var value = methods[property]; 
     2903      if (Object.isFunction(value) && !(property in element)) 
     2904        element[property] = value.methodize(); 
     2905    } 
     2906  } 
     2907 
     2908  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); 
     2909 
     2910  if (Prototype.BrowserFeatures.SpecificElementExtensions) { 
     2911    if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { 
     2912      return function(element) { 
     2913        if (element && typeof element._extendedByPrototype == 'undefined') { 
     2914          var t = element.tagName; 
     2915          if (t && (/^(?:object|applet|embed)$/i.test(t))) { 
     2916            extendElementWith(element, Element.Methods); 
     2917            extendElementWith(element, Element.Methods.Simulated); 
     2918            extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); 
     2919          } 
     2920        } 
     2921        return element; 
     2922      } 
     2923    } 
    25582924    return Prototype.K; 
     2925  } 
    25592926 
    25602927  var Methods = { }, ByTag = Element.Methods.ByTag; 
    25612928 
    25622929  var extend = Object.extend(function(element) { 
    2563     if (!element || element._extendedByPrototype || 
     2930    if (!element || typeof element._extendedByPrototype != 'undefined' || 
    25642931        element.nodeType != 1 || element == window) return element; 
    25652932 
    25662933    var methods = Object.clone(Methods), 
    2567       tagName = element.tagName, property, value; 
     2934        tagName = element.tagName.toUpperCase(); 
    25682935 
    2569     // extend methods for specific tags 
    25702936    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); 
    25712937 
    2572     for (property in methods) { 
    2573       value = methods[property]; 
    2574       if (Object.isFunction(value) && !(property in element)) 
    2575         element[property] = value.methodize(); 
    2576     } 
     2938    extendElementWith(element, methods); 
    25772939 
    25782940    element._extendedByPrototype = Prototype.emptyFunction; 
    25792941    return element; 
    25802942 
    25812943  }, { 
    25822944    refresh: function() { 
    2583       // extend methods for all tags (Safari doesn't need this) 
    25842945      if (!Prototype.BrowserFeatures.ElementExtensions) { 
    25852946        Object.extend(Methods, Element.Methods); 
    25862947        Object.extend(Methods, Element.Methods.Simulated); 
     
    26593020    klass = 'HTML' + tagName.capitalize() + 'Element'; 
    26603021    if (window[klass]) return window[klass]; 
    26613022 
    2662     window[klass] = { }; 
    2663     window[klass].prototype = document.createElement(tagName).__proto__; 
    2664     return window[klass]; 
     3023    var element = document.createElement(tagName); 
     3024    var proto = element['__proto__'] || element.constructor.prototype; 
     3025    element = null; 
     3026    return proto; 
    26653027  } 
    26663028 
     3029  var elementPrototype = window.HTMLElement ? HTMLElement.prototype : 
     3030   Element.prototype; 
     3031 
    26673032  if (F.ElementExtensions) { 
    2668     copy(Element.Methods, HTMLElement.prototype); 
    2669     copy(Element.Methods.Simulated, HTMLElement.prototype, true); 
     3033    copy(Element.Methods, elementPrototype); 
     3034    copy(Element.Methods.Simulated, elementPrototype, true); 
    26703035  } 
    26713036 
    26723037  if (F.SpecificElementExtensions) { 
     
    26843049  Element.cache = { }; 
    26853050}; 
    26863051 
     3052 
    26873053document.viewport = { 
     3054 
    26883055  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; 
     3056    return { width: this.getWidth(), height: this.getHeight() }; 
    26963057  }, 
    26973058 
    2698   getWidth: function() { 
    2699     return this.getDimensions().width; 
     3059  getScrollOffsets: function() { 
     3060    return Element._returnOffset( 
     3061      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, 
     3062      window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop); 
     3063  } 
     3064}; 
     3065 
     3066(function(viewport) { 
     3067  var B = Prototype.Browser, doc = document, element, property = {}; 
     3068 
     3069  function getRootElement() { 
     3070    if (B.WebKit && !doc.evaluate) 
     3071      return document; 
     3072 
     3073    if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) 
     3074      return document.body; 
     3075 
     3076    return document.documentElement; 
     3077  } 
     3078 
     3079  function define(D) { 
     3080    if (!element) element = getRootElement(); 
     3081 
     3082    property[D] = 'client' + D; 
     3083 
     3084    viewport['get' + D] = function() { return element[property[D]] }; 
     3085    return viewport['get' + D](); 
     3086  } 
     3087 
     3088  viewport.getWidth  = define.curry('Width'); 
     3089 
     3090  viewport.getHeight = define.curry('Height'); 
     3091})(document.viewport); 
     3092 
     3093 
     3094Element.Storage = { 
     3095  UID: 1 
     3096}; 
     3097 
     3098Element.addMethods({ 
     3099  getStorage: function(element) { 
     3100    if (!(element = $(element))) return; 
     3101 
     3102    var uid; 
     3103    if (element === window) { 
     3104      uid = 0; 
     3105    } else { 
     3106      if (typeof element._prototypeUID === "undefined") 
     3107        element._prototypeUID = [Element.Storage.UID++]; 
     3108      uid = element._prototypeUID[0]; 
     3109    } 
     3110 
     3111    if (!Element.Storage[uid]) 
     3112      Element.Storage[uid] = $H(); 
     3113 
     3114    return Element.Storage[uid]; 
    27003115  }, 
    27013116 
    2702   getHeight: function() { 
    2703     return this.getDimensions().height; 
     3117  store: function(element, key, value) { 
     3118    if (!(element = $(element))) return; 
     3119 
     3120    if (arguments.length === 2) { 
     3121      Element.getStorage(element).update(key); 
     3122    } else { 
     3123      Element.getStorage(element).set(key, value); 
     3124    } 
     3125 
     3126    return element; 
    27043127  }, 
    27053128 
    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); 
     3129  retrieve: function(element, key, defaultValue) { 
     3130    if (!(element = $(element))) return; 
     3131    var hash = Element.getStorage(element), value = hash.get(key); 
     3132 
     3133    if (Object.isUndefined(value)) { 
     3134      hash.set(key, defaultValue); 
     3135      value = defaultValue; 
     3136    } 
     3137 
     3138    return value; 
     3139  }, 
     3140 
     3141  clone: function(element, deep) { 
     3142    if (!(element = $(element))) return; 
     3143    var clone = element.cloneNode(deep); 
     3144    clone._prototypeUID = void 0; 
     3145    if (deep) { 
     3146      var descendants = Element.select(clone, '*'), 
     3147          i = descendants.length; 
     3148      while (i--) { 
     3149        descendants[i]._prototypeUID = void 0; 
     3150      } 
     3151    } 
     3152    return Element.extend(clone); 
    27103153  } 
    2711 }; 
    2712 /* Portions of the Selector class are derived from Jack Slocums DomQuery, 
     3154}); 
     3155/* Portions of the Selector class are derived from Jack Slocum's DomQuery, 
    27133156 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style 
    27143157 * license.  Please see http://www.yui-ext.com/ for more information. */ 
    27153158 
    27163159var Selector = Class.create({ 
    27173160  initialize: function(expression) { 
    27183161    this.expression = expression.strip(); 
    2719     this.compileMatcher(); 
     3162 
     3163    if (this.shouldUseSelectorsAPI()) { 
     3164      this.mode = 'selectorsAPI'; 
     3165    } else if (this.shouldUseXPath()) { 
     3166      this.mode = 'xpath'; 
     3167      this.compileXPathMatcher(); 
     3168    } else { 
     3169      this.mode = "normal"; 
     3170      this.compileMatcher(); 
     3171    } 
     3172 
    27203173  }, 
    27213174 
     3175  shouldUseXPath: (function() { 
     3176 
     3177    var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ 
     3178      var isBuggy = false; 
     3179      if (document.evaluate && window.XPathResult) { 
     3180        var el = document.createElement('div'); 
     3181        el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>'; 
     3182 
     3183        var xpath = ".//*[local-name()='ul' or local-name()='UL']" + 
     3184          "//*[local-name()='li' or local-name()='LI']"; 
     3185 
     3186        var result = document.evaluate(xpath, el, null, 
     3187          XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 
     3188 
     3189        isBuggy = (result.snapshotLength !== 2); 
     3190        el = null; 
     3191      } 
     3192      return isBuggy; 
     3193    })(); 
     3194 
     3195    return function() { 
     3196      if (!Prototype.BrowserFeatures.XPath) return false; 
     3197 
     3198      var e = this.expression; 
     3199 
     3200      if (Prototype.Browser.WebKit && 
     3201       (e.include("-of-type") || e.include(":empty"))) 
     3202        return false; 
     3203 
     3204      if ((/(\[[\w-]*?:|:checked)/).test(e)) 
     3205        return false; 
     3206 
     3207      if (IS_DESCENDANT_SELECTOR_BUGGY) return false; 
     3208 
     3209      return true; 
     3210    } 
     3211 
     3212  })(), 
     3213 
     3214  shouldUseSelectorsAPI: function() { 
     3215    if (!Prototype.BrowserFeatures.SelectorsAPI) return false; 
     3216 
     3217    if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; 
     3218 
     3219    if (!Selector._div) Selector._div = new Element('div'); 
     3220 
     3221    try { 
     3222      Selector._div.querySelector(this.expression); 
     3223    } catch(e) { 
     3224      return false; 
     3225    } 
     3226 
     3227    return true; 
     3228  }, 
     3229 
    27223230  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  
    27273231    var e = this.expression, ps = Selector.patterns, h = Selector.handlers, 
    2728         c = Selector.criteria, le, p, m; 
     3232        c = Selector.criteria, le, p, m, len = ps.length, name; 
    27293233 
    27303234    if (Selector._cache[e]) { 
    27313235      this.matcher = Selector._cache[e]; 
     
    27373241 
    27383242    while (e && le != e && (/\S/).test(e)) { 
    27393243      le = e; 
    2740       for (var i in ps) { 
    2741         p = ps[i]; 
     3244      for (var i = 0; i<len; i++) { 
     3245        p = ps[i].re; 
     3246        name = ps[i].name; 
    27423247        if (m = e.match(p)) { 
    2743           this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : 
    2744               new Template(c[i]).evaluate(m)); 
     3248          this.matcher.push(Object.isFunction(c[name]) ? c[name](m) : 
     3249            new Template(c[name]).evaluate(m)); 
    27453250          e = e.replace(m[0], ''); 
    27463251          break; 
    27473252        } 
     
    27553260 
    27563261  compileXPathMatcher: function() { 
    27573262    var e = this.expression, ps = Selector.patterns, 
    2758         x = Selector.xpath, le, m; 
     3263        x = Selector.xpath, le, m, len = ps.length, name; 
    27593264 
    27603265    if (Selector._cache[e]) { 
    27613266      this.xpath = Selector._cache[e]; return; 
     
    27643269    this.matcher = ['.//*']; 
    27653270    while (e && le != e && (/\S/).test(e)) { 
    27663271      le = e; 
    2767       for (var i in ps) { 
    2768         if (m = e.match(ps[i])) { 
    2769           this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : 
    2770             new Template(x[i]).evaluate(m)); 
     3272      for (var i = 0; i<len; i++) { 
     3273        name = ps[i].name; 
     3274        if (m = e.match(ps[i].re)) { 
     3275          this.matcher.push(Object.isFunction(x[name]) ? x[name](m) : 
     3276            new Template(x[name]).evaluate(m)); 
    27713277          e = e.replace(m[0], ''); 
    27723278          break; 
    27733279        } 
     
    27803286 
    27813287  findElements: function(root) { 
    27823288    root = root || document; 
    2783     if (this.xpath) return document._getElementsByXPath(this.xpath, root); 
    2784     return this.matcher(root); 
     3289    var e = this.expression, results; 
     3290 
     3291    switch (this.mode) { 
     3292      case 'selectorsAPI': 
     3293        if (root !== document) { 
     3294          var oldId = root.id, id = $(root).identify(); 
     3295          id = id.replace(/([\.:])/g, "\\$1"); 
     3296          e = "#" + id + " " + e; 
     3297        } 
     3298 
     3299        results = $A(root.querySelectorAll(e)).map(Element.extend); 
     3300        root.id = oldId; 
     3301 
     3302        return results; 
     3303      case 'xpath': 
     3304        return document._getElementsByXPath(this.xpath, root); 
     3305      default: 
     3306       return this.matcher(root); 
     3307    } 
    27853308  }, 
    27863309 
    27873310  match: function(element) { 
    27883311    this.tokens = []; 
    27893312 
    27903313    var e = this.expression, ps = Selector.patterns, as = Selector.assertions; 
    2791     var le, p, m; 
     3314    var le, p, m, len = ps.length, name; 
    27923315 
    27933316    while (e && le !== e && (/\S/).test(e)) { 
    27943317      le = e; 
    2795       for (var i in ps) { 
    2796         p = ps[i]; 
     3318      for (var i = 0; i<len; i++) { 
     3319        p = ps[i].re; 
     3320        name = ps[i].name; 
    27973321        if (m = e.match(p)) { 
    2798           // use the Selector.assertions methods unless the selector 
    2799           // is too complex. 
    2800           if (as[i]) { 
    2801             this.tokens.push([i, Object.clone(m)]); 
     3322          if (as[name]) { 
     3323            this.tokens.push([name, Object.clone(m)]); 
    28023324            e = e.replace(m[0], ''); 
    28033325          } else { 
    2804             // reluctantly do a document-wide search 
    2805             // and look for a match in the array 
    28063326            return this.findElements(document).include(element); 
    28073327          } 
    28083328        } 
     
    28293349  } 
    28303350}); 
    28313351 
     3352if (Prototype.BrowserFeatures.SelectorsAPI && 
     3353 document.compatMode === 'BackCompat') { 
     3354  Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ 
     3355    var div = document.createElement('div'), 
     3356     span = document.createElement('span'); 
     3357 
     3358    div.id = "prototype_test_id"; 
     3359    span.className = 'Test'; 
     3360    div.appendChild(span); 
     3361    var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); 
     3362    div = span = null; 
     3363    return isIgnored; 
     3364  })(); 
     3365} 
     3366 
    28323367Object.extend(Selector, { 
    28333368  _cache: { }, 
    28343369 
     
    28443379    }, 
    28453380    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]", 
    28463381    id:           "[@id='#{1}']", 
    2847     attrPresence: "[@#{1}]", 
     3382    attrPresence: function(m) { 
     3383      m[1] = m[1].toLowerCase(); 
     3384      return new Template("[@#{1}]").evaluate(m); 
     3385    }, 
    28483386    attr: function(m) { 
     3387      m[1] = m[1].toLowerCase(); 
    28493388      m[3] = m[5] || m[6]; 
    28503389      return new Template(Selector.xpath.operators[m[2]]).evaluate(m); 
    28513390    }, 
     
    28683407      'first-child': '[not(preceding-sibling::*)]', 
    28693408      'last-child':  '[not(following-sibling::*)]', 
    28703409      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]', 
    2871       'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 
     3410      'empty':       "[count(*) = 0 and (count(text()) = 0)]", 
    28723411      'checked':     "[@checked]", 
    2873       'disabled':    "[@disabled]", 
    2874       'enabled':     "[not(@disabled)]", 
     3412      'disabled':    "[(@disabled) and (@type!='hidden')]", 
     3413      'enabled':     "[not(@disabled) and (@type!='hidden')]", 
    28753414      'not': function(m) { 
    28763415        var e = m[6], p = Selector.patterns, 
    2877             x = Selector.xpath, le, m, v; 
     3416            x = Selector.xpath, le, v, len = p.length, name; 
    28783417 
    28793418        var exclusion = []; 
    28803419        while (e && le != e && (/\S/).test(e)) { 
    28813420          le = e; 
    2882           for (var i in p) { 
    2883             if (m = e.match(p[i])) { 
    2884               v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); 
     3421          for (var i = 0; i<len; i++) { 
     3422            name = p[i].name 
     3423            if (m = e.match(p[i].re)) { 
     3424              v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m); 
    28853425              exclusion.push("(" + v.substring(1, v.length - 1) + ")"); 
    28863426              e = e.replace(m[0], ''); 
    28873427              break; 
     
    29313471  }, 
    29323472 
    29333473  criteria: { 
    2934     tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;', 
    2935     className:    'n = h.className(n, r, "#{1}", c); c = false;', 
    2936     id:           'n = h.id(n, r, "#{1}", c);        c = false;', 
    2937     attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', 
     3474    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;', 
     3475    className:    'n = h.className(n, r, "#{1}", c);    c = false;', 
     3476    id:           'n = h.id(n, r, "#{1}", c);           c = false;', 
     3477    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', 
    29383478    attr: function(m) { 
    29393479      m[3] = (m[5] || m[6]); 
    2940       return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); 
     3480      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); 
    29413481    }, 
    29423482    pseudo: function(m) { 
    29433483      if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); 
     
    29493489    laterSibling: 'c = "laterSibling";' 
    29503490  }, 
    29513491 
    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/, 
     3492  patterns: [ 
     3493    { name: 'laterSibling', re: /^\s*~\s*/ }, 
     3494    { name: 'child',        re: /^\s*>\s*/ }, 
     3495    { name: 'adjacent',     re: /^\s*\+\s*/ }, 
     3496    { name: 'descendant',   re: /^\s/ }, 
    29593497 
    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   }, 
     3498    { name: 'tagName',      re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, 
     3499    { name: 'id',           re: /^#([\w\-\*]+)(\b|$)/ }, 
     3500    { name: 'className',    re: /^\.([\w\-\*]+)(\b|$)/ }, 
     3501    { name: 'pseudo',       re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, 
     3502    { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, 
     3503    { name: 'attr',         re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } 
     3504  ], 
    29683505 
    2969   // for Selector.match and Element#match 
    29703506  assertions: { 
    29713507    tagName: function(element, matches) { 
    29723508      return matches[1].toUpperCase() == element.tagName.toUpperCase(); 
     
    29863522 
    29873523    attr: function(element, matches) { 
    29883524      var nodeValue = Element.readAttribute(element, matches[1]); 
    2989       return Selector.operators[matches[2]](nodeValue, matches[3]); 
     3525      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); 
    29903526    } 
    29913527  }, 
    29923528 
    29933529  handlers: { 
    2994     // UTILITY FUNCTIONS 
    2995     // joins two collections 
    29963530    concat: function(a, b) { 
    29973531      for (var i = 0, node; node = b[i]; i++) 
    29983532        a.push(node); 
    29993533      return a; 
    30003534    }, 
    30013535 
    3002     // marks an array of nodes for counting 
    30033536    mark: function(nodes) { 
     3537      var _true = Prototype.emptyFunction; 
    30043538      for (var i = 0, node; node = nodes[i]; i++) 
    3005         node._counted = true; 
     3539        node._countedByPrototype = _true; 
    30063540      return nodes; 
    30073541    }, 
    30083542 
    3009     unmark: function(nodes) { 
    3010       for (var i = 0, node; node = nodes[i]; i++) 
    3011         node._counted = undefined; 
    3012       return nodes; 
    3013     }, 
     3543    unmark: (function(){ 
    30143544 
    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 
     3545      var PROPERTIES_ATTRIBUTES_MAP = (function(){ 
     3546        var el = document.createElement('div'), 
     3547            isBuggy = false, 
     3548            propName = '_countedByPrototype', 
     3549            value = 'x' 
     3550        el[propName] = value; 
     3551        isBuggy = (el.getAttribute(propName) === value); 
     3552        el = null; 
     3553        return isBuggy; 
     3554      })(); 
     3555 
     3556      return PROPERTIES_ATTRIBUTES_MAP ? 
     3557        function(nodes) { 
     3558          for (var i = 0, node; node = nodes[i]; i++) 
     3559            node.removeAttribute('_countedByPrototype'); 
     3560          return nodes; 
     3561        } : 
     3562        function(nodes) { 
     3563          for (var i = 0, node; node = nodes[i]; i++) 
     3564            node._countedByPrototype = void 0; 
     3565          return nodes; 
     3566        } 
     3567    })(), 
     3568 
    30183569    index: function(parentNode, reverse, ofType) { 
    3019       parentNode._counted = true; 
     3570      parentNode._countedByPrototype = Prototype.emptyFunction; 
    30203571      if (reverse) { 
    30213572        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { 
    30223573          var node = nodes[i]; 
    3023           if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 
     3574          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 
    30243575        } 
    30253576      } else { 
    30263577        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) 
    3027           if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; 
     3578          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; 
    30283579      } 
    30293580    }, 
    30303581 
    3031     // filters out duplicates and extends all nodes 
    30323582    unique: function(nodes) { 
    30333583      if (nodes.length == 0) return nodes; 
    30343584      var results = [], n; 
    30353585      for (var i = 0, l = nodes.length; i < l; i++) 
    3036         if (!(n = nodes[i])._counted) { 
    3037           n._counted = true; 
     3586        if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { 
     3587          n._countedByPrototype = Prototype.emptyFunction; 
    30383588          results.push(Element.extend(n)); 
    30393589        } 
    30403590      return Selector.handlers.unmark(results); 
    30413591    }, 
    30423592 
    3043     // COMBINATOR FUNCTIONS 
    30443593    descendant: function(nodes) { 
    30453594      var h = Selector.handlers; 
    30463595      for (var i = 0, results = [], node; node = nodes[i]; i++) 
     
    30513600    child: function(nodes) { 
    30523601      var h = Selector.handlers; 
    30533602      for (var i = 0, results = [], node; node = nodes[i]; i++) { 
    3054         for (var j = 0, children = [], child; child = node.childNodes[j]; j++) 
     3603        for (var j = 0, child; child = node.childNodes[j]; j++) 
    30553604          if (child.nodeType == 1 && child.tagName != '!') results.push(child); 
    30563605      } 
    30573606      return results; 
     
    30743623 
    30753624    nextElementSibling: function(node) { 
    30763625      while (node = node.nextSibling) 
    3077               if (node.nodeType == 1) return node; 
     3626        if (node.nodeType == 1) return node; 
    30783627      return null; 
    30793628    }, 
    30803629 
     
    30843633      return null; 
    30853634    }, 
    30863635 
    3087     // TOKEN FUNCTIONS 
    30883636    tagName: function(nodes, root, tagName, combinator) { 
    3089       tagName = tagName.toUpperCase(); 
     3637      var uTagName = tagName.toUpperCase(); 
    30903638      var results = [], h = Selector.handlers; 
    30913639      if (nodes) { 
    30923640        if (combinator) { 
    3093           // fastlane for ordinary descendant combinators 
    30943641          if (combinator == "descendant") { 
    30953642            for (var i = 0, node; node = nodes[i]; i++) 
    30963643              h.concat(results, node.getElementsByTagName(tagName)); 
     
    30993646          if (tagName == "*") return nodes; 
    31003647        } 
    31013648        for (var i = 0, node; node = nodes[i]; i++) 
    3102           if (node.tagName.toUpperCase() == tagName) results.push(node); 
     3649          if (node.tagName.toUpperCase() === uTagName) results.push(node); 
    31033650        return results; 
    31043651      } else return root.getElementsByTagName(tagName); 
    31053652    }, 
    31063653 
    31073654    id: function(nodes, root, id, combinator) { 
    31083655      var targetNode = $(id), h = Selector.handlers; 
    3109       if (!targetNode) return []; 
    3110       if (!nodes && root == document) return [targetNode]; 
     3656 
     3657      if (root == document) { 
     3658        if (!targetNode) return []; 
     3659        if (!nodes) return [targetNode]; 
     3660      } else { 
     3661        if (!root.sourceIndex || root.sourceIndex < 1) { 
     3662          var nodes = root.getElementsByTagName('*'); 
     3663          for (var j = 0, node; node = nodes[j]; j++) { 
     3664            if (node.id === id) return [node]; 
     3665          } 
     3666        } 
     3667      } 
     3668 
    31113669      if (nodes) { 
    31123670        if (combinator) { 
    31133671          if (combinator == 'child') { 
     
    31463704      return results; 
    31473705    }, 
    31483706 
    3149     attrPresence: function(nodes, root, attr) { 
     3707    attrPresence: function(nodes, root, attr, combinator) { 
    31503708      if (!nodes) nodes = root.getElementsByTagName("*"); 
     3709      if (nodes && combinator) nodes = this[combinator](nodes); 
    31513710      var results = []; 
    31523711      for (var i = 0, node; node = nodes[i]; i++) 
    31533712        if (Element.hasAttribute(node, attr)) results.push(node); 
    31543713      return results; 
    31553714    }, 
    31563715 
    3157     attr: function(nodes, root, attr, value, operator) { 
     3716    attr: function(nodes, root, attr, value, operator, combinator) { 
    31583717      if (!nodes) nodes = root.getElementsByTagName("*"); 
     3718      if (nodes && combinator) nodes = this[combinator](nodes); 
    31593719      var handler = Selector.operators[operator], results = []; 
    31603720      for (var i = 0, node; node = nodes[i]; i++) { 
    31613721        var nodeValue = Element.readAttribute(node, attr); 
     
    32173777      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); 
    32183778    }, 
    32193779 
    3220     // handles the an+b logic 
    32213780    getIndices: function(a, b, total) { 
    32223781      if (a == 0) return b > 0 ? [b] : []; 
    32233782      return $R(1, total).inject([], function(memo, i) { 
     
    32263785      }); 
    32273786    }, 
    32283787 
    3229     // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type 
    32303788    nth: function(nodes, formula, root, reverse, ofType) { 
    32313789      if (nodes.length == 0) return []; 
    32323790      if (formula == 'even') formula = '2n+0'; 
     
    32343792      var h = Selector.handlers, results = [], indexed = [], m; 
    32353793      h.mark(nodes); 
    32363794      for (var i = 0, node; node = nodes[i]; i++) { 
    3237         if (!node.parentNode._counted) { 
     3795        if (!node.parentNode._countedByPrototype) { 
    32383796          h.index(node.parentNode, reverse, ofType); 
    32393797          indexed.push(node.parentNode); 
    32403798        } 
     
    32603818 
    32613819    'empty': function(nodes, value, root) { 
    32623820      for (var i = 0, results = [], node; node = nodes[i]; i++) { 
    3263         // IE treats comments as element nodes 
    3264         if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; 
     3821        if (node.tagName == '!' || node.firstChild) continue; 
    32653822        results.push(node); 
    32663823      } 
    32673824      return results; 
     
    32723829      var exclusions = new Selector(selector).findElements(root); 
    32733830      h.mark(exclusions); 
    32743831      for (var i = 0, results = [], node; node = nodes[i]; i++) 
    3275         if (!node._counted) results.push(node); 
     3832        if (!node._countedByPrototype) results.push(node); 
    32763833      h.unmark(exclusions); 
    32773834      return results; 
    32783835    }, 
    32793836 
    32803837    'enabled': function(nodes, value, root) { 
    32813838      for (var i = 0, results = [], node; node = nodes[i]; i++) 
    3282         if (!node.disabled) results.push(node); 
     3839        if (!node.disabled && (!node.type || node.type !== 'hidden')) 
     3840          results.push(node); 
    32833841      return results; 
    32843842    }, 
    32853843 
     
    32993857  operators: { 
    33003858    '=':  function(nv, v) { return nv == v; }, 
    33013859    '!=': function(nv, v) { return nv != v; }, 
    3302     '^=': function(nv, v) { return nv.startsWith(v); }, 
    3303     '$=': function(nv, v) { return nv.endsWith(v); }, 
    3304     '*=': function(nv, v) { return nv.include(v); }, 
     3860    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, 
     3861    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, 
     3862    '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, 
    33053863    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, 
    3306     '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } 
     3864    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + 
     3865     '-').include('-' + (v || "").toUpperCase() + '-'); } 
    33073866  }, 
    33083867 
     3868  split: function(expression) { 
     3869    var expressions = []; 
     3870    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 
     3871      expressions.push(m[1].strip()); 
     3872    }); 
     3873    return expressions; 
     3874  }, 
     3875 
    33093876  matchElements: function(elements, expression) { 
    3310     var matches = new Selector(expression).findElements(), h = Selector.handlers; 
     3877    var matches = $$(expression), h = Selector.handlers; 
    33113878    h.mark(matches); 
    33123879    for (var i = 0, results = [], element; element = elements[i]; i++) 
    3313       if (element._counted) results.push(element); 
     3880      if (element._countedByPrototype) results.push(element); 
    33143881    h.unmark(matches); 
    33153882    return results; 
    33163883  }, 
     
    33233890  }, 
    33243891 
    33253892  findChildElements: function(element, expressions) { 
    3326     var exprs = expressions.join(','), expressions = []; 
    3327     exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { 
    3328       expressions.push(m[1].strip()); 
    3329     }); 
     3893    expressions = Selector.split(expressions.join(',')); 
    33303894    var results = [], h = Selector.handlers; 
    33313895    for (var i = 0, l = expressions.length, selector; i < l; i++) { 
    33323896      selector = new Selector(expressions[i].strip()); 
     
    33363900  } 
    33373901}); 
    33383902 
     3903if (Prototype.Browser.IE) { 
     3904  Object.extend(Selector.handlers, { 
     3905    concat: function(a, b) { 
     3906      for (var i = 0, node; node = b[i]; i++) 
     3907        if (node.tagName !== "!") a.push(node); 
     3908      return a; 
     3909    } 
     3910  }); 
     3911} 
     3912 
    33393913function $$() { 
    33403914  return Selector.findChildElements(document, $A(arguments)); 
    33413915} 
     3916 
    33423917var Form = { 
    33433918  reset: function(form) { 
    3344     $(form).reset(); 
     3919    form = $(form); 
     3920    form.reset(); 
    33453921    return form; 
    33463922  }, 
    33473923 
    33483924  serializeElements: function(elements, options) { 
    33493925    if (typeof options != 'object') options = { hash: !!options }; 
    3350     else if (options.hash === undefined) options.hash = true; 
     3926    else if (Object.isUndefined(options.hash)) options.hash = true; 
    33513927    var key, value, submitted = false, submit = options.submit; 
    33523928 
    33533929    var data = elements.inject({ }, function(result, element) { 
    33543930      if (!element.disabled && element.name) { 
    33553931        key = element.name; value = $(element).getValue(); 
    3356         if (value != null && (element.type != 'submit' || (!submitted && 
     3932        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && 
    33573933            submit !== false && (!submit || key == submit) && (submitted = true)))) { 
    33583934          if (key in result) { 
    3359             // a key is already present; construct an array of values 
    33603935            if (!Object.isArray(result[key])) result[key] = [result[key]]; 
    33613936            result[key].push(value); 
    33623937          } 
     
    33763951  }, 
    33773952 
    33783953  getElements: function(form) { 
    3379     return $A($(form).getElementsByTagName('*')).inject([], 
    3380       function(elements, child) { 
    3381         if (Form.Element.Serializers[child.tagName.toLowerCase()]) 
    3382           elements.push(Element.extend(child)); 
    3383         return elements; 
    3384       } 
    3385     ); 
     3954    var elements = $(form).getElementsByTagName('*'), 
     3955        element, 
     3956        arr = [ ], 
     3957        serializers = Form.Element.Serializers; 
     3958    for (var i = 0; element = elements[i]; i++) { 
     3959      arr.push(element); 
     3960    } 
     3961    return arr.inject([], function(elements, child) { 
     3962      if (serializers[child.tagName.toLowerCase()]) 
     3963        elements.push(Element.extend(child)); 
     3964      return elements; 
     3965    }) 
    33863966  }, 
    33873967 
    33883968  getInputs: function(form, typeName, name) { 
     
    34224002    }).sortBy(function(element) { return element.tabIndex }).first(); 
    34234003 
    34244004    return firstByIndex ? firstByIndex : elements.find(function(element) { 
    3425       return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); 
     4005      return /^(?:input|select|textarea)$/i.test(element.tagName); 
    34264006    }); 
    34274007  }, 
    34284008 
     
    34534033 
    34544034/*--------------------------------------------------------------------------*/ 
    34554035 
     4036 
    34564037Form.Element = { 
    34574038  focus: function(element) { 
    34584039    $(element).focus(); 
     
    34664047}; 
    34674048 
    34684049Form.Element.Methods = { 
     4050 
    34694051  serialize: function(element) { 
    34704052    element = $(element); 
    34714053    if (!element.disabled && element.name) { 
     
    35064088    try { 
    35074089      element.focus(); 
    35084090      if (element.select && (element.tagName.toLowerCase() != 'input' || 
    3509           !['button', 'reset', 'submit'].include(element.type))) 
     4091          !(/^(?:button|reset|submit)$/i.test(element.type)))) 
    35104092        element.select(); 
    35114093    } catch (e) { } 
    35124094    return element; 
     
    35144096 
    35154097  disable: function(element) { 
    35164098    element = $(element); 
    3517     element.blur(); 
    35184099    element.disabled = true; 
    35194100    return element; 
    35204101  }, 
     
    35294110/*--------------------------------------------------------------------------*/ 
    35304111 
    35314112var Field = Form.Element; 
     4113 
    35324114var $F = Form.Element.Methods.getValue; 
    35334115 
    35344116/*--------------------------------------------------------------------------*/ 
     
    35454127  }, 
    35464128 
    35474129  inputSelector: function(element, value) { 
    3548     if (value === undefined) return element.checked ? element.value : null; 
     4130    if (Object.isUndefined(value)) return element.checked ? element.value : null; 
    35494131    else element.checked = !!value; 
    35504132  }, 
    35514133 
    35524134  textarea: function(element, value) { 
    3553     if (value === undefined) return element.value; 
     4135    if (Object.isUndefined(value)) return element.value; 
    35544136    else element.value = value; 
    35554137  }, 
    35564138 
    3557   select: function(element, index) { 
    3558     if (index === undefined) 
     4139  select: function(element, value) { 
     4140    if (Object.isUndefined(value)) 
    35594141      return this[element.type == 'select-one' ? 
    35604142        'selectOne' : 'selectMany'](element); 
    35614143    else { 
    3562       var opt, value, single = !Object.isArray(index); 
     4144      var opt, currentValue, single = !Object.isArray(value); 
    35634145      for (var i = 0, length = element.length; i < length; i++) { 
    35644146        opt = element.options[i]; 
    3565         value = this.optionValue(opt); 
     4147        currentValue = this.optionValue(opt); 
    35664148        if (single) { 
    3567           if (value == index) { 
     4149          if (currentValue == value) { 
    35684150            opt.selected = true; 
    35694151            return; 
    35704152          } 
    35714153        } 
    3572         else opt.selected = index.include(value); 
     4154        else opt.selected = value.include(currentValue); 
    35734155      } 
    35744156    } 
    35754157  }, 
     
    35914173  }, 
    35924174 
    35934175  optionValue: function(opt) { 
    3594     // extend element because hasAttribute may not be native 
    35954176    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; 
    35964177  } 
    35974178}; 
    35984179 
    35994180/*--------------------------------------------------------------------------*/ 
    36004181 
     4182 
    36014183Abstract.TimedObserver = Class.create(PeriodicalExecuter, { 
    36024184  initialize: function($super, element, frequency, callback) { 
    36034185    $super(callback, frequency); 
     
    36794261    return Form.serialize(this.element); 
    36804262  } 
    36814263}); 
    3682 if (!window.Event) var Event = { }; 
     4264(function() { 
    36834265 
    3684 Object.extend(Event, { 
    3685   KEY_BACKSPACE: 8, 
    3686   KEY_TAB:       9, 
    3687   KEY_RETURN:   13, 
    3688   KEY_ESC:      27, 
    3689   KEY_LEFT:     37, 
    3690   KEY_UP:       38, 
    3691   KEY_RIGHT:    39, 
    3692   KEY_DOWN:     40, 
    3693   KEY_DELETE:   46, 
    3694   KEY_HOME:     36, 
    3695   KEY_END:      35, 
    3696   KEY_PAGEUP:   33, 
    3697   KEY_PAGEDOWN: 34, 
    3698   KEY_INSERT:   45, 
     4266  var Event = { 
     4267    KEY_BACKSPACE: 8, 
     4268    KEY_TAB:       9, 
     4269    KEY_RETURN:   13, 
     4270    KEY_ESC:      27, 
     4271    KEY_LEFT:     37, 
     4272    KEY_UP:       38, 
     4273    KEY_RIGHT:    39, 
     4274    KEY_DOWN:     40, 
     4275    KEY_DELETE:   46, 
     4276    KEY_HOME:     36, 
     4277    KEY_END:      35, 
     4278    KEY_PAGEUP:   33, 
     4279    KEY_PAGEDOWN: 34, 
     4280    KEY_INSERT:   45, 
    36994281 
    3700   cache: { }, 
     4282    cache: {} 
     4283  }; 
    37014284 
    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 }); 
     4285  var docEl = document.documentElement; 
     4286  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl 
     4287    && 'onmouseleave' in docEl; 
    37124288 
    3713 Event.Methods = (function() { 
    3714   var isButton; 
    3715  
     4289  var _isButton; 
    37164290  if (Prototype.Browser.IE) { 
    37174291    var buttonMap = { 0: 1, 1: 4, 2: 2 }; 
    3718     isButton = function(event, code) { 
    3719       return event.button == buttonMap[code]; 
     4292    _isButton = function(event, code) { 
     4293      return event.button === buttonMap[code]; 
    37204294    }; 
    3721  
    37224295  } else if (Prototype.Browser.WebKit) { 
    3723     isButton = function(event, code) { 
     4296    _isButton = function(event, code) { 
    37244297      switch (code) { 
    37254298        case 0: return event.which == 1 && !event.metaKey; 
    37264299        case 1: return event.which == 1 && event.metaKey; 
    37274300        default: return false; 
    37284301      } 
    37294302    }; 
    3730  
    37314303  } else { 
    3732     isButton = function(event, code) { 
     4304    _isButton = function(event, code) { 
    37334305      return event.which ? (event.which === code + 1) : (event.button === code); 
    37344306    }; 
    37354307  } 
    37364308 
    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) }, 
     4309  function isLeftClick(event)   { return _isButton(event, 0) } 
    37414310 
    3742     element: function(event) { 
    3743       var node = Event.extend(event).target; 
    3744       return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); 
    3745     }, 
     4311  function isMiddleClick(event) { return _isButton(event, 1) } 
    37464312 
    3747     findElement: function(event, expression) { 
    3748       var element = Event.element(event); 
    3749       return element.match(expression) ? element : element.up(expression); 
    3750     }, 
     4313  function isRightClick(event)  { return _isButton(event, 2) } 
    37514314 
    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     }, 
     4315  function element(event) { 
     4316    event = Event.extend(event); 
    37604317 
    3761     pointerX: function(event) { return Event.pointer(event).x }, 
    3762     pointerY: function(event) { return Event.pointer(event).y }, 
     4318    var node = event.target, type = event.type, 
     4319     currentTarget = event.currentTarget; 
    37634320 
    3764     stop: function(event) { 
    3765       Event.extend(event); 
    3766       event.preventDefault(); 
    3767       event.stopPropagation(); 
    3768       event.stopped = true; 
     4321    if (currentTarget && currentTarget.tagName) { 
     4322      if (type === 'load' || type === 'error' || 
     4323        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' 
     4324          && currentTarget.type === 'radio')) 
     4325            node = currentTarget; 
    37694326    } 
     4327 
     4328    if (node.nodeType == Node.TEXT_NODE) 
     4329      node = node.parentNode; 
     4330 
     4331    return Element.extend(node); 
     4332  } 
     4333 
     4334  function findElement(event, expression) { 
     4335    var element = Event.element(event); 
     4336    if (!expression) return element; 
     4337    var elements = [element].concat(element.ancestors()); 
     4338    return Selector.findElement(elements, expression, 0); 
     4339  } 
     4340 
     4341  function pointer(event) { 
     4342    return { x: pointerX(event), y: pointerY(event) }; 
     4343  } 
     4344 
     4345  function pointerX(event) { 
     4346    var docElement = document.documentElement, 
     4347     body = document.body || { scrollLeft: 0 }; 
     4348 
     4349    return event.pageX || (event.clientX + 
     4350      (docElement.scrollLeft || body.scrollLeft) - 
     4351      (docElement.clientLeft || 0)); 
     4352  } 
     4353 
     4354  function pointerY(event) { 
     4355    var docElement = document.documentElement, 
     4356     body = document.body || { scrollTop: 0 }; 
     4357 
     4358    return  event.pageY || (event.clientY + 
     4359       (docElement.scrollTop || body.scrollTop) - 
     4360       (docElement.clientTop || 0)); 
     4361  } 
     4362 
     4363 
     4364  function stop(event) { 
     4365    Event.extend(event); 
     4366    event.preventDefault(); 
     4367    event.stopPropagation(); 
     4368 
     4369    event.stopped = true; 
     4370  } 
     4371 
     4372  Event.Methods = { 
     4373    isLeftClick: isLeftClick, 
     4374    isMiddleClick: isMiddleClick, 
     4375    isRightClick: isRightClick, 
     4376 
     4377    element: element, 
     4378    findElement: findElement, 
     4379 
     4380    pointer: pointer, 
     4381    pointerX: pointerX, 
     4382    pointerY: pointerY, 
     4383 
     4384    stop: stop 
    37704385  }; 
    3771 })(); 
    37724386 
    3773 Event.extend = (function() { 
     4387 
    37744388  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { 
    37754389    m[name] = Event.Methods[name].methodize(); 
    37764390    return m; 
    37774391  }); 
    37784392 
    37794393  if (Prototype.Browser.IE) { 
     4394    function _relatedTarget(event) { 
     4395      var element; 
     4396      switch (event.type) { 
     4397        case 'mouseover': element = event.fromElement; break; 
     4398        case 'mouseout':  element = event.toElement;   break; 
     4399        default: return null; 
     4400      } 
     4401      return Element.extend(element); 
     4402    } 
     4403 
    37804404    Object.extend(methods, { 
    37814405      stopPropagation: function() { this.cancelBubble = true }, 
    37824406      preventDefault:  function() { this.returnValue = false }, 
    3783       inspect: function() { return "[object Event]" } 
     4407      inspect: function() { return '[object Event]' } 
    37844408    }); 
    37854409 
    3786     return function(event) { 
     4410    Event.extend = function(event, element) { 
    37874411      if (!event) return false; 
    37884412      if (event._extendedByPrototype) return event; 
    37894413 
    37904414      event._extendedByPrototype = Prototype.emptyFunction; 
    37914415      var pointer = Event.pointer(event); 
     4416 
    37924417      Object.extend(event, { 
    3793         target: event.srcElement, 
    3794         relatedTarget: Event.relatedTarget(event), 
     4418        target: event.srcElement || element, 
     4419        relatedTarget: _relatedTarget(event), 
    37954420        pageX:  pointer.x, 
    37964421        pageY:  pointer.y 
    37974422      }); 
     4423 
    37984424      return Object.extend(event, methods); 
    37994425    }; 
    3800  
    38014426  } else { 
    3802     Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; 
     4427    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; 
    38034428    Object.extend(Event.prototype, methods); 
    3804     return Prototype.K; 
     4429    Event.extend = Prototype.K; 
    38054430  } 
    3806 })(); 
    38074431 
    3808 Object.extend(Event, (function() { 
    3809   var cache = Event.cache; 
     4432  function _createResponder(element, eventName, handler) { 
     4433    var registry = Element.retrieve(element, 'prototype_event_registry'); 
    38104434 
    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   } 
     4435    if (Object.isUndefined(registry)) { 
     4436      CACHE.push(element); 
     4437      registry = Element.retrieve(element, 'prototype_event_registry', $H()); 
     4438    } 
    38164439 
    3817   function getDOMEventName(eventName) { 
    3818     if (eventName && eventName.include(':')) return "dataavailable"; 
    3819     return eventName; 
    3820   } 
     4440    var respondersForEvent = registry.get(eventName); 
     4441    if (Object.isUndefined(respondersForEvent)) { 
     4442      respondersForEvent = []; 
     4443      registry.set(eventName, respondersForEvent); 
     4444    } 
    38214445 
    3822   function getCacheForID(id) { 
    3823     return cache[id] = cache[id] || { }; 
    3824   } 
     4446    if (respondersForEvent.pluck('handler').include(handler)) return false; 
    38254447 
    3826   function getWrappersForEventName(id, eventName) { 
    3827     var c = getCacheForID(id); 
    3828     return c[eventName] = c[eventName] || []; 
    3829   } 
     4448    var responder; 
     4449    if (eventName.include(":")) { 
     4450      responder = function(event) { 
     4451        if (Object.isUndefined(event.eventName)) 
     4452          return false; 
    38304453 
    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)) 
     4454        if (event.eventName !== eventName) 
    38394455          return false; 
    38404456 
    3841       Event.extend(event); 
    3842       handler.call(element, event) 
    3843     }; 
     4457        Event.extend(event, element); 
     4458        handler.call(element, event); 
     4459      }; 
     4460    } else { 
     4461      if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && 
     4462       (eventName === "mouseenter" || eventName === "mouseleave")) { 
     4463        if (eventName === "mouseenter" || eventName === "mouseleave") { 
     4464          responder = function(event) { 
     4465            Event.extend(event, element); 
    38444466 
    3845     wrapper.handler = handler; 
    3846     c.push(wrapper); 
    3847     return wrapper; 
    3848   } 
     4467            var parent = event.relatedTarget; 
     4468            while (parent && parent !== element) { 
     4469              try { parent = parent.parentNode; } 
     4470              catch(e) { parent = element; } 
     4471            } 
    38494472 
    3850   function findWrapper(id, eventName, handler) { 
    3851     var c = getWrappersForEventName(id, eventName); 
    3852     return c.find(function(wrapper) { return wrapper.handler == handler }); 
    3853   } 
     4473            if (parent === element) return; 
    38544474 
    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)); 
     4475            handler.call(element, event); 
     4476          }; 
     4477        } 
     4478      } else { 
     4479        responder = function(event) { 
     4480          Event.extend(event, element); 
     4481          handler.call(element, event); 
     4482        }; 
     4483      } 
     4484    } 
     4485 
     4486    responder.handler = handler; 
     4487    respondersForEvent.push(responder); 
     4488    return responder; 
    38594489  } 
    38604490 
    3861   function destroyCache() { 
    3862     for (var id in cache) 
    3863       for (var eventName in cache[id]) 
    3864         cache[id][eventName] = null; 
     4491  function _destroyCache() { 
     4492    for (var i = 0, length = CACHE.length; i < length; i++) { 
     4493      Event.stopObserving(CACHE[i]); 
     4494      CACHE[i] = null; 
     4495    } 
    38654496  } 
    38664497 
    3867   if (window.attachEvent) { 
    3868     window.attachEvent("onunload", destroyCache); 
     4498  var CACHE = []; 
     4499 
     4500  if (Prototype.Browser.IE) 
     4501    window.attachEvent('onunload', _destroyCache); 
     4502 
     4503  if (Prototype.Browser.WebKit) 
     4504    window.addEventListener('unload', Prototype.emptyFunction, false); 
     4505 
     4506 
     4507  var _getDOMEventName = Prototype.K; 
     4508 
     4509  if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { 
     4510    _getDOMEventName = function(eventName) { 
     4511      var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; 
     4512      return eventName in translations ? translations[eventName] : eventName; 
     4513    }; 
    38694514  } 
    38704515 
    3871   return { 
    3872     observe: function(element, eventName, handler) { 
    3873       element = $(element); 
    3874       var name = getDOMEventName(eventName); 
     4516  function observe(element, eventName, handler) { 
     4517    element = $(element); 
    38754518 
    3876       var wrapper = createWrapper(element, eventName, handler); 
    3877       if (!wrapper) return element; 
     4519    var responder = _createResponder(element, eventName, handler); 
    38784520 
    3879       if (element.addEventListener) { 
    3880         element.addEventListener(name, wrapper, false); 
    3881       } else { 
    3882         element.attachEvent("on" + name, wrapper); 
     4521    if (!responder) return element; 
     4522 
     4523    if (eventName.include(':')) { 
     4524      if (element.addEventListener) 
     4525        element.addEventListener("dataavailable", responder, false); 
     4526      else { 
     4527        element.attachEvent("ondataavailable", responder); 
     4528        element.attachEvent("onfilterchange", responder); 
    38834529      } 
     4530    } else { 
     4531      var actualEventName = _getDOMEventName(eventName); 
    38844532 
    3885       return element; 
    3886     }, 
     4533      if (element.addEventListener) 
     4534        element.addEventListener(actualEventName, responder, false); 
     4535      else 
     4536        element.attachEvent("on" + actualEventName, responder); 
     4537    } 
    38874538 
    3888     stopObserving: function(element, eventName, handler) { 
    3889       element = $(element); 
    3890       var id = getEventID(element), name = getDOMEventName(eventName); 
     4539    return element; 
     4540  } 
    38914541 
    3892       if (!handler && eventName) { 
    3893         getWrappersForEventName(id, eventName).each(function(wrapper) { 
    3894           element.stopObserving(eventName, wrapper.handler); 
    3895         }); 
    3896         return element; 
     4542  function stopObserving(element, eventName, handler) { 
     4543    element = $(element); 
    38974544 
    3898       } else if (!eventName) { 
    3899         Object.keys(getCacheForID(id)).each(function(eventName) { 
    3900           element.stopObserving(eventName); 
    3901         }); 
    3902         return element; 
    3903       } 
     4545    var registry = Element.retrieve(element, 'prototype_event_registry'); 
    39044546 
    3905       var wrapper = findWrapper(id, eventName, handler); 
    3906       if (!wrapper) return element; 
     4547    if (Object.isUndefined(registry)) return element; 
    39074548 
    3908       if (element.removeEventListener) { 
    3909         element.removeEventListener(name, wrapper, false); 
    3910       } else { 
    3911         element.detachEvent("on" + name, wrapper); 
    3912       } 
     4549    if (eventName && !handler) { 
     4550      var responders = registry.get(eventName); 
    39134551 
    3914       destroyWrapper(id, eventName, handler); 
     4552      if (Object.isUndefined(responders)) return element; 
    39154553 
     4554      responders.each( function(r) { 
     4555        Element.stopObserving(element, eventName, r.handler); 
     4556      }); 
    39164557      return element; 
    3917     }, 
     4558    } else if (!eventName) { 
     4559      registry.each( function(pair) { 
     4560        var eventName = pair.key, responders = pair.value; 
    39184561 
    3919     fire: function(element, eventName, memo) { 
    3920       element = $(element); 
    3921       if (element == document && document.createEvent && !element.dispatchEvent) 
    3922         element = document.documentElement; 
     4562        responders.each( function(r) { 
     4563          Element.stopObserving(element, eventName, r.handler); 
     4564        }); 
     4565      }); 
     4566      return element; 
     4567    } 
    39234568 
    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       } 
     4569    var responders = registry.get(eventName); 
    39314570 
    3932       event.eventName = eventName; 
    3933       event.memo = memo || { }; 
     4571    if (!responders) return; 
    39344572 
    3935       if (document.createEvent) { 
    3936         element.dispatchEvent(event); 
    3937       } else { 
    3938         element.fireEvent(event.eventType, event); 
     4573    var responder = responders.find( function(r) { return r.handler === handler; }); 
     4574    if (!responder) return element; 
     4575 
     4576    var actualEventName = _getDOMEventName(eventName); 
     4577 
     4578    if (eventName.include(':')) { 
     4579      if (element.removeEventListener) 
     4580        element.removeEventListener("dataavailable", responder, false); 
     4581      else { 
     4582        element.detachEvent("ondataavailable", responder); 
     4583        element.detachEvent("onfilterchange",  responder); 
    39394584      } 
     4585    } else { 
     4586      if (element.removeEventListener) 
     4587        element.removeEventListener(actualEventName, responder, false); 
     4588      else 
     4589        element.detachEvent('on' + actualEventName, responder); 
     4590    } 
    39404591 
    3941       return event; 
     4592    registry.set(eventName, responders.without(responder)); 
     4593 
     4594    return element; 
     4595  } 
     4596 
     4597  function fire(element, eventName, memo, bubble) { 
     4598    element = $(element); 
     4599 
     4600    if (Object.isUndefined(bubble)) 
     4601      bubble = true; 
     4602 
     4603    if (element == document && document.createEvent && !element.dispatchEvent) 
     4604      element = document.documentElement; 
     4605 
     4606    var event; 
     4607    if (document.createEvent) { 
     4608      event = document.createEvent('HTMLEvents'); 
     4609      event.initEvent('dataavailable', true, true); 
     4610    } else { 
     4611      event = document.createEventObject(); 
     4612      event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; 
    39424613    } 
    3943   }; 
    3944 })()); 
    39454614 
    3946 Object.extend(Event, Event.Methods); 
     4615    event.eventName = eventName; 
     4616    event.memo = memo || { }; 
    39474617 
    3948 Element.addMethods({ 
    3949   fire:          Event.fire, 
    3950   observe:       Event.observe, 
    3951   stopObserving: Event.stopObserving 
    3952 }); 
     4618    if (document.createEvent) 
     4619      element.dispatchEvent(event); 
     4620    else 
     4621      element.fireEvent(event.eventType, event); 
    39534622 
    3954 Object.extend(document, { 
    3955   fire:          Element.Methods.fire.methodize(), 
    3956   observe:       Element.Methods.observe.methodize(), 
    3957   stopObserving: Element.Methods.stopObserving.methodize() 
    3958 }); 
     4623    return Event.extend(event); 
     4624  } 
    39594625 
     4626 
     4627  Object.extend(Event, Event.Methods); 
     4628 
     4629  Object.extend(Event, { 
     4630    fire:          fire, 
     4631    observe:       observe, 
     4632    stopObserving: stopObserving 
     4633  }); 
     4634 
     4635  Element.addMethods({ 
     4636    fire:          fire, 
     4637 
     4638    observe:       observe, 
     4639 
     4640    stopObserving: stopObserving 
     4641  }); 
     4642 
     4643  Object.extend(document, { 
     4644    fire:          fire.methodize(), 
     4645 
     4646    observe:       observe.methodize(), 
     4647 
     4648    stopObserving: stopObserving.methodize(), 
     4649 
     4650    loaded:        false 
     4651  }); 
     4652 
     4653  if (window.Event) Object.extend(window.Event, Event); 
     4654  else window.Event = Event; 
     4655})(); 
     4656 
    39604657(function() { 
    39614658  /* Support for the DOMContentLoaded event is based on work by Dan Webb, 
    3962      Matthias Miller, Dean Edwards and John Resig. */ 
     4659     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ 
    39634660 
    3964   var timer, fired = false; 
     4661  var timer; 
    39654662 
    39664663  function fireContentLoadedEvent() { 
    3967     if (fired) return; 
    3968     if (timer) window.clearInterval(timer); 
    3969     document.fire("dom:loaded"); 
    3970     fired = true; 
     4664    if (document.loaded) return; 
     4665    if (timer) window.clearTimeout(timer); 
     4666    document.loaded = true; 
     4667    document.fire('dom:loaded'); 
    39714668  } 
    39724669 
    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); 
     4670  function checkReadyState() { 
     4671    if (document.readyState === 'complete') { 
     4672      document.stopObserving('readystatechange', checkReadyState); 
     4673      fireContentLoadedEvent(); 
     4674    } 
     4675  } 
    39794676 
    3980       Event.observe(window, "load", fireContentLoadedEvent); 
    3981  
    3982     } else { 
    3983       document.addEventListener("DOMContentLoaded", 
    3984         fireContentLoadedEvent, false); 
     4677  function pollDoScroll() { 
     4678    try { document.documentElement.doScroll('left'); } 
     4679    catch(e) { 
     4680      timer = pollDoScroll.defer(); 
     4681      return; 
    39854682    } 
     4683    fireContentLoadedEvent(); 
     4684  } 
    39864685 
     4686  if (document.addEventListener) { 
     4687    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); 
    39874688  } 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     }; 
     4689    document.observe('readystatechange', checkReadyState); 
     4690    if (window == top) 
     4691      timer = pollDoScroll.defer(); 
    39954692  } 
     4693 
     4694  Event.observe(window, 'load', fireContentLoadedEvent); 
    39964695})(); 
     4696 
     4697Element.addMethods(); 
     4698 
    39974699/*------------------------------- DEPRECATED -------------------------------*/ 
    39984700 
    39994701Hash.toQueryString = Object.toQueryString; 
     
    40224724 
    40234725var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); 
    40244726 
    4025 // This should be moved to script.aculo.us; notice the deprecated methods 
    4026 // further below, that map to the newer Element methods. 
    40274727var Position = { 
    4028   // set to true if needed, warning: firefox performance problems 
    4029   // NOT neeeded for page scrolling, only if draggable contained in 
    4030   // scrollable elements 
    40314728  includeScrollOffsets: false, 
    40324729 
    4033   // must be called before calling withinIncludingScrolloffset, every time the 
    4034   // page is scrolled 
    40354730  prepare: function() { 
    40364731    this.deltaX =  window.pageXOffset 
    40374732                || document.documentElement.scrollLeft 
     
    40434738                || 0; 
    40444739  }, 
    40454740 
    4046   // caches x/y coordinate pair to use with overlap 
    40474741  within: function(element, x, y) { 
    40484742    if (this.includeScrollOffsets) 
    40494743      return this.withinIncludingScrolloffsets(element, x, y); 
     
    40704764            this.xcomp <  this.offset[0] + element.offsetWidth); 
    40714765  }, 
    40724766 
    4073   // within must be called directly before 
    40744767  overlap: function(mode, element) { 
    40754768    if (!mode) return 0; 
    40764769    if (mode == 'vertical') 
     
    40814774        element.offsetWidth; 
    40824775  }, 
    40834776 
    4084   // Deprecation layer -- use newer Element methods now (1.5.2). 
    40854777 
    40864778  cumulativeOffset: Element.Methods.cumulativeOffset, 
    40874779 
     
    41804872Object.extend(Element.ClassNames.prototype, Enumerable); 
    41814873 
    41824874/*--------------------------------------------------------------------------*/ 
    4183  
    4184 Element.addMethods(); 
    4185  No newline at end of file