PageRenderTime 129ms CodeModel.GetById 20ms app.highlight 94ms RepoModel.GetById 1ms app.codeStats 1ms

/hudson-war/src/main/webapp/scripts/prototype.js

http://github.com/hudson/hudson
JavaScript | 2281 lines | 1912 code | 323 blank | 46 comment | 427 complexity | 10e9fac7f2dc36362ea8f98bf8401c0a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*  Prototype JavaScript framework, version 1.5.1.1
   2 *  (c) 2005-2007 Sam Stephenson
   3 *
   4 *  Prototype is freely distributable under the terms of an MIT-style license.
   5 *  For details, see the Prototype web site: http://www.prototypejs.org/
   6 *
   7/*--------------------------------------------------------------------------*/
   8
   9var Prototype = {
  10  Version: '1.5.1.1',
  11
  12  Browser: {
  13    IE:     !!(window.attachEvent && !window.opera),
  14    Opera:  !!window.opera,
  15    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
  16    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
  17  },
  18
  19  BrowserFeatures: {
  20    XPath: !!document.evaluate,
  21    ElementExtensions: !!window.HTMLElement,
  22    SpecificElementExtensions:
  23      (document.createElement('div').__proto__ !==
  24       document.createElement('form').__proto__)
  25  },
  26
  27  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
  28  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
  29
  30  emptyFunction: function() { },
  31  K: function(x) { return x }
  32}
  33
  34var Class = {
  35  create: function() {
  36    return function() {
  37      this.initialize.apply(this, arguments);
  38    }
  39  }
  40}
  41
  42var Abstract = new Object();
  43
  44Object.extend = function(destination, source) {
  45  for (var property in source) {
  46    destination[property] = source[property];
  47  }
  48  return destination;
  49}
  50
  51Object.extend(Object, {
  52  inspect: function(object) {
  53    try {
  54      if (object === undefined) return 'undefined';
  55      if (object === null) return 'null';
  56      return object.inspect ? object.inspect() : object.toString();
  57    } catch (e) {
  58      if (e instanceof RangeError) return '...';
  59      throw e;
  60    }
  61  },
  62
  63  toJSON: function(object) {
  64    var type = typeof object;
  65    switch(type) {
  66      case 'undefined':
  67      case 'function':
  68      case 'unknown': return;
  69      case 'boolean': return object.toString();
  70    }
  71    if (object === null) return 'null';
  72    // "|| object.toJSON" below is workaround for Opera 10.52/53 bug, see HUDSON-6424
  73    if (object.toJSON || object.toJSON) return object.toJSON();
  74    if (object.ownerDocument === document) return;
  75    var results = [];
  76    for (var property in object) {
  77      var value = Object.toJSON(object[property]);
  78      if (value !== undefined)
  79        results.push(property.toJSON() + ': ' + value);
  80    }
  81    return '{' + results.join(', ') + '}';
  82  },
  83
  84  keys: function(object) {
  85    var keys = [];
  86    for (var property in object)
  87      keys.push(property);
  88    return keys;
  89  },
  90
  91  values: function(object) {
  92    var values = [];
  93    for (var property in object)
  94      values.push(object[property]);
  95    return values;
  96  },
  97
  98  clone: function(object) {
  99    return Object.extend({}, object);
 100  }
 101});
 102
 103Function.prototype.bind = function() {
 104  var __method = this, args = $A(arguments), object = args.shift();
 105  return function() {
 106    return __method.apply(object, args.concat($A(arguments)));
 107  }
 108}
 109
 110Function.prototype.bindAsEventListener = function(object) {
 111  var __method = this, args = $A(arguments), object = args.shift();
 112  return function(event) {
 113    return __method.apply(object, [event || window.event].concat(args));
 114  }
 115}
 116
 117Object.extend(Number.prototype, {
 118  toColorPart: function() {
 119    return this.toPaddedString(2, 16);
 120  },
 121
 122  succ: function() {
 123    return this + 1;
 124  },
 125
 126  times: function(iterator) {
 127    $R(0, this, true).each(iterator);
 128    return this;
 129  },
 130
 131  toPaddedString: function(length, radix) {
 132    var string = this.toString(radix || 10);
 133    return '0'.times(length - string.length) + string;
 134  },
 135
 136  toJSON: function() {
 137    return isFinite(this) ? this.toString() : 'null';
 138  }
 139});
 140
 141Date.prototype.toJSON = function() {
 142  return '"' + this.getFullYear() + '-' +
 143    (this.getMonth() + 1).toPaddedString(2) + '-' +
 144    this.getDate().toPaddedString(2) + 'T' +
 145    this.getHours().toPaddedString(2) + ':' +
 146    this.getMinutes().toPaddedString(2) + ':' +
 147    this.getSeconds().toPaddedString(2) + '"';
 148};
 149
 150var Try = {
 151  these: function() {
 152    var returnValue;
 153
 154    for (var i = 0, length = arguments.length; i < length; i++) {
 155      var lambda = arguments[i];
 156      try {
 157        returnValue = lambda();
 158        break;
 159      } catch (e) {}
 160    }
 161
 162    return returnValue;
 163  }
 164}
 165
 166/*--------------------------------------------------------------------------*/
 167
 168var PeriodicalExecuter = Class.create();
 169PeriodicalExecuter.prototype = {
 170  initialize: function(callback, frequency) {
 171    this.callback = callback;
 172    this.frequency = frequency;
 173    this.currentlyExecuting = false;
 174
 175    this.registerCallback();
 176  },
 177
 178  registerCallback: function() {
 179    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
 180  },
 181
 182  stop: function() {
 183    if (!this.timer) return;
 184    clearInterval(this.timer);
 185    this.timer = null;
 186  },
 187
 188  onTimerEvent: function() {
 189    if (!this.currentlyExecuting) {
 190      try {
 191        this.currentlyExecuting = true;
 192        this.callback(this);
 193      } finally {
 194        this.currentlyExecuting = false;
 195      }
 196    }
 197  }
 198}
 199Object.extend(String, {
 200  interpret: function(value) {
 201    return value == null ? '' : String(value);
 202  },
 203  specialChar: {
 204    '\b': '\\b',
 205    '\t': '\\t',
 206    '\n': '\\n',
 207    '\f': '\\f',
 208    '\r': '\\r',
 209    '\\': '\\\\'
 210  }
 211});
 212
 213Object.extend(String.prototype, {
 214  gsub: function(pattern, replacement) {
 215    var result = '', source = this, match;
 216    replacement = arguments.callee.prepareReplacement(replacement);
 217
 218    while (source.length > 0) {
 219      if (match = source.match(pattern)) {
 220        result += source.slice(0, match.index);
 221        result += String.interpret(replacement(match));
 222        source  = source.slice(match.index + match[0].length);
 223      } else {
 224        result += source, source = '';
 225      }
 226    }
 227    return result;
 228  },
 229
 230  sub: function(pattern, replacement, count) {
 231    replacement = this.gsub.prepareReplacement(replacement);
 232    count = count === undefined ? 1 : count;
 233
 234    return this.gsub(pattern, function(match) {
 235      if (--count < 0) return match[0];
 236      return replacement(match);
 237    });
 238  },
 239
 240  scan: function(pattern, iterator) {
 241    this.gsub(pattern, iterator);
 242    return this;
 243  },
 244
 245  truncate: function(length, truncation) {
 246    length = length || 30;
 247    truncation = truncation === undefined ? '...' : truncation;
 248    return this.length > length ?
 249      this.slice(0, length - truncation.length) + truncation : this;
 250  },
 251
 252  strip: function() {
 253    return this.replace(/^\s+/, '').replace(/\s+$/, '');
 254  },
 255
 256  stripTags: function() {
 257    return this.replace(/<\/?[^>]+>/gi, '');
 258  },
 259
 260  stripScripts: function() {
 261    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
 262  },
 263
 264  extractScripts: function() {
 265    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
 266    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
 267    return (this.match(matchAll) || []).map(function(scriptTag) {
 268      return (scriptTag.match(matchOne) || ['', ''])[1];
 269    });
 270  },
 271
 272  evalScripts: function() {
 273    return this.extractScripts().map(function(script) { return eval(script) });
 274  },
 275
 276  escapeHTML: function() {
 277    var self = arguments.callee;
 278    self.text.data = this;
 279    return self.div.innerHTML;
 280  },
 281
 282  unescapeHTML: function() {
 283    var div = document.createElement('div');
 284    div.innerHTML = this.stripTags();
 285    return div.childNodes[0] ? (div.childNodes.length > 1 ?
 286      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
 287      div.childNodes[0].nodeValue) : '';
 288  },
 289
 290  toQueryParams: function(separator) {
 291    var match = this.strip().match(/([^?#]*)(#.*)?$/);
 292    if (!match) return {};
 293
 294    return match[1].split(separator || '&').inject({}, function(hash, pair) {
 295      if ((pair = pair.split('='))[0]) {
 296        var key = decodeURIComponent(pair.shift());
 297        var value = pair.length > 1 ? pair.join('=') : pair[0];
 298        if (value != undefined) value = decodeURIComponent(value);
 299
 300        if (key in hash) {
 301          if (hash[key].constructor != Array) hash[key] = [hash[key]];
 302          hash[key].push(value);
 303        }
 304        else hash[key] = value;
 305      }
 306      return hash;
 307    });
 308  },
 309
 310  toArray: function() {
 311    return this.split('');
 312  },
 313
 314  succ: function() {
 315    return this.slice(0, this.length - 1) +
 316      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
 317  },
 318
 319  times: function(count) {
 320    var result = '';
 321    for (var i = 0; i < count; i++) result += this;
 322    return result;
 323  },
 324
 325  camelize: function() {
 326    var parts = this.split('-'), len = parts.length;
 327    if (len == 1) return parts[0];
 328
 329    var camelized = this.charAt(0) == '-'
 330      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
 331      : parts[0];
 332
 333    for (var i = 1; i < len; i++)
 334      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
 335
 336    return camelized;
 337  },
 338
 339  capitalize: function() {
 340    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
 341  },
 342
 343  underscore: function() {
 344    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
 345  },
 346
 347  dasherize: function() {
 348    return this.gsub(/_/,'-');
 349  },
 350
 351  inspect: function(useDoubleQuotes) {
 352    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
 353      var character = String.specialChar[match[0]];
 354      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
 355    });
 356    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
 357    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
 358  },
 359
 360  toJSON: function() {
 361    return this.inspect(true);
 362  },
 363
 364  unfilterJSON: function(filter) {
 365    return this.sub(filter || Prototype.JSONFilter, '#{1}');
 366  },
 367
 368  isJSON: function() {
 369    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
 370    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
 371  },
 372
 373  evalJSON: function(sanitize) {
 374    var json = this.unfilterJSON();
 375    try {
 376      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
 377    } catch (e) { }
 378    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
 379  },
 380
 381  include: function(pattern) {
 382    return this.indexOf(pattern) > -1;
 383  },
 384
 385  startsWith: function(pattern) {
 386    return this.indexOf(pattern) === 0;
 387  },
 388
 389  endsWith: function(pattern) {
 390    var d = this.length - pattern.length;
 391    return d >= 0 && this.lastIndexOf(pattern) === d;
 392  },
 393
 394  empty: function() {
 395    return this == '';
 396  },
 397
 398  blank: function() {
 399    return /^\s*$/.test(this);
 400  }
 401});
 402
 403if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
 404  escapeHTML: function() {
 405    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
 406  },
 407  unescapeHTML: function() {
 408    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
 409  }
 410});
 411
 412String.prototype.gsub.prepareReplacement = function(replacement) {
 413  if (typeof replacement == 'function') return replacement;
 414  var template = new Template(replacement);
 415  return function(match) { return template.evaluate(match) };
 416}
 417
 418String.prototype.parseQuery = String.prototype.toQueryParams;
 419
 420Object.extend(String.prototype.escapeHTML, {
 421  div:  document.createElement('div'),
 422  text: document.createTextNode('')
 423});
 424
 425with (String.prototype.escapeHTML) div.appendChild(text);
 426
 427var Template = Class.create();
 428Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
 429Template.prototype = {
 430  initialize: function(template, pattern) {
 431    this.template = template.toString();
 432    this.pattern  = pattern || Template.Pattern;
 433  },
 434
 435  evaluate: function(object) {
 436    return this.template.gsub(this.pattern, function(match) {
 437      var before = match[1];
 438      if (before == '\\') return match[2];
 439      return before + String.interpret(object[match[3]]);
 440    });
 441  }
 442}
 443
 444var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
 445
 446var Enumerable = {
 447  each: function(iterator) {
 448    var index = 0;
 449    try {
 450      this._each(function(value) {
 451        iterator(value, index++);
 452      });
 453    } catch (e) {
 454      if (e != $break) throw e;
 455    }
 456    return this;
 457  },
 458
 459  eachSlice: function(number, iterator) {
 460    var index = -number, slices = [], array = this.toArray();
 461    while ((index += number) < array.length)
 462      slices.push(array.slice(index, index+number));
 463    return slices.map(iterator);
 464  },
 465
 466  all: function(iterator) {
 467    var result = true;
 468    this.each(function(value, index) {
 469      result = result && !!(iterator || Prototype.K)(value, index);
 470      if (!result) throw $break;
 471    });
 472    return result;
 473  },
 474
 475  any: function(iterator) {
 476    var result = false;
 477    this.each(function(value, index) {
 478      if (result = !!(iterator || Prototype.K)(value, index))
 479        throw $break;
 480    });
 481    return result;
 482  },
 483
 484  collect: function(iterator) {
 485    var results = [];
 486    this.each(function(value, index) {
 487      results.push((iterator || Prototype.K)(value, index));
 488    });
 489    return results;
 490  },
 491
 492  detect: function(iterator) {
 493    var result;
 494    this.each(function(value, index) {
 495      if (iterator(value, index)) {
 496        result = value;
 497        throw $break;
 498      }
 499    });
 500    return result;
 501  },
 502
 503  findAll: function(iterator) {
 504    var results = [];
 505    this.each(function(value, index) {
 506      if (iterator(value, index))
 507        results.push(value);
 508    });
 509    return results;
 510  },
 511
 512  grep: function(pattern, iterator) {
 513    var results = [];
 514    this.each(function(value, index) {
 515      var stringValue = value.toString();
 516      if (stringValue.match(pattern))
 517        results.push((iterator || Prototype.K)(value, index));
 518    })
 519    return results;
 520  },
 521
 522  include: function(object) {
 523    var found = false;
 524    this.each(function(value) {
 525      if (value == object) {
 526        found = true;
 527        throw $break;
 528      }
 529    });
 530    return found;
 531  },
 532
 533  inGroupsOf: function(number, fillWith) {
 534    fillWith = fillWith === undefined ? null : fillWith;
 535    return this.eachSlice(number, function(slice) {
 536      while(slice.length < number) slice.push(fillWith);
 537      return slice;
 538    });
 539  },
 540
 541  inject: function(memo, iterator) {
 542    this.each(function(value, index) {
 543      memo = iterator(memo, value, index);
 544    });
 545    return memo;
 546  },
 547
 548  invoke: function(method) {
 549    var args = $A(arguments).slice(1);
 550    return this.map(function(value) {
 551      return value[method].apply(value, args);
 552    });
 553  },
 554
 555  max: function(iterator) {
 556    var result;
 557    this.each(function(value, index) {
 558      value = (iterator || Prototype.K)(value, index);
 559      if (result == undefined || value >= result)
 560        result = value;
 561    });
 562    return result;
 563  },
 564
 565  min: function(iterator) {
 566    var result;
 567    this.each(function(value, index) {
 568      value = (iterator || Prototype.K)(value, index);
 569      if (result == undefined || value < result)
 570        result = value;
 571    });
 572    return result;
 573  },
 574
 575  partition: function(iterator) {
 576    var trues = [], falses = [];
 577    this.each(function(value, index) {
 578      ((iterator || Prototype.K)(value, index) ?
 579        trues : falses).push(value);
 580    });
 581    return [trues, falses];
 582  },
 583
 584  pluck: function(property) {
 585    var results = [];
 586    this.each(function(value, index) {
 587      results.push(value[property]);
 588    });
 589    return results;
 590  },
 591
 592  reject: function(iterator) {
 593    var results = [];
 594    this.each(function(value, index) {
 595      if (!iterator(value, index))
 596        results.push(value);
 597    });
 598    return results;
 599  },
 600
 601  sortBy: function(iterator) {
 602    return this.map(function(value, index) {
 603      return {value: value, criteria: iterator(value, index)};
 604    }).sort(function(left, right) {
 605      var a = left.criteria, b = right.criteria;
 606      return a < b ? -1 : a > b ? 1 : 0;
 607    }).pluck('value');
 608  },
 609
 610  toArray: function() {
 611    return this.map();
 612  },
 613
 614  zip: function() {
 615    var iterator = Prototype.K, args = $A(arguments);
 616    if (typeof args.last() == 'function')
 617      iterator = args.pop();
 618
 619    var collections = [this].concat(args).map($A);
 620    return this.map(function(value, index) {
 621      return iterator(collections.pluck(index));
 622    });
 623  },
 624
 625  size: function() {
 626    return this.toArray().length;
 627  },
 628
 629  inspect: function() {
 630    return '#<Enumerable:' + this.toArray().inspect() + '>';
 631  }
 632}
 633
 634Object.extend(Enumerable, {
 635  map:     Enumerable.collect,
 636  find:    Enumerable.detect,
 637  select:  Enumerable.findAll,
 638  member:  Enumerable.include,
 639  entries: Enumerable.toArray
 640});
 641var $A = Array.from = function(iterable) {
 642  if (!iterable) return [];
 643  if (iterable.toArray) {
 644    return iterable.toArray();
 645  } else {
 646    var results = [];
 647    for (var i = 0, length = iterable.length; i < length; i++)
 648      results.push(iterable[i]);
 649    return results;
 650  }
 651}
 652
 653if (Prototype.Browser.WebKit) {
 654  $A = Array.from = function(iterable) {
 655    if (!iterable) return [];
 656    if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
 657      iterable.toArray) {
 658      return iterable.toArray();
 659    } else {
 660      var results = [];
 661      for (var i = 0, length = iterable.length; i < length; i++)
 662        results.push(iterable[i]);
 663      return results;
 664    }
 665  }
 666}
 667
 668Object.extend(Array.prototype, Enumerable);
 669
 670if (!Array.prototype._reverse)
 671  Array.prototype._reverse = Array.prototype.reverse;
 672
 673Object.extend(Array.prototype, {
 674  _each: function(iterator) {
 675    for (var i = 0, length = this.length; i < length; i++)
 676      iterator(this[i]);
 677  },
 678
 679  clear: function() {
 680    this.length = 0;
 681    return this;
 682  },
 683
 684  first: function() {
 685    return this[0];
 686  },
 687
 688  last: function() {
 689    return this[this.length - 1];
 690  },
 691
 692  compact: function() {
 693    return this.select(function(value) {
 694      return value != null;
 695    });
 696  },
 697
 698  flatten: function() {
 699    return this.inject([], function(array, value) {
 700      return array.concat(value && value.constructor == Array ?
 701        value.flatten() : [value]);
 702    });
 703  },
 704
 705  without: function() {
 706    var values = $A(arguments);
 707    return this.select(function(value) {
 708      return !values.include(value);
 709    });
 710  },
 711
 712  indexOf: function(object) {
 713    for (var i = 0, length = this.length; i < length; i++)
 714      if (this[i] == object) return i;
 715    return -1;
 716  },
 717
 718  reverse: function(inline) {
 719    return (inline !== false ? this : this.toArray())._reverse();
 720  },
 721
 722  reduce: function() {
 723    return this.length > 1 ? this : this[0];
 724  },
 725
 726  uniq: function(sorted) {
 727    return this.inject([], function(array, value, index) {
 728      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
 729        array.push(value);
 730      return array;
 731    });
 732  },
 733
 734  clone: function() {
 735    return [].concat(this);
 736  },
 737
 738  size: function() {
 739    return this.length;
 740  },
 741
 742  inspect: function() {
 743    return '[' + this.map(Object.inspect).join(', ') + ']';
 744  },
 745
 746  toJSON: function() {
 747    var results = [];
 748    this.each(function(object) {
 749      var value = Object.toJSON(object);
 750      if (value !== undefined) results.push(value);
 751    });
 752    return '[' + results.join(', ') + ']';
 753  }
 754});
 755
 756Array.prototype.toArray = Array.prototype.clone;
 757
 758function $w(string) {
 759  string = string.strip();
 760  return string ? string.split(/\s+/) : [];
 761}
 762
 763if (Prototype.Browser.Opera){
 764  Array.prototype.concat = function() {
 765    var array = [];
 766    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
 767    for (var i = 0, length = arguments.length; i < length; i++) {
 768      if (arguments[i].constructor == Array) {
 769        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
 770          array.push(arguments[i][j]);
 771      } else {
 772        array.push(arguments[i]);
 773      }
 774    }
 775    return array;
 776  }
 777}
 778var Hash = function(object) {
 779  if (object instanceof Hash) this.merge(object);
 780  else Object.extend(this, object || {});
 781};
 782
 783Object.extend(Hash, {
 784  toQueryString: function(obj) {
 785    var parts = [];
 786    parts.add = arguments.callee.addPair;
 787
 788    this.prototype._each.call(obj, function(pair) {
 789      if (!pair.key) return;
 790      var value = pair.value;
 791
 792      if (value && typeof value == 'object') {
 793        if (value.constructor == Array) value.each(function(value) {
 794          parts.add(pair.key, value);
 795        });
 796        return;
 797      }
 798      parts.add(pair.key, value);
 799    });
 800
 801    return parts.join('&');
 802  },
 803
 804  toJSON: function(object) {
 805    var results = [];
 806    this.prototype._each.call(object, function(pair) {
 807      var value = Object.toJSON(pair.value);
 808      if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
 809    });
 810    return '{' + results.join(', ') + '}';
 811  }
 812});
 813
 814Hash.toQueryString.addPair = function(key, value, prefix) {
 815  key = encodeURIComponent(key);
 816  if (value === undefined) this.push(key);
 817  else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
 818}
 819
 820Object.extend(Hash.prototype, Enumerable);
 821Object.extend(Hash.prototype, {
 822  _each: function(iterator) {
 823    for (var key in this) {
 824      var value = this[key];
 825      if (value && value == Hash.prototype[key]) continue;
 826
 827      var pair = [key, value];
 828      pair.key = key;
 829      pair.value = value;
 830      iterator(pair);
 831    }
 832  },
 833
 834  keys: function() {
 835    return this.pluck('key');
 836  },
 837
 838  values: function() {
 839    return this.pluck('value');
 840  },
 841
 842  merge: function(hash) {
 843    return $H(hash).inject(this, function(mergedHash, pair) {
 844      mergedHash[pair.key] = pair.value;
 845      return mergedHash;
 846    });
 847  },
 848
 849  remove: function() {
 850    var result;
 851    for(var i = 0, length = arguments.length; i < length; i++) {
 852      var value = this[arguments[i]];
 853      if (value !== undefined){
 854        if (result === undefined) result = value;
 855        else {
 856          if (result.constructor != Array) result = [result];
 857          result.push(value)
 858        }
 859      }
 860      delete this[arguments[i]];
 861    }
 862    return result;
 863  },
 864
 865  toQueryString: function() {
 866    return Hash.toQueryString(this);
 867  },
 868
 869  inspect: function() {
 870    return '#<Hash:{' + this.map(function(pair) {
 871      return pair.map(Object.inspect).join(': ');
 872    }).join(', ') + '}>';
 873  },
 874
 875  toJSON: function() {
 876    return Hash.toJSON(this);
 877  }
 878});
 879
 880function $H(object) {
 881  if (object instanceof Hash) return object;
 882  return new Hash(object);
 883};
 884
 885// Safari iterates over shadowed properties
 886if (function() {
 887  var i = 0, Test = function(value) { this.key = value };
 888  Test.prototype.key = 'foo';
 889  for (var property in new Test('bar')) i++;
 890  return i > 1;
 891}()) Hash.prototype._each = function(iterator) {
 892  var cache = [];
 893  for (var key in this) {
 894    var value = this[key];
 895    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
 896    cache.push(key);
 897    var pair = [key, value];
 898    pair.key = key;
 899    pair.value = value;
 900    iterator(pair);
 901  }
 902};
 903ObjectRange = Class.create();
 904Object.extend(ObjectRange.prototype, Enumerable);
 905Object.extend(ObjectRange.prototype, {
 906  initialize: function(start, end, exclusive) {
 907    this.start = start;
 908    this.end = end;
 909    this.exclusive = exclusive;
 910  },
 911
 912  _each: function(iterator) {
 913    var value = this.start;
 914    while (this.include(value)) {
 915      iterator(value);
 916      value = value.succ();
 917    }
 918  },
 919
 920  include: function(value) {
 921    if (value < this.start)
 922      return false;
 923    if (this.exclusive)
 924      return value < this.end;
 925    return value <= this.end;
 926  }
 927});
 928
 929var $R = function(start, end, exclusive) {
 930  return new ObjectRange(start, end, exclusive);
 931}
 932
 933var Ajax = {
 934  getTransport: function() {
 935    return Try.these(
 936      function() {return new XMLHttpRequest()},
 937      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
 938      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
 939    ) || false;
 940  },
 941
 942  activeRequestCount: 0
 943}
 944
 945Ajax.Responders = {
 946  responders: [],
 947
 948  _each: function(iterator) {
 949    this.responders._each(iterator);
 950  },
 951
 952  register: function(responder) {
 953    if (!this.include(responder))
 954      this.responders.push(responder);
 955  },
 956
 957  unregister: function(responder) {
 958    this.responders = this.responders.without(responder);
 959  },
 960
 961  dispatch: function(callback, request, transport, json) {
 962    this.each(function(responder) {
 963      if (typeof responder[callback] == 'function') {
 964        try {
 965          responder[callback].apply(responder, [request, transport, json]);
 966        } catch (e) {}
 967      }
 968    });
 969  }
 970};
 971
 972Object.extend(Ajax.Responders, Enumerable);
 973
 974Ajax.Responders.register({
 975  onCreate: function() {
 976    Ajax.activeRequestCount++;
 977  },
 978  onComplete: function() {
 979    Ajax.activeRequestCount--;
 980  }
 981});
 982
 983Ajax.Base = function() {};
 984Ajax.Base.prototype = {
 985  setOptions: function(options) {
 986    this.options = {
 987      method:       'post',
 988      asynchronous: true,
 989      contentType:  'application/x-www-form-urlencoded',
 990      encoding:     'UTF-8',
 991      parameters:   ''
 992    }
 993    Object.extend(this.options, options || {});
 994
 995    this.options.method = this.options.method.toLowerCase();
 996    if (typeof this.options.parameters == 'string')
 997      this.options.parameters = this.options.parameters.toQueryParams();
 998
 999    // KK patch -- handle crumb for POST automatically by adding a header
1000    if(this.options.method=="post") {
1001        if(this.options.requestHeaders==undefined)
1002            this.options.requestHeaders = {};
1003        crumb.wrap(this.options.requestHeaders);
1004    }
1005    // KK patch until here
1006  }
1007}
1008
1009Ajax.Request = Class.create();
1010Ajax.Request.Events =
1011  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1012
1013Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
1014  _complete: false,
1015
1016  initialize: function(url, options) {
1017    this.transport = Ajax.getTransport();
1018    this.setOptions(options);
1019    this.request(url);
1020  },
1021
1022  request: function(url) {
1023    this.url = url;
1024    this.method = this.options.method;
1025    var params = Object.clone(this.options.parameters);
1026
1027    if (!['get', 'post'].include(this.method)) {
1028      // simulate other verbs over post
1029      params['_method'] = this.method;
1030      this.method = 'post';
1031    }
1032
1033    this.parameters = params;
1034
1035    if (params = Hash.toQueryString(params)) {
1036      // when GET, append parameters to URL
1037      if (this.method == 'get')
1038        this.url += (this.url.include('?') ? '&' : '?') + params;
1039      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1040        params += '&_=';
1041    }
1042
1043    try {
1044      if (this.options.onCreate) this.options.onCreate(this.transport);
1045      Ajax.Responders.dispatch('onCreate', this, this.transport);
1046
1047      this.transport.open(this.method.toUpperCase(), this.url,
1048        this.options.asynchronous);
1049
1050      if (this.options.asynchronous)
1051        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
1052
1053      this.transport.onreadystatechange = this.onStateChange.bind(this);
1054      this.setRequestHeaders();
1055
1056      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1057      this.transport.send(this.body);
1058
1059      /* Force Firefox to handle ready state 4 for synchronous requests */
1060      if (!this.options.asynchronous && this.transport.overrideMimeType)
1061        this.onStateChange();
1062
1063    }
1064    catch (e) {
1065      this.dispatchException(e);
1066    }
1067  },
1068
1069  onStateChange: function() {
1070    var readyState = this.transport.readyState;
1071    if (readyState > 1 && !((readyState == 4) && this._complete))
1072      this.respondToReadyState(this.transport.readyState);
1073  },
1074
1075  setRequestHeaders: function() {
1076    var headers = {
1077      'X-Requested-With': 'XMLHttpRequest',
1078      'X-Prototype-Version': Prototype.Version,
1079      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1080    };
1081
1082    if (this.method == 'post') {
1083      headers['Content-type'] = this.options.contentType +
1084        (this.options.encoding ? '; charset=' + this.options.encoding : '');
1085
1086      /* Force "Connection: close" for older Mozilla browsers to work
1087       * around a bug where XMLHttpRequest sends an incorrect
1088       * Content-length header. See Mozilla Bugzilla #246651.
1089       */
1090      if (this.transport.overrideMimeType &&
1091          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1092            headers['Connection'] = 'close';
1093    }
1094
1095    // user-defined headers
1096    if (typeof this.options.requestHeaders == 'object') {
1097      var extras = this.options.requestHeaders;
1098
1099      if (typeof extras.push == 'function')
1100        for (var i = 0, length = extras.length; i < length; i += 2)
1101          headers[extras[i]] = extras[i+1];
1102      else
1103        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1104    }
1105
1106    for (var name in headers)
1107      this.transport.setRequestHeader(name, headers[name]);
1108  },
1109
1110  success: function() {
1111    return !this.transport.status
1112        || (this.transport.status >= 200 && this.transport.status < 300);
1113  },
1114
1115  respondToReadyState: function(readyState) {
1116    var state = Ajax.Request.Events[readyState];
1117    var transport = this.transport, json = this.evalJSON();
1118
1119    if (state == 'Complete') {
1120      try {
1121        this._complete = true;
1122        (this.options['on' + this.transport.status]
1123         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1124         || Prototype.emptyFunction)(transport, json);
1125      } catch (e) {
1126        this.dispatchException(e);
1127      }
1128
1129//      var contentType = this.getHeader('Content-type');
1130//      if (contentType && contentType.strip().
1131//        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
1132//          this.evalResponse();
1133    }
1134
1135    try {
1136      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
1137      Ajax.Responders.dispatch('on' + state, this, transport, json);
1138    } catch (e) {
1139      this.dispatchException(e);
1140    }
1141
1142    if (state == 'Complete') {
1143      // avoid memory leak in MSIE: clean up
1144      this.transport.onreadystatechange = Prototype.emptyFunction;
1145    }
1146  },
1147
1148  getHeader: function(name) {
1149    try {
1150      return this.transport.getResponseHeader(name);
1151    } catch (e) { return null }
1152  },
1153
1154  evalJSON: function() {
1155    try {
1156      var json = this.getHeader('X-JSON');
1157      return json ? json.evalJSON() : null;
1158    } catch (e) { return null }
1159  },
1160
1161  evalResponse: function() {
1162    try {
1163      return eval('('+(this.transport.responseText || '').unfilterJSON()+')');
1164    } catch (e) {
1165      this.dispatchException(e);
1166    }
1167  },
1168
1169  dispatchException: function(exception) {
1170    (this.options.onException || Prototype.emptyFunction)(this, exception);
1171    Ajax.Responders.dispatch('onException', this, exception);
1172  }
1173});
1174
1175Ajax.Updater = Class.create();
1176
1177Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
1178  initialize: function(container, url, options) {
1179    this.container = {
1180      success: (container.success || container),
1181      failure: (container.failure || (container.success ? null : container))
1182    }
1183
1184    this.transport = Ajax.getTransport();
1185    this.setOptions(options);
1186
1187    var onComplete = this.options.onComplete || Prototype.emptyFunction;
1188    this.options.onComplete = (function(transport, param) {
1189      this.updateContent();
1190      onComplete(transport, param);
1191    }).bind(this);
1192
1193    this.request(url);
1194  },
1195
1196  updateContent: function() {
1197    var receiver = this.container[this.success() ? 'success' : 'failure'];
1198    var response = this.transport.responseText;
1199
1200    if (!this.options.evalScripts) response = response.stripScripts();
1201
1202    if (receiver = $(receiver)) {
1203      if (this.options.insertion)
1204        new this.options.insertion(receiver, response);
1205      else
1206        receiver.update(response);
1207    }
1208
1209    if (this.success()) {
1210      if (this.onComplete)
1211        setTimeout(this.onComplete.bind(this), 10);
1212    }
1213  }
1214});
1215
1216Ajax.PeriodicalUpdater = Class.create();
1217Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
1218  initialize: function(container, url, options) {
1219    this.setOptions(options);
1220    this.onComplete = this.options.onComplete;
1221
1222    this.frequency = (this.options.frequency || 2);
1223    this.decay = (this.options.decay || 1);
1224
1225    this.updater = {};
1226    this.container = container;
1227    this.url = url;
1228
1229    this.start();
1230  },
1231
1232  start: function() {
1233    this.options.onComplete = this.updateComplete.bind(this);
1234    this.onTimerEvent();
1235  },
1236
1237  stop: function() {
1238    this.updater.options.onComplete = undefined;
1239    clearTimeout(this.timer);
1240    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1241  },
1242
1243  updateComplete: function(request) {
1244    if (this.options.decay) {
1245      this.decay = (request.responseText == this.lastText ?
1246        this.decay * this.options.decay : 1);
1247
1248      this.lastText = request.responseText;
1249    }
1250    this.timer = setTimeout(this.onTimerEvent.bind(this),
1251      this.decay * this.frequency * 1000);
1252  },
1253
1254  onTimerEvent: function() {
1255    this.updater = new Ajax.Updater(this.container, this.url, this.options);
1256  }
1257});
1258function $(element) {
1259  if (arguments.length > 1) {
1260    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1261      elements.push($(arguments[i]));
1262    return elements;
1263  }
1264  if (typeof element == 'string')
1265    element = document.getElementById(element);
1266  return Element.extend(element);
1267}
1268
1269if (Prototype.BrowserFeatures.XPath) {
1270  document._getElementsByXPath = function(expression, parentElement) {
1271    var results = [];
1272    var query = document.evaluate(expression, $(parentElement) || document,
1273      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1274    for (var i = 0, length = query.snapshotLength; i < length; i++)
1275      results.push(query.snapshotItem(i));
1276    return results;
1277  };
1278
1279  document.getElementsByClassName = function(className, parentElement) {
1280    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1281    return document._getElementsByXPath(q, parentElement);
1282  }
1283
1284} else document.getElementsByClassName = function(className, parentElement) {
1285  var children = ($(parentElement) || document.body).getElementsByTagName('*');
1286  var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
1287  for (var i = 0, length = children.length; i < length; i++) {
1288    child = children[i];
1289    var elementClassName = child.className;
1290    if (elementClassName.length == 0) continue;
1291    if (elementClassName == className || elementClassName.match(pattern))
1292      elements.push(Element.extend(child));
1293  }
1294  return elements;
1295};
1296
1297/*--------------------------------------------------------------------------*/
1298
1299if (!window.Element) var Element = {};
1300
1301Element.extend = function(element) {
1302  var F = Prototype.BrowserFeatures;
1303  if (!element || !element.tagName || element.nodeType == 3 ||
1304   element._extended || F.SpecificElementExtensions || element == window)
1305    return element;
1306
1307  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
1308   T = Element.Methods.ByTag;
1309
1310  // extend methods for all tags (Safari doesn't need this)
1311  if (!F.ElementExtensions) {
1312    Object.extend(methods, Element.Methods),
1313    Object.extend(methods, Element.Methods.Simulated);
1314  }
1315
1316  // extend methods for specific tags
1317  if (T[tagName]) Object.extend(methods, T[tagName]);
1318
1319  for (var property in methods) {
1320    var value = methods[property];
1321    if (typeof value == 'function' && !(property in element))
1322      element[property] = cache.findOrStore(value);
1323  }
1324
1325  element._extended = Prototype.emptyFunction;
1326  return element;
1327};
1328
1329Element.extend.cache = {
1330  findOrStore: function(value) {
1331    return this[value] = this[value] || function() {
1332      return value.apply(null, [this].concat($A(arguments)));
1333    }
1334  }
1335};
1336
1337Element.Methods = {
1338  visible: function(element) {
1339    return $(element).style.display != 'none';
1340  },
1341
1342  toggle: function(element) {
1343    element = $(element);
1344    Element[Element.visible(element) ? 'hide' : 'show'](element);
1345    return element;
1346  },
1347
1348  hide: function(element) {
1349    $(element).style.display = 'none';
1350    return element;
1351  },
1352
1353  show: function(element) {
1354    $(element).style.display = '';
1355    return element;
1356  },
1357
1358  remove: function(element) {
1359    element = $(element);
1360    element.parentNode.removeChild(element);
1361    return element;
1362  },
1363
1364  update: function(element, html) {
1365    html = typeof html == 'undefined' ? '' : html.toString();
1366    $(element).innerHTML = html.stripScripts();
1367    setTimeout(function() {html.evalScripts()}, 10);
1368    return element;
1369  },
1370
1371  replace: function(element, html) {
1372    element = $(element);
1373    html = typeof html == 'undefined' ? '' : html.toString();
1374    if (element.outerHTML) {
1375      element.outerHTML = html.stripScripts();
1376    } else {
1377      var range = element.ownerDocument.createRange();
1378      range.selectNodeContents(element);
1379      element.parentNode.replaceChild(
1380        range.createContextualFragment(html.stripScripts()), element);
1381    }
1382    setTimeout(function() {html.evalScripts()}, 10);
1383    return element;
1384  },
1385
1386  inspect: function(element) {
1387    element = $(element);
1388    var result = '<' + element.tagName.toLowerCase();
1389    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1390      var property = pair.first(), attribute = pair.last();
1391      var value = (element[property] || '').toString();
1392      if (value) result += ' ' + attribute + '=' + value.inspect(true);
1393    });
1394    return result + '>';
1395  },
1396
1397  recursivelyCollect: function(element, property) {
1398    element = $(element);
1399    var elements = [];
1400    while (element = element[property])
1401      if (element.nodeType == 1)
1402        elements.push(Element.extend(element));
1403    return elements;
1404  },
1405
1406  ancestors: function(element) {
1407    return $(element).recursivelyCollect('parentNode');
1408  },
1409
1410  descendants: function(element) {
1411    return $A($(element).getElementsByTagName('*')).each(Element.extend);
1412  },
1413
1414  firstDescendant: function(element) {
1415    element = $(element).firstChild;
1416    while (element && element.nodeType != 1) element = element.nextSibling;
1417    return $(element);
1418  },
1419
1420  immediateDescendants: function(element) {
1421    if (!(element = $(element).firstChild)) return [];
1422    while (element && element.nodeType != 1) element = element.nextSibling;
1423    if (element) return [element].concat($(element).nextSiblings());
1424    return [];
1425  },
1426
1427  previousSiblings: function(element) {
1428    return $(element).recursivelyCollect('previousSibling');
1429  },
1430
1431  nextSiblings: function(element) {
1432    return $(element).recursivelyCollect('nextSibling');
1433  },
1434
1435  siblings: function(element) {
1436    element = $(element);
1437    return element.previousSiblings().reverse().concat(element.nextSiblings());
1438  },
1439
1440  match: function(element, selector) {
1441    if (typeof selector == 'string')
1442      selector = new Selector(selector);
1443    return selector.match($(element));
1444  },
1445
1446  up: function(element, expression, index) {
1447    element = $(element);
1448    if (arguments.length == 1) return $(element.parentNode);
1449    var ancestors = element.ancestors();
1450    return expression ? Selector.findElement(ancestors, expression, index) :
1451      ancestors[index || 0];
1452  },
1453
1454  down: function(element, expression, index) {
1455    element = $(element);
1456    if (arguments.length == 1) return element.firstDescendant();
1457    var descendants = element.descendants();
1458    return expression ? Selector.findElement(descendants, expression, index) :
1459      descendants[index || 0];
1460  },
1461
1462  previous: function(element, expression, index) {
1463    element = $(element);
1464    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1465    var previousSiblings = element.previousSiblings();
1466    return expression ? Selector.findElement(previousSiblings, expression, index) :
1467      previousSiblings[index || 0];
1468  },
1469
1470  next: function(element, expression, index) {
1471    element = $(element);
1472    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1473    var nextSiblings = element.nextSiblings();
1474    return expression ? Selector.findElement(nextSiblings, expression, index) :
1475      nextSiblings[index || 0];
1476  },
1477
1478  getElementsBySelector: function() {
1479    var args = $A(arguments), element = $(args.shift());
1480    return Selector.findChildElements(element, args);
1481  },
1482
1483  getElementsByClassName: function(element, className) {
1484    return document.getElementsByClassName(className, element);
1485  },
1486
1487  readAttribute: function(element, name) {
1488    element = $(element);
1489    if (Prototype.Browser.IE) {
1490      if (!element.attributes) return null;
1491      var t = Element._attributeTranslations;
1492      if (t.values[name]) return t.values[name](element, name);
1493      if (t.names[name])  name = t.names[name];
1494      var attribute = element.attributes[name];
1495      return attribute ? attribute.nodeValue : null;
1496    }
1497    return element.getAttribute(name);
1498  },
1499
1500  getHeight: function(element) {
1501    return $(element).getDimensions().height;
1502  },
1503
1504  getWidth: function(element) {
1505    return $(element).getDimensions().width;
1506  },
1507
1508  classNames: function(element) {
1509    return new Element.ClassNames(element);
1510  },
1511
1512  hasClassName: function(element, className) {
1513    if (!(element = $(element))) return;
1514    var elementClassName = element.className;
1515    if (!elementClassName || elementClassName.length == 0) return false;
1516    if (elementClassName == className ||
1517        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1518      return true;
1519    return false;
1520  },
1521
1522  addClassName: function(element, className) {
1523    if (!(element = $(element))) return;
1524    Element.classNames(element).add(className);
1525    return element;
1526  },
1527
1528  removeClassName: function(element, className) {
1529    if (!(element = $(element))) return;
1530    Element.classNames(element).remove(className);
1531    return element;
1532  },
1533
1534  toggleClassName: function(element, className) {
1535    if (!(element = $(element))) return;
1536    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
1537    return element;
1538  },
1539
1540  observe: function() {
1541    Event.observe.apply(Event, arguments);
1542    return $A(arguments).first();
1543  },
1544
1545  stopObserving: function() {
1546    Event.stopObserving.apply(Event, arguments);
1547    return $A(arguments).first();
1548  },
1549
1550  // removes whitespace-only text node children
1551  cleanWhitespace: function(element) {
1552    element = $(element);
1553    var node = element.firstChild;
1554    while (node) {
1555      var nextNode = node.nextSibling;
1556      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1557        element.removeChild(node);
1558      node = nextNode;
1559    }
1560    return element;
1561  },
1562
1563  empty: function(element) {
1564    return $(element).innerHTML.blank();
1565  },
1566
1567  descendantOf: function(element, ancestor) {
1568    element = $(element), ancestor = $(ancestor);
1569    while (element = element.parentNode)
1570      if (element == ancestor) return true;
1571    return false;
1572  },
1573
1574  scrollTo: function(element) {
1575    element = $(element);
1576    var pos = Position.cumulativeOffset(element);
1577    window.scrollTo(pos[0], pos[1]);
1578    return element;
1579  },
1580
1581  getStyle: function(element, style) {
1582    element = $(element);
1583    style = style == 'float' ? 'cssFloat' : style.camelize();
1584    var value = element.style[style];
1585    if (!value) {
1586      var css = document.defaultView.getComputedStyle(element, null);
1587      value = css ? css[style] : null;
1588    }
1589    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1590    return value == 'auto' ? null : value;
1591  },
1592
1593  getOpacity: function(element) {
1594    return $(element).getStyle('opacity');
1595  },
1596
1597  setStyle: function(element, styles, camelized) {
1598    element = $(element);
1599    var elementStyle = element.style;
1600
1601    for (var property in styles)
1602      if (property == 'opacity') element.setOpacity(styles[property])
1603      else
1604        elementStyle[(property == 'float' || property == 'cssFloat') ?
1605          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
1606          (camelized ? property : property.camelize())] = styles[property];
1607
1608    return element;
1609  },
1610
1611  setOpacity: function(element, value) {
1612    element = $(element);
1613    element.style.opacity = (value == 1 || value === '') ? '' :
1614      (value < 0.00001) ? 0 : value;
1615    return element;
1616  },
1617
1618  getDimensions: function(element) {
1619    element = $(element);
1620    var display = $(element).getStyle('display');
1621    if (display != 'none' && display != null) // Safari bug
1622      return {width: element.offsetWidth, height: element.offsetHeight};
1623
1624    // All *Width and *Height properties give 0 on elements with display none,
1625    // so enable the element temporarily
1626    var els = element.style;
1627    var originalVisibility = els.visibility;
1628    var originalPosition = els.position;
1629    var originalDisplay = els.display;
1630    els.visibility = 'hidden';
1631    els.position = 'absolute';
1632    els.display = 'block';
1633    var originalWidth = element.clientWidth;
1634    var originalHeight = element.clientHeight;
1635    els.display = originalDisplay;
1636    els.position = originalPosition;
1637    els.visibility = originalVisibility;
1638    return {width: originalWidth, height: originalHeight};
1639  },
1640
1641  makePositioned: function(element) {
1642    element = $(element);
1643    var pos = Element.getStyle(element, 'position');
1644    if (pos == 'static' || !pos) {
1645      element._madePositioned = true;
1646      element.style.position = 'relative';
1647      // Opera returns the offset relative to the positioning context, when an
1648      // element is position relative but top and left have not been defined
1649      if (window.opera) {
1650        element.style.top = 0;
1651        element.style.left = 0;
1652      }
1653    }
1654    return element;
1655  },
1656
1657  undoPositioned: function(element) {
1658    element = $(element);
1659    if (element._madePositioned) {
1660      element._madePositioned = undefined;
1661      element.style.position =
1662        element.style.top =
1663        element.style.left =
1664        element.style.bottom =
1665        element.style.right = '';
1666    }
1667    return element;
1668  },
1669
1670  makeClipping: function(element) {
1671    element = $(element);
1672    if (element._overflow) return element;
1673    element._overflow = element.style.overflow || 'auto';
1674    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1675      element.style.overflow = 'hidden';
1676    return element;
1677  },
1678
1679  undoClipping: function(element) {
1680    element = $(element);
1681    if (!element._overflow) return element;
1682    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1683    element._overflow = null;
1684    return element;
1685  }
1686};
1687
1688Object.extend(Element.Methods, {
1689  childOf: Element.Methods.descendantOf,
1690  childElements: Element.Methods.immediateDescendants
1691});
1692
1693if (Prototype.Browser.Opera) {
1694  Element.Methods._getStyle = Element.Methods.getStyle;
1695  Element.Methods.getStyle = function(element, style) {
1696    switch(style) {
1697      case 'left':
1698      case 'top':
1699      case 'right':
1700      case 'bottom':
1701        if (Element._getStyle(element, 'position') == 'static') return null;
1702      default: return Element._getStyle(element, style);
1703    }
1704  };
1705}
1706else if (Prototype.Browser.IE) {
1707  Element.Methods.getStyle = function(element, style) {
1708    element = $(element);
1709    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
1710    var value = element.style[style];
1711    if (!value && element.currentStyle) value = element.currentStyle[style];
1712
1713    if (style == 'opacity') {
1714      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
1715        if (value[1]) return parseFloat(value[1]) / 100;
1716      return 1.0;
1717    }
1718
1719    if (value == 'auto') {
1720      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
1721        return element['offset'+style.capitalize()] + 'px';
1722      return null;
1723    }
1724    return value;
1725  };
1726
1727  Element.Methods.setOpacity = function(element, value) {
1728    element = $(element);
1729    var filter = element.getStyle('filter'), style = element.style;
1730    if (value == 1 || value === '') {
1731      style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
1732      return element;
1733    } else if (value < 0.00001) value = 0;
1734    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
1735      'alpha(opacity=' + (value * 100) + ')';
1736    return element;
1737  };
1738
1739  // IE is missing .innerHTML support for TABLE-related elements
1740  Element.Methods.update = function(element, html) {
1741    element = $(element);
1742    html = typeof html == 'undefined' ? '' : html.toString();
1743    var tagName = element.tagName.toUpperCase();
1744    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1745      var div = document.createElement('div');
1746      switch (tagName) {
1747        case 'THEAD':
1748        case 'TBODY':
1749          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
1750          depth = 2;
1751          break;
1752        case 'TR':
1753          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
1754          depth = 3;
1755          break;
1756        case 'TD':
1757          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
1758          depth = 4;
1759      }
1760      $A(element.childNodes).each(function(node) { element.removeChild(node) });
1761      depth.times(function() { div = div.firstChild });
1762      $A(div.childNodes).each(function(node) { element.appendChild(node) });
1763    } else {
1764      element.innerHTML = html.stripScripts();
1765    }
1766    setTimeout(function() { html.evalScripts() }, 10);
1767    return element;
1768  }
1769}
1770else if (Prototype.Browser.Gecko) {
1771  Element.Methods.setOpacity = function(element, value) {
1772    element = $(element);
1773    element.style.opacity = (value == 1) ? 0.999999 :
1774      (value === '') ? '' : (value < 0.00001) ? 0 : value;
1775    return element;
1776  };
1777}
1778
1779Element._attributeTranslations = {
1780  names: {
1781    colspan:   "colSpan",
1782    rowspan:   "rowSpan",
1783    valign:    "vAlign",
1784    datetime:  "dateTime",
1785    accesskey: "accessKey",
1786    tabindex:  "tabIndex",
1787    enctype:   "encType",
1788    maxlength: "maxLength",
1789    readonly:  "readOnly",
1790    longdesc:  "longDesc"
1791  },
1792  values: {
1793    _getAttr: function(element, attribute) {
1794      return element.getAttribute(attribute, 2);
1795    },
1796    _flag: func

Large files files are truncated, but you can click here to view the full file