adhearsion 0.7.0

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