prototype.js
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:32k
源码类别:

网格计算

开发平台:

Java

  1. /*  Prototype JavaScript framework, version 1.4.0_pre4
  2.  *  (c) 2005 Sam Stephenson <sam@conio.net>
  3.  *
  4.  *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
  5.  *  against the source tree, available from the Prototype darcs repository. 
  6.  *
  7.  *  Prototype is freely distributable under the terms of an MIT-style license.
  8.  *
  9.  *  For details, see the Prototype web site: http://prototype.conio.net/
  10.  *
  11. /*--------------------------------------------------------------------------*/
  12. var Prototype = {
  13.   Version: '1.4.0_pre4',
  14.   
  15.   emptyFunction: function() {},
  16.   K: function(x) {return x}
  17. }
  18. var Class = {
  19.   create: function() {
  20.     return function() { 
  21.       this.initialize.apply(this, arguments);
  22.     }
  23.   }
  24. }
  25. var Abstract = new Object();
  26. Object.extend = function(destination, source) {
  27.   for (property in source) {
  28.     destination[property] = source[property];
  29.   }
  30.   return destination;
  31. }
  32. Function.prototype.bind = function(object) {
  33.   var __method = this;
  34.   return function() {
  35.     return __method.apply(object, arguments);
  36.   }
  37. }
  38. Function.prototype.bindAsEventListener = function(object) {
  39.   var __method = this;
  40.   return function(event) {
  41.     return __method.call(object, event || window.event);
  42.   }
  43. }
  44. Number.prototype.toColorPart = function() {
  45.   var digits = this.toString(16);
  46.   if (this < 16) return '0' + digits;
  47.   return digits;
  48. }
  49. var Try = {
  50.   these: function() {
  51.     var returnValue;
  52.     for (var i = 0; i < arguments.length; i++) {
  53.       var lambda = arguments[i];
  54.       try {
  55.         returnValue = lambda();
  56.         break;
  57.       } catch (e) {}
  58.     }
  59.     return returnValue;
  60.   }
  61. }
  62. /*--------------------------------------------------------------------------*/
  63. var PeriodicalExecuter = Class.create();
  64. PeriodicalExecuter.prototype = {
  65.   initialize: function(callback, frequency) {
  66.     this.callback = callback;
  67.     this.frequency = frequency;
  68.     this.currentlyExecuting = false;
  69.     this.registerCallback();
  70.   },
  71.   registerCallback: function() {
  72.     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  73.   },
  74.   onTimerEvent: function() {
  75.     if (!this.currentlyExecuting) {
  76.       try { 
  77.         this.currentlyExecuting = true;
  78.         this.callback(); 
  79.       } finally { 
  80.         this.currentlyExecuting = false;
  81.       }
  82.     }
  83.   }
  84. }
  85. /*--------------------------------------------------------------------------*/
  86. function $() {
  87.   var elements = new Array();
  88.   for (var i = 0; i < arguments.length; i++) {
  89.     var element = arguments[i];
  90.     if (typeof element == 'string')
  91.       element = document.getElementById(element);
  92.     if (arguments.length == 1) 
  93.       return element;
  94.     elements.push(element);
  95.   }
  96.   return elements;
  97. }
  98. if (!Array.prototype.push) {
  99.   Array.prototype.push = function() {
  100. var startLength = this.length;
  101. for (var i = 0; i < arguments.length; i++)
  102.       this[startLength + i] = arguments[i];
  103.   return this.length;
  104.   }
  105. }
  106. if (!Function.prototype.apply) {
  107.   // Based on code from http://www.youngpup.net/
  108.   Function.prototype.apply = function(object, parameters) {
  109.     var parameterStrings = new Array();
  110.     if (!object)     object = window;
  111.     if (!parameters) parameters = new Array();
  112.     
  113.     for (var i = 0; i < parameters.length; i++)
  114.       parameterStrings[i] = 'parameters[' + i + ']';
  115.     
  116.     object.__apply__ = this;
  117.     var result = eval('object.__apply__(' + 
  118.       parameterStrings.join(', ') + ')');
  119.     object.__apply__ = null;
  120.     
  121.     return result;
  122.   }
  123. }
  124. Object.extend(String.prototype, {
  125.   stripTags: function() {
  126.     return this.replace(/</?[^>]+>/gi, '');
  127.   },
  128.   escapeHTML: function() {
  129.     var div = document.createElement('div');
  130.     var text = document.createTextNode(this);
  131.     div.appendChild(text);
  132.     return div.innerHTML;
  133.   },
  134.   unescapeHTML: function() {
  135.     var div = document.createElement('div');
  136.     div.innerHTML = this.stripTags();
  137.     return div.childNodes[0].nodeValue;
  138.   },
  139.   
  140.   parseQuery: function() {
  141.     var str = this;
  142.     if (str.substring(0,1) == '?') {
  143.       str = this.substring(1);
  144.     }
  145.     var result = {};
  146.     var pairs = str.split('&');
  147.     for (var i = 0; i < pairs.length; i++) {
  148.       var pair = pairs[i].split('=');
  149.       result[pair[0]] = pair[1];
  150.     }
  151.     return result;
  152.   }
  153. });
  154. var _break    = new Object();
  155. var _continue = new Object();
  156. var Enumerable = {
  157.   each: function(iterator) {
  158.     var index = 0;
  159.     try {
  160.       this._each(function(value) {
  161.         try {
  162.           iterator(value, index++);
  163.         } catch (e) {
  164.           if (e != _continue) throw e;
  165.         }
  166.       });
  167.     } catch (e) {
  168.       if (e != _break) throw e;
  169.     }
  170.   },
  171.   
  172.   all: function(iterator) {
  173.     var result = true;
  174.     this.each(function(value, index) {
  175.       if (!(result &= (iterator || Prototype.K)(value, index))) 
  176.         throw _break;
  177.     });
  178.     return result;
  179.   },
  180.   
  181.   any: function(iterator) {
  182.     var result = true;
  183.     this.each(function(value, index) {
  184.       if (result &= (iterator || Prototype.K)(value, index)) 
  185.         throw _break;
  186.     });
  187.     return result;
  188.   },
  189.   
  190.   collect: function(iterator) {
  191.     var results = [];
  192.     this.each(function(value, index) {
  193.       results.push(iterator(value, index));
  194.     });
  195.     return results;
  196.   },
  197.   
  198.   detect: function (iterator) {
  199.     var result;
  200.     this.each(function(value, index) {
  201.       if (iterator(value, index)) {
  202.         result = value;
  203.         throw _break;
  204.       }
  205.     });
  206.     return result;
  207.   },
  208.   
  209.   findAll: function(iterator) {
  210.     var results = [];
  211.     this.each(function(value, index) {
  212.       if (iterator(value, index))
  213.         results.push(value);
  214.     });
  215.     return results;
  216.   },
  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.   
  228.   include: function(object) {
  229.     var found = false;
  230.     this.each(function(value) {
  231.       if (value == object) {
  232.         found = true;
  233.         throw _break;
  234.       }
  235.     });
  236.     return found;
  237.   },
  238.   
  239.   inject: function(memo, iterator) {
  240.     this.each(function(value, index) {
  241.       memo = iterator(memo, value, index);
  242.     });
  243.     return memo;
  244.   },
  245.   
  246.   invoke: function(method) {
  247.     var args = $A(arguments).slice(1);
  248.     return this.collect(function(value) {
  249.       return value[method].apply(value, args);
  250.     });
  251.   },
  252.   
  253.   max: function(iterator) {
  254.     var result;
  255.     this.each(function(value, index) {
  256.       value = (iterator || Prototype.K)(value, index);
  257.       if (value >= (result || value))
  258.         result = value;
  259.     });
  260.     return result;
  261.   },
  262.   
  263.   min: function(iterator) {
  264.     var result;
  265.     this.each(function(value, index) {
  266.       value = (iterator || Prototype.K)(value, index);
  267.       if (value <= (result || value))
  268.         result = value;
  269.     });
  270.     return result;
  271.   },
  272.   
  273.   partition: function(iterator) {
  274.     var trues = [], falses = [];
  275.     this.each(function(value, index) {
  276.       ((iterator || Prototype.K)(value, index) ? 
  277.         trues : falses).push(value);
  278.     });
  279.     return [trues, falses];
  280.   },
  281.   
  282.   pluck: function(property) {
  283.     var results = [];
  284.     this.each(function(value, index) {
  285.       results.push(value[property]);
  286.     });
  287.     return results;
  288.   },
  289.   
  290.   reject: function(iterator) {
  291.     var results = [];
  292.     this.each(function(value, index) {
  293.       if (!iterator(value, index))
  294.         results.push(value);
  295.     });
  296.     return results;
  297.   },
  298.   
  299.   sortBy: function(iterator) {
  300.     return this.collect(function(value, index) {
  301.       return {value: value, criteria: iterator(value, index)};
  302.     }).sort(function(left, right) {
  303.       var a = left.criteria, b = right.criteria;
  304.       return a < b ? -1 : a > b ? 1 : 0;
  305.     }).pluck('value');
  306.   },
  307.   
  308.   toArray: function() {
  309.     return this.collect(Prototype.K);
  310.   },
  311.   
  312.   zip: function() {
  313.     var iterator = Prototype.K, args = $A(arguments);
  314.     if (typeof args.last() == 'function')
  315.       iterator = args.pop();
  316.     var collections = [this].concat(args).map($A);
  317.     return this.map(function(value, index) {
  318.       iterator(value = collections.pluck(index));
  319.       return value;
  320.     });
  321.   }
  322. }
  323. Object.extend(Enumerable, {
  324.   map:     Enumerable.collect,
  325.   find:    Enumerable.detect,
  326.   select:  Enumerable.findAll,
  327.   member:  Enumerable.include,
  328.   entries: Enumerable.toArray
  329. });
  330. $A = Array.from = function(iterable) {
  331.   var results = [];
  332.   for (var i = 0; i < iterable.length; i++)
  333.     results.push(iterable[i]);
  334.   return results;
  335. }
  336. Object.extend(Array.prototype, {
  337.   _each: function(iterator) {
  338.     for (var i = 0; i < this.length; i++)
  339.       iterator(this[i]);
  340.   },
  341.   
  342.   first: function() {
  343.     return this[0];
  344.   },
  345.   
  346.   last: function() {
  347.     return this[this.length - 1];
  348.   }
  349. });
  350. Object.extend(Array.prototype, Enumerable);
  351. var Ajax = {
  352.   getTransport: function() {
  353.     return Try.these(
  354.       function() {return new ActiveXObject('Msxml2.XMLHTTP')},
  355.       function() {return new ActiveXObject('Microsoft.XMLHTTP')},
  356.       function() {return new XMLHttpRequest()}
  357.     ) || false;
  358.   }
  359. }
  360. Ajax.Base = function() {};
  361. Ajax.Base.prototype = {
  362.   setOptions: function(options) {
  363.     this.options = {
  364.       method:       'post',
  365.       asynchronous: true,
  366.       parameters:   ''
  367.     }
  368.     Object.extend(this.options, options || {});
  369.   },
  370.   responseIsSuccess: function() {
  371.     return this.transport.status == undefined
  372.         || this.transport.status == 0 
  373.         || (this.transport.status >= 200 && this.transport.status < 300);
  374.   },
  375.   responseIsFailure: function() {
  376.     return !this.responseIsSuccess();
  377.   }
  378. }
  379. Ajax.Request = Class.create();
  380. Ajax.Request.Events = 
  381.   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
  382. Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  383.   initialize: function(url, options) {
  384.     this.transport = Ajax.getTransport();
  385.     this.setOptions(options);
  386.     this.request(url);
  387.   },
  388.   request: function(url) {
  389.     var parameters = this.options.parameters || '';
  390.     if (parameters.length > 0) parameters += '&_=';
  391.     try {
  392.       if (this.options.method == 'get')
  393.         url += '?' + parameters;
  394.       this.transport.open(this.options.method, url,
  395.         this.options.asynchronous);
  396.       if (this.options.asynchronous) {
  397.         this.transport.onreadystatechange = this.onStateChange.bind(this);
  398.         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
  399.       }
  400.       this.setRequestHeaders();
  401.       var body = this.options.postBody ? this.options.postBody : parameters;
  402.       this.transport.send(this.options.method == 'post' ? body : null);
  403.     } catch (e) {
  404.     }
  405.   },
  406.   setRequestHeaders: function() {
  407.     var requestHeaders = 
  408.       ['X-Requested-With', 'XMLHttpRequest',
  409.        'X-Prototype-Version', Prototype.Version];
  410.     if (this.options.method == 'post') {
  411.       requestHeaders.push('Content-type', 
  412.         'application/x-www-form-urlencoded');
  413.       /* Force "Connection: close" for Mozilla browsers to work around
  414.        * a bug where XMLHttpReqeuest sends an incorrect Content-length
  415.        * header. See Mozilla Bugzilla #246651. 
  416.        */
  417.       if (this.transport.overrideMimeType)
  418.         requestHeaders.push('Connection', 'close');
  419.     }
  420.     if (this.options.requestHeaders)
  421.       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
  422.     for (var i = 0; i < requestHeaders.length; i += 2)
  423.       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
  424.   },
  425.   onStateChange: function() {
  426.     var readyState = this.transport.readyState;
  427.     if (readyState != 1)
  428.       this.respondToReadyState(this.transport.readyState);
  429.   },
  430.   respondToReadyState: function(readyState) {
  431.     var event = Ajax.Request.Events[readyState];
  432.     if (event == 'Complete')
  433.       (this.options['on' + this.transport.status]
  434.        || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
  435.        || Prototype.emptyFunction)(this.transport);
  436.     (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
  437.     /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
  438.     if (event == 'Complete')
  439.       this.transport.onreadystatechange = Prototype.emptyFunction;
  440.   }
  441. });
  442. Ajax.Updater = Class.create();
  443. Ajax.Updater.ScriptFragment = '(?:<script.*?>)((n|.)*?)(?:</script>)';
  444. Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  445.   initialize: function(container, url, options) {
  446.     this.containers = {
  447.       success: container.success ? $(container.success) : $(container),
  448.       failure: container.failure ? $(container.failure) :
  449.         (container.success ? null : $(container))
  450.     }
  451.     this.transport = Ajax.getTransport();
  452.     this.setOptions(options);
  453.     var onComplete = this.options.onComplete || Prototype.emptyFunction;
  454.     this.options.onComplete = (function() {
  455.       this.updateContent();
  456.       onComplete(this.transport);
  457.     }).bind(this);
  458.     this.request(url);
  459.   },
  460.   updateContent: function() {
  461.     var receiver = this.responseIsSuccess() ?
  462.       this.containers.success : this.containers.failure;
  463.     var match    = new RegExp(Ajax.Updater.ScriptFragment, 'img');
  464.     var response = this.transport.responseText.replace(match, '');
  465.     var scripts  = this.transport.responseText.match(match);
  466.     if (receiver) {
  467.       if (this.options.insertion) {
  468.         new this.options.insertion(receiver, response);
  469.       } else {
  470.         receiver.innerHTML = response;
  471.       }
  472.     }
  473.     if (this.responseIsSuccess()) {
  474.       if (this.onComplete)
  475.         setTimeout((function() {this.onComplete(
  476.           this.transport)}).bind(this), 10);
  477.     }
  478.     if (this.options.evalScripts && scripts) {
  479.       match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
  480.       setTimeout((function() {
  481.         for (var i = 0; i < scripts.length; i++)
  482.           eval(scripts[i].match(match)[1]);
  483.       }).bind(this), 10);
  484.     }
  485.   }
  486. });
  487. Ajax.PeriodicalUpdater = Class.create();
  488. Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  489.   initialize: function(container, url, options) {
  490.     this.setOptions(options);
  491.     this.onComplete = this.options.onComplete;
  492.     this.frequency = (this.options.frequency || 2);
  493.     this.decay = 1;
  494.     this.updater = {};
  495.     this.container = container;
  496.     this.url = url;
  497.     this.start();
  498.   },
  499.   start: function() {
  500.     this.options.onComplete = this.updateComplete.bind(this);
  501.     this.onTimerEvent();
  502.   },
  503.   stop: function() {
  504.     this.updater.onComplete = undefined;
  505.     clearTimeout(this.timer);
  506.     (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
  507.   },
  508.   updateComplete: function(request) {
  509.     if (this.options.decay) {
  510.       this.decay = (request.responseText == this.lastText ? 
  511.         this.decay * this.options.decay : 1);
  512.       this.lastText = request.responseText;
  513.     }
  514.     this.timer = setTimeout(this.onTimerEvent.bind(this), 
  515.       this.decay * this.frequency * 1000);
  516.   },
  517.   onTimerEvent: function() {
  518.     this.updater = new Ajax.Updater(this.container, this.url, this.options);
  519.   }
  520. });
  521. document.getElementsByClassName = function(className) {
  522.   var children = document.getElementsByTagName('*') || document.all;
  523.   var elements = new Array();
  524.   
  525.   for (var i = 0; i < children.length; i++) {
  526.     var child = children[i];
  527.     var classNames = child.className.split(' ');
  528.     for (var j = 0; j < classNames.length; j++) {
  529.       if (classNames[j] == className) {
  530.         elements.push(child);
  531.         break;
  532.       }
  533.     }
  534.   }
  535.   
  536.   return elements;
  537. }
  538. /*--------------------------------------------------------------------------*/
  539. if (!window.Element) {
  540.   var Element = new Object();
  541. }
  542. Object.extend(Element, {
  543.   toggle: function() {
  544.     for (var i = 0; i < arguments.length; i++) {
  545.       var element = $(arguments[i]);
  546.       element.style.display = 
  547.         (element.style.display == 'none' ? '' : 'none');
  548.     }
  549.   },
  550.   hide: function() {
  551.     for (var i = 0; i < arguments.length; i++) {
  552.       var element = $(arguments[i]);
  553.       element.style.display = 'none';
  554.     }
  555.   },
  556.   show: function() {
  557.     for (var i = 0; i < arguments.length; i++) {
  558.       var element = $(arguments[i]);
  559.       element.style.display = '';
  560.     }
  561.   },
  562.   remove: function(element) {
  563.     element = $(element);
  564.     element.parentNode.removeChild(element);
  565.   },
  566.    
  567.   getHeight: function(element) {
  568.     element = $(element);
  569.     return element.offsetHeight; 
  570.   },
  571.   hasClassName: function(element, className) {
  572.     element = $(element);
  573.     if (!element)
  574.       return;
  575.     var a = element.className.split(' ');
  576.     for (var i = 0; i < a.length; i++) {
  577.       if (a[i] == className)
  578.         return true;
  579.     }
  580.     return false;
  581.   },
  582.   addClassName: function(element, className) {
  583.     element = $(element);
  584.     Element.removeClassName(element, className);
  585.     element.className += ' ' + className;
  586.   },
  587.   removeClassName: function(element, className) {
  588.     element = $(element);
  589.     if (!element)
  590.       return;
  591.     var newClassName = '';
  592.     var a = element.className.split(' ');
  593.     for (var i = 0; i < a.length; i++) {
  594.       if (a[i] != className) {
  595.         if (i > 0)
  596.           newClassName += ' ';
  597.         newClassName += a[i];
  598.       }
  599.     }
  600.     element.className = newClassName;
  601.   },
  602.   
  603.   // removes whitespace-only text node children
  604.   cleanWhitespace: function(element) {
  605.     var element = $(element);
  606.     for (var i = 0; i < element.childNodes.length; i++) {
  607.       var node = element.childNodes[i];
  608.       if (node.nodeType == 3 && !/S/.test(node.nodeValue)) 
  609.         Element.remove(node);
  610.     }
  611.   }
  612. });
  613. var Toggle = new Object();
  614. Toggle.display = Element.toggle;
  615. /*--------------------------------------------------------------------------*/
  616. Abstract.Insertion = function(adjacency) {
  617.   this.adjacency = adjacency;
  618. }
  619. Abstract.Insertion.prototype = {
  620.   initialize: function(element, content) {
  621.     this.element = $(element);
  622.     this.content = content;
  623.     
  624.     if (this.adjacency && this.element.insertAdjacentHTML) {
  625.       this.element.insertAdjacentHTML(this.adjacency, this.content);
  626.     } else {
  627.       this.range = this.element.ownerDocument.createRange();
  628.       if (this.initializeRange) this.initializeRange();
  629.       this.fragment = this.range.createContextualFragment(this.content);
  630.       this.insertContent();
  631.     }
  632.   }
  633. }
  634. var Insertion = new Object();
  635. Insertion.Before = Class.create();
  636. Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  637.   initializeRange: function() {
  638.     this.range.setStartBefore(this.element);
  639.   },
  640.   
  641.   insertContent: function() {
  642.     this.element.parentNode.insertBefore(this.fragment, this.element);
  643.   }
  644. });
  645. Insertion.Top = Class.create();
  646. Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  647.   initializeRange: function() {
  648.     this.range.selectNodeContents(this.element);
  649.     this.range.collapse(true);
  650.   },
  651.   
  652.   insertContent: function() {  
  653.     this.element.insertBefore(this.fragment, this.element.firstChild);
  654.   }
  655. });
  656. Insertion.Bottom = Class.create();
  657. Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  658.   initializeRange: function() {
  659.     this.range.selectNodeContents(this.element);
  660.     this.range.collapse(this.element);
  661.   },
  662.   
  663.   insertContent: function() {
  664.     this.element.appendChild(this.fragment);
  665.   }
  666. });
  667. Insertion.After = Class.create();
  668. Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  669.   initializeRange: function() {
  670.     this.range.setStartAfter(this.element);
  671.   },
  672.   
  673.   insertContent: function() {
  674.     this.element.parentNode.insertBefore(this.fragment, 
  675.       this.element.nextSibling);
  676.   }
  677. });
  678. var Field = {
  679.   clear: function() {
  680.     for (var i = 0; i < arguments.length; i++)
  681.       $(arguments[i]).value = '';
  682.   },
  683.   focus: function(element) {
  684.     $(element).focus();
  685.   },
  686.   
  687.   present: function() {
  688.     for (var i = 0; i < arguments.length; i++)
  689.       if ($(arguments[i]).value == '') return false;
  690.     return true;
  691.   },
  692.   
  693.   select: function(element) {
  694.     $(element).select();
  695.   },
  696.    
  697.   activate: function(element) {
  698.     $(element).focus();
  699.     $(element).select();
  700.   }
  701. }
  702. /*--------------------------------------------------------------------------*/
  703. var Form = {
  704.   serialize: function(form) {
  705.     var elements = Form.getElements($(form));
  706.     var queryComponents = new Array();
  707.     
  708.     for (var i = 0; i < elements.length; i++) {
  709.       var queryComponent = Form.Element.serialize(elements[i]);
  710.       if (queryComponent)
  711.         queryComponents.push(queryComponent);
  712.     }
  713.     
  714.     return queryComponents.join('&');
  715.   },
  716.   
  717.   getElements: function(form) {
  718.     var form = $(form);
  719.     var elements = new Array();
  720.     for (tagName in Form.Element.Serializers) {
  721.       var tagElements = form.getElementsByTagName(tagName);
  722.       for (var j = 0; j < tagElements.length; j++)
  723.         elements.push(tagElements[j]);
  724.     }
  725.     return elements;
  726.   },
  727.   
  728.   getInputs: function(form, typeName, name) {
  729.     var form = $(form);
  730.     var inputs = form.getElementsByTagName('input');
  731.     
  732.     if (!typeName && !name)
  733.       return inputs;
  734.       
  735.     var matchingInputs = new Array();
  736.     for (var i = 0; i < inputs.length; i++) {
  737.       var input = inputs[i];
  738.       if ((typeName && input.type != typeName) ||
  739.           (name && input.name != name)) 
  740.         continue;
  741.       matchingInputs.push(input);
  742.     }
  743.     return matchingInputs;
  744.   },
  745.   disable: function(form) {
  746.     var elements = Form.getElements(form);
  747.     for (var i = 0; i < elements.length; i++) {
  748.       var element = elements[i];
  749.       element.blur();
  750.       element.disabled = 'true';
  751.     }
  752.   },
  753.   enable: function(form) {
  754.     var elements = Form.getElements(form);
  755.     for (var i = 0; i < elements.length; i++) {
  756.       var element = elements[i];
  757.       element.disabled = '';
  758.     }
  759.   },
  760.   focusFirstElement: function(form) {
  761.     var form = $(form);
  762.     var elements = Form.getElements(form);
  763.     for (var i = 0; i < elements.length; i++) {
  764.       var element = elements[i];
  765.       if (element.type != 'hidden' && !element.disabled) {
  766.         Field.activate(element);
  767.         break;
  768.       }
  769.     }
  770.   },
  771.   reset: function(form) {
  772.     $(form).reset();
  773.   }
  774. }
  775. Form.Element = {
  776.   serialize: function(element) {
  777.     var element = $(element);
  778.     var method = element.tagName.toLowerCase();
  779.     var parameter = Form.Element.Serializers[method](element);
  780.     
  781.     if (parameter)
  782.       return encodeURIComponent(parameter[0]) + '=' + 
  783.         encodeURIComponent(parameter[1]);                   
  784.   },
  785.   
  786.   getValue: function(element) {
  787.     var element = $(element);
  788.     var method = element.tagName.toLowerCase();
  789.     var parameter = Form.Element.Serializers[method](element);
  790.     
  791.     if (parameter) 
  792.       return parameter[1];
  793.   }
  794. }
  795. Form.Element.Serializers = {
  796.   input: function(element) {
  797.     switch (element.type.toLowerCase()) {
  798.       case 'submit':
  799.       case 'hidden':
  800.       case 'password':
  801.       case 'text':
  802.         return Form.Element.Serializers.textarea(element);
  803.       case 'checkbox':  
  804.       case 'radio':
  805.         return Form.Element.Serializers.inputSelector(element);
  806.     }
  807.     return false;
  808.   },
  809.   inputSelector: function(element) {
  810.     if (element.checked)
  811.       return [element.name, element.value];
  812.   },
  813.   textarea: function(element) {
  814.     return [element.name, element.value];
  815.   },
  816.   select: function(element) {
  817.     var value = '';
  818.     if (element.type == 'select-one') {
  819.       var index = element.selectedIndex;
  820.       if (index >= 0)
  821.         value = element.options[index].value || element.options[index].text;
  822.     } else {
  823.       value = new Array();
  824.       for (var i = 0; i < element.length; i++) {
  825.         var opt = element.options[i];
  826.         if (opt.selected)
  827.           value.push(opt.value || opt.text);
  828.       }
  829.     }
  830.     return [element.name, value];
  831.   }
  832. }
  833. /*--------------------------------------------------------------------------*/
  834. var $F = Form.Element.getValue;
  835. /*--------------------------------------------------------------------------*/
  836. Abstract.TimedObserver = function() {}
  837. Abstract.TimedObserver.prototype = {
  838.   initialize: function(element, frequency, callback) {
  839.     this.frequency = frequency;
  840.     this.element   = $(element);
  841.     this.callback  = callback;
  842.     
  843.     this.lastValue = this.getValue();
  844.     this.registerCallback();
  845.   },
  846.   
  847.   registerCallback: function() {
  848.     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  849.   },
  850.   
  851.   onTimerEvent: function() {
  852.     var value = this.getValue();
  853.     if (this.lastValue != value) {
  854.       this.callback(this.element, value);
  855.       this.lastValue = value;
  856.     }
  857.   }
  858. }
  859. Form.Element.Observer = Class.create();
  860. Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  861.   getValue: function() {
  862.     return Form.Element.getValue(this.element);
  863.   }
  864. });
  865. Form.Observer = Class.create();
  866. Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  867.   getValue: function() {
  868.     return Form.serialize(this.element);
  869.   }
  870. });
  871. /*--------------------------------------------------------------------------*/
  872. Abstract.EventObserver = function() {}
  873. Abstract.EventObserver.prototype = {
  874.   initialize: function(element, callback) {
  875.     this.element  = $(element);
  876.     this.callback = callback;
  877.     
  878.     this.lastValue = this.getValue();
  879.     if (this.element.tagName.toLowerCase() == 'form')
  880.       this.registerFormCallbacks();
  881.     else
  882.       this.registerCallback(this.element);
  883.   },
  884.   
  885.   onElementEvent: function() {
  886.     var value = this.getValue();
  887.     if (this.lastValue != value) {
  888.       this.callback(this.element, value);
  889.       this.lastValue = value;
  890.     }
  891.   },
  892.   
  893.   registerFormCallbacks: function() {
  894.     var elements = Form.getElements(this.element);
  895.     for (var i = 0; i < elements.length; i++)
  896.       this.registerCallback(elements[i]);
  897.   },
  898.   
  899.   registerCallback: function(element) {
  900.     if (element.type) {
  901.       switch (element.type.toLowerCase()) {
  902.         case 'checkbox':  
  903.         case 'radio':
  904.           element.target = this;
  905.           element.prev_onclick = element.onclick || Prototype.emptyFunction;
  906.           element.onclick = function() {
  907.             this.prev_onclick(); 
  908.             this.target.onElementEvent();
  909.           }
  910.           break;
  911.         case 'password':
  912.         case 'text':
  913.         case 'textarea':
  914.         case 'select-one':
  915.         case 'select-multiple':
  916.           element.target = this;
  917.           element.prev_onchange = element.onchange || Prototype.emptyFunction;
  918.           element.onchange = function() {
  919.             this.prev_onchange(); 
  920.             this.target.onElementEvent();
  921.           }
  922.           break;
  923.       }
  924.     }    
  925.   }
  926. }
  927. Form.Element.EventObserver = Class.create();
  928. Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  929.   getValue: function() {
  930.     return Form.Element.getValue(this.element);
  931.   }
  932. });
  933. Form.EventObserver = Class.create();
  934. Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  935.   getValue: function() {
  936.     return Form.serialize(this.element);
  937.   }
  938. });
  939. if (!window.Event) {
  940.   var Event = new Object();
  941. }
  942. Object.extend(Event, {
  943.   KEY_BACKSPACE: 8,
  944.   KEY_TAB:       9,
  945.   KEY_RETURN:   13,
  946.   KEY_ESC:      27,
  947.   KEY_LEFT:     37,
  948.   KEY_UP:       38,
  949.   KEY_RIGHT:    39,
  950.   KEY_DOWN:     40,
  951.   KEY_DELETE:   46,
  952.   element: function(event) {
  953.     return event.target || event.srcElement;
  954.   },
  955.   isLeftClick: function(event) {
  956.     return (((event.which) && (event.which == 1)) ||
  957.             ((event.button) && (event.button == 1)));
  958.   },
  959.   pointerX: function(event) {
  960.     return event.pageX || (event.clientX + 
  961.       (document.documentElement.scrollLeft || document.body.scrollLeft));
  962.   },
  963.   pointerY: function(event) {
  964.     return event.pageY || (event.clientY + 
  965.       (document.documentElement.scrollTop || document.body.scrollTop));
  966.   },
  967.   stop: function(event) {
  968.     if (event.preventDefault) { 
  969.       event.preventDefault(); 
  970.       event.stopPropagation(); 
  971.     } else {
  972.       event.returnValue = false;
  973.     }
  974.   },
  975.   // find the first node with the given tagName, starting from the
  976.   // node the event was triggered on; traverses the DOM upwards
  977.   findElement: function(event, tagName) {
  978.     var element = Event.element(event);
  979.     while (element.parentNode && (!element.tagName ||
  980.         (element.tagName.toUpperCase() != tagName.toUpperCase())))
  981.       element = element.parentNode;
  982.     return element;
  983.   },
  984.   observers: false,
  985.   
  986.   _observeAndCache: function(element, name, observer, useCapture) {
  987.     if (!this.observers) this.observers = [];
  988.     if (element.addEventListener) {
  989.       this.observers.push([element, name, observer, useCapture]);
  990.       element.addEventListener(name, observer, useCapture);
  991.     } else if (element.attachEvent) {
  992.       this.observers.push([element, name, observer, useCapture]);
  993.       element.attachEvent('on' + name, observer);
  994.     }
  995.   },
  996.   
  997.   unloadCache: function() {
  998.     if (!Event.observers) return;
  999.     for (var i = 0; i < Event.observers.length; i++) {
  1000.       Event.stopObserving.apply(this, Event.observers[i]);
  1001.       Event.observers[i][0] = null;
  1002.     }
  1003.     Event.observers = false;
  1004.   },
  1005.   observe: function(element, name, observer, useCapture) {
  1006.     var element = $(element);
  1007.     useCapture = useCapture || false;
  1008.     
  1009.     if (name == 'keypress' &&
  1010.         ((/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 
  1011.         || element.attachEvent))
  1012.       name = 'keydown';
  1013.     
  1014.     this._observeAndCache(element, name, observer, useCapture);
  1015.   },
  1016.   stopObserving: function(element, name, observer, useCapture) {
  1017.     var element = $(element);
  1018.     useCapture = useCapture || false;
  1019.     
  1020.     if (name == 'keypress' &&
  1021.         ((/Konqueror|Safari|KHTML/.test(navigator.userAgent)) 
  1022.         || element.detachEvent))
  1023.       name = 'keydown';
  1024.     
  1025.     if (element.removeEventListener) {
  1026.       element.removeEventListener(name, observer, useCapture);
  1027.     } else if (element.detachEvent) {
  1028.       element.detachEvent('on' + name, observer);
  1029.     }
  1030.   }
  1031. });
  1032. /* prevent memory leaks in IE */
  1033. Event.observe(window, 'unload', Event.unloadCache, false);
  1034. var Position = {
  1035.   // set to true if needed, warning: firefox performance problems
  1036.   // NOT neeeded for page scrolling, only if draggable contained in
  1037.   // scrollable elements
  1038.   includeScrollOffsets: false, 
  1039.   // must be called before calling withinIncludingScrolloffset, every time the
  1040.   // page is scrolled
  1041.   prepare: function() {
  1042.     this.deltaX =  window.pageXOffset 
  1043.                 || document.documentElement.scrollLeft 
  1044.                 || document.body.scrollLeft 
  1045.                 || 0;
  1046.     this.deltaY =  window.pageYOffset 
  1047.                 || document.documentElement.scrollTop 
  1048.                 || document.body.scrollTop 
  1049.                 || 0;
  1050.   },
  1051.   realOffset: function(element) {
  1052.     var valueT = 0, valueL = 0;
  1053.     do {
  1054.       valueT += element.scrollTop  || 0;
  1055.       valueL += element.scrollLeft || 0; 
  1056.       element = element.parentNode;
  1057.     } while (element);
  1058.     return [valueL, valueT];
  1059.   },
  1060.   cumulativeOffset: function(element) {
  1061.     var valueT = 0, valueL = 0;
  1062.     do {
  1063.       valueT += element.offsetTop  || 0;
  1064.       valueL += element.offsetLeft || 0;
  1065.       element = element.offsetParent;
  1066.     } while (element);
  1067.     return [valueL, valueT];
  1068.   },
  1069.   // caches x/y coordinate pair to use with overlap
  1070.   within: function(element, x, y) {
  1071.     if (this.includeScrollOffsets)
  1072.       return this.withinIncludingScrolloffsets(element, x, y);
  1073.     this.xcomp = x;
  1074.     this.ycomp = y;
  1075.     this.offset = this.cumulativeOffset(element);
  1076.     return (y >= this.offset[1] &&
  1077.             y <  this.offset[1] + element.offsetHeight &&
  1078.             x >= this.offset[0] && 
  1079.             x <  this.offset[0] + element.offsetWidth);
  1080.   },
  1081.   withinIncludingScrolloffsets: function(element, x, y) {
  1082.     var offsetcache = this.realOffset(element);
  1083.     this.xcomp = x + offsetcache[0] - this.deltaX;
  1084.     this.ycomp = y + offsetcache[1] - this.deltaY;
  1085.     this.offset = this.cumulativeOffset(element);
  1086.     return (this.ycomp >= this.offset[1] &&
  1087.             this.ycomp <  this.offset[1] + element.offsetHeight &&
  1088.             this.xcomp >= this.offset[0] && 
  1089.             this.xcomp <  this.offset[0] + element.offsetWidth);
  1090.   },
  1091.   // within must be called directly before
  1092.   overlap: function(mode, element) {  
  1093.     if (!mode) return 0;  
  1094.     if (mode == 'vertical') 
  1095.       return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 
  1096.         element.offsetHeight;
  1097.     if (mode == 'horizontal')
  1098.       return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 
  1099.         element.offsetWidth;
  1100.   },
  1101.   clone: function(source, target) {
  1102.     source = $(source);
  1103.     target = $(target);
  1104.     target.style.position = 'absolute';
  1105.     var offsets = this.cumulativeOffset(source);
  1106.     target.style.top    = offsets[1] + 'px';
  1107.     target.style.left   = offsets[0] + 'px';
  1108.     target.style.width  = source.offsetWidth + 'px';
  1109.     target.style.height = source.offsetHeight + 'px';
  1110.   }
  1111. }