prototype.js
Upload User: qxmc52
Upload Date: 2015-01-24
Package Size: 2876k
Code Size: 27k
Category:

.net

Development Platform:

ASP/ASPX

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