/[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

Annotation of /Webpacus/root/js/prototype.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 203 - (hide annotations)
Fri Dec 2 23:01:25 2005 UTC (18 years, 5 months ago) by dpavlin
File MIME type: application/javascript
File size: 47156 byte(s)
 r11427@llin:  dpavlin | 2005-12-02 23:58:03 +0100
 huge update: new upstream HTML::Prototype and handling of Ajax.Autocompleter mode: enter
 now *ALWAYS* trigger search, while accepting suggestions is made using tab.
 Also, list doesn't wrap. [0.12]
 

1 dpavlin 203 /* Prototype JavaScript framework, version 1.4.0_rc4
2 dpavlin 83 * (c) 2005 Sam Stephenson <sam@conio.net>
3     *
4     * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5 dpavlin 203 * against the source tree, available from the Prototype darcs repository.
6 dpavlin 83 *
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    
13     var Prototype = {
14 dpavlin 203 Version: '1.4.0_rc4',
15     ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
16    
17     emptyFunction: function() {},
18     K: function(x) {return x}
19 dpavlin 83 }
20    
21     var Class = {
22     create: function() {
23 dpavlin 203 return function() {
24 dpavlin 83 this.initialize.apply(this, arguments);
25     }
26     }
27     }
28    
29     var Abstract = new Object();
30    
31     Object.extend = function(destination, source) {
32     for (property in source) {
33     destination[property] = source[property];
34     }
35     return destination;
36     }
37    
38 dpavlin 203 Object.inspect = function(object) {
39     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 dpavlin 83 }
48    
49     Function.prototype.bind = function(object) {
50     var __method = this;
51     return function() {
52 dpavlin 203 return __method.apply(object, arguments);
53 dpavlin 83 }
54     }
55    
56     Function.prototype.bindAsEventListener = function(object) {
57     var __method = this;
58     return function(event) {
59 dpavlin 203 return __method.call(object, event || window.event);
60 dpavlin 83 }
61     }
62    
63 dpavlin 203 Object.extend(Number.prototype, {
64     toColorPart: function() {
65     var digits = this.toString(16);
66     if (this < 16) return '0' + digits;
67     return digits;
68     },
69 dpavlin 83
70 dpavlin 203 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 dpavlin 83 var Try = {
81     these: function() {
82     var returnValue;
83    
84     for (var i = 0; i < arguments.length; i++) {
85     var lambda = arguments[i];
86     try {
87     returnValue = lambda();
88     break;
89     } catch (e) {}
90     }
91    
92     return returnValue;
93     }
94     }
95    
96     /*--------------------------------------------------------------------------*/
97    
98     var PeriodicalExecuter = Class.create();
99     PeriodicalExecuter.prototype = {
100     initialize: function(callback, frequency) {
101     this.callback = callback;
102     this.frequency = frequency;
103     this.currentlyExecuting = false;
104    
105     this.registerCallback();
106     },
107    
108     registerCallback: function() {
109     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
110     },
111    
112     onTimerEvent: function() {
113     if (!this.currentlyExecuting) {
114 dpavlin 203 try {
115 dpavlin 83 this.currentlyExecuting = true;
116 dpavlin 203 this.callback();
117     } finally {
118 dpavlin 83 this.currentlyExecuting = false;
119     }
120     }
121     }
122     }
123    
124     /*--------------------------------------------------------------------------*/
125    
126     function $() {
127     var elements = new Array();
128    
129     for (var i = 0; i < arguments.length; i++) {
130     var element = arguments[i];
131     if (typeof element == 'string')
132     element = document.getElementById(element);
133    
134 dpavlin 203 if (arguments.length == 1)
135 dpavlin 83 return element;
136    
137     elements.push(element);
138     }
139    
140     return elements;
141     }
142 dpavlin 203 Object.extend(String.prototype, {
143     stripTags: function() {
144     return this.replace(/<\/?[^>]+>/gi, '');
145     },
146 dpavlin 83
147 dpavlin 203 stripScripts: function() {
148     return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
149     },
150 dpavlin 83
151 dpavlin 203 extractScripts: function() {
152     var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
153     var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
154     return (this.match(matchAll) || []).map(function(scriptTag) {
155     return (scriptTag.match(matchOne) || ['', ''])[1];
156     });
157     },
158 dpavlin 83
159 dpavlin 203 evalScripts: function() {
160     return this.extractScripts().map(eval);
161 dpavlin 83 },
162    
163     escapeHTML: function() {
164     var div = document.createElement('div');
165     var text = document.createTextNode(this);
166     div.appendChild(text);
167     return div.innerHTML;
168     },
169    
170     unescapeHTML: function() {
171     var div = document.createElement('div');
172     div.innerHTML = this.stripTags();
173 dpavlin 203 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 dpavlin 83 }
208     });
209    
210 dpavlin 203 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 dpavlin 83 var Ajax = {
541     getTransport: function() {
542     return Try.these(
543     function() {return new ActiveXObject('Msxml2.XMLHTTP')},
544     function() {return new ActiveXObject('Microsoft.XMLHTTP')},
545     function() {return new XMLHttpRequest()}
546     ) || false;
547 dpavlin 203 },
548    
549     activeRequestCount: 0
550 dpavlin 83 }
551    
552 dpavlin 203 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 dpavlin 83 Ajax.Base = function() {};
592     Ajax.Base.prototype = {
593     setOptions: function(options) {
594     this.options = {
595     method: 'post',
596     asynchronous: true,
597     parameters: ''
598 dpavlin 203 }
599     Object.extend(this.options, options || {});
600 dpavlin 83 },
601    
602     responseIsSuccess: function() {
603     return this.transport.status == undefined
604 dpavlin 203 || this.transport.status == 0
605 dpavlin 83 || (this.transport.status >= 200 && this.transport.status < 300);
606     },
607    
608     responseIsFailure: function() {
609     return !this.responseIsSuccess();
610     }
611     }
612    
613     Ajax.Request = Class.create();
614 dpavlin 203 Ajax.Request.Events =
615 dpavlin 83 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
616    
617 dpavlin 203 Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
618 dpavlin 83 initialize: function(url, options) {
619     this.transport = Ajax.getTransport();
620     this.setOptions(options);
621     this.request(url);
622     },
623    
624     request: function(url) {
625     var parameters = this.options.parameters || '';
626     if (parameters.length > 0) parameters += '&_=';
627    
628     try {
629 dpavlin 203 this.url = url;
630     if (this.options.method == 'get' && parameters.length > 0)
631     this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
632 dpavlin 83
633 dpavlin 203 Ajax.Responders.dispatch('onCreate', this, this.transport);
634    
635     this.transport.open(this.options.method, this.url,
636 dpavlin 83 this.options.asynchronous);
637    
638     if (this.options.asynchronous) {
639     this.transport.onreadystatechange = this.onStateChange.bind(this);
640     setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
641     }
642    
643     this.setRequestHeaders();
644    
645     var body = this.options.postBody ? this.options.postBody : parameters;
646     this.transport.send(this.options.method == 'post' ? body : null);
647    
648     } catch (e) {
649 dpavlin 203 this.dispatchException(e);
650 dpavlin 83 }
651     },
652    
653     setRequestHeaders: function() {
654 dpavlin 203 var requestHeaders =
655 dpavlin 83 ['X-Requested-With', 'XMLHttpRequest',
656     'X-Prototype-Version', Prototype.Version];
657    
658     if (this.options.method == 'post') {
659 dpavlin 203 requestHeaders.push('Content-type',
660 dpavlin 83 'application/x-www-form-urlencoded');
661    
662     /* Force "Connection: close" for Mozilla browsers to work around
663     * a bug where XMLHttpReqeuest sends an incorrect Content-length
664 dpavlin 203 * header. See Mozilla Bugzilla #246651.
665 dpavlin 83 */
666     if (this.transport.overrideMimeType)
667     requestHeaders.push('Connection', 'close');
668     }
669    
670     if (this.options.requestHeaders)
671     requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
672    
673     for (var i = 0; i < requestHeaders.length; i += 2)
674     this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
675     },
676    
677     onStateChange: function() {
678     var readyState = this.transport.readyState;
679     if (readyState != 1)
680     this.respondToReadyState(this.transport.readyState);
681     },
682    
683 dpavlin 203 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 dpavlin 83 respondToReadyState: function(readyState) {
704     var event = Ajax.Request.Events[readyState];
705 dpavlin 203 var transport = this.transport, json = this.evalJSON();
706 dpavlin 83
707 dpavlin 203 if (event == 'Complete') {
708     try {
709     (this.options['on' + this.transport.status]
710     || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
711     || Prototype.emptyFunction)(transport, json);
712     } catch (e) {
713     this.dispatchException(e);
714     }
715 dpavlin 83
716 dpavlin 203 if ((this.header('Content-type') || '').match(/^text\/javascript/i))
717     this.evalResponse();
718     }
719 dpavlin 83
720 dpavlin 203 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 dpavlin 83 /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
728     if (event == 'Complete')
729     this.transport.onreadystatechange = Prototype.emptyFunction;
730 dpavlin 203 },
731    
732     dispatchException: function(exception) {
733     (this.options.onException || Prototype.emptyFunction)(this, exception);
734     Ajax.Responders.dispatch('onException', this, exception);
735 dpavlin 83 }
736     });
737    
738     Ajax.Updater = Class.create();
739    
740 dpavlin 203 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
741 dpavlin 83 initialize: function(container, url, options) {
742     this.containers = {
743     success: container.success ? $(container.success) : $(container),
744     failure: container.failure ? $(container.failure) :
745     (container.success ? null : $(container))
746     }
747    
748     this.transport = Ajax.getTransport();
749     this.setOptions(options);
750    
751     var onComplete = this.options.onComplete || Prototype.emptyFunction;
752 dpavlin 203 this.options.onComplete = (function(transport, object) {
753 dpavlin 83 this.updateContent();
754 dpavlin 203 onComplete(transport, object);
755 dpavlin 83 }).bind(this);
756    
757     this.request(url);
758     },
759    
760     updateContent: function() {
761     var receiver = this.responseIsSuccess() ?
762     this.containers.success : this.containers.failure;
763 dpavlin 203 var response = this.transport.responseText;
764 dpavlin 83
765 dpavlin 203 if (!this.options.evalScripts)
766     response = response.stripScripts();
767 dpavlin 83
768     if (receiver) {
769     if (this.options.insertion) {
770     new this.options.insertion(receiver, response);
771     } else {
772 dpavlin 203 Element.update(receiver, response);
773 dpavlin 83 }
774     }
775    
776     if (this.responseIsSuccess()) {
777     if (this.onComplete)
778 dpavlin 203 setTimeout(this.onComplete.bind(this), 10);
779 dpavlin 83 }
780     }
781     });
782    
783     Ajax.PeriodicalUpdater = Class.create();
784 dpavlin 203 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
785 dpavlin 83 initialize: function(container, url, options) {
786     this.setOptions(options);
787     this.onComplete = this.options.onComplete;
788    
789     this.frequency = (this.options.frequency || 2);
790 dpavlin 203 this.decay = (this.options.decay || 1);
791 dpavlin 83
792     this.updater = {};
793     this.container = container;
794     this.url = url;
795    
796     this.start();
797     },
798    
799     start: function() {
800     this.options.onComplete = this.updateComplete.bind(this);
801     this.onTimerEvent();
802     },
803    
804     stop: function() {
805     this.updater.onComplete = undefined;
806     clearTimeout(this.timer);
807 dpavlin 203 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
808 dpavlin 83 },
809    
810     updateComplete: function(request) {
811     if (this.options.decay) {
812 dpavlin 203 this.decay = (request.responseText == this.lastText ?
813 dpavlin 83 this.decay * this.options.decay : 1);
814    
815     this.lastText = request.responseText;
816     }
817 dpavlin 203 this.timer = setTimeout(this.onTimerEvent.bind(this),
818 dpavlin 83 this.decay * this.frequency * 1000);
819     },
820    
821     onTimerEvent: function() {
822     this.updater = new Ajax.Updater(this.container, this.url, this.options);
823     }
824     });
825 dpavlin 203 document.getElementsByClassName = function(className, parentElement) {
826     var children = ($(parentElement) || document.body).getElementsByTagName('*');
827     return $A(children).inject([], function(elements, child) {
828     if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
829     elements.push(child);
830     return elements;
831     });
832 dpavlin 83 }
833    
834     /*--------------------------------------------------------------------------*/
835    
836     if (!window.Element) {
837     var Element = new Object();
838     }
839    
840     Object.extend(Element, {
841 dpavlin 203 visible: function(element) {
842     return $(element).style.display != 'none';
843     },
844    
845 dpavlin 83 toggle: function() {
846     for (var i = 0; i < arguments.length; i++) {
847     var element = $(arguments[i]);
848 dpavlin 203 Element[Element.visible(element) ? 'hide' : 'show'](element);
849 dpavlin 83 }
850     },
851    
852     hide: function() {
853     for (var i = 0; i < arguments.length; i++) {
854     var element = $(arguments[i]);
855     element.style.display = 'none';
856     }
857     },
858    
859     show: function() {
860     for (var i = 0; i < arguments.length; i++) {
861     var element = $(arguments[i]);
862     element.style.display = '';
863     }
864     },
865    
866     remove: function(element) {
867     element = $(element);
868     element.parentNode.removeChild(element);
869     },
870 dpavlin 203
871     update: function(element, html) {
872     $(element).innerHTML = html.stripScripts();
873     setTimeout(function() {html.evalScripts()}, 10);
874     },
875    
876 dpavlin 83 getHeight: function(element) {
877     element = $(element);
878 dpavlin 203 return element.offsetHeight;
879 dpavlin 83 },
880    
881 dpavlin 203 classNames: function(element) {
882     return new Element.ClassNames(element);
883     },
884    
885 dpavlin 83 hasClassName: function(element, className) {
886 dpavlin 203 if (!(element = $(element))) return;
887     return Element.classNames(element).include(className);
888 dpavlin 83 },
889    
890     addClassName: function(element, className) {
891 dpavlin 203 if (!(element = $(element))) return;
892     return Element.classNames(element).add(className);
893 dpavlin 83 },
894    
895     removeClassName: function(element, className) {
896 dpavlin 203 if (!(element = $(element))) return;
897     return Element.classNames(element).remove(className);
898 dpavlin 83 },
899 dpavlin 203
900 dpavlin 83 // removes whitespace-only text node children
901     cleanWhitespace: function(element) {
902 dpavlin 203 element = $(element);
903 dpavlin 83 for (var i = 0; i < element.childNodes.length; i++) {
904     var node = element.childNodes[i];
905 dpavlin 203 if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
906 dpavlin 83 Element.remove(node);
907     }
908 dpavlin 203 },
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 dpavlin 83 }
1007     });
1008    
1009     var Toggle = new Object();
1010     Toggle.display = Element.toggle;
1011    
1012     /*--------------------------------------------------------------------------*/
1013    
1014     Abstract.Insertion = function(adjacency) {
1015     this.adjacency = adjacency;
1016     }
1017    
1018     Abstract.Insertion.prototype = {
1019     initialize: function(element, content) {
1020     this.element = $(element);
1021 dpavlin 203 this.content = content.stripScripts();
1022    
1023 dpavlin 83 if (this.adjacency && this.element.insertAdjacentHTML) {
1024 dpavlin 203 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 dpavlin 83 } else {
1034     this.range = this.element.ownerDocument.createRange();
1035     if (this.initializeRange) this.initializeRange();
1036 dpavlin 203 this.insertContent([this.range.createContextualFragment(this.content)]);
1037 dpavlin 83 }
1038 dpavlin 203
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 dpavlin 83 }
1047     }
1048    
1049     var Insertion = new Object();
1050    
1051     Insertion.Before = Class.create();
1052 dpavlin 203 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1053 dpavlin 83 initializeRange: function() {
1054     this.range.setStartBefore(this.element);
1055     },
1056 dpavlin 203
1057     insertContent: function(fragments) {
1058     fragments.each((function(fragment) {
1059     this.element.parentNode.insertBefore(fragment, this.element);
1060     }).bind(this));
1061 dpavlin 83 }
1062     });
1063    
1064     Insertion.Top = Class.create();
1065 dpavlin 203 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1066 dpavlin 83 initializeRange: function() {
1067     this.range.selectNodeContents(this.element);
1068     this.range.collapse(true);
1069     },
1070 dpavlin 203
1071     insertContent: function(fragments) {
1072     fragments.reverse(false).each((function(fragment) {
1073     this.element.insertBefore(fragment, this.element.firstChild);
1074     }).bind(this));
1075 dpavlin 83 }
1076     });
1077    
1078     Insertion.Bottom = Class.create();
1079 dpavlin 203 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1080 dpavlin 83 initializeRange: function() {
1081     this.range.selectNodeContents(this.element);
1082     this.range.collapse(this.element);
1083     },
1084 dpavlin 203
1085     insertContent: function(fragments) {
1086     fragments.each((function(fragment) {
1087     this.element.appendChild(fragment);
1088     }).bind(this));
1089 dpavlin 83 }
1090     });
1091    
1092     Insertion.After = Class.create();
1093 dpavlin 203 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1094 dpavlin 83 initializeRange: function() {
1095     this.range.setStartAfter(this.element);
1096     },
1097 dpavlin 203
1098     insertContent: function(fragments) {
1099     fragments.each((function(fragment) {
1100     this.element.parentNode.insertBefore(fragment,
1101     this.element.nextSibling);
1102     }).bind(this));
1103 dpavlin 83 }
1104     });
1105    
1106 dpavlin 203 /*--------------------------------------------------------------------------*/
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 dpavlin 83 var Field = {
1143     clear: function() {
1144     for (var i = 0; i < arguments.length; i++)
1145     $(arguments[i]).value = '';
1146     },
1147    
1148     focus: function(element) {
1149     $(element).focus();
1150     },
1151 dpavlin 203
1152 dpavlin 83 present: function() {
1153     for (var i = 0; i < arguments.length; i++)
1154     if ($(arguments[i]).value == '') return false;
1155     return true;
1156     },
1157 dpavlin 203
1158 dpavlin 83 select: function(element) {
1159     $(element).select();
1160     },
1161 dpavlin 203
1162 dpavlin 83 activate: function(element) {
1163 dpavlin 203 element = $(element);
1164     element.focus();
1165     if (element.select)
1166     element.select();
1167 dpavlin 83 }
1168     }
1169    
1170     /*--------------------------------------------------------------------------*/
1171    
1172     var Form = {
1173     serialize: function(form) {
1174     var elements = Form.getElements($(form));
1175     var queryComponents = new Array();
1176 dpavlin 203
1177 dpavlin 83 for (var i = 0; i < elements.length; i++) {
1178     var queryComponent = Form.Element.serialize(elements[i]);
1179     if (queryComponent)
1180     queryComponents.push(queryComponent);
1181     }
1182 dpavlin 203
1183 dpavlin 83 return queryComponents.join('&');
1184     },
1185 dpavlin 203
1186 dpavlin 83 getElements: function(form) {
1187 dpavlin 203 form = $(form);
1188 dpavlin 83 var elements = new Array();
1189    
1190     for (tagName in Form.Element.Serializers) {
1191     var tagElements = form.getElementsByTagName(tagName);
1192     for (var j = 0; j < tagElements.length; j++)
1193     elements.push(tagElements[j]);
1194     }
1195     return elements;
1196     },
1197 dpavlin 203
1198 dpavlin 83 getInputs: function(form, typeName, name) {
1199 dpavlin 203 form = $(form);
1200 dpavlin 83 var inputs = form.getElementsByTagName('input');
1201 dpavlin 203
1202 dpavlin 83 if (!typeName && !name)
1203     return inputs;
1204 dpavlin 203
1205 dpavlin 83 var matchingInputs = new Array();
1206     for (var i = 0; i < inputs.length; i++) {
1207     var input = inputs[i];
1208     if ((typeName && input.type != typeName) ||
1209 dpavlin 203 (name && input.name != name))
1210 dpavlin 83 continue;
1211     matchingInputs.push(input);
1212     }
1213    
1214     return matchingInputs;
1215     },
1216    
1217     disable: function(form) {
1218     var elements = Form.getElements(form);
1219     for (var i = 0; i < elements.length; i++) {
1220     var element = elements[i];
1221     element.blur();
1222     element.disabled = 'true';
1223     }
1224     },
1225    
1226     enable: function(form) {
1227     var elements = Form.getElements(form);
1228     for (var i = 0; i < elements.length; i++) {
1229     var element = elements[i];
1230     element.disabled = '';
1231     }
1232     },
1233    
1234 dpavlin 203 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 dpavlin 83 focusFirstElement: function(form) {
1242 dpavlin 203 Field.activate(Form.findFirstElement(form));
1243 dpavlin 83 },
1244    
1245     reset: function(form) {
1246     $(form).reset();
1247     }
1248     }
1249    
1250     Form.Element = {
1251     serialize: function(element) {
1252 dpavlin 203 element = $(element);
1253 dpavlin 83 var method = element.tagName.toLowerCase();
1254     var parameter = Form.Element.Serializers[method](element);
1255 dpavlin 203
1256 dpavlin 83 if (parameter)
1257 dpavlin 203 return encodeURIComponent(parameter[0]) + '=' +
1258     encodeURIComponent(parameter[1]);
1259 dpavlin 83 },
1260 dpavlin 203
1261 dpavlin 83 getValue: function(element) {
1262 dpavlin 203 element = $(element);
1263 dpavlin 83 var method = element.tagName.toLowerCase();
1264     var parameter = Form.Element.Serializers[method](element);
1265 dpavlin 203
1266     if (parameter)
1267 dpavlin 83 return parameter[1];
1268     }
1269     }
1270    
1271     Form.Element.Serializers = {
1272     input: function(element) {
1273     switch (element.type.toLowerCase()) {
1274     case 'submit':
1275     case 'hidden':
1276     case 'password':
1277     case 'text':
1278     return Form.Element.Serializers.textarea(element);
1279 dpavlin 203 case 'checkbox':
1280 dpavlin 83 case 'radio':
1281     return Form.Element.Serializers.inputSelector(element);
1282     }
1283     return false;
1284     },
1285    
1286     inputSelector: function(element) {
1287     if (element.checked)
1288     return [element.name, element.value];
1289     },
1290    
1291     textarea: function(element) {
1292     return [element.name, element.value];
1293     },
1294    
1295     select: function(element) {
1296 dpavlin 203 return Form.Element.Serializers[element.type == 'select-one' ?
1297     'selectOne' : 'selectMany'](element);
1298     },
1299    
1300     selectOne: function(element) {
1301     var value = '', opt, index = element.selectedIndex;
1302     if (index >= 0) {
1303     opt = element.options[index];
1304     value = opt.value;
1305     if (!value && !('value' in opt))
1306     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 dpavlin 83 }
1321     }
1322     return [element.name, value];
1323     }
1324     }
1325    
1326     /*--------------------------------------------------------------------------*/
1327    
1328     var $F = Form.Element.getValue;
1329    
1330     /*--------------------------------------------------------------------------*/
1331    
1332     Abstract.TimedObserver = function() {}
1333     Abstract.TimedObserver.prototype = {
1334     initialize: function(element, frequency, callback) {
1335     this.frequency = frequency;
1336     this.element = $(element);
1337     this.callback = callback;
1338 dpavlin 203
1339 dpavlin 83 this.lastValue = this.getValue();
1340     this.registerCallback();
1341     },
1342 dpavlin 203
1343 dpavlin 83 registerCallback: function() {
1344     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1345     },
1346 dpavlin 203
1347 dpavlin 83 onTimerEvent: function() {
1348     var value = this.getValue();
1349     if (this.lastValue != value) {
1350     this.callback(this.element, value);
1351     this.lastValue = value;
1352     }
1353     }
1354     }
1355    
1356     Form.Element.Observer = Class.create();
1357 dpavlin 203 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1358 dpavlin 83 getValue: function() {
1359     return Form.Element.getValue(this.element);
1360     }
1361     });
1362    
1363     Form.Observer = Class.create();
1364 dpavlin 203 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1365 dpavlin 83 getValue: function() {
1366     return Form.serialize(this.element);
1367     }
1368     });
1369    
1370     /*--------------------------------------------------------------------------*/
1371    
1372     Abstract.EventObserver = function() {}
1373     Abstract.EventObserver.prototype = {
1374     initialize: function(element, callback) {
1375     this.element = $(element);
1376     this.callback = callback;
1377 dpavlin 203
1378 dpavlin 83 this.lastValue = this.getValue();
1379     if (this.element.tagName.toLowerCase() == 'form')
1380     this.registerFormCallbacks();
1381     else
1382     this.registerCallback(this.element);
1383     },
1384 dpavlin 203
1385 dpavlin 83 onElementEvent: function() {
1386     var value = this.getValue();
1387     if (this.lastValue != value) {
1388     this.callback(this.element, value);
1389     this.lastValue = value;
1390     }
1391     },
1392 dpavlin 203
1393 dpavlin 83 registerFormCallbacks: function() {
1394     var elements = Form.getElements(this.element);
1395     for (var i = 0; i < elements.length; i++)
1396     this.registerCallback(elements[i]);
1397     },
1398 dpavlin 203
1399 dpavlin 83 registerCallback: function(element) {
1400     if (element.type) {
1401     switch (element.type.toLowerCase()) {
1402 dpavlin 203 case 'checkbox':
1403 dpavlin 83 case 'radio':
1404 dpavlin 203 Event.observe(element, 'click', this.onElementEvent.bind(this));
1405 dpavlin 83 break;
1406     case 'password':
1407     case 'text':
1408     case 'textarea':
1409     case 'select-one':
1410     case 'select-multiple':
1411 dpavlin 203 Event.observe(element, 'change', this.onElementEvent.bind(this));
1412 dpavlin 83 break;
1413     }
1414 dpavlin 203 }
1415 dpavlin 83 }
1416     }
1417    
1418     Form.Element.EventObserver = Class.create();
1419 dpavlin 203 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1420 dpavlin 83 getValue: function() {
1421     return Form.Element.getValue(this.element);
1422     }
1423     });
1424    
1425     Form.EventObserver = Class.create();
1426 dpavlin 203 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1427 dpavlin 83 getValue: function() {
1428     return Form.serialize(this.element);
1429     }
1430     });
1431     if (!window.Event) {
1432     var Event = new Object();
1433     }
1434    
1435     Object.extend(Event, {
1436     KEY_BACKSPACE: 8,
1437     KEY_TAB: 9,
1438     KEY_RETURN: 13,
1439     KEY_ESC: 27,
1440     KEY_LEFT: 37,
1441     KEY_UP: 38,
1442     KEY_RIGHT: 39,
1443     KEY_DOWN: 40,
1444     KEY_DELETE: 46,
1445    
1446     element: function(event) {
1447     return event.target || event.srcElement;
1448     },
1449    
1450     isLeftClick: function(event) {
1451     return (((event.which) && (event.which == 1)) ||
1452     ((event.button) && (event.button == 1)));
1453     },
1454    
1455     pointerX: function(event) {
1456 dpavlin 203 return event.pageX || (event.clientX +
1457 dpavlin 83 (document.documentElement.scrollLeft || document.body.scrollLeft));
1458     },
1459    
1460     pointerY: function(event) {
1461 dpavlin 203 return event.pageY || (event.clientY +
1462 dpavlin 83 (document.documentElement.scrollTop || document.body.scrollTop));
1463     },
1464    
1465     stop: function(event) {
1466 dpavlin 203 if (event.preventDefault) {
1467     event.preventDefault();
1468     event.stopPropagation();
1469 dpavlin 83 } else {
1470     event.returnValue = false;
1471 dpavlin 203 event.cancelBubble = true;
1472 dpavlin 83 }
1473     },
1474    
1475     // find the first node with the given tagName, starting from the
1476     // node the event was triggered on; traverses the DOM upwards
1477     findElement: function(event, tagName) {
1478     var element = Event.element(event);
1479     while (element.parentNode && (!element.tagName ||
1480     (element.tagName.toUpperCase() != tagName.toUpperCase())))
1481     element = element.parentNode;
1482     return element;
1483     },
1484    
1485     observers: false,
1486 dpavlin 203
1487 dpavlin 83 _observeAndCache: function(element, name, observer, useCapture) {
1488     if (!this.observers) this.observers = [];
1489     if (element.addEventListener) {
1490     this.observers.push([element, name, observer, useCapture]);
1491     element.addEventListener(name, observer, useCapture);
1492     } else if (element.attachEvent) {
1493     this.observers.push([element, name, observer, useCapture]);
1494     element.attachEvent('on' + name, observer);
1495     }
1496     },
1497 dpavlin 203
1498 dpavlin 83 unloadCache: function() {
1499     if (!Event.observers) return;
1500     for (var i = 0; i < Event.observers.length; i++) {
1501     Event.stopObserving.apply(this, Event.observers[i]);
1502     Event.observers[i][0] = null;
1503     }
1504     Event.observers = false;
1505     },
1506    
1507     observe: function(element, name, observer, useCapture) {
1508     var element = $(element);
1509     useCapture = useCapture || false;
1510 dpavlin 203
1511 dpavlin 83 if (name == 'keypress' &&
1512 dpavlin 203 (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1513 dpavlin 83 || element.attachEvent))
1514     name = 'keydown';
1515 dpavlin 203
1516 dpavlin 83 this._observeAndCache(element, name, observer, useCapture);
1517     },
1518    
1519     stopObserving: function(element, name, observer, useCapture) {
1520     var element = $(element);
1521     useCapture = useCapture || false;
1522 dpavlin 203
1523 dpavlin 83 if (name == 'keypress' &&
1524 dpavlin 203 (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1525 dpavlin 83 || element.detachEvent))
1526     name = 'keydown';
1527 dpavlin 203
1528 dpavlin 83 if (element.removeEventListener) {
1529     element.removeEventListener(name, observer, useCapture);
1530     } else if (element.detachEvent) {
1531     element.detachEvent('on' + name, observer);
1532     }
1533     }
1534     });
1535    
1536     /* prevent memory leaks in IE */
1537     Event.observe(window, 'unload', Event.unloadCache, false);
1538     var Position = {
1539     // set to true if needed, warning: firefox performance problems
1540     // NOT neeeded for page scrolling, only if draggable contained in
1541     // scrollable elements
1542 dpavlin 203 includeScrollOffsets: false,
1543 dpavlin 83
1544     // must be called before calling withinIncludingScrolloffset, every time the
1545     // page is scrolled
1546     prepare: function() {
1547 dpavlin 203 this.deltaX = window.pageXOffset
1548     || document.documentElement.scrollLeft
1549     || document.body.scrollLeft
1550 dpavlin 83 || 0;
1551 dpavlin 203 this.deltaY = window.pageYOffset
1552     || document.documentElement.scrollTop
1553     || document.body.scrollTop
1554 dpavlin 83 || 0;
1555     },
1556    
1557     realOffset: function(element) {
1558     var valueT = 0, valueL = 0;
1559     do {
1560     valueT += element.scrollTop || 0;
1561 dpavlin 203 valueL += element.scrollLeft || 0;
1562 dpavlin 83 element = element.parentNode;
1563     } while (element);
1564     return [valueL, valueT];
1565     },
1566    
1567     cumulativeOffset: function(element) {
1568     var valueT = 0, valueL = 0;
1569     do {
1570     valueT += element.offsetTop || 0;
1571     valueL += element.offsetLeft || 0;
1572     element = element.offsetParent;
1573     } while (element);
1574     return [valueL, valueT];
1575     },
1576    
1577 dpavlin 203 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 dpavlin 83 // caches x/y coordinate pair to use with overlap
1603     within: function(element, x, y) {
1604     if (this.includeScrollOffsets)
1605     return this.withinIncludingScrolloffsets(element, x, y);
1606     this.xcomp = x;
1607     this.ycomp = y;
1608     this.offset = this.cumulativeOffset(element);
1609    
1610     return (y >= this.offset[1] &&
1611     y < this.offset[1] + element.offsetHeight &&
1612 dpavlin 203 x >= this.offset[0] &&
1613 dpavlin 83 x < this.offset[0] + element.offsetWidth);
1614     },
1615    
1616     withinIncludingScrolloffsets: function(element, x, y) {
1617     var offsetcache = this.realOffset(element);
1618    
1619     this.xcomp = x + offsetcache[0] - this.deltaX;
1620     this.ycomp = y + offsetcache[1] - this.deltaY;
1621     this.offset = this.cumulativeOffset(element);
1622    
1623     return (this.ycomp >= this.offset[1] &&
1624     this.ycomp < this.offset[1] + element.offsetHeight &&
1625 dpavlin 203 this.xcomp >= this.offset[0] &&
1626 dpavlin 83 this.xcomp < this.offset[0] + element.offsetWidth);
1627     },
1628    
1629     // within must be called directly before
1630 dpavlin 203 overlap: function(mode, element) {
1631     if (!mode) return 0;
1632     if (mode == 'vertical')
1633     return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1634 dpavlin 83 element.offsetHeight;
1635     if (mode == 'horizontal')
1636 dpavlin 203 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1637 dpavlin 83 element.offsetWidth;
1638     },
1639    
1640     clone: function(source, target) {
1641     source = $(source);
1642     target = $(target);
1643     target.style.position = 'absolute';
1644     var offsets = this.cumulativeOffset(source);
1645     target.style.top = offsets[1] + 'px';
1646     target.style.left = offsets[0] + 'px';
1647     target.style.width = source.offsetWidth + 'px';
1648     target.style.height = source.offsetHeight + 'px';
1649 dpavlin 203 },
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 dpavlin 83 }
1749     }
1750 dpavlin 203
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     }

  ViewVC Help
Powered by ViewVC 1.1.26