Changeset 4813

Show
Ignore:
Timestamp:
01/26/07 03:41:17 (2 years ago)
Author:
ryan
Message:

Update to prototype 1.5.0 and scriptaculous 1.7.0. Fix some AJAXy bits. Props mdawaffe. fixes #3645 #3676 #3519

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/wp-includes/js/list-manipulation-js.php

    r4768 r4813  
    3333        if ( ajaxAdd.notInitialized() ) 
    3434            return true; 
    35         ajaxAdd.options.parameters += '&action=' + ( update ? 'update-' : 'add-' ) + what + '&' + this.grabInputs( where, ajaxAdd ) + this.inputData; 
     35        var action = ( update ? 'update-' : 'add-' ) + what; 
     36        ajaxAdd.options.parameters = $H(ajaxAdd.options.parameters).merge({action: action}).merge(this.inputData.toQueryParams()).merge(this.grabInputs( where, ajaxAdd ).toQueryParams()); 
     37 
    3638        var tempObj=this; 
    3739        ajaxAdd.addOnComplete( function(transport) { 
     
    8082            return true; 
    8183        var tempObj = this; 
    82         var action = 'delete-' + what + '&id=' + id; 
     84        var action = 'delete-' + what; 
     85        var actionId = action + '&id=' + id; 
    8386        var idName = what.replace('-as-spam','') + '-' + id; 
    8487        ajaxDel.addOnComplete( function(transport) { 
    8588            Element.update(ajaxDel.myResponseElement,''); 
    86             tempObj.destore(action); 
     89            tempObj.destore(actionId); 
    8790            if( tempObj.delComplete && typeof tempObj.delComplete == 'function' ) 
    8891                tempObj.delComplete( what, id, transport ); 
    8992        }); 
    90         ajaxDel.addOnWPError( function(transport) { tempObj.restore(action, true); }); 
    91         ajaxDel.options.parameters += '&action=' + action + this.inputData
     93        ajaxDel.addOnWPError( function(transport) { tempObj.restore(actionId, true); }); 
     94        ajaxDel.options.parameters = $H(ajaxDel.options.parameters).merge({action: action, id: id}).merge(this.inputData.toQueryParams())
    9295        ajaxDel.request(ajaxDel.url); 
    93         this.store(action, idName); 
     96        this.store(actionId, idName); 
    9497        tempObj.removeListItem( idName ); 
    9598        return false; 
     
    103106            return true; 
    104107        var tempObj = this; 
    105         var action = 'dim-' + what + '&id=' + id; 
     108        var action = 'dim-' + what; 
     109        var actionId = action + '&id=' + id; 
    106110        var idName = what + '-' + id; 
    107111        ajaxDim.addOnComplete( function(transport) { 
    108112            Element.update(ajaxDim.myResponseElement,''); 
    109             tempObj.destore(action); 
     113            tempObj.destore(actionId); 
    110114            if ( tempObj.dimComplete && typeof tempObj.dimComplete == 'function' ) 
    111115                tempObj.dimComplete( what, id, dimClass, transport ); 
    112116        }); 
    113         ajaxDim.addOnWPError( function(transport) { tempObj.restore(action, true); }); 
    114         ajaxDim.options.parameters += '&action=' + action + this.inputData
     117        ajaxDim.addOnWPError( function(transport) { tempObj.restore(actionId, true); }); 
     118        ajaxDim.options.parameters = $H(ajaxDim.options.parameters).merge({action: action, id: id}).merge(this.inputData.toQueryParams())
    115119        ajaxDim.request(ajaxDim.url); 
    116         this.store(action, idName); 
     120        this.store(actionId, idName); 
    117121        this.dimItem( idName, dimClass ); 
    118122        return false; 
  • trunk/wp-includes/js/prototype.js

    <
    r4082 r4813  
    1 /*  Prototype JavaScript framework, version 1.5.0_rc0 
    2  *  (c) 2005 Sam Stephenson <sam@conio.net> 
     1/*  Prototype JavaScript framework, version 1.5.0 
     2 *  (c) 2005-2007 Sam Stephenson 
    33 * 
    44 *  Prototype is freely distributable under the terms of an MIT-style license. 
     
    88 
    99var Prototype = { 
    10   Version: '1.5.0_rc0', 
     10  Version: '1.5.0', 
     11  BrowserFeatures: { 
     12    XPath: !!document.evaluate 
     13  }, 
     14 
    1115  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 
    12  
    1316  emptyFunction: function() {}, 
    14   K: function(x) {return x
     17  K: function(x) { return x
    1518} 
    1619 
     
    3235} 
    3336 
    34 Object.inspect = function(object) { 
    35   try { 
    36     if (object == undefined) return 'undefined'; 
    37     if (object == null) return 'null'; 
    38     return object.inspect ? object.inspect() : object.toString(); 
    39   } catch (e) { 
    40     if (e instanceof RangeError) return '...'; 
    41     throw e; 
    42   } 
    43 
     37Object.extend(Object, { 
     38  inspect: function(object) { 
     39    try { 
     40      if (object === undefined) return 'undefined'; 
     41      if (object === null) return 'null'; 
     42      return object.inspect ? object.inspect() : object.toString(); 
     43    } catch (e) { 
     44      if (e instanceof RangeError) return '...'; 
     45      throw e; 
     46    } 
     47  }, 
     48 
     49  keys: function(object) { 
     50    var keys = []; 
     51    for (var property in object) 
     52      keys.push(property); 
     53    return keys; 
     54  }, 
     55 
     56  values: function(object) { 
     57    var values = []; 
     58    for (var property in object) 
     59      values.push(object[property]); 
     60    return values; 
     61  }, 
     62 
     63  clone: function(object) { 
     64    return Object.extend({}, object); 
     65  } 
     66}); 
    4467 
    4568Function.prototype.bind = function() { 
     
    5174 
    5275Function.prototype.bindAsEventListener = function(object) { 
    53   var __method = this
     76  var __method = this, args = $A(arguments), object = args.shift()
    5477  return function(event) { 
    55     return __method.call(object, event || window.event); 
     78    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); 
    5679  } 
    5780} 
     
    78101    var returnValue; 
    79102 
    80     for (var i = 0; i < arguments.length; i++) { 
     103    for (var i = 0, length = arguments.length; i < length; i++) { 
    81104      var lambda = arguments[i]; 
    82105      try { 
     
    103126 
    104127  registerCallback: function() { 
    105     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 
     128    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); 
     129  }, 
     130 
     131  stop: function() { 
     132    if (!this.timer) return; 
     133    clearInterval(this.timer); 
     134    this.timer = null; 
    106135  }, 
    107136 
     
    110139      try { 
    111140        this.currentlyExecuting = true; 
    112         this.callback(); 
     141        this.callback(this); 
    113142      } finally { 
    114143        this.currentlyExecuting = false; 
     
    117146  } 
    118147} 
     148String.interpret = function(value){ 
     149  return value == null ? '' : String(value); 
     150} 
     151 
    119152Object.extend(String.prototype, { 
    120153  gsub: function(pattern, replacement) { 
     
    125158      if (match = source.match(pattern)) { 
    126159        result += source.slice(0, match.index); 
    127         result += (replacement(match) || '').toString(); 
     160        result += String.interpret(replacement(match)); 
    128161        source  = source.slice(match.index + match[0].length); 
    129162      } else { 
     
    190223    var div = document.createElement('div'); 
    191224    div.innerHTML = this.stripTags(); 
    192     return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; 
    193   }, 
    194  
    195   toQueryParams: function() { 
    196     var pairs = this.match(/^\??(.*)$/)[1].split('&'); 
    197     return pairs.inject({}, function(params, pairString) { 
    198       var pair = pairString.split('='); 
    199       params[pair[0]] = pair[1]; 
    200       return params; 
     225    return div.childNodes[0] ? (div.childNodes.length > 1 ? 
     226      $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : 
     227      div.childNodes[0].nodeValue) : ''; 
     228  }, 
     229 
     230  toQueryParams: function(separator) { 
     231    var match = this.strip().match(/([^?#]*)(#.*)?$/); 
     232    if (!match) return {}; 
     233 
     234    return match[1].split(separator || '&').inject({}, function(hash, pair) { 
     235      if ((pair = pair.split('='))[0]) { 
     236        var name = decodeURIComponent(pair[0]); 
     237        var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; 
     238 
     239        if (hash[name] !== undefined) { 
     240          if (hash[name].constructor != Array) 
     241            hash[name] = [hash[name]]; 
     242          if (value) hash[name].push(value); 
     243        } 
     244        else hash[name] = value; 
     245      } 
     246      return hash; 
    201247    }); 
    202248  }, 
     
    206252  }, 
    207253 
     254  succ: function() { 
     255    return this.slice(0, this.length - 1) + 
     256      String.fromCharCode(this.charCodeAt(this.length - 1) + 1); 
     257  }, 
     258 
    208259  camelize: function() { 
    209     var oStringList = this.split('-'); 
    210     if (oStringList.length == 1) return oStringList[0]; 
    211  
    212     var camelizedString = this.indexOf('-') == 0 
    213       ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 
    214       : oStringList[0]; 
    215  
    216     for (var i = 1, len = oStringList.length; i < len; i++) { 
    217       var s = oStringList[i]; 
    218       camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 
    219     } 
    220  
    221     return camelizedString; 
    222   }, 
    223  
    224   inspect: function() { 
    225     return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; 
     260    var parts = this.split('-'), len = parts.length; 
     261    if (len == 1) return parts[0]; 
     262 
     263    var camelized = this.charAt(0) == '-' 
     264      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 
     265      : parts[0]; 
     266 
     267    for (var i = 1; i < len; i++) 
     268      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 
     269 
     270    return camelized; 
     271  }, 
     272 
     273  capitalize: function(){ 
     274    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 
     275  }, 
     276 
     277  underscore: function() { 
     278    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); 
     279  }, 
     280 
     281  dasherize: function() { 
     282    return this.gsub(/_/,'-'); 
     283  }, 
     284 
     285  inspect: function(useDoubleQuotes) { 
     286    var escapedString = this.replace(/\\/g, '\\\\'); 
     287    if (useDoubleQuotes) 
     288      return '"' + escapedString.replace(/"/g, '\\"') + '"'; 
     289    else 
     290      return "'" + escapedString.replace(/'/g, '\\\'') + "'"; 
    226291  } 
    227292}); 
     
    247312      var before = match[1]; 
    248313      if (before == '\\') return match[2]; 
    249       return before + (object[match[3]] || '').toString(); 
     314      return before + String.interpret(object[match[3]]); 
    250315    }); 
    251316  } 
     
    269334      if (e != $break) throw e; 
    270335    } 
     336    return this; 
     337  }, 
     338 
     339  eachSlice: function(number, iterator) { 
     340    var index = -number, slices = [], array = this.toArray(); 
     341    while ((index += number) < array.length) 
     342      slices.push(array.slice(index, index+number)); 
     343    return slices.map(iterator); 
    271344  }, 
    272345 
     
    281354 
    282355  any: function(iterator) { 
    283     var result = true; 
     356    var result = false; 
    284357    this.each(function(value, index) { 
    285358      if (result = !!(iterator || Prototype.K)(value, index)) 
     
    292365    var results = []; 
    293366    this.each(function(value, index) { 
    294       results.push(iterator(value, index)); 
     367      results.push((iterator || Prototype.K)(value, index)); 
    295368    }); 
    296369    return results; 
    297370  }, 
    298371 
    299   detect: function (iterator) { 
     372  detect: function(iterator) { 
    300373    var result; 
    301374    this.each(function(value, index) { 
     
    338411  }, 
    339412 
     413  inGroupsOf: function(number, fillWith) { 
     414    fillWith = fillWith === undefined ? null : fillWith; 
     415    return this.eachSlice(number, function(slice) { 
     416      while(slice.length < number) slice.push(fillWith); 
     417      return slice; 
     418    }); 
     419  }, 
     420 
    340421  inject: function(memo, iterator) { 
    341422    this.each(function(value, index) { 
     
    347428  invoke: function(method) { 
    348429    var args = $A(arguments).slice(1); 
    349     return this.collect(function(value) { 
     430    return this.map(function(value) { 
    350431      return value[method].apply(value, args); 
    351432    }); 
     
    399480 
    400481  sortBy: function(iterator) { 
    401     return this.collect(function(value, index) { 
     482    return this.map(function(value, index) { 
    402483      return {value: value, criteria: iterator(value, index)}; 
    403484    }).sort(function(left, right) { 
     
    408489 
    409490  toArray: function() { 
    410     return this.collect(Prototype.K); 
     491    return this.map(); 
    411492  }, 
    412493 
     
    420501      return iterator(collections.pluck(index)); 
    421502    }); 
     503  }, 
     504 
     505  size: function() { 
     506    return this.toArray().length; 
    422507  }, 
    423508 
     
    440525  } else { 
    441526    var results = []; 
    442     for (var i = 0; i < iterable.length; i++) 
     527    for (var i = 0, length = iterable.length; i < length; i++) 
    443528      results.push(iterable[i]); 
    444529    return results; 
     
    453538Object.extend(Array.prototype, { 
    454539  _each: function(iterator) { 
    455     for (var i = 0; i < this.length; i++) 
     540    for (var i = 0, length = this.length; i < length; i++) 
    456541      iterator(this[i]); 
    457542  }, 
     
    472557  compact: function() { 
    473558    return this.select(function(value) { 
    474       return value != undefined || value != null; 
     559      return value != null; 
    475560    }); 
    476561  }, 
     
    491576 
    492577  indexOf: function(object) { 
    493     for (var i = 0; i < this.length; i++) 
     578    for (var i = 0, length = this.length; i < length; i++) 
    494579      if (this[i] == object) return i; 
    495580    return -1; 
     
    500585  }, 
    501586 
     587  reduce: function() { 
     588    return this.length > 1 ? this : this[0]; 
     589  }, 
     590 
     591  uniq: function() { 
     592    return this.inject([], function(array, value) { 
     593      return array.include(value) ? array : array.concat([value]); 
     594    }); 
     595  }, 
     596 
     597  clone: function() { 
     598    return [].concat(this); 
     599  }, 
     600 
     601  size: function() { 
     602    return this.length; 
     603  }, 
     604 
    502605  inspect: function() { 
    503606    return '[' + this.map(Object.inspect).join(', ') + ']'; 
    504607  } 
    505608}); 
    506 var Hash = { 
     609 
     610Array.prototype.toArray = Array.prototype.clone; 
     611 
     612function $w(string){ 
     613  string = string.strip(); 
     614  return string ? string.split(/\s+/) : []; 
     615
     616 
     617if(window.opera){ 
     618  Array.prototype.concat = function(){ 
     619    var array = []; 
     620    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); 
     621    for(var i = 0, length = arguments.length; i < length; i++) { 
     622      if(arguments[i].constructor == Array) { 
     623        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) 
     624          array.push(arguments[i][j]); 
     625      } else { 
     626        array.push(arguments[i]); 
     627      } 
     628    } 
     629    return array; 
     630  } 
     631
     632var Hash = function(obj) { 
     633  Object.extend(this, obj || {}); 
     634}; 
     635 
     636Object.extend(Hash, { 
     637  toQueryString: function(obj) { 
     638    var parts = []; 
     639 
     640      this.prototype._each.call(obj, function(pair) { 
     641      if (!pair.key) return; 
     642 
     643      if (pair.value && pair.value.constructor == Array) { 
     644        var values = pair.value.compact(); 
     645        if (values.length < 2) pair.value = values.reduce(); 
     646        else { 
     647            key = encodeURIComponent(pair.key); 
     648          values.each(function(value) { 
     649            value = value != undefined ? encodeURIComponent(value) : ''; 
     650            parts.push(key + '=' + encodeURIComponent(value)); 
     651          }); 
     652          return; 
     653        } 
     654      } 
     655      if (pair.value == undefined) pair[1] = ''; 
     656      parts.push(pair.map(encodeURIComponent).join('=')); 
     657      }); 
     658 
     659    return parts.join('&'); 
     660  } 
     661}); 
     662 
     663Object.extend(Hash.prototype, Enumerable); 
     664Object.extend(Hash.prototype, { 
    507665  _each: function(iterator) { 
    508666    for (var key in this) { 
    509667      var value = this[key]; 
    510       if (typeof value == 'function') continue; 
     668      if (value && value == Hash.prototype[key]) continue; 
    511669 
    512670      var pair = [key, value]; 
     
    526684 
    527685  merge: function(hash) { 
    528     return $H(hash).inject($H(this), function(mergedHash, pair) { 
     686    return $H(hash).inject(this, function(mergedHash, pair) { 
    529687      mergedHash[pair.key] = pair.value; 
    530688      return mergedHash; 
     
    532690  }, 
    533691 
     692  remove: function() { 
     693    var result; 
     694    for(var i = 0, length = arguments.length; i < length; i++) { 
     695      var value = this[arguments[i]]; 
     696      if (value !== undefined){ 
     697        if (result === undefined) result = value; 
     698        else { 
     699          if (result.constructor != Array) result = [result]; 
     700          result.push(value) 
     701        } 
     702      } 
     703      delete this[arguments[i]]; 
     704    } 
     705    return result; 
     706  }, 
     707 
    534708  toQueryString: function() { 
    535     return this.map(function(pair) { 
    536       return pair.map(encodeURIComponent).join('='); 
    537     }).join('&'); 
     709    return Hash.toQueryString(this); 
    538710  }, 
    539711 
     
    543715    }).join(', ') + '}>'; 
    544716  } 
    545 } 
     717}); 
    546718 
    547719function $H(object) { 
    548   var hash = Object.extend({}, object || {}); 
    549   Object.extend(hash, Enumerable); 
    550   Object.extend(hash, Hash); 
    551   return hash; 
    552 
     720  if (object && object.constructor == Hash) return object; 
     721  return new Hash(object); 
     722}; 
    553723ObjectRange = Class.create(); 
    554724Object.extend(ObjectRange.prototype, Enumerable); 
     
    562732  _each: function(iterator) { 
    563733    var value = this.start; 
    564     do
     734    while (this.include(value))
    565735      iterator(value); 
    566736      value = value.succ(); 
    567     } while (this.include(value)); 
     737    } 
    568738  }, 
    569739 
     
    600770  }, 
    601771 
    602   register: function(responderToAdd) { 
    603     if (!this.include(responderToAdd)) 
    604       this.responders.push(responderToAdd); 
    605   }, 
    606  
    607   unregister: function(responderToRemove) { 
    608     this.responders = this.responders.without(responderToRemove); 
     772  register: function(responder) { 
     773    if (!this.include(responder)) 
     774      this.responders.push(responder); 
     775  }, 
     776 
     777  unregister: function(responder) { 
     778    this.responders = this.responders.without(responder); 
    609779  }, 
    610780 
    611781  dispatch: function(callback, request, transport, json) { 
    612782    this.each(function(responder) { 
    613       if (responder[callback] && typeof responder[callback] == 'function') { 
     783      if (typeof responder[callback] == 'function') { 
    614784        try { 
    615785          responder[callback].apply(responder, [request, transport, json]); 
     
    626796    Ajax.activeRequestCount++; 
    627797  }, 
    628  
    629798  onComplete: function() { 
    630799    Ajax.activeRequestCount--; 
     
    639808      asynchronous: true, 
    640809      contentType:  'application/x-www-form-urlencoded', 
     810      encoding:     'UTF-8', 
    641811      parameters:   '' 
    642812    } 
    643813    Object.extend(this.options, options || {}); 
    644   }, 
    645  
    646   responseIsSuccess: function() { 
    647     return this.transport.status == undefined 
    648         || this.transport.status == 0 
    649         || (this.transport.status >= 200 && this.transport.status < 300); 
    650   }, 
    651  
    652   responseIsFailure: function() { 
    653     return !this.responseIsSuccess(); 
     814 
     815    this.options.method = this.options.method.toLowerCase(); 
     816    if (typeof this.options.parameters == 'string') 
     817      this.options.parameters = this.options.parameters.toQueryParams(); 
    654818  } 
    655819} 
     
    660824 
    661825Ajax.Request.prototype = Object.extend(new Ajax.Base(), { 
     826  _complete: false, 
     827 
    662828  initialize: function(url, options) { 
    663829    this.transport = Ajax.getTransport(); 
     
    667833 
    668834  request: function(url) { 
    669     var parameters = this.options.parameters || ''; 
    670     if (parameters.length > 0) parameters += '&_='; 
     835    this.url = url; 
     836    this.method = this.options.method; 
     837    var params = this.options.parameters; 
     838 
     839    if (!['get', 'post'].include(this.method)) { 
     840      // simulate other verbs over post 
     841      params['_method'] = this.method; 
     842      this.method = 'post'; 
     843    } 
     844 
     845    params = Hash.toQueryString(params); 
     846    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' 
     847 
     848    // when GET, append parameters to URL 
     849    if (this.method == 'get' && params) 
     850      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; 
    671851 
    672852    try { 
    673       this.url = url; 
    674       if (this.options.method == 'get' && parameters.length > 0) 
    675         this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; 
    676  
    677853      Ajax.Responders.dispatch('onCreate', this, this.transport); 
    678854 
    679       this.transport.open(this.options.method, this.url, 
     855      this.transport.open(this.method.toUpperCase(), this.url, 
    680856        this.options.asynchronous); 
    681857 
    682       if (this.options.asynchronous) { 
    683         this.transport.onreadystatechange = this.onStateChange.bind(this); 
    684         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); 
     858      if (this.options.asynchronous) 
     859        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); 
     860 
     861      this.transport.onreadystatechange = this.onStateChange.bind(this); 
     862      this.setRequestHeaders(); 
     863 
     864      var body = this.method == 'post' ? (this.options.postBody || params) : null; 
     865 
     866      this.transport.send(body); 
     867 
     868      /* Force Firefox to handle ready state 4 for synchronous requests */ 
     869      if (!this.options.asynchronous && this.transport.overrideMimeType) 
     870        this.onStateChange(); 
     871 
     872    } 
     873    catch (e) { 
     874      this.dispatchException(e); 
     875    } 
     876  }, 
     877 
     878  onStateChange: function() { 
     879    var readyState = this.transport.readyState; 
     880    if (readyState > 1 && !((readyState == 4) && this._complete)) 
     881      this.respondToReadyState(this.transport.readyState); 
     882  }, 
     883 
     884  setRequestHeaders: function() { 
     885    var headers = { 
     886      'X-Requested-With': 'XMLHttpRequest', 
     887      'X-Prototype-Version': Prototype.Version, 
     888      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' 
     889    }; 
     890 
     891    if (this.method == 'post') { 
     892      headers['Content-type'] = this.options.contentType + 
     893        (this.options.encoding ? '; charset=' + this.options.encoding : ''); 
     894 
     895      /* Force "Connection: close" for older Mozilla browsers to work 
     896       * around a bug where XMLHttpRequest sends an incorrect 
     897       * Content-length header. See Mozilla Bugzilla #246651. 
     898       */ 
     899      if (this.transport.overrideMimeType && 
     900          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) 
     901            headers['Connection'] = 'close'; 
     902    } 
     903 
     904    // user-defined headers 
     905    if (typeof this.options.requestHeaders == 'object') { 
     906      var extras = this.options.requestHeaders; 
     907 
     908      if (typeof extras.push == 'function') 
     909        for (var i = 0, length = extras.length; i < length; i += 2) 
     910          headers[extras[i]] = extras[i+1]; 
     911      else 
     912        $H(extras).each(function(pair) { headers[pair.key] = pair.value }); 
     913    } 
     914 
     915    for (var name in headers) 
     916      this.transport.setRequestHeader(name, headers[name]); 
     917  }, 
     918 
     919  success: function() { 
     920    return !this.transport.status 
     921        || (this.transport.status >= 200 && this.transport.status < 300); 
     922  }, 
     923 
     924  respondToReadyState: function(readyState) { 
     925    var state = Ajax.Request.Events[readyState]; 
     926    var transport = this.transport, json = this.evalJSON(); 
     927 
     928    if (state == 'Complete') { 
     929      try { 
     930        this._complete = true; 
     931        (this.options['on' + this.transport.status] 
     932         || this.options['on' + (this.success() ? 'Success' : 'Failure')] 
     933         || Prototype.emptyFunction)(transport, json); 
     934      } catch (e) { 
     935        this.dispatchException(e); 
    685936      } 
    686937 
    687       this.setRequestHeaders(); 
    688  
    689       var body = this.options.postBody ? this.options.postBody : parameters; 
    690       this.transport.send(this.options.method == 'post' ? body : null); 
    691  
     938      if ((this.getHeader('Content-type') || 'text/javascript').strip(). 
     939        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) 
     940          this.evalResponse(); 
     941    } 
     942 
     943    try { 
     944      (this.options['on' + state] || Prototype.emptyFunction)(transport, json); 
     945      Ajax.Responders.dispatch('on' + state, this, transport, json); 
    692946    } catch (e) { 
    693947      this.dispatchException(e); 
    694948    } 
    695   }, 
    696  
    697   setRequestHeaders: function() { 
    698     var requestHeaders = 
    699       ['X-Requested-With', 'XMLHttpRequest', 
    700        'X-Prototype-Version', Prototype.Version, 
    701        'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; 
    702  
    703     if (this.options.method == 'post') { 
    704       requestHeaders.push('Content-type', this.options.contentType); 
    705  
    706       /* Force "Connection: close" for Mozilla browsers to work around 
    707        * a bug where XMLHttpReqeuest sends an incorrect Content-length 
    708        * header. See Mozilla Bugzilla #246651. 
    709        */ 
    710       if (this.transport.overrideMimeType) 
    711         requestHeaders.push('Connection', 'close'); 
    712     } 
    713  
    714     if (this.options.requestHeaders) 
    715       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); 
    716  
    717     for (var i = 0; i < requestHeaders.length; i += 2) 
    718       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); 
    719   }, 
    720  
    721   onStateChange: function() { 
    722     var readyState = this.transport.readyState; 
    723     if (readyState != 1) 
    724       this.respondToReadyState(this.transport.readyState); 
    725   }, 
    726  
    727   header: function(name) { 
     949 
     950    if (state == 'Complete') { 
     951      // avoid memory leak in MSIE: clean up 
     952      this.transport.onreadystatechange = Prototype.emptyFunction; 
     953    } 
     954  }, 
     955 
     956  getHeader: function(name) { 
    728957    try { 
    729958      return this.transport.getResponseHeader(name); 
    730     } catch (e) {
     959    } catch (e) { return null
    731960  }, 
    732961 
    733962  evalJSON: function() { 
    734963    try { 
    735       return eval('(' + this.header('X-JSON') + ')'); 
    736     } catch (e) {} 
     964      var json = this.getHeader('X-JSON'); 
     965      return json ? eval('(' + json + ')') : null; 
     966    } catch (e) { return null } 
    737967  }, 
    738968 
     
    745975  }, 
    746976 
    747   respondToReadyState: function(readyState) { 
    748     var event = Ajax.Request.Events[readyState]; 
    749     var transport = this.transport, json = this.evalJSON(); 
    750  
    751     if (event == 'Complete') { 
    752       try { 
    753         (this.options['on' + this.transport.status] 
    754          || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] 
    755          || Prototype.emptyFunction)(transport, json); 
    756       } catch (e) { 
    757         this.dispatchException(e); 
    758       } 
    759  
    760       if ((this.header('Content-type') || '').match(/^text\/javascript/i)) 
    761         this.evalResponse(); 
    762     } 
    763  
    764     try { 
    765       (this.options['on' + event] || Prototype.emptyFunction)(transport, json); 
    766       Ajax.Responders.dispatch('on' + event, this, transport, json); 
    767     } catch (e) { 
    768       this.dispatchException(e); 
    769     } 
    770  
    771     /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ 
    772     if (event == 'Complete') 
    773       this.transport.onreadystatechange = Prototype.emptyFunction; 
    774   }, 
    775  
    776977  dispatchException: function(exception) { 
    777978    (this.options.onException || Prototype.emptyFunction)(this, exception); 
     
    784985Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { 
    785986  initialize: function(container, url, options) { 
    786     this.containers = { 
    787       success: container.success ? $(container.success) : $(container), 
    788       failure: container.failure ? $(container.failure) : 
    789         (container.success ? null : $(container)) 
     987    this.container = { 
     988      success: (container.success || container), 
     989      failure: (container.failure || (container.success ? null : container)) 
    790990    } 
    791991 
     
    794994 
    795995    var onComplete = this.options.onComplete || Prototype.emptyFunction; 
    796     this.options.onComplete = (function(transport, object) { 
     996    this.options.onComplete = (function(transport, param) { 
    797997      this.updateContent(); 
    798       onComplete(transport, object); 
     998      onComplete(transport, param); 
    799999    }).bind(this); 
    8001000 
     
    8031003 
    8041004  updateContent: function() { 
    805     var receiver = this.responseIsSuccess() ? 
    806       this.containers.success : this.containers.failure; 
     1005    var receiver = this.container[this.success() ? 'success' : 'failure']; 
    8071006    var response = this.transport.responseText; 
    8081007 
    809     if (!this.options.evalScripts) 
    810       response = response.stripScripts(); 
    811  
    812     if (receiver) { 
    813       if (this.options.insertion) { 
     1008    if (!this.options.evalScripts) response = response.stripScripts(); 
     1009 
     1010    if (receiver = $(receiver)) { 
     1011      if (this.options.insertion) 
    8141012        new this.options.insertion(receiver, response); 
    815       } else { 
    816         Element.update(receiver, response); 
    817       } 
    818     } 
    819  
    820     if (this.responseIsSuccess()) { 
     1013      else 
     1014        receiver.update(response); 
     1015    } 
     1016 
     1017    if (this.success()) { 
    8211018      if (this.onComplete) 
    8221019        setTimeout(this.onComplete.bind(this), 10); 
     
    8471044 
    8481045  stop: function() { 
    849     this.updater.onComplete = undefined; 
     1046    this.updater.options.onComplete = undefined; 
    8501047    clearTimeout(this.timer); 
    8511048    (this.onComplete || Prototype.emptyFunction).apply(this, arguments); 
     
    8671064  } 
    8681065}); 
    869 function $() { 
    870   var results = [], element; 
    871   for (var i = 0; i < arguments.length; i++) { 
    872     element = arguments[i]; 
    873     if (typeof element == 'string') 
    874       element = document.getElementById(element); 
    875     results.push(Element.extend(element)); 
    876   } 
    877   return results.length < 2 ? results[0] : results; 
     1066function $(element) { 
     1067  if (arguments.length > 1) { 
     1068    for (var i = 0, elements = [], length = arguments.length; i < length; i++) 
     1069      elements.push($(arguments[i])); 
     1070    return elements; 
     1071  } 
     1072  if (typeof element == 'string') 
     1073    element = document.getElementById(element); 
     1074  return Element.extend(element); 
     1075
     1076 
     1077if (Prototype.BrowserFeatures.XPath) { 
     1078  document._getElementsByXPath = function(expression, parentElement) { 
     1079    var results = []; 
     1080    var query = document.evaluate(expression, $(parentElement) || document, 
     1081      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 
     1082    for (var i = 0, length = query.snapshotLength; i < length; i++) 
     1083      results.push(query.snapshotItem(i)); 
     1084    return results; 
     1085  }; 
    8781086} 
    8791087 
    8801088document.getElementsByClassName = function(className, parentElement) { 
    881   var children = ($(parentElement) || document.body).getElementsByTagName('*'); 
    882   return $A(children).inject([], function(elements, child) { 
    883     if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 
    884       elements.push(Element.extend(child)); 
     1089  if (Prototype.BrowserFeatures.XPath) { 
     1090    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; 
     1091    return document._getElementsByXPath(q, parentElement); 
     1092  } else { 
     1093    var children = ($(parentElement) || document.body).getElementsByTagName('*'); 
     1094    var elements = [], child; 
     1095    for (var i = 0, length = children.length; i < length; i++) { 
     1096      child = children[i]; 
     1097      if (Element.hasClassName(child, className)) 
     1098        elements.push(Element.extend(child)); 
     1099    } 
    8851100    return elements; 
    886   }); 
    887 } 
     1101  } 
     1102}; 
    8881103 
    8891104/*--------------------------------------------------------------------------*/ 
     
    8931108 
    8941109Element.extend = function(element) { 
    895   if (!element) return; 
    896   if (_nativeExtensions) return element; 
     1110  if (!element || _nativeExtensions || element.nodeType == 3) return element; 
    8971111 
    8981112  if (!element._extended && element.tagName && element != window) { 
    899     var methods = Element.Methods, cache = Element.extend.cache; 
    900     for (property in methods) { 
     1113    var methods = Object.clone(Element.Methods), cache = Element.extend.cache; 
     1114 
     1115    if (element.tagName == 'FORM') 
     1116      Object.extend(methods, Form.Methods); 
     1117    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) 
     1118      Object.extend(methods, Form.Element.Methods); 
     1119 
     1120    Object.extend(methods, Element.Methods.Simulated); 
     1121 
     1122    for (var property in methods) { 
    9011123      var value = methods[property]; 
    902       if (typeof value == 'function'
     1124      if (typeof value == 'function' && !(property in element)
    9031125        element[property] = cache.findOrStore(value); 
    9041126    } 
     
    9071129  element._extended = true; 
    9081130  return element; 
    909 } 
     1131}; 
    9101132 
    9111133Element.extend.cache = { 
     
    9151137    } 
    9161138  } 
    917 } 
     1139}; 
    9181140 
    9191141Element.Methods = { 
     
    9221144  }, 
    9231145 
    924   toggle: function() { 
    925     for (var i = 0; i < arguments.length; i++) { 
    926       var element = $(arguments[i]); 
    927       Element[Element.visible(element) ? 'hide' : 'show'](element); 
    928     } 
    929   }, 
    930  
    931   hide: function() { 
    932     for (var i = 0; i < arguments.length; i++) { 
    933       var element = $(arguments[i]); 
    934       element.style.display = 'none'; 
    935     } 
    936   }, 
    937  
    938   show: function() { 
    939     for (var i = 0; i < arguments.length; i++) { 
    940       var element = $(arguments[i]); 
    941       element.style.display = ''; 
    942     } 
     1146  toggle: function(element) { 
     1147    element = $(element); 
     1148    Element[Element.visible(element) ? 'hide' : 'show'](element); 
     1149    return element; 
     1150  }, 
     1151 
     1152  hide: function(element) { 
     1153    $(element).style.display = 'none'; 
     1154    return element; 
     1155  }, 
     1156 
     1157  show: function(element) { 
     1158    $(element).style.display = ''; 
     1159    return element; 
    9431160  }, 
    9441161 
     
    9461163    element = $(element); 
    9471164    element.parentNode.removeChild(element); 
     1165    return element; 
    9481166  }, 
    9491167 
    9501168  update: function(element, html) { 
     1169    html = typeof html == 'undefined' ? '' : html.toString(); 
    9511170    $(element).innerHTML = html.stripScripts(); 
    9521171    setTimeout(function() {html.evalScripts()}, 10); 
     1172    return element; 
    9531173  }, 
    9541174 
    9551175  replace: function(element, html) { 
    9561176    element = $(element); 
     1177    html = typeof html == 'undefined' ? '' : html.toString(); 
    9571178    if (element.outerHTML) { 
    9581179      element.outerHTML = html.stripScripts(); 
     
    9641185    } 
    9651186    setTimeout(function() {html.evalScripts()}, 10); 
     1187    return element; 
     1188  }, 
     1189 
     1190  inspect: function(element) { 
     1191    element = $(element); 
     1192    var result = '<' + element.tagName.toLowerCase(); 
     1193    $H({'id': 'id', 'className': 'class'}).each(function(pair) { 
     1194      var property = pair.first(), attribute = pair.last(); 
     1195      var value = (element[property] || '').toString(); 
     1196      if (value) result += ' ' + attribute + '=' + value.inspect(true); 
     1197    }); 
     1198    return result + '>'; 
     1199  }, 
     1200 
     1201  recursivelyCollect: function(element, property) { 
     1202    element = $(element); 
     1203    var elements = []; 
     1204    while (element = element[property]) 
     1205      if (element.nodeType == 1) 
     1206        elements.push(Element.extend(element)); 
     1207    return elements; 
     1208  }, 
     1209 
     1210  ancestors: function(element) { 
     1211    return $(element).recursivelyCollect('parentNode'); 
     1212  }, 
     1213 
     1214  descendants: function(element) { 
     1215    return $A($(element).getElementsByTagName('*')); 
     1216  }, 
     1217 
     1218  immediateDescendants: function(element) { 
     1219    if (!(element = $(element).firstChild)) return []; 
     1220    while (element && element.nodeType != 1) element = element.nextSibling; 
     1221    if (element) return [element].concat($(element).nextSiblings()); 
     1222    return []; 
     1223  }, 
     1224