Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ] 

001 /*  Prototype JavaScript framework, version 1.5.0
002  *  (c) 2005-2007 Sam Stephenson
003  *
004  *  Prototype is freely distributable under the terms of an MIT-style license.
005  *  For details, see the Prototype web site: http://prototype.conio.net/
006  *
007 /*--------------------------------------------------------------------------*/
008 
009 var Prototype = {
010   Version: '1.5.0',
011   BrowserFeatures: {
012     XPath: !!document.evaluate
013   },
014 
015   ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
016   emptyFunction: function() {},
017   K: function(x) { return x }
018 }
019 
020 var Class = {
021   create: function() {
022     return function() {
023       this.initialize.apply(this, arguments);
024     }
025   }
026 }
027 
028 var Abstract = new Object();
029 
030 Object.extend = function(destination, source) {
031   for (var property in source) {
032     destination[property] = source[property];
033   }
034   return destination;
035 }
036 
037 Object.extend(Object, {
038   inspect: function(object) {
039     try {
040       if (object === undefined) return 'undefined';
041       if (object === null) return 'null';
042       return object.inspect ? object.inspect() : object.toString();
043     } catch (e) {
044       if (e instanceof RangeError) return '...';
045       throw e;
046     }
047   },
048 
049   keys: function(object) {
050     var keys = [];
051     for (var property in object)
052       keys.push(property);
053     return keys;
054   },
055 
056   values: function(object) {
057     var values = [];
058     for (var property in object)
059       values.push(object[property]);
060     return values;
061   },
062 
063   clone: function(object) {
064     return Object.extend({}, object);
065   }
066 });
067 
068 Function.prototype.bind = function() {
069   var __method = this, args = $A(arguments), object = args.shift();
070   return function() {
071     return __method.apply(object, args.concat($A(arguments)));
072   }
073 }
074 
075 Function.prototype.bindAsEventListener = function(object) {
076   var __method = this, args = $A(arguments), object = args.shift();
077   return function(event) {
078     return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
079   }
080 }
081 
082 Object.extend(Number.prototype, {
083   toColorPart: function() {
084     var digits = this.toString(16);
085     if (this < 16) return '0' + digits;
086     return digits;
087   },
088 
089   succ: function() {
090     return this + 1;
091   },
092 
093   times: function(iterator) {
094     $R(0, this, true).each(iterator);
095     return this;
096   }
097 });
098 
099 var Try = {
100   these: function() {
101     var returnValue;
102 
103     for (var i = 0, length = arguments.length; i < length; i++) {
104       var lambda = arguments[i];
105       try {
106         returnValue = lambda();
107         break;
108       } catch (e) {}
109     }
110 
111     return returnValue;
112   }
113 }
114 
115 /*--------------------------------------------------------------------------*/
116 
117 var PeriodicalExecuter = Class.create();
118 PeriodicalExecuter.prototype = {
119   initialize: function(callback, frequency) {
120     this.callback = callback;
121     this.frequency = frequency;
122     this.currentlyExecuting = false;
123 
124     this.registerCallback();
125   },
126 
127   registerCallback: function() {
128     this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
129   },
130 
131   stop: function() {
132     if (!this.timer) return;
133     clearInterval(this.timer);
134     this.timer = null;
135   },
136 
137   onTimerEvent: function() {
138     if (!this.currentlyExecuting) {
139       try {
140         this.currentlyExecuting = true;
141         this.callback(this);
142       } finally {
143         this.currentlyExecuting = false;
144       }
145     }
146   }
147 }
148 String.interpret = function(value){
149   return value == null ? '' : String(value);
150 }
151 
152 Object.extend(String.prototype, {
153   gsub: function(pattern, replacement) {
154     var result = '', source = this, match;
155     replacement = arguments.callee.prepareReplacement(replacement);
156 
157     while (source.length > 0) {
158       if (match = source.match(pattern)) {
159         result += source.slice(0, match.index);
160         result += String.interpret(replacement(match));
161         source  = source.slice(match.index + match[0].length);
162       } else {
163         result += source, source = '';
164       }
165     }
166     return result;
167   },
168 
169   sub: function(pattern, replacement, count) {
170     replacement = this.gsub.prepareReplacement(replacement);
171     count = count === undefined ? 1 : count;
172 
173     return this.gsub(pattern, function(match) {
174       if (--count < 0) return match[0];
175       return replacement(match);
176     });
177   },
178 
179   scan: function(pattern, iterator) {
180     this.gsub(pattern, iterator);
181     return this;
182   },
183 
184   truncate: function(length, truncation) {
185     length = length || 30;
186     truncation = truncation === undefined ? '...' : truncation;
187     return this.length > length ?
188       this.slice(0, length - truncation.length) + truncation : this;
189   },
190 
191   strip: function() {
192     return this.replace(/^\s+/, '').replace(/\s+$/, '');
193   },
194 
195   stripTags: function() {
196     return this.replace(/<\/?[^>]+>/gi, '');
197   },
198 
199   stripScripts: function() {
200     return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
201   },
202 
203   extractScripts: function() {
204     var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
205     var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
206     return (this.match(matchAll) || []).map(function(scriptTag) {
207       return (scriptTag.match(matchOne) || ['', ''])[1];
208     });
209   },
210 
211   evalScripts: function() {
212     return this.extractScripts().map(function(script) { return eval(script) });
213   },
214 
215   escapeHTML: function() {
216     var div = document.createElement('div');
217     var text = document.createTextNode(this);
218     div.appendChild(text);
219     return div.innerHTML;
220   },
221 
222   unescapeHTML: function() {
223     var div = document.createElement('div');
224     div.innerHTML = this.stripTags();
225     return div.childNodes[0] ? (div.childNodes.length > 1 ?
226       $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
227       div.childNodes[0].nodeValue) : '';
228   },
229 
230   toQueryParams: function(separator) {
231     var match = this.strip().match(/([^?#]*)(#.*)?$/);
232     if (!match) return {};
233 
234     return match[1].split(separator || '&').inject({}, function(hash, pair) {
235       if ((pair = pair.split('='))[0]) {
236         var name = decodeURIComponent(pair[0]);
237         var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
238 
239         if (hash[name] !== undefined) {
240           if (hash[name].constructor != Array)
241             hash[name] = [hash[name]];
242           if (value) hash[name].push(value);
243         }
244         else hash[name] = value;
245       }
246       return hash;
247     });
248   },
249 
250   toArray: function() {
251     return this.split('');
252   },
253 
254   succ: function() {
255     return this.slice(0, this.length - 1) +
256       String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
257   },
258 
259   camelize: function() {
260     var parts = this.split('-'), len = parts.length;
261     if (len == 1) return parts[0];
262 
263     var camelized = this.charAt(0) == '-'
264       ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
265       : parts[0];
266 
267     for (var i = 1; i < len; i++)
268       camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
269 
270     return camelized;
271   },
272 
273   capitalize: function(){
274     return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
275   },
276 
277   underscore: function() {
278     return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
279   },
280 
281   dasherize: function() {
282     return this.gsub(/_/,'-');
283   },
284 
285   inspect: function(useDoubleQuotes) {
286     var escapedString = this.replace(/\\/g, '\\\\');
287     if (useDoubleQuotes)
288       return '"' + escapedString.replace(/"/g, '\\"') + '"';
289     else
290       return "'" + escapedString.replace(/'/g, '\\\'') + "'";
291   }
292 });
293 
294 String.prototype.gsub.prepareReplacement = function(replacement) {
295   if (typeof replacement == 'function') return replacement;
296   var template = new Template(replacement);
297   return function(match) { return template.evaluate(match) };
298 }
299 
300 String.prototype.parseQuery = String.prototype.toQueryParams;
301 
302 var Template = Class.create();
303 Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
304 Template.prototype = {
305   initialize: function(template, pattern) {
306     this.template = template.toString();
307     this.pattern  = pattern || Template.Pattern;
308   },
309 
310   evaluate: function(object) {
311     return this.template.gsub(this.pattern, function(match) {
312       var before = match[1];
313       if (before == '\\') return match[2];
314       return before + String.interpret(object[match[3]]);
315     });
316   }
317 }
318 
319 var $break    = new Object();
320 var $continue = new Object();
321 
322 var Enumerable = {
323   each: function(iterator) {
324     var index = 0;
325     try {
326       this._each(function(value) {
327         try {
328           iterator(value, index++);
329         } catch (e) {
330           if (e != $continue) throw e;
331         }
332       });
333     } catch (e) {
334       if (e != $break) throw e;
335     }
336     return this;
337   },
338 
339   eachSlice: function(number, iterator) {
340     var index = -number, slices = [], array = this.toArray();
341     while ((index += number) < array.length)
342       slices.push(array.slice(index, index+number));
343     return slices.map(iterator);
344   },
345 
346   all: function(iterator) {
347     var result = true;
348     this.each(function(value, index) {
349       result = result && !!(iterator || Prototype.K)(value, index);
350       if (!result) throw $break;
351     });
352     return result;
353   },
354 
355   any: function(iterator) {
356     var result = false;
357     this.each(function(value, index) {
358       if (result = !!(iterator || Prototype.K)(value, index))
359         throw $break;
360     });
361     return result;
362   },
363 
364   collect: function(iterator) {
365     var results = [];
366     this.each(function(value, index) {
367       results.push((iterator || Prototype.K)(value, index));
368     });
369     return results;
370   },
371 
372   detect: function(iterator) {
373     var result;
374     this.each(function(value, index) {
375       if (iterator(value, index)) {
376         result = value;
377         throw $break;
378       }
379     });
380     return result;
381   },
382 
383   findAll: function(iterator) {
384     var results = [];
385     this.each(function(value, index) {
386       if (iterator(value, index))
387         results.push(value);
388     });
389     return results;
390   },
391 
392   grep: function(pattern, iterator) {
393     var results = [];
394     this.each(function(value, index) {
395       var stringValue = value.toString();
396       if (stringValue.match(pattern))
397         results.push((iterator || Prototype.K)(value, index));
398     })
399     return results;
400   },
401 
402   include: function(object) {
403     var found = false;
404     this.each(function(value) {
405       if (value == object) {
406         found = true;
407         throw $break;
408       }
409     });
410     return found;
411   },
412 
413   inGroupsOf: function(number, fillWith) {
414     fillWith = fillWith === undefined ? null : fillWith;
415     return this.eachSlice(number, function(slice) {
416       while(slice.length < number) slice.push(fillWith);
417       return slice;
418     });
419   },
420 
421   inject: function(memo, iterator) {
422     this.each(function(value, index) {
423       memo = iterator(memo, value, index);
424     });
425     return memo;
426   },
427 
428   invoke: function(method) {
429     var args = $A(arguments).slice(1);
430     return this.map(function(value) {
431       return value[method].apply(value, args);
432     });
433   },
434 
435   max: function(iterator) {
436     var result;
437     this.each(function(value, index) {
438       value = (iterator || Prototype.K)(value, index);
439       if (result == undefined || value >= result)
440         result = value;
441     });
442     return result;
443   },
444 
445   min: function(iterator) {
446     var result;
447     this.each(function(value, index) {
448       value = (iterator || Prototype.K)(value, index);
449       if (result == undefined || value < result)
450         result = value;
451     });
452     return result;
453   },
454 
455   partition: function(iterator) {
456     var trues = [], falses = [];
457     this.each(function(value, index) {
458       ((iterator || Prototype.K)(value, index) ?
459         trues : falses).push(value);
460     });
461     return [trues, falses];
462   },
463 
464   pluck: function(property) {
465     var results = [];
466     this.each(function(value, index) {
467       results.push(value[property]);
468     });
469     return results;
470   },
471 
472   reject: function(iterator) {
473     var results = [];
474     this.each(function(value, index) {
475       if (!iterator(value, index))
476         results.push(value);
477     });
478     return results;
479   },
480 
481   sortBy: function(iterator) {
482     return this.map(function(value, index) {
483       return {value: value, criteria: iterator(value, index)};
484     }).sort(function(left, right) {
485       var a = left.criteria, b = right.criteria;
486       return a < b ? -1 : a > b ? 1 : 0;
487     }).pluck('value');
488   },
489 
490   toArray: function() {
491     return this.map();
492   },
493 
494   zip: function() {
495     var iterator = Prototype.K, args = $A(arguments);
496     if (typeof args.last() == 'function')
497       iterator = args.pop();
498 
499     var collections = [this].concat(args).map($A);
500     return this.map(function(value, index) {
501       return iterator(collections.pluck(index));
502     });
503   },
504 
505   size: function() {
506     return this.toArray().length;
507   },
508 
509   inspect: function() {
510     return '#<Enumerable:' + this.toArray().inspect() + '>';
511   }
512 }
513 
514 Object.extend(Enumerable, {
515   map:     Enumerable.collect,
516   find:    Enumerable.detect,
517   select:  Enumerable.findAll,
518   member:  Enumerable.include,
519   entries: Enumerable.toArray
520 });
521 var $A = Array.from = function(iterable) {
522   if (!iterable) return [];
523   if (iterable.toArray) {
524     return iterable.toArray();
525   } else {
526     var results = [];
527     for (var i = 0, length = iterable.length; i < length; i++)
528       results.push(iterable[i]);
529     return results;
530   }
531 }
532 
533 Object.extend(Array.prototype, Enumerable);
534 
535 if (!Array.prototype._reverse)
536   Array.prototype._reverse = Array.prototype.reverse;
537 
538 Object.extend(Array.prototype, {
539   _each: function(iterator) {
540     for (var i = 0, length = this.length; i < length; i++)
541       iterator(this[i]);
542   },
543 
544   clear: function() {
545     this.length = 0;
546     return this;
547   },
548 
549   first: function() {
550     return this[0];
551   },
552 
553   last: function() {
554     return this[this.length - 1];
555   },
556 
557   compact: function() {
558     return this.select(function(value) {
559       return value != null;
560     });
561   },
562 
563   flatten: function() {
564     return this.inject([], function(array, value) {
565       return array.concat(value && value.constructor == Array ?
566         value.flatten() : [value]);
567     });
568   },
569 
570   without: function() {
571     var values = $A(arguments);
572     return this.select(function(value) {
573       return !values.include(value);
574     });
575   },
576 
577   indexOf: function(object) {
578     for (var i = 0, length = this.length; i < length; i++)
579       if (this[i] == object) return i;
580     return -1;
581   },
582 
583   reverse: function(inline) {
584     return (inline !== false ? this : this.toArray())._reverse();
585   },
586 
587   reduce: function() {
588     return this.length > 1 ? this : this[0];
589   },
590 
591   uniq: function() {
592     return this.inject([], function(array, value) {
593       return array.include(value) ? array : array.concat([value]);
594     });
595   },
596 
597   clone: function() {
598     return [].concat(this);
599   },
600 
601   size: function() {
602     return this.length;
603   },
604 
605   inspect: function() {
606     return '[' + this.map(Object.inspect).join(', ') + ']';
607   }
608 });
609 
610 Array.prototype.toArray = Array.prototype.clone;
611 
612 function $w(string){
613   string = string.strip();
614   return string ? string.split(/\s+/) : [];
615 }
616 
617 if(window.opera){
618   Array.prototype.concat = function(){
619     var array = [];
620     for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
621     for(var i = 0, length = arguments.length; i < length; i++) {
622       if(arguments[i].constructor == Array) {
623         for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
624           array.push(arguments[i][j]);
625       } else {
626         array.push(arguments[i]);
627       }
628     }
629     return array;
630   }
631 }
632 var Hash = function(obj) {
633   Object.extend(this, obj || {});
634 };
635 
636 Object.extend(Hash, {
637   toQueryString: function(obj) {
638     var parts = [];
639 
640           this.prototype._each.call(obj, function(pair) {
641       if (!pair.key) return;
642 
643       if (pair.value && pair.value.constructor == Array) {
644         var values = pair.value.compact();
645         if (values.length < 2) pair.value = values.reduce();
646         else {
647                 key = encodeURIComponent(pair.key);
648           values.each(function(value) {
649             value = value != undefined ? encodeURIComponent(value) : '';
650             parts.push(key + '=' + encodeURIComponent(value));
651           });
652           return;
653         }
654       }
655       if (pair.value == undefined) pair[1] = '';
656       parts.push(pair.map(encodeURIComponent).join('='));
657           });
658 
659     return parts.join('&');
660   }
661 });
662 
663 Object.extend(Hash.prototype, Enumerable);
664 Object.extend(Hash.prototype, {
665   _each: function(iterator) {
666     for (var key in this) {
667       var value = this[key];
668       if (value && value == Hash.prototype[key]) continue;
669 
670       var pair = [key, value];
671       pair.key = key;
672       pair.value = value;
673       iterator(pair);
674     }
675   },
676 
677   keys: function() {
678     return this.pluck('key');
679   },
680 
681   values: function() {
682     return this.pluck('value');
683   },
684 
685   merge: function(hash) {
686     return $H(hash).inject(this, function(mergedHash, pair) {
687       mergedHash[pair.key] = pair.value;
688       return mergedHash;
689     });
690   },
691 
692   remove: function() {
693     var result;
694     for(var i = 0, length = arguments.length; i < length; i++) {
695       var value = this[arguments[i]];
696       if (value !== undefined){
697         if (result === undefined) result = value;
698         else {
699           if (result.constructor != Array) result = [result];
700           result.push(value)
701         }
702       }
703       delete this[arguments[i]];
704     }
705     return result;
706   },
707 
708   toQueryString: function() {
709     return Hash.toQueryString(this);
710   },
711 
712   inspect: function() {
713     return '#<Hash:{' + this.map(function(pair) {
714       return pair.map(Object.inspect).join(': ');
715     }).join(', ') + '}>';
716   }
717 });
718 
719 function $H(object) {
720   if (object && object.constructor == Hash) return object;
721   return new Hash(object);
722 };
723 ObjectRange = Class.create();
724 Object.extend(ObjectRange.prototype, Enumerable);
725 Object.extend(ObjectRange.prototype, {
726   initialize: function(start, end, exclusive) {
727     this.start = start;
728     this.end = end;
729     this.exclusive = exclusive;
730   },
731 
732   _each: function(iterator) {
733     var value = this.start;
734     while (this.include(value)) {
735       iterator(value);
736       value = value.succ();
737     }
738   },
739 
740   include: function(value) {
741     if (value < this.start)
742       return false;
743     if (this.exclusive)
744       return value < this.end;
745     return value <= this.end;
746   }
747 });
748 
749 var $R = function(start, end, exclusive) {
750   return new ObjectRange(start, end, exclusive);
751 }
752 
753 var Ajax = {
754   getTransport: function() {
755     return Try.these(
756       function() {return new XMLHttpRequest()},
757       function() {return new ActiveXObject('Msxml2.XMLHTTP')},
758       function() {return new ActiveXObject('Microsoft.XMLHTTP')}
759     ) || false;
760   },
761 
762   activeRequestCount: 0
763 }
764 
765 Ajax.Responders = {
766   responders: [],
767 
768   _each: function(iterator) {
769     this.responders._each(iterator);
770   },
771 
772   register: function(responder) {
773     if (!this.include(responder))
774       this.responders.push(responder);
775   },
776 
777   unregister: function(responder) {
778     this.responders = this.responders.without(responder);
779   },
780 
781   dispatch: function(callback, request, transport, json) {
782     this.each(function(responder) {
783       if (typeof responder[callback] == 'function') {
784         try {
785           responder[callback].apply(responder, [request, transport, json]);
786         } catch (e) {}
787       }
788     });
789   }
790 };
791 
792 Object.extend(Ajax.Responders, Enumerable);
793 
794 Ajax.Responders.register({
795   onCreate: function() {
796     Ajax.activeRequestCount++;
797   },
798   onComplete: function() {
799     Ajax.activeRequestCount--;
800   }
801 });
802 
803 Ajax.Base = function() {};
804 Ajax.Base.prototype = {
805   setOptions: function(options) {
806     this.options = {
807       method:       'post',
808       asynchronous: true,
809       contentType:  'application/x-www-form-urlencoded',
810       encoding:     'UTF-8',
811       parameters:   ''
812     }
813     Object.extend(this.options, options || {});
814 
815     this.options.method = this.options.method.toLowerCase();
816     if (typeof this.options.parameters == 'string')
817       this.options.parameters = this.options.parameters.toQueryParams();
818   }
819 }
820 
821 Ajax.Request = Class.create();
822 Ajax.Request.Events =
823   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
824 
825 Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
826   _complete: false,
827 
828   initialize: function(url, options) {
829     this.transport = Ajax.getTransport();
830     this.setOptions(options);
831     this.request(url);
832   },
833 
834   request: function(url) {
835     this.url = url;
836     this.method = this.options.method;
837     var params = this.options.parameters;
838 
839     if (!['get', 'post'].include(this.method)) {
840       // simulate other verbs over post
841       params['_method'] = this.method;
842       this.method = 'post';
843     }
844 
845     params = Hash.toQueryString(params);
846     if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
847 
848     // when GET, append parameters to URL
849     if (this.method == 'get' && params)
850       this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
851 
852     try {
853       Ajax.Responders.dispatch('onCreate', this, this.transport);
854 
855       this.transport.open(this.method.toUpperCase(), this.url,
856         this.options.asynchronous);
857 
858       if (this.options.asynchronous)
859         setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
860 
861       this.transport.onreadystatechange = this.onStateChange.bind(this);
862       this.setRequestHeaders();
863 
864       var body = this.method == 'post' ? (this.options.postBody || params) : null;
865 
866       this.transport.send(body);
867 
868       /* Force Firefox to handle ready state 4 for synchronous requests */
869       if (!this.options.asynchronous && this.transport.overrideMimeType)
870         this.onStateChange();
871 
872     }
873     catch (e) {
874       this.dispatchException(e);
875     }
876   },
877 
878   onStateChange: function() {
879     var readyState = this.transport.readyState;
880     if (readyState > 1 && !((readyState == 4) && this._complete))
881       this.respondToReadyState(this.transport.readyState);
882   },
883 
884   setRequestHeaders: function() {
885     var headers = {
886       'X-Requested-With': 'XMLHttpRequest',
887       'X-Prototype-Version': Prototype.Version,
888       'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
889     };
890 
891     if (this.method == 'post') {
892       headers['Content-type'] = this.options.contentType +
893         (this.options.encoding ? '; charset=' + this.options.encoding : '');
894 
895       /* Force "Connection: close" for older Mozilla browsers to work
896        * around a bug where XMLHttpRequest sends an incorrect
897        * Content-length header. See Mozilla Bugzilla #246651.
898        */
899       if (this.transport.overrideMimeType &&
900           (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
901             headers['Connection'] = 'close';
902     }
903 
904     // user-defined headers
905     if (typeof this.options.requestHeaders == 'object') {
906       var extras = this.options.requestHeaders;
907 
908       if (typeof extras.push == 'function')
909         for (var i = 0, length = extras.length; i < length; i += 2)
910           headers[extras[i]] = extras[i+1];
911       else
912         $H(extras).each(function(pair) { headers[pair.key] = pair.value });
913     }
914 
915     for (var name in headers)
916       this.transport.setRequestHeader(name, headers[name]);
917   },
918 
919   success: function() {
920     return !this.transport.status
921         || (this.transport.status >= 200 && this.transport.status < 300);
922   },
923 
924   respondToReadyState: function(readyState) {
925     var state = Ajax.Request.Events[readyState];
926     var transport = this.transport, json = this.evalJSON();
927 
928     if (state == 'Complete') {
929       try {
930         this._complete = true;
931         (this.options['on' + this.transport.status]
932          || this.options['on' + (this.success() ? 'Success' : 'Failure')]
933          || Prototype.emptyFunction)(transport, json);
934       } catch (e) {
935         this.dispatchException(e);
936       }
937 
938       if ((this.getHeader('Content-type') || 'text/javascript').strip().
939         match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
940           this.evalResponse();
941     }
942 
943     try {
944       (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
945       Ajax.Responders.dispatch('on' + state, this, transport, json);
946     } catch (e) {
947       this.dispatchException(e);
948     }
949 
950     if (state == 'Complete') {
951       // avoid memory leak in MSIE: clean up
952       this.transport.onreadystatechange = Prototype.emptyFunction;
953     }
954   },
955 
956   getHeader: function(name) {
957     try {
958       return this.transport.getResponseHeader(name);
959     } catch (e) { return null }
960   },
961 
962   evalJSON: function() {
963     try {
964       var json = this.getHeader('X-JSON');
965       return json ? eval('(' + json + ')') : null;
966     } catch (e) { return null }
967   },
968 
969   evalResponse: function() {
970     try {
971       return eval(this.transport.responseText);
972     } catch (e) {
973       this.dispatchException(e);
974     }
975   },
976 
977   dispatchException: function(exception) {
978     (this.options.onException || Prototype.emptyFunction)(this, exception);
979     Ajax.Responders.dispatch('onException', this, exception);
980   }
981 });
982 
983 Ajax.Updater = Class.create();
984 
985 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
986   initialize: function(container, url, options) {
987     this.container = {
988       success: (container.success || container),
989       failure: (container.failure || (container.success ? null : container))
990     }
991 
992     this.transport = Ajax.getTransport();
993     this.setOptions(options);
994 
995     var onComplete = this.options.onComplete || Prototype.emptyFunction;
996     this.options.onComplete = (function(transport, param) {
997       this.updateContent();
998       onComplete(transport, param);
999     }).bind(this);
1000 
1001     this.request(url);
1002   },
1003 
1004   updateContent: function() {
1005     var receiver = this.container[this.success() ? 'success' : 'failure'];
1006     var response = this.transport.responseText;
1007 
1008     if (!this.options.evalScripts) response = response.stripScripts();
1009 
1010     if (receiver = $(receiver)) {
1011       if (this.options.insertion)
1012         new this.options.insertion(receiver, response);
1013       else
1014         receiver.update(response);
1015     }
1016 
1017     if (this.success()) {
1018       if (this.onComplete)
1019         setTimeout(this.onComplete.bind(this), 10);
1020     }
1021   }
1022 });
1023 
1024 Ajax.PeriodicalUpdater = Class.create();
1025 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
1026   initialize: function(container, url, options) {
1027     this.setOptions(options);
1028     this.onComplete = this.options.onComplete;
1029 
1030     this.frequency = (this.options.frequency || 2);
1031     this.decay = (this.options.decay || 1);
1032 
1033     this.updater = {};
1034     this.container = container;
1035     this.url = url;
1036 
1037     this.start();
1038   },
1039 
1040   start: function() {
1041     this.options.onComplete = this.updateComplete.bind(this);
1042     this.onTimerEvent();
1043   },
1044 
1045   stop: function() {
1046     this.updater.options.onComplete = undefined;
1047     clearTimeout(this.timer);
1048     (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1049   },
1050 
1051   updateComplete: function(request) {
1052     if (this.options.decay) {
1053       this.decay = (request.responseText == this.lastText ?
1054         this.decay * this.options.decay : 1);
1055 
1056       this.lastText = request.responseText;
1057     }
1058     this.timer = setTimeout(this.onTimerEvent.bind(this),
1059       this.decay * this.frequency * 1000);
1060   },
1061 
1062   onTimerEvent: function() {
1063     this.updater = new Ajax.Updater(this.container, this.url, this.options);
1064   }
1065 });
1066 function $(element) {
1067   if (arguments.length > 1) {
1068     for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1069       elements.push($(arguments[i]));
1070     return elements;
1071   }
1072   if (typeof element == 'string')
1073     element = document.getElementById(element);
1074   return Element.extend(element);
1075 }
1076 
1077 if (Prototype.BrowserFeatures.XPath) {
1078   document._getElementsByXPath = function(expression, parentElement) {
1079     var results = [];
1080     var query = document.evaluate(expression, $(parentElement) || document,
1081       null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1082     for (var i = 0, length = query.snapshotLength; i < length; i++)
1083       results.push(query.snapshotItem(i));
1084     return results;
1085   };
1086 }
1087 
1088 document.getElementsByClassName = function(className, parentElement) {
1089   if (Prototype.BrowserFeatures.XPath) {
1090     var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1091     return document._getElementsByXPath(q, parentElement);
1092   } else {
1093     var children = ($(parentElement) || document.body).getElementsByTagName('*');
1094     var elements = [], child;
1095     for (var i = 0, length = children.length; i < length; i++) {
1096       child = children[i];
1097       if (Element.hasClassName(child, className))
1098         elements.push(Element.extend(child));
1099     }
1100     return elements;
1101   }
1102 };
1103 
1104 /*--------------------------------------------------------------------------*/
1105 
1106 if (!window.Element)
1107   var Element = new Object();
1108 
1109 Element.extend = function(element) {
1110   if (!element || _nativeExtensions || element.nodeType == 3) return element;
1111 
1112   if (!element._extended && element.tagName && element != window) {
1113     var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
1114 
1115     if (element.tagName == 'FORM')
1116       Object.extend(methods, Form.Methods);
1117     if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
1118       Object.extend(methods, Form.Element.Methods);
1119 
1120     Object.extend(methods, Element.Methods.Simulated);
1121 
1122     for (var property in methods) {
1123       var value = methods[property];
1124       if (typeof value == 'function' && !(property in element))
1125         element[property] = cache.findOrStore(value);
1126     }
1127   }
1128 
1129   element._extended = true;
1130   return element;
1131 };
1132 
1133 Element.extend.cache = {
1134   findOrStore: function(value) {
1135     return this[value] = this[value] || function() {
1136       return value.apply(null, [this].concat($A(arguments)));
1137     }
1138   }
1139 };
1140 
1141 Element.Methods = {
1142   visible: function(element) {
1143     return $(element).style.display != 'none';
1144   },
1145 
1146   toggle: function(element) {
1147     element = $(element);
1148     Element[Element.visible(element) ? 'hide' : 'show'](element);
1149     return element;
1150   },
1151 
1152   hide: function(element) {
1153     $(element).style.display = 'none';
1154     return element;
1155   },
1156 
1157   show: function(element) {
1158     $(element).style.display = '';
1159     return element;
1160   },
1161 
1162   remove: function(element) {
1163     element = $(element);
1164     element.parentNode.removeChild(element);
1165     return element;
1166   },
1167 
1168   update: function(element, html) {
1169     html = typeof html == 'undefined' ? '' : html.toString();
1170     $(element).innerHTML = html.stripScripts();
1171     setTimeout(function() {html.evalScripts()}, 10);
1172     return element;
1173   },
1174 
1175   replace: function(element, html) {
1176     element = $(element);
1177     html = typeof html == 'undefined' ? '' : html.toString();
1178     if (element.outerHTML) {
1179       element.outerHTML = html.stripScripts();
1180     } else {
1181       var range = element.ownerDocument.createRange();
1182       range.selectNodeContents(element);
1183       element.parentNode.replaceChild(
1184         range.createContextualFragment(html.stripScripts()), element);
1185     }
1186     setTimeout(function() {html.evalScripts()}, 10);
1187     return element;
1188   },
1189 
1190   inspect: function(element) {
1191     element = $(element);
1192     var result = '<' + element.tagName.toLowerCase();
1193     $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1194       var property = pair.first(), attribute = pair.last();
1195       var value = (element[property] || '').toString();
1196       if (value) result += ' ' + attribute + '=' + value.inspect(true);
1197     });
1198     return result + '>';
1199   },
1200 
1201   recursivelyCollect: function(element, property) {
1202     element = $(element);
1203     var elements = [];
1204     while (element = element[property])
1205       if (element.nodeType == 1)
1206         elements.push(Element.extend(element));
1207     return elements;
1208   },
1209 
1210   ancestors: function(element) {
1211     return $(element).recursivelyCollect('parentNode');
1212   },
1213 
1214   descendants: function(element) {
1215     return $A($(element).getElementsByTagName('*'));
1216   },
1217 
1218   immediateDescendants: function(element) {
1219     if (!(element = $(element).firstChild)) return [];
1220     while (element && element.nodeType != 1) element = element.nextSibling;
1221     if (element) return [element].concat($(element).nextSiblings());
1222     return [];
1223   },
1224 
1225   previousSiblings: function(element) {
1226     return $(element).recursivelyCollect('previousSibling');
1227   },
1228 
1229   nextSiblings: function(element) {
1230     return $(element).recursivelyCollect('nextSibling');
1231   },
1232 
1233   siblings: function(element) {
1234     element = $(element);
1235     return element.previousSiblings().reverse().concat(element.nextSiblings());
1236   },
1237 
1238   match: function(element, selector) {
1239     if (typeof selector == 'string')
1240       selector = new Selector(selector);
1241     return selector.match($(element));
1242   },
1243 
1244   up: function(element, expression, index) {
1245     return Selector.findElement($(element).ancestors(), expression, index);
1246   },
1247 
1248   down: function(element, expression, index) {
1249     return Selector.findElement($(element).descendants(), expression, index);
1250   },
1251 
1252   previous: function(element, expression, index) {
1253     return Selector.findElement($(element).previousSiblings(), expression, index);
1254   },
1255 
1256   next: function(element, expression, index) {
1257     return Selector.findElement($(element).nextSiblings(), expression, index);
1258   },
1259 
1260   getElementsBySelector: function() {
1261     var args = $A(arguments), element = $(args.shift());
1262     return Selector.findChildElements(element, args);
1263   },
1264 
1265   getElementsByClassName: function(element, className) {
1266     return document.getElementsByClassName(className, element);
1267   },
1268 
1269   readAttribute: function(element, name) {
1270     element = $(element);
1271     if (document.all && !window.opera) {
1272       var t = Element._attributeTranslations;
1273       if (t.values[name]) return t.values[name](element, name);
1274       if (t.names[name])  name = t.names[name];
1275       var attribute = element.attributes[name];
1276       if(attribute) return attribute.nodeValue;
1277     }
1278     return element.getAttribute(name);
1279   },
1280 
1281   getHeight: function(element) {
1282     return $(element).getDimensions().height;
1283   },
1284 
1285   getWidth: function(element) {
1286     return $(element).getDimensions().width;
1287   },
1288 
1289   classNames: function(element) {
1290     return new Element.ClassNames(element);
1291   },
1292 
1293   hasClassName: function(element, className) {
1294     if (!(element = $(element))) return;
1295     var elementClassName = element.className;
1296     if (elementClassName.length == 0) return false;
1297     if (elementClassName == className ||
1298         elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1299       return true;
1300     return false;
1301   },
1302 
1303   addClassName: function(element, className) {
1304     if (!(element = $(element))) return;
1305     Element.classNames(element).add(className);
1306     return element;
1307   },
1308 
1309   removeClassName: function(element, className) {
1310     if (!(element = $(element))) return;
1311     Element.classNames(element).remove(className);
1312     return element;
1313   },
1314 
1315   toggleClassName: function(element, className) {
1316     if (!(element = $(element))) return;
1317     Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
1318     return element;
1319   },
1320 
1321   observe: function() {
1322     Event.observe.apply(Event, arguments);
1323     return $A(arguments).first();
1324   },
1325 
1326   stopObserving: function() {
1327     Event.stopObserving.apply(Event, arguments);
1328     return $A(arguments).first();
1329   },
1330 
1331   // removes whitespace-only text node children
1332   cleanWhitespace: function(element) {
1333     element = $(element);
1334     var node = element.firstChild;
1335     while (node) {
1336       var nextNode = node.nextSibling;
1337       if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1338         element.removeChild(node);
1339       node = nextNode;
1340     }
1341     return element;
1342   },
1343 
1344   empty: function(element) {
1345     return $(element).innerHTML.match(/^\s*$/);
1346   },
1347 
1348   descendantOf: function(element, ancestor) {
1349     element = $(element), ancestor = $(ancestor);
1350     while (element = element.parentNode)
1351       if (element == ancestor) return true;
1352     return false;
1353   },
1354 
1355   scrollTo: function(element) {
1356     element = $(element);
1357     var pos = Position.cumulativeOffset(element);
1358     window.scrollTo(pos[0], pos[1]);
1359     return element;
1360   },
1361 
1362   getStyle: function(element, style) {
1363     element = $(element);
1364     if (['float','cssFloat'].include(style))
1365       style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
1366     style = style.camelize();
1367     var value = element.style[style];
1368     if (!value) {
1369       if (document.defaultView && document.defaultView.getComputedStyle) {
1370         var css = document.defaultView.getComputedStyle(element, null);
1371         value = css ? css[style] : null;
1372       } else if (element.currentStyle) {
1373         value = element.currentStyle[style];
1374       }
1375     }
1376 
1377     if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
1378       value = element['offset'+style.capitalize()] + 'px';
1379 
1380     if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
1381       if (Element.getStyle(element, 'position') == 'static') value = 'auto';
1382     if(style == 'opacity') {
1383       if(value) return parseFloat(value);
1384       if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
1385         if(value[1]) return parseFloat(value[1]) / 100;
1386       return 1.0;
1387     }
1388     return value == 'auto' ? null : value;
1389   },
1390 
1391   setStyle: function(element, style) {
1392     element = $(element);
1393     for (var name in style) {
1394       var value = style[name];
1395       if(name == 'opacity') {
1396         if (value == 1) {
1397           value = (/Gecko/.test(navigator.userAgent) &&
1398             !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
1399           if(/MSIE/.test(navigator.userAgent) && !window.opera)
1400             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
1401         } else if(value === '') {
1402           if(/MSIE/.test(navigator.userAgent) && !window.opera)
1403             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
1404         } else {
1405           if(value < 0.00001) value = 0;
1406           if(/MSIE/.test(navigator.userAgent) && !window.opera)
1407             element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
1408               'alpha(opacity='+value*100+')';
1409         }
1410       } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
1411       element.style[name.camelize()] = value;
1412     }
1413     return element;
1414   },
1415 
1416   getDimensions: function(element) {
1417     element = $(element);
1418     var display = $(element).getStyle('display');
1419     if (display != 'none' && display != null) // Safari bug
1420       return {width: element.offsetWidth, height: element.offsetHeight};
1421 
1422     // All *Width and *Height properties give 0 on elements with display none,
1423     // so enable the element temporarily
1424     var els = element.style;
1425     var originalVisibility = els.visibility;
1426     var originalPosition = els.position;
1427     var originalDisplay = els.display;
1428     els.visibility = 'hidden';
1429     els.position = 'absolute';
1430     els.display = 'block';
1431     var originalWidth = element.clientWidth;
1432     var originalHeight = element.clientHeight;
1433     els.display = originalDisplay;
1434     els.position = originalPosition;
1435     els.visibility = originalVisibility;
1436     return {width: originalWidth, height: originalHeight};
1437   },
1438 
1439   makePositioned: function(element) {
1440     element = $(element);
1441     var pos = Element.getStyle(element, 'position');
1442     if (pos == 'static' || !pos) {
1443       element._madePositioned = true;
1444       element.style.position = 'relative';
1445       // Opera returns the offset relative to the positioning context, when an
1446       // element is position relative but top and left have not been defined
1447       if (window.opera) {
1448         element.style.top = 0;
1449         element.style.left = 0;
1450       }
1451     }
1452     return element;
1453   },
1454 
1455   undoPositioned: function(element) {
1456     element = $(element);
1457     if (element._madePositioned) {
1458       element._madePositioned = undefined;
1459       element.style.position =
1460         element.style.top =
1461         element.style.left =
1462         element.style.bottom =
1463         element.style.right = '';
1464     }
1465     return element;
1466   },
1467 
1468   makeClipping: function(element) {
1469     element = $(element);
1470     if (element._overflow) return element;
1471     element._overflow = element.style.overflow || 'auto';
1472     if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1473       element.style.overflow = 'hidden';
1474     return element;
1475   },
1476 
1477   undoClipping: function(element) {
1478     element = $(element);
1479     if (!element._overflow) return element;
1480     element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1481     element._overflow = null;
1482     return element;
1483   }
1484 };
1485 
1486 Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
1487 
1488 Element._attributeTranslations = {};
1489 
1490 Element._attributeTranslations.names = {
1491   colspan:   "colSpan",
1492   rowspan:   "rowSpan",
1493   valign:    "vAlign",
1494   datetime:  "dateTime",
1495   accesskey: "accessKey",
1496   tabindex:  "tabIndex",
1497   enctype:   "encType",
1498   maxlength: "maxLength",
1499   readonly:  "readOnly",
1500   longdesc:  "longDesc"
1501 };
1502 
1503 Element._attributeTranslations.values = {
1504   _getAttr: function(element, attribute) {
1505     return element.getAttribute(attribute, 2);
1506   },
1507 
1508   _flag: function(element, attribute) {
1509     return $(element).hasAttribute(attribute) ? attribute : null;
1510   },
1511 
1512   style: function(element) {
1513     return element.style.cssText.toLowerCase();
1514   },
1515 
1516   title: function(element) {
1517     var node = element.getAttributeNode('title');
1518     return node.specified ? node.nodeValue : null;
1519   }
1520 };
1521 
1522 Object.extend(Element._attributeTranslations.values, {
1523   href: Element._attributeTranslations.values._getAttr,
1524   src:  Element._attributeTranslations.values._getAttr,
1525   disabled: Element._attributeTranslations.values._flag,
1526   checked:  Element._attributeTranslations.values._flag,
1527   readonly: Element._attributeTranslations.values._flag,
1528   multiple: Element._attributeTranslations.values._flag
1529 });
1530 
1531 Element.Methods.Simulated = {
1532   hasAttribute: function(element, attribute) {
1533     var t = Element._attributeTranslations;
1534     attribute = t.names[attribute] || attribute;
1535     return $(element).getAttributeNode(attribute).specified;
1536   }
1537 };
1538 
1539 // IE is missing .innerHTML support for TABLE-related elements
1540 if (document.all && !window.opera){
1541   Element.Methods.update = function(element, html) {
1542     element = $(element);
1543     html = typeof html == 'undefined' ? '' : html.toString();
1544     var tagName = element.tagName.toUpperCase();
1545     if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1546       var div = document.createElement('div');
1547       switch (tagName) {
1548         case 'THEAD':
1549         case 'TBODY':
1550           div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
1551           depth = 2;
1552           break;
1553         case 'TR':
1554           div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
1555           depth = 3;
1556           break;
1557         case 'TD':
1558           div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
1559           depth = 4;
1560       }
1561       $A(element.childNodes).each(function(node){
1562         element.removeChild(node)
1563       });
1564       depth.times(function(){ div = div.firstChild });
1565 
1566       $A(div.childNodes).each(
1567         function(node){ element.appendChild(node) });
1568     } else {
1569       element.innerHTML = html.stripScripts();
1570     }
1571     setTimeout(function() {html.evalScripts()}, 10);
1572     return element;
1573   }
1574 };
1575 
1576 Object.extend(Element, Element.Methods);
1577 
1578 var _nativeExtensions = false;
1579 
1580 if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1581   ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
1582     var className = 'HTML' + tag + 'Element';
1583     if(window[className]) return;
1584     var klass = window[className] = {};
1585     klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
1586   });
1587 
1588 Element.addMethods = function(methods) {
1589   Object.extend(Element.Methods, methods || {});
1590 
1591   function copy(methods, destination, onlyIfAbsent) {
1592     onlyIfAbsent = onlyIfAbsent || false;
1593     var cache = Element.extend.cache;
1594     for (var property in methods) {
1595       var value = methods[property];
1596       if (!onlyIfAbsent || !(property in destination))
1597         destination[property] = cache.findOrStore(value);
1598     }
1599   }
1600 
1601   if (typeof HTMLElement != 'undefined') {
1602     copy(Element.Methods, HTMLElement.prototype);
1603     copy(Element.Methods.Simulated, HTMLElement.prototype, true);
1604     copy(Form.Methods, HTMLFormElement.prototype);
1605     [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
1606       copy(Form.Element.Methods, klass.prototype);
1607     });
1608     _nativeExtensions = true;
1609   }
1610 }
1611 
1612 var Toggle = new Object();
1613 Toggle.display = Element.toggle;
1614 
1615 /*--------------------------------------------------------------------------*/
1616 
1617 Abstract.Insertion = function(adjacency) {
1618   this.adjacency = adjacency;
1619 }
1620 
1621 Abstract.Insertion.prototype = {
1622   initialize: function(element, content) {
1623     this.element = $(element);
1624     this.content = content.stripScripts();
1625 
1626     if (this.adjacency && this.element.insertAdjacentHTML) {
1627       try {
1628         this.element.insertAdjacentHTML(this.adjacency, this.content);
1629       } catch (e) {
1630         var tagName = this.element.tagName.toUpperCase();
1631         if (['TBODY', 'TR'].include(tagName)) {
1632           this.insertContent(this.contentFromAnonymousTable());
1633         } else {
1634           throw e;
1635         }
1636       }
1637     } else {
1638       this.range = this.element.ownerDocument.createRange();
1639       if (this.initializeRange) this.initializeRange();
1640       this.insertContent([this.range.createContextualFragment(this.content)]);
1641     }
1642 
1643     setTimeout(function() {content.evalScripts()}, 10);
1644   },
1645 
1646   contentFromAnonymousTable: function() {
1647     var div = document.createElement('div');
1648     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1649     return $A(div.childNodes[0].childNodes[0].childNodes);
1650   }
1651 }
1652 
1653 var Insertion = new Object();
1654 
1655 Insertion.Before = Class.create();
1656 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1657   initializeRange: function() {
1658     this.range.setStartBefore(this.element);
1659   },
1660 
1661   insertContent: function(fragments) {
1662     fragments.each((function(fragment) {
1663       this.element.parentNode.insertBefore(fragment, this.element);
1664     }).bind(this));
1665   }
1666 });
1667 
1668 Insertion.Top = Class.create();
1669 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1670   initializeRange: function() {
1671     this.range.selectNodeContents(this.element);
1672     this.range.collapse(true);
1673   },
1674 
1675   insertContent: function(fragments) {
1676     fragments.reverse(false).each((function(fragment) {
1677       this.element.insertBefore(fragment, this.element.firstChild);
1678     }).bind(this));
1679   }
1680 });
1681 
1682 Insertion.Bottom = Class.create();
1683 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1684   initializeRange: function() {
1685     this.range.selectNodeContents(this.element);
1686     this.range.collapse(this.element);
1687   },
1688 
1689   insertContent: function(fragments) {
1690     fragments.each((function(fragment) {
1691       this.element.appendChild(fragment);
1692     }).bind(this));
1693   }
1694 });
1695 
1696 Insertion.After = Class.create();
1697 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1698   initializeRange: function() {
1699     this.range.setStartAfter(this.element);
1700   },
1701 
1702   insertContent: function(fragments) {
1703     fragments.each((function(fragment) {
1704       this.element.parentNode.insertBefore(fragment,
1705         this.element.nextSibling);
1706     }).bind(this));
1707   }
1708 });
1709 
1710 /*--------------------------------------------------------------------------*/
1711 
1712 Element.ClassNames = Class.create();
1713 Element.ClassNames.prototype = {
1714   initialize: function(element) {
1715     this.element = $(element);
1716   },
1717 
1718   _each: function(iterator) {
1719     this.element.className.split(/\s+/).select(function(name) {
1720       return name.length > 0;
1721     })._each(iterator);
1722   },
1723 
1724   set: function(className) {
1725     this.element.className = className;
1726   },
1727 
1728   add: function(classNameToAdd) {
1729     if (this.include(classNameToAdd)) return;
1730     this.set($A(this).concat(classNameToAdd).join(' '));
1731   },
1732 
1733   remove: function(classNameToRemove) {
1734     if (!this.include(classNameToRemove)) return;
1735     this.set($A(this).without(classNameToRemove).join(' '));
1736   },
1737 
1738   toString: function() {
1739     return $A(this).join(' ');
1740   }
1741 };
1742 
1743 Object.extend(Element.ClassNames.prototype, Enumerable);
1744 var Selector = Class.create();
1745 Selector.prototype = {
1746   initialize: function(expression) {
1747     this.params = {classNames: []};
1748     this.expression = expression.toString().strip();
1749     this.parseExpression();
1750     this.compileMatcher();
1751   },
1752 
1753   parseExpression: function() {
1754     function abort(message) { throw 'Parse error in selector: ' + message; }
1755 
1756     if (this.expression == '')  abort('empty expression');
1757 
1758     var params = this.params, expr = this.expression, match, modifier, clause, rest;
1759     while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1760       params.attributes = params.attributes || [];
1761       params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1762       expr = match[1];
1763     }
1764 
1765     if (expr == '*') return this.params.wildcard = true;
1766 
1767     while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1768       modifier = match[1], clause = match[2], rest = match[3];
1769       switch (modifier) {
1770         case '#':       params.id = clause; break;
1771         case '.':       params.classNames.push(clause); break;
1772         case '':
1773         case undefined: params.tagName = clause.toUpperCase(); break;
1774         default:        abort(expr.inspect());
1775       }
1776       expr = rest;
1777     }
1778 
1779     if (expr.length > 0) abort(expr.inspect());
1780   },
1781 
1782   buildMatchExpression: function() {
1783     var params = this.params, conditions = [], clause;
1784 
1785     if (params.wildcard)
1786       conditions.push('true');
1787     if (clause = params.id)
1788       conditions.push('element.readAttribute("id") == ' + clause.inspect());
1789     if (clause = params.tagName)
1790       conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
1791     if ((clause = params.classNames).length > 0)
1792       for (var i = 0, length = clause.length; i < length; i++)
1793         conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
1794     if (clause = params.attributes) {
1795       clause.each(function(attribute) {
1796         var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
1797         var splitValueBy = function(delimiter) {
1798           return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
1799         }
1800 
1801         switch (attribute.operator) {
1802           case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
1803           case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
1804           case '|=':      conditions.push(
1805                             splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
1806                           ); break;
1807           case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
1808           case '':
1809           case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
1810           default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
1811         }
1812       });
1813     }
1814 
1815     return conditions.join(' && ');
1816   },
1817 
1818   compileMatcher: function() {
1819     this.match = new Function('element', 'if (!element.tagName) return false; \
1820       element = $(element); \
1821       return ' + this.buildMatchExpression());
1822   },
1823 
1824   findElements: function(scope) {
1825     var element;
1826 
1827     if (element = $(this.params.id))
1828       if (this.match(element))
1829         if (!scope || Element.childOf(element, scope))
1830           return [element];
1831 
1832     scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
1833 
1834     var results = [];
1835     for (var i = 0, length = scope.length; i < length; i++)
1836       if (this.match(element = scope[i]))
1837         results.push(Element.extend(element));
1838 
1839     return results;
1840   },
1841 
1842   toString: function() {
1843     return this.expression;
1844   }
1845 }
1846 
1847 Object.extend(Selector, {
1848   matchElements: function(elements, expression) {
1849     var selector = new Selector(expression);
1850     return elements.select(selector.match.bind(selector)).map(Element.extend);
1851   },
1852 
1853   findElement: function(elements, expression, index) {
1854     if (typeof expression == 'number') index = expression, expression = false;
1855     return Selector.matchElements(elements, expression || '*')[index || 0];
1856   },
1857 
1858   findChildElements: function(element, expressions) {
1859     return expressions.map(function(expression) {
1860       return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
1861         var selector = new Selector(expr);
1862         return results.inject([], function(elements, result) {
1863           return elements.concat(selector.findElements(result || element));
1864         });
1865       });
1866     }).flatten();
1867   }
1868 });
1869 
1870 function $$() {
1871   return Selector.findChildElements(document, $A(arguments));
1872 }
1873 var Form = {
1874   reset: function(form) {
1875     $(form).reset();
1876     return form;
1877   },
1878 
1879   serializeElements: function(elements, getHash) {
1880     var data = elements.inject({}, function(result, element) {
1881       if (!element.disabled && element.name) {
1882         var key = element.name, value = $(element).getValue();
1883         if (value != undefined) {
1884           if (result[key]) {
1885             if (result[key].constructor != Array) result[key] = [result[key]];
1886             result[key].push(value);
1887           }
1888           else result[key] = value;
1889         }
1890       }
1891       return result;
1892     });
1893 
1894     return getHash ? data : Hash.toQueryString(data);
1895   }
1896 };
1897 
1898 Form.Methods = {
1899   serialize: function(form, getHash) {
1900     return Form.serializeElements(Form.getElements(form), getHash);
1901   },
1902 
1903   getElements: function(form) {
1904     return $A($(form).getElementsByTagName('*')).inject([],
1905       function(elements, child) {
1906         if (Form.Element.Serializers[child.tagName.toLowerCase()])
1907           elements.push(Element.extend(child));
1908         return elements;
1909       }
1910     );
1911   },
1912 
1913   getInputs: function(form, typeName, name) {
1914     form = $(form);
1915     var inputs = form.getElementsByTagName('input');
1916 
1917     if (!typeName && !name) return $A(inputs).map(Element.extend);
1918 
1919     for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
1920       var input = inputs[i];
1921       if ((typeName && input.type != typeName) || (name && input.name != name))
1922         continue;
1923       matchingInputs.push(Element.extend(input));
1924     }
1925 
1926     return matchingInputs;
1927   },
1928 
1929   disable: function(form) {
1930     form = $(form);
1931     form.getElements().each(function(element) {
1932       element.blur();
1933       element.disabled = 'true';
1934     });
1935     return form;
1936   },
1937 
1938   enable: function(form) {
1939     form = $(form);
1940     form.getElements().each(function(element) {
1941       element.disabled = '';
1942     });
1943     return form;
1944   },
1945 
1946   findFirstElement: function(form) {
1947     return $(form).getElements().find(function(element) {
1948       return element.type != 'hidden' && !element.disabled &&
1949         ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1950     });
1951   },
1952 
1953   focusFirstElement: function(form) {
1954     form = $(form);
1955     form.findFirstElement().activate();
1956     return form;
1957   }
1958 }
1959 
1960 Object.extend(Form, Form.Methods);
1961 
1962 /*--------------------------------------------------------------------------*/
1963 
1964 Form.Element = {
1965   focus: function(element) {
1966     $(element).focus();
1967     return element;
1968   },
1969 
1970   select: function(element) {
1971     $(element).select();
1972     return element;
1973   }
1974 }
1975 
1976 Form.Element.Methods = {
1977   serialize: function(element) {
1978     element = $(element);
1979     if (!element.disabled && element.name) {
1980       var value = element.getValue();
1981       if (value != undefined) {
1982         var pair = {};
1983         pair[element.name] = value;
1984         return Hash.toQueryString(pair);
1985       }
1986     }
1987     return '';
1988   },
1989 
1990   getValue: function(element) {
1991     element = $(element);
1992     var method = element.tagName.toLowerCase();
1993     return Form.Element.Serializers[method](element);
1994   },
1995 
1996   clear: function(element) {
1997     $(element).value = '';
1998     return element;
1999   },
2000 
2001   present: function(element) {
2002     return $(element).value != '';
2003   },
2004 
2005   activate: function(element) {
2006     element = $(element);
2007     element.focus();
2008     if (element.select && ( element.tagName.toLowerCase() != 'input' ||
2009       !['button', 'reset', 'submit'].include(element.type) ) )
2010       element.select();
2011     return element;
2012   },
2013 
2014   disable: function(element) {
2015     element = $(element);
2016     element.disabled = true;
2017     return element;
2018   },
2019 
2020   enable: function(element) {
2021     element = $(element);
2022     element.blur();
2023     element.disabled = false;
2024     return element;
2025   }
2026 }
2027 
2028 Object.extend(Form.Element, Form.Element.Methods);
2029 var Field = Form.Element;
2030 var $F = Form.Element.getValue;
2031 
2032 /*--------------------------------------------------------------------------*/
2033 
2034 Form.Element.Serializers = {
2035   input: function(element) {
2036     switch (element.type.toLowerCase()) {
2037       case 'checkbox':
2038       case 'radio':
2039         return Form.Element.Serializers.inputSelector(element);
2040       default:
2041         return Form.Element.Serializers.textarea(element);
2042     }
2043   },
2044 
2045   inputSelector: function(element) {
2046     return element.checked ? element.value : null;
2047   },
2048 
2049   textarea: function(element) {
2050     return element.value;
2051   },
2052 
2053   select: function(element) {
2054     return this[element.type == 'select-one' ?
2055       'selectOne' : 'selectMany'](element);
2056   },
2057 
2058   selectOne: function(element) {
2059     var index = element.selectedIndex;
2060     return index >= 0 ? this.optionValue(element.options[index]) : null;
2061   },
2062 
2063   selectMany: function(element) {
2064     var values, length = element.length;
2065     if (!length) return null;
2066 
2067     for (var i = 0, values = []; i < length; i++) {
2068       var opt = element.options[i];
2069       if (opt.selected) values.push(this.optionValue(opt));
2070     }
2071     return values;
2072   },
2073 
2074   optionValue: function(opt) {
2075     // extend element because hasAttribute may not be native
2076     return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
2077   }
2078 }
2079 
2080 /*--------------------------------------------------------------------------*/
2081 
2082 Abstract.TimedObserver = function() {}
2083 Abstract.TimedObserver.prototype = {
2084   initialize: function(element, frequency, callback) {
2085     this.frequency = frequency;
2086     this.element   = $(element);
2087     this.callback  = callback;
2088 
2089     this.lastValue = this.getValue();
2090     this.registerCallback();
2091   },
2092 
2093   registerCallback: function() {
2094     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
2095   },
2096 
2097   onTimerEvent: function() {
2098     var value = this.getValue();
2099     var changed = ('string' == typeof this.lastValue && 'string' == typeof value
2100       ? this.lastValue != value : String(this.lastValue) != String(value));
2101     if (changed) {
2102       this.callback(this.element, value);
2103       this.lastValue = value;
2104     }
2105   }
2106 }
2107 
2108 Form.Element.Observer = Class.create();
2109 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2110   getValue: function() {
2111     return Form.Element.getValue(this.element);
2112   }
2113 });
2114 
2115 Form.Observer = Class.create();
2116 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2117   getValue: function() {
2118     return Form.serialize(this.element);
2119   }
2120 });
2121 
2122 /*--------------------------------------------------------------------------*/
2123 
2124 Abstract.EventObserver = function() {}
2125 Abstract.EventObserver.prototype = {
2126   initialize: function(element, callback) {
2127     this.element  = $(element);
2128     this.callback = callback;
2129 
2130     this.lastValue = this.getValue();
2131     if (this.element.tagName.toLowerCase() == 'form')
2132       this.registerFormCallbacks();
2133     else
2134       this.registerCallback(this.element);
2135   },
2136 
2137   onElementEvent: function() {
2138     var value = this.getValue();
2139     if (this.lastValue != value) {
2140       this.callback(this.element, value);
2141       this.lastValue = value;
2142     }
2143   },
2144 
2145   registerFormCallbacks: function() {
2146     Form.getElements(this.element).each(this.registerCallback.bind(this));
2147   },
2148 
2149   registerCallback: function(element) {
2150     if (element.type) {
2151       switch (element.type.toLowerCase()) {
2152         case 'checkbox':
2153         case 'radio':
2154           Event.observe(element, 'click', this.onElementEvent.bind(this));
2155           break;
2156         default:
2157           Event.observe(element, 'change', this.onElementEvent.bind(this));
2158           break;
2159       }
2160     }
2161   }
2162 }
2163 
2164 Form.Element.EventObserver = Class.create();
2165 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2166   getValue: function() {
2167     return Form.Element.getValue(this.element);
2168   }
2169 });
2170 
2171 Form.EventObserver = Class.create();
2172 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2173   getValue: function() {
2174     return Form.serialize(this.element);
2175   }
2176 });
2177 if (!window.Event) {
2178   var Event = new Object();
2179 }
2180 
2181 Object.extend(Event, {
2182   KEY_BACKSPACE: 8,
2183   KEY_TAB:       9,
2184   KEY_RETURN:   13,
2185   KEY_ESC:      27,
2186   KEY_LEFT:     37,
2187   KEY_UP:       38,
2188   KEY_RIGHT:    39,
2189   KEY_DOWN:     40,
2190   KEY_DELETE:   46,
2191   KEY_HOME:     36,
2192   KEY_END:      35,
2193   KEY_PAGEUP:   33,
2194   KEY_PAGEDOWN: 34,
2195 
2196   element: function(event) {
2197     return event.target || event.srcElement;
2198   },
2199 
2200   isLeftClick: function(event) {
2201     return (((event.which) && (event.which == 1)) ||
2202             ((event.button) && (event.button == 1)));
2203   },
2204 
2205   pointerX: function(event) {
2206     return event.pageX || (event.clientX +
2207       (document.documentElement.scrollLeft || document.body.scrollLeft));
2208   },
2209 
2210   pointerY: function(event) {
2211     return event.pageY || (event.clientY +
2212       (document.documentElement.scrollTop || document.body.scrollTop));
2213   },
2214 
2215   stop: function(event) {
2216     if (event.preventDefault) {
2217       event.preventDefault();
2218       event.stopPropagation();
2219     } else {
2220       event.returnValue = false;
2221       event.cancelBubble = true;
2222     }
2223   },
2224 
2225   // find the first node with the given tagName, starting from the
2226   // node the event was triggered on; traverses the DOM upwards
2227   findElement: function(event, tagName) {
2228     var element = Event.element(event);
2229     while (element.parentNode && (!element.tagName ||
2230         (element.tagName.toUpperCase() != tagName.toUpperCase())))
2231       element = element.parentNode;
2232     return element;
2233   },
2234 
2235   observers: false,
2236 
2237   _observeAndCache: function(element, name, observer, useCapture) {
2238     if (!this.observers) this.observers = [];
2239     if (element.addEventListener) {
2240       this.observers.push([element, name, observer, useCapture]);
2241       element.addEventListener(name, observer, useCapture);
2242     } else if (element.attachEvent) {
2243       this.observers.push([element, name, observer, useCapture]);
2244       element.attachEvent('on' + name, observer);
2245     }
2246   },
2247 
2248   unloadCache: function() {
2249     if (!Event.observers) return;
2250     for (var i = 0, length = Event.observers.length; i < length; i++) {
2251       Event.stopObserving.apply(this, Event.observers[i]);
2252       Event.observers[i][0] = null;
2253     }
2254     Event.observers = false;
2255   },
2256 
2257   observe: function(element, name, observer, useCapture) {
2258     element = $(element);
2259     useCapture = useCapture || false;
2260 
2261     if (name == 'keypress' &&
2262         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
2263         || element.attachEvent))
2264       name = 'keydown';
2265 
2266     Event._observeAndCache(element, name, observer, useCapture);
2267   },
2268 
2269   stopObserving: function(element, name, observer, useCapture) {
2270     element = $(element);
2271     useCapture = useCapture || false;
2272 
2273     if (name == 'keypress' &&
2274         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
2275         || element.detachEvent))
2276       name = 'keydown';
2277 
2278     if (element.removeEventListener) {
2279       element.removeEventListener(name, observer, useCapture);
2280     } else if (element.detachEvent) {
2281       try {
2282         element.detachEvent('on' + name, observer);
2283       } catch (e) {}
2284     }
2285   }
2286 });
2287 
2288 /* prevent memory leaks in IE */
2289 if (navigator.appVersion.match(/\bMSIE\b/))
2290   Event.observe(window, 'unload', Event.unloadCache, false);
2291 var Position = {
2292   // set to true if needed, warning: firefox performance problems
2293   // NOT neeeded for page scrolling, only if draggable contained in
2294   // scrollable elements
2295   includeScrollOffsets: false,
2296 
2297   // must be called before calling withinIncludingScrolloffset, every time the
2298   // page is scrolled
2299   prepare: function() {
2300     this.deltaX =  window.pageXOffset
2301                 || document.documentElement.scrollLeft
2302                 || document.body.scrollLeft
2303                 || 0;
2304     this.deltaY =  window.pageYOffset
2305                 || document.documentElement.scrollTop
2306                 || document.body.scrollTop
2307                 || 0;
2308   },
2309 
2310   realOffset: function(element) {
2311     var valueT = 0, valueL = 0;
2312     do {
2313       valueT += element.scrollTop  || 0;
2314       valueL += element.scrollLeft || 0;
2315       element = element.parentNode;
2316     } while (element);
2317     return [valueL, valueT];
2318   },
2319 
2320   cumulativeOffset: function(element) {
2321     var valueT = 0, valueL = 0;
2322     do {
2323       valueT += element.offsetTop  || 0;
2324       valueL += element.offsetLeft || 0;
2325       element = element.offsetParent;
2326     } while (element);
2327     return [valueL, valueT];
2328   },
2329 
2330   positionedOffset: function(element) {
2331     var valueT = 0, valueL = 0;
2332     do {
2333       valueT += element.offsetTop  || 0;
2334       valueL += element.offsetLeft || 0;
2335       element = element.offsetParent;
2336       if (element) {
2337         if(element.tagName=='BODY') break;
2338         var p = Element.getStyle(element, 'position');
2339         if (p == 'relative' || p == 'absolute') break;
2340       }
2341     } while (element);
2342     return [valueL, valueT];
2343   },
2344 
2345   offsetParent: function(element) {
2346     if (element.offsetParent) return element.offsetParent;
2347     if (element == document.body) return element;
2348 
2349     while ((element = element.parentNode) && element != document.body)
2350       if (Element.getStyle(element, 'position') != 'static')
2351         return element;
2352 
2353     return document.body;
2354   },
2355 
2356   // caches x/y coordinate pair to use with overlap
2357   within: function(element, x, y) {
2358     if (this.includeScrollOffsets)
2359       return this.withinIncludingScrolloffsets(element, x, y);
2360     this.xcomp = x;
2361     this.ycomp = y;
2362     this.offset = this.cumulativeOffset(element);
2363 
2364     return (y >= this.offset[1] &&
2365             y <  this.offset[1] + element.offsetHeight &&
2366             x >= this.offset[0] &&
2367             x <  this.offset[0] + element.offsetWidth);
2368   },
2369 
2370   withinIncludingScrolloffsets: function(element, x, y) {
2371     var offsetcache = this.realOffset(element);
2372 
2373     this.xcomp = x + offsetcache[0] - this.deltaX;
2374     this.ycomp = y + offsetcache[1] - this.deltaY;
2375     this.offset = this.cumulativeOffset(element);
2376 
2377     return (this.ycomp >= this.offset[1] &&
2378             this.ycomp <  this.offset[1] + element.offsetHeight &&
2379             this.xcomp >= this.offset[0] &&
2380             this.xcomp <  this.offset[0] + element.offsetWidth);
2381   },
2382 
2383   // within must be called directly before
2384   overlap: function(mode, element) {
2385     if (!mode) return 0;
2386     if (mode == 'vertical')
2387       return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
2388         element.offsetHeight;
2389     if (mode == 'horizontal')
2390       return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
2391         element.offsetWidth;
2392   },
2393 
2394   page: function(forElement) {
2395     var valueT = 0, valueL = 0;
2396 
2397     var element = forElement;
2398     do {
2399       valueT += element.offsetTop  || 0;
2400       valueL += element.offsetLeft || 0;
2401 
2402       // Safari fix
2403       if (element.offsetParent==document.body)
2404         if (Element.getStyle(element,'position')=='absolute') break;
2405 
2406     } while (element = element.offsetParent);
2407 
2408     element = forElement;
2409     do {
2410       if (!window.opera || element.tagName=='BODY') {
2411         valueT -= element.scrollTop  || 0;
2412         valueL -= element.scrollLeft || 0;
2413       }
2414     } while (element = element.parentNode);
2415 
2416     return [valueL, valueT];
2417   },
2418 
2419   clone: function(source, target) {
2420     var options = Object.extend({
2421       setLeft:    true,
2422       setTop:     true,
2423       setWidth:   true,
2424       setHeight:  true,
2425       offsetTop:  0,
2426       offsetLeft: 0
2427     }, arguments[2] || {})
2428 
2429     // find page position of source
2430     source = $(source);
2431     var p = Position.page(source);
2432 
2433     // find coordinate system to use
2434     target = $(target);
2435     var delta = [0, 0];
2436     var parent = null;
2437     // delta [0,0] will do fine with position: fixed elements,
2438     // position:absolute needs offsetParent deltas
2439     if (Element.getStyle(target,'position') == 'absolute') {
2440       parent = Position.offsetParent(target);
2441       delta = Position.page(parent);
2442     }
2443 
2444     // correct by body offsets (fixes Safari)
2445     if (parent == document.body) {
2446       delta[0] -= document.body.offsetLeft;
2447       delta[1] -= document.body.offsetTop;
2448     }
2449 
2450     // set position
2451     if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
2452     if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
2453     if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
2454     if(options.setHeight) target.style.height = source.offsetHeight + 'px';
2455   },
2456 
2457   absolutize: function(element) {
2458     element = $(element);
2459     if (element.style.position == 'absolute') return;
2460     Position.prepare();
2461 
2462     var offsets = Position.positionedOffset(element);
2463     var top     = offsets[1];
2464     var left    = offsets[0];
2465     var width   = element.clientWidth;
2466     var height  = element.clientHeight;
2467 
2468     element._originalLeft   = left - parseFloat(element.style.left  || 0);
2469     element._originalTop    = top  - parseFloat(element.style.top || 0);
2470     element._originalWidth  = element.style.width;
2471     element._originalHeight = element.style.height;
2472 
2473     element.style.position = 'absolute';
2474     element.style.top    = top + 'px';
2475     element.style.left   = left + 'px';
2476     element.style.width  = width + 'px';
2477     element.style.height = height + 'px';
2478   },
2479 
2480   relativize: function(element) {
2481     element = $(element);
2482     if (element.style.position == 'relative') return;
2483     Position.prepare();
2484 
2485     element.style.position = 'relative';
2486     var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
2487     var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
2488 
2489     element.style.top    = top + 'px';
2490     element.style.left   = left + 'px';
2491     element.style.height = element._originalHeight;
2492     element.style.width  = element._originalWidth;
2493   }
2494 }
2495 
2496 // Safari returns margins on body which is incorrect if the child is absolutely
2497 // positioned.  For performance reasons, redefine Position.cumulativeOffset for
2498 // KHTML/WebKit only.
2499 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
2500   Position.cumulativeOffset = function(element) {
2501     var valueT = 0, valueL = 0;
2502     do {
2503       valueT += element.offsetTop  || 0;
2504       valueL += element.offsetLeft || 0;
2505       if (element.offsetParent == document.body)
2506         if (Element.getStyle(element, 'position') == 'absolute') break;
2507 
2508       element = element.offsetParent;
2509     } while (element);
2510 
2511     return [valueL, valueT];
2512   }
2513 }
2514 
2515 Element.addMethods();

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!