insults 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4401 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2
+ <html lang='en'>
3
+ <head>
4
+ <title>Methods [Insults will insult you when it feels you deserve it.]</title>
5
+ <meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
6
+ <link href='rdoc-style.css' media='screen' rel='stylesheet' type='text/css'>
7
+ <base target='docwin'>
8
+ </head>
9
+ <body class='list'>
10
+ <div id='index'>
11
+ <h1>Methods</h1>
12
+ <script type='text/javascript'>
13
+ /* Prototype JavaScript framework, version 1.6.0.3
14
+ * (c) 2005-2008 Sam Stephenson
15
+ *
16
+ * Prototype is freely distributable under the terms of an MIT-style license.
17
+ * For details, see the Prototype web site: http://www.prototypejs.org/
18
+ *
19
+ *--------------------------------------------------------------------------*/
20
+
21
+ var Prototype = {
22
+ Version: '1.6.0.3',
23
+
24
+ Browser: {
25
+ IE: !!(window.attachEvent &&
26
+ navigator.userAgent.indexOf('Opera') === -1),
27
+ Opera: navigator.userAgent.indexOf('Opera') > -1,
28
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
29
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
30
+ navigator.userAgent.indexOf('KHTML') === -1,
31
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
32
+ },
33
+
34
+ BrowserFeatures: {
35
+ XPath: !!document.evaluate,
36
+ SelectorsAPI: !!document.querySelector,
37
+ ElementExtensions: !!window.HTMLElement,
38
+ SpecificElementExtensions:
39
+ document.createElement('div')['__proto__'] &&
40
+ document.createElement('div')['__proto__'] !==
41
+ document.createElement('form')['__proto__']
42
+ },
43
+
44
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
45
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
46
+
47
+ emptyFunction: function() { },
48
+ K: function(x) { return x }
49
+ };
50
+
51
+ if (Prototype.Browser.MobileSafari)
52
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
53
+
54
+
55
+ /* Based on Alex Arnell's inheritance implementation. */
56
+ var Class = {
57
+ create: function() {
58
+ var parent = null, properties = $A(arguments);
59
+ if (Object.isFunction(properties[0]))
60
+ parent = properties.shift();
61
+
62
+ function klass() {
63
+ this.initialize.apply(this, arguments);
64
+ }
65
+
66
+ Object.extend(klass, Class.Methods);
67
+ klass.superclass = parent;
68
+ klass.subclasses = [];
69
+
70
+ if (parent) {
71
+ var subclass = function() { };
72
+ subclass.prototype = parent.prototype;
73
+ klass.prototype = new subclass;
74
+ parent.subclasses.push(klass);
75
+ }
76
+
77
+ for (var i = 0; i < properties.length; i++)
78
+ klass.addMethods(properties[i]);
79
+
80
+ if (!klass.prototype.initialize)
81
+ klass.prototype.initialize = Prototype.emptyFunction;
82
+
83
+ klass.prototype.constructor = klass;
84
+
85
+ return klass;
86
+ }
87
+ };
88
+
89
+ Class.Methods = {
90
+ addMethods: function(source) {
91
+ var ancestor = this.superclass && this.superclass.prototype;
92
+ var properties = Object.keys(source);
93
+
94
+ if (!Object.keys({ toString: true }).length)
95
+ properties.push("toString", "valueOf");
96
+
97
+ for (var i = 0, length = properties.length; i < length; i++) {
98
+ var property = properties[i], value = source[property];
99
+ if (ancestor && Object.isFunction(value) &&
100
+ value.argumentNames().first() == "$super") {
101
+ var method = value;
102
+ value = (function(m) {
103
+ return function() { return ancestor[m].apply(this, arguments) };
104
+ })(property).wrap(method);
105
+
106
+ value.valueOf = method.valueOf.bind(method);
107
+ value.toString = method.toString.bind(method);
108
+ }
109
+ this.prototype[property] = value;
110
+ }
111
+
112
+ return this;
113
+ }
114
+ };
115
+
116
+ var Abstract = { };
117
+
118
+ Object.extend = function(destination, source) {
119
+ for (var property in source)
120
+ destination[property] = source[property];
121
+ return destination;
122
+ };
123
+
124
+ Object.extend(Object, {
125
+ inspect: function(object) {
126
+ try {
127
+ if (Object.isUndefined(object)) return 'undefined';
128
+ if (object === null) return 'null';
129
+ return object.inspect ? object.inspect() : String(object);
130
+ } catch (e) {
131
+ if (e instanceof RangeError) return '...';
132
+ throw e;
133
+ }
134
+ },
135
+
136
+ toJSON: function(object) {
137
+ var type = typeof object;
138
+ switch (type) {
139
+ case 'undefined':
140
+ case 'function':
141
+ case 'unknown': return;
142
+ case 'boolean': return object.toString();
143
+ }
144
+
145
+ if (object === null) return 'null';
146
+ if (object.toJSON) return object.toJSON();
147
+ if (Object.isElement(object)) return;
148
+
149
+ var results = [];
150
+ for (var property in object) {
151
+ var value = Object.toJSON(object[property]);
152
+ if (!Object.isUndefined(value))
153
+ results.push(property.toJSON() + ': ' + value);
154
+ }
155
+
156
+ return '{' + results.join(', ') + '}';
157
+ },
158
+
159
+ toQueryString: function(object) {
160
+ return $H(object).toQueryString();
161
+ },
162
+
163
+ toHTML: function(object) {
164
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
165
+ },
166
+
167
+ keys: function(object) {
168
+ var keys = [];
169
+ for (var property in object)
170
+ keys.push(property);
171
+ return keys;
172
+ },
173
+
174
+ values: function(object) {
175
+ var values = [];
176
+ for (var property in object)
177
+ values.push(object[property]);
178
+ return values;
179
+ },
180
+
181
+ clone: function(object) {
182
+ return Object.extend({ }, object);
183
+ },
184
+
185
+ isElement: function(object) {
186
+ return !!(object && object.nodeType == 1);
187
+ },
188
+
189
+ isArray: function(object) {
190
+ return object != null && typeof object == "object" &&
191
+ 'splice' in object && 'join' in object;
192
+ },
193
+
194
+ isHash: function(object) {
195
+ return object instanceof Hash;
196
+ },
197
+
198
+ isFunction: function(object) {
199
+ return typeof object == "function";
200
+ },
201
+
202
+ isString: function(object) {
203
+ return typeof object == "string";
204
+ },
205
+
206
+ isNumber: function(object) {
207
+ return typeof object == "number";
208
+ },
209
+
210
+ isUndefined: function(object) {
211
+ return typeof object == "undefined";
212
+ }
213
+ });
214
+
215
+ Object.extend(Function.prototype, {
216
+ argumentNames: function() {
217
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
218
+ .replace(/\s+/g, '').split(',');
219
+ return names.length == 1 && !names[0] ? [] : names;
220
+ },
221
+
222
+ bind: function() {
223
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
224
+ var __method = this, args = $A(arguments), object = args.shift();
225
+ return function() {
226
+ return __method.apply(object, args.concat($A(arguments)));
227
+ }
228
+ },
229
+
230
+ bindAsEventListener: function() {
231
+ var __method = this, args = $A(arguments), object = args.shift();
232
+ return function(event) {
233
+ return __method.apply(object, [event || window.event].concat(args));
234
+ }
235
+ },
236
+
237
+ curry: function() {
238
+ if (!arguments.length) return this;
239
+ var __method = this, args = $A(arguments);
240
+ return function() {
241
+ return __method.apply(this, args.concat($A(arguments)));
242
+ }
243
+ },
244
+
245
+ delay: function() {
246
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
247
+ return window.setTimeout(function() {
248
+ return __method.apply(__method, args);
249
+ }, timeout);
250
+ },
251
+
252
+ defer: function() {
253
+ var args = [0.01].concat($A(arguments));
254
+ return this.delay.apply(this, args);
255
+ },
256
+
257
+ wrap: function(wrapper) {
258
+ var __method = this;
259
+ return function() {
260
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
261
+ }
262
+ },
263
+
264
+ methodize: function() {
265
+ if (this._methodized) return this._methodized;
266
+ var __method = this;
267
+ return this._methodized = function() {
268
+ return __method.apply(null, [this].concat($A(arguments)));
269
+ };
270
+ }
271
+ });
272
+
273
+ Date.prototype.toJSON = function() {
274
+ return '"' + this.getUTCFullYear() + '-' +
275
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
276
+ this.getUTCDate().toPaddedString(2) + 'T' +
277
+ this.getUTCHours().toPaddedString(2) + ':' +
278
+ this.getUTCMinutes().toPaddedString(2) + ':' +
279
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
280
+ };
281
+
282
+ var Try = {
283
+ these: function() {
284
+ var returnValue;
285
+
286
+ for (var i = 0, length = arguments.length; i < length; i++) {
287
+ var lambda = arguments[i];
288
+ try {
289
+ returnValue = lambda();
290
+ break;
291
+ } catch (e) { }
292
+ }
293
+
294
+ return returnValue;
295
+ }
296
+ };
297
+
298
+ RegExp.prototype.match = RegExp.prototype.test;
299
+
300
+ RegExp.escape = function(str) {
301
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
302
+ };
303
+
304
+ /*--------------------------------------------------------------------------*/
305
+
306
+ var PeriodicalExecuter = Class.create({
307
+ initialize: function(callback, frequency) {
308
+ this.callback = callback;
309
+ this.frequency = frequency;
310
+ this.currentlyExecuting = false;
311
+
312
+ this.registerCallback();
313
+ },
314
+
315
+ registerCallback: function() {
316
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
317
+ },
318
+
319
+ execute: function() {
320
+ this.callback(this);
321
+ },
322
+
323
+ stop: function() {
324
+ if (!this.timer) return;
325
+ clearInterval(this.timer);
326
+ this.timer = null;
327
+ },
328
+
329
+ onTimerEvent: function() {
330
+ if (!this.currentlyExecuting) {
331
+ try {
332
+ this.currentlyExecuting = true;
333
+ this.execute();
334
+ } finally {
335
+ this.currentlyExecuting = false;
336
+ }
337
+ }
338
+ }
339
+ });
340
+ Object.extend(String, {
341
+ interpret: function(value) {
342
+ return value == null ? '' : String(value);
343
+ },
344
+ specialChar: {
345
+ '\b': '\\b',
346
+ '\t': '\\t',
347
+ '\n': '\\n',
348
+ '\f': '\\f',
349
+ '\r': '\\r',
350
+ '\\': '\\\\'
351
+ }
352
+ });
353
+
354
+ Object.extend(String.prototype, {
355
+ gsub: function(pattern, replacement) {
356
+ var result = '', source = this, match;
357
+ replacement = arguments.callee.prepareReplacement(replacement);
358
+
359
+ while (source.length > 0) {
360
+ if (match = source.match(pattern)) {
361
+ result += source.slice(0, match.index);
362
+ result += String.interpret(replacement(match));
363
+ source = source.slice(match.index + match[0].length);
364
+ } else {
365
+ result += source, source = '';
366
+ }
367
+ }
368
+ return result;
369
+ },
370
+
371
+ sub: function(pattern, replacement, count) {
372
+ replacement = this.gsub.prepareReplacement(replacement);
373
+ count = Object.isUndefined(count) ? 1 : count;
374
+
375
+ return this.gsub(pattern, function(match) {
376
+ if (--count < 0) return match[0];
377
+ return replacement(match);
378
+ });
379
+ },
380
+
381
+ scan: function(pattern, iterator) {
382
+ this.gsub(pattern, iterator);
383
+ return String(this);
384
+ },
385
+
386
+ truncate: function(length, truncation) {
387
+ length = length || 30;
388
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
389
+ return this.length > length ?
390
+ this.slice(0, length - truncation.length) + truncation : String(this);
391
+ },
392
+
393
+ strip: function() {
394
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
395
+ },
396
+
397
+ stripTags: function() {
398
+ return this.replace(/<\/?[^>]+>/gi, '');
399
+ },
400
+
401
+ stripScripts: function() {
402
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
403
+ },
404
+
405
+ extractScripts: function() {
406
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
407
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
408
+ return (this.match(matchAll) || []).map(function(scriptTag) {
409
+ return (scriptTag.match(matchOne) || ['', ''])[1];
410
+ });
411
+ },
412
+
413
+ evalScripts: function() {
414
+ return this.extractScripts().map(function(script) { return eval(script) });
415
+ },
416
+
417
+ escapeHTML: function() {
418
+ var self = arguments.callee;
419
+ self.text.data = this;
420
+ return self.div.innerHTML;
421
+ },
422
+
423
+ unescapeHTML: function() {
424
+ var div = new Element('div');
425
+ div.innerHTML = this.stripTags();
426
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
427
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
428
+ div.childNodes[0].nodeValue) : '';
429
+ },
430
+
431
+ toQueryParams: function(separator) {
432
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
433
+ if (!match) return { };
434
+
435
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
436
+ if ((pair = pair.split('='))[0]) {
437
+ var key = decodeURIComponent(pair.shift());
438
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
439
+ if (value != undefined) value = decodeURIComponent(value);
440
+
441
+ if (key in hash) {
442
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
443
+ hash[key].push(value);
444
+ }
445
+ else hash[key] = value;
446
+ }
447
+ return hash;
448
+ });
449
+ },
450
+
451
+ toArray: function() {
452
+ return this.split('');
453
+ },
454
+
455
+ succ: function() {
456
+ return this.slice(0, this.length - 1) +
457
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
458
+ },
459
+
460
+ times: function(count) {
461
+ return count < 1 ? '' : new Array(count + 1).join(this);
462
+ },
463
+
464
+ camelize: function() {
465
+ var parts = this.split('-'), len = parts.length;
466
+ if (len == 1) return parts[0];
467
+
468
+ var camelized = this.charAt(0) == '-'
469
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
470
+ : parts[0];
471
+
472
+ for (var i = 1; i < len; i++)
473
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
474
+
475
+ return camelized;
476
+ },
477
+
478
+ capitalize: function() {
479
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
480
+ },
481
+
482
+ underscore: function() {
483
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
484
+ },
485
+
486
+ dasherize: function() {
487
+ return this.gsub(/_/,'-');
488
+ },
489
+
490
+ inspect: function(useDoubleQuotes) {
491
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
492
+ var character = String.specialChar[match[0]];
493
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
494
+ });
495
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
496
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
497
+ },
498
+
499
+ toJSON: function() {
500
+ return this.inspect(true);
501
+ },
502
+
503
+ unfilterJSON: function(filter) {
504
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
505
+ },
506
+
507
+ isJSON: function() {
508
+ var str = this;
509
+ if (str.blank()) return false;
510
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
511
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
512
+ },
513
+
514
+ evalJSON: function(sanitize) {
515
+ var json = this.unfilterJSON();
516
+ try {
517
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
518
+ } catch (e) { }
519
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
520
+ },
521
+
522
+ include: function(pattern) {
523
+ return this.indexOf(pattern) > -1;
524
+ },
525
+
526
+ startsWith: function(pattern) {
527
+ return this.indexOf(pattern) === 0;
528
+ },
529
+
530
+ endsWith: function(pattern) {
531
+ var d = this.length - pattern.length;
532
+ return d >= 0 && this.lastIndexOf(pattern) === d;
533
+ },
534
+
535
+ empty: function() {
536
+ return this == '';
537
+ },
538
+
539
+ blank: function() {
540
+ return /^\s*$/.test(this);
541
+ },
542
+
543
+ interpolate: function(object, pattern) {
544
+ return new Template(this, pattern).evaluate(object);
545
+ }
546
+ });
547
+
548
+ if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
549
+ escapeHTML: function() {
550
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
551
+ },
552
+ unescapeHTML: function() {
553
+ return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
554
+ }
555
+ });
556
+
557
+ String.prototype.gsub.prepareReplacement = function(replacement) {
558
+ if (Object.isFunction(replacement)) return replacement;
559
+ var template = new Template(replacement);
560
+ return function(match) { return template.evaluate(match) };
561
+ };
562
+
563
+ String.prototype.parseQuery = String.prototype.toQueryParams;
564
+
565
+ Object.extend(String.prototype.escapeHTML, {
566
+ div: document.createElement('div'),
567
+ text: document.createTextNode('')
568
+ });
569
+
570
+ String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
571
+
572
+ var Template = Class.create({
573
+ initialize: function(template, pattern) {
574
+ this.template = template.toString();
575
+ this.pattern = pattern || Template.Pattern;
576
+ },
577
+
578
+ evaluate: function(object) {
579
+ if (Object.isFunction(object.toTemplateReplacements))
580
+ object = object.toTemplateReplacements();
581
+
582
+ return this.template.gsub(this.pattern, function(match) {
583
+ if (object == null) return '';
584
+
585
+ var before = match[1] || '';
586
+ if (before == '\\') return match[2];
587
+
588
+ var ctx = object, expr = match[3];
589
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
590
+ match = pattern.exec(expr);
591
+ if (match == null) return before;
592
+
593
+ while (match != null) {
594
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
595
+ ctx = ctx[comp];
596
+ if (null == ctx || '' == match[3]) break;
597
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
598
+ match = pattern.exec(expr);
599
+ }
600
+
601
+ return before + String.interpret(ctx);
602
+ });
603
+ }
604
+ });
605
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
606
+
607
+ var $break = { };
608
+
609
+ var Enumerable = {
610
+ each: function(iterator, context) {
611
+ var index = 0;
612
+ try {
613
+ this._each(function(value) {
614
+ iterator.call(context, value, index++);
615
+ });
616
+ } catch (e) {
617
+ if (e != $break) throw e;
618
+ }
619
+ return this;
620
+ },
621
+
622
+ eachSlice: function(number, iterator, context) {
623
+ var index = -number, slices = [], array = this.toArray();
624
+ if (number < 1) return array;
625
+ while ((index += number) < array.length)
626
+ slices.push(array.slice(index, index+number));
627
+ return slices.collect(iterator, context);
628
+ },
629
+
630
+ all: function(iterator, context) {
631
+ iterator = iterator || Prototype.K;
632
+ var result = true;
633
+ this.each(function(value, index) {
634
+ result = result && !!iterator.call(context, value, index);
635
+ if (!result) throw $break;
636
+ });
637
+ return result;
638
+ },
639
+
640
+ any: function(iterator, context) {
641
+ iterator = iterator || Prototype.K;
642
+ var result = false;
643
+ this.each(function(value, index) {
644
+ if (result = !!iterator.call(context, value, index))
645
+ throw $break;
646
+ });
647
+ return result;
648
+ },
649
+
650
+ collect: function(iterator, context) {
651
+ iterator = iterator || Prototype.K;
652
+ var results = [];
653
+ this.each(function(value, index) {
654
+ results.push(iterator.call(context, value, index));
655
+ });
656
+ return results;
657
+ },
658
+
659
+ detect: function(iterator, context) {
660
+ var result;
661
+ this.each(function(value, index) {
662
+ if (iterator.call(context, value, index)) {
663
+ result = value;
664
+ throw $break;
665
+ }
666
+ });
667
+ return result;
668
+ },
669
+
670
+ findAll: function(iterator, context) {
671
+ var results = [];
672
+ this.each(function(value, index) {
673
+ if (iterator.call(context, value, index))
674
+ results.push(value);
675
+ });
676
+ return results;
677
+ },
678
+
679
+ grep: function(filter, iterator, context) {
680
+ iterator = iterator || Prototype.K;
681
+ var results = [];
682
+
683
+ if (Object.isString(filter))
684
+ filter = new RegExp(filter);
685
+
686
+ this.each(function(value, index) {
687
+ if (filter.match(value))
688
+ results.push(iterator.call(context, value, index));
689
+ });
690
+ return results;
691
+ },
692
+
693
+ include: function(object) {
694
+ if (Object.isFunction(this.indexOf))
695
+ if (this.indexOf(object) != -1) return true;
696
+
697
+ var found = false;
698
+ this.each(function(value) {
699
+ if (value == object) {
700
+ found = true;
701
+ throw $break;
702
+ }
703
+ });
704
+ return found;
705
+ },
706
+
707
+ inGroupsOf: function(number, fillWith) {
708
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
709
+ return this.eachSlice(number, function(slice) {
710
+ while(slice.length < number) slice.push(fillWith);
711
+ return slice;
712
+ });
713
+ },
714
+
715
+ inject: function(memo, iterator, context) {
716
+ this.each(function(value, index) {
717
+ memo = iterator.call(context, memo, value, index);
718
+ });
719
+ return memo;
720
+ },
721
+
722
+ invoke: function(method) {
723
+ var args = $A(arguments).slice(1);
724
+ return this.map(function(value) {
725
+ return value[method].apply(value, args);
726
+ });
727
+ },
728
+
729
+ max: function(iterator, context) {
730
+ iterator = iterator || Prototype.K;
731
+ var result;
732
+ this.each(function(value, index) {
733
+ value = iterator.call(context, value, index);
734
+ if (result == null || value >= result)
735
+ result = value;
736
+ });
737
+ return result;
738
+ },
739
+
740
+ min: function(iterator, context) {
741
+ iterator = iterator || Prototype.K;
742
+ var result;
743
+ this.each(function(value, index) {
744
+ value = iterator.call(context, value, index);
745
+ if (result == null || value < result)
746
+ result = value;
747
+ });
748
+ return result;
749
+ },
750
+
751
+ partition: function(iterator, context) {
752
+ iterator = iterator || Prototype.K;
753
+ var trues = [], falses = [];
754
+ this.each(function(value, index) {
755
+ (iterator.call(context, value, index) ?
756
+ trues : falses).push(value);
757
+ });
758
+ return [trues, falses];
759
+ },
760
+
761
+ pluck: function(property) {
762
+ var results = [];
763
+ this.each(function(value) {
764
+ results.push(value[property]);
765
+ });
766
+ return results;
767
+ },
768
+
769
+ reject: function(iterator, context) {
770
+ var results = [];
771
+ this.each(function(value, index) {
772
+ if (!iterator.call(context, value, index))
773
+ results.push(value);
774
+ });
775
+ return results;
776
+ },
777
+
778
+ sortBy: function(iterator, context) {
779
+ return this.map(function(value, index) {
780
+ return {
781
+ value: value,
782
+ criteria: iterator.call(context, value, index)
783
+ };
784
+ }).sort(function(left, right) {
785
+ var a = left.criteria, b = right.criteria;
786
+ return a < b ? -1 : a > b ? 1 : 0;
787
+ }).pluck('value');
788
+ },
789
+
790
+ toArray: function() {
791
+ return this.map();
792
+ },
793
+
794
+ zip: function() {
795
+ var iterator = Prototype.K, args = $A(arguments);
796
+ if (Object.isFunction(args.last()))
797
+ iterator = args.pop();
798
+
799
+ var collections = [this].concat(args).map($A);
800
+ return this.map(function(value, index) {
801
+ return iterator(collections.pluck(index));
802
+ });
803
+ },
804
+
805
+ size: function() {
806
+ return this.toArray().length;
807
+ },
808
+
809
+ inspect: function() {
810
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
811
+ }
812
+ };
813
+
814
+ Object.extend(Enumerable, {
815
+ map: Enumerable.collect,
816
+ find: Enumerable.detect,
817
+ select: Enumerable.findAll,
818
+ filter: Enumerable.findAll,
819
+ member: Enumerable.include,
820
+ entries: Enumerable.toArray,
821
+ every: Enumerable.all,
822
+ some: Enumerable.any
823
+ });
824
+ function $A(iterable) {
825
+ if (!iterable) return [];
826
+ if (iterable.toArray) return iterable.toArray();
827
+ var length = iterable.length || 0, results = new Array(length);
828
+ while (length--) results[length] = iterable[length];
829
+ return results;
830
+ }
831
+
832
+ if (Prototype.Browser.WebKit) {
833
+ $A = function(iterable) {
834
+ if (!iterable) return [];
835
+ // In Safari, only use the `toArray` method if it's not a NodeList.
836
+ // A NodeList is a function, has an function `item` property, and a numeric
837
+ // `length` property. Adapted from Google Doctype.
838
+ if (!(typeof iterable === 'function' && typeof iterable.length ===
839
+ 'number' && typeof iterable.item === 'function') && iterable.toArray)
840
+ return iterable.toArray();
841
+ var length = iterable.length || 0, results = new Array(length);
842
+ while (length--) results[length] = iterable[length];
843
+ return results;
844
+ };
845
+ }
846
+
847
+ Array.from = $A;
848
+
849
+ Object.extend(Array.prototype, Enumerable);
850
+
851
+ if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
852
+
853
+ Object.extend(Array.prototype, {
854
+ _each: function(iterator) {
855
+ for (var i = 0, length = this.length; i < length; i++)
856
+ iterator(this[i]);
857
+ },
858
+
859
+ clear: function() {
860
+ this.length = 0;
861
+ return this;
862
+ },
863
+
864
+ first: function() {
865
+ return this[0];
866
+ },
867
+
868
+ last: function() {
869
+ return this[this.length - 1];
870
+ },
871
+
872
+ compact: function() {
873
+ return this.select(function(value) {
874
+ return value != null;
875
+ });
876
+ },
877
+
878
+ flatten: function() {
879
+ return this.inject([], function(array, value) {
880
+ return array.concat(Object.isArray(value) ?
881
+ value.flatten() : [value]);
882
+ });
883
+ },
884
+
885
+ without: function() {
886
+ var values = $A(arguments);
887
+ return this.select(function(value) {
888
+ return !values.include(value);
889
+ });
890
+ },
891
+
892
+ reverse: function(inline) {
893
+ return (inline !== false ? this : this.toArray())._reverse();
894
+ },
895
+
896
+ reduce: function() {
897
+ return this.length > 1 ? this : this[0];
898
+ },
899
+
900
+ uniq: function(sorted) {
901
+ return this.inject([], function(array, value, index) {
902
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
903
+ array.push(value);
904
+ return array;
905
+ });
906
+ },
907
+
908
+ intersect: function(array) {
909
+ return this.uniq().findAll(function(item) {
910
+ return array.detect(function(value) { return item === value });
911
+ });
912
+ },
913
+
914
+ clone: function() {
915
+ return [].concat(this);
916
+ },
917
+
918
+ size: function() {
919
+ return this.length;
920
+ },
921
+
922
+ inspect: function() {
923
+ return '[' + this.map(Object.inspect).join(', ') + ']';
924
+ },
925
+
926
+ toJSON: function() {
927
+ var results = [];
928
+ this.each(function(object) {
929
+ var value = Object.toJSON(object);
930
+ if (!Object.isUndefined(value)) results.push(value);
931
+ });
932
+ return '[' + results.join(', ') + ']';
933
+ }
934
+ });
935
+
936
+ // use native browser JS 1.6 implementation if available
937
+ if (Object.isFunction(Array.prototype.forEach))
938
+ Array.prototype._each = Array.prototype.forEach;
939
+
940
+ if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
941
+ i || (i = 0);
942
+ var length = this.length;
943
+ if (i < 0) i = length + i;
944
+ for (; i < length; i++)
945
+ if (this[i] === item) return i;
946
+ return -1;
947
+ };
948
+
949
+ if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
950
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
951
+ var n = this.slice(0, i).reverse().indexOf(item);
952
+ return (n < 0) ? n : i - n - 1;
953
+ };
954
+
955
+ Array.prototype.toArray = Array.prototype.clone;
956
+
957
+ function $w(string) {
958
+ if (!Object.isString(string)) return [];
959
+ string = string.strip();
960
+ return string ? string.split(/\s+/) : [];
961
+ }
962
+
963
+ if (Prototype.Browser.Opera){
964
+ Array.prototype.concat = function() {
965
+ var array = [];
966
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
967
+ for (var i = 0, length = arguments.length; i < length; i++) {
968
+ if (Object.isArray(arguments[i])) {
969
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
970
+ array.push(arguments[i][j]);
971
+ } else {
972
+ array.push(arguments[i]);
973
+ }
974
+ }
975
+ return array;
976
+ };
977
+ }
978
+ Object.extend(Number.prototype, {
979
+ toColorPart: function() {
980
+ return this.toPaddedString(2, 16);
981
+ },
982
+
983
+ succ: function() {
984
+ return this + 1;
985
+ },
986
+
987
+ times: function(iterator, context) {
988
+ $R(0, this, true).each(iterator, context);
989
+ return this;
990
+ },
991
+
992
+ toPaddedString: function(length, radix) {
993
+ var string = this.toString(radix || 10);
994
+ return '0'.times(length - string.length) + string;
995
+ },
996
+
997
+ toJSON: function() {
998
+ return isFinite(this) ? this.toString() : 'null';
999
+ }
1000
+ });
1001
+
1002
+ $w('abs round ceil floor').each(function(method){
1003
+ Number.prototype[method] = Math[method].methodize();
1004
+ });
1005
+ function $H(object) {
1006
+ return new Hash(object);
1007
+ };
1008
+
1009
+ var Hash = Class.create(Enumerable, (function() {
1010
+
1011
+ function toQueryPair(key, value) {
1012
+ if (Object.isUndefined(value)) return key;
1013
+ return key + '=' + encodeURIComponent(String.interpret(value));
1014
+ }
1015
+
1016
+ return {
1017
+ initialize: function(object) {
1018
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1019
+ },
1020
+
1021
+ _each: function(iterator) {
1022
+ for (var key in this._object) {
1023
+ var value = this._object[key], pair = [key, value];
1024
+ pair.key = key;
1025
+ pair.value = value;
1026
+ iterator(pair);
1027
+ }
1028
+ },
1029
+
1030
+ set: function(key, value) {
1031
+ return this._object[key] = value;
1032
+ },
1033
+
1034
+ get: function(key) {
1035
+ // simulating poorly supported hasOwnProperty
1036
+ if (this._object[key] !== Object.prototype[key])
1037
+ return this._object[key];
1038
+ },
1039
+
1040
+ unset: function(key) {
1041
+ var value = this._object[key];
1042
+ delete this._object[key];
1043
+ return value;
1044
+ },
1045
+
1046
+ toObject: function() {
1047
+ return Object.clone(this._object);
1048
+ },
1049
+
1050
+ keys: function() {
1051
+ return this.pluck('key');
1052
+ },
1053
+
1054
+ values: function() {
1055
+ return this.pluck('value');
1056
+ },
1057
+
1058
+ index: function(value) {
1059
+ var match = this.detect(function(pair) {
1060
+ return pair.value === value;
1061
+ });
1062
+ return match && match.key;
1063
+ },
1064
+
1065
+ merge: function(object) {
1066
+ return this.clone().update(object);
1067
+ },
1068
+
1069
+ update: function(object) {
1070
+ return new Hash(object).inject(this, function(result, pair) {
1071
+ result.set(pair.key, pair.value);
1072
+ return result;
1073
+ });
1074
+ },
1075
+
1076
+ toQueryString: function() {
1077
+ return this.inject([], function(results, pair) {
1078
+ var key = encodeURIComponent(pair.key), values = pair.value;
1079
+
1080
+ if (values && typeof values == 'object') {
1081
+ if (Object.isArray(values))
1082
+ return results.concat(values.map(toQueryPair.curry(key)));
1083
+ } else results.push(toQueryPair(key, values));
1084
+ return results;
1085
+ }).join('&');
1086
+ },
1087
+
1088
+ inspect: function() {
1089
+ return '#<Hash:{' + this.map(function(pair) {
1090
+ return pair.map(Object.inspect).join(': ');
1091
+ }).join(', ') + '}>';
1092
+ },
1093
+
1094
+ toJSON: function() {
1095
+ return Object.toJSON(this.toObject());
1096
+ },
1097
+
1098
+ clone: function() {
1099
+ return new Hash(this);
1100
+ }
1101
+ }
1102
+ })());
1103
+
1104
+ Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
1105
+ Hash.from = $H;
1106
+ var ObjectRange = Class.create(Enumerable, {
1107
+ initialize: function(start, end, exclusive) {
1108
+ this.start = start;
1109
+ this.end = end;
1110
+ this.exclusive = exclusive;
1111
+ },
1112
+
1113
+ _each: function(iterator) {
1114
+ var value = this.start;
1115
+ while (this.include(value)) {
1116
+ iterator(value);
1117
+ value = value.succ();
1118
+ }
1119
+ },
1120
+
1121
+ include: function(value) {
1122
+ if (value < this.start)
1123
+ return false;
1124
+ if (this.exclusive)
1125
+ return value < this.end;
1126
+ return value <= this.end;
1127
+ }
1128
+ });
1129
+
1130
+ var $R = function(start, end, exclusive) {
1131
+ return new ObjectRange(start, end, exclusive);
1132
+ };
1133
+
1134
+ var Ajax = {
1135
+ getTransport: function() {
1136
+ return Try.these(
1137
+ function() {return new XMLHttpRequest()},
1138
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1139
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1140
+ ) || false;
1141
+ },
1142
+
1143
+ activeRequestCount: 0
1144
+ };
1145
+
1146
+ Ajax.Responders = {
1147
+ responders: [],
1148
+
1149
+ _each: function(iterator) {
1150
+ this.responders._each(iterator);
1151
+ },
1152
+
1153
+ register: function(responder) {
1154
+ if (!this.include(responder))
1155
+ this.responders.push(responder);
1156
+ },
1157
+
1158
+ unregister: function(responder) {
1159
+ this.responders = this.responders.without(responder);
1160
+ },
1161
+
1162
+ dispatch: function(callback, request, transport, json) {
1163
+ this.each(function(responder) {
1164
+ if (Object.isFunction(responder[callback])) {
1165
+ try {
1166
+ responder[callback].apply(responder, [request, transport, json]);
1167
+ } catch (e) { }
1168
+ }
1169
+ });
1170
+ }
1171
+ };
1172
+
1173
+ Object.extend(Ajax.Responders, Enumerable);
1174
+
1175
+ Ajax.Responders.register({
1176
+ onCreate: function() { Ajax.activeRequestCount++ },
1177
+ onComplete: function() { Ajax.activeRequestCount-- }
1178
+ });
1179
+
1180
+ Ajax.Base = Class.create({
1181
+ initialize: function(options) {
1182
+ this.options = {
1183
+ method: 'post',
1184
+ asynchronous: true,
1185
+ contentType: 'application/x-www-form-urlencoded',
1186
+ encoding: 'UTF-8',
1187
+ parameters: '',
1188
+ evalJSON: true,
1189
+ evalJS: true
1190
+ };
1191
+ Object.extend(this.options, options || { });
1192
+
1193
+ this.options.method = this.options.method.toLowerCase();
1194
+
1195
+ if (Object.isString(this.options.parameters))
1196
+ this.options.parameters = this.options.parameters.toQueryParams();
1197
+ else if (Object.isHash(this.options.parameters))
1198
+ this.options.parameters = this.options.parameters.toObject();
1199
+ }
1200
+ });
1201
+
1202
+ Ajax.Request = Class.create(Ajax.Base, {
1203
+ _complete: false,
1204
+
1205
+ initialize: function($super, url, options) {
1206
+ $super(options);
1207
+ this.transport = Ajax.getTransport();
1208
+ this.request(url);
1209
+ },
1210
+
1211
+ request: function(url) {
1212
+ this.url = url;
1213
+ this.method = this.options.method;
1214
+ var params = Object.clone(this.options.parameters);
1215
+
1216
+ if (!['get', 'post'].include(this.method)) {
1217
+ // simulate other verbs over post
1218
+ params['_method'] = this.method;
1219
+ this.method = 'post';
1220
+ }
1221
+
1222
+ this.parameters = params;
1223
+
1224
+ if (params = Object.toQueryString(params)) {
1225
+ // when GET, append parameters to URL
1226
+ if (this.method == 'get')
1227
+ this.url += (this.url.include('?') ? '&' : '?') + params;
1228
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1229
+ params += '&_=';
1230
+ }
1231
+
1232
+ try {
1233
+ var response = new Ajax.Response(this);
1234
+ if (this.options.onCreate) this.options.onCreate(response);
1235
+ Ajax.Responders.dispatch('onCreate', this, response);
1236
+
1237
+ this.transport.open(this.method.toUpperCase(), this.url,
1238
+ this.options.asynchronous);
1239
+
1240
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1241
+
1242
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
1243
+ this.setRequestHeaders();
1244
+
1245
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1246
+ this.transport.send(this.body);
1247
+
1248
+ /* Force Firefox to handle ready state 4 for synchronous requests */
1249
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
1250
+ this.onStateChange();
1251
+
1252
+ }
1253
+ catch (e) {
1254
+ this.dispatchException(e);
1255
+ }
1256
+ },
1257
+
1258
+ onStateChange: function() {
1259
+ var readyState = this.transport.readyState;
1260
+ if (readyState > 1 && !((readyState == 4) && this._complete))
1261
+ this.respondToReadyState(this.transport.readyState);
1262
+ },
1263
+
1264
+ setRequestHeaders: function() {
1265
+ var headers = {
1266
+ 'X-Requested-With': 'XMLHttpRequest',
1267
+ 'X-Prototype-Version': Prototype.Version,
1268
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1269
+ };
1270
+
1271
+ if (this.method == 'post') {
1272
+ headers['Content-type'] = this.options.contentType +
1273
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
1274
+
1275
+ /* Force "Connection: close" for older Mozilla browsers to work
1276
+ * around a bug where XMLHttpRequest sends an incorrect
1277
+ * Content-length header. See Mozilla Bugzilla #246651.
1278
+ */
1279
+ if (this.transport.overrideMimeType &&
1280
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1281
+ headers['Connection'] = 'close';
1282
+ }
1283
+
1284
+ // user-defined headers
1285
+ if (typeof this.options.requestHeaders == 'object') {
1286
+ var extras = this.options.requestHeaders;
1287
+
1288
+ if (Object.isFunction(extras.push))
1289
+ for (var i = 0, length = extras.length; i < length; i += 2)
1290
+ headers[extras[i]] = extras[i+1];
1291
+ else
1292
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1293
+ }
1294
+
1295
+ for (var name in headers)
1296
+ this.transport.setRequestHeader(name, headers[name]);
1297
+ },
1298
+
1299
+ success: function() {
1300
+ var status = this.getStatus();
1301
+ return !status || (status >= 200 && status < 300);
1302
+ },
1303
+
1304
+ getStatus: function() {
1305
+ try {
1306
+ return this.transport.status || 0;
1307
+ } catch (e) { return 0 }
1308
+ },
1309
+
1310
+ respondToReadyState: function(readyState) {
1311
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1312
+
1313
+ if (state == 'Complete') {
1314
+ try {
1315
+ this._complete = true;
1316
+ (this.options['on' + response.status]
1317
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1318
+ || Prototype.emptyFunction)(response, response.headerJSON);
1319
+ } catch (e) {
1320
+ this.dispatchException(e);
1321
+ }
1322
+
1323
+ var contentType = response.getHeader('Content-type');
1324
+ if (this.options.evalJS == 'force'
1325
+ || (this.options.evalJS && this.isSameOrigin() && contentType
1326
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1327
+ this.evalResponse();
1328
+ }
1329
+
1330
+ try {
1331
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1332
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1333
+ } catch (e) {
1334
+ this.dispatchException(e);
1335
+ }
1336
+
1337
+ if (state == 'Complete') {
1338
+ // avoid memory leak in MSIE: clean up
1339
+ this.transport.onreadystatechange = Prototype.emptyFunction;
1340
+ }
1341
+ },
1342
+
1343
+ isSameOrigin: function() {
1344
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1345
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1346
+ protocol: location.protocol,
1347
+ domain: document.domain,
1348
+ port: location.port ? ':' + location.port : ''
1349
+ }));
1350
+ },
1351
+
1352
+ getHeader: function(name) {
1353
+ try {
1354
+ return this.transport.getResponseHeader(name) || null;
1355
+ } catch (e) { return null }
1356
+ },
1357
+
1358
+ evalResponse: function() {
1359
+ try {
1360
+ return eval((this.transport.responseText || '').unfilterJSON());
1361
+ } catch (e) {
1362
+ this.dispatchException(e);
1363
+ }
1364
+ },
1365
+
1366
+ dispatchException: function(exception) {
1367
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
1368
+ Ajax.Responders.dispatch('onException', this, exception);
1369
+ }
1370
+ });
1371
+
1372
+ Ajax.Request.Events =
1373
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1374
+
1375
+ Ajax.Response = Class.create({
1376
+ initialize: function(request){
1377
+ this.request = request;
1378
+ var transport = this.transport = request.transport,
1379
+ readyState = this.readyState = transport.readyState;
1380
+
1381
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1382
+ this.status = this.getStatus();
1383
+ this.statusText = this.getStatusText();
1384
+ this.responseText = String.interpret(transport.responseText);
1385
+ this.headerJSON = this._getHeaderJSON();
1386
+ }
1387
+
1388
+ if(readyState == 4) {
1389
+ var xml = transport.responseXML;
1390
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
1391
+ this.responseJSON = this._getResponseJSON();
1392
+ }
1393
+ },
1394
+
1395
+ status: 0,
1396
+ statusText: '',
1397
+
1398
+ getStatus: Ajax.Request.prototype.getStatus,
1399
+
1400
+ getStatusText: function() {
1401
+ try {
1402
+ return this.transport.statusText || '';
1403
+ } catch (e) { return '' }
1404
+ },
1405
+
1406
+ getHeader: Ajax.Request.prototype.getHeader,
1407
+
1408
+ getAllHeaders: function() {
1409
+ try {
1410
+ return this.getAllResponseHeaders();
1411
+ } catch (e) { return null }
1412
+ },
1413
+
1414
+ getResponseHeader: function(name) {
1415
+ return this.transport.getResponseHeader(name);
1416
+ },
1417
+
1418
+ getAllResponseHeaders: function() {
1419
+ return this.transport.getAllResponseHeaders();
1420
+ },
1421
+
1422
+ _getHeaderJSON: function() {
1423
+ var json = this.getHeader('X-JSON');
1424
+ if (!json) return null;
1425
+ json = decodeURIComponent(escape(json));
1426
+ try {
1427
+ return json.evalJSON(this.request.options.sanitizeJSON ||
1428
+ !this.request.isSameOrigin());
1429
+ } catch (e) {
1430
+ this.request.dispatchException(e);
1431
+ }
1432
+ },
1433
+
1434
+ _getResponseJSON: function() {
1435
+ var options = this.request.options;
1436
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
1437
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
1438
+ this.responseText.blank())
1439
+ return null;
1440
+ try {
1441
+ return this.responseText.evalJSON(options.sanitizeJSON ||
1442
+ !this.request.isSameOrigin());
1443
+ } catch (e) {
1444
+ this.request.dispatchException(e);
1445
+ }
1446
+ }
1447
+ });
1448
+
1449
+ Ajax.Updater = Class.create(Ajax.Request, {
1450
+ initialize: function($super, container, url, options) {
1451
+ this.container = {
1452
+ success: (container.success || container),
1453
+ failure: (container.failure || (container.success ? null : container))
1454
+ };
1455
+
1456
+ options = Object.clone(options);
1457
+ var onComplete = options.onComplete;
1458
+ options.onComplete = (function(response, json) {
1459
+ this.updateContent(response.responseText);
1460
+ if (Object.isFunction(onComplete)) onComplete(response, json);
1461
+ }).bind(this);
1462
+
1463
+ $super(url, options);
1464
+ },
1465
+
1466
+ updateContent: function(responseText) {
1467
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
1468
+ options = this.options;
1469
+
1470
+ if (!options.evalScripts) responseText = responseText.stripScripts();
1471
+
1472
+ if (receiver = $(receiver)) {
1473
+ if (options.insertion) {
1474
+ if (Object.isString(options.insertion)) {
1475
+ var insertion = { }; insertion[options.insertion] = responseText;
1476
+ receiver.insert(insertion);
1477
+ }
1478
+ else options.insertion(receiver, responseText);
1479
+ }
1480
+ else receiver.update(responseText);
1481
+ }
1482
+ }
1483
+ });
1484
+
1485
+ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1486
+ initialize: function($super, container, url, options) {
1487
+ $super(options);
1488
+ this.onComplete = this.options.onComplete;
1489
+
1490
+ this.frequency = (this.options.frequency || 2);
1491
+ this.decay = (this.options.decay || 1);
1492
+
1493
+ this.updater = { };
1494
+ this.container = container;
1495
+ this.url = url;
1496
+
1497
+ this.start();
1498
+ },
1499
+
1500
+ start: function() {
1501
+ this.options.onComplete = this.updateComplete.bind(this);
1502
+ this.onTimerEvent();
1503
+ },
1504
+
1505
+ stop: function() {
1506
+ this.updater.options.onComplete = undefined;
1507
+ clearTimeout(this.timer);
1508
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1509
+ },
1510
+
1511
+ updateComplete: function(response) {
1512
+ if (this.options.decay) {
1513
+ this.decay = (response.responseText == this.lastText ?
1514
+ this.decay * this.options.decay : 1);
1515
+
1516
+ this.lastText = response.responseText;
1517
+ }
1518
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1519
+ },
1520
+
1521
+ onTimerEvent: function() {
1522
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
1523
+ }
1524
+ });
1525
+ function $(element) {
1526
+ if (arguments.length > 1) {
1527
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1528
+ elements.push($(arguments[i]));
1529
+ return elements;
1530
+ }
1531
+ if (Object.isString(element))
1532
+ element = document.getElementById(element);
1533
+ return Element.extend(element);
1534
+ }
1535
+
1536
+ if (Prototype.BrowserFeatures.XPath) {
1537
+ document._getElementsByXPath = function(expression, parentElement) {
1538
+ var results = [];
1539
+ var query = document.evaluate(expression, $(parentElement) || document,
1540
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1541
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
1542
+ results.push(Element.extend(query.snapshotItem(i)));
1543
+ return results;
1544
+ };
1545
+ }
1546
+
1547
+ /*--------------------------------------------------------------------------*/
1548
+
1549
+ if (!window.Node) var Node = { };
1550
+
1551
+ if (!Node.ELEMENT_NODE) {
1552
+ // DOM level 2 ECMAScript Language Binding
1553
+ Object.extend(Node, {
1554
+ ELEMENT_NODE: 1,
1555
+ ATTRIBUTE_NODE: 2,
1556
+ TEXT_NODE: 3,
1557
+ CDATA_SECTION_NODE: 4,
1558
+ ENTITY_REFERENCE_NODE: 5,
1559
+ ENTITY_NODE: 6,
1560
+ PROCESSING_INSTRUCTION_NODE: 7,
1561
+ COMMENT_NODE: 8,
1562
+ DOCUMENT_NODE: 9,
1563
+ DOCUMENT_TYPE_NODE: 10,
1564
+ DOCUMENT_FRAGMENT_NODE: 11,
1565
+ NOTATION_NODE: 12
1566
+ });
1567
+ }
1568
+
1569
+ (function() {
1570
+ var element = this.Element;
1571
+ this.Element = function(tagName, attributes) {
1572
+ attributes = attributes || { };
1573
+ tagName = tagName.toLowerCase();
1574
+ var cache = Element.cache;
1575
+ if (Prototype.Browser.IE && attributes.name) {
1576
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
1577
+ delete attributes.name;
1578
+ return Element.writeAttribute(document.createElement(tagName), attributes);
1579
+ }
1580
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1581
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
1582
+ };
1583
+ Object.extend(this.Element, element || { });
1584
+ if (element) this.Element.prototype = element.prototype;
1585
+ }).call(window);
1586
+
1587
+ Element.cache = { };
1588
+
1589
+ Element.Methods = {
1590
+ visible: function(element) {
1591
+ return $(element).style.display != 'none';
1592
+ },
1593
+
1594
+ toggle: function(element) {
1595
+ element = $(element);
1596
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
1597
+ return element;
1598
+ },
1599
+
1600
+ hide: function(element) {
1601
+ element = $(element);
1602
+ element.style.display = 'none';
1603
+ return element;
1604
+ },
1605
+
1606
+ show: function(element) {
1607
+ element = $(element);
1608
+ element.style.display = '';
1609
+ return element;
1610
+ },
1611
+
1612
+ remove: function(element) {
1613
+ element = $(element);
1614
+ element.parentNode.removeChild(element);
1615
+ return element;
1616
+ },
1617
+
1618
+ update: function(element, content) {
1619
+ element = $(element);
1620
+ if (content && content.toElement) content = content.toElement();
1621
+ if (Object.isElement(content)) return element.update().insert(content);
1622
+ content = Object.toHTML(content);
1623
+ element.innerHTML = content.stripScripts();
1624
+ content.evalScripts.bind(content).defer();
1625
+ return element;
1626
+ },
1627
+
1628
+ replace: function(element, content) {
1629
+ element = $(element);
1630
+ if (content && content.toElement) content = content.toElement();
1631
+ else if (!Object.isElement(content)) {
1632
+ content = Object.toHTML(content);
1633
+ var range = element.ownerDocument.createRange();
1634
+ range.selectNode(element);
1635
+ content.evalScripts.bind(content).defer();
1636
+ content = range.createContextualFragment(content.stripScripts());
1637
+ }
1638
+ element.parentNode.replaceChild(content, element);
1639
+ return element;
1640
+ },
1641
+
1642
+ insert: function(element, insertions) {
1643
+ element = $(element);
1644
+
1645
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
1646
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
1647
+ insertions = {bottom:insertions};
1648
+
1649
+ var content, insert, tagName, childNodes;
1650
+
1651
+ for (var position in insertions) {
1652
+ content = insertions[position];
1653
+ position = position.toLowerCase();
1654
+ insert = Element._insertionTranslations[position];
1655
+
1656
+ if (content && content.toElement) content = content.toElement();
1657
+ if (Object.isElement(content)) {
1658
+ insert(element, content);
1659
+ continue;
1660
+ }
1661
+
1662
+ content = Object.toHTML(content);
1663
+
1664
+ tagName = ((position == 'before' || position == 'after')
1665
+ ? element.parentNode : element).tagName.toUpperCase();
1666
+
1667
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
1668
+
1669
+ if (position == 'top' || position == 'after') childNodes.reverse();
1670
+ childNodes.each(insert.curry(element));
1671
+
1672
+ content.evalScripts.bind(content).defer();
1673
+ }
1674
+
1675
+ return element;
1676
+ },
1677
+
1678
+ wrap: function(element, wrapper, attributes) {
1679
+ element = $(element);
1680
+ if (Object.isElement(wrapper))
1681
+ $(wrapper).writeAttribute(attributes || { });
1682
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
1683
+ else wrapper = new Element('div', wrapper);
1684
+ if (element.parentNode)
1685
+ element.parentNode.replaceChild(wrapper, element);
1686
+ wrapper.appendChild(element);
1687
+ return wrapper;
1688
+ },
1689
+
1690
+ inspect: function(element) {
1691
+ element = $(element);
1692
+ var result = '<' + element.tagName.toLowerCase();
1693
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1694
+ var property = pair.first(), attribute = pair.last();
1695
+ var value = (element[property] || '').toString();
1696
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
1697
+ });
1698
+ return result + '>';
1699
+ },
1700
+
1701
+ recursivelyCollect: function(element, property) {
1702
+ element = $(element);
1703
+ var elements = [];
1704
+ while (element = element[property])
1705
+ if (element.nodeType == 1)
1706
+ elements.push(Element.extend(element));
1707
+ return elements;
1708
+ },
1709
+
1710
+ ancestors: function(element) {
1711
+ return $(element).recursivelyCollect('parentNode');
1712
+ },
1713
+
1714
+ descendants: function(element) {
1715
+ return $(element).select("*");
1716
+ },
1717
+
1718
+ firstDescendant: function(element) {
1719
+ element = $(element).firstChild;
1720
+ while (element && element.nodeType != 1) element = element.nextSibling;
1721
+ return $(element);
1722
+ },
1723
+
1724
+ immediateDescendants: function(element) {
1725
+ if (!(element = $(element).firstChild)) return [];
1726
+ while (element && element.nodeType != 1) element = element.nextSibling;
1727
+ if (element) return [element].concat($(element).nextSiblings());
1728
+ return [];
1729
+ },
1730
+
1731
+ previousSiblings: function(element) {
1732
+ return $(element).recursivelyCollect('previousSibling');
1733
+ },
1734
+
1735
+ nextSiblings: function(element) {
1736
+ return $(element).recursivelyCollect('nextSibling');
1737
+ },
1738
+
1739
+ siblings: function(element) {
1740
+ element = $(element);
1741
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
1742
+ },
1743
+
1744
+ match: function(element, selector) {
1745
+ if (Object.isString(selector))
1746
+ selector = new Selector(selector);
1747
+ return selector.match($(element));
1748
+ },
1749
+
1750
+ up: function(element, expression, index) {
1751
+ element = $(element);
1752
+ if (arguments.length == 1) return $(element.parentNode);
1753
+ var ancestors = element.ancestors();
1754
+ return Object.isNumber(expression) ? ancestors[expression] :
1755
+ Selector.findElement(ancestors, expression, index);
1756
+ },
1757
+
1758
+ down: function(element, expression, index) {
1759
+ element = $(element);
1760
+ if (arguments.length == 1) return element.firstDescendant();
1761
+ return Object.isNumber(expression) ? element.descendants()[expression] :
1762
+ Element.select(element, expression)[index || 0];
1763
+ },
1764
+
1765
+ previous: function(element, expression, index) {
1766
+ element = $(element);
1767
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1768
+ var previousSiblings = element.previousSiblings();
1769
+ return Object.isNumber(expression) ? previousSiblings[expression] :
1770
+ Selector.findElement(previousSiblings, expression, index);
1771
+ },
1772
+
1773
+ next: function(element, expression, index) {
1774
+ element = $(element);
1775
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1776
+ var nextSiblings = element.nextSiblings();
1777
+ return Object.isNumber(expression) ? nextSiblings[expression] :
1778
+ Selector.findElement(nextSiblings, expression, index);
1779
+ },
1780
+
1781
+ select: function() {
1782
+ var args = $A(arguments), element = $(args.shift());
1783
+ return Selector.findChildElements(element, args);
1784
+ },
1785
+
1786
+ adjacent: function() {
1787
+ var args = $A(arguments), element = $(args.shift());
1788
+ return Selector.findChildElements(element.parentNode, args).without(element);
1789
+ },
1790
+
1791
+ identify: function(element) {
1792
+ element = $(element);
1793
+ var id = element.readAttribute('id'), self = arguments.callee;
1794
+ if (id) return id;
1795
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
1796
+ element.writeAttribute('id', id);
1797
+ return id;
1798
+ },
1799
+
1800
+ readAttribute: function(element, name) {
1801
+ element = $(element);
1802
+ if (Prototype.Browser.IE) {
1803
+ var t = Element._attributeTranslations.read;
1804
+ if (t.values[name]) return t.values[name](element, name);
1805
+ if (t.names[name]) name = t.names[name];
1806
+ if (name.include(':')) {
1807
+ return (!element.attributes || !element.attributes[name]) ? null :
1808
+ element.attributes[name].value;
1809
+ }
1810
+ }
1811
+ return element.getAttribute(name);
1812
+ },
1813
+
1814
+ writeAttribute: function(element, name, value) {
1815
+ element = $(element);
1816
+ var attributes = { }, t = Element._attributeTranslations.write;
1817
+
1818
+ if (typeof name == 'object') attributes = name;
1819
+ else attributes[name] = Object.isUndefined(value) ? true : value;
1820
+
1821
+ for (var attr in attributes) {
1822
+ name = t.names[attr] || attr;
1823
+ value = attributes[attr];
1824
+ if (t.values[attr]) name = t.values[attr](element, value);
1825
+ if (value === false || value === null)
1826
+ element.removeAttribute(name);
1827
+ else if (value === true)
1828
+ element.setAttribute(name, name);
1829
+ else element.setAttribute(name, value);
1830
+ }
1831
+ return element;
1832
+ },
1833
+
1834
+ getHeight: function(element) {
1835
+ return $(element).getDimensions().height;
1836
+ },
1837
+
1838
+ getWidth: function(element) {
1839
+ return $(element).getDimensions().width;
1840
+ },
1841
+
1842
+ classNames: function(element) {
1843
+ return new Element.ClassNames(element);
1844
+ },
1845
+
1846
+ hasClassName: function(element, className) {
1847
+ if (!(element = $(element))) return;
1848
+ var elementClassName = element.className;
1849
+ return (elementClassName.length > 0 && (elementClassName == className ||
1850
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
1851
+ },
1852
+
1853
+ addClassName: function(element, className) {
1854
+ if (!(element = $(element))) return;
1855
+ if (!element.hasClassName(className))
1856
+ element.className += (element.className ? ' ' : '') + className;
1857
+ return element;
1858
+ },
1859
+
1860
+ removeClassName: function(element, className) {
1861
+ if (!(element = $(element))) return;
1862
+ element.className = element.className.replace(
1863
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
1864
+ return element;
1865
+ },
1866
+
1867
+ toggleClassName: function(element, className) {
1868
+ if (!(element = $(element))) return;
1869
+ return element[element.hasClassName(className) ?
1870
+ 'removeClassName' : 'addClassName'](className);
1871
+ },
1872
+
1873
+ // removes whitespace-only text node children
1874
+ cleanWhitespace: function(element) {
1875
+ element = $(element);
1876
+ var node = element.firstChild;
1877
+ while (node) {
1878
+ var nextNode = node.nextSibling;
1879
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1880
+ element.removeChild(node);
1881
+ node = nextNode;
1882
+ }
1883
+ return element;
1884
+ },
1885
+
1886
+ empty: function(element) {
1887
+ return $(element).innerHTML.blank();
1888
+ },
1889
+
1890
+ descendantOf: function(element, ancestor) {
1891
+ element = $(element), ancestor = $(ancestor);
1892
+
1893
+ if (element.compareDocumentPosition)
1894
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
1895
+
1896
+ if (ancestor.contains)
1897
+ return ancestor.contains(element) && ancestor !== element;
1898
+
1899
+ while (element = element.parentNode)
1900
+ if (element == ancestor) return true;
1901
+
1902
+ return false;
1903
+ },
1904
+
1905
+ scrollTo: function(element) {
1906
+ element = $(element);
1907
+ var pos = element.cumulativeOffset();
1908
+ window.scrollTo(pos[0], pos[1]);
1909
+ return element;
1910
+ },
1911
+
1912
+ getStyle: function(element, style) {
1913
+ element = $(element);
1914
+ style = style == 'float' ? 'cssFloat' : style.camelize();
1915
+ var value = element.style[style];
1916
+ if (!value || value == 'auto') {
1917
+ var css = document.defaultView.getComputedStyle(element, null);
1918
+ value = css ? css[style] : null;
1919
+ }
1920
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1921
+ return value == 'auto' ? null : value;
1922
+ },
1923
+
1924
+ getOpacity: function(element) {
1925
+ return $(element).getStyle('opacity');
1926
+ },
1927
+
1928
+ setStyle: function(element, styles) {
1929
+ element = $(element);
1930
+ var elementStyle = element.style, match;
1931
+ if (Object.isString(styles)) {
1932
+ element.style.cssText += ';' + styles;
1933
+ return styles.include('opacity') ?
1934
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
1935
+ }
1936
+ for (var property in styles)
1937
+ if (property == 'opacity') element.setOpacity(styles[property]);
1938
+ else
1939
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
1940
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
1941
+ property] = styles[property];
1942
+
1943
+ return element;
1944
+ },
1945
+
1946
+ setOpacity: function(element, value) {
1947
+ element = $(element);
1948
+ element.style.opacity = (value == 1 || value === '') ? '' :
1949
+ (value < 0.00001) ? 0 : value;
1950
+ return element;
1951
+ },
1952
+
1953
+ getDimensions: function(element) {
1954
+ element = $(element);
1955
+ var display = element.getStyle('display');
1956
+ if (display != 'none' && display != null) // Safari bug
1957
+ return {width: element.offsetWidth, height: element.offsetHeight};
1958
+
1959
+ // All *Width and *Height properties give 0 on elements with display none,
1960
+ // so enable the element temporarily
1961
+ var els = element.style;
1962
+ var originalVisibility = els.visibility;
1963
+ var originalPosition = els.position;
1964
+ var originalDisplay = els.display;
1965
+ els.visibility = 'hidden';
1966
+ els.position = 'absolute';
1967
+ els.display = 'block';
1968
+ var originalWidth = element.clientWidth;
1969
+ var originalHeight = element.clientHeight;
1970
+ els.display = originalDisplay;
1971
+ els.position = originalPosition;
1972
+ els.visibility = originalVisibility;
1973
+ return {width: originalWidth, height: originalHeight};
1974
+ },
1975
+
1976
+ makePositioned: function(element) {
1977
+ element = $(element);
1978
+ var pos = Element.getStyle(element, 'position');
1979
+ if (pos == 'static' || !pos) {
1980
+ element._madePositioned = true;
1981
+ element.style.position = 'relative';
1982
+ // Opera returns the offset relative to the positioning context, when an
1983
+ // element is position relative but top and left have not been defined
1984
+ if (Prototype.Browser.Opera) {
1985
+ element.style.top = 0;
1986
+ element.style.left = 0;
1987
+ }
1988
+ }
1989
+ return element;
1990
+ },
1991
+
1992
+ undoPositioned: function(element) {
1993
+ element = $(element);
1994
+ if (element._madePositioned) {
1995
+ element._madePositioned = undefined;
1996
+ element.style.position =
1997
+ element.style.top =
1998
+ element.style.left =
1999
+ element.style.bottom =
2000
+ element.style.right = '';
2001
+ }
2002
+ return element;
2003
+ },
2004
+
2005
+ makeClipping: function(element) {
2006
+ element = $(element);
2007
+ if (element._overflow) return element;
2008
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
2009
+ if (element._overflow !== 'hidden')
2010
+ element.style.overflow = 'hidden';
2011
+ return element;
2012
+ },
2013
+
2014
+ undoClipping: function(element) {
2015
+ element = $(element);
2016
+ if (!element._overflow) return element;
2017
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
2018
+ element._overflow = null;
2019
+ return element;
2020
+ },
2021
+
2022
+ cumulativeOffset: function(element) {
2023
+ var valueT = 0, valueL = 0;
2024
+ do {
2025
+ valueT += element.offsetTop || 0;
2026
+ valueL += element.offsetLeft || 0;
2027
+ element = element.offsetParent;
2028
+ } while (element);
2029
+ return Element._returnOffset(valueL, valueT);
2030
+ },
2031
+
2032
+ positionedOffset: function(element) {
2033
+ var valueT = 0, valueL = 0;
2034
+ do {
2035
+ valueT += element.offsetTop || 0;
2036
+ valueL += element.offsetLeft || 0;
2037
+ element = element.offsetParent;
2038
+ if (element) {
2039
+ if (element.tagName.toUpperCase() == 'BODY') break;
2040
+ var p = Element.getStyle(element, 'position');
2041
+ if (p !== 'static') break;
2042
+ }
2043
+ } while (element);
2044
+ return Element._returnOffset(valueL, valueT);
2045
+ },
2046
+
2047
+ absolutize: function(element) {
2048
+ element = $(element);
2049
+ if (element.getStyle('position') == 'absolute') return element;
2050
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
2051
+
2052
+ var offsets = element.positionedOffset();
2053
+ var top = offsets[1];
2054
+ var left = offsets[0];
2055
+ var width = element.clientWidth;
2056
+ var height = element.clientHeight;
2057
+
2058
+ element._originalLeft = left - parseFloat(element.style.left || 0);
2059
+ element._originalTop = top - parseFloat(element.style.top || 0);
2060
+ element._originalWidth = element.style.width;
2061
+ element._originalHeight = element.style.height;
2062
+
2063
+ element.style.position = 'absolute';
2064
+ element.style.top = top + 'px';
2065
+ element.style.left = left + 'px';
2066
+ element.style.width = width + 'px';
2067
+ element.style.height = height + 'px';
2068
+ return element;
2069
+ },
2070
+
2071
+ relativize: function(element) {
2072
+ element = $(element);
2073
+ if (element.getStyle('position') == 'relative') return element;
2074
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
2075
+
2076
+ element.style.position = 'relative';
2077
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
2078
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
2079
+
2080
+ element.style.top = top + 'px';
2081
+ element.style.left = left + 'px';
2082
+ element.style.height = element._originalHeight;
2083
+ element.style.width = element._originalWidth;
2084
+ return element;
2085
+ },
2086
+
2087
+ cumulativeScrollOffset: function(element) {
2088
+ var valueT = 0, valueL = 0;
2089
+ do {
2090
+ valueT += element.scrollTop || 0;
2091
+ valueL += element.scrollLeft || 0;
2092
+ element = element.parentNode;
2093
+ } while (element);
2094
+ return Element._returnOffset(valueL, valueT);
2095
+ },
2096
+
2097
+ getOffsetParent: function(element) {
2098
+ if (element.offsetParent) return $(element.offsetParent);
2099
+ if (element == document.body) return $(element);
2100
+
2101
+ while ((element = element.parentNode) && element != document.body)
2102
+ if (Element.getStyle(element, 'position') != 'static')
2103
+ return $(element);
2104
+
2105
+ return $(document.body);
2106
+ },
2107
+
2108
+ viewportOffset: function(forElement) {
2109
+ var valueT = 0, valueL = 0;
2110
+
2111
+ var element = forElement;
2112
+ do {
2113
+ valueT += element.offsetTop || 0;
2114
+ valueL += element.offsetLeft || 0;
2115
+
2116
+ // Safari fix
2117
+ if (element.offsetParent == document.body &&
2118
+ Element.getStyle(element, 'position') == 'absolute') break;
2119
+
2120
+ } while (element = element.offsetParent);
2121
+
2122
+ element = forElement;
2123
+ do {
2124
+ if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
2125
+ valueT -= element.scrollTop || 0;
2126
+ valueL -= element.scrollLeft || 0;
2127
+ }
2128
+ } while (element = element.parentNode);
2129
+
2130
+ return Element._returnOffset(valueL, valueT);
2131
+ },
2132
+
2133
+ clonePosition: function(element, source) {
2134
+ var options = Object.extend({
2135
+ setLeft: true,
2136
+ setTop: true,
2137
+ setWidth: true,
2138
+ setHeight: true,
2139
+ offsetTop: 0,
2140
+ offsetLeft: 0
2141
+ }, arguments[2] || { });
2142
+
2143
+ // find page position of source
2144
+ source = $(source);
2145
+ var p = source.viewportOffset();
2146
+
2147
+ // find coordinate system to use
2148
+ element = $(element);
2149
+ var delta = [0, 0];
2150
+ var parent = null;
2151
+ // delta [0,0] will do fine with position: fixed elements,
2152
+ // position:absolute needs offsetParent deltas
2153
+ if (Element.getStyle(element, 'position') == 'absolute') {
2154
+ parent = element.getOffsetParent();
2155
+ delta = parent.viewportOffset();
2156
+ }
2157
+
2158
+ // correct by body offsets (fixes Safari)
2159
+ if (parent == document.body) {
2160
+ delta[0] -= document.body.offsetLeft;
2161
+ delta[1] -= document.body.offsetTop;
2162
+ }
2163
+
2164
+ // set position
2165
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
2166
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
2167
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
2168
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
2169
+ return element;
2170
+ }
2171
+ };
2172
+
2173
+ Element.Methods.identify.counter = 1;
2174
+
2175
+ Object.extend(Element.Methods, {
2176
+ getElementsBySelector: Element.Methods.select,
2177
+ childElements: Element.Methods.immediateDescendants
2178
+ });
2179
+
2180
+ Element._attributeTranslations = {
2181
+ write: {
2182
+ names: {
2183
+ className: 'class',
2184
+ htmlFor: 'for'
2185
+ },
2186
+ values: { }
2187
+ }
2188
+ };
2189
+
2190
+ if (Prototype.Browser.Opera) {
2191
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2192
+ function(proceed, element, style) {
2193
+ switch (style) {
2194
+ case 'left': case 'top': case 'right': case 'bottom':
2195
+ if (proceed(element, 'position') === 'static') return null;
2196
+ case 'height': case 'width':
2197
+ // returns '0px' for hidden elements; we want it to return null
2198
+ if (!Element.visible(element)) return null;
2199
+
2200
+ // returns the border-box dimensions rather than the content-box
2201
+ // dimensions, so we subtract padding and borders from the value
2202
+ var dim = parseInt(proceed(element, style), 10);
2203
+
2204
+ if (dim !== element['offset' + style.capitalize()])
2205
+ return dim + 'px';
2206
+
2207
+ var properties;
2208
+ if (style === 'height') {
2209
+ properties = ['border-top-width', 'padding-top',
2210
+ 'padding-bottom', 'border-bottom-width'];
2211
+ }
2212
+ else {
2213
+ properties = ['border-left-width', 'padding-left',
2214
+ 'padding-right', 'border-right-width'];
2215
+ }
2216
+ return properties.inject(dim, function(memo, property) {
2217
+ var val = proceed(element, property);
2218
+ return val === null ? memo : memo - parseInt(val, 10);
2219
+ }) + 'px';
2220
+ default: return proceed(element, style);
2221
+ }
2222
+ }
2223
+ );
2224
+
2225
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2226
+ function(proceed, element, attribute) {
2227
+ if (attribute === 'title') return element.title;
2228
+ return proceed(element, attribute);
2229
+ }
2230
+ );
2231
+ }
2232
+
2233
+ else if (Prototype.Browser.IE) {
2234
+ // IE doesn't report offsets correctly for static elements, so we change them
2235
+ // to "relative" to get the values, then change them back.
2236
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
2237
+ function(proceed, element) {
2238
+ element = $(element);
2239
+ // IE throws an error if element is not in document
2240
+ try { element.offsetParent }
2241
+ catch(e) { return $(document.body) }
2242
+ var position = element.getStyle('position');
2243
+ if (position !== 'static') return proceed(element);
2244
+ element.setStyle({ position: 'relative' });
2245
+ var value = proceed(element);
2246
+ element.setStyle({ position: position });
2247
+ return value;
2248
+ }
2249
+ );
2250
+
2251
+ $w('positionedOffset viewportOffset').each(function(method) {
2252
+ Element.Methods[method] = Element.Methods[method].wrap(
2253
+ function(proceed, element) {
2254
+ element = $(element);
2255
+ try { element.offsetParent }
2256
+ catch(e) { return Element._returnOffset(0,0) }
2257
+ var position = element.getStyle('position');
2258
+ if (position !== 'static') return proceed(element);
2259
+ // Trigger hasLayout on the offset parent so that IE6 reports
2260
+ // accurate offsetTop and offsetLeft values for position: fixed.
2261
+ var offsetParent = element.getOffsetParent();
2262
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
2263
+ offsetParent.setStyle({ zoom: 1 });
2264
+ element.setStyle({ position: 'relative' });
2265
+ var value = proceed(element);
2266
+ element.setStyle({ position: position });
2267
+ return value;
2268
+ }
2269
+ );
2270
+ });
2271
+
2272
+ Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
2273
+ function(proceed, element) {
2274
+ try { element.offsetParent }
2275
+ catch(e) { return Element._returnOffset(0,0) }
2276
+ return proceed(element);
2277
+ }
2278
+ );
2279
+
2280
+ Element.Methods.getStyle = function(element, style) {
2281
+ element = $(element);
2282
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
2283
+ var value = element.style[style];
2284
+ if (!value && element.currentStyle) value = element.currentStyle[style];
2285
+
2286
+ if (style == 'opacity') {
2287
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
2288
+ if (value[1]) return parseFloat(value[1]) / 100;
2289
+ return 1.0;
2290
+ }
2291
+
2292
+ if (value == 'auto') {
2293
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
2294
+ return element['offset' + style.capitalize()] + 'px';
2295
+ return null;
2296
+ }
2297
+ return value;
2298
+ };
2299
+
2300
+ Element.Methods.setOpacity = function(element, value) {
2301
+ function stripAlpha(filter){
2302
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
2303
+ }
2304
+ element = $(element);
2305
+ var currentStyle = element.currentStyle;
2306
+ if ((currentStyle && !currentStyle.hasLayout) ||
2307
+ (!currentStyle && element.style.zoom == 'normal'))
2308
+ element.style.zoom = 1;
2309
+
2310
+ var filter = element.getStyle('filter'), style = element.style;
2311
+ if (value == 1 || value === '') {
2312
+ (filter = stripAlpha(filter)) ?
2313
+ style.filter = filter : style.removeAttribute('filter');
2314
+ return element;
2315
+ } else if (value < 0.00001) value = 0;
2316
+ style.filter = stripAlpha(filter) +
2317
+ 'alpha(opacity=' + (value * 100) + ')';
2318
+ return element;
2319
+ };
2320
+
2321
+ Element._attributeTranslations = {
2322
+ read: {
2323
+ names: {
2324
+ 'class': 'className',
2325
+ 'for': 'htmlFor'
2326
+ },
2327
+ values: {
2328
+ _getAttr: function(element, attribute) {
2329
+ return element.getAttribute(attribute, 2);
2330
+ },
2331
+ _getAttrNode: function(element, attribute) {
2332
+ var node = element.getAttributeNode(attribute);
2333
+ return node ? node.value : "";
2334
+ },
2335
+ _getEv: function(element, attribute) {
2336
+ attribute = element.getAttribute(attribute);
2337
+ return attribute ? attribute.toString().slice(23, -2) : null;
2338
+ },
2339
+ _flag: function(element, attribute) {
2340
+ return $(element).hasAttribute(attribute) ? attribute : null;
2341
+ },
2342
+ style: function(element) {
2343
+ return element.style.cssText.toLowerCase();
2344
+ },
2345
+ title: function(element) {
2346
+ return element.title;
2347
+ }
2348
+ }
2349
+ }
2350
+ };
2351
+
2352
+ Element._attributeTranslations.write = {
2353
+ names: Object.extend({
2354
+ cellpadding: 'cellPadding',
2355
+ cellspacing: 'cellSpacing'
2356
+ }, Element._attributeTranslations.read.names),
2357
+ values: {
2358
+ checked: function(element, value) {
2359
+ element.checked = !!value;
2360
+ },
2361
+
2362
+ style: function(element, value) {
2363
+ element.style.cssText = value ? value : '';
2364
+ }
2365
+ }
2366
+ };
2367
+
2368
+ Element._attributeTranslations.has = {};
2369
+
2370
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
2371
+ 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
2372
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
2373
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
2374
+ });
2375
+
2376
+ (function(v) {
2377
+ Object.extend(v, {
2378
+ href: v._getAttr,
2379
+ src: v._getAttr,
2380
+ type: v._getAttr,
2381
+ action: v._getAttrNode,
2382
+ disabled: v._flag,
2383
+ checked: v._flag,
2384
+ readonly: v._flag,
2385
+ multiple: v._flag,
2386
+ onload: v._getEv,
2387
+ onunload: v._getEv,
2388
+ onclick: v._getEv,
2389
+ ondblclick: v._getEv,
2390
+ onmousedown: v._getEv,
2391
+ onmouseup: v._getEv,
2392
+ onmouseover: v._getEv,
2393
+ onmousemove: v._getEv,
2394
+ onmouseout: v._getEv,
2395
+ onfocus: v._getEv,
2396
+ onblur: v._getEv,
2397
+ onkeypress: v._getEv,
2398
+ onkeydown: v._getEv,
2399
+ onkeyup: v._getEv,
2400
+ onsubmit: v._getEv,
2401
+ onreset: v._getEv,
2402
+ onselect: v._getEv,
2403
+ onchange: v._getEv
2404
+ });
2405
+ })(Element._attributeTranslations.read.values);
2406
+ }
2407
+
2408
+ else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
2409
+ Element.Methods.setOpacity = function(element, value) {
2410
+ element = $(element);
2411
+ element.style.opacity = (value == 1) ? 0.999999 :
2412
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
2413
+ return element;
2414
+ };
2415
+ }
2416
+
2417
+ else if (Prototype.Browser.WebKit) {
2418
+ Element.Methods.setOpacity = function(element, value) {
2419
+ element = $(element);
2420
+ element.style.opacity = (value == 1 || value === '') ? '' :
2421
+ (value < 0.00001) ? 0 : value;
2422
+
2423
+ if (value == 1)
2424
+ if(element.tagName.toUpperCase() == 'IMG' && element.width) {
2425
+ element.width++; element.width--;
2426
+ } else try {
2427
+ var n = document.createTextNode(' ');
2428
+ element.appendChild(n);
2429
+ element.removeChild(n);
2430
+ } catch (e) { }
2431
+
2432
+ return element;
2433
+ };
2434
+
2435
+ // Safari returns margins on body which is incorrect if the child is absolutely
2436
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
2437
+ // KHTML/WebKit only.
2438
+ Element.Methods.cumulativeOffset = function(element) {
2439
+ var valueT = 0, valueL = 0;
2440
+ do {
2441
+ valueT += element.offsetTop || 0;
2442
+ valueL += element.offsetLeft || 0;
2443
+ if (element.offsetParent == document.body)
2444
+ if (Element.getStyle(element, 'position') == 'absolute') break;
2445
+
2446
+ element = element.offsetParent;
2447
+ } while (element);
2448
+
2449
+ return Element._returnOffset(valueL, valueT);
2450
+ };
2451
+ }
2452
+
2453
+ if (Prototype.Browser.IE || Prototype.Browser.Opera) {
2454
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
2455
+ Element.Methods.update = function(element, content) {
2456
+ element = $(element);
2457
+
2458
+ if (content && content.toElement) content = content.toElement();
2459
+ if (Object.isElement(content)) return element.update().insert(content);
2460
+
2461
+ content = Object.toHTML(content);
2462
+ var tagName = element.tagName.toUpperCase();
2463
+
2464
+ if (tagName in Element._insertionTranslations.tags) {
2465
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
2466
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
2467
+ .each(function(node) { element.appendChild(node) });
2468
+ }
2469
+ else element.innerHTML = content.stripScripts();
2470
+
2471
+ content.evalScripts.bind(content).defer();
2472
+ return element;
2473
+ };
2474
+ }
2475
+
2476
+ if ('outerHTML' in document.createElement('div')) {
2477
+ Element.Methods.replace = function(element, content) {
2478
+ element = $(element);
2479
+
2480
+ if (content && content.toElement) content = content.toElement();
2481
+ if (Object.isElement(content)) {
2482
+ element.parentNode.replaceChild(content, element);
2483
+ return element;
2484
+ }
2485
+
2486
+ content = Object.toHTML(content);
2487
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2488
+
2489
+ if (Element._insertionTranslations.tags[tagName]) {
2490
+ var nextSibling = element.next();
2491
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2492
+ parent.removeChild(element);
2493
+ if (nextSibling)
2494
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
2495
+ else
2496
+ fragments.each(function(node) { parent.appendChild(node) });
2497
+ }
2498
+ else element.outerHTML = content.stripScripts();
2499
+
2500
+ content.evalScripts.bind(content).defer();
2501
+ return element;
2502
+ };
2503
+ }
2504
+
2505
+ Element._returnOffset = function(l, t) {
2506
+ var result = [l, t];
2507
+ result.left = l;
2508
+ result.top = t;
2509
+ return result;
2510
+ };
2511
+
2512
+ Element._getContentFromAnonymousElement = function(tagName, html) {
2513
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
2514
+ if (t) {
2515
+ div.innerHTML = t[0] + html + t[1];
2516
+ t[2].times(function() { div = div.firstChild });
2517
+ } else div.innerHTML = html;
2518
+ return $A(div.childNodes);
2519
+ };
2520
+
2521
+ Element._insertionTranslations = {
2522
+ before: function(element, node) {
2523
+ element.parentNode.insertBefore(node, element);
2524
+ },
2525
+ top: function(element, node) {
2526
+ element.insertBefore(node, element.firstChild);
2527
+ },
2528
+ bottom: function(element, node) {
2529
+ element.appendChild(node);
2530
+ },
2531
+ after: function(element, node) {
2532
+ element.parentNode.insertBefore(node, element.nextSibling);
2533
+ },
2534
+ tags: {
2535
+ TABLE: ['<table>', '</table>', 1],
2536
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
2537
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2538
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2539
+ SELECT: ['<select>', '</select>', 1]
2540
+ }
2541
+ };
2542
+
2543
+ (function() {
2544
+ Object.extend(this.tags, {
2545
+ THEAD: this.tags.TBODY,
2546
+ TFOOT: this.tags.TBODY,
2547
+ TH: this.tags.TD
2548
+ });
2549
+ }).call(Element._insertionTranslations);
2550
+
2551
+ Element.Methods.Simulated = {
2552
+ hasAttribute: function(element, attribute) {
2553
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
2554
+ var node = $(element).getAttributeNode(attribute);
2555
+ return !!(node && node.specified);
2556
+ }
2557
+ };
2558
+
2559
+ Element.Methods.ByTag = { };
2560
+
2561
+ Object.extend(Element, Element.Methods);
2562
+
2563
+ if (!Prototype.BrowserFeatures.ElementExtensions &&
2564
+ document.createElement('div')['__proto__']) {
2565
+ window.HTMLElement = { };
2566
+ window.HTMLElement.prototype = document.createElement('div')['__proto__'];
2567
+ Prototype.BrowserFeatures.ElementExtensions = true;
2568
+ }
2569
+
2570
+ Element.extend = (function() {
2571
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
2572
+ return Prototype.K;
2573
+
2574
+ var Methods = { }, ByTag = Element.Methods.ByTag;
2575
+
2576
+ var extend = Object.extend(function(element) {
2577
+ if (!element || element._extendedByPrototype ||
2578
+ element.nodeType != 1 || element == window) return element;
2579
+
2580
+ var methods = Object.clone(Methods),
2581
+ tagName = element.tagName.toUpperCase(), property, value;
2582
+
2583
+ // extend methods for specific tags
2584
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2585
+
2586
+ for (property in methods) {
2587
+ value = methods[property];
2588
+ if (Object.isFunction(value) && !(property in element))
2589
+ element[property] = value.methodize();
2590
+ }
2591
+
2592
+ element._extendedByPrototype = Prototype.emptyFunction;
2593
+ return element;
2594
+
2595
+ }, {
2596
+ refresh: function() {
2597
+ // extend methods for all tags (Safari doesn't need this)
2598
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
2599
+ Object.extend(Methods, Element.Methods);
2600
+ Object.extend(Methods, Element.Methods.Simulated);
2601
+ }
2602
+ }
2603
+ });
2604
+
2605
+ extend.refresh();
2606
+ return extend;
2607
+ })();
2608
+
2609
+ Element.hasAttribute = function(element, attribute) {
2610
+ if (element.hasAttribute) return element.hasAttribute(attribute);
2611
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
2612
+ };
2613
+
2614
+ Element.addMethods = function(methods) {
2615
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
2616
+
2617
+ if (!methods) {
2618
+ Object.extend(Form, Form.Methods);
2619
+ Object.extend(Form.Element, Form.Element.Methods);
2620
+ Object.extend(Element.Methods.ByTag, {
2621
+ "FORM": Object.clone(Form.Methods),
2622
+ "INPUT": Object.clone(Form.Element.Methods),
2623
+ "SELECT": Object.clone(Form.Element.Methods),
2624
+ "TEXTAREA": Object.clone(Form.Element.Methods)
2625
+ });
2626
+ }
2627
+
2628
+ if (arguments.length == 2) {
2629
+ var tagName = methods;
2630
+ methods = arguments[1];
2631
+ }
2632
+
2633
+ if (!tagName) Object.extend(Element.Methods, methods || { });
2634
+ else {
2635
+ if (Object.isArray(tagName)) tagName.each(extend);
2636
+ else extend(tagName);
2637
+ }
2638
+
2639
+ function extend(tagName) {
2640
+ tagName = tagName.toUpperCase();
2641
+ if (!Element.Methods.ByTag[tagName])
2642
+ Element.Methods.ByTag[tagName] = { };
2643
+ Object.extend(Element.Methods.ByTag[tagName], methods);
2644
+ }
2645
+
2646
+ function copy(methods, destination, onlyIfAbsent) {
2647
+ onlyIfAbsent = onlyIfAbsent || false;
2648
+ for (var property in methods) {
2649
+ var value = methods[property];
2650
+ if (!Object.isFunction(value)) continue;
2651
+ if (!onlyIfAbsent || !(property in destination))
2652
+ destination[property] = value.methodize();
2653
+ }
2654
+ }
2655
+
2656
+ function findDOMClass(tagName) {
2657
+ var klass;
2658
+ var trans = {
2659
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
2660
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
2661
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
2662
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
2663
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
2664
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
2665
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
2666
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
2667
+ "FrameSet", "IFRAME": "IFrame"
2668
+ };
2669
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
2670
+ if (window[klass]) return window[klass];
2671
+ klass = 'HTML' + tagName + 'Element';
2672
+ if (window[klass]) return window[klass];
2673
+ klass = 'HTML' + tagName.capitalize() + 'Element';
2674
+ if (window[klass]) return window[klass];
2675
+
2676
+ window[klass] = { };
2677
+ window[klass].prototype = document.createElement(tagName)['__proto__'];
2678
+ return window[klass];
2679
+ }
2680
+
2681
+ if (F.ElementExtensions) {
2682
+ copy(Element.Methods, HTMLElement.prototype);
2683
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
2684
+ }
2685
+
2686
+ if (F.SpecificElementExtensions) {
2687
+ for (var tag in Element.Methods.ByTag) {
2688
+ var klass = findDOMClass(tag);
2689
+ if (Object.isUndefined(klass)) continue;
2690
+ copy(T[tag], klass.prototype);
2691
+ }
2692
+ }
2693
+
2694
+ Object.extend(Element, Element.Methods);
2695
+ delete Element.ByTag;
2696
+
2697
+ if (Element.extend.refresh) Element.extend.refresh();
2698
+ Element.cache = { };
2699
+ };
2700
+
2701
+ document.viewport = {
2702
+ getDimensions: function() {
2703
+ var dimensions = { }, B = Prototype.Browser;
2704
+ $w('width height').each(function(d) {
2705
+ var D = d.capitalize();
2706
+ if (B.WebKit && !document.evaluate) {
2707
+ // Safari <3.0 needs self.innerWidth/Height
2708
+ dimensions[d] = self['inner' + D];
2709
+ } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
2710
+ // Opera <9.5 needs document.body.clientWidth/Height
2711
+ dimensions[d] = document.body['client' + D]
2712
+ } else {
2713
+ dimensions[d] = document.documentElement['client' + D];
2714
+ }
2715
+ });
2716
+ return dimensions;
2717
+ },
2718
+
2719
+ getWidth: function() {
2720
+ return this.getDimensions().width;
2721
+ },
2722
+
2723
+ getHeight: function() {
2724
+ return this.getDimensions().height;
2725
+ },
2726
+
2727
+ getScrollOffsets: function() {
2728
+ return Element._returnOffset(
2729
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
2730
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
2731
+ }
2732
+ };
2733
+ /* Portions of the Selector class are derived from Jack Slocum's DomQuery,
2734
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
2735
+ * license. Please see http://www.yui-ext.com/ for more information. */
2736
+
2737
+ var Selector = Class.create({
2738
+ initialize: function(expression) {
2739
+ this.expression = expression.strip();
2740
+
2741
+ if (this.shouldUseSelectorsAPI()) {
2742
+ this.mode = 'selectorsAPI';
2743
+ } else if (this.shouldUseXPath()) {
2744
+ this.mode = 'xpath';
2745
+ this.compileXPathMatcher();
2746
+ } else {
2747
+ this.mode = "normal";
2748
+ this.compileMatcher();
2749
+ }
2750
+
2751
+ },
2752
+
2753
+ shouldUseXPath: function() {
2754
+ if (!Prototype.BrowserFeatures.XPath) return false;
2755
+
2756
+ var e = this.expression;
2757
+
2758
+ // Safari 3 chokes on :*-of-type and :empty
2759
+ if (Prototype.Browser.WebKit &&
2760
+ (e.include("-of-type") || e.include(":empty")))
2761
+ return false;
2762
+
2763
+ // XPath can't do namespaced attributes, nor can it read
2764
+ // the "checked" property from DOM nodes
2765
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
2766
+ return false;
2767
+
2768
+ return true;
2769
+ },
2770
+
2771
+ shouldUseSelectorsAPI: function() {
2772
+ if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
2773
+
2774
+ if (!Selector._div) Selector._div = new Element('div');
2775
+
2776
+ // Make sure the browser treats the selector as valid. Test on an
2777
+ // isolated element to minimize cost of this check.
2778
+ try {
2779
+ Selector._div.querySelector(this.expression);
2780
+ } catch(e) {
2781
+ return false;
2782
+ }
2783
+
2784
+ return true;
2785
+ },
2786
+
2787
+ compileMatcher: function() {
2788
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
2789
+ c = Selector.criteria, le, p, m;
2790
+
2791
+ if (Selector._cache[e]) {
2792
+ this.matcher = Selector._cache[e];
2793
+ return;
2794
+ }
2795
+
2796
+ this.matcher = ["this.matcher = function(root) {",
2797
+ "var r = root, h = Selector.handlers, c = false, n;"];
2798
+
2799
+ while (e && le != e && (/\S/).test(e)) {
2800
+ le = e;
2801
+ for (var i in ps) {
2802
+ p = ps[i];
2803
+ if (m = e.match(p)) {
2804
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
2805
+ new Template(c[i]).evaluate(m));
2806
+ e = e.replace(m[0], '');
2807
+ break;
2808
+ }
2809
+ }
2810
+ }
2811
+
2812
+ this.matcher.push("return h.unique(n);\n}");
2813
+ eval(this.matcher.join('\n'));
2814
+ Selector._cache[this.expression] = this.matcher;
2815
+ },
2816
+
2817
+ compileXPathMatcher: function() {
2818
+ var e = this.expression, ps = Selector.patterns,
2819
+ x = Selector.xpath, le, m;
2820
+
2821
+ if (Selector._cache[e]) {
2822
+ this.xpath = Selector._cache[e]; return;
2823
+ }
2824
+
2825
+ this.matcher = ['.//*'];
2826
+ while (e && le != e && (/\S/).test(e)) {
2827
+ le = e;
2828
+ for (var i in ps) {
2829
+ if (m = e.match(ps[i])) {
2830
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
2831
+ new Template(x[i]).evaluate(m));
2832
+ e = e.replace(m[0], '');
2833
+ break;
2834
+ }
2835
+ }
2836
+ }
2837
+
2838
+ this.xpath = this.matcher.join('');
2839
+ Selector._cache[this.expression] = this.xpath;
2840
+ },
2841
+
2842
+ findElements: function(root) {
2843
+ root = root || document;
2844
+ var e = this.expression, results;
2845
+
2846
+ switch (this.mode) {
2847
+ case 'selectorsAPI':
2848
+ // querySelectorAll queries document-wide, then filters to descendants
2849
+ // of the context element. That's not what we want.
2850
+ // Add an explicit context to the selector if necessary.
2851
+ if (root !== document) {
2852
+ var oldId = root.id, id = $(root).identify();
2853
+ e = "#" + id + " " + e;
2854
+ }
2855
+
2856
+ results = $A(root.querySelectorAll(e)).map(Element.extend);
2857
+ root.id = oldId;
2858
+
2859
+ return results;
2860
+ case 'xpath':
2861
+ return document._getElementsByXPath(this.xpath, root);
2862
+ default:
2863
+ return this.matcher(root);
2864
+ }
2865
+ },
2866
+
2867
+ match: function(element) {
2868
+ this.tokens = [];
2869
+
2870
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
2871
+ var le, p, m;
2872
+
2873
+ while (e && le !== e && (/\S/).test(e)) {
2874
+ le = e;
2875
+ for (var i in ps) {
2876
+ p = ps[i];
2877
+ if (m = e.match(p)) {
2878
+ // use the Selector.assertions methods unless the selector
2879
+ // is too complex.
2880
+ if (as[i]) {
2881
+ this.tokens.push([i, Object.clone(m)]);
2882
+ e = e.replace(m[0], '');
2883
+ } else {
2884
+ // reluctantly do a document-wide search
2885
+ // and look for a match in the array
2886
+ return this.findElements(document).include(element);
2887
+ }
2888
+ }
2889
+ }
2890
+ }
2891
+
2892
+ var match = true, name, matches;
2893
+ for (var i = 0, token; token = this.tokens[i]; i++) {
2894
+ name = token[0], matches = token[1];
2895
+ if (!Selector.assertions[name](element, matches)) {
2896
+ match = false; break;
2897
+ }
2898
+ }
2899
+
2900
+ return match;
2901
+ },
2902
+
2903
+ toString: function() {
2904
+ return this.expression;
2905
+ },
2906
+
2907
+ inspect: function() {
2908
+ return "#<Selector:" + this.expression.inspect() + ">";
2909
+ }
2910
+ });
2911
+
2912
+ Object.extend(Selector, {
2913
+ _cache: { },
2914
+
2915
+ xpath: {
2916
+ descendant: "//*",
2917
+ child: "/*",
2918
+ adjacent: "/following-sibling::*[1]",
2919
+ laterSibling: '/following-sibling::*',
2920
+ tagName: function(m) {
2921
+ if (m[1] == '*') return '';
2922
+ return "[local-name()='" + m[1].toLowerCase() +
2923
+ "' or local-name()='" + m[1].toUpperCase() + "']";
2924
+ },
2925
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2926
+ id: "[@id='#{1}']",
2927
+ attrPresence: function(m) {
2928
+ m[1] = m[1].toLowerCase();
2929
+ return new Template("[@#{1}]").evaluate(m);
2930
+ },
2931
+ attr: function(m) {
2932
+ m[1] = m[1].toLowerCase();
2933
+ m[3] = m[5] || m[6];
2934
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2935
+ },
2936
+ pseudo: function(m) {
2937
+ var h = Selector.xpath.pseudos[m[1]];
2938
+ if (!h) return '';
2939
+ if (Object.isFunction(h)) return h(m);
2940
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
2941
+ },
2942
+ operators: {
2943
+ '=': "[@#{1}='#{3}']",
2944
+ '!=': "[@#{1}!='#{3}']",
2945
+ '^=': "[starts-with(@#{1}, '#{3}')]",
2946
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
2947
+ '*=': "[contains(@#{1}, '#{3}')]",
2948
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
2949
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
2950
+ },
2951
+ pseudos: {
2952
+ 'first-child': '[not(preceding-sibling::*)]',
2953
+ 'last-child': '[not(following-sibling::*)]',
2954
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
2955
+ 'empty': "[count(*) = 0 and (count(text()) = 0)]",
2956
+ 'checked': "[@checked]",
2957
+ 'disabled': "[(@disabled) and (@type!='hidden')]",
2958
+ 'enabled': "[not(@disabled) and (@type!='hidden')]",
2959
+ 'not': function(m) {
2960
+ var e = m[6], p = Selector.patterns,
2961
+ x = Selector.xpath, le, v;
2962
+
2963
+ var exclusion = [];
2964
+ while (e && le != e && (/\S/).test(e)) {
2965
+ le = e;
2966
+ for (var i in p) {
2967
+ if (m = e.match(p[i])) {
2968
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
2969
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2970
+ e = e.replace(m[0], '');
2971
+ break;
2972
+ }
2973
+ }
2974
+ }
2975
+ return "[not(" + exclusion.join(" and ") + ")]";
2976
+ },
2977
+ 'nth-child': function(m) {
2978
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
2979
+ },
2980
+ 'nth-last-child': function(m) {
2981
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
2982
+ },
2983
+ 'nth-of-type': function(m) {
2984
+ return Selector.xpath.pseudos.nth("position() ", m);
2985
+ },
2986
+ 'nth-last-of-type': function(m) {
2987
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
2988
+ },
2989
+ 'first-of-type': function(m) {
2990
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
2991
+ },
2992
+ 'last-of-type': function(m) {
2993
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
2994
+ },
2995
+ 'only-of-type': function(m) {
2996
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
2997
+ },
2998
+ nth: function(fragment, m) {
2999
+ var mm, formula = m[6], predicate;
3000
+ if (formula == 'even') formula = '2n+0';
3001
+ if (formula == 'odd') formula = '2n+1';
3002
+ if (mm = formula.match(/^(\d+)$/)) // digit only
3003
+ return '[' + fragment + "= " + mm[1] + ']';
3004
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
3005
+ if (mm[1] == "-") mm[1] = -1;
3006
+ var a = mm[1] ? Number(mm[1]) : 1;
3007
+ var b = mm[2] ? Number(mm[2]) : 0;
3008
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
3009
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
3010
+ return new Template(predicate).evaluate({
3011
+ fragment: fragment, a: a, b: b });
3012
+ }
3013
+ }
3014
+ }
3015
+ },
3016
+
3017
+ criteria: {
3018
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
3019
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
3020
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
3021
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
3022
+ attr: function(m) {
3023
+ m[3] = (m[5] || m[6]);
3024
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
3025
+ },
3026
+ pseudo: function(m) {
3027
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
3028
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
3029
+ },
3030
+ descendant: 'c = "descendant";',
3031
+ child: 'c = "child";',
3032
+ adjacent: 'c = "adjacent";',
3033
+ laterSibling: 'c = "laterSibling";'
3034
+ },
3035
+
3036
+ patterns: {
3037
+ // combinators must be listed first
3038
+ // (and descendant needs to be last combinator)
3039
+ laterSibling: /^\s*~\s*/,
3040
+ child: /^\s*>\s*/,
3041
+ adjacent: /^\s*\+\s*/,
3042
+ descendant: /^\s/,
3043
+
3044
+ // selectors follow
3045
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
3046
+ id: /^#([\w\-\*]+)(\b|$)/,
3047
+ className: /^\.([\w\-\*]+)(\b|$)/,
3048
+ pseudo:
3049
+ /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
3050
+ attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
3051
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
3052
+ },
3053
+
3054
+ // for Selector.match and Element#match
3055
+ assertions: {
3056
+ tagName: function(element, matches) {
3057
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
3058
+ },
3059
+
3060
+ className: function(element, matches) {
3061
+ return Element.hasClassName(element, matches[1]);
3062
+ },
3063
+
3064
+ id: function(element, matches) {
3065
+ return element.id === matches[1];
3066
+ },
3067
+
3068
+ attrPresence: function(element, matches) {
3069
+ return Element.hasAttribute(element, matches[1]);
3070
+ },
3071
+
3072
+ attr: function(element, matches) {
3073
+ var nodeValue = Element.readAttribute(element, matches[1]);
3074
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
3075
+ }
3076
+ },
3077
+
3078
+ handlers: {
3079
+ // UTILITY FUNCTIONS
3080
+ // joins two collections
3081
+ concat: function(a, b) {
3082
+ for (var i = 0, node; node = b[i]; i++)
3083
+ a.push(node);
3084
+ return a;
3085
+ },
3086
+
3087
+ // marks an array of nodes for counting
3088
+ mark: function(nodes) {
3089
+ var _true = Prototype.emptyFunction;
3090
+ for (var i = 0, node; node = nodes[i]; i++)
3091
+ node._countedByPrototype = _true;
3092
+ return nodes;
3093
+ },
3094
+
3095
+ unmark: function(nodes) {
3096
+ for (var i = 0, node; node = nodes[i]; i++)
3097
+ node._countedByPrototype = undefined;
3098
+ return nodes;
3099
+ },
3100
+
3101
+ // mark each child node with its position (for nth calls)
3102
+ // "ofType" flag indicates whether we're indexing for nth-of-type
3103
+ // rather than nth-child
3104
+ index: function(parentNode, reverse, ofType) {
3105
+ parentNode._countedByPrototype = Prototype.emptyFunction;
3106
+ if (reverse) {
3107
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
3108
+ var node = nodes[i];
3109
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3110
+ }
3111
+ } else {
3112
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
3113
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3114
+ }
3115
+ },
3116
+
3117
+ // filters out duplicates and extends all nodes
3118
+ unique: function(nodes) {
3119
+ if (nodes.length == 0) return nodes;
3120
+ var results = [], n;
3121
+ for (var i = 0, l = nodes.length; i < l; i++)
3122
+ if (!(n = nodes[i])._countedByPrototype) {
3123
+ n._countedByPrototype = Prototype.emptyFunction;
3124
+ results.push(Element.extend(n));
3125
+ }
3126
+ return Selector.handlers.unmark(results);
3127
+ },
3128
+
3129
+ // COMBINATOR FUNCTIONS
3130
+ descendant: function(nodes) {
3131
+ var h = Selector.handlers;
3132
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3133
+ h.concat(results, node.getElementsByTagName('*'));
3134
+ return results;
3135
+ },
3136
+
3137
+ child: function(nodes) {
3138
+ var h = Selector.handlers;
3139
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3140
+ for (var j = 0, child; child = node.childNodes[j]; j++)
3141
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
3142
+ }
3143
+ return results;
3144
+ },
3145
+
3146
+ adjacent: function(nodes) {
3147
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3148
+ var next = this.nextElementSibling(node);
3149
+ if (next) results.push(next);
3150
+ }
3151
+ return results;
3152
+ },
3153
+
3154
+ laterSibling: function(nodes) {
3155
+ var h = Selector.handlers;
3156
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3157
+ h.concat(results, Element.nextSiblings(node));
3158
+ return results;
3159
+ },
3160
+
3161
+ nextElementSibling: function(node) {
3162
+ while (node = node.nextSibling)
3163
+ if (node.nodeType == 1) return node;
3164
+ return null;
3165
+ },
3166
+
3167
+ previousElementSibling: function(node) {
3168
+ while (node = node.previousSibling)
3169
+ if (node.nodeType == 1) return node;
3170
+ return null;
3171
+ },
3172
+
3173
+ // TOKEN FUNCTIONS
3174
+ tagName: function(nodes, root, tagName, combinator) {
3175
+ var uTagName = tagName.toUpperCase();
3176
+ var results = [], h = Selector.handlers;
3177
+ if (nodes) {
3178
+ if (combinator) {
3179
+ // fastlane for ordinary descendant combinators
3180
+ if (combinator == "descendant") {
3181
+ for (var i = 0, node; node = nodes[i]; i++)
3182
+ h.concat(results, node.getElementsByTagName(tagName));
3183
+ return results;
3184
+ } else nodes = this[combinator](nodes);
3185
+ if (tagName == "*") return nodes;
3186
+ }
3187
+ for (var i = 0, node; node = nodes[i]; i++)
3188
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
3189
+ return results;
3190
+ } else return root.getElementsByTagName(tagName);
3191
+ },
3192
+
3193
+ id: function(nodes, root, id, combinator) {
3194
+ var targetNode = $(id), h = Selector.handlers;
3195
+ if (!targetNode) return [];
3196
+ if (!nodes && root == document) return [targetNode];
3197
+ if (nodes) {
3198
+ if (combinator) {
3199
+ if (combinator == 'child') {
3200
+ for (var i = 0, node; node = nodes[i]; i++)
3201
+ if (targetNode.parentNode == node) return [targetNode];
3202
+ } else if (combinator == 'descendant') {
3203
+ for (var i = 0, node; node = nodes[i]; i++)
3204
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
3205
+ } else if (combinator == 'adjacent') {
3206
+ for (var i = 0, node; node = nodes[i]; i++)
3207
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
3208
+ return [targetNode];
3209
+ } else nodes = h[combinator](nodes);
3210
+ }
3211
+ for (var i = 0, node; node = nodes[i]; i++)
3212
+ if (node == targetNode) return [targetNode];
3213
+ return [];
3214
+ }
3215
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
3216
+ },
3217
+
3218
+ className: function(nodes, root, className, combinator) {
3219
+ if (nodes && combinator) nodes = this[combinator](nodes);
3220
+ return Selector.handlers.byClassName(nodes, root, className);
3221
+ },
3222
+
3223
+ byClassName: function(nodes, root, className) {
3224
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
3225
+ var needle = ' ' + className + ' ';
3226
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
3227
+ nodeClassName = node.className;
3228
+ if (nodeClassName.length == 0) continue;
3229
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
3230
+ results.push(node);
3231
+ }
3232
+ return results;
3233
+ },
3234
+
3235
+ attrPresence: function(nodes, root, attr, combinator) {
3236
+ if (!nodes) nodes = root.getElementsByTagName("*");
3237
+ if (nodes && combinator) nodes = this[combinator](nodes);
3238
+ var results = [];
3239
+ for (var i = 0, node; node = nodes[i]; i++)
3240
+ if (Element.hasAttribute(node, attr)) results.push(node);
3241
+ return results;
3242
+ },
3243
+
3244
+ attr: function(nodes, root, attr, value, operator, combinator) {
3245
+ if (!nodes) nodes = root.getElementsByTagName("*");
3246
+ if (nodes && combinator) nodes = this[combinator](nodes);
3247
+ var handler = Selector.operators[operator], results = [];
3248
+ for (var i = 0, node; node = nodes[i]; i++) {
3249
+ var nodeValue = Element.readAttribute(node, attr);
3250
+ if (nodeValue === null) continue;
3251
+ if (handler(nodeValue, value)) results.push(node);
3252
+ }
3253
+ return results;
3254
+ },
3255
+
3256
+ pseudo: function(nodes, name, value, root, combinator) {
3257
+ if (nodes && combinator) nodes = this[combinator](nodes);
3258
+ if (!nodes) nodes = root.getElementsByTagName("*");
3259
+ return Selector.pseudos[name](nodes, value, root);
3260
+ }
3261
+ },
3262
+
3263
+ pseudos: {
3264
+ 'first-child': function(nodes, value, root) {
3265
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3266
+ if (Selector.handlers.previousElementSibling(node)) continue;
3267
+ results.push(node);
3268
+ }
3269
+ return results;
3270
+ },
3271
+ 'last-child': function(nodes, value, root) {
3272
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3273
+ if (Selector.handlers.nextElementSibling(node)) continue;
3274
+ results.push(node);
3275
+ }
3276
+ return results;
3277
+ },
3278
+ 'only-child': function(nodes, value, root) {
3279
+ var h = Selector.handlers;
3280
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3281
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
3282
+ results.push(node);
3283
+ return results;
3284
+ },
3285
+ 'nth-child': function(nodes, formula, root) {
3286
+ return Selector.pseudos.nth(nodes, formula, root);
3287
+ },
3288
+ 'nth-last-child': function(nodes, formula, root) {
3289
+ return Selector.pseudos.nth(nodes, formula, root, true);
3290
+ },
3291
+ 'nth-of-type': function(nodes, formula, root) {
3292
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
3293
+ },
3294
+ 'nth-last-of-type': function(nodes, formula, root) {
3295
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
3296
+ },
3297
+ 'first-of-type': function(nodes, formula, root) {
3298
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
3299
+ },
3300
+ 'last-of-type': function(nodes, formula, root) {
3301
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
3302
+ },
3303
+ 'only-of-type': function(nodes, formula, root) {
3304
+ var p = Selector.pseudos;
3305
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
3306
+ },
3307
+
3308
+ // handles the an+b logic
3309
+ getIndices: function(a, b, total) {
3310
+ if (a == 0) return b > 0 ? [b] : [];
3311
+ return $R(1, total).inject([], function(memo, i) {
3312
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
3313
+ return memo;
3314
+ });
3315
+ },
3316
+
3317
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
3318
+ nth: function(nodes, formula, root, reverse, ofType) {
3319
+ if (nodes.length == 0) return [];
3320
+ if (formula == 'even') formula = '2n+0';
3321
+ if (formula == 'odd') formula = '2n+1';
3322
+ var h = Selector.handlers, results = [], indexed = [], m;
3323
+ h.mark(nodes);
3324
+ for (var i = 0, node; node = nodes[i]; i++) {
3325
+ if (!node.parentNode._countedByPrototype) {
3326
+ h.index(node.parentNode, reverse, ofType);
3327
+ indexed.push(node.parentNode);
3328
+ }
3329
+ }
3330
+ if (formula.match(/^\d+$/)) { // just a number
3331
+ formula = Number(formula);
3332
+ for (var i = 0, node; node = nodes[i]; i++)
3333
+ if (node.nodeIndex == formula) results.push(node);
3334
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
3335
+ if (m[1] == "-") m[1] = -1;
3336
+ var a = m[1] ? Number(m[1]) : 1;
3337
+ var b = m[2] ? Number(m[2]) : 0;
3338
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
3339
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
3340
+ for (var j = 0; j < l; j++)
3341
+ if (node.nodeIndex == indices[j]) results.push(node);
3342
+ }
3343
+ }
3344
+ h.unmark(nodes);
3345
+ h.unmark(indexed);
3346
+ return results;
3347
+ },
3348
+
3349
+ 'empty': function(nodes, value, root) {
3350
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3351
+ // IE treats comments as element nodes
3352
+ if (node.tagName == '!' || node.firstChild) continue;
3353
+ results.push(node);
3354
+ }
3355
+ return results;
3356
+ },
3357
+
3358
+ 'not': function(nodes, selector, root) {
3359
+ var h = Selector.handlers, selectorType, m;
3360
+ var exclusions = new Selector(selector).findElements(root);
3361
+ h.mark(exclusions);
3362
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3363
+ if (!node._countedByPrototype) results.push(node);
3364
+ h.unmark(exclusions);
3365
+ return results;
3366
+ },
3367
+
3368
+ 'enabled': function(nodes, value, root) {
3369
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3370
+ if (!node.disabled && (!node.type || node.type !== 'hidden'))
3371
+ results.push(node);
3372
+ return results;
3373
+ },
3374
+
3375
+ 'disabled': function(nodes, value, root) {
3376
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3377
+ if (node.disabled) results.push(node);
3378
+ return results;
3379
+ },
3380
+
3381
+ 'checked': function(nodes, value, root) {
3382
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3383
+ if (node.checked) results.push(node);
3384
+ return results;
3385
+ }
3386
+ },
3387
+
3388
+ operators: {
3389
+ '=': function(nv, v) { return nv == v; },
3390
+ '!=': function(nv, v) { return nv != v; },
3391
+ '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
3392
+ '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
3393
+ '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
3394
+ '$=': function(nv, v) { return nv.endsWith(v); },
3395
+ '*=': function(nv, v) { return nv.include(v); },
3396
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
3397
+ '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
3398
+ '-').include('-' + (v || "").toUpperCase() + '-'); }
3399
+ },
3400
+
3401
+ split: function(expression) {
3402
+ var expressions = [];
3403
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
3404
+ expressions.push(m[1].strip());
3405
+ });
3406
+ return expressions;
3407
+ },
3408
+
3409
+ matchElements: function(elements, expression) {
3410
+ var matches = $$(expression), h = Selector.handlers;
3411
+ h.mark(matches);
3412
+ for (var i = 0, results = [], element; element = elements[i]; i++)
3413
+ if (element._countedByPrototype) results.push(element);
3414
+ h.unmark(matches);
3415
+ return results;
3416
+ },
3417
+
3418
+ findElement: function(elements, expression, index) {
3419
+ if (Object.isNumber(expression)) {
3420
+ index = expression; expression = false;
3421
+ }
3422
+ return Selector.matchElements(elements, expression || '*')[index || 0];
3423
+ },
3424
+
3425
+ findChildElements: function(element, expressions) {
3426
+ expressions = Selector.split(expressions.join(','));
3427
+ var results = [], h = Selector.handlers;
3428
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
3429
+ selector = new Selector(expressions[i].strip());
3430
+ h.concat(results, selector.findElements(element));
3431
+ }
3432
+ return (l > 1) ? h.unique(results) : results;
3433
+ }
3434
+ });
3435
+
3436
+ if (Prototype.Browser.IE) {
3437
+ Object.extend(Selector.handlers, {
3438
+ // IE returns comment nodes on getElementsByTagName("*").
3439
+ // Filter them out.
3440
+ concat: function(a, b) {
3441
+ for (var i = 0, node; node = b[i]; i++)
3442
+ if (node.tagName !== "!") a.push(node);
3443
+ return a;
3444
+ },
3445
+
3446
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
3447
+ unmark: function(nodes) {
3448
+ for (var i = 0, node; node = nodes[i]; i++)
3449
+ node.removeAttribute('_countedByPrototype');
3450
+ return nodes;
3451
+ }
3452
+ });
3453
+ }
3454
+
3455
+ function $$() {
3456
+ return Selector.findChildElements(document, $A(arguments));
3457
+ }
3458
+ var Form = {
3459
+ reset: function(form) {
3460
+ $(form).reset();
3461
+ return form;
3462
+ },
3463
+
3464
+ serializeElements: function(elements, options) {
3465
+ if (typeof options != 'object') options = { hash: !!options };
3466
+ else if (Object.isUndefined(options.hash)) options.hash = true;
3467
+ var key, value, submitted = false, submit = options.submit;
3468
+
3469
+ var data = elements.inject({ }, function(result, element) {
3470
+ if (!element.disabled && element.name) {
3471
+ key = element.name; value = $(element).getValue();
3472
+ if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
3473
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
3474
+ if (key in result) {
3475
+ // a key is already present; construct an array of values
3476
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
3477
+ result[key].push(value);
3478
+ }
3479
+ else result[key] = value;
3480
+ }
3481
+ }
3482
+ return result;
3483
+ });
3484
+
3485
+ return options.hash ? data : Object.toQueryString(data);
3486
+ }
3487
+ };
3488
+
3489
+ Form.Methods = {
3490
+ serialize: function(form, options) {
3491
+ return Form.serializeElements(Form.getElements(form), options);
3492
+ },
3493
+
3494
+ getElements: function(form) {
3495
+ return $A($(form).getElementsByTagName('*')).inject([],
3496
+ function(elements, child) {
3497
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
3498
+ elements.push(Element.extend(child));
3499
+ return elements;
3500
+ }
3501
+ );
3502
+ },
3503
+
3504
+ getInputs: function(form, typeName, name) {
3505
+ form = $(form);
3506
+ var inputs = form.getElementsByTagName('input');
3507
+
3508
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
3509
+
3510
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
3511
+ var input = inputs[i];
3512
+ if ((typeName && input.type != typeName) || (name && input.name != name))
3513
+ continue;
3514
+ matchingInputs.push(Element.extend(input));
3515
+ }
3516
+
3517
+ return matchingInputs;
3518
+ },
3519
+
3520
+ disable: function(form) {
3521
+ form = $(form);
3522
+ Form.getElements(form).invoke('disable');
3523
+ return form;
3524
+ },
3525
+
3526
+ enable: function(form) {
3527
+ form = $(form);
3528
+ Form.getElements(form).invoke('enable');
3529
+ return form;
3530
+ },
3531
+
3532
+ findFirstElement: function(form) {
3533
+ var elements = $(form).getElements().findAll(function(element) {
3534
+ return 'hidden' != element.type && !element.disabled;
3535
+ });
3536
+ var firstByIndex = elements.findAll(function(element) {
3537
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
3538
+ }).sortBy(function(element) { return element.tabIndex }).first();
3539
+
3540
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
3541
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
3542
+ });
3543
+ },
3544
+
3545
+ focusFirstElement: function(form) {
3546
+ form = $(form);
3547
+ form.findFirstElement().activate();
3548
+ return form;
3549
+ },
3550
+
3551
+ request: function(form, options) {
3552
+ form = $(form), options = Object.clone(options || { });
3553
+
3554
+ var params = options.parameters, action = form.readAttribute('action') || '';
3555
+ if (action.blank()) action = window.location.href;
3556
+ options.parameters = form.serialize(true);
3557
+
3558
+ if (params) {
3559
+ if (Object.isString(params)) params = params.toQueryParams();
3560
+ Object.extend(options.parameters, params);
3561
+ }
3562
+
3563
+ if (form.hasAttribute('method') && !options.method)
3564
+ options.method = form.method;
3565
+
3566
+ return new Ajax.Request(action, options);
3567
+ }
3568
+ };
3569
+
3570
+ /*--------------------------------------------------------------------------*/
3571
+
3572
+ Form.Element = {
3573
+ focus: function(element) {
3574
+ $(element).focus();
3575
+ return element;
3576
+ },
3577
+
3578
+ select: function(element) {
3579
+ $(element).select();
3580
+ return element;
3581
+ }
3582
+ };
3583
+
3584
+ Form.Element.Methods = {
3585
+ serialize: function(element) {
3586
+ element = $(element);
3587
+ if (!element.disabled && element.name) {
3588
+ var value = element.getValue();
3589
+ if (value != undefined) {
3590
+ var pair = { };
3591
+ pair[element.name] = value;
3592
+ return Object.toQueryString(pair);
3593
+ }
3594
+ }
3595
+ return '';
3596
+ },
3597
+
3598
+ getValue: function(element) {
3599
+ element = $(element);
3600
+ var method = element.tagName.toLowerCase();
3601
+ return Form.Element.Serializers[method](element);
3602
+ },
3603
+
3604
+ setValue: function(element, value) {
3605
+ element = $(element);
3606
+ var method = element.tagName.toLowerCase();
3607
+ Form.Element.Serializers[method](element, value);
3608
+ return element;
3609
+ },
3610
+
3611
+ clear: function(element) {
3612
+ $(element).value = '';
3613
+ return element;
3614
+ },
3615
+
3616
+ present: function(element) {
3617
+ return $(element).value != '';
3618
+ },
3619
+
3620
+ activate: function(element) {
3621
+ element = $(element);
3622
+ try {
3623
+ element.focus();
3624
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
3625
+ !['button', 'reset', 'submit'].include(element.type)))
3626
+ element.select();
3627
+ } catch (e) { }
3628
+ return element;
3629
+ },
3630
+
3631
+ disable: function(element) {
3632
+ element = $(element);
3633
+ element.disabled = true;
3634
+ return element;
3635
+ },
3636
+
3637
+ enable: function(element) {
3638
+ element = $(element);
3639
+ element.disabled = false;
3640
+ return element;
3641
+ }
3642
+ };
3643
+
3644
+ /*--------------------------------------------------------------------------*/
3645
+
3646
+ var Field = Form.Element;
3647
+ var $F = Form.Element.Methods.getValue;
3648
+
3649
+ /*--------------------------------------------------------------------------*/
3650
+
3651
+ Form.Element.Serializers = {
3652
+ input: function(element, value) {
3653
+ switch (element.type.toLowerCase()) {
3654
+ case 'checkbox':
3655
+ case 'radio':
3656
+ return Form.Element.Serializers.inputSelector(element, value);
3657
+ default:
3658
+ return Form.Element.Serializers.textarea(element, value);
3659
+ }
3660
+ },
3661
+
3662
+ inputSelector: function(element, value) {
3663
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
3664
+ else element.checked = !!value;
3665
+ },
3666
+
3667
+ textarea: function(element, value) {
3668
+ if (Object.isUndefined(value)) return element.value;
3669
+ else element.value = value;
3670
+ },
3671
+
3672
+ select: function(element, value) {
3673
+ if (Object.isUndefined(value))
3674
+ return this[element.type == 'select-one' ?
3675
+ 'selectOne' : 'selectMany'](element);
3676
+ else {
3677
+ var opt, currentValue, single = !Object.isArray(value);
3678
+ for (var i = 0, length = element.length; i < length; i++) {
3679
+ opt = element.options[i];
3680
+ currentValue = this.optionValue(opt);
3681
+ if (single) {
3682
+ if (currentValue == value) {
3683
+ opt.selected = true;
3684
+ return;
3685
+ }
3686
+ }
3687
+ else opt.selected = value.include(currentValue);
3688
+ }
3689
+ }
3690
+ },
3691
+
3692
+ selectOne: function(element) {
3693
+ var index = element.selectedIndex;
3694
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
3695
+ },
3696
+
3697
+ selectMany: function(element) {
3698
+ var values, length = element.length;
3699
+ if (!length) return null;
3700
+
3701
+ for (var i = 0, values = []; i < length; i++) {
3702
+ var opt = element.options[i];
3703
+ if (opt.selected) values.push(this.optionValue(opt));
3704
+ }
3705
+ return values;
3706
+ },
3707
+
3708
+ optionValue: function(opt) {
3709
+ // extend element because hasAttribute may not be native
3710
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
3711
+ }
3712
+ };
3713
+
3714
+ /*--------------------------------------------------------------------------*/
3715
+
3716
+ Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
3717
+ initialize: function($super, element, frequency, callback) {
3718
+ $super(callback, frequency);
3719
+ this.element = $(element);
3720
+ this.lastValue = this.getValue();
3721
+ },
3722
+
3723
+ execute: function() {
3724
+ var value = this.getValue();
3725
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
3726
+ this.lastValue != value : String(this.lastValue) != String(value)) {
3727
+ this.callback(this.element, value);
3728
+ this.lastValue = value;
3729
+ }
3730
+ }
3731
+ });
3732
+
3733
+ Form.Element.Observer = Class.create(Abstract.TimedObserver, {
3734
+ getValue: function() {
3735
+ return Form.Element.getValue(this.element);
3736
+ }
3737
+ });
3738
+
3739
+ Form.Observer = Class.create(Abstract.TimedObserver, {
3740
+ getValue: function() {
3741
+ return Form.serialize(this.element);
3742
+ }
3743
+ });
3744
+
3745
+ /*--------------------------------------------------------------------------*/
3746
+
3747
+ Abstract.EventObserver = Class.create({
3748
+ initialize: function(element, callback) {
3749
+ this.element = $(element);
3750
+ this.callback = callback;
3751
+
3752
+ this.lastValue = this.getValue();
3753
+ if (this.element.tagName.toLowerCase() == 'form')
3754
+ this.registerFormCallbacks();
3755
+ else
3756
+ this.registerCallback(this.element);
3757
+ },
3758
+
3759
+ onElementEvent: function() {
3760
+ var value = this.getValue();
3761
+ if (this.lastValue != value) {
3762
+ this.callback(this.element, value);
3763
+ this.lastValue = value;
3764
+ }
3765
+ },
3766
+
3767
+ registerFormCallbacks: function() {
3768
+ Form.getElements(this.element).each(this.registerCallback, this);
3769
+ },
3770
+
3771
+ registerCallback: function(element) {
3772
+ if (element.type) {
3773
+ switch (element.type.toLowerCase()) {
3774
+ case 'checkbox':
3775
+ case 'radio':
3776
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
3777
+ break;
3778
+ default:
3779
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
3780
+ break;
3781
+ }
3782
+ }
3783
+ }
3784
+ });
3785
+
3786
+ Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
3787
+ getValue: function() {
3788
+ return Form.Element.getValue(this.element);
3789
+ }
3790
+ });
3791
+
3792
+ Form.EventObserver = Class.create(Abstract.EventObserver, {
3793
+ getValue: function() {
3794
+ return Form.serialize(this.element);
3795
+ }
3796
+ });
3797
+ if (!window.Event) var Event = { };
3798
+
3799
+ Object.extend(Event, {
3800
+ KEY_BACKSPACE: 8,
3801
+ KEY_TAB: 9,
3802
+ KEY_RETURN: 13,
3803
+ KEY_ESC: 27,
3804
+ KEY_LEFT: 37,
3805
+ KEY_UP: 38,
3806
+ KEY_RIGHT: 39,
3807
+ KEY_DOWN: 40,
3808
+ KEY_DELETE: 46,
3809
+ KEY_HOME: 36,
3810
+ KEY_END: 35,
3811
+ KEY_PAGEUP: 33,
3812
+ KEY_PAGEDOWN: 34,
3813
+ KEY_INSERT: 45,
3814
+
3815
+ cache: { },
3816
+
3817
+ relatedTarget: function(event) {
3818
+ var element;
3819
+ switch(event.type) {
3820
+ case 'mouseover': element = event.fromElement; break;
3821
+ case 'mouseout': element = event.toElement; break;
3822
+ default: return null;
3823
+ }
3824
+ return Element.extend(element);
3825
+ }
3826
+ });
3827
+
3828
+ Event.Methods = (function() {
3829
+ var isButton;
3830
+
3831
+ if (Prototype.Browser.IE) {
3832
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
3833
+ isButton = function(event, code) {
3834
+ return event.button == buttonMap[code];
3835
+ };
3836
+
3837
+ } else if (Prototype.Browser.WebKit) {
3838
+ isButton = function(event, code) {
3839
+ switch (code) {
3840
+ case 0: return event.which == 1 && !event.metaKey;
3841
+ case 1: return event.which == 1 && event.metaKey;
3842
+ default: return false;
3843
+ }
3844
+ };
3845
+
3846
+ } else {
3847
+ isButton = function(event, code) {
3848
+ return event.which ? (event.which === code + 1) : (event.button === code);
3849
+ };
3850
+ }
3851
+
3852
+ return {
3853
+ isLeftClick: function(event) { return isButton(event, 0) },
3854
+ isMiddleClick: function(event) { return isButton(event, 1) },
3855
+ isRightClick: function(event) { return isButton(event, 2) },
3856
+
3857
+ element: function(event) {
3858
+ event = Event.extend(event);
3859
+
3860
+ var node = event.target,
3861
+ type = event.type,
3862
+ currentTarget = event.currentTarget;
3863
+
3864
+ if (currentTarget && currentTarget.tagName) {
3865
+ // Firefox screws up the "click" event when moving between radio buttons
3866
+ // via arrow keys. It also screws up the "load" and "error" events on images,
3867
+ // reporting the document as the target instead of the original image.
3868
+ if (type === 'load' || type === 'error' ||
3869
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
3870
+ && currentTarget.type === 'radio'))
3871
+ node = currentTarget;
3872
+ }
3873
+ if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
3874
+ return Element.extend(node);
3875
+ },
3876
+
3877
+ findElement: function(event, expression) {
3878
+ var element = Event.element(event);
3879
+ if (!expression) return element;
3880
+ var elements = [element].concat(element.ancestors());
3881
+ return Selector.findElement(elements, expression, 0);
3882
+ },
3883
+
3884
+ pointer: function(event) {
3885
+ var docElement = document.documentElement,
3886
+ body = document.body || { scrollLeft: 0, scrollTop: 0 };
3887
+ return {
3888
+ x: event.pageX || (event.clientX +
3889
+ (docElement.scrollLeft || body.scrollLeft) -
3890
+ (docElement.clientLeft || 0)),
3891
+ y: event.pageY || (event.clientY +
3892
+ (docElement.scrollTop || body.scrollTop) -
3893
+ (docElement.clientTop || 0))
3894
+ };
3895
+ },
3896
+
3897
+ pointerX: function(event) { return Event.pointer(event).x },
3898
+ pointerY: function(event) { return Event.pointer(event).y },
3899
+
3900
+ stop: function(event) {
3901
+ Event.extend(event);
3902
+ event.preventDefault();
3903
+ event.stopPropagation();
3904
+ event.stopped = true;
3905
+ }
3906
+ };
3907
+ })();
3908
+
3909
+ Event.extend = (function() {
3910
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
3911
+ m[name] = Event.Methods[name].methodize();
3912
+ return m;
3913
+ });
3914
+
3915
+ if (Prototype.Browser.IE) {
3916
+ Object.extend(methods, {
3917
+ stopPropagation: function() { this.cancelBubble = true },
3918
+ preventDefault: function() { this.returnValue = false },
3919
+ inspect: function() { return "[object Event]" }
3920
+ });
3921
+
3922
+ return function(event) {
3923
+ if (!event) return false;
3924
+ if (event._extendedByPrototype) return event;
3925
+
3926
+ event._extendedByPrototype = Prototype.emptyFunction;
3927
+ var pointer = Event.pointer(event);
3928
+ Object.extend(event, {
3929
+ target: event.srcElement,
3930
+ relatedTarget: Event.relatedTarget(event),
3931
+ pageX: pointer.x,
3932
+ pageY: pointer.y
3933
+ });
3934
+ return Object.extend(event, methods);
3935
+ };
3936
+
3937
+ } else {
3938
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
3939
+ Object.extend(Event.prototype, methods);
3940
+ return Prototype.K;
3941
+ }
3942
+ })();
3943
+
3944
+ Object.extend(Event, (function() {
3945
+ var cache = Event.cache;
3946
+
3947
+ function getEventID(element) {
3948
+ if (element._prototypeEventID) return element._prototypeEventID[0];
3949
+ arguments.callee.id = arguments.callee.id || 1;
3950
+ return element._prototypeEventID = [++arguments.callee.id];
3951
+ }
3952
+
3953
+ function getDOMEventName(eventName) {
3954
+ if (eventName && eventName.include(':')) return "dataavailable";
3955
+ return eventName;
3956
+ }
3957
+
3958
+ function getCacheForID(id) {
3959
+ return cache[id] = cache[id] || { };
3960
+ }
3961
+
3962
+ function getWrappersForEventName(id, eventName) {
3963
+ var c = getCacheForID(id);
3964
+ return c[eventName] = c[eventName] || [];
3965
+ }
3966
+
3967
+ function createWrapper(element, eventName, handler) {
3968
+ var id = getEventID(element);
3969
+ var c = getWrappersForEventName(id, eventName);
3970
+ if (c.pluck("handler").include(handler)) return false;
3971
+
3972
+ var wrapper = function(event) {
3973
+ if (!Event || !Event.extend ||
3974
+ (event.eventName && event.eventName != eventName))
3975
+ return false;
3976
+
3977
+ Event.extend(event);
3978
+ handler.call(element, event);
3979
+ };
3980
+
3981
+ wrapper.handler = handler;
3982
+ c.push(wrapper);
3983
+ return wrapper;
3984
+ }
3985
+
3986
+ function findWrapper(id, eventName, handler) {
3987
+ var c = getWrappersForEventName(id, eventName);
3988
+ return c.find(function(wrapper) { return wrapper.handler == handler });
3989
+ }
3990
+
3991
+ function destroyWrapper(id, eventName, handler) {
3992
+ var c = getCacheForID(id);
3993
+ if (!c[eventName]) return false;
3994
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
3995
+ }
3996
+
3997
+ function destroyCache() {
3998
+ for (var id in cache)
3999
+ for (var eventName in cache[id])
4000
+ cache[id][eventName] = null;
4001
+ }
4002
+
4003
+
4004
+ // Internet Explorer needs to remove event handlers on page unload
4005
+ // in order to avoid memory leaks.
4006
+ if (window.attachEvent) {
4007
+ window.attachEvent("onunload", destroyCache);
4008
+ }
4009
+
4010
+ // Safari has a dummy event handler on page unload so that it won't
4011
+ // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
4012
+ // object when page is returned to via the back button using its bfcache.
4013
+ if (Prototype.Browser.WebKit) {
4014
+ window.addEventListener('unload', Prototype.emptyFunction, false);
4015
+ }
4016
+
4017
+ return {
4018
+ observe: function(element, eventName, handler) {
4019
+ element = $(element);
4020
+ var name = getDOMEventName(eventName);
4021
+
4022
+ var wrapper = createWrapper(element, eventName, handler);
4023
+ if (!wrapper) return element;
4024
+
4025
+ if (element.addEventListener) {
4026
+ element.addEventListener(name, wrapper, false);
4027
+ } else {
4028
+ element.attachEvent("on" + name, wrapper);
4029
+ }
4030
+
4031
+ return element;
4032
+ },
4033
+
4034
+ stopObserving: function(element, eventName, handler) {
4035
+ element = $(element);
4036
+ var id = getEventID(element), name = getDOMEventName(eventName);
4037
+
4038
+ if (!handler && eventName) {
4039
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
4040
+ element.stopObserving(eventName, wrapper.handler);
4041
+ });
4042
+ return element;
4043
+
4044
+ } else if (!eventName) {
4045
+ Object.keys(getCacheForID(id)).each(function(eventName) {
4046
+ element.stopObserving(eventName);
4047
+ });
4048
+ return element;
4049
+ }
4050
+
4051
+ var wrapper = findWrapper(id, eventName, handler);
4052
+ if (!wrapper) return element;
4053
+
4054
+ if (element.removeEventListener) {
4055
+ element.removeEventListener(name, wrapper, false);
4056
+ } else {
4057
+ element.detachEvent("on" + name, wrapper);
4058
+ }
4059
+
4060
+ destroyWrapper(id, eventName, handler);
4061
+
4062
+ return element;
4063
+ },
4064
+
4065
+ fire: function(element, eventName, memo) {
4066
+ element = $(element);
4067
+ if (element == document && document.createEvent && !element.dispatchEvent)
4068
+ element = document.documentElement;
4069
+
4070
+ var event;
4071
+ if (document.createEvent) {
4072
+ event = document.createEvent("HTMLEvents");
4073
+ event.initEvent("dataavailable", true, true);
4074
+ } else {
4075
+ event = document.createEventObject();
4076
+ event.eventType = "ondataavailable";
4077
+ }
4078
+
4079
+ event.eventName = eventName;
4080
+ event.memo = memo || { };
4081
+
4082
+ if (document.createEvent) {
4083
+ element.dispatchEvent(event);
4084
+ } else {
4085
+ element.fireEvent(event.eventType, event);
4086
+ }
4087
+
4088
+ return Event.extend(event);
4089
+ }
4090
+ };
4091
+ })());
4092
+
4093
+ Object.extend(Event, Event.Methods);
4094
+
4095
+ Element.addMethods({
4096
+ fire: Event.fire,
4097
+ observe: Event.observe,
4098
+ stopObserving: Event.stopObserving
4099
+ });
4100
+
4101
+ Object.extend(document, {
4102
+ fire: Element.Methods.fire.methodize(),
4103
+ observe: Element.Methods.observe.methodize(),
4104
+ stopObserving: Element.Methods.stopObserving.methodize(),
4105
+ loaded: false
4106
+ });
4107
+
4108
+ (function() {
4109
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
4110
+ Matthias Miller, Dean Edwards and John Resig. */
4111
+
4112
+ var timer;
4113
+
4114
+ function fireContentLoadedEvent() {
4115
+ if (document.loaded) return;
4116
+ if (timer) window.clearInterval(timer);
4117
+ document.fire("dom:loaded");
4118
+ document.loaded = true;
4119
+ }
4120
+
4121
+ if (document.addEventListener) {
4122
+ if (Prototype.Browser.WebKit) {
4123
+ timer = window.setInterval(function() {
4124
+ if (/loaded|complete/.test(document.readyState))
4125
+ fireContentLoadedEvent();
4126
+ }, 0);
4127
+
4128
+ Event.observe(window, "load", fireContentLoadedEvent);
4129
+
4130
+ } else {
4131
+ document.addEventListener("DOMContentLoaded",
4132
+ fireContentLoadedEvent, false);
4133
+ }
4134
+
4135
+ } else {
4136
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
4137
+ $("__onDOMContentLoaded").onreadystatechange = function() {
4138
+ if (this.readyState == "complete") {
4139
+ this.onreadystatechange = null;
4140
+ fireContentLoadedEvent();
4141
+ }
4142
+ };
4143
+ }
4144
+ })();
4145
+ /*------------------------------- DEPRECATED -------------------------------*/
4146
+
4147
+ Hash.toQueryString = Object.toQueryString;
4148
+
4149
+ var Toggle = { display: Element.toggle };
4150
+
4151
+ Element.Methods.childOf = Element.Methods.descendantOf;
4152
+
4153
+ var Insertion = {
4154
+ Before: function(element, content) {
4155
+ return Element.insert(element, {before:content});
4156
+ },
4157
+
4158
+ Top: function(element, content) {
4159
+ return Element.insert(element, {top:content});
4160
+ },
4161
+
4162
+ Bottom: function(element, content) {
4163
+ return Element.insert(element, {bottom:content});
4164
+ },
4165
+
4166
+ After: function(element, content) {
4167
+ return Element.insert(element, {after:content});
4168
+ }
4169
+ };
4170
+
4171
+ var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
4172
+
4173
+ // This should be moved to script.aculo.us; notice the deprecated methods
4174
+ // further below, that map to the newer Element methods.
4175
+ var Position = {
4176
+ // set to true if needed, warning: firefox performance problems
4177
+ // NOT neeeded for page scrolling, only if draggable contained in
4178
+ // scrollable elements
4179
+ includeScrollOffsets: false,
4180
+
4181
+ // must be called before calling withinIncludingScrolloffset, every time the
4182
+ // page is scrolled
4183
+ prepare: function() {
4184
+ this.deltaX = window.pageXOffset
4185
+ || document.documentElement.scrollLeft
4186
+ || document.body.scrollLeft
4187
+ || 0;
4188
+ this.deltaY = window.pageYOffset
4189
+ || document.documentElement.scrollTop
4190
+ || document.body.scrollTop
4191
+ || 0;
4192
+ },
4193
+
4194
+ // caches x/y coordinate pair to use with overlap
4195
+ within: function(element, x, y) {
4196
+ if (this.includeScrollOffsets)
4197
+ return this.withinIncludingScrolloffsets(element, x, y);
4198
+ this.xcomp = x;
4199
+ this.ycomp = y;
4200
+ this.offset = Element.cumulativeOffset(element);
4201
+
4202
+ return (y >= this.offset[1] &&
4203
+ y < this.offset[1] + element.offsetHeight &&
4204
+ x >= this.offset[0] &&
4205
+ x < this.offset[0] + element.offsetWidth);
4206
+ },
4207
+
4208
+ withinIncludingScrolloffsets: function(element, x, y) {
4209
+ var offsetcache = Element.cumulativeScrollOffset(element);
4210
+
4211
+ this.xcomp = x + offsetcache[0] - this.deltaX;
4212
+ this.ycomp = y + offsetcache[1] - this.deltaY;
4213
+ this.offset = Element.cumulativeOffset(element);
4214
+
4215
+ return (this.ycomp >= this.offset[1] &&
4216
+ this.ycomp < this.offset[1] + element.offsetHeight &&
4217
+ this.xcomp >= this.offset[0] &&
4218
+ this.xcomp < this.offset[0] + element.offsetWidth);
4219
+ },
4220
+
4221
+ // within must be called directly before
4222
+ overlap: function(mode, element) {
4223
+ if (!mode) return 0;
4224
+ if (mode == 'vertical')
4225
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
4226
+ element.offsetHeight;
4227
+ if (mode == 'horizontal')
4228
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
4229
+ element.offsetWidth;
4230
+ },
4231
+
4232
+ // Deprecation layer -- use newer Element methods now (1.5.2).
4233
+
4234
+ cumulativeOffset: Element.Methods.cumulativeOffset,
4235
+
4236
+ positionedOffset: Element.Methods.positionedOffset,
4237
+
4238
+ absolutize: function(element) {
4239
+ Position.prepare();
4240
+ return Element.absolutize(element);
4241
+ },
4242
+
4243
+ relativize: function(element) {
4244
+ Position.prepare();
4245
+ return Element.relativize(element);
4246
+ },
4247
+
4248
+ realOffset: Element.Methods.cumulativeScrollOffset,
4249
+
4250
+ offsetParent: Element.Methods.getOffsetParent,
4251
+
4252
+ page: Element.Methods.viewportOffset,
4253
+
4254
+ clone: function(source, target, options) {
4255
+ options = options || { };
4256
+ return Element.clonePosition(target, source, options);
4257
+ }
4258
+ };
4259
+
4260
+ /*--------------------------------------------------------------------------*/
4261
+
4262
+ if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
4263
+ function iter(name) {
4264
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
4265
+ }
4266
+
4267
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
4268
+ function(element, className) {
4269
+ className = className.toString().strip();
4270
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
4271
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
4272
+ } : function(element, className) {
4273
+ className = className.toString().strip();
4274
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
4275
+ if (!classNames && !className) return elements;
4276
+
4277
+ var nodes = $(element).getElementsByTagName('*');
4278
+ className = ' ' + className + ' ';
4279
+
4280
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
4281
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
4282
+ (classNames && classNames.all(function(name) {
4283
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
4284
+ }))))
4285
+ elements.push(Element.extend(child));
4286
+ }
4287
+ return elements;
4288
+ };
4289
+
4290
+ return function(className, parentElement) {
4291
+ return $(parentElement || document.body).getElementsByClassName(className);
4292
+ };
4293
+ }(Element.Methods);
4294
+
4295
+ /*--------------------------------------------------------------------------*/
4296
+
4297
+ Element.ClassNames = Class.create();
4298
+ Element.ClassNames.prototype = {
4299
+ initialize: function(element) {
4300
+ this.element = $(element);
4301
+ },
4302
+
4303
+ _each: function(iterator) {
4304
+ this.element.className.split(/\s+/).select(function(name) {
4305
+ return name.length > 0;
4306
+ })._each(iterator);
4307
+ },
4308
+
4309
+ set: function(className) {
4310
+ this.element.className = className;
4311
+ },
4312
+
4313
+ add: function(classNameToAdd) {
4314
+ if (this.include(classNameToAdd)) return;
4315
+ this.set($A(this).concat(classNameToAdd).join(' '));
4316
+ },
4317
+
4318
+ remove: function(classNameToRemove) {
4319
+ if (!this.include(classNameToRemove)) return;
4320
+ this.set($A(this).without(classNameToRemove).join(' '));
4321
+ },
4322
+
4323
+ toString: function() {
4324
+ return $A(this).join(' ');
4325
+ }
4326
+ };
4327
+
4328
+ Object.extend(Element.ClassNames.prototype, Enumerable);
4329
+
4330
+ /*--------------------------------------------------------------------------*/
4331
+
4332
+ Element.addMethods();
4333
+ var search_index = [
4334
+ { method: 'broken', module: 'try', html: '<a href="classes/Try.html#M000001"><span class="method_name">broken</span> <span class="module_name">(Try)</span></a>' },
4335
+ ]
4336
+ $(document).observe('dom:loaded', function() {
4337
+ // Setup search-during-typing.
4338
+ new Form.Element.Observer('search', 0.3, function(element, value) {
4339
+ performSearch();
4340
+ });
4341
+
4342
+ // Remove the default search box value when the user puts the focus on
4343
+ // the search box for the first time.
4344
+ var search_box = $('search');
4345
+ if ($F('search') == 'Enter search terms...') {
4346
+ search_box.observe('focus', function() {
4347
+ if (search_box.hasClassName('untouched')) {
4348
+ search_box.removeClassName('untouched');
4349
+ search_box.value = '';
4350
+ }
4351
+ });
4352
+ } else {
4353
+ search_box.removeClassName('untouched');
4354
+ }
4355
+ });
4356
+
4357
+ function searchInIndex(query) {
4358
+ var i;
4359
+ var results = [];
4360
+ query = query.toLowerCase();
4361
+ for (i = 0; i < search_index.length; i++) {
4362
+ if (search_index[i].method.indexOf(query) != -1) {
4363
+ results.push(search_index[i]);
4364
+ }
4365
+ }
4366
+ return results;
4367
+ }
4368
+
4369
+ function buildHtmlForResults(results) {
4370
+ var html = "";
4371
+ var i;
4372
+ for (i = 0; i < results.length; i++) {
4373
+ html += '<li>' + results[i].html + '</li>';
4374
+ }
4375
+ return html;
4376
+ }
4377
+
4378
+ function performSearch() {
4379
+ var query = $F('search');
4380
+ if (query == '') {
4381
+ $('index-entries').show();
4382
+ $('search-results').hide();
4383
+ } else {
4384
+ var results = searchInIndex(query);
4385
+ $('search-results').update(buildHtmlForResults(results));
4386
+ $('index-entries').hide();
4387
+ $('search-results').show();
4388
+ }
4389
+ return false;
4390
+ }
4391
+ </script>
4392
+ <form onsubmit='return performSearch()'>
4393
+ <input class='untouched' id='search' type='text' value='Enter search terms...'>
4394
+ </form>
4395
+ <ol class='methods' id='search-results' style='display: none'></ol>
4396
+ <ol class='methods' id='index-entries'>
4397
+ <li><a href="classes/Try.html#M000001"><span class="method_name">broken</span> <span class="module_name">(Try)</span></a></li>
4398
+ </ol>
4399
+ </div>
4400
+ </body>
4401
+ </html>