neerajdotname-javascript_lab 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3286 @@
1
+ /* Prototype JavaScript framework, version 1.5.1.2
2
+ * (c) 2005-2008 Sam Stephenson
3
+ *
4
+ * Prototype is freely distributable under the terms of an MIT-style license.
5
+ * For details, see the Prototype web site: http://www.prototypejs.org/
6
+ *
7
+ /*--------------------------------------------------------------------------*/
8
+
9
+ var Prototype = {
10
+ Version: '1.5.1.2',
11
+
12
+ Browser: {
13
+ IE: !!(window.attachEvent && !window.opera),
14
+ Opera: !!window.opera,
15
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
16
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
17
+ },
18
+
19
+ BrowserFeatures: {
20
+ XPath: !!document.evaluate,
21
+ ElementExtensions: !!window.HTMLElement,
22
+ SpecificElementExtensions:
23
+ (document.createElement('div').__proto__ !==
24
+ document.createElement('form').__proto__)
25
+ },
26
+
27
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
28
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
29
+
30
+ emptyFunction: function() { },
31
+ K: function(x) { return x }
32
+ }
33
+
34
+ var Class = {
35
+ create: function() {
36
+ return function() {
37
+ this.initialize.apply(this, arguments);
38
+ }
39
+ }
40
+ }
41
+
42
+ var Abstract = new Object();
43
+
44
+ Object.extend = function(destination, source) {
45
+ for (var property in source) {
46
+ destination[property] = source[property];
47
+ }
48
+ return destination;
49
+ }
50
+
51
+ Object.extend(Object, {
52
+ inspect: function(object) {
53
+ try {
54
+ if (object === undefined) return 'undefined';
55
+ if (object === null) return 'null';
56
+ return object.inspect ? object.inspect() : object.toString();
57
+ } catch (e) {
58
+ if (e instanceof RangeError) return '...';
59
+ throw e;
60
+ }
61
+ },
62
+
63
+ toJSON: function(object) {
64
+ var type = typeof object;
65
+ switch(type) {
66
+ case 'undefined':
67
+ case 'function':
68
+ case 'unknown': return;
69
+ case 'boolean': return object.toString();
70
+ }
71
+ if (object === null) return 'null';
72
+ if (object.toJSON) return object.toJSON();
73
+ if (object.ownerDocument === document) return;
74
+ var results = [];
75
+ for (var property in object) {
76
+ var value = Object.toJSON(object[property]);
77
+ if (value !== undefined)
78
+ results.push(property.toJSON() + ': ' + value);
79
+ }
80
+ return '{' + results.join(', ') + '}';
81
+ },
82
+
83
+ keys: function(object) {
84
+ var keys = [];
85
+ for (var property in object)
86
+ keys.push(property);
87
+ return keys;
88
+ },
89
+
90
+ values: function(object) {
91
+ var values = [];
92
+ for (var property in object)
93
+ values.push(object[property]);
94
+ return values;
95
+ },
96
+
97
+ clone: function(object) {
98
+ return Object.extend({}, object);
99
+ }
100
+ });
101
+
102
+ Function.prototype.bind = function() {
103
+ var __method = this, args = $A(arguments), object = args.shift();
104
+ return function() {
105
+ return __method.apply(object, args.concat($A(arguments)));
106
+ }
107
+ }
108
+
109
+ Function.prototype.bindAsEventListener = function(object) {
110
+ var __method = this, args = $A(arguments), object = args.shift();
111
+ return function(event) {
112
+ return __method.apply(object, [event || window.event].concat(args));
113
+ }
114
+ }
115
+
116
+ Object.extend(Number.prototype, {
117
+ toColorPart: function() {
118
+ return this.toPaddedString(2, 16);
119
+ },
120
+
121
+ succ: function() {
122
+ return this + 1;
123
+ },
124
+
125
+ times: function(iterator) {
126
+ $R(0, this, true).each(iterator);
127
+ return this;
128
+ },
129
+
130
+ toPaddedString: function(length, radix) {
131
+ var string = this.toString(radix || 10);
132
+ return '0'.times(length - string.length) + string;
133
+ },
134
+
135
+ toJSON: function() {
136
+ return isFinite(this) ? this.toString() : 'null';
137
+ }
138
+ });
139
+
140
+ Date.prototype.toJSON = function() {
141
+ return '"' + this.getFullYear() + '-' +
142
+ (this.getMonth() + 1).toPaddedString(2) + '-' +
143
+ this.getDate().toPaddedString(2) + 'T' +
144
+ this.getHours().toPaddedString(2) + ':' +
145
+ this.getMinutes().toPaddedString(2) + ':' +
146
+ this.getSeconds().toPaddedString(2) + '"';
147
+ };
148
+
149
+ var Try = {
150
+ these: function() {
151
+ var returnValue;
152
+
153
+ for (var i = 0, length = arguments.length; i < length; i++) {
154
+ var lambda = arguments[i];
155
+ try {
156
+ returnValue = lambda();
157
+ break;
158
+ } catch (e) {}
159
+ }
160
+
161
+ return returnValue;
162
+ }
163
+ }
164
+
165
+ /*--------------------------------------------------------------------------*/
166
+
167
+ var PeriodicalExecuter = Class.create();
168
+ PeriodicalExecuter.prototype = {
169
+ initialize: function(callback, frequency) {
170
+ this.callback = callback;
171
+ this.frequency = frequency;
172
+ this.currentlyExecuting = false;
173
+
174
+ this.registerCallback();
175
+ },
176
+
177
+ registerCallback: function() {
178
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
179
+ },
180
+
181
+ stop: function() {
182
+ if (!this.timer) return;
183
+ clearInterval(this.timer);
184
+ this.timer = null;
185
+ },
186
+
187
+ onTimerEvent: function() {
188
+ if (!this.currentlyExecuting) {
189
+ try {
190
+ this.currentlyExecuting = true;
191
+ this.callback(this);
192
+ } finally {
193
+ this.currentlyExecuting = false;
194
+ }
195
+ }
196
+ }
197
+ }
198
+ Object.extend(String, {
199
+ interpret: function(value) {
200
+ return value == null ? '' : String(value);
201
+ },
202
+ specialChar: {
203
+ '\b': '\\b',
204
+ '\t': '\\t',
205
+ '\n': '\\n',
206
+ '\f': '\\f',
207
+ '\r': '\\r',
208
+ '\\': '\\\\'
209
+ }
210
+ });
211
+
212
+ Object.extend(String.prototype, {
213
+ gsub: function(pattern, replacement) {
214
+ var result = '', source = this, match;
215
+ replacement = arguments.callee.prepareReplacement(replacement);
216
+
217
+ while (source.length > 0) {
218
+ if (match = source.match(pattern)) {
219
+ result += source.slice(0, match.index);
220
+ result += String.interpret(replacement(match));
221
+ source = source.slice(match.index + match[0].length);
222
+ } else {
223
+ result += source, source = '';
224
+ }
225
+ }
226
+ return result;
227
+ },
228
+
229
+ sub: function(pattern, replacement, count) {
230
+ replacement = this.gsub.prepareReplacement(replacement);
231
+ count = count === undefined ? 1 : count;
232
+
233
+ return this.gsub(pattern, function(match) {
234
+ if (--count < 0) return match[0];
235
+ return replacement(match);
236
+ });
237
+ },
238
+
239
+ scan: function(pattern, iterator) {
240
+ this.gsub(pattern, iterator);
241
+ return this;
242
+ },
243
+
244
+ truncate: function(length, truncation) {
245
+ length = length || 30;
246
+ truncation = truncation === undefined ? '...' : truncation;
247
+ return this.length > length ?
248
+ this.slice(0, length - truncation.length) + truncation : this;
249
+ },
250
+
251
+ strip: function() {
252
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
253
+ },
254
+
255
+ stripTags: function() {
256
+ return this.replace(/<\/?[^>]+>/gi, '');
257
+ },
258
+
259
+ stripScripts: function() {
260
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
261
+ },
262
+
263
+ extractScripts: function() {
264
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
265
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
266
+ return (this.match(matchAll) || []).map(function(scriptTag) {
267
+ return (scriptTag.match(matchOne) || ['', ''])[1];
268
+ });
269
+ },
270
+
271
+ evalScripts: function() {
272
+ return this.extractScripts().map(function(script) { return eval(script) });
273
+ },
274
+
275
+ escapeHTML: function() {
276
+ var self = arguments.callee;
277
+ self.text.data = this;
278
+ return self.div.innerHTML;
279
+ },
280
+
281
+ unescapeHTML: function() {
282
+ var div = document.createElement('div');
283
+ div.innerHTML = this.stripTags();
284
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
285
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
286
+ div.childNodes[0].nodeValue) : '';
287
+ },
288
+
289
+ toQueryParams: function(separator) {
290
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
291
+ if (!match) return {};
292
+
293
+ return match[1].split(separator || '&').inject({}, function(hash, pair) {
294
+ if ((pair = pair.split('='))[0]) {
295
+ var key = decodeURIComponent(pair.shift());
296
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
297
+ if (value != undefined) value = decodeURIComponent(value);
298
+
299
+ if (key in hash) {
300
+ if (hash[key].constructor != Array) hash[key] = [hash[key]];
301
+ hash[key].push(value);
302
+ }
303
+ else hash[key] = value;
304
+ }
305
+ return hash;
306
+ });
307
+ },
308
+
309
+ toArray: function() {
310
+ return this.split('');
311
+ },
312
+
313
+ succ: function() {
314
+ return this.slice(0, this.length - 1) +
315
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
316
+ },
317
+
318
+ times: function(count) {
319
+ var result = '';
320
+ for (var i = 0; i < count; i++) result += this;
321
+ return result;
322
+ },
323
+
324
+ camelize: function() {
325
+ var parts = this.split('-'), len = parts.length;
326
+ if (len == 1) return parts[0];
327
+
328
+ var camelized = this.charAt(0) == '-'
329
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
330
+ : parts[0];
331
+
332
+ for (var i = 1; i < len; i++)
333
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
334
+
335
+ return camelized;
336
+ },
337
+
338
+ capitalize: function() {
339
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
340
+ },
341
+
342
+ underscore: function() {
343
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
344
+ },
345
+
346
+ dasherize: function() {
347
+ return this.gsub(/_/,'-');
348
+ },
349
+
350
+ inspect: function(useDoubleQuotes) {
351
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
352
+ var character = String.specialChar[match[0]];
353
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
354
+ });
355
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
356
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
357
+ },
358
+
359
+ toJSON: function() {
360
+ return this.inspect(true);
361
+ },
362
+
363
+ unfilterJSON: function(filter) {
364
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
365
+ },
366
+
367
+ isJSON: function() {
368
+ var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
369
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
370
+ },
371
+
372
+ evalJSON: function(sanitize) {
373
+ var json = this.unfilterJSON();
374
+ try {
375
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
376
+ } catch (e) { }
377
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
378
+ },
379
+
380
+ include: function(pattern) {
381
+ return this.indexOf(pattern) > -1;
382
+ },
383
+
384
+ startsWith: function(pattern) {
385
+ return this.indexOf(pattern) === 0;
386
+ },
387
+
388
+ endsWith: function(pattern) {
389
+ var d = this.length - pattern.length;
390
+ return d >= 0 && this.lastIndexOf(pattern) === d;
391
+ },
392
+
393
+ empty: function() {
394
+ return this == '';
395
+ },
396
+
397
+ blank: function() {
398
+ return /^\s*$/.test(this);
399
+ }
400
+ });
401
+
402
+ if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
403
+ escapeHTML: function() {
404
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
405
+ },
406
+ unescapeHTML: function() {
407
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
408
+ }
409
+ });
410
+
411
+ String.prototype.gsub.prepareReplacement = function(replacement) {
412
+ if (typeof replacement == 'function') return replacement;
413
+ var template = new Template(replacement);
414
+ return function(match) { return template.evaluate(match) };
415
+ }
416
+
417
+ String.prototype.parseQuery = String.prototype.toQueryParams;
418
+
419
+ Object.extend(String.prototype.escapeHTML, {
420
+ div: document.createElement('div'),
421
+ text: document.createTextNode('')
422
+ });
423
+
424
+ with (String.prototype.escapeHTML) div.appendChild(text);
425
+
426
+ var Template = Class.create();
427
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
428
+ Template.prototype = {
429
+ initialize: function(template, pattern) {
430
+ this.template = template.toString();
431
+ this.pattern = pattern || Template.Pattern;
432
+ },
433
+
434
+ evaluate: function(object) {
435
+ return this.template.gsub(this.pattern, function(match) {
436
+ var before = match[1];
437
+ if (before == '\\') return match[2];
438
+ return before + String.interpret(object[match[3]]);
439
+ });
440
+ }
441
+ }
442
+
443
+ var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
444
+
445
+ var Enumerable = {
446
+ each: function(iterator) {
447
+ var index = 0;
448
+ try {
449
+ this._each(function(value) {
450
+ iterator(value, index++);
451
+ });
452
+ } catch (e) {
453
+ if (e != $break) throw e;
454
+ }
455
+ return this;
456
+ },
457
+
458
+ eachSlice: function(number, iterator) {
459
+ var index = -number, slices = [], array = this.toArray();
460
+ while ((index += number) < array.length)
461
+ slices.push(array.slice(index, index+number));
462
+ return slices.map(iterator);
463
+ },
464
+
465
+ all: function(iterator) {
466
+ var result = true;
467
+ this.each(function(value, index) {
468
+ result = result && !!(iterator || Prototype.K)(value, index);
469
+ if (!result) throw $break;
470
+ });
471
+ return result;
472
+ },
473
+
474
+ any: function(iterator) {
475
+ var result = false;
476
+ this.each(function(value, index) {
477
+ if (result = !!(iterator || Prototype.K)(value, index))
478
+ throw $break;
479
+ });
480
+ return result;
481
+ },
482
+
483
+ collect: function(iterator) {
484
+ var results = [];
485
+ this.each(function(value, index) {
486
+ results.push((iterator || Prototype.K)(value, index));
487
+ });
488
+ return results;
489
+ },
490
+
491
+ detect: function(iterator) {
492
+ var result;
493
+ this.each(function(value, index) {
494
+ if (iterator(value, index)) {
495
+ result = value;
496
+ throw $break;
497
+ }
498
+ });
499
+ return result;
500
+ },
501
+
502
+ findAll: function(iterator) {
503
+ var results = [];
504
+ this.each(function(value, index) {
505
+ if (iterator(value, index))
506
+ results.push(value);
507
+ });
508
+ return results;
509
+ },
510
+
511
+ grep: function(pattern, iterator) {
512
+ var results = [];
513
+ this.each(function(value, index) {
514
+ var stringValue = value.toString();
515
+ if (stringValue.match(pattern))
516
+ results.push((iterator || Prototype.K)(value, index));
517
+ })
518
+ return results;
519
+ },
520
+
521
+ include: function(object) {
522
+ var found = false;
523
+ this.each(function(value) {
524
+ if (value == object) {
525
+ found = true;
526
+ throw $break;
527
+ }
528
+ });
529
+ return found;
530
+ },
531
+
532
+ inGroupsOf: function(number, fillWith) {
533
+ fillWith = fillWith === undefined ? null : fillWith;
534
+ return this.eachSlice(number, function(slice) {
535
+ while(slice.length < number) slice.push(fillWith);
536
+ return slice;
537
+ });
538
+ },
539
+
540
+ inject: function(memo, iterator) {
541
+ this.each(function(value, index) {
542
+ memo = iterator(memo, value, index);
543
+ });
544
+ return memo;
545
+ },
546
+
547
+ invoke: function(method) {
548
+ var args = $A(arguments).slice(1);
549
+ return this.map(function(value) {
550
+ return value[method].apply(value, args);
551
+ });
552
+ },
553
+
554
+ max: function(iterator) {
555
+ var result;
556
+ this.each(function(value, index) {
557
+ value = (iterator || Prototype.K)(value, index);
558
+ if (result == undefined || value >= result)
559
+ result = value;
560
+ });
561
+ return result;
562
+ },
563
+
564
+ min: function(iterator) {
565
+ var result;
566
+ this.each(function(value, index) {
567
+ value = (iterator || Prototype.K)(value, index);
568
+ if (result == undefined || value < result)
569
+ result = value;
570
+ });
571
+ return result;
572
+ },
573
+
574
+ partition: function(iterator) {
575
+ var trues = [], falses = [];
576
+ this.each(function(value, index) {
577
+ ((iterator || Prototype.K)(value, index) ?
578
+ trues : falses).push(value);
579
+ });
580
+ return [trues, falses];
581
+ },
582
+
583
+ pluck: function(property) {
584
+ var results = [];
585
+ this.each(function(value, index) {
586
+ results.push(value[property]);
587
+ });
588
+ return results;
589
+ },
590
+
591
+ reject: function(iterator) {
592
+ var results = [];
593
+ this.each(function(value, index) {
594
+ if (!iterator(value, index))
595
+ results.push(value);
596
+ });
597
+ return results;
598
+ },
599
+
600
+ sortBy: function(iterator) {
601
+ return this.map(function(value, index) {
602
+ return {value: value, criteria: iterator(value, index)};
603
+ }).sort(function(left, right) {
604
+ var a = left.criteria, b = right.criteria;
605
+ return a < b ? -1 : a > b ? 1 : 0;
606
+ }).pluck('value');
607
+ },
608
+
609
+ toArray: function() {
610
+ return this.map();
611
+ },
612
+
613
+ zip: function() {
614
+ var iterator = Prototype.K, args = $A(arguments);
615
+ if (typeof args.last() == 'function')
616
+ iterator = args.pop();
617
+
618
+ var collections = [this].concat(args).map($A);
619
+ return this.map(function(value, index) {
620
+ return iterator(collections.pluck(index));
621
+ });
622
+ },
623
+
624
+ size: function() {
625
+ return this.toArray().length;
626
+ },
627
+
628
+ inspect: function() {
629
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
630
+ }
631
+ }
632
+
633
+ Object.extend(Enumerable, {
634
+ map: Enumerable.collect,
635
+ find: Enumerable.detect,
636
+ select: Enumerable.findAll,
637
+ member: Enumerable.include,
638
+ entries: Enumerable.toArray
639
+ });
640
+ var $A = Array.from = function(iterable) {
641
+ if (!iterable) return [];
642
+ if (iterable.toArray) {
643
+ return iterable.toArray();
644
+ } else {
645
+ var results = [];
646
+ for (var i = 0, length = iterable.length; i < length; i++)
647
+ results.push(iterable[i]);
648
+ return results;
649
+ }
650
+ }
651
+
652
+ if (Prototype.Browser.WebKit) {
653
+ $A = Array.from = function(iterable) {
654
+ if (!iterable) return [];
655
+ if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
656
+ iterable.toArray) {
657
+ return iterable.toArray();
658
+ } else {
659
+ var results = [];
660
+ for (var i = 0, length = iterable.length; i < length; i++)
661
+ results.push(iterable[i]);
662
+ return results;
663
+ }
664
+ }
665
+ }
666
+
667
+ Object.extend(Array.prototype, Enumerable);
668
+
669
+ if (!Array.prototype._reverse)
670
+ Array.prototype._reverse = Array.prototype.reverse;
671
+
672
+ Object.extend(Array.prototype, {
673
+ _each: function(iterator) {
674
+ for (var i = 0, length = this.length; i < length; i++)
675
+ iterator(this[i]);
676
+ },
677
+
678
+ clear: function() {
679
+ this.length = 0;
680
+ return this;
681
+ },
682
+
683
+ first: function() {
684
+ return this[0];
685
+ },
686
+
687
+ last: function() {
688
+ return this[this.length - 1];
689
+ },
690
+
691
+ compact: function() {
692
+ return this.select(function(value) {
693
+ return value != null;
694
+ });
695
+ },
696
+
697
+ flatten: function() {
698
+ return this.inject([], function(array, value) {
699
+ return array.concat(value && value.constructor == Array ?
700
+ value.flatten() : [value]);
701
+ });
702
+ },
703
+
704
+ without: function() {
705
+ var values = $A(arguments);
706
+ return this.select(function(value) {
707
+ return !values.include(value);
708
+ });
709
+ },
710
+
711
+ indexOf: function(object) {
712
+ for (var i = 0, length = this.length; i < length; i++)
713
+ if (this[i] == object) return i;
714
+ return -1;
715
+ },
716
+
717
+ reverse: function(inline) {
718
+ return (inline !== false ? this : this.toArray())._reverse();
719
+ },
720
+
721
+ reduce: function() {
722
+ return this.length > 1 ? this : this[0];
723
+ },
724
+
725
+ uniq: function(sorted) {
726
+ return this.inject([], function(array, value, index) {
727
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
728
+ array.push(value);
729
+ return array;
730
+ });
731
+ },
732
+
733
+ clone: function() {
734
+ return [].concat(this);
735
+ },
736
+
737
+ size: function() {
738
+ return this.length;
739
+ },
740
+
741
+ inspect: function() {
742
+ return '[' + this.map(Object.inspect).join(', ') + ']';
743
+ },
744
+
745
+ toJSON: function() {
746
+ var results = [];
747
+ this.each(function(object) {
748
+ var value = Object.toJSON(object);
749
+ if (value !== undefined) results.push(value);
750
+ });
751
+ return '[' + results.join(', ') + ']';
752
+ }
753
+ });
754
+
755
+ Array.prototype.toArray = Array.prototype.clone;
756
+
757
+ function $w(string) {
758
+ string = string.strip();
759
+ return string ? string.split(/\s+/) : [];
760
+ }
761
+
762
+ if (Prototype.Browser.Opera){
763
+ Array.prototype.concat = function() {
764
+ var array = [];
765
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
766
+ for (var i = 0, length = arguments.length; i < length; i++) {
767
+ if (arguments[i].constructor == Array) {
768
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
769
+ array.push(arguments[i][j]);
770
+ } else {
771
+ array.push(arguments[i]);
772
+ }
773
+ }
774
+ return array;
775
+ }
776
+ }
777
+ var Hash = function(object) {
778
+ if (object instanceof Hash) this.merge(object);
779
+ else Object.extend(this, object || {});
780
+ };
781
+
782
+ Object.extend(Hash, {
783
+ toQueryString: function(obj) {
784
+ var parts = [];
785
+ parts.add = arguments.callee.addPair;
786
+
787
+ this.prototype._each.call(obj, function(pair) {
788
+ if (!pair.key) return;
789
+ var value = pair.value;
790
+
791
+ if (value && typeof value == 'object') {
792
+ if (value.constructor == Array) value.each(function(value) {
793
+ parts.add(pair.key, value);
794
+ });
795
+ return;
796
+ }
797
+ parts.add(pair.key, value);
798
+ });
799
+
800
+ return parts.join('&');
801
+ },
802
+
803
+ toJSON: function(object) {
804
+ var results = [];
805
+ this.prototype._each.call(object, function(pair) {
806
+ var value = Object.toJSON(pair.value);
807
+ if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
808
+ });
809
+ return '{' + results.join(', ') + '}';
810
+ }
811
+ });
812
+
813
+ Hash.toQueryString.addPair = function(key, value, prefix) {
814
+ key = encodeURIComponent(key);
815
+ if (value === undefined) this.push(key);
816
+ else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
817
+ }
818
+
819
+ Object.extend(Hash.prototype, Enumerable);
820
+ Object.extend(Hash.prototype, {
821
+ _each: function(iterator) {
822
+ for (var key in this) {
823
+ var value = this[key];
824
+ if (value && value == Hash.prototype[key]) continue;
825
+
826
+ var pair = [key, value];
827
+ pair.key = key;
828
+ pair.value = value;
829
+ iterator(pair);
830
+ }
831
+ },
832
+
833
+ keys: function() {
834
+ return this.pluck('key');
835
+ },
836
+
837
+ values: function() {
838
+ return this.pluck('value');
839
+ },
840
+
841
+ merge: function(hash) {
842
+ return $H(hash).inject(this, function(mergedHash, pair) {
843
+ mergedHash[pair.key] = pair.value;
844
+ return mergedHash;
845
+ });
846
+ },
847
+
848
+ remove: function() {
849
+ var result;
850
+ for(var i = 0, length = arguments.length; i < length; i++) {
851
+ var value = this[arguments[i]];
852
+ if (value !== undefined){
853
+ if (result === undefined) result = value;
854
+ else {
855
+ if (result.constructor != Array) result = [result];
856
+ result.push(value)
857
+ }
858
+ }
859
+ delete this[arguments[i]];
860
+ }
861
+ return result;
862
+ },
863
+
864
+ toQueryString: function() {
865
+ return Hash.toQueryString(this);
866
+ },
867
+
868
+ inspect: function() {
869
+ return '#<Hash:{' + this.map(function(pair) {
870
+ return pair.map(Object.inspect).join(': ');
871
+ }).join(', ') + '}>';
872
+ },
873
+
874
+ toJSON: function() {
875
+ return Hash.toJSON(this);
876
+ }
877
+ });
878
+
879
+ function $H(object) {
880
+ if (object instanceof Hash) return object;
881
+ return new Hash(object);
882
+ };
883
+
884
+ // Safari iterates over shadowed properties
885
+ if (function() {
886
+ var i = 0, Test = function(value) { this.key = value };
887
+ Test.prototype.key = 'foo';
888
+ for (var property in new Test('bar')) i++;
889
+ return i > 1;
890
+ }()) Hash.prototype._each = function(iterator) {
891
+ var cache = [];
892
+ for (var key in this) {
893
+ var value = this[key];
894
+ if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
895
+ cache.push(key);
896
+ var pair = [key, value];
897
+ pair.key = key;
898
+ pair.value = value;
899
+ iterator(pair);
900
+ }
901
+ };
902
+ ObjectRange = Class.create();
903
+ Object.extend(ObjectRange.prototype, Enumerable);
904
+ Object.extend(ObjectRange.prototype, {
905
+ initialize: function(start, end, exclusive) {
906
+ this.start = start;
907
+ this.end = end;
908
+ this.exclusive = exclusive;
909
+ },
910
+
911
+ _each: function(iterator) {
912
+ var value = this.start;
913
+ while (this.include(value)) {
914
+ iterator(value);
915
+ value = value.succ();
916
+ }
917
+ },
918
+
919
+ include: function(value) {
920
+ if (value < this.start)
921
+ return false;
922
+ if (this.exclusive)
923
+ return value < this.end;
924
+ return value <= this.end;
925
+ }
926
+ });
927
+
928
+ var $R = function(start, end, exclusive) {
929
+ return new ObjectRange(start, end, exclusive);
930
+ }
931
+
932
+ var Ajax = {
933
+ getTransport: function() {
934
+ return Try.these(
935
+ function() {return new XMLHttpRequest()},
936
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
937
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
938
+ ) || false;
939
+ },
940
+
941
+ activeRequestCount: 0
942
+ }
943
+
944
+ Ajax.Responders = {
945
+ responders: [],
946
+
947
+ _each: function(iterator) {
948
+ this.responders._each(iterator);
949
+ },
950
+
951
+ register: function(responder) {
952
+ if (!this.include(responder))
953
+ this.responders.push(responder);
954
+ },
955
+
956
+ unregister: function(responder) {
957
+ this.responders = this.responders.without(responder);
958
+ },
959
+
960
+ dispatch: function(callback, request, transport, json) {
961
+ this.each(function(responder) {
962
+ if (typeof responder[callback] == 'function') {
963
+ try {
964
+ responder[callback].apply(responder, [request, transport, json]);
965
+ } catch (e) {}
966
+ }
967
+ });
968
+ }
969
+ };
970
+
971
+ Object.extend(Ajax.Responders, Enumerable);
972
+
973
+ Ajax.Responders.register({
974
+ onCreate: function() {
975
+ Ajax.activeRequestCount++;
976
+ },
977
+ onComplete: function() {
978
+ Ajax.activeRequestCount--;
979
+ }
980
+ });
981
+
982
+ Ajax.Base = function() {};
983
+ Ajax.Base.prototype = {
984
+ setOptions: function(options) {
985
+ this.options = {
986
+ method: 'post',
987
+ asynchronous: true,
988
+ contentType: 'application/x-www-form-urlencoded',
989
+ encoding: 'UTF-8',
990
+ parameters: ''
991
+ }
992
+ Object.extend(this.options, options || {});
993
+
994
+ this.options.method = this.options.method.toLowerCase();
995
+ if (typeof this.options.parameters == 'string')
996
+ this.options.parameters = this.options.parameters.toQueryParams();
997
+ }
998
+ }
999
+
1000
+ Ajax.Request = Class.create();
1001
+ Ajax.Request.Events =
1002
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1003
+
1004
+ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
1005
+ _complete: false,
1006
+
1007
+ initialize: function(url, options) {
1008
+ this.transport = Ajax.getTransport();
1009
+ this.setOptions(options);
1010
+ this.request(url);
1011
+ },
1012
+
1013
+ request: function(url) {
1014
+ this.url = url;
1015
+ this.method = this.options.method;
1016
+ var params = Object.clone(this.options.parameters);
1017
+
1018
+ if (!['get', 'post'].include(this.method)) {
1019
+ // simulate other verbs over post
1020
+ params['_method'] = this.method;
1021
+ this.method = 'post';
1022
+ }
1023
+
1024
+ this.parameters = params;
1025
+
1026
+ if (params = Hash.toQueryString(params)) {
1027
+ // when GET, append parameters to URL
1028
+ if (this.method == 'get')
1029
+ this.url += (this.url.include('?') ? '&' : '?') + params;
1030
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1031
+ params += '&_=';
1032
+ }
1033
+
1034
+ try {
1035
+ if (this.options.onCreate) this.options.onCreate(this.transport);
1036
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
1037
+
1038
+ this.transport.open(this.method.toUpperCase(), this.url,
1039
+ this.options.asynchronous);
1040
+
1041
+ if (this.options.asynchronous)
1042
+ setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
1043
+
1044
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
1045
+ this.setRequestHeaders();
1046
+
1047
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1048
+ this.transport.send(this.body);
1049
+
1050
+ /* Force Firefox to handle ready state 4 for synchronous requests */
1051
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
1052
+ this.onStateChange();
1053
+
1054
+ }
1055
+ catch (e) {
1056
+ this.dispatchException(e);
1057
+ }
1058
+ },
1059
+
1060
+ onStateChange: function() {
1061
+ var readyState = this.transport.readyState;
1062
+ if (readyState > 1 && !((readyState == 4) && this._complete))
1063
+ this.respondToReadyState(this.transport.readyState);
1064
+ },
1065
+
1066
+ setRequestHeaders: function() {
1067
+ var headers = {
1068
+ 'X-Requested-With': 'XMLHttpRequest',
1069
+ 'X-Prototype-Version': Prototype.Version,
1070
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1071
+ };
1072
+
1073
+ if (this.method == 'post') {
1074
+ headers['Content-type'] = this.options.contentType +
1075
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
1076
+
1077
+ /* Force "Connection: close" for older Mozilla browsers to work
1078
+ * around a bug where XMLHttpRequest sends an incorrect
1079
+ * Content-length header. See Mozilla Bugzilla #246651.
1080
+ */
1081
+ if (this.transport.overrideMimeType &&
1082
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1083
+ headers['Connection'] = 'close';
1084
+ }
1085
+
1086
+ // user-defined headers
1087
+ if (typeof this.options.requestHeaders == 'object') {
1088
+ var extras = this.options.requestHeaders;
1089
+
1090
+ if (typeof extras.push == 'function')
1091
+ for (var i = 0, length = extras.length; i < length; i += 2)
1092
+ headers[extras[i]] = extras[i+1];
1093
+ else
1094
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1095
+ }
1096
+
1097
+ for (var name in headers)
1098
+ this.transport.setRequestHeader(name, headers[name]);
1099
+ },
1100
+
1101
+ success: function() {
1102
+ return !this.transport.status
1103
+ || (this.transport.status >= 200 && this.transport.status < 300);
1104
+ },
1105
+
1106
+ respondToReadyState: function(readyState) {
1107
+ var state = Ajax.Request.Events[readyState];
1108
+ var transport = this.transport, json = this.evalJSON();
1109
+
1110
+ if (state == 'Complete') {
1111
+ try {
1112
+ this._complete = true;
1113
+ (this.options['on' + this.transport.status]
1114
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1115
+ || Prototype.emptyFunction)(transport, json);
1116
+ } catch (e) {
1117
+ this.dispatchException(e);
1118
+ }
1119
+
1120
+ var contentType = this.getHeader('Content-type');
1121
+ if (contentType && this.isSameOrigin() && contentType.strip().
1122
+ match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
1123
+ this.evalResponse();
1124
+ }
1125
+
1126
+ try {
1127
+ (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
1128
+ Ajax.Responders.dispatch('on' + state, this, transport, json);
1129
+ } catch (e) {
1130
+ this.dispatchException(e);
1131
+ }
1132
+
1133
+ if (state == 'Complete') {
1134
+ // avoid memory leak in MSIE: clean up
1135
+ this.transport.onreadystatechange = Prototype.emptyFunction;
1136
+ }
1137
+ },
1138
+
1139
+ isSameOrigin: function() {
1140
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1141
+ return !m || (m[0] == new Template('#{protocol}//#{domain}#{port}').evaluate({
1142
+ protocol: location.protocol,
1143
+ domain: document.domain,
1144
+ port: location.port ? ':' + location.port : ''
1145
+ }));
1146
+ },
1147
+
1148
+ getHeader: function(name) {
1149
+ try {
1150
+ return this.transport.getResponseHeader(name);
1151
+ } catch (e) { return null }
1152
+ },
1153
+
1154
+ evalJSON: function() {
1155
+ try {
1156
+ var json = this.getHeader('X-JSON');
1157
+ return json ? json.evalJSON(!this.isSameOrigin()) : null;
1158
+ } catch (e) { return null }
1159
+ },
1160
+
1161
+ evalResponse: function() {
1162
+ try {
1163
+ return eval((this.transport.responseText || '').unfilterJSON());
1164
+ } catch (e) {
1165
+ this.dispatchException(e);
1166
+ }
1167
+ },
1168
+
1169
+ dispatchException: function(exception) {
1170
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
1171
+ Ajax.Responders.dispatch('onException', this, exception);
1172
+ }
1173
+ });
1174
+
1175
+ Ajax.Updater = Class.create();
1176
+
1177
+ Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
1178
+ initialize: function(container, url, options) {
1179
+ this.container = {
1180
+ success: (container.success || container),
1181
+ failure: (container.failure || (container.success ? null : container))
1182
+ }
1183
+
1184
+ this.transport = Ajax.getTransport();
1185
+ this.setOptions(options);
1186
+
1187
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
1188
+ this.options.onComplete = (function(transport, param) {
1189
+ this.updateContent();
1190
+ onComplete(transport, param);
1191
+ }).bind(this);
1192
+
1193
+ this.request(url);
1194
+ },
1195
+
1196
+ updateContent: function() {
1197
+ var receiver = this.container[this.success() ? 'success' : 'failure'];
1198
+ var response = this.transport.responseText;
1199
+
1200
+ if (!this.options.evalScripts) response = response.stripScripts();
1201
+
1202
+ if (receiver = $(receiver)) {
1203
+ if (this.options.insertion)
1204
+ new this.options.insertion(receiver, response);
1205
+ else
1206
+ receiver.update(response);
1207
+ }
1208
+
1209
+ if (this.success()) {
1210
+ if (this.onComplete)
1211
+ setTimeout(this.onComplete.bind(this), 10);
1212
+ }
1213
+ }
1214
+ });
1215
+
1216
+ Ajax.PeriodicalUpdater = Class.create();
1217
+ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
1218
+ initialize: function(container, url, options) {
1219
+ this.setOptions(options);
1220
+ this.onComplete = this.options.onComplete;
1221
+
1222
+ this.frequency = (this.options.frequency || 2);
1223
+ this.decay = (this.options.decay || 1);
1224
+
1225
+ this.updater = {};
1226
+ this.container = container;
1227
+ this.url = url;
1228
+
1229
+ this.start();
1230
+ },
1231
+
1232
+ start: function() {
1233
+ this.options.onComplete = this.updateComplete.bind(this);
1234
+ this.onTimerEvent();
1235
+ },
1236
+
1237
+ stop: function() {
1238
+ this.updater.options.onComplete = undefined;
1239
+ clearTimeout(this.timer);
1240
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1241
+ },
1242
+
1243
+ updateComplete: function(request) {
1244
+ if (this.options.decay) {
1245
+ this.decay = (request.responseText == this.lastText ?
1246
+ this.decay * this.options.decay : 1);
1247
+
1248
+ this.lastText = request.responseText;
1249
+ }
1250
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
1251
+ this.decay * this.frequency * 1000);
1252
+ },
1253
+
1254
+ onTimerEvent: function() {
1255
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
1256
+ }
1257
+ });
1258
+ function $(element) {
1259
+ if (arguments.length > 1) {
1260
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1261
+ elements.push($(arguments[i]));
1262
+ return elements;
1263
+ }
1264
+ if (typeof element == 'string')
1265
+ element = document.getElementById(element);
1266
+ return Element.extend(element);
1267
+ }
1268
+
1269
+ if (Prototype.BrowserFeatures.XPath) {
1270
+ document._getElementsByXPath = function(expression, parentElement) {
1271
+ var results = [];
1272
+ var query = document.evaluate(expression, $(parentElement) || document,
1273
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1274
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
1275
+ results.push(query.snapshotItem(i));
1276
+ return results;
1277
+ };
1278
+
1279
+ document.getElementsByClassName = function(className, parentElement) {
1280
+ var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
1281
+ return document._getElementsByXPath(q, parentElement);
1282
+ }
1283
+
1284
+ } else document.getElementsByClassName = function(className, parentElement) {
1285
+ var children = ($(parentElement) || document.body).getElementsByTagName('*');
1286
+ var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
1287
+ for (var i = 0, length = children.length; i < length; i++) {
1288
+ child = children[i];
1289
+ var elementClassName = child.className;
1290
+ if (elementClassName.length == 0) continue;
1291
+ if (elementClassName == className || elementClassName.match(pattern))
1292
+ elements.push(Element.extend(child));
1293
+ }
1294
+ return elements;
1295
+ };
1296
+
1297
+ /*--------------------------------------------------------------------------*/
1298
+
1299
+ if (!window.Element) var Element = {};
1300
+
1301
+ Element.extend = function(element) {
1302
+ var F = Prototype.BrowserFeatures;
1303
+ if (!element || !element.tagName || element.nodeType == 3 ||
1304
+ element._extended || F.SpecificElementExtensions || element == window)
1305
+ return element;
1306
+
1307
+ var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
1308
+ T = Element.Methods.ByTag;
1309
+
1310
+ // extend methods for all tags (Safari doesn't need this)
1311
+ if (!F.ElementExtensions) {
1312
+ Object.extend(methods, Element.Methods),
1313
+ Object.extend(methods, Element.Methods.Simulated);
1314
+ }
1315
+
1316
+ // extend methods for specific tags
1317
+ if (T[tagName]) Object.extend(methods, T[tagName]);
1318
+
1319
+ for (var property in methods) {
1320
+ var value = methods[property];
1321
+ if (typeof value == 'function' && !(property in element))
1322
+ element[property] = cache.findOrStore(value);
1323
+ }
1324
+
1325
+ element._extended = Prototype.emptyFunction;
1326
+ return element;
1327
+ };
1328
+
1329
+ Element.extend.cache = {
1330
+ findOrStore: function(value) {
1331
+ return this[value] = this[value] || function() {
1332
+ return value.apply(null, [this].concat($A(arguments)));
1333
+ }
1334
+ }
1335
+ };
1336
+
1337
+ Element.Methods = {
1338
+ visible: function(element) {
1339
+ return $(element).style.display != 'none';
1340
+ },
1341
+
1342
+ toggle: function(element) {
1343
+ element = $(element);
1344
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
1345
+ return element;
1346
+ },
1347
+
1348
+ hide: function(element) {
1349
+ $(element).style.display = 'none';
1350
+ return element;
1351
+ },
1352
+
1353
+ show: function(element) {
1354
+ $(element).style.display = '';
1355
+ return element;
1356
+ },
1357
+
1358
+ remove: function(element) {
1359
+ element = $(element);
1360
+ element.parentNode.removeChild(element);
1361
+ return element;
1362
+ },
1363
+
1364
+ update: function(element, html) {
1365
+ html = typeof html == 'undefined' ? '' : html.toString();
1366
+ $(element).innerHTML = html.stripScripts();
1367
+ setTimeout(function() {html.evalScripts()}, 10);
1368
+ return element;
1369
+ },
1370
+
1371
+ replace: function(element, html) {
1372
+ element = $(element);
1373
+ html = typeof html == 'undefined' ? '' : html.toString();
1374
+ if (element.outerHTML) {
1375
+ element.outerHTML = html.stripScripts();
1376
+ } else {
1377
+ var range = element.ownerDocument.createRange();
1378
+ range.selectNodeContents(element);
1379
+ element.parentNode.replaceChild(
1380
+ range.createContextualFragment(html.stripScripts()), element);
1381
+ }
1382
+ setTimeout(function() {html.evalScripts()}, 10);
1383
+ return element;
1384
+ },
1385
+
1386
+ inspect: function(element) {
1387
+ element = $(element);
1388
+ var result = '<' + element.tagName.toLowerCase();
1389
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1390
+ var property = pair.first(), attribute = pair.last();
1391
+ var value = (element[property] || '').toString();
1392
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
1393
+ });
1394
+ return result + '>';
1395
+ },
1396
+
1397
+ recursivelyCollect: function(element, property) {
1398
+ element = $(element);
1399
+ var elements = [];
1400
+ while (element = element[property])
1401
+ if (element.nodeType == 1)
1402
+ elements.push(Element.extend(element));
1403
+ return elements;
1404
+ },
1405
+
1406
+ ancestors: function(element) {
1407
+ return $(element).recursivelyCollect('parentNode');
1408
+ },
1409
+
1410
+ descendants: function(element) {
1411
+ return $A($(element).getElementsByTagName('*')).each(Element.extend);
1412
+ },
1413
+
1414
+ firstDescendant: function(element) {
1415
+ element = $(element).firstChild;
1416
+ while (element && element.nodeType != 1) element = element.nextSibling;
1417
+ return $(element);
1418
+ },
1419
+
1420
+ immediateDescendants: function(element) {
1421
+ if (!(element = $(element).firstChild)) return [];
1422
+ while (element && element.nodeType != 1) element = element.nextSibling;
1423
+ if (element) return [element].concat($(element).nextSiblings());
1424
+ return [];
1425
+ },
1426
+
1427
+ previousSiblings: function(element) {
1428
+ return $(element).recursivelyCollect('previousSibling');
1429
+ },
1430
+
1431
+ nextSiblings: function(element) {
1432
+ return $(element).recursivelyCollect('nextSibling');
1433
+ },
1434
+
1435
+ siblings: function(element) {
1436
+ element = $(element);
1437
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
1438
+ },
1439
+
1440
+ match: function(element, selector) {
1441
+ if (typeof selector == 'string')
1442
+ selector = new Selector(selector);
1443
+ return selector.match($(element));
1444
+ },
1445
+
1446
+ up: function(element, expression, index) {
1447
+ element = $(element);
1448
+ if (arguments.length == 1) return $(element.parentNode);
1449
+ var ancestors = element.ancestors();
1450
+ return expression ? Selector.findElement(ancestors, expression, index) :
1451
+ ancestors[index || 0];
1452
+ },
1453
+
1454
+ down: function(element, expression, index) {
1455
+ element = $(element);
1456
+ if (arguments.length == 1) return element.firstDescendant();
1457
+ var descendants = element.descendants();
1458
+ return expression ? Selector.findElement(descendants, expression, index) :
1459
+ descendants[index || 0];
1460
+ },
1461
+
1462
+ previous: function(element, expression, index) {
1463
+ element = $(element);
1464
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1465
+ var previousSiblings = element.previousSiblings();
1466
+ return expression ? Selector.findElement(previousSiblings, expression, index) :
1467
+ previousSiblings[index || 0];
1468
+ },
1469
+
1470
+ next: function(element, expression, index) {
1471
+ element = $(element);
1472
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1473
+ var nextSiblings = element.nextSiblings();
1474
+ return expression ? Selector.findElement(nextSiblings, expression, index) :
1475
+ nextSiblings[index || 0];
1476
+ },
1477
+
1478
+ getElementsBySelector: function() {
1479
+ var args = $A(arguments), element = $(args.shift());
1480
+ return Selector.findChildElements(element, args);
1481
+ },
1482
+
1483
+ getElementsByClassName: function(element, className) {
1484
+ return document.getElementsByClassName(className, element);
1485
+ },
1486
+
1487
+ readAttribute: function(element, name) {
1488
+ element = $(element);
1489
+ if (Prototype.Browser.IE) {
1490
+ if (!element.attributes) return null;
1491
+ var t = Element._attributeTranslations;
1492
+ if (t.values[name]) return t.values[name](element, name);
1493
+ if (t.names[name]) name = t.names[name];
1494
+ var attribute = element.attributes[name];
1495
+ return attribute ? attribute.nodeValue : null;
1496
+ }
1497
+ return element.getAttribute(name);
1498
+ },
1499
+
1500
+ getHeight: function(element) {
1501
+ return $(element).getDimensions().height;
1502
+ },
1503
+
1504
+ getWidth: function(element) {
1505
+ return $(element).getDimensions().width;
1506
+ },
1507
+
1508
+ classNames: function(element) {
1509
+ return new Element.ClassNames(element);
1510
+ },
1511
+
1512
+ hasClassName: function(element, className) {
1513
+ if (!(element = $(element))) return;
1514
+ var elementClassName = element.className;
1515
+ if (elementClassName.length == 0) return false;
1516
+ if (elementClassName == className ||
1517
+ elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
1518
+ return true;
1519
+ return false;
1520
+ },
1521
+
1522
+ addClassName: function(element, className) {
1523
+ if (!(element = $(element))) return;
1524
+ Element.classNames(element).add(className);
1525
+ return element;
1526
+ },
1527
+
1528
+ removeClassName: function(element, className) {
1529
+ if (!(element = $(element))) return;
1530
+ Element.classNames(element).remove(className);
1531
+ return element;
1532
+ },
1533
+
1534
+ toggleClassName: function(element, className) {
1535
+ if (!(element = $(element))) return;
1536
+ Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
1537
+ return element;
1538
+ },
1539
+
1540
+ observe: function() {
1541
+ Event.observe.apply(Event, arguments);
1542
+ return $A(arguments).first();
1543
+ },
1544
+
1545
+ stopObserving: function() {
1546
+ Event.stopObserving.apply(Event, arguments);
1547
+ return $A(arguments).first();
1548
+ },
1549
+
1550
+ // removes whitespace-only text node children
1551
+ cleanWhitespace: function(element) {
1552
+ element = $(element);
1553
+ var node = element.firstChild;
1554
+ while (node) {
1555
+ var nextNode = node.nextSibling;
1556
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1557
+ element.removeChild(node);
1558
+ node = nextNode;
1559
+ }
1560
+ return element;
1561
+ },
1562
+
1563
+ empty: function(element) {
1564
+ return $(element).innerHTML.blank();
1565
+ },
1566
+
1567
+ descendantOf: function(element, ancestor) {
1568
+ element = $(element), ancestor = $(ancestor);
1569
+ while (element = element.parentNode)
1570
+ if (element == ancestor) return true;
1571
+ return false;
1572
+ },
1573
+
1574
+ scrollTo: function(element) {
1575
+ element = $(element);
1576
+ var pos = Position.cumulativeOffset(element);
1577
+ window.scrollTo(pos[0], pos[1]);
1578
+ return element;
1579
+ },
1580
+
1581
+ getStyle: function(element, style) {
1582
+ element = $(element);
1583
+ style = style == 'float' ? 'cssFloat' : style.camelize();
1584
+ var value = element.style[style];
1585
+ if (!value) {
1586
+ var css = document.defaultView.getComputedStyle(element, null);
1587
+ value = css ? css[style] : null;
1588
+ }
1589
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1590
+ return value == 'auto' ? null : value;
1591
+ },
1592
+
1593
+ getOpacity: function(element) {
1594
+ return $(element).getStyle('opacity');
1595
+ },
1596
+
1597
+ setStyle: function(element, styles, camelized) {
1598
+ element = $(element);
1599
+ var elementStyle = element.style;
1600
+
1601
+ for (var property in styles)
1602
+ if (property == 'opacity') element.setOpacity(styles[property])
1603
+ else
1604
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
1605
+ (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
1606
+ (camelized ? property : property.camelize())] = styles[property];
1607
+
1608
+ return element;
1609
+ },
1610
+
1611
+ setOpacity: function(element, value) {
1612
+ element = $(element);
1613
+ element.style.opacity = (value == 1 || value === '') ? '' :
1614
+ (value < 0.00001) ? 0 : value;
1615
+ return element;
1616
+ },
1617
+
1618
+ getDimensions: function(element) {
1619
+ element = $(element);
1620
+ var display = $(element).getStyle('display');
1621
+ if (display != 'none' && display != null) // Safari bug
1622
+ return {width: element.offsetWidth, height: element.offsetHeight};
1623
+
1624
+ // All *Width and *Height properties give 0 on elements with display none,
1625
+ // so enable the element temporarily
1626
+ var els = element.style;
1627
+ var originalVisibility = els.visibility;
1628
+ var originalPosition = els.position;
1629
+ var originalDisplay = els.display;
1630
+ els.visibility = 'hidden';
1631
+ els.position = 'absolute';
1632
+ els.display = 'block';
1633
+ var originalWidth = element.clientWidth;
1634
+ var originalHeight = element.clientHeight;
1635
+ els.display = originalDisplay;
1636
+ els.position = originalPosition;
1637
+ els.visibility = originalVisibility;
1638
+ return {width: originalWidth, height: originalHeight};
1639
+ },
1640
+
1641
+ makePositioned: function(element) {
1642
+ element = $(element);
1643
+ var pos = Element.getStyle(element, 'position');
1644
+ if (pos == 'static' || !pos) {
1645
+ element._madePositioned = true;
1646
+ element.style.position = 'relative';
1647
+ // Opera returns the offset relative to the positioning context, when an
1648
+ // element is position relative but top and left have not been defined
1649
+ if (window.opera) {
1650
+ element.style.top = 0;
1651
+ element.style.left = 0;
1652
+ }
1653
+ }
1654
+ return element;
1655
+ },
1656
+
1657
+ undoPositioned: function(element) {
1658
+ element = $(element);
1659
+ if (element._madePositioned) {
1660
+ element._madePositioned = undefined;
1661
+ element.style.position =
1662
+ element.style.top =
1663
+ element.style.left =
1664
+ element.style.bottom =
1665
+ element.style.right = '';
1666
+ }
1667
+ return element;
1668
+ },
1669
+
1670
+ makeClipping: function(element) {
1671
+ element = $(element);
1672
+ if (element._overflow) return element;
1673
+ element._overflow = element.style.overflow || 'auto';
1674
+ if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1675
+ element.style.overflow = 'hidden';
1676
+ return element;
1677
+ },
1678
+
1679
+ undoClipping: function(element) {
1680
+ element = $(element);
1681
+ if (!element._overflow) return element;
1682
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
1683
+ element._overflow = null;
1684
+ return element;
1685
+ }
1686
+ };
1687
+
1688
+ Object.extend(Element.Methods, {
1689
+ childOf: Element.Methods.descendantOf,
1690
+ childElements: Element.Methods.immediateDescendants
1691
+ });
1692
+
1693
+ if (Prototype.Browser.Opera) {
1694
+ Element.Methods._getStyle = Element.Methods.getStyle;
1695
+ Element.Methods.getStyle = function(element, style) {
1696
+ switch(style) {
1697
+ case 'left':
1698
+ case 'top':
1699
+ case 'right':
1700
+ case 'bottom':
1701
+ if (Element._getStyle(element, 'position') == 'static') return null;
1702
+ default: return Element._getStyle(element, style);
1703
+ }
1704
+ };
1705
+ }
1706
+ else if (Prototype.Browser.IE) {
1707
+ Element.Methods.getStyle = function(element, style) {
1708
+ element = $(element);
1709
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
1710
+ var value = element.style[style];
1711
+ if (!value && element.currentStyle) value = element.currentStyle[style];
1712
+
1713
+ if (style == 'opacity') {
1714
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
1715
+ if (value[1]) return parseFloat(value[1]) / 100;
1716
+ return 1.0;
1717
+ }
1718
+
1719
+ if (value == 'auto') {
1720
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
1721
+ return element['offset'+style.capitalize()] + 'px';
1722
+ return null;
1723
+ }
1724
+ return value;
1725
+ };
1726
+
1727
+ Element.Methods.setOpacity = function(element, value) {
1728
+ element = $(element);
1729
+ var filter = element.getStyle('filter'), style = element.style;
1730
+ if (value == 1 || value === '') {
1731
+ style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
1732
+ return element;
1733
+ } else if (value < 0.00001) value = 0;
1734
+ style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
1735
+ 'alpha(opacity=' + (value * 100) + ')';
1736
+ return element;
1737
+ };
1738
+
1739
+ // IE is missing .innerHTML support for TABLE-related elements
1740
+ Element.Methods.update = function(element, html) {
1741
+ element = $(element);
1742
+ html = typeof html == 'undefined' ? '' : html.toString();
1743
+ var tagName = element.tagName.toUpperCase();
1744
+ if (['THEAD','TBODY','TR','TD'].include(tagName)) {
1745
+ var div = document.createElement('div');
1746
+ switch (tagName) {
1747
+ case 'THEAD':
1748
+ case 'TBODY':
1749
+ div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
1750
+ depth = 2;
1751
+ break;
1752
+ case 'TR':
1753
+ div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
1754
+ depth = 3;
1755
+ break;
1756
+ case 'TD':
1757
+ div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
1758
+ depth = 4;
1759
+ }
1760
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
1761
+ depth.times(function() { div = div.firstChild });
1762
+ $A(div.childNodes).each(function(node) { element.appendChild(node) });
1763
+ } else {
1764
+ element.innerHTML = html.stripScripts();
1765
+ }
1766
+ setTimeout(function() { html.evalScripts() }, 10);
1767
+ return element;
1768
+ }
1769
+ }
1770
+ else if (Prototype.Browser.Gecko) {
1771
+ Element.Methods.setOpacity = function(element, value) {
1772
+ element = $(element);
1773
+ element.style.opacity = (value == 1) ? 0.999999 :
1774
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
1775
+ return element;
1776
+ };
1777
+ }
1778
+
1779
+ Element._attributeTranslations = {
1780
+ names: {
1781
+ colspan: "colSpan",
1782
+ rowspan: "rowSpan",
1783
+ valign: "vAlign",
1784
+ datetime: "dateTime",
1785
+ accesskey: "accessKey",
1786
+ tabindex: "tabIndex",
1787
+ enctype: "encType",
1788
+ maxlength: "maxLength",
1789
+ readonly: "readOnly",
1790
+ longdesc: "longDesc"
1791
+ },
1792
+ values: {
1793
+ _getAttr: function(element, attribute) {
1794
+ return element.getAttribute(attribute, 2);
1795
+ },
1796
+ _flag: function(element, attribute) {
1797
+ return $(element).hasAttribute(attribute) ? attribute : null;
1798
+ },
1799
+ style: function(element) {
1800
+ return element.style.cssText.toLowerCase();
1801
+ },
1802
+ title: function(element) {
1803
+ var node = element.getAttributeNode('title');
1804
+ return node.specified ? node.nodeValue : null;
1805
+ }
1806
+ }
1807
+ };
1808
+
1809
+ (function() {
1810
+ Object.extend(this, {
1811
+ href: this._getAttr,
1812
+ src: this._getAttr,
1813
+ type: this._getAttr,
1814
+ disabled: this._flag,
1815
+ checked: this._flag,
1816
+ readonly: this._flag,
1817
+ multiple: this._flag
1818
+ });
1819
+ }).call(Element._attributeTranslations.values);
1820
+
1821
+ Element.Methods.Simulated = {
1822
+ hasAttribute: function(element, attribute) {
1823
+ var t = Element._attributeTranslations, node;
1824
+ attribute = t.names[attribute] || attribute;
1825
+ node = $(element).getAttributeNode(attribute);
1826
+ return node && node.specified;
1827
+ }
1828
+ };
1829
+
1830
+ Element.Methods.ByTag = {};
1831
+
1832
+ Object.extend(Element, Element.Methods);
1833
+
1834
+ if (!Prototype.BrowserFeatures.ElementExtensions &&
1835
+ document.createElement('div').__proto__) {
1836
+ window.HTMLElement = {};
1837
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
1838
+ Prototype.BrowserFeatures.ElementExtensions = true;
1839
+ }
1840
+
1841
+ Element.hasAttribute = function(element, attribute) {
1842
+ if (element.hasAttribute) return element.hasAttribute(attribute);
1843
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
1844
+ };
1845
+
1846
+ Element.addMethods = function(methods) {
1847
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
1848
+
1849
+ if (!methods) {
1850
+ Object.extend(Form, Form.Methods);
1851
+ Object.extend(Form.Element, Form.Element.Methods);
1852
+ Object.extend(Element.Methods.ByTag, {
1853
+ "FORM": Object.clone(Form.Methods),
1854
+ "INPUT": Object.clone(Form.Element.Methods),
1855
+ "SELECT": Object.clone(Form.Element.Methods),
1856
+ "TEXTAREA": Object.clone(Form.Element.Methods)
1857
+ });
1858
+ }
1859
+
1860
+ if (arguments.length == 2) {
1861
+ var tagName = methods;
1862
+ methods = arguments[1];
1863
+ }
1864
+
1865
+ if (!tagName) Object.extend(Element.Methods, methods || {});
1866
+ else {
1867
+ if (tagName.constructor == Array) tagName.each(extend);
1868
+ else extend(tagName);
1869
+ }
1870
+
1871
+ function extend(tagName) {
1872
+ tagName = tagName.toUpperCase();
1873
+ if (!Element.Methods.ByTag[tagName])
1874
+ Element.Methods.ByTag[tagName] = {};
1875
+ Object.extend(Element.Methods.ByTag[tagName], methods);
1876
+ }
1877
+
1878
+ function copy(methods, destination, onlyIfAbsent) {
1879
+ onlyIfAbsent = onlyIfAbsent || false;
1880
+ var cache = Element.extend.cache;
1881
+ for (var property in methods) {
1882
+ var value = methods[property];
1883
+ if (!onlyIfAbsent || !(property in destination))
1884
+ destination[property] = cache.findOrStore(value);
1885
+ }
1886
+ }
1887
+
1888
+ function findDOMClass(tagName) {
1889
+ var klass;
1890
+ var trans = {
1891
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
1892
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
1893
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
1894
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
1895
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
1896
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
1897
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
1898
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
1899
+ "FrameSet", "IFRAME": "IFrame"
1900
+ };
1901
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
1902
+ if (window[klass]) return window[klass];
1903
+ klass = 'HTML' + tagName + 'Element';
1904
+ if (window[klass]) return window[klass];
1905
+ klass = 'HTML' + tagName.capitalize() + 'Element';
1906
+ if (window[klass]) return window[klass];
1907
+
1908
+ window[klass] = {};
1909
+ window[klass].prototype = document.createElement(tagName).__proto__;
1910
+ return window[klass];
1911
+ }
1912
+
1913
+ if (F.ElementExtensions) {
1914
+ copy(Element.Methods, HTMLElement.prototype);
1915
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
1916
+ }
1917
+
1918
+ if (F.SpecificElementExtensions) {
1919
+ for (var tag in Element.Methods.ByTag) {
1920
+ var klass = findDOMClass(tag);
1921
+ if (typeof klass == "undefined") continue;
1922
+ copy(T[tag], klass.prototype);
1923
+ }
1924
+ }
1925
+
1926
+ Object.extend(Element, Element.Methods);
1927
+ delete Element.ByTag;
1928
+ };
1929
+
1930
+ var Toggle = { display: Element.toggle };
1931
+
1932
+ /*--------------------------------------------------------------------------*/
1933
+
1934
+ Abstract.Insertion = function(adjacency) {
1935
+ this.adjacency = adjacency;
1936
+ }
1937
+
1938
+ Abstract.Insertion.prototype = {
1939
+ initialize: function(element, content) {
1940
+ this.element = $(element);
1941
+ this.content = content.stripScripts();
1942
+
1943
+ if (this.adjacency && this.element.insertAdjacentHTML) {
1944
+ try {
1945
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
1946
+ } catch (e) {
1947
+ var tagName = this.element.tagName.toUpperCase();
1948
+ if (['TBODY', 'TR'].include(tagName)) {
1949
+ this.insertContent(this.contentFromAnonymousTable());
1950
+ } else {
1951
+ throw e;
1952
+ }
1953
+ }
1954
+ } else {
1955
+ this.range = this.element.ownerDocument.createRange();
1956
+ if (this.initializeRange) this.initializeRange();
1957
+ this.insertContent([this.range.createContextualFragment(this.content)]);
1958
+ }
1959
+
1960
+ setTimeout(function() {content.evalScripts()}, 10);
1961
+ },
1962
+
1963
+ contentFromAnonymousTable: function() {
1964
+ var div = document.createElement('div');
1965
+ div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1966
+ return $A(div.childNodes[0].childNodes[0].childNodes);
1967
+ }
1968
+ }
1969
+
1970
+ var Insertion = new Object();
1971
+
1972
+ Insertion.Before = Class.create();
1973
+ Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1974
+ initializeRange: function() {
1975
+ this.range.setStartBefore(this.element);
1976
+ },
1977
+
1978
+ insertContent: function(fragments) {
1979
+ fragments.each((function(fragment) {
1980
+ this.element.parentNode.insertBefore(fragment, this.element);
1981
+ }).bind(this));
1982
+ }
1983
+ });
1984
+
1985
+ Insertion.Top = Class.create();
1986
+ Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1987
+ initializeRange: function() {
1988
+ this.range.selectNodeContents(this.element);
1989
+ this.range.collapse(true);
1990
+ },
1991
+
1992
+ insertContent: function(fragments) {
1993
+ fragments.reverse(false).each((function(fragment) {
1994
+ this.element.insertBefore(fragment, this.element.firstChild);
1995
+ }).bind(this));
1996
+ }
1997
+ });
1998
+
1999
+ Insertion.Bottom = Class.create();
2000
+ Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
2001
+ initializeRange: function() {
2002
+ this.range.selectNodeContents(this.element);
2003
+ this.range.collapse(this.element);
2004
+ },
2005
+
2006
+ insertContent: function(fragments) {
2007
+ fragments.each((function(fragment) {
2008
+ this.element.appendChild(fragment);
2009
+ }).bind(this));
2010
+ }
2011
+ });
2012
+
2013
+ Insertion.After = Class.create();
2014
+ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
2015
+ initializeRange: function() {
2016
+ this.range.setStartAfter(this.element);
2017
+ },
2018
+
2019
+ insertContent: function(fragments) {
2020
+ fragments.each((function(fragment) {
2021
+ this.element.parentNode.insertBefore(fragment,
2022
+ this.element.nextSibling);
2023
+ }).bind(this));
2024
+ }
2025
+ });
2026
+
2027
+ /*--------------------------------------------------------------------------*/
2028
+
2029
+ Element.ClassNames = Class.create();
2030
+ Element.ClassNames.prototype = {
2031
+ initialize: function(element) {
2032
+ this.element = $(element);
2033
+ },
2034
+
2035
+ _each: function(iterator) {
2036
+ this.element.className.split(/\s+/).select(function(name) {
2037
+ return name.length > 0;
2038
+ })._each(iterator);
2039
+ },
2040
+
2041
+ set: function(className) {
2042
+ this.element.className = className;
2043
+ },
2044
+
2045
+ add: function(classNameToAdd) {
2046
+ if (this.include(classNameToAdd)) return;
2047
+ this.set($A(this).concat(classNameToAdd).join(' '));
2048
+ },
2049
+
2050
+ remove: function(classNameToRemove) {
2051
+ if (!this.include(classNameToRemove)) return;
2052
+ this.set($A(this).without(classNameToRemove).join(' '));
2053
+ },
2054
+
2055
+ toString: function() {
2056
+ return $A(this).join(' ');
2057
+ }
2058
+ };
2059
+
2060
+ Object.extend(Element.ClassNames.prototype, Enumerable);
2061
+ /* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
2062
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
2063
+ * license. Please see http://www.yui-ext.com/ for more information. */
2064
+
2065
+ var Selector = Class.create();
2066
+
2067
+ Selector.prototype = {
2068
+ initialize: function(expression) {
2069
+ this.expression = expression.strip();
2070
+ this.compileMatcher();
2071
+ },
2072
+
2073
+ compileMatcher: function() {
2074
+ // Selectors with namespaced attributes can't use the XPath version
2075
+ if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression))
2076
+ return this.compileXPathMatcher();
2077
+
2078
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
2079
+ c = Selector.criteria, le, p, m;
2080
+
2081
+ if (Selector._cache[e]) {
2082
+ this.matcher = Selector._cache[e]; return;
2083
+ }
2084
+ this.matcher = ["this.matcher = function(root) {",
2085
+ "var r = root, h = Selector.handlers, c = false, n;"];
2086
+
2087
+ while (e && le != e && (/\S/).test(e)) {
2088
+ le = e;
2089
+ for (var i in ps) {
2090
+ p = ps[i];
2091
+ if (m = e.match(p)) {
2092
+ this.matcher.push(typeof c[i] == 'function' ? c[i](m) :
2093
+ new Template(c[i]).evaluate(m));
2094
+ e = e.replace(m[0], '');
2095
+ break;
2096
+ }
2097
+ }
2098
+ }
2099
+
2100
+ this.matcher.push("return h.unique(n);\n}");
2101
+ eval(this.matcher.join('\n'));
2102
+ Selector._cache[this.expression] = this.matcher;
2103
+ },
2104
+
2105
+ compileXPathMatcher: function() {
2106
+ var e = this.expression, ps = Selector.patterns,
2107
+ x = Selector.xpath, le, m;
2108
+
2109
+ if (Selector._cache[e]) {
2110
+ this.xpath = Selector._cache[e]; return;
2111
+ }
2112
+
2113
+ this.matcher = ['.//*'];
2114
+ while (e && le != e && (/\S/).test(e)) {
2115
+ le = e;
2116
+ for (var i in ps) {
2117
+ if (m = e.match(ps[i])) {
2118
+ this.matcher.push(typeof x[i] == 'function' ? x[i](m) :
2119
+ new Template(x[i]).evaluate(m));
2120
+ e = e.replace(m[0], '');
2121
+ break;
2122
+ }
2123
+ }
2124
+ }
2125
+
2126
+ this.xpath = this.matcher.join('');
2127
+ Selector._cache[this.expression] = this.xpath;
2128
+ },
2129
+
2130
+ findElements: function(root) {
2131
+ root = root || document;
2132
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
2133
+ return this.matcher(root);
2134
+ },
2135
+
2136
+ match: function(element) {
2137
+ return this.findElements(document).include(element);
2138
+ },
2139
+
2140
+ toString: function() {
2141
+ return this.expression;
2142
+ },
2143
+
2144
+ inspect: function() {
2145
+ return "#<Selector:" + this.expression.inspect() + ">";
2146
+ }
2147
+ };
2148
+
2149
+ Object.extend(Selector, {
2150
+ _cache: {},
2151
+
2152
+ xpath: {
2153
+ descendant: "//*",
2154
+ child: "/*",
2155
+ adjacent: "/following-sibling::*[1]",
2156
+ laterSibling: '/following-sibling::*',
2157
+ tagName: function(m) {
2158
+ if (m[1] == '*') return '';
2159
+ return "[local-name()='" + m[1].toLowerCase() +
2160
+ "' or local-name()='" + m[1].toUpperCase() + "']";
2161
+ },
2162
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2163
+ id: "[@id='#{1}']",
2164
+ attrPresence: "[@#{1}]",
2165
+ attr: function(m) {
2166
+ m[3] = m[5] || m[6];
2167
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2168
+ },
2169
+ pseudo: function(m) {
2170
+ var h = Selector.xpath.pseudos[m[1]];
2171
+ if (!h) return '';
2172
+ if (typeof h === 'function') return h(m);
2173
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
2174
+ },
2175
+ operators: {
2176
+ '=': "[@#{1}='#{3}']",
2177
+ '!=': "[@#{1}!='#{3}']",
2178
+ '^=': "[starts-with(@#{1}, '#{3}')]",
2179
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
2180
+ '*=': "[contains(@#{1}, '#{3}')]",
2181
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
2182
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
2183
+ },
2184
+ pseudos: {
2185
+ 'first-child': '[not(preceding-sibling::*)]',
2186
+ 'last-child': '[not(following-sibling::*)]',
2187
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
2188
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
2189
+ 'checked': "[@checked]",
2190
+ 'disabled': "[@disabled]",
2191
+ 'enabled': "[not(@disabled)]",
2192
+ 'not': function(m) {
2193
+ var e = m[6], p = Selector.patterns,
2194
+ x = Selector.xpath, le, m, v;
2195
+
2196
+ var exclusion = [];
2197
+ while (e && le != e && (/\S/).test(e)) {
2198
+ le = e;
2199
+ for (var i in p) {
2200
+ if (m = e.match(p[i])) {
2201
+ v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m);
2202
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2203
+ e = e.replace(m[0], '');
2204
+ break;
2205
+ }
2206
+ }
2207
+ }
2208
+ return "[not(" + exclusion.join(" and ") + ")]";
2209
+ },
2210
+ 'nth-child': function(m) {
2211
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
2212
+ },
2213
+ 'nth-last-child': function(m) {
2214
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
2215
+ },
2216
+ 'nth-of-type': function(m) {
2217
+ return Selector.xpath.pseudos.nth("position() ", m);
2218
+ },
2219
+ 'nth-last-of-type': function(m) {
2220
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
2221
+ },
2222
+ 'first-of-type': function(m) {
2223
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
2224
+ },
2225
+ 'last-of-type': function(m) {
2226
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
2227
+ },
2228
+ 'only-of-type': function(m) {
2229
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
2230
+ },
2231
+ nth: function(fragment, m) {
2232
+ var mm, formula = m[6], predicate;
2233
+ if (formula == 'even') formula = '2n+0';
2234
+ if (formula == 'odd') formula = '2n+1';
2235
+ if (mm = formula.match(/^(\d+)$/)) // digit only
2236
+ return '[' + fragment + "= " + mm[1] + ']';
2237
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
2238
+ if (mm[1] == "-") mm[1] = -1;
2239
+ var a = mm[1] ? Number(mm[1]) : 1;
2240
+ var b = mm[2] ? Number(mm[2]) : 0;
2241
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
2242
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
2243
+ return new Template(predicate).evaluate({
2244
+ fragment: fragment, a: a, b: b });
2245
+ }
2246
+ }
2247
+ }
2248
+ },
2249
+
2250
+ criteria: {
2251
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
2252
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
2253
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
2254
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
2255
+ attr: function(m) {
2256
+ m[3] = (m[5] || m[6]);
2257
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
2258
+ },
2259
+ pseudo: function(m) {
2260
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
2261
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
2262
+ },
2263
+ descendant: 'c = "descendant";',
2264
+ child: 'c = "child";',
2265
+ adjacent: 'c = "adjacent";',
2266
+ laterSibling: 'c = "laterSibling";'
2267
+ },
2268
+
2269
+ patterns: {
2270
+ // combinators must be listed first
2271
+ // (and descendant needs to be last combinator)
2272
+ laterSibling: /^\s*~\s*/,
2273
+ child: /^\s*>\s*/,
2274
+ adjacent: /^\s*\+\s*/,
2275
+ descendant: /^\s/,
2276
+
2277
+ // selectors follow
2278
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
2279
+ id: /^#([\w\-\*]+)(\b|$)/,
2280
+ className: /^\.([\w\-\*]+)(\b|$)/,
2281
+ pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/,
2282
+ attrPresence: /^\[([\w]+)\]/,
2283
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/
2284
+ },
2285
+
2286
+ handlers: {
2287
+ // UTILITY FUNCTIONS
2288
+ // joins two collections
2289
+ concat: function(a, b) {
2290
+ for (var i = 0, node; node = b[i]; i++)
2291
+ a.push(node);
2292
+ return a;
2293
+ },
2294
+
2295
+ // marks an array of nodes for counting
2296
+ mark: function(nodes) {
2297
+ for (var i = 0, node; node = nodes[i]; i++)
2298
+ node._counted = true;
2299
+ return nodes;
2300
+ },
2301
+
2302
+ unmark: function(nodes) {
2303
+ for (var i = 0, node; node = nodes[i]; i++)
2304
+ node._counted = undefined;
2305
+ return nodes;
2306
+ },
2307
+
2308
+ // mark each child node with its position (for nth calls)
2309
+ // "ofType" flag indicates whether we're indexing for nth-of-type
2310
+ // rather than nth-child
2311
+ index: function(parentNode, reverse, ofType) {
2312
+ parentNode._counted = true;
2313
+ if (reverse) {
2314
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
2315
+ node = nodes[i];
2316
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
2317
+ }
2318
+ } else {
2319
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
2320
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
2321
+ }
2322
+ },
2323
+
2324
+ // filters out duplicates and extends all nodes
2325
+ unique: function(nodes) {
2326
+ if (nodes.length == 0) return nodes;
2327
+ var results = [], n;
2328
+ for (var i = 0, l = nodes.length; i < l; i++)
2329
+ if (!(n = nodes[i])._counted) {
2330
+ n._counted = true;
2331
+ results.push(Element.extend(n));
2332
+ }
2333
+ return Selector.handlers.unmark(results);
2334
+ },
2335
+
2336
+ // COMBINATOR FUNCTIONS
2337
+ descendant: function(nodes) {
2338
+ var h = Selector.handlers;
2339
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2340
+ h.concat(results, node.getElementsByTagName('*'));
2341
+ return results;
2342
+ },
2343
+
2344
+ child: function(nodes) {
2345
+ var h = Selector.handlers;
2346
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
2347
+ for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
2348
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
2349
+ }
2350
+ return results;
2351
+ },
2352
+
2353
+ adjacent: function(nodes) {
2354
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
2355
+ var next = this.nextElementSibling(node);
2356
+ if (next) results.push(next);
2357
+ }
2358
+ return results;
2359
+ },
2360
+
2361
+ laterSibling: function(nodes) {
2362
+ var h = Selector.handlers;
2363
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2364
+ h.concat(results, Element.nextSiblings(node));
2365
+ return results;
2366
+ },
2367
+
2368
+ nextElementSibling: function(node) {
2369
+ while (node = node.nextSibling)
2370
+ if (node.nodeType == 1) return node;
2371
+ return null;
2372
+ },
2373
+
2374
+ previousElementSibling: function(node) {
2375
+ while (node = node.previousSibling)
2376
+ if (node.nodeType == 1) return node;
2377
+ return null;
2378
+ },
2379
+
2380
+ // TOKEN FUNCTIONS
2381
+ tagName: function(nodes, root, tagName, combinator) {
2382
+ tagName = tagName.toUpperCase();
2383
+ var results = [], h = Selector.handlers;
2384
+ if (nodes) {
2385
+ if (combinator) {
2386
+ // fastlane for ordinary descendant combinators
2387
+ if (combinator == "descendant") {
2388
+ for (var i = 0, node; node = nodes[i]; i++)
2389
+ h.concat(results, node.getElementsByTagName(tagName));
2390
+ return results;
2391
+ } else nodes = this[combinator](nodes);
2392
+ if (tagName == "*") return nodes;
2393
+ }
2394
+ for (var i = 0, node; node = nodes[i]; i++)
2395
+ if (node.tagName.toUpperCase() == tagName) results.push(node);
2396
+ return results;
2397
+ } else return root.getElementsByTagName(tagName);
2398
+ },
2399
+
2400
+ id: function(nodes, root, id, combinator) {
2401
+ var targetNode = $(id), h = Selector.handlers;
2402
+ if (!nodes && root == document) return targetNode ? [targetNode] : [];
2403
+ if (nodes) {
2404
+ if (combinator) {
2405
+ if (combinator == 'child') {
2406
+ for (var i = 0, node; node = nodes[i]; i++)
2407
+ if (targetNode.parentNode == node) return [targetNode];
2408
+ } else if (combinator == 'descendant') {
2409
+ for (var i = 0, node; node = nodes[i]; i++)
2410
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
2411
+ } else if (combinator == 'adjacent') {
2412
+ for (var i = 0, node; node = nodes[i]; i++)
2413
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
2414
+ return [targetNode];
2415
+ } else nodes = h[combinator](nodes);
2416
+ }
2417
+ for (var i = 0, node; node = nodes[i]; i++)
2418
+ if (node == targetNode) return [targetNode];
2419
+ return [];
2420
+ }
2421
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
2422
+ },
2423
+
2424
+ className: function(nodes, root, className, combinator) {
2425
+ if (nodes && combinator) nodes = this[combinator](nodes);
2426
+ return Selector.handlers.byClassName(nodes, root, className);
2427
+ },
2428
+
2429
+ byClassName: function(nodes, root, className) {
2430
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
2431
+ var needle = ' ' + className + ' ';
2432
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
2433
+ nodeClassName = node.className;
2434
+ if (nodeClassName.length == 0) continue;
2435
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
2436
+ results.push(node);
2437
+ }
2438
+ return results;
2439
+ },
2440
+
2441
+ attrPresence: function(nodes, root, attr) {
2442
+ var results = [];
2443
+ for (var i = 0, node; node = nodes[i]; i++)
2444
+ if (Element.hasAttribute(node, attr)) results.push(node);
2445
+ return results;
2446
+ },
2447
+
2448
+ attr: function(nodes, root, attr, value, operator) {
2449
+ if (!nodes) nodes = root.getElementsByTagName("*");
2450
+ var handler = Selector.operators[operator], results = [];
2451
+ for (var i = 0, node; node = nodes[i]; i++) {
2452
+ var nodeValue = Element.readAttribute(node, attr);
2453
+ if (nodeValue === null) continue;
2454
+ if (handler(nodeValue, value)) results.push(node);
2455
+ }
2456
+ return results;
2457
+ },
2458
+
2459
+ pseudo: function(nodes, name, value, root, combinator) {
2460
+ if (nodes && combinator) nodes = this[combinator](nodes);
2461
+ if (!nodes) nodes = root.getElementsByTagName("*");
2462
+ return Selector.pseudos[name](nodes, value, root);
2463
+ }
2464
+ },
2465
+
2466
+ pseudos: {
2467
+ 'first-child': function(nodes, value, root) {
2468
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
2469
+ if (Selector.handlers.previousElementSibling(node)) continue;
2470
+ results.push(node);
2471
+ }
2472
+ return results;
2473
+ },
2474
+ 'last-child': function(nodes, value, root) {
2475
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
2476
+ if (Selector.handlers.nextElementSibling(node)) continue;
2477
+ results.push(node);
2478
+ }
2479
+ return results;
2480
+ },
2481
+ 'only-child': function(nodes, value, root) {
2482
+ var h = Selector.handlers;
2483
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2484
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
2485
+ results.push(node);
2486
+ return results;
2487
+ },
2488
+ 'nth-child': function(nodes, formula, root) {
2489
+ return Selector.pseudos.nth(nodes, formula, root);
2490
+ },
2491
+ 'nth-last-child': function(nodes, formula, root) {
2492
+ return Selector.pseudos.nth(nodes, formula, root, true);
2493
+ },
2494
+ 'nth-of-type': function(nodes, formula, root) {
2495
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
2496
+ },
2497
+ 'nth-last-of-type': function(nodes, formula, root) {
2498
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
2499
+ },
2500
+ 'first-of-type': function(nodes, formula, root) {
2501
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
2502
+ },
2503
+ 'last-of-type': function(nodes, formula, root) {
2504
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
2505
+ },
2506
+ 'only-of-type': function(nodes, formula, root) {
2507
+ var p = Selector.pseudos;
2508
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
2509
+ },
2510
+
2511
+ // handles the an+b logic
2512
+ getIndices: function(a, b, total) {
2513
+ if (a == 0) return b > 0 ? [b] : [];
2514
+ return $R(1, total).inject([], function(memo, i) {
2515
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
2516
+ return memo;
2517
+ });
2518
+ },
2519
+
2520
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
2521
+ nth: function(nodes, formula, root, reverse, ofType) {
2522
+ if (nodes.length == 0) return [];
2523
+ if (formula == 'even') formula = '2n+0';
2524
+ if (formula == 'odd') formula = '2n+1';
2525
+ var h = Selector.handlers, results = [], indexed = [], m;
2526
+ h.mark(nodes);
2527
+ for (var i = 0, node; node = nodes[i]; i++) {
2528
+ if (!node.parentNode._counted) {
2529
+ h.index(node.parentNode, reverse, ofType);
2530
+ indexed.push(node.parentNode);
2531
+ }
2532
+ }
2533
+ if (formula.match(/^\d+$/)) { // just a number
2534
+ formula = Number(formula);
2535
+ for (var i = 0, node; node = nodes[i]; i++)
2536
+ if (node.nodeIndex == formula) results.push(node);
2537
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
2538
+ if (m[1] == "-") m[1] = -1;
2539
+ var a = m[1] ? Number(m[1]) : 1;
2540
+ var b = m[2] ? Number(m[2]) : 0;
2541
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
2542
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
2543
+ for (var j = 0; j < l; j++)
2544
+ if (node.nodeIndex == indices[j]) results.push(node);
2545
+ }
2546
+ }
2547
+ h.unmark(nodes);
2548
+ h.unmark(indexed);
2549
+ return results;
2550
+ },
2551
+
2552
+ 'empty': function(nodes, value, root) {
2553
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
2554
+ // IE treats comments as element nodes
2555
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
2556
+ results.push(node);
2557
+ }
2558
+ return results;
2559
+ },
2560
+
2561
+ 'not': function(nodes, selector, root) {
2562
+ var h = Selector.handlers, selectorType, m;
2563
+ var exclusions = new Selector(selector).findElements(root);
2564
+ h.mark(exclusions);
2565
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2566
+ if (!node._counted) results.push(node);
2567
+ h.unmark(exclusions);
2568
+ return results;
2569
+ },
2570
+
2571
+ 'enabled': function(nodes, value, root) {
2572
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2573
+ if (!node.disabled) results.push(node);
2574
+ return results;
2575
+ },
2576
+
2577
+ 'disabled': function(nodes, value, root) {
2578
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2579
+ if (node.disabled) results.push(node);
2580
+ return results;
2581
+ },
2582
+
2583
+ 'checked': function(nodes, value, root) {
2584
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
2585
+ if (node.checked) results.push(node);
2586
+ return results;
2587
+ }
2588
+ },
2589
+
2590
+ operators: {
2591
+ '=': function(nv, v) { return nv == v; },
2592
+ '!=': function(nv, v) { return nv != v; },
2593
+ '^=': function(nv, v) { return nv.startsWith(v); },
2594
+ '$=': function(nv, v) { return nv.endsWith(v); },
2595
+ '*=': function(nv, v) { return nv.include(v); },
2596
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
2597
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
2598
+ },
2599
+
2600
+ matchElements: function(elements, expression) {
2601
+ var matches = new Selector(expression).findElements(), h = Selector.handlers;
2602
+ h.mark(matches);
2603
+ for (var i = 0, results = [], element; element = elements[i]; i++)
2604
+ if (element._counted) results.push(element);
2605
+ h.unmark(matches);
2606
+ return results;
2607
+ },
2608
+
2609
+ findElement: function(elements, expression, index) {
2610
+ if (typeof expression == 'number') {
2611
+ index = expression; expression = false;
2612
+ }
2613
+ return Selector.matchElements(elements, expression || '*')[index || 0];
2614
+ },
2615
+
2616
+ findChildElements: function(element, expressions) {
2617
+ var exprs = expressions.join(','), expressions = [];
2618
+ exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
2619
+ expressions.push(m[1].strip());
2620
+ });
2621
+ var results = [], h = Selector.handlers;
2622
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
2623
+ selector = new Selector(expressions[i].strip());
2624
+ h.concat(results, selector.findElements(element));
2625
+ }
2626
+ return (l > 1) ? h.unique(results) : results;
2627
+ }
2628
+ });
2629
+
2630
+ function $$() {
2631
+ return Selector.findChildElements(document, $A(arguments));
2632
+ }
2633
+ var Form = {
2634
+ reset: function(form) {
2635
+ $(form).reset();
2636
+ return form;
2637
+ },
2638
+
2639
+ serializeElements: function(elements, getHash) {
2640
+ var data = elements.inject({}, function(result, element) {
2641
+ if (!element.disabled && element.name) {
2642
+ var key = element.name, value = $(element).getValue();
2643
+ if (value != null) {
2644
+ if (key in result) {
2645
+ if (result[key].constructor != Array) result[key] = [result[key]];
2646
+ result[key].push(value);
2647
+ }
2648
+ else result[key] = value;
2649
+ }
2650
+ }
2651
+ return result;
2652
+ });
2653
+
2654
+ return getHash ? data : Hash.toQueryString(data);
2655
+ }
2656
+ };
2657
+
2658
+ Form.Methods = {
2659
+ serialize: function(form, getHash) {
2660
+ return Form.serializeElements(Form.getElements(form), getHash);
2661
+ },
2662
+
2663
+ getElements: function(form) {
2664
+ return $A($(form).getElementsByTagName('*')).inject([],
2665
+ function(elements, child) {
2666
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
2667
+ elements.push(Element.extend(child));
2668
+ return elements;
2669
+ }
2670
+ );
2671
+ },
2672
+
2673
+ getInputs: function(form, typeName, name) {
2674
+ form = $(form);
2675
+ var inputs = form.getElementsByTagName('input');
2676
+
2677
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
2678
+
2679
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
2680
+ var input = inputs[i];
2681
+ if ((typeName && input.type != typeName) || (name && input.name != name))
2682
+ continue;
2683
+ matchingInputs.push(Element.extend(input));
2684
+ }
2685
+
2686
+ return matchingInputs;
2687
+ },
2688
+
2689
+ disable: function(form) {
2690
+ form = $(form);
2691
+ Form.getElements(form).invoke('disable');
2692
+ return form;
2693
+ },
2694
+
2695
+ enable: function(form) {
2696
+ form = $(form);
2697
+ Form.getElements(form).invoke('enable');
2698
+ return form;
2699
+ },
2700
+
2701
+ findFirstElement: function(form) {
2702
+ return $(form).getElements().find(function(element) {
2703
+ return element.type != 'hidden' && !element.disabled &&
2704
+ ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
2705
+ });
2706
+ },
2707
+
2708
+ focusFirstElement: function(form) {
2709
+ form = $(form);
2710
+ form.findFirstElement().activate();
2711
+ return form;
2712
+ },
2713
+
2714
+ request: function(form, options) {
2715
+ form = $(form), options = Object.clone(options || {});
2716
+
2717
+ var params = options.parameters;
2718
+ options.parameters = form.serialize(true);
2719
+
2720
+ if (params) {
2721
+ if (typeof params == 'string') params = params.toQueryParams();
2722
+ Object.extend(options.parameters, params);
2723
+ }
2724
+
2725
+ if (form.hasAttribute('method') && !options.method)
2726
+ options.method = form.method;
2727
+
2728
+ return new Ajax.Request(form.readAttribute('action'), options);
2729
+ }
2730
+ }
2731
+
2732
+ /*--------------------------------------------------------------------------*/
2733
+
2734
+ Form.Element = {
2735
+ focus: function(element) {
2736
+ $(element).focus();
2737
+ return element;
2738
+ },
2739
+
2740
+ select: function(element) {
2741
+ $(element).select();
2742
+ return element;
2743
+ }
2744
+ }
2745
+
2746
+ Form.Element.Methods = {
2747
+ serialize: function(element) {
2748
+ element = $(element);
2749
+ if (!element.disabled && element.name) {
2750
+ var value = element.getValue();
2751
+ if (value != undefined) {
2752
+ var pair = {};
2753
+ pair[element.name] = value;
2754
+ return Hash.toQueryString(pair);
2755
+ }
2756
+ }
2757
+ return '';
2758
+ },
2759
+
2760
+ getValue: function(element) {
2761
+ element = $(element);
2762
+ var method = element.tagName.toLowerCase();
2763
+ return Form.Element.Serializers[method](element);
2764
+ },
2765
+
2766
+ clear: function(element) {
2767
+ $(element).value = '';
2768
+ return element;
2769
+ },
2770
+
2771
+ present: function(element) {
2772
+ return $(element).value != '';
2773
+ },
2774
+
2775
+ activate: function(element) {
2776
+ element = $(element);
2777
+ try {
2778
+ element.focus();
2779
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
2780
+ !['button', 'reset', 'submit'].include(element.type)))
2781
+ element.select();
2782
+ } catch (e) {}
2783
+ return element;
2784
+ },
2785
+
2786
+ disable: function(element) {
2787
+ element = $(element);
2788
+ element.blur();
2789
+ element.disabled = true;
2790
+ return element;
2791
+ },
2792
+
2793
+ enable: function(element) {
2794
+ element = $(element);
2795
+ element.disabled = false;
2796
+ return element;
2797
+ }
2798
+ }
2799
+
2800
+ /*--------------------------------------------------------------------------*/
2801
+
2802
+ var Field = Form.Element;
2803
+ var $F = Form.Element.Methods.getValue;
2804
+
2805
+ /*--------------------------------------------------------------------------*/
2806
+
2807
+ Form.Element.Serializers = {
2808
+ input: function(element) {
2809
+ switch (element.type.toLowerCase()) {
2810
+ case 'checkbox':
2811
+ case 'radio':
2812
+ return Form.Element.Serializers.inputSelector(element);
2813
+ default:
2814
+ return Form.Element.Serializers.textarea(element);
2815
+ }
2816
+ },
2817
+
2818
+ inputSelector: function(element) {
2819
+ return element.checked ? element.value : null;
2820
+ },
2821
+
2822
+ textarea: function(element) {
2823
+ return element.value;
2824
+ },
2825
+
2826
+ select: function(element) {
2827
+ return this[element.type == 'select-one' ?
2828
+ 'selectOne' : 'selectMany'](element);
2829
+ },
2830
+
2831
+ selectOne: function(element) {
2832
+ var index = element.selectedIndex;
2833
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
2834
+ },
2835
+
2836
+ selectMany: function(element) {
2837
+ var values, length = element.length;
2838
+ if (!length) return null;
2839
+
2840
+ for (var i = 0, values = []; i < length; i++) {
2841
+ var opt = element.options[i];
2842
+ if (opt.selected) values.push(this.optionValue(opt));
2843
+ }
2844
+ return values;
2845
+ },
2846
+
2847
+ optionValue: function(opt) {
2848
+ // extend element because hasAttribute may not be native
2849
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
2850
+ }
2851
+ }
2852
+
2853
+ /*--------------------------------------------------------------------------*/
2854
+
2855
+ Abstract.TimedObserver = function() {}
2856
+ Abstract.TimedObserver.prototype = {
2857
+ initialize: function(element, frequency, callback) {
2858
+ this.frequency = frequency;
2859
+ this.element = $(element);
2860
+ this.callback = callback;
2861
+
2862
+ this.lastValue = this.getValue();
2863
+ this.registerCallback();
2864
+ },
2865
+
2866
+ registerCallback: function() {
2867
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
2868
+ },
2869
+
2870
+ onTimerEvent: function() {
2871
+ var value = this.getValue();
2872
+ var changed = ('string' == typeof this.lastValue && 'string' == typeof value
2873
+ ? this.lastValue != value : String(this.lastValue) != String(value));
2874
+ if (changed) {
2875
+ this.callback(this.element, value);
2876
+ this.lastValue = value;
2877
+ }
2878
+ }
2879
+ }
2880
+
2881
+ Form.Element.Observer = Class.create();
2882
+ Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2883
+ getValue: function() {
2884
+ return Form.Element.getValue(this.element);
2885
+ }
2886
+ });
2887
+
2888
+ Form.Observer = Class.create();
2889
+ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
2890
+ getValue: function() {
2891
+ return Form.serialize(this.element);
2892
+ }
2893
+ });
2894
+
2895
+ /*--------------------------------------------------------------------------*/
2896
+
2897
+ Abstract.EventObserver = function() {}
2898
+ Abstract.EventObserver.prototype = {
2899
+ initialize: function(element, callback) {
2900
+ this.element = $(element);
2901
+ this.callback = callback;
2902
+
2903
+ this.lastValue = this.getValue();
2904
+ if (this.element.tagName.toLowerCase() == 'form')
2905
+ this.registerFormCallbacks();
2906
+ else
2907
+ this.registerCallback(this.element);
2908
+ },
2909
+
2910
+ onElementEvent: function() {
2911
+ var value = this.getValue();
2912
+ if (this.lastValue != value) {
2913
+ this.callback(this.element, value);
2914
+ this.lastValue = value;
2915
+ }
2916
+ },
2917
+
2918
+ registerFormCallbacks: function() {
2919
+ Form.getElements(this.element).each(this.registerCallback.bind(this));
2920
+ },
2921
+
2922
+ registerCallback: function(element) {
2923
+ if (element.type) {
2924
+ switch (element.type.toLowerCase()) {
2925
+ case 'checkbox':
2926
+ case 'radio':
2927
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
2928
+ break;
2929
+ default:
2930
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
2931
+ break;
2932
+ }
2933
+ }
2934
+ }
2935
+ }
2936
+
2937
+ Form.Element.EventObserver = Class.create();
2938
+ Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2939
+ getValue: function() {
2940
+ return Form.Element.getValue(this.element);
2941
+ }
2942
+ });
2943
+
2944
+ Form.EventObserver = Class.create();
2945
+ Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
2946
+ getValue: function() {
2947
+ return Form.serialize(this.element);
2948
+ }
2949
+ });
2950
+ if (!window.Event) {
2951
+ var Event = new Object();
2952
+ }
2953
+
2954
+ Object.extend(Event, {
2955
+ KEY_BACKSPACE: 8,
2956
+ KEY_TAB: 9,
2957
+ KEY_RETURN: 13,
2958
+ KEY_ESC: 27,
2959
+ KEY_LEFT: 37,
2960
+ KEY_UP: 38,
2961
+ KEY_RIGHT: 39,
2962
+ KEY_DOWN: 40,
2963
+ KEY_DELETE: 46,
2964
+ KEY_HOME: 36,
2965
+ KEY_END: 35,
2966
+ KEY_PAGEUP: 33,
2967
+ KEY_PAGEDOWN: 34,
2968
+
2969
+ element: function(event) {
2970
+ return $(event.target || event.srcElement);
2971
+ },
2972
+
2973
+ isLeftClick: function(event) {
2974
+ return (((event.which) && (event.which == 1)) ||
2975
+ ((event.button) && (event.button == 1)));
2976
+ },
2977
+
2978
+ pointerX: function(event) {
2979
+ return event.pageX || (event.clientX +
2980
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
2981
+ },
2982
+
2983
+ pointerY: function(event) {
2984
+ return event.pageY || (event.clientY +
2985
+ (document.documentElement.scrollTop || document.body.scrollTop));
2986
+ },
2987
+
2988
+ stop: function(event) {
2989
+ if (event.preventDefault) {
2990
+ event.preventDefault();
2991
+ event.stopPropagation();
2992
+ } else {
2993
+ event.returnValue = false;
2994
+ event.cancelBubble = true;
2995
+ }
2996
+ },
2997
+
2998
+ // find the first node with the given tagName, starting from the
2999
+ // node the event was triggered on; traverses the DOM upwards
3000
+ findElement: function(event, tagName) {
3001
+ var element = Event.element(event);
3002
+ while (element.parentNode && (!element.tagName ||
3003
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
3004
+ element = element.parentNode;
3005
+ return element;
3006
+ },
3007
+
3008
+ observers: false,
3009
+
3010
+ _observeAndCache: function(element, name, observer, useCapture) {
3011
+ if (!this.observers) this.observers = [];
3012
+ if (element.addEventListener) {
3013
+ this.observers.push([element, name, observer, useCapture]);
3014
+ element.addEventListener(name, observer, useCapture);
3015
+ } else if (element.attachEvent) {
3016
+ this.observers.push([element, name, observer, useCapture]);
3017
+ element.attachEvent('on' + name, observer);
3018
+ }
3019
+ },
3020
+
3021
+ unloadCache: function() {
3022
+ if (!Event.observers) return;
3023
+ for (var i = 0, length = Event.observers.length; i < length; i++) {
3024
+ Event.stopObserving.apply(this, Event.observers[i]);
3025
+ Event.observers[i][0] = null;
3026
+ }
3027
+ Event.observers = false;
3028
+ },
3029
+
3030
+ observe: function(element, name, observer, useCapture) {
3031
+ element = $(element);
3032
+ useCapture = useCapture || false;
3033
+
3034
+ if (name == 'keypress' &&
3035
+ (Prototype.Browser.WebKit || element.attachEvent))
3036
+ name = 'keydown';
3037
+
3038
+ Event._observeAndCache(element, name, observer, useCapture);
3039
+ },
3040
+
3041
+ stopObserving: function(element, name, observer, useCapture) {
3042
+ element = $(element);
3043
+ useCapture = useCapture || false;
3044
+
3045
+ if (name == 'keypress' &&
3046
+ (Prototype.Browser.WebKit || element.attachEvent))
3047
+ name = 'keydown';
3048
+
3049
+ if (element.removeEventListener) {
3050
+ element.removeEventListener(name, observer, useCapture);
3051
+ } else if (element.detachEvent) {
3052
+ try {
3053
+ element.detachEvent('on' + name, observer);
3054
+ } catch (e) {}
3055
+ }
3056
+ }
3057
+ });
3058
+
3059
+ /* prevent memory leaks in IE */
3060
+ if (Prototype.Browser.IE)
3061
+ Event.observe(window, 'unload', Event.unloadCache, false);
3062
+ var Position = {
3063
+ // set to true if needed, warning: firefox performance problems
3064
+ // NOT neeeded for page scrolling, only if draggable contained in
3065
+ // scrollable elements
3066
+ includeScrollOffsets: false,
3067
+
3068
+ // must be called before calling withinIncludingScrolloffset, every time the
3069
+ // page is scrolled
3070
+ prepare: function() {
3071
+ this.deltaX = window.pageXOffset
3072
+ || document.documentElement.scrollLeft
3073
+ || document.body.scrollLeft
3074
+ || 0;
3075
+ this.deltaY = window.pageYOffset
3076
+ || document.documentElement.scrollTop
3077
+ || document.body.scrollTop
3078
+ || 0;
3079
+ },
3080
+
3081
+ realOffset: function(element) {
3082
+ var valueT = 0, valueL = 0;
3083
+ do {
3084
+ valueT += element.scrollTop || 0;
3085
+ valueL += element.scrollLeft || 0;
3086
+ element = element.parentNode;
3087
+ } while (element);
3088
+ return [valueL, valueT];
3089
+ },
3090
+
3091
+ cumulativeOffset: function(element) {
3092
+ var valueT = 0, valueL = 0;
3093
+ do {
3094
+ valueT += element.offsetTop || 0;
3095
+ valueL += element.offsetLeft || 0;
3096
+ element = element.offsetParent;
3097
+ } while (element);
3098
+ return [valueL, valueT];
3099
+ },
3100
+
3101
+ positionedOffset: function(element) {
3102
+ var valueT = 0, valueL = 0;
3103
+ do {
3104
+ valueT += element.offsetTop || 0;
3105
+ valueL += element.offsetLeft || 0;
3106
+ element = element.offsetParent;
3107
+ if (element) {
3108
+ if(element.tagName=='BODY') break;
3109
+ var p = Element.getStyle(element, 'position');
3110
+ if (p == 'relative' || p == 'absolute') break;
3111
+ }
3112
+ } while (element);
3113
+ return [valueL, valueT];
3114
+ },
3115
+
3116
+ offsetParent: function(element) {
3117
+ if (element.offsetParent) return element.offsetParent;
3118
+ if (element == document.body) return element;
3119
+
3120
+ while ((element = element.parentNode) && element != document.body)
3121
+ if (Element.getStyle(element, 'position') != 'static')
3122
+ return element;
3123
+
3124
+ return document.body;
3125
+ },
3126
+
3127
+ // caches x/y coordinate pair to use with overlap
3128
+ within: function(element, x, y) {
3129
+ if (this.includeScrollOffsets)
3130
+ return this.withinIncludingScrolloffsets(element, x, y);
3131
+ this.xcomp = x;
3132
+ this.ycomp = y;
3133
+ this.offset = this.cumulativeOffset(element);
3134
+
3135
+ return (y >= this.offset[1] &&
3136
+ y < this.offset[1] + element.offsetHeight &&
3137
+ x >= this.offset[0] &&
3138
+ x < this.offset[0] + element.offsetWidth);
3139
+ },
3140
+
3141
+ withinIncludingScrolloffsets: function(element, x, y) {
3142
+ var offsetcache = this.realOffset(element);
3143
+
3144
+ this.xcomp = x + offsetcache[0] - this.deltaX;
3145
+ this.ycomp = y + offsetcache[1] - this.deltaY;
3146
+ this.offset = this.cumulativeOffset(element);
3147
+
3148
+ return (this.ycomp >= this.offset[1] &&
3149
+ this.ycomp < this.offset[1] + element.offsetHeight &&
3150
+ this.xcomp >= this.offset[0] &&
3151
+ this.xcomp < this.offset[0] + element.offsetWidth);
3152
+ },
3153
+
3154
+ // within must be called directly before
3155
+ overlap: function(mode, element) {
3156
+ if (!mode) return 0;
3157
+ if (mode == 'vertical')
3158
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
3159
+ element.offsetHeight;
3160
+ if (mode == 'horizontal')
3161
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
3162
+ element.offsetWidth;
3163
+ },
3164
+
3165
+ page: function(forElement) {
3166
+ var valueT = 0, valueL = 0;
3167
+
3168
+ var element = forElement;
3169
+ do {
3170
+ valueT += element.offsetTop || 0;
3171
+ valueL += element.offsetLeft || 0;
3172
+
3173
+ // Safari fix
3174
+ if (element.offsetParent == document.body)
3175
+ if (Element.getStyle(element,'position')=='absolute') break;
3176
+
3177
+ } while (element = element.offsetParent);
3178
+
3179
+ element = forElement;
3180
+ do {
3181
+ if (!window.opera || element.tagName=='BODY') {
3182
+ valueT -= element.scrollTop || 0;
3183
+ valueL -= element.scrollLeft || 0;
3184
+ }
3185
+ } while (element = element.parentNode);
3186
+
3187
+ return [valueL, valueT];
3188
+ },
3189
+
3190
+ clone: function(source, target) {
3191
+ var options = Object.extend({
3192
+ setLeft: true,
3193
+ setTop: true,
3194
+ setWidth: true,
3195
+ setHeight: true,
3196
+ offsetTop: 0,
3197
+ offsetLeft: 0
3198
+ }, arguments[2] || {})
3199
+
3200
+ // find page position of source
3201
+ source = $(source);
3202
+ var p = Position.page(source);
3203
+
3204
+ // find coordinate system to use
3205
+ target = $(target);
3206
+ var delta = [0, 0];
3207
+ var parent = null;
3208
+ // delta [0,0] will do fine with position: fixed elements,
3209
+ // position:absolute needs offsetParent deltas
3210
+ if (Element.getStyle(target,'position') == 'absolute') {
3211
+ parent = Position.offsetParent(target);
3212
+ delta = Position.page(parent);
3213
+ }
3214
+
3215
+ // correct by body offsets (fixes Safari)
3216
+ if (parent == document.body) {
3217
+ delta[0] -= document.body.offsetLeft;
3218
+ delta[1] -= document.body.offsetTop;
3219
+ }
3220
+
3221
+ // set position
3222
+ if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
3223
+ if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
3224
+ if(options.setWidth) target.style.width = source.offsetWidth + 'px';
3225
+ if(options.setHeight) target.style.height = source.offsetHeight + 'px';
3226
+ },
3227
+
3228
+ absolutize: function(element) {
3229
+ element = $(element);
3230
+ if (element.style.position == 'absolute') return;
3231
+ Position.prepare();
3232
+
3233
+ var offsets = Position.positionedOffset(element);
3234
+ var top = offsets[1];
3235
+ var left = offsets[0];
3236
+ var width = element.clientWidth;
3237
+ var height = element.clientHeight;
3238
+
3239
+ element._originalLeft = left - parseFloat(element.style.left || 0);
3240
+ element._originalTop = top - parseFloat(element.style.top || 0);
3241
+ element._originalWidth = element.style.width;
3242
+ element._originalHeight = element.style.height;
3243
+
3244
+ element.style.position = 'absolute';
3245
+ element.style.top = top + 'px';
3246
+ element.style.left = left + 'px';
3247
+ element.style.width = width + 'px';
3248
+ element.style.height = height + 'px';
3249
+ },
3250
+
3251
+ relativize: function(element) {
3252
+ element = $(element);
3253
+ if (element.style.position == 'relative') return;
3254
+ Position.prepare();
3255
+
3256
+ element.style.position = 'relative';
3257
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
3258
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
3259
+
3260
+ element.style.top = top + 'px';
3261
+ element.style.left = left + 'px';
3262
+ element.style.height = element._originalHeight;
3263
+ element.style.width = element._originalWidth;
3264
+ }
3265
+ }
3266
+
3267
+ // Safari returns margins on body which is incorrect if the child is absolutely
3268
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
3269
+ // KHTML/WebKit only.
3270
+ if (Prototype.Browser.WebKit) {
3271
+ Position.cumulativeOffset = function(element) {
3272
+ var valueT = 0, valueL = 0;
3273
+ do {
3274
+ valueT += element.offsetTop || 0;
3275
+ valueL += element.offsetLeft || 0;
3276
+ if (element.offsetParent == document.body)
3277
+ if (Element.getStyle(element, 'position') == 'absolute') break;
3278
+
3279
+ element = element.offsetParent;
3280
+ } while (element);
3281
+
3282
+ return [valueL, valueT];
3283
+ }
3284
+ }
3285
+
3286
+ Element.addMethods();