Commit | Line | Data |
---|---|---|
d2512426 DC |
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.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 | } |