/[webpac2]/Webpacus/root/js/prototype.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /Webpacus/root/js/prototype.js

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.83  
changed lines
  Added in v.203

  ViewVC Help
Powered by ViewVC 1.1.26