[ Index ]
 

Code source de LifeType 1.2.4

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/js/prototype/ -> prototype.js (source)

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


Généré le : Mon Nov 26 21:04:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics