NameSpace: SGL_Request.htm

File SGL_Request.htm, 52.4 kB (added by randy, 7 years ago)

SGL Request

Line 
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2 <html><head><title></title><meta http-equiv="Content-type" content="text/html; charset=windows-1251" />
3 <style>
4         table.dBug_array,table.dBug_object,table.dBug_resource,table.dBug_resourceC,table.dBug_xml {
5                 font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:12px;
6         }
7        
8         .dBug_arrayHeader,
9         .dBug_objectHeader,
10         .dBug_resourceHeader,
11         .dBug_resourceCHeader,
12         .dBug_xmlHeader
13                 { font-weight:bold; color:#FFFFFF; }
14        
15         /* array */
16         table.dBug_array { background-color:#006600; }
17         table.dBug_array td { background-color:#FFFFFF; }
18         table.dBug_array td.dBug_arrayHeader { background-color:#009900; }
19         table.dBug_array td.dBug_arrayKey { background-color:#CCFFCC; }
20        
21         /* object */
22         table.dBug_object { background-color:#0000CC; }
23         table.dBug_object td { background-color:#FFFFFF; }
24         table.dBug_object td.dBug_objectHeader { background-color:#4444CC; }
25         table.dBug_object td.dBug_objectKey { background-color:#CCDDFF; }
26        
27         /* resource */
28         table.dBug_resourceC { background-color:#884488; }
29         table.dBug_resourceC td { background-color:#FFFFFF; }
30         table.dBug_resourceC td.dBug_resourceCHeader { background-color:#AA66AA; }
31         table.dBug_resourceC td.dBug_resourceCKey { background-color:#FFDDFF; }
32        
33         /* resource */
34         table.dBug_resource { background-color:#884488; }
35         table.dBug_resource td { background-color:#FFFFFF; }
36         table.dBug_resource td.dBug_resourceHeader { background-color:#AA66AA; }
37         table.dBug_resource td.dBug_resourceKey { background-color:#FFDDFF; }
38         table.dBug_resource td.dBug_resourceKey2 { background-color:#FFDDFF; }
39        
40         /* xml */
41         table.dBug_xml { background-color:#888888; }
42         table.dBug_xml td { background-color:#FFFFFF; }
43         table.dBug_xml td.dBug_xmlHeader { background-color:#AAAAAA; }
44         table.dBug_xml td.dBug_xmlKey { background-color:#DDDDDD; }
45 </style>
46 <script type="text/javascript">
47 /*  Prototype JavaScript framework, version 1.4.0
48  *  (c) 2005 Sam Stephenson <sam@conio.net>
49  *
50  *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
51  *  against the source tree, available from the Prototype darcs repository.
52  *
53  *  Prototype is freely distributable under the terms of an MIT-style license.
54  *
55  *  For details, see the Prototype web site: http://prototype.conio.net/
56  *
57 /*--------------------------------------------------------------------------*/
58
59 var Prototype = {
60   Version: '1.4.0',
61   ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
62
63   emptyFunction: function() {},
64   K: function(x) {return x}
65 }
66
67 var Class = {
68   create: function() {
69     return function() {
70       this.initialize.apply(this, arguments);
71     }
72   }
73 }
74
75 var Abstract = new Object();
76
77 Object.extend = function(destination, source) {
78   for (property in source) {
79     destination[property] = source[property];
80   }
81   return destination;
82 }
83
84 Object.inspect = function(object) {
85   try {
86     if (object == undefined) return 'undefined';
87     if (object == null) return 'null';
88     return object.inspect ? object.inspect() : object.toString();
89   } catch (e) {
90     if (e instanceof RangeError) return '...';
91     throw e;
92   }
93 }
94
95 Function.prototype.bind = function() {
96   var __method = this, args = $A(arguments), object = args.shift();
97   return function() {
98     return __method.apply(object, args.concat($A(arguments)));
99   }
100 }
101
102 Function.prototype.bindAsEventListener = function(object) {
103   var __method = this;
104   return function(event) {
105     return __method.call(object, event || window.event);
106   }
107 }
108
109 Object.extend(Number.prototype, {
110   toColorPart: function() {
111     var digits = this.toString(16);
112     if (this < 16) return '0' + digits;
113     return digits;
114   },
115
116   succ: function() {
117     return this + 1;
118   },
119
120   times: function(iterator) {
121     $R(0, this, true).each(iterator);
122     return this;
123   }
124 });
125
126 var Try = {
127   these: function() {
128     var returnValue;
129
130     for (var i = 0; i < arguments.length; i++) {
131       var lambda = arguments[i];
132       try {
133         returnValue = lambda();
134         break;
135       } catch (e) {}
136     }
137
138     return returnValue;
139   }
140 }
141
142 /*--------------------------------------------------------------------------*/
143
144 var PeriodicalExecuter = Class.create();
145 PeriodicalExecuter.prototype = {
146   initialize: function(callback, frequency) {
147     this.callback = callback;
148     this.frequency = frequency;
149     this.currentlyExecuting = false;
150
151     this.registerCallback();
152   },
153
154   registerCallback: function() {
155     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
156   },
157
158   onTimerEvent: function() {
159     if (!this.currentlyExecuting) {
160       try {
161         this.currentlyExecuting = true;
162         this.callback();
163       } finally {
164         this.currentlyExecuting = false;
165       }
166     }
167   }
168 }
169
170 /*--------------------------------------------------------------------------*/
171
172 function $() {
173   var elements = new Array();
174
175   for (var i = 0; i < arguments.length; i++) {
176     var element = arguments[i];
177     if (typeof element == 'string')
178       element = document.getElementById(element);
179
180     if (arguments.length == 1)
181       return element;
182
183     elements.push(element);
184   }
185
186   return elements;
187 }
188 Object.extend(String.prototype, {
189   stripTags: function() {
190     return this.replace(/<\/?[^>]+>/gi, '');
191   },
192
193   stripScripts: function() {
194     return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
195   },
196
197   extractScripts: function() {
198     var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
199     var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
200     return (this.match(matchAll) || []).map(function(scriptTag) {
201       return (scriptTag.match(matchOne) || ['', ''])[1];
202     });
203   },
204
205   evalScripts: function() {
206     return this.extractScripts().map(eval);
207   },
208
209   escapeHTML: function() {
210     var div = document.createElement('div');
211     var text = document.createTextNode(this);
212     div.appendChild(text);
213     return div.innerHTML;
214   },
215
216   unescapeHTML: function() {
217     var div = document.createElement('div');
218     div.innerHTML = this.stripTags();
219     return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
220   },
221
222   toQueryParams: function() {
223     var pairs = this.match(/^\??(.*)$/)[1].split('&');
224     return pairs.inject({}, function(params, pairString) {
225       var pair = pairString.split('=');
226       params[pair[0]] = pair[1];
227       return params;
228     });
229   },
230
231   toArray: function() {
232     return this.split('');
233   },
234
235   camelize: function() {
236     var oStringList = this.split('-');
237     if (oStringList.length == 1) return oStringList[0];
238
239     var camelizedString = this.indexOf('-') == 0
240       ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
241       : oStringList[0];
242
243     for (var i = 1, len = oStringList.length; i < len; i++) {
244       var s = oStringList[i];
245       camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
246     }
247
248     return camelizedString;
249   },
250
251   inspect: function() {
252     return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
253   }
254 });
255
256 String.prototype.parseQuery = String.prototype.toQueryParams;
257
258 var $break    = new Object();
259 var $continue = new Object();
260
261 var Enumerable = {
262   each: function(iterator) {
263     var index = 0;
264     try {
265       this._each(function(value) {
266         try {
267           iterator(value, index++);
268         } catch (e) {
269           if (e != $continue) throw e;
270         }
271       });
272     } catch (e) {
273       if (e != $break) throw e;
274     }
275   },
276
277   all: function(iterator) {
278     var result = true;
279     this.each(function(value, index) {
280       result = result && !!(iterator || Prototype.K)(value, index);
281       if (!result) throw $break;
282     });
283     return result;
284   },
285
286   any: function(iterator) {
287     var result = true;
288     this.each(function(value, index) {
289       if (result = !!(iterator || Prototype.K)(value, index))
290         throw $break;
291     });
292     return result;
293   },
294
295   collect: function(iterator) {
296     var results = [];
297     this.each(function(value, index) {
298       results.push(iterator(value, index));
299     });
300     return results;
301   },
302
303   detect: function (iterator) {
304     var result;
305     this.each(function(value, index) {
306       if (iterator(value, index)) {
307         result = value;
308         throw $break;
309       }
310     });
311     return result;
312   },
313
314   findAll: function(iterator) {
315     var results = [];
316     this.each(function(value, index) {
317       if (iterator(value, index))
318         results.push(value);
319     });
320     return results;
321   },
322
323   grep: function(pattern, iterator) {
324     var results = [];
325     this.each(function(value, index) {
326       var stringValue = value.toString();
327       if (stringValue.match(pattern))
328         results.push((iterator || Prototype.K)(value, index));
329     })
330     return results;
331   },
332
333   include: function(object) {
334     var found = false;
335     this.each(function(value) {
336       if (value == object) {
337         found = true;
338         throw $break;
339       }
340     });
341     return found;
342   },
343
344   inject: function(memo, iterator) {
345     this.each(function(value, index) {
346       memo = iterator(memo, value, index);
347     });
348     return memo;
349   },
350
351   invoke: function(method) {
352     var args = $A(arguments).slice(1);
353     return this.collect(function(value) {
354       return value[method].apply(value, args);
355     });
356   },
357
358   max: function(iterator) {
359     var result;
360     this.each(function(value, index) {
361       value = (iterator || Prototype.K)(value, index);
362       if (value >= (result || value))
363         result = value;
364     });
365     return result;
366   },
367
368   min: function(iterator) {
369     var result;
370     this.each(function(value, index) {
371       value = (iterator || Prototype.K)(value, index);
372       if (value <= (result || value))
373         result = value;
374     });
375     return result;
376   },
377
378   partition: function(iterator) {
379     var trues = [], falses = [];
380     this.each(function(value, index) {
381       ((iterator || Prototype.K)(value, index) ?
382         trues : falses).push(value);
383     });
384     return [trues, falses];
385   },
386
387   pluck: function(property) {
388     var results = [];
389     this.each(function(value, index) {
390       results.push(value[property]);
391     });
392     return results;
393   },
394
395   reject: function(iterator) {
396     var results = [];
397     this.each(function(value, index) {
398       if (!iterator(value, index))
399         results.push(value);
400     });
401     return results;
402   },
403
404   sortBy: function(iterator) {
405     return this.collect(function(value, index) {
406       return {value: value, criteria: iterator(value, index)};
407     }).sort(function(left, right) {
408       var a = left.criteria, b = right.criteria;
409       return a < b ? -1 : a > b ? 1 : 0;
410     }).pluck('value');
411   },
412
413   toArray: function() {
414     return this.collect(Prototype.K);
415   },
416
417   zip: function() {
418     var iterator = Prototype.K, args = $A(arguments);
419     if (typeof args.last() == 'function')
420       iterator = args.pop();
421
422     var collections = [this].concat(args).map($A);
423     return this.map(function(value, index) {
424       iterator(value = collections.pluck(index));
425       return value;
426     });
427   },
428
429   inspect: function() {
430     return '#<Enumerable:' + this.toArray().inspect() + '>';
431   }
432 }
433
434 Object.extend(Enumerable, {
435   map:     Enumerable.collect,
436   find:    Enumerable.detect,
437   select:  Enumerable.findAll,
438   member:  Enumerable.include,
439   entries: Enumerable.toArray
440 });
441 var $A = Array.from = function(iterable) {
442   if (!iterable) return [];
443   if (iterable.toArray) {
444     return iterable.toArray();
445   } else {
446     var results = [];
447     for (var i = 0; i < iterable.length; i++)
448       results.push(iterable[i]);
449     return results;
450   }
451 }
452
453 Object.extend(Array.prototype, Enumerable);
454
455 Array.prototype._reverse = Array.prototype.reverse;
456
457 Object.extend(Array.prototype, {
458   _each: function(iterator) {
459     for (var i = 0; i < this.length; i++)
460       iterator(this[i]);
461   },
462
463   clear: function() {
464     this.length = 0;
465     return this;
466   },
467
468   first: function() {
469     return this[0];
470   },
471
472   last: function() {
473     return this[this.length - 1];
474   },
475
476   compact: function() {
477     return this.select(function(value) {
478       return value != undefined || value != null;
479     });
480   },
481
482   flatten: function() {
483     return this.inject([], function(array, value) {
484       return array.concat(value.constructor == Array ?
485         value.flatten() : [value]);
486     });
487   },
488
489   without: function() {
490     var values = $A(arguments);
491     return this.select(function(value) {
492       return !values.include(value);
493     });
494   },
495
496   indexOf: function(object) {
497     for (var i = 0; i < this.length; i++)
498       if (this[i] == object) return i;
499     return -1;
500   },
501
502   reverse: function(inline) {
503     return (inline !== false ? this : this.toArray())._reverse();
504   },
505
506   shift: function() {
507     var result = this[0];
508     for (var i = 0; i < this.length - 1; i++)
509       this[i] = this[i + 1];
510     this.length--;
511     return result;
512   },
513
514   inspect: function() {
515     return '[' + this.map(Object.inspect).join(', ') + ']';
516   }
517 });
518 var Hash = {
519   _each: function(iterator) {
520     for (key in this) {
521       var value = this[key];
522       if (typeof value == 'function') continue;
523
524       var pair = [key, value];
525       pair.key = key;
526       pair.value = value;
527       iterator(pair);
528     }
529   },
530
531   keys: function() {
532     return this.pluck('key');
533   },
534
535   values: function() {
536     return this.pluck('value');
537   },
538
539   merge: function(hash) {
540     return $H(hash).inject($H(this), function(mergedHash, pair) {
541       mergedHash[pair.key] = pair.value;
542       return mergedHash;
543     });
544   },
545
546   toQueryString: function() {
547     return this.map(function(pair) {
548       return pair.map(encodeURIComponent).join('=');
549     }).join('&');
550   },
551
552   inspect: function() {
553     return '#<Hash:{' + this.map(function(pair) {
554       return pair.map(Object.inspect).join(': ');
555     }).join(', ') + '}>';
556   }
557 }
558
559 function $H(object) {
560   var hash = Object.extend({}, object || {});
561   Object.extend(hash, Enumerable);
562   Object.extend(hash, Hash);
563   return hash;
564 }
565 ObjectRange = Class.create();
566 Object.extend(ObjectRange.prototype, Enumerable);
567 Object.extend(ObjectRange.prototype, {
568   initialize: function(start, end, exclusive) {
569     this.start = start;
570     this.end = end;
571     this.exclusive = exclusive;
572   },
573
574   _each: function(iterator) {
575     var value = this.start;
576     do {
577       iterator(value);
578       value = value.succ();
579     } while (this.include(value));
580   },
581
582   include: function(value) {
583     if (value < this.start)
584       return false;
585     if (this.exclusive)
586       return value < this.end;
587     return value <= this.end;
588   }
589 });
590
591 var $R = function(start, end, exclusive) {
592   return new ObjectRange(start, end, exclusive);
593 }
594
595 var Ajax = {
596   getTransport: function() {
597     return Try.these(
598       function() {return new ActiveXObject('Msxml2.XMLHTTP')},
599       function() {return new ActiveXObject('Microsoft.XMLHTTP')},
600       function() {return new XMLHttpRequest()}
601     ) || false;
602   },
603
604   activeRequestCount: 0
605 }
606
607 Ajax.Responders = {
608   responders: [],
609
610   _each: function(iterator) {
611     this.responders._each(iterator);
612   },
613
614   register: function(responderToAdd) {
615     if (!this.include(responderToAdd))
616       this.responders.push(responderToAdd);
617   },
618
619   unregister: function(responderToRemove) {
620     this.responders = this.responders.without(responderToRemove);
621   },
622
623   dispatch: function(callback, request, transport, json) {
624     this.each(function(responder) {
625       if (responder[callback] && typeof responder[callback] == 'function') {
626         try {
627           responder[callback].apply(responder, [request, transport, json]);
628         } catch (e) {}
629       }
630     });
631   }
632 };
633
634 Object.extend(Ajax.Responders, Enumerable);
635
636 Ajax.Responders.register({
637   onCreate: function() {
638     Ajax.activeRequestCount++;
639   },
640
641   onComplete: function() {
642     Ajax.activeRequestCount--;
643   }
644 });
645
646 Ajax.Base = function() {};
647 Ajax.Base.prototype = {
648   setOptions: function(options) {
649     this.options = {
650       method:       'post',
651       asynchronous: true,
652       parameters:   ''
653     }
654     Object.extend(this.options, options || {});
655   },
656
657   responseIsSuccess: function() {
658     return this.transport.status == undefined
659         || this.transport.status == 0
660         || (this.transport.status >= 200 && this.transport.status < 300);
661   },
662
663   responseIsFailure: function() {
664     return !this.responseIsSuccess();
665   }
666 }
667
668 Ajax.Request = Class.create();
669 Ajax.Request.Events =
670   ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
671
672 Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
673   initialize: function(url, options) {
674     this.transport = Ajax.getTransport();
675     this.setOptions(options);
676     this.request(url);
677   },
678
679   request: function(url) {
680     var parameters = this.options.parameters || '';
681     if (parameters.length > 0) parameters += '&_=';
682
683     try {
684       this.url = url;
685       if (this.options.method == 'get' && parameters.length > 0)
686         this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
687
688       Ajax.Responders.dispatch('onCreate', this, this.transport);
689
690       this.transport.open(this.options.method, this.url,
691         this.options.asynchronous);
692
693       if (this.options.asynchronous) {
694         this.transport.onreadystatechange = this.onStateChange.bind(this);
695         setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
696       }
697
698       this.setRequestHeaders();
699
700       var body = this.options.postBody ? this.options.postBody : parameters;
701       this.transport.send(this.options.method == 'post' ? body : null);
702
703     } catch (e) {
704       this.dispatchException(e);
705     }
706   },
707
708   setRequestHeaders: function() {
709     var requestHeaders =
710       ['X-Requested-With', 'XMLHttpRequest',
711        'X-Prototype-Version', Prototype.Version];
712
713     if (this.options.method == 'post') {
714       requestHeaders.push('Content-type',
715         'application/x-www-form-urlencoded');
716
717       /* Force "Connection: close" for Mozilla browsers to work around
718        * a bug where XMLHttpReqeuest sends an incorrect Content-length
719        * header. See Mozilla Bugzilla #246651.
720        */
721       if (this.transport.overrideMimeType)
722         requestHeaders.push('Connection', 'close');
723     }
724
725     if (this.options.requestHeaders)
726       requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
727
728     for (var i = 0; i < requestHeaders.length; i += 2)
729       this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
730   },
731
732   onStateChange: function() {
733     var readyState = this.transport.readyState;
734     if (readyState != 1)
735       this.respondToReadyState(this.transport.readyState);
736   },
737
738   header: function(name) {
739     try {
740       return this.transport.getResponseHeader(name);
741     } catch (e) {}
742   },
743
744   evalJSON: function() {
745     try {
746       return eval(this.header('X-JSON'));
747     } catch (e) {}
748   },
749
750   evalResponse: function() {
751     try {
752       return eval(this.transport.responseText);
753     } catch (e) {
754       this.dispatchException(e);
755     }
756   },
757
758   respondToReadyState: function(readyState) {
759     var event = Ajax.Request.Events[readyState];
760     var transport = this.transport, json = this.evalJSON();
761
762     if (event == 'Complete') {
763       try {
764         (this.options['on' + this.transport.status]
765          || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
766          || Prototype.emptyFunction)(transport, json);
767       } catch (e) {
768         this.dispatchException(e);
769       }
770
771       if ((this.header('Content-type') || '').match(/^text\/javascript/i))
772         this.evalResponse();
773     }
774
775     try {
776       (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
777       Ajax.Responders.dispatch('on' + event, this, transport, json);
778     } catch (e) {
779       this.dispatchException(e);
780     }
781
782     /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
783     if (event == 'Complete')
784       this.transport.onreadystatechange = Prototype.emptyFunction;
785   },
786
787   dispatchException: function(exception) {
788     (this.options.onException || Prototype.emptyFunction)(this, exception);
789     Ajax.Responders.dispatch('onException', this, exception);
790   }
791 });
792
793 Ajax.Updater = Class.create();
794
795 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
796   initialize: function(container, url, options) {
797     this.containers = {
798       success: container.success ? $(container.success) : $(container),
799       failure: container.failure ? $(container.failure) :
800         (container.success ? null : $(container))
801     }
802
803     this.transport = Ajax.getTransport();
804     this.setOptions(options);
805
806     var onComplete = this.options.onComplete || Prototype.emptyFunction;
807     this.options.onComplete = (function(transport, object) {
808       this.updateContent();
809       onComplete(transport, object);
810     }).bind(this);
811
812     this.request(url);
813   },
814
815   updateContent: function() {
816     var receiver = this.responseIsSuccess() ?
817       this.containers.success : this.containers.failure;
818     var response = this.transport.responseText;
819
820     if (!this.options.evalScripts)
821       response = response.stripScripts();
822
823     if (receiver) {
824       if (this.options.insertion) {
825         new this.options.insertion(receiver, response);
826       } else {
827         Element.update(receiver, response);
828       }
829     }
830
831     if (this.responseIsSuccess()) {
832       if (this.onComplete)
833         setTimeout(this.onComplete.bind(this), 10);
834     }
835   }
836 });
837
838 Ajax.PeriodicalUpdater = Class.create();
839 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
840   initialize: function(container, url, options) {
841     this.setOptions(options);
842     this.onComplete = this.options.onComplete;
843
844     this.frequency = (this.options.frequency || 2);
845     this.decay = (this.options.decay || 1);
846
847     this.updater = {};
848     this.container = container;
849     this.url = url;
850
851     this.start();
852   },
853
854   start: function() {
855     this.options.onComplete = this.updateComplete.bind(this);
856     this.onTimerEvent();
857   },
858
859   stop: function() {
860     this.updater.onComplete = undefined;
861     clearTimeout(this.timer);
862     (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
863   },
864
865   updateComplete: function(request) {
866     if (this.options.decay) {
867       this.decay = (request.responseText == this.lastText ?
868         this.decay * this.options.decay : 1);
869
870       this.lastText = request.responseText;
871     }
872     this.timer = setTimeout(this.onTimerEvent.bind(this),
873       this.decay * this.frequency * 1000);
874   },
875
876   onTimerEvent: function() {
877     this.updater = new Ajax.Updater(this.container, this.url, this.options);
878   }
879 });
880 document.getElementsByClassName = function(className, parentElement) {
881   var children = ($(parentElement) || document.body).getElementsByTagName('*');
882   return $A(children).inject([], function(elements, child) {
883     if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
884       elements.push(child);
885     return elements;
886   });
887 }
888
889 /*--------------------------------------------------------------------------*/
890
891 if (!window.Element) {
892   var Element = new Object();
893 }
894
895 Object.extend(Element, {
896   visible: function(element) {
897     return $(element).style.display != 'none';
898   },
899
900   toggle: function() {
901     for (var i = 0; i < arguments.length; i++) {
902       var element = $(arguments[i]);
903       Element[Element.visible(element) ? 'hide' : 'show'](element);
904     }
905   },
906
907   hide: function() {
908     for (var i = 0; i < arguments.length; i++) {
909       var element = $(arguments[i]);
910       element.style.display = 'none';
911     }
912   },
913
914   show: function() {
915     for (var i = 0; i < arguments.length; i++) {
916       var element = $(arguments[i]);
917       element.style.display = '';
918     }
919   },
920
921   remove: function(element) {
922     element = $(element);
923     element.parentNode.removeChild(element);
924   },
925
926   update: function(element, html) {
927     $(element).innerHTML = html.stripScripts();
928     setTimeout(function() {html.evalScripts()}, 10);
929   },
930
931   getHeight: function(element) {
932     element = $(element);
933     return element.offsetHeight;
934   },
935
936   classNames: function(element) {
937     return new Element.ClassNames(element);
938   },
939
940   hasClassName: function(element, className) {
941     if (!(element = $(element))) return;
942     return Element.classNames(element).include(className);
943   },
944
945   addClassName: function(element, className) {
946     if (!(element = $(element))) return;
947     return Element.classNames(element).add(className);
948   },
949
950   removeClassName: function(element, className) {
951     if (!(element = $(element))) return;
952     return Element.classNames(element).remove(className);
953   },
954
955   // removes whitespace-only text node children
956   cleanWhitespace: function(element) {
957     element = $(element);
958     for (var i = 0; i < element.childNodes.length; i++) {
959       var node = element.childNodes[i];
960       if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
961         Element.remove(node);
962     }
963   },
964
965   empty: function(element) {
966     return $(element).innerHTML.match(/^\s*$/);
967   },
968
969   scrollTo: function(element) {
970     element = $(element);
971     var x = element.x ? element.x : element.offsetLeft,
972         y = element.y ? element.y : element.offsetTop;
973     window.scrollTo(x, y);
974   },
975
976   getStyle: function(element, style) {
977     element = $(element);
978     var value = element.style[style.camelize()];
979     if (!value) {
980       if (document.defaultView && document.defaultView.getComputedStyle) {
981         var css = document.defaultView.getComputedStyle(element, null);
982         value = css ? css.getPropertyValue(style) : null;
983       } else if (element.currentStyle) {
984         value = element.currentStyle[style.camelize()];
985       }
986     }
987
988     if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
989       if (Element.getStyle(element, 'position') == 'static') value = 'auto';
990
991     return value == 'auto' ? null : value;
992   },
993
994   setStyle: function(element, style) {
995     element = $(element);
996     for (name in style)
997       element.style[name.camelize()] = style[name];
998   },
999
1000   getDimensions: function(element) {
1001     element = $(element);
1002     if (Element.getStyle(element, 'display') != 'none')
1003       return {width: element.offsetWidth, height: element.offsetHeight};
1004
1005     // All *Width and *Height properties give 0 on elements with display none,
1006     // so enable the element temporarily
1007     var els = element.style;
1008     var originalVisibility = els.visibility;
1009     var originalPosition = els.position;
1010     els.visibility = 'hidden';
1011     els.position = 'absolute';
1012     els.display = '';
1013     var originalWidth = element.clientWidth;
1014     var originalHeight = element.clientHeight;
1015     els.display = 'none';
1016     els.position = originalPosition;
1017     els.visibility = originalVisibility;
1018     return {width: originalWidth, height: originalHeight};
1019   },
1020
1021   makePositioned: function(element) {
1022     element = $(element);
1023     var pos = Element.getStyle(element, 'position');
1024     if (pos == 'static' || !pos) {
1025       element._madePositioned = true;
1026       element.style.position = 'relative';
1027       // Opera returns the offset relative to the positioning context, when an
1028       // element is position relative but top and left have not been defined
1029       if (window.opera) {
1030         element.style.top = 0;
1031         element.style.left = 0;
1032       }
1033     }
1034   },
1035
1036   undoPositioned: function(element) {
1037     element = $(element);
1038     if (element._madePositioned) {
1039       element._madePositioned = undefined;
1040       element.style.position =
1041         element.style.top =
1042         element.style.left =
1043         element.style.bottom =
1044         element.style.right = '';
1045     }
1046   },
1047
1048   makeClipping: function(element) {
1049     element = $(element);
1050     if (element._overflow) return;
1051     element._overflow = element.style.overflow;
1052     if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1053       element.style.overflow = 'hidden';
1054   },
1055
1056   undoClipping: function(element) {
1057     element = $(element);
1058     if (element._overflow) return;
1059     element.style.overflow = element._overflow;
1060     element._overflow = undefined;
1061   }
1062 });
1063
1064 var Toggle = new Object();
1065 Toggle.display = Element.toggle;
1066
1067 /*--------------------------------------------------------------------------*/
1068
1069 Abstract.Insertion = function(adjacency) {
1070   this.adjacency = adjacency;
1071 }
1072
1073 Abstract.Insertion.prototype = {
1074   initialize: function(element, content) {
1075     this.element = $(element);
1076     this.content = content.stripScripts();
1077
1078     if (this.adjacency && this.element.insertAdjacentHTML) {
1079       try {
1080         this.element.insertAdjacentHTML(this.adjacency, this.content);
1081       } catch (e) {
1082         if (this.element.tagName.toLowerCase() == 'tbody') {
1083           this.insertContent(this.contentFromAnonymousTable());
1084         } else {
1085           throw e;
1086         }
1087       }
1088     } else {
1089       this.range = this.element.ownerDocument.createRange();
1090       if (this.initializeRange) this.initializeRange();
1091       this.insertContent([this.range.createContextualFragment(this.content)]);
1092     }
1093
1094     setTimeout(function() {content.evalScripts()}, 10);
1095   },
1096
1097   contentFromAnonymousTable: function() {
1098     var div = document.createElement('div');
1099     div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1100     return $A(div.childNodes[0].childNodes[0].childNodes);
1101   }
1102 }
1103
1104 var Insertion = new Object();
1105
1106 Insertion.Before = Class.create();
1107 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1108   initializeRange: function() {
1109     this.range.setStartBefore(this.element);
1110   },
1111
1112   insertContent: function(fragments) {
1113     fragments.each((function(fragment) {
1114       this.element.parentNode.insertBefore(fragment, this.element);
1115     }).bind(this));
1116   }
1117 });
1118
1119 Insertion.Top = Class.create();
1120 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1121   initializeRange: function() {
1122     this.range.selectNodeContents(this.element);
1123     this.range.collapse(true);
1124   },
1125
1126   insertContent: function(fragments) {
1127     fragments.reverse(false).each((function(fragment) {
1128       this.element.insertBefore(fragment, this.element.firstChild);
1129     }).bind(this));
1130   }
1131 });
1132
1133 Insertion.Bottom = Class.create();
1134 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1135   initializeRange: function() {
1136     this.range.selectNodeContents(this.element);
1137     this.range.collapse(this.element);
1138   },
1139
1140   insertContent: function(fragments) {
1141     fragments.each((function(fragment) {
1142       this.element.appendChild(fragment);
1143     }).bind(this));
1144   }
1145 });
1146
1147 Insertion.After = Class.create();
1148 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1149   initializeRange: function() {
1150     this.range.setStartAfter(this.element);
1151   },
1152
1153   insertContent: function(fragments) {
1154     fragments.each((function(fragment) {
1155       this.element.parentNode.insertBefore(fragment,
1156         this.element.nextSibling);
1157     }).bind(this));
1158   }
1159 });
1160
1161 /*--------------------------------------------------------------------------*/
1162
1163 Element.ClassNames = Class.create();
1164 Element.ClassNames.prototype = {
1165   initialize: function(element) {
1166     this.element = $(element);
1167   },
1168
1169   _each: function(iterator) {
1170     this.element.className.split(/\s+/).select(function(name) {
1171       return name.length > 0;
1172     })._each(iterator);
1173   },
1174
1175   set: function(className) {
1176     this.element.className = className;
1177   },
1178
1179   add: function(classNameToAdd) {
1180     if (this.include(classNameToAdd)) return;
1181     this.set(this.toArray().concat(classNameToAdd).join(' '));
1182   },
1183
1184   remove: function(classNameToRemove) {
1185     if (!this.include(classNameToRemove)) return;
1186     this.set(this.select(function(className) {
1187       return className != classNameToRemove;
1188     }).join(' '));
1189   },
1190
1191   toString: function() {
1192     return this.toArray().join(' ');
1193   }
1194 }
1195
1196 Object.extend(Element.ClassNames.prototype, Enumerable);
1197 var Field = {
1198   clear: function() {
1199     for (var i = 0; i < arguments.length; i++)
1200       $(arguments[i]).value = '';
1201   },
1202
1203   focus: function(element) {
1204     $(element).focus();
1205   },
1206
1207   present: function() {
1208     for (var i = 0; i < arguments.length; i++)
1209       if ($(arguments[i]).value == '') return false;
1210     return true;
1211   },
1212
1213   select: function(element) {
1214     $(element).select();
1215   },
1216
1217   activate: function(element) {
1218     element = $(element);
1219     element.focus();
1220     if (element.select)
1221       element.select();
1222   }
1223 }
1224
1225 /*--------------------------------------------------------------------------*/
1226
1227 var Form = {
1228   serialize: function(form) {
1229     var elements = Form.getElements($(form));
1230     var queryComponents = new Array();
1231
1232     for (var i = 0; i < elements.length; i++) {
1233       var queryComponent = Form.Element.serialize(elements[i]);
1234       if (queryComponent)
1235         queryComponents.push(queryComponent);
1236     }
1237
1238     return queryComponents.join('&');
1239   },
1240
1241   getElements: function(form) {
1242     form = $(form);
1243     var elements = new Array();
1244
1245     for (tagName in Form.Element.Serializers) {
1246       var tagElements = form.getElementsByTagName(tagName);
1247       for (var j = 0; j < tagElements.length; j++)
1248         elements.push(tagElements[j]);
1249     }
1250     return elements;
1251   },
1252
1253   getInputs: function(form, typeName, name) {
1254     form = $(form);
1255     var inputs = form.getElementsByTagName('input');
1256
1257     if (!typeName && !name)
1258       return inputs;
1259
1260     var matchingInputs = new Array();
1261     for (var i = 0; i < inputs.length; i++) {
1262       var input = inputs[i];
1263       if ((typeName && input.type != typeName) ||
1264           (name && input.name != name))
1265         continue;
1266       matchingInputs.push(input);
1267     }
1268
1269     return matchingInputs;
1270   },
1271
1272   disable: function(form) {
1273     var elements = Form.getElements(form);
1274     for (var i = 0; i < elements.length; i++) {
1275       var element = elements[i];
1276       element.blur();
1277       element.disabled = 'true';
1278     }
1279   },
1280
1281   enable: function(form) {
1282     var elements = Form.getElements(form);
1283     for (var i = 0; i < elements.length; i++) {
1284       var element = elements[i];
1285       element.disabled = '';
1286     }
1287   },
1288
1289   findFirstElement: function(form) {
1290     return Form.getElements(form).find(function(element) {
1291       return element.type != 'hidden' && !element.disabled &&
1292         ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1293     });
1294   },
1295
1296   focusFirstElement: function(form) {
1297     Field.activate(Form.findFirstElement(form));
1298   },
1299
1300   reset: function(form) {
1301     $(form).reset();
1302   }
1303 }
1304
1305 Form.Element = {
1306   serialize: function(element) {
1307     element = $(element);
1308     var method = element.tagName.toLowerCase();
1309     var parameter = Form.Element.Serializers[method](element);
1310
1311     if (parameter) {
1312       var key = encodeURIComponent(parameter[0]);
1313       if (key.length == 0) return;
1314
1315       if (parameter[1].constructor != Array)
1316         parameter[1] = [parameter[1]];
1317
1318       return parameter[1].map(function(value) {
1319         return key + '=' + encodeURIComponent(value);
1320       }).join('&');
1321     }
1322   },
1323
1324   getValue: function(element) {
1325     element = $(element);
1326     var method = element.tagName.toLowerCase();
1327     var parameter = Form.Element.Serializers[method](element);
1328
1329     if (parameter)
1330       return parameter[1];
1331   }
1332 }
1333
1334 Form.Element.Serializers = {
1335   input: function(element) {
1336     switch (element.type.toLowerCase()) {
1337       case 'submit':
1338       case 'hidden':
1339       case 'password':
1340       case 'text':
1341         return Form.Element.Serializers.textarea(element);
1342       case 'checkbox':
1343       case 'radio':
1344         return Form.Element.Serializers.inputSelector(element);
1345     }
1346     return false;
1347   },
1348
1349   inputSelector: function(element) {
1350     if (element.checked)
1351       return [element.name, element.value];
1352   },
1353
1354   textarea: function(element) {
1355     return [element.name, element.value];
1356   },
1357
1358   select: function(element) {
1359     return Form.Element.Serializers[element.type == 'select-one' ?
1360       'selectOne' : 'selectMany'](element);
1361   },
1362
1363   selectOne: function(element) {
1364     var value = '', opt, index = element.selectedIndex;
1365     if (index >= 0) {
1366       opt = element.options[index];
1367       value = opt.value;
1368       if (!value && !('value' in opt))
1369         value = opt.text;
1370     }
1371     return [element.name, value];
1372   },
1373
1374   selectMany: function(element) {
1375     var value = new Array();
1376     for (var i = 0; i < element.length; i++) {
1377       var opt = element.options[i];
1378       if (opt.selected) {
1379         var optValue = opt.value;
1380         if (!optValue && !('value' in opt))
1381           optValue = opt.text;
1382         value.push(optValue);
1383       }
1384     }
1385     return [element.name, value];
1386   }
1387 }
1388
1389 /*--------------------------------------------------------------------------*/
1390
1391 var $F = Form.Element.getValue;
1392
1393 /*--------------------------------------------------------------------------*/
1394
1395 Abstract.TimedObserver = function() {}
1396 Abstract.TimedObserver.prototype = {
1397   initialize: function(element, frequency, callback) {
1398     this.frequency = frequency;
1399     this.element   = $(element);
1400     this.callback  = callback;
1401
1402     this.lastValue = this.getValue();
1403     this.registerCallback();
1404   },
1405
1406   registerCallback: function() {
1407     setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1408   },
1409
1410   onTimerEvent: function() {
1411     var value = this.getValue();
1412     if (this.lastValue != value) {
1413       this.callback(this.element, value);
1414       this.lastValue = value;
1415     }
1416   }
1417 }
1418
1419 Form.Element.Observer = Class.create();
1420 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1421   getValue: function() {
1422     return Form.Element.getValue(this.element);
1423   }
1424 });
1425
1426 Form.Observer = Class.create();
1427 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1428   getValue: function() {
1429     return Form.serialize(this.element);
1430   }
1431 });
1432
1433 /*--------------------------------------------------------------------------*/
1434
1435 Abstract.EventObserver = function() {}
1436 Abstract.EventObserver.prototype = {
1437   initialize: function(element, callback) {
1438     this.element  = $(element);
1439     this.callback = callback;
1440
1441     this.lastValue = this.getValue();
1442     if (this.element.tagName.toLowerCase() == 'form')
1443       this.registerFormCallbacks();
1444     else
1445       this.registerCallback(this.element);
1446   },
1447
1448   onElementEvent: function() {
1449     var value = this.getValue();
1450     if (this.lastValue != value) {
1451       this.callback(this.element, value);
1452       this.lastValue = value;
1453     }
1454   },
1455
1456   registerFormCallbacks: function() {
1457     var elements = Form.getElements(this.element);
1458     for (var i = 0; i < elements.length; i++)
1459       this.registerCallback(elements[i]);
1460   },
1461
1462   registerCallback: function(element) {
1463     if (element.type) {
1464       switch (element.type.toLowerCase()) {
1465         case 'checkbox':
1466         case 'radio':
1467           Event.observe(element, 'click', this.onElementEvent.bind(this));
1468           break;
1469         case 'password':
1470         case 'text':
1471         case 'textarea':
1472         case 'select-one':
1473         case 'select-multiple':
1474           Event.observe(element, 'change', this.onElementEvent.bind(this));
1475           break;
1476       }
1477     }
1478   }
1479 }
1480
1481 Form.Element.EventObserver = Class.create();
1482 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1483   getValue: function() {
1484     return Form.Element.getValue(this.element);
1485   }
1486 });
1487
1488 Form.EventObserver = Class.create();
1489 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1490   getValue: function() {
1491     return Form.serialize(this.element);
1492   }
1493 });
1494 if (!window.Event) {
1495   var Event = new Object();
1496 }
1497
1498 Object.extend(Event, {
1499   KEY_BACKSPACE: 8,
1500   KEY_TAB:       9,
1501   KEY_RETURN:   13,
1502   KEY_ESC:      27,
1503   KEY_LEFT:     37,
1504   KEY_UP:       38,
1505   KEY_RIGHT:    39,
1506   KEY_DOWN:     40,
1507   KEY_DELETE:   46,
1508
1509   element: function(event) {
1510     return event.target || event.srcElement;
1511   },
1512
1513   isLeftClick: function(event) {
1514     return (((event.which) && (event.which == 1)) ||
1515             ((event.button) && (event.button == 1)));
1516   },
1517
1518   pointerX: function(event) {
1519     return event.pageX || (event.clientX +
1520       (document.documentElement.scrollLeft || document.body.scrollLeft));
1521   },
1522
1523   pointerY: function(event) {
1524     return event.pageY || (event.clientY +
1525       (document.documentElement.scrollTop || document.body.scrollTop));
1526   },
1527
1528   stop: function(event) {
1529     if (event.preventDefault) {
1530       event.preventDefault();
1531       event.stopPropagation();
1532     } else {
1533       event.returnValue = false;
1534       event.cancelBubble = true;
1535     }
1536   },
1537
1538   // find the first node with the given tagName, starting from the
1539   // node the event was triggered on; traverses the DOM upwards
1540   findElement: function(event, tagName) {
1541     var element = Event.element(event);
1542     while (element.parentNode && (!element.tagName ||
1543         (element.tagName.toUpperCase() != tagName.toUpperCase())))
1544       element = element.parentNode;
1545     return element;
1546   },
1547
1548   observers: false,
1549
1550   _observeAndCache: function(element, name, observer, useCapture) {
1551     if (!this.observers) this.observers = [];
1552     if (element.addEventListener) {
1553       this.observers.push([element, name, observer, useCapture]);
1554       element.addEventListener(name, observer, useCapture);
1555     } else if (element.attachEvent) {
1556       this.observers.push([element, name, observer, useCapture]);
1557       element.attachEvent('on' + name, observer);
1558     }
1559   },
1560
1561   unloadCache: function() {
1562     if (!Event.observers) return;
1563     for (var i = 0; i < Event.observers.length; i++) {
1564       Event.stopObserving.apply(this, Event.observers[i]);
1565       Event.observers[i][0] = null;
1566     }
1567     Event.observers = false;
1568   },
1569
1570   observe: function(element, name, observer, useCapture) {
1571     var element = $(element);
1572     useCapture = useCapture || false;
1573
1574     if (name == 'keypress' &&
1575         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1576         || element.attachEvent))
1577       name = 'keydown';
1578
1579     this._observeAndCache(element, name, observer, useCapture);
1580   },
1581
1582   stopObserving: function(element, name, observer, useCapture) {
1583     var element = $(element);
1584     useCapture = useCapture || false;
1585
1586     if (name == 'keypress' &&
1587         (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1588         || element.detachEvent))
1589       name = 'keydown';
1590
1591     if (element.removeEventListener) {
1592       element.removeEventListener(name, observer, useCapture);
1593     } else if (element.detachEvent) {
1594       element.detachEvent('on' + name, observer);
1595     }
1596   }
1597 });
1598
1599 /* prevent memory leaks in IE */
1600 Event.observe(window, 'unload', Event.unloadCache, false);
1601 var Position = {
1602   // set to true if needed, warning: firefox performance problems
1603   // NOT neeeded for page scrolling, only if draggable contained in
1604   // scrollable elements
1605   includeScrollOffsets: false,
1606
1607   // must be called before calling withinIncludingScrolloffset, every time the
1608   // page is scrolled
1609   prepare: function() {
1610     this.deltaX =  window.pageXOffset
1611                 || document.documentElement.scrollLeft
1612                 || document.body.scrollLeft
1613                 || 0;
1614     this.deltaY =  window.pageYOffset
1615                 || document.documentElement.scrollTop
1616                 || document.body.scrollTop
1617                 || 0;
1618   },
1619
1620   realOffset: function(element) {
1621     var valueT = 0, valueL = 0;
1622     do {
1623       valueT += element.scrollTop  || 0;
1624       valueL += element.scrollLeft || 0;
1625       element = element.parentNode;
1626     } while (element);
1627     return [valueL, valueT];
1628   },
1629
1630   cumulativeOffset: function(element) {
1631     var valueT = 0, valueL = 0;
1632     do {
1633       valueT += element.offsetTop  || 0;
1634       valueL += element.offsetLeft || 0;
1635       element = element.offsetParent;
1636     } while (element);
1637     return [valueL, valueT];
1638   },
1639
1640   positionedOffset: function(element) {
1641     var valueT = 0, valueL = 0;
1642     do {
1643       valueT += element.offsetTop  || 0;
1644       valueL += element.offsetLeft || 0;
1645       element = element.offsetParent;
1646       if (element) {
1647         p = Element.getStyle(element, 'position');
1648         if (p == 'relative' || p == 'absolute') break;
1649       }
1650     } while (element);
1651     return [valueL, valueT];
1652   },
1653
1654   offsetParent: function(element) {
1655     if (element.offsetParent) return element.offsetParent;
1656     if (element == document.body) return element;
1657
1658     while ((element = element.parentNode) && element != document.body)
1659       if (Element.getStyle(element, 'position') != 'static')
1660         return element;
1661
1662     return document.body;
1663   },
1664
1665   // caches x/y coordinate pair to use with overlap
1666   within: function(element, x, y) {
1667     if (this.includeScrollOffsets)
1668       return this.withinIncludingScrolloffsets(element, x, y);
1669     this.xcomp = x;
1670     this.ycomp = y;
1671     this.offset = this.cumulativeOffset(element);
1672
1673     return (y >= this.offset[1] &&
1674             y <  this.offset[1] + element.offsetHeight &&
1675             x >= this.offset[0] &&
1676             x <  this.offset[0] + element.offsetWidth);
1677   },
1678
1679   withinIncludingScrolloffsets: function(element, x, y) {
1680     var offsetcache = this.realOffset(element);
1681
1682     this.xcomp = x + offsetcache[0] - this.deltaX;
1683     this.ycomp = y + offsetcache[1] - this.deltaY;
1684     this.offset = this.cumulativeOffset(element);
1685
1686     return (this.ycomp >= this.offset[1] &&
1687             this.ycomp <  this.offset[1] + element.offsetHeight &&
1688             this.xcomp >= this.offset[0] &&
1689             this.xcomp <  this.offset[0] + element.offsetWidth);
1690   },
1691
1692   // within must be called directly before
1693   overlap: function(mode, element) {
1694     if (!mode) return 0;
1695     if (mode == 'vertical')
1696       return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1697         element.offsetHeight;
1698     if (mode == 'horizontal')
1699       return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1700         element.offsetWidth;
1701   },
1702
1703   clone: function(source, target) {
1704     source = $(source);
1705     target = $(target);
1706     target.style.position = 'absolute';
1707     var offsets = this.cumulativeOffset(source);
1708     target.style.top    = offsets[1] + 'px';
1709     target.style.left   = offsets[0] + 'px';
1710     target.style.width  = source.offsetWidth + 'px';
1711     target.style.height = source.offsetHeight + 'px';
1712   },
1713
1714   page: function(forElement) {
1715     var valueT = 0, valueL = 0;
1716
1717     var element = forElement;
1718     do {
1719       valueT += element.offsetTop  || 0;
1720       valueL += element.offsetLeft || 0;
1721
1722       // Safari fix
1723       if (element.offsetParent==document.body)
1724         if (Element.getStyle(element,'position')=='absolute') break;
1725
1726     } while (element = element.offsetParent);
1727
1728     element = forElement;
1729     do {
1730       valueT -= element.scrollTop  || 0;
1731       valueL -= element.scrollLeft || 0;
1732     } while (element = element.parentNode);
1733
1734     return [valueL, valueT];
1735   },
1736
1737   clone: function(source, target) {
1738     var options = Object.extend({
1739       setLeft:    true,
1740       setTop:     true,
1741       setWidth:   true,
1742       setHeight:  true,
1743       offsetTop:  0,
1744       offsetLeft: 0
1745     }, arguments[2] || {})
1746
1747     // find page position of source
1748     source = $(source);
1749     var p = Position.page(source);
1750
1751     // find coordinate system to use
1752     target = $(target);
1753     var delta = [0, 0];
1754     var parent = null;
1755     // delta [0,0] will do fine with position: fixed elements,
1756     // position:absolute needs offsetParent deltas
1757     if (Element.getStyle(target,'position') == 'absolute') {
1758       parent = Position.offsetParent(target);
1759       delta = Position.page(parent);
1760     }
1761
1762     // correct by body offsets (fixes Safari)
1763     if (parent == document.body) {
1764       delta[0] -= document.body.offsetLeft;
1765       delta[1] -= document.body.offsetTop;
1766     }
1767
1768     // set position
1769     if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
1770     if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
1771     if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
1772     if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1773   },
1774
1775   absolutize: function(element) {
1776     element = $(element);
1777     if (element.style.position == 'absolute') return;
1778     Position.prepare();
1779
1780     var offsets = Position.positionedOffset(element);
1781     var top     = offsets[1];
1782     var left    = offsets[0];
1783     var width   = element.clientWidth;
1784     var height  = element.clientHeight;
1785
1786     element._originalLeft   = left - parseFloat(element.style.left  || 0);
1787     element._originalTop    = top  - parseFloat(element.style.top || 0);
1788     element._originalWidth  = element.style.width;
1789     element._originalHeight = element.style.height;
1790
1791     element.style.position = 'absolute';
1792     element.style.top    = top + 'px';;
1793     element.style.left   = left + 'px';;
1794     element.style.width  = width + 'px';;
1795     element.style.height = height + 'px';;
1796   },
1797
1798   relativize: function(element) {
1799     element = $(element);
1800     if (element.style.position == 'relative') return;
1801     Position.prepare();
1802
1803     element.style.position = 'relative';
1804     var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
1805     var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1806
1807     element.style.top    = top + 'px';
1808     element.style.left   = left + 'px';
1809     element.style.height = element._originalHeight;
1810     element.style.width  = element._originalWidth;
1811   }
1812 }
1813
1814 // Safari returns margins on body which is incorrect if the child is absolutely
1815 // positioned.  For performance reasons, redefine Position.cumulativeOffset for
1816 // KHTML/WebKit only.
1817 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1818   Position.cumulativeOffset = function(element) {
1819     var valueT = 0, valueL = 0;
1820     do {
1821       valueT += element.offsetTop  || 0;
1822       valueL += element.offsetLeft || 0;
1823       if (element.offsetParent == document.body)
1824         if (Element.getStyle(element, 'position') == 'absolute') break;
1825
1826       element = element.offsetParent;
1827     } while (element);
1828
1829     return [valueL, valueT];
1830   }
1831 }
1832 </script>
1833 <script type="text/javascript">
1834 /* code modified from ColdFusion's cfdump code */
1835 /* code modified from original dBug */
1836 dBug = new Object();
1837 dBug.toggleRow = function(source) {
1838                 var source = Event.element(source);
1839                 var target=(document.all) ? source.parentElement.cells[1] : source.parentNode.lastChild
1840                 dBug.toggleTarget(target,dBug.toggleSource(source));
1841         }
1842        
1843 dBug.toggleSource = function(source) {
1844                 if (source.style.fontStyle=='italic') {
1845                         source.style.fontStyle='normal';
1846                         source.title='click to collapse';
1847                         return 'open';
1848                 } else {
1849                         source.style.fontStyle='italic';
1850                         source.title='click to expand';
1851                         return 'closed';
1852                 }
1853         }
1854
1855 dBug.toggleTarget = function(target,switchToState) {
1856                 target.style.display=(switchToState=='open') ? '' : 'none';
1857         }
1858
1859 dBug.toggleTable = function(source) {
1860                 var source = Event.element(source);
1861                 var switchToState=dBug.toggleSource(source);
1862                 if(document.all) {
1863                         var table=source.parentElement.parentElement;
1864                         for(var i=1;i<table.rows.length;i++) {
1865                                 target=table.rows[i];
1866                                 dBug.toggleTarget(target,switchToState);
1867                         }
1868                 }
1869                 else {
1870                         var table=source.parentNode.parentNode;
1871                         for (var i=1;i<table.childNodes.length;i++) {
1872                                 target=table.childNodes[i];
1873                                 if(target.style) {
1874                                         dBug.toggleTarget(target,switchToState);
1875                                 }
1876                         }
1877                 }
1878         }
1879
1880 dBug.attachHandlers = function(cls, mtd) {
1881                 $A(document.getElementsByClassName(cls)).each(
1882                         function (td) {
1883                                         Event.observe( td, 'click', mtd );
1884                                         Event.observe( td, 'mouseover',
1885                                                 function( ev ) {
1886                                                         el = Event.element(ev);
1887                                                         el.style.cursor = 'pointer';
1888                                                 }
1889                                         );
1890                                         Event.observe( td, 'mouseout',
1891                                                 function( ev ) {
1892                                                         el = Event.element(ev);
1893                                                         el.style.cursor = 'auto';
1894                                                 }
1895                                         );
1896                                 }
1897                 );
1898         }
1899
1900 dBug.initialize = function() {
1901                 $A(dBug.types).each(
1902                         function (str) {
1903                                 dBug.attachHandlers( "dBug_" + str + "Header", dBug.toggleTable );
1904                                 dBug.attachHandlers( "dBug_" + str + "Key", dBug.toggleRow );
1905                         }
1906                 );
1907         }
1908
1909 dBug.types = ['resource', 'object', 'array', 'boolean', 'gd', 'xml',
1910         'fbsql', 'mssql', 'msql', 'pgsql', 'sybase-db', 'sybase-ct', 'mysql'];
1911
1912
1913 Event.observe( window, 'load', dBug.initialize );
1914 </script>
1915 </head>
1916 <body>
1917
1918     <table class="dBug_object" cellpadding="3" cellspacing="2">
1919                                 <tbody><tr>
1920                                         <td class="dBug_objectHeader" colspan="2">Object id #10 (SGL_Request)</td>
1921                                 </tr><tr>
1922                                 <td class="dBug_objectKey" valign="top">aProps</td>
1923                                 <td><table class="dBug_array" cellpadding="3" cellspacing="2">
1924                                 <tbody><tr>
1925                                         <td class="dBug_arrayHeader" colspan="2">array (2)</td>
1926                                 </tr><tr>
1927                                 <td class="dBug_arrayKey" valign="top">moduleName</td>
1928                                 <td>default</td>
1929 </tr>
1930 <tr>
1931                                 <td class="dBug_arrayKey" valign="top">managerName</td>
1932                                 <td>default</td>
1933 </tr>
1934 </tbody></table></td>
1935 </tr>
1936 <tr>
1937                                 <td class="dBug_objectKey" valign="top">init</td>
1938                                 <td>[function]</td>
1939 </tr>
1940 <tr>
1941                                 <td class="dBug_objectKey" valign="top">singleton</td>
1942                                 <td>[function]</td>
1943 </tr>
1944 <tr>
1945                                 <td class="dBug_objectKey" valign="top">isEmpty</td>
1946                                 <td>[function]</td>
1947 </tr>
1948 <tr>
1949                                 <td class="dBug_objectKey" valign="top">initHttp</td>
1950                                 <td>[function]</td>
1951 </tr>
1952 <tr>
1953                                 <td class="dBug_objectKey" valign="top">initCli</td>
1954                                 <td>[function]</td>
1955 </tr>
1956 <tr>
1957                                 <td class="dBug_objectKey" valign="top">merge</td>
1958                                 <td>[function]</td>
1959 </tr>
1960 <tr>
1961                                 <td class="dBug_objectKey" valign="top">get</td>
1962                                 <td>[function]</td>
1963 </tr>
1964 <tr>
1965                                 <td class="dBug_objectKey" valign="top">set</td>
1966                                 <td>[function]</td>
1967 </tr>
1968 <tr>
1969                                 <td class="dBug_objectKey" valign="top">add</td>
1970                                 <td>[function]</td>
1971 </tr>
1972 <tr>
1973                                 <td class="dBug_objectKey" valign="top">getAll</td>
1974                                 <td>[function]</td>
1975 </tr>
1976 <tr>
1977                                 <td class="dBug_objectKey" valign="top">getModuleName</td>
1978                                 <td>[function]</td>
1979 </tr>
1980 <tr>
1981                                 <td class="dBug_objectKey" valign="top">getManagerName</td>
1982                                 <td>[function]</td>
1983 </tr>
1984 <tr>
1985                                 <td class="dBug_objectKey" valign="top">getUri</td>
1986                                 <td>[function]</td>
1987 </tr>
1988 <tr>
1989                                 <td class="dBug_objectKey" valign="top">debug</td>
1990                                 <td>[function]</td>
1991 </tr>
1992 </tbody></table></body></html>