prototype.js
上传用户:mtjhgs
上传日期:2021-12-08
资源大小:3755k
文件大小:45k
源码类别:

WEB源码(ASP,PHP,...)

开发平台:

HTML/CSS

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