nitro-auth 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1038 @@
1
+ /* Prototype JavaScript framework, version 1.3.1
2
+ * (c) 2005 Sam Stephenson <sam@conio.net>
3
+ *
4
+ * THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5
+ * against the source tree, available from the Prototype darcs repository.
6
+ *
7
+ * Prototype is freely distributable under the terms of an MIT-style license.
8
+ *
9
+ * For details, see the Prototype web site: http://prototype.conio.net/
10
+ *
11
+ /*--------------------------------------------------------------------------*/
12
+
13
+ var Prototype = {
14
+ Version: '1.3.1',
15
+ emptyFunction: function() {}
16
+ }
17
+
18
+ var Class = {
19
+ create: function() {
20
+ return function() {
21
+ this.initialize.apply(this, arguments);
22
+ }
23
+ }
24
+ }
25
+
26
+ var Abstract = new Object();
27
+
28
+ Object.extend = function(destination, source) {
29
+ for (property in source) {
30
+ destination[property] = source[property];
31
+ }
32
+ return destination;
33
+ }
34
+
35
+ Object.prototype.extend = function(object) {
36
+ return Object.extend.apply(this, [this, object]);
37
+ }
38
+
39
+ Function.prototype.bind = function(object) {
40
+ var __method = this;
41
+ return function() {
42
+ __method.apply(object, arguments);
43
+ }
44
+ }
45
+
46
+ Function.prototype.bindAsEventListener = function(object) {
47
+ var __method = this;
48
+ return function(event) {
49
+ __method.call(object, event || window.event);
50
+ }
51
+ }
52
+
53
+ Number.prototype.toColorPart = function() {
54
+ var digits = this.toString(16);
55
+ if (this < 16) return '0' + digits;
56
+ return digits;
57
+ }
58
+
59
+ var Try = {
60
+ these: function() {
61
+ var returnValue;
62
+
63
+ for (var i = 0; i < arguments.length; i++) {
64
+ var lambda = arguments[i];
65
+ try {
66
+ returnValue = lambda();
67
+ break;
68
+ } catch (e) {}
69
+ }
70
+
71
+ return returnValue;
72
+ }
73
+ }
74
+
75
+ /*--------------------------------------------------------------------------*/
76
+
77
+ var PeriodicalExecuter = Class.create();
78
+ PeriodicalExecuter.prototype = {
79
+ initialize: function(callback, frequency) {
80
+ this.callback = callback;
81
+ this.frequency = frequency;
82
+ this.currentlyExecuting = false;
83
+
84
+ this.registerCallback();
85
+ },
86
+
87
+ registerCallback: function() {
88
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
89
+ },
90
+
91
+ onTimerEvent: function() {
92
+ if (!this.currentlyExecuting) {
93
+ try {
94
+ this.currentlyExecuting = true;
95
+ this.callback();
96
+ } finally {
97
+ this.currentlyExecuting = false;
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ /*--------------------------------------------------------------------------*/
104
+
105
+ function $() {
106
+ var elements = new Array();
107
+
108
+ for (var i = 0; i < arguments.length; i++) {
109
+ var element = arguments[i];
110
+ if (typeof element == 'string')
111
+ element = document.getElementById(element);
112
+
113
+ if (arguments.length == 1)
114
+ return element;
115
+
116
+ elements.push(element);
117
+ }
118
+
119
+ return elements;
120
+ }
121
+
122
+ if (!Array.prototype.push) {
123
+ Array.prototype.push = function() {
124
+ var startLength = this.length;
125
+ for (var i = 0; i < arguments.length; i++)
126
+ this[startLength + i] = arguments[i];
127
+ return this.length;
128
+ }
129
+ }
130
+
131
+ if (!Function.prototype.apply) {
132
+ // Based on code from http://www.youngpup.net/
133
+ Function.prototype.apply = function(object, parameters) {
134
+ var parameterStrings = new Array();
135
+ if (!object) object = window;
136
+ if (!parameters) parameters = new Array();
137
+
138
+ for (var i = 0; i < parameters.length; i++)
139
+ parameterStrings[i] = 'parameters[' + i + ']';
140
+
141
+ object.__apply__ = this;
142
+ var result = eval('object.__apply__(' +
143
+ parameterStrings[i].join(', ') + ')');
144
+ object.__apply__ = null;
145
+
146
+ return result;
147
+ }
148
+ }
149
+
150
+ String.prototype.extend({
151
+ stripTags: function() {
152
+ return this.replace(/<\/?[^>]+>/gi, '');
153
+ },
154
+
155
+ escapeHTML: function() {
156
+ var div = document.createElement('div');
157
+ var text = document.createTextNode(this);
158
+ div.appendChild(text);
159
+ return div.innerHTML;
160
+ },
161
+
162
+ unescapeHTML: function() {
163
+ var div = document.createElement('div');
164
+ div.innerHTML = this.stripTags();
165
+ return div.childNodes[0].nodeValue;
166
+ }
167
+ });
168
+
169
+ var Ajax = {
170
+ getTransport: function() {
171
+ return Try.these(
172
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
173
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')},
174
+ function() {return new XMLHttpRequest()}
175
+ ) || false;
176
+ }
177
+ }
178
+
179
+ Ajax.Base = function() {};
180
+ Ajax.Base.prototype = {
181
+ setOptions: function(options) {
182
+ this.options = {
183
+ method: 'post',
184
+ asynchronous: true,
185
+ parameters: ''
186
+ }.extend(options || {});
187
+ },
188
+
189
+ responseIsSuccess: function() {
190
+ return this.transport.status == undefined
191
+ || this.transport.status == 0
192
+ || (this.transport.status >= 200 && this.transport.status < 300);
193
+ },
194
+
195
+ responseIsFailure: function() {
196
+ return !this.responseIsSuccess();
197
+ }
198
+ }
199
+
200
+ Ajax.Request = Class.create();
201
+ Ajax.Request.Events =
202
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
203
+
204
+ Ajax.Request.prototype = (new Ajax.Base()).extend({
205
+ initialize: function(url, options) {
206
+ this.transport = Ajax.getTransport();
207
+ this.setOptions(options);
208
+ this.request(url);
209
+ },
210
+
211
+ request: function(url) {
212
+ var parameters = this.options.parameters || '';
213
+ if (parameters.length > 0) parameters += '&_=';
214
+
215
+ try {
216
+ if (this.options.method == 'get')
217
+ url += '?' + parameters;
218
+
219
+ this.transport.open(this.options.method, url,
220
+ this.options.asynchronous);
221
+
222
+ if (this.options.asynchronous) {
223
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
224
+ setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
225
+ }
226
+
227
+ this.setRequestHeaders();
228
+
229
+ var body = this.options.postBody ? this.options.postBody : parameters;
230
+ this.transport.send(this.options.method == 'post' ? body : null);
231
+
232
+ } catch (e) {
233
+ }
234
+ },
235
+
236
+ setRequestHeaders: function() {
237
+ var requestHeaders =
238
+ ['X-Requested-With', 'XMLHttpRequest',
239
+ 'X-Prototype-Version', Prototype.Version];
240
+
241
+ if (this.options.method == 'post') {
242
+ requestHeaders.push('Content-type',
243
+ 'application/x-www-form-urlencoded');
244
+
245
+ /* Force "Connection: close" for Mozilla browsers to work around
246
+ * a bug where XMLHttpReqeuest sends an incorrect Content-length
247
+ * header. See Mozilla Bugzilla #246651.
248
+ */
249
+ if (this.transport.overrideMimeType)
250
+ requestHeaders.push('Connection', 'close');
251
+ }
252
+
253
+ if (this.options.requestHeaders)
254
+ requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
255
+
256
+ for (var i = 0; i < requestHeaders.length; i += 2)
257
+ this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
258
+ },
259
+
260
+ onStateChange: function() {
261
+ var readyState = this.transport.readyState;
262
+ if (readyState != 1)
263
+ this.respondToReadyState(this.transport.readyState);
264
+ },
265
+
266
+ respondToReadyState: function(readyState) {
267
+ var event = Ajax.Request.Events[readyState];
268
+
269
+ if (event == 'Complete')
270
+ (this.options['on' + this.transport.status]
271
+ || this.options['on' + this.responseIsSuccess() ? 'Success' : 'Failure']
272
+ || Prototype.emptyFunction)(this.transport);
273
+
274
+ (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
275
+
276
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277
+ if (event == 'Complete')
278
+ this.transport.onreadystatechange = Prototype.emptyFunction;
279
+ }
280
+ });
281
+
282
+ Ajax.Updater = Class.create();
283
+ Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
284
+
285
+ Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
286
+ initialize: function(container, url, options) {
287
+ this.containers = {
288
+ success: container.success ? $(container.success) : $(container),
289
+ failure: container.failure ? $(container.failure) :
290
+ (container.success ? null : $(container))
291
+ }
292
+
293
+ this.transport = Ajax.getTransport();
294
+ this.setOptions(options);
295
+
296
+ var onComplete = this.options.onComplete || Prototype.emptyFunction;
297
+ this.options.onComplete = (function() {
298
+ this.updateContent();
299
+ onComplete(this.transport);
300
+ }).bind(this);
301
+
302
+ this.request(url);
303
+ },
304
+
305
+ updateContent: function() {
306
+ var receiver = this.responseIsSuccess() ?
307
+ this.containers.success : this.containers.failure;
308
+
309
+ var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');
310
+ var response = this.transport.responseText.replace(match, '');
311
+ var scripts = this.transport.responseText.match(match);
312
+
313
+ if (receiver) {
314
+ if (this.options.insertion) {
315
+ new this.options.insertion(receiver, response);
316
+ } else {
317
+ receiver.innerHTML = response;
318
+ }
319
+ }
320
+
321
+ if (this.responseIsSuccess()) {
322
+ if (this.onComplete)
323
+ setTimeout((function() {this.onComplete(
324
+ this.transport)}).bind(this), 10);
325
+ }
326
+
327
+ if (this.options.evalScripts && scripts) {
328
+ match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
329
+ setTimeout((function() {
330
+ for (var i = 0; i < scripts.length; i++)
331
+ eval(scripts[i].match(match)[1]);
332
+ }).bind(this), 10);
333
+ }
334
+ }
335
+ });
336
+
337
+ Ajax.PeriodicalUpdater = Class.create();
338
+ Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
339
+ initialize: function(container, url, options) {
340
+ this.setOptions(options);
341
+ this.onComplete = this.options.onComplete;
342
+
343
+ this.frequency = (this.options.frequency || 2);
344
+ this.decay = 1;
345
+
346
+ this.updater = {};
347
+ this.container = container;
348
+ this.url = url;
349
+
350
+ this.start();
351
+ },
352
+
353
+ start: function() {
354
+ this.options.onComplete = this.updateComplete.bind(this);
355
+ this.onTimerEvent();
356
+ },
357
+
358
+ stop: function() {
359
+ this.updater.onComplete = undefined;
360
+ clearTimeout(this.timer);
361
+ (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
362
+ },
363
+
364
+ updateComplete: function(request) {
365
+ if (this.options.decay) {
366
+ this.decay = (request.responseText == this.lastText ?
367
+ this.decay * this.options.decay : 1);
368
+
369
+ this.lastText = request.responseText;
370
+ }
371
+ this.timer = setTimeout(this.onTimerEvent.bind(this),
372
+ this.decay * this.frequency * 1000);
373
+ },
374
+
375
+ onTimerEvent: function() {
376
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
377
+ }
378
+ });
379
+
380
+ document.getElementsByClassName = function(className) {
381
+ var children = document.getElementsByTagName('*') || document.all;
382
+ var elements = new Array();
383
+
384
+ for (var i = 0; i < children.length; i++) {
385
+ var child = children[i];
386
+ var classNames = child.className.split(' ');
387
+ for (var j = 0; j < classNames.length; j++) {
388
+ if (classNames[j] == className) {
389
+ elements.push(child);
390
+ break;
391
+ }
392
+ }
393
+ }
394
+
395
+ return elements;
396
+ }
397
+
398
+ /*--------------------------------------------------------------------------*/
399
+
400
+ if (!window.Element) {
401
+ var Element = new Object();
402
+ }
403
+
404
+ Object.extend(Element, {
405
+ toggle: function() {
406
+ for (var i = 0; i < arguments.length; i++) {
407
+ var element = $(arguments[i]);
408
+ element.style.display =
409
+ (element.style.display == 'none' ? '' : 'none');
410
+ }
411
+ },
412
+
413
+ hide: function() {
414
+ for (var i = 0; i < arguments.length; i++) {
415
+ var element = $(arguments[i]);
416
+ element.style.display = 'none';
417
+ }
418
+ },
419
+
420
+ show: function() {
421
+ for (var i = 0; i < arguments.length; i++) {
422
+ var element = $(arguments[i]);
423
+ element.style.display = '';
424
+ }
425
+ },
426
+
427
+ remove: function(element) {
428
+ element = $(element);
429
+ element.parentNode.removeChild(element);
430
+ },
431
+
432
+ getHeight: function(element) {
433
+ element = $(element);
434
+ return element.offsetHeight;
435
+ },
436
+
437
+ hasClassName: function(element, className) {
438
+ element = $(element);
439
+ if (!element)
440
+ return;
441
+ var a = element.className.split(' ');
442
+ for (var i = 0; i < a.length; i++) {
443
+ if (a[i] == className)
444
+ return true;
445
+ }
446
+ return false;
447
+ },
448
+
449
+ addClassName: function(element, className) {
450
+ element = $(element);
451
+ Element.removeClassName(element, className);
452
+ element.className += ' ' + className;
453
+ },
454
+
455
+ removeClassName: function(element, className) {
456
+ element = $(element);
457
+ if (!element)
458
+ return;
459
+ var newClassName = '';
460
+ var a = element.className.split(' ');
461
+ for (var i = 0; i < a.length; i++) {
462
+ if (a[i] != className) {
463
+ if (i > 0)
464
+ newClassName += ' ';
465
+ newClassName += a[i];
466
+ }
467
+ }
468
+ element.className = newClassName;
469
+ },
470
+
471
+ // removes whitespace-only text node children
472
+ cleanWhitespace: function(element) {
473
+ var element = $(element);
474
+ for (var i = 0; i < element.childNodes.length; i++) {
475
+ var node = element.childNodes[i];
476
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
477
+ Element.remove(node);
478
+ }
479
+ }
480
+ });
481
+
482
+ var Toggle = new Object();
483
+ Toggle.display = Element.toggle;
484
+
485
+ /*--------------------------------------------------------------------------*/
486
+
487
+ Abstract.Insertion = function(adjacency) {
488
+ this.adjacency = adjacency;
489
+ }
490
+
491
+ Abstract.Insertion.prototype = {
492
+ initialize: function(element, content) {
493
+ this.element = $(element);
494
+ this.content = content;
495
+
496
+ if (this.adjacency && this.element.insertAdjacentHTML) {
497
+ this.element.insertAdjacentHTML(this.adjacency, this.content);
498
+ } else {
499
+ this.range = this.element.ownerDocument.createRange();
500
+ if (this.initializeRange) this.initializeRange();
501
+ this.fragment = this.range.createContextualFragment(this.content);
502
+ this.insertContent();
503
+ }
504
+ }
505
+ }
506
+
507
+ var Insertion = new Object();
508
+
509
+ Insertion.Before = Class.create();
510
+ Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
511
+ initializeRange: function() {
512
+ this.range.setStartBefore(this.element);
513
+ },
514
+
515
+ insertContent: function() {
516
+ this.element.parentNode.insertBefore(this.fragment, this.element);
517
+ }
518
+ });
519
+
520
+ Insertion.Top = Class.create();
521
+ Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
522
+ initializeRange: function() {
523
+ this.range.selectNodeContents(this.element);
524
+ this.range.collapse(true);
525
+ },
526
+
527
+ insertContent: function() {
528
+ this.element.insertBefore(this.fragment, this.element.firstChild);
529
+ }
530
+ });
531
+
532
+ Insertion.Bottom = Class.create();
533
+ Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
534
+ initializeRange: function() {
535
+ this.range.selectNodeContents(this.element);
536
+ this.range.collapse(this.element);
537
+ },
538
+
539
+ insertContent: function() {
540
+ this.element.appendChild(this.fragment);
541
+ }
542
+ });
543
+
544
+ Insertion.After = Class.create();
545
+ Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
546
+ initializeRange: function() {
547
+ this.range.setStartAfter(this.element);
548
+ },
549
+
550
+ insertContent: function() {
551
+ this.element.parentNode.insertBefore(this.fragment,
552
+ this.element.nextSibling);
553
+ }
554
+ });
555
+
556
+ var Field = {
557
+ clear: function() {
558
+ for (var i = 0; i < arguments.length; i++)
559
+ $(arguments[i]).value = '';
560
+ },
561
+
562
+ focus: function(element) {
563
+ $(element).focus();
564
+ },
565
+
566
+ present: function() {
567
+ for (var i = 0; i < arguments.length; i++)
568
+ if ($(arguments[i]).value == '') return false;
569
+ return true;
570
+ },
571
+
572
+ select: function(element) {
573
+ $(element).select();
574
+ },
575
+
576
+ activate: function(element) {
577
+ $(element).focus();
578
+ $(element).select();
579
+ }
580
+ }
581
+
582
+ /*--------------------------------------------------------------------------*/
583
+
584
+ var Form = {
585
+ serialize: function(form) {
586
+ var elements = Form.getElements($(form));
587
+ var queryComponents = new Array();
588
+
589
+ for (var i = 0; i < elements.length; i++) {
590
+ var queryComponent = Form.Element.serialize(elements[i]);
591
+ if (queryComponent)
592
+ queryComponents.push(queryComponent);
593
+ }
594
+
595
+ return queryComponents.join('&');
596
+ },
597
+
598
+ getElements: function(form) {
599
+ var form = $(form);
600
+ var elements = new Array();
601
+
602
+ for (tagName in Form.Element.Serializers) {
603
+ var tagElements = form.getElementsByTagName(tagName);
604
+ for (var j = 0; j < tagElements.length; j++)
605
+ elements.push(tagElements[j]);
606
+ }
607
+ return elements;
608
+ },
609
+
610
+ getInputs: function(form, typeName, name) {
611
+ var form = $(form);
612
+ var inputs = form.getElementsByTagName('input');
613
+
614
+ if (!typeName && !name)
615
+ return inputs;
616
+
617
+ var matchingInputs = new Array();
618
+ for (var i = 0; i < inputs.length; i++) {
619
+ var input = inputs[i];
620
+ if ((typeName && input.type != typeName) ||
621
+ (name && input.name != name))
622
+ continue;
623
+ matchingInputs.push(input);
624
+ }
625
+
626
+ return matchingInputs;
627
+ },
628
+
629
+ disable: function(form) {
630
+ var elements = Form.getElements(form);
631
+ for (var i = 0; i < elements.length; i++) {
632
+ var element = elements[i];
633
+ element.blur();
634
+ element.disabled = 'true';
635
+ }
636
+ },
637
+
638
+ enable: function(form) {
639
+ var elements = Form.getElements(form);
640
+ for (var i = 0; i < elements.length; i++) {
641
+ var element = elements[i];
642
+ element.disabled = '';
643
+ }
644
+ },
645
+
646
+ focusFirstElement: function(form) {
647
+ var form = $(form);
648
+ var elements = Form.getElements(form);
649
+ for (var i = 0; i < elements.length; i++) {
650
+ var element = elements[i];
651
+ if (element.type != 'hidden' && !element.disabled) {
652
+ Field.activate(element);
653
+ break;
654
+ }
655
+ }
656
+ },
657
+
658
+ reset: function(form) {
659
+ $(form).reset();
660
+ }
661
+ }
662
+
663
+ Form.Element = {
664
+ serialize: function(element) {
665
+ var element = $(element);
666
+ var method = element.tagName.toLowerCase();
667
+ var parameter = Form.Element.Serializers[method](element);
668
+
669
+ if (parameter)
670
+ return encodeURIComponent(parameter[0]) + '=' +
671
+ encodeURIComponent(parameter[1]);
672
+ },
673
+
674
+ getValue: function(element) {
675
+ var element = $(element);
676
+ var method = element.tagName.toLowerCase();
677
+ var parameter = Form.Element.Serializers[method](element);
678
+
679
+ if (parameter)
680
+ return parameter[1];
681
+ }
682
+ }
683
+
684
+ Form.Element.Serializers = {
685
+ input: function(element) {
686
+ switch (element.type.toLowerCase()) {
687
+ case 'submit':
688
+ case 'hidden':
689
+ case 'password':
690
+ case 'text':
691
+ return Form.Element.Serializers.textarea(element);
692
+ case 'checkbox':
693
+ case 'radio':
694
+ return Form.Element.Serializers.inputSelector(element);
695
+ }
696
+ return false;
697
+ },
698
+
699
+ inputSelector: function(element) {
700
+ if (element.checked)
701
+ return [element.name, element.value];
702
+ },
703
+
704
+ textarea: function(element) {
705
+ return [element.name, element.value];
706
+ },
707
+
708
+ select: function(element) {
709
+ var value = '';
710
+ if (element.type == 'select-one') {
711
+ var index = element.selectedIndex;
712
+ if (index >= 0)
713
+ value = element.options[index].value || element.options[index].text;
714
+ } else {
715
+ value = new Array();
716
+ for (var i = 0; i < element.length; i++) {
717
+ var opt = element.options[i];
718
+ if (opt.selected)
719
+ value.push(opt.value || opt.text);
720
+ }
721
+ }
722
+ return [element.name, value];
723
+ }
724
+ }
725
+
726
+ /*--------------------------------------------------------------------------*/
727
+
728
+ var $F = Form.Element.getValue;
729
+
730
+ /*--------------------------------------------------------------------------*/
731
+
732
+ Abstract.TimedObserver = function() {}
733
+ Abstract.TimedObserver.prototype = {
734
+ initialize: function(element, frequency, callback) {
735
+ this.frequency = frequency;
736
+ this.element = $(element);
737
+ this.callback = callback;
738
+
739
+ this.lastValue = this.getValue();
740
+ this.registerCallback();
741
+ },
742
+
743
+ registerCallback: function() {
744
+ setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
745
+ },
746
+
747
+ onTimerEvent: function() {
748
+ var value = this.getValue();
749
+ if (this.lastValue != value) {
750
+ this.callback(this.element, value);
751
+ this.lastValue = value;
752
+ }
753
+ }
754
+ }
755
+
756
+ Form.Element.Observer = Class.create();
757
+ Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
758
+ getValue: function() {
759
+ return Form.Element.getValue(this.element);
760
+ }
761
+ });
762
+
763
+ Form.Observer = Class.create();
764
+ Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
765
+ getValue: function() {
766
+ return Form.serialize(this.element);
767
+ }
768
+ });
769
+
770
+ /*--------------------------------------------------------------------------*/
771
+
772
+ Abstract.EventObserver = function() {}
773
+ Abstract.EventObserver.prototype = {
774
+ initialize: function(element, callback) {
775
+ this.element = $(element);
776
+ this.callback = callback;
777
+
778
+ this.lastValue = this.getValue();
779
+ if (this.element.tagName.toLowerCase() == 'form')
780
+ this.registerFormCallbacks();
781
+ else
782
+ this.registerCallback(this.element);
783
+ },
784
+
785
+ onElementEvent: function() {
786
+ var value = this.getValue();
787
+ if (this.lastValue != value) {
788
+ this.callback(this.element, value);
789
+ this.lastValue = value;
790
+ }
791
+ },
792
+
793
+ registerFormCallbacks: function() {
794
+ var elements = Form.getElements(this.element);
795
+ for (var i = 0; i < elements.length; i++)
796
+ this.registerCallback(elements[i]);
797
+ },
798
+
799
+ registerCallback: function(element) {
800
+ if (element.type) {
801
+ switch (element.type.toLowerCase()) {
802
+ case 'checkbox':
803
+ case 'radio':
804
+ element.target = this;
805
+ element.prev_onclick = element.onclick || Prototype.emptyFunction;
806
+ element.onclick = function() {
807
+ this.prev_onclick();
808
+ this.target.onElementEvent();
809
+ }
810
+ break;
811
+ case 'password':
812
+ case 'text':
813
+ case 'textarea':
814
+ case 'select-one':
815
+ case 'select-multiple':
816
+ element.target = this;
817
+ element.prev_onchange = element.onchange || Prototype.emptyFunction;
818
+ element.onchange = function() {
819
+ this.prev_onchange();
820
+ this.target.onElementEvent();
821
+ }
822
+ break;
823
+ }
824
+ }
825
+ }
826
+ }
827
+
828
+ Form.Element.EventObserver = Class.create();
829
+ Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
830
+ getValue: function() {
831
+ return Form.Element.getValue(this.element);
832
+ }
833
+ });
834
+
835
+ Form.EventObserver = Class.create();
836
+ Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
837
+ getValue: function() {
838
+ return Form.serialize(this.element);
839
+ }
840
+ });
841
+
842
+
843
+ if (!window.Event) {
844
+ var Event = new Object();
845
+ }
846
+
847
+ Object.extend(Event, {
848
+ KEY_BACKSPACE: 8,
849
+ KEY_TAB: 9,
850
+ KEY_RETURN: 13,
851
+ KEY_ESC: 27,
852
+ KEY_LEFT: 37,
853
+ KEY_UP: 38,
854
+ KEY_RIGHT: 39,
855
+ KEY_DOWN: 40,
856
+ KEY_DELETE: 46,
857
+
858
+ element: function(event) {
859
+ return event.target || event.srcElement;
860
+ },
861
+
862
+ isLeftClick: function(event) {
863
+ return (((event.which) && (event.which == 1)) ||
864
+ ((event.button) && (event.button == 1)));
865
+ },
866
+
867
+ pointerX: function(event) {
868
+ return event.pageX || (event.clientX +
869
+ (document.documentElement.scrollLeft || document.body.scrollLeft));
870
+ },
871
+
872
+ pointerY: function(event) {
873
+ return event.pageY || (event.clientY +
874
+ (document.documentElement.scrollTop || document.body.scrollTop));
875
+ },
876
+
877
+ stop: function(event) {
878
+ if (event.preventDefault) {
879
+ event.preventDefault();
880
+ event.stopPropagation();
881
+ } else {
882
+ event.returnValue = false;
883
+ }
884
+ },
885
+
886
+ // find the first node with the given tagName, starting from the
887
+ // node the event was triggered on; traverses the DOM upwards
888
+ findElement: function(event, tagName) {
889
+ var element = Event.element(event);
890
+ while (element.parentNode && (!element.tagName ||
891
+ (element.tagName.toUpperCase() != tagName.toUpperCase())))
892
+ element = element.parentNode;
893
+ return element;
894
+ },
895
+
896
+ observers: false,
897
+
898
+ _observeAndCache: function(element, name, observer, useCapture) {
899
+ if (!this.observers) this.observers = [];
900
+ if (element.addEventListener) {
901
+ this.observers.push([element, name, observer, useCapture]);
902
+ element.addEventListener(name, observer, useCapture);
903
+ } else if (element.attachEvent) {
904
+ this.observers.push([element, name, observer, useCapture]);
905
+ element.attachEvent('on' + name, observer);
906
+ }
907
+ },
908
+
909
+ unloadCache: function() {
910
+ if (!Event.observers) return;
911
+ for (var i = 0; i < Event.observers.length; i++) {
912
+ Event.stopObserving.apply(this, Event.observers[i]);
913
+ Event.observers[i][0] = null;
914
+ }
915
+ Event.observers = false;
916
+ },
917
+
918
+ observe: function(element, name, observer, useCapture) {
919
+ var element = $(element);
920
+ useCapture = useCapture || false;
921
+
922
+ if (name == 'keypress' &&
923
+ ((navigator.appVersion.indexOf('AppleWebKit') > 0)
924
+ || element.attachEvent))
925
+ name = 'keydown';
926
+
927
+ this._observeAndCache(element, name, observer, useCapture);
928
+ },
929
+
930
+ stopObserving: function(element, name, observer, useCapture) {
931
+ var element = $(element);
932
+ useCapture = useCapture || false;
933
+
934
+ if (name == 'keypress' &&
935
+ ((navigator.appVersion.indexOf('AppleWebKit') > 0)
936
+ || element.detachEvent))
937
+ name = 'keydown';
938
+
939
+ if (element.removeEventListener) {
940
+ element.removeEventListener(name, observer, useCapture);
941
+ } else if (element.detachEvent) {
942
+ element.detachEvent('on' + name, observer);
943
+ }
944
+ }
945
+ });
946
+
947
+ /* prevent memory leaks in IE */
948
+ Event.observe(window, 'unload', Event.unloadCache, false);
949
+
950
+ var Position = {
951
+
952
+ // set to true if needed, warning: firefox performance problems
953
+ // NOT neeeded for page scrolling, only if draggable contained in
954
+ // scrollable elements
955
+ includeScrollOffsets: false,
956
+
957
+ // must be called before calling withinIncludingScrolloffset, every time the
958
+ // page is scrolled
959
+ prepare: function() {
960
+ this.deltaX = window.pageXOffset
961
+ || document.documentElement.scrollLeft
962
+ || document.body.scrollLeft
963
+ || 0;
964
+ this.deltaY = window.pageYOffset
965
+ || document.documentElement.scrollTop
966
+ || document.body.scrollTop
967
+ || 0;
968
+ },
969
+
970
+ realOffset: function(element) {
971
+ var valueT = 0, valueL = 0;
972
+ do {
973
+ valueT += element.scrollTop || 0;
974
+ valueL += element.scrollLeft || 0;
975
+ element = element.parentNode;
976
+ } while (element);
977
+ return [valueL, valueT];
978
+ },
979
+
980
+ cumulativeOffset: function(element) {
981
+ var valueT = 0, valueL = 0;
982
+ do {
983
+ valueT += element.offsetTop || 0;
984
+ valueL += element.offsetLeft || 0;
985
+ element = element.offsetParent;
986
+ } while (element);
987
+ return [valueL, valueT];
988
+ },
989
+
990
+ // caches x/y coordinate pair to use with overlap
991
+ within: function(element, x, y) {
992
+ if (this.includeScrollOffsets)
993
+ return this.withinIncludingScrolloffsets(element, x, y);
994
+ this.xcomp = x;
995
+ this.ycomp = y;
996
+ this.offset = this.cumulativeOffset(element);
997
+
998
+ return (y >= this.offset[1] &&
999
+ y < this.offset[1] + element.offsetHeight &&
1000
+ x >= this.offset[0] &&
1001
+ x < this.offset[0] + element.offsetWidth);
1002
+ },
1003
+
1004
+ withinIncludingScrolloffsets: function(element, x, y) {
1005
+ var offsetcache = this.realOffset(element);
1006
+
1007
+ this.xcomp = x + offsetcache[0] - this.deltaX;
1008
+ this.ycomp = y + offsetcache[1] - this.deltaY;
1009
+ this.offset = this.cumulativeOffset(element);
1010
+
1011
+ return (this.ycomp >= this.offset[1] &&
1012
+ this.ycomp < this.offset[1] + element.offsetHeight &&
1013
+ this.xcomp >= this.offset[0] &&
1014
+ this.xcomp < this.offset[0] + element.offsetWidth);
1015
+ },
1016
+
1017
+ // within must be called directly before
1018
+ overlap: function(mode, element) {
1019
+ if (!mode) return 0;
1020
+ if (mode == 'vertical')
1021
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1022
+ element.offsetHeight;
1023
+ if (mode == 'horizontal')
1024
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1025
+ element.offsetWidth;
1026
+ },
1027
+
1028
+ clone: function(source, target) {
1029
+ source = $(source);
1030
+ target = $(target);
1031
+ target.style.position = 'absolute';
1032
+ var offsets = this.cumulativeOffset(source);
1033
+ target.style.top = offsets[1] + 'px';
1034
+ target.style.left = offsets[0] + 'px';
1035
+ target.style.width = source.offsetWidth + 'px';
1036
+ target.style.height = source.offsetHeight + 'px';
1037
+ }
1038
+ }