Mercurial > laserkard
comparison onlypaths/js/prototype.js @ 46:26c2b3ad21c7 laserkard
[svn r47] saving progresswww.cinemassacre.com/new/?page_id=30
author | rlm |
---|---|
date | Sun, 31 Jan 2010 12:33:33 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
45:bff96abdddfa | 46:26c2b3ad21c7 |
---|---|
1 /* Prototype JavaScript framework, version 1.4.0 | |
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.4.0', | |
15 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', | |
16 | |
17 emptyFunction: function() {}, | |
18 K: function(x) {return x} | |
19 } | |
20 | |
21 var Class = { | |
22 create: function() { | |
23 return function() { | |
24 this.initialize.apply(this, arguments); | |
25 } | |
26 } | |
27 } | |
28 | |
29 var Abstract = new Object(); | |
30 | |
31 Object.extend = function(destination, source) { | |
32 for (property in source) { | |
33 destination[property] = source[property]; | |
34 } | |
35 return destination; | |
36 } | |
37 | |
38 Object.inspect = function(object) { | |
39 try { | |
40 if (object == undefined) return 'undefined'; | |
41 if (object == null) return 'null'; | |
42 return object.inspect ? object.inspect() : object.toString(); | |
43 } catch (e) { | |
44 if (e instanceof RangeError) return '...'; | |
45 throw e; | |
46 } | |
47 } | |
48 | |
49 Function.prototype.bind = function() { | |
50 var __method = this, args = $A(arguments), object = args.shift(); | |
51 return function() { | |
52 return __method.apply(object, args.concat($A(arguments))); | |
53 } | |
54 } | |
55 | |
56 Function.prototype.bindAsEventListener = function(object) { | |
57 var __method = this; | |
58 return function(event) { | |
59 return __method.call(object, event || window.event); | |
60 } | |
61 } | |
62 | |
63 Object.extend(Number.prototype, { | |
64 toColorPart: function() { | |
65 var digits = this.toString(16); | |
66 if (this < 16) return '0' + digits; | |
67 return digits; | |
68 }, | |
69 | |
70 succ: function() { | |
71 return this + 1; | |
72 }, | |
73 | |
74 times: function(iterator) { | |
75 $R(0, this, true).each(iterator); | |
76 return this; | |
77 } | |
78 }); | |
79 | |
80 var Try = { | |
81 these: function() { | |
82 var returnValue; | |
83 | |
84 for (var i = 0; i < arguments.length; i++) { | |
85 var lambda = arguments[i]; | |
86 try { | |
87 returnValue = lambda(); | |
88 break; | |
89 } catch (e) {} | |
90 } | |
91 | |
92 return returnValue; | |
93 } | |
94 } | |
95 | |
96 /*--------------------------------------------------------------------------*/ | |
97 | |
98 var PeriodicalExecuter = Class.create(); | |
99 PeriodicalExecuter.prototype = { | |
100 initialize: function(callback, frequency) { | |
101 this.callback = callback; | |
102 this.frequency = frequency; | |
103 this.currentlyExecuting = false; | |
104 | |
105 this.registerCallback(); | |
106 }, | |
107 | |
108 registerCallback: function() { | |
109 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); | |
110 }, | |
111 | |
112 onTimerEvent: function() { | |
113 if (!this.currentlyExecuting) { | |
114 try { | |
115 this.currentlyExecuting = true; | |
116 this.callback(); | |
117 } finally { | |
118 this.currentlyExecuting = false; | |
119 } | |
120 } | |
121 } | |
122 } | |
123 | |
124 /*--------------------------------------------------------------------------*/ | |
125 | |
126 function $() { | |
127 var elements = new Array(); | |
128 | |
129 for (var i = 0; i < arguments.length; i++) { | |
130 var element = arguments[i]; | |
131 if (typeof element == 'string') | |
132 element = document.getElementById(element); | |
133 | |
134 if (arguments.length == 1) | |
135 return element; | |
136 | |
137 elements.push(element); | |
138 } | |
139 | |
140 return elements; | |
141 } | |
142 Object.extend(String.prototype, { | |
143 stripTags: function() { | |
144 return this.replace(/<\/?[^>]+>/gi, ''); | |
145 }, | |
146 | |
147 stripScripts: function() { | |
148 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); | |
149 }, | |
150 | |
151 extractScripts: function() { | |
152 var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); | |
153 var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); | |
154 return (this.match(matchAll) || []).map(function(scriptTag) { | |
155 return (scriptTag.match(matchOne) || ['', ''])[1]; | |
156 }); | |
157 }, | |
158 | |
159 evalScripts: function() { | |
160 return this.extractScripts().map(eval); | |
161 }, | |
162 | |
163 escapeHTML: function() { | |
164 var div = document.createElement('div'); | |
165 var text = document.createTextNode(this); | |
166 div.appendChild(text); | |
167 return div.innerHTML; | |
168 }, | |
169 | |
170 unescapeHTML: function() { | |
171 var div = document.createElement('div'); | |
172 div.innerHTML = this.stripTags(); | |
173 return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; | |
174 }, | |
175 | |
176 toQueryParams: function() { | |
177 var pairs = this.match(/^\??(.*)$/)[1].split('&'); | |
178 return pairs.inject({}, function(params, pairString) { | |
179 var pair = pairString.split('='); | |
180 params[pair[0]] = pair[1]; | |
181 return params; | |
182 }); | |
183 }, | |
184 | |
185 toArray: function() { | |
186 return this.split(''); | |
187 }, | |
188 | |
189 camelize: function() { | |
190 var oStringList = this.split('-'); | |
191 if (oStringList.length == 1) return oStringList[0]; | |
192 | |
193 var camelizedString = this.indexOf('-') == 0 | |
194 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) | |
195 : oStringList[0]; | |
196 | |
197 for (var i = 1, len = oStringList.length; i < len; i++) { | |
198 var s = oStringList[i]; | |
199 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); | |
200 } | |
201 | |
202 return camelizedString; | |
203 }, | |
204 | |
205 inspect: function() { | |
206 return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; | |
207 } | |
208 }); | |
209 | |
210 String.prototype.parseQuery = String.prototype.toQueryParams; | |
211 | |
212 var $break = new Object(); | |
213 var $continue = new Object(); | |
214 | |
215 var Enumerable = { | |
216 each: function(iterator) { | |
217 var index = 0; | |
218 try { | |
219 this._each(function(value) { | |
220 try { | |
221 iterator(value, index++); | |
222 } catch (e) { | |
223 if (e != $continue) throw e; | |
224 } | |
225 }); | |
226 } catch (e) { | |
227 if (e != $break) throw e; | |
228 } | |
229 }, | |
230 | |
231 all: function(iterator) { | |
232 var result = true; | |
233 this.each(function(value, index) { | |
234 result = result && !!(iterator || Prototype.K)(value, index); | |
235 if (!result) throw $break; | |
236 }); | |
237 return result; | |
238 }, | |
239 | |
240 any: function(iterator) { | |
241 var result = true; | |
242 this.each(function(value, index) { | |
243 if (result = !!(iterator || Prototype.K)(value, index)) | |
244 throw $break; | |
245 }); | |
246 return result; | |
247 }, | |
248 | |
249 collect: function(iterator) { | |
250 var results = []; | |
251 this.each(function(value, index) { | |
252 results.push(iterator(value, index)); | |
253 }); | |
254 return results; | |
255 }, | |
256 | |
257 detect: function (iterator) { | |
258 var result; | |
259 this.each(function(value, index) { | |
260 if (iterator(value, index)) { | |
261 result = value; | |
262 throw $break; | |
263 } | |
264 }); | |
265 return result; | |
266 }, | |
267 | |
268 findAll: function(iterator) { | |
269 var results = []; | |
270 this.each(function(value, index) { | |
271 if (iterator(value, index)) | |
272 results.push(value); | |
273 }); | |
274 return results; | |
275 }, | |
276 | |
277 grep: function(pattern, iterator) { | |
278 var results = []; | |
279 this.each(function(value, index) { | |
280 var stringValue = value.toString(); | |
281 if (stringValue.match(pattern)) | |
282 results.push((iterator || Prototype.K)(value, index)); | |
283 }) | |
284 return results; | |
285 }, | |
286 | |
287 include: function(object) { | |
288 var found = false; | |
289 this.each(function(value) { | |
290 if (value == object) { | |
291 found = true; | |
292 throw $break; | |
293 } | |
294 }); | |
295 return found; | |
296 }, | |
297 | |
298 inject: function(memo, iterator) { | |
299 this.each(function(value, index) { | |
300 memo = iterator(memo, value, index); | |
301 }); | |
302 return memo; | |
303 }, | |
304 | |
305 invoke: function(method) { | |
306 var args = $A(arguments).slice(1); | |
307 return this.collect(function(value) { | |
308 return value[method].apply(value, args); | |
309 }); | |
310 }, | |
311 | |
312 max: function(iterator) { | |
313 var result; | |
314 this.each(function(value, index) { | |
315 value = (iterator || Prototype.K)(value, index); | |
316 if (value >= (result || value)) | |
317 result = value; | |
318 }); | |
319 return result; | |
320 }, | |
321 | |
322 min: function(iterator) { | |
323 var result; | |
324 this.each(function(value, index) { | |
325 value = (iterator || Prototype.K)(value, index); | |
326 if (value <= (result || value)) | |
327 result = value; | |
328 }); | |
329 return result; | |
330 }, | |
331 | |
332 partition: function(iterator) { | |
333 var trues = [], falses = []; | |
334 this.each(function(value, index) { | |
335 ((iterator || Prototype.K)(value, index) ? | |
336 trues : falses).push(value); | |
337 }); | |
338 return [trues, falses]; | |
339 }, | |
340 | |
341 pluck: function(property) { | |
342 var results = []; | |
343 this.each(function(value, index) { | |
344 results.push(value[property]); | |
345 }); | |
346 return results; | |
347 }, | |
348 | |
349 reject: function(iterator) { | |
350 var results = []; | |
351 this.each(function(value, index) { | |
352 if (!iterator(value, index)) | |
353 results.push(value); | |
354 }); | |
355 return results; | |
356 }, | |
357 | |
358 sortBy: function(iterator) { | |
359 return this.collect(function(value, index) { | |
360 return {value: value, criteria: iterator(value, index)}; | |
361 }).sort(function(left, right) { | |
362 var a = left.criteria, b = right.criteria; | |
363 return a < b ? -1 : a > b ? 1 : 0; | |
364 }).pluck('value'); | |
365 }, | |
366 | |
367 toArray: function() { | |
368 return this.collect(Prototype.K); | |
369 }, | |
370 | |
371 zip: function() { | |
372 var iterator = Prototype.K, args = $A(arguments); | |
373 if (typeof args.last() == 'function') | |
374 iterator = args.pop(); | |
375 | |
376 var collections = [this].concat(args).map($A); | |
377 return this.map(function(value, index) { | |
378 iterator(value = collections.pluck(index)); | |
379 return value; | |
380 }); | |
381 }, | |
382 | |
383 inspect: function() { | |
384 return '#<Enumerable:' + this.toArray().inspect() + '>'; | |
385 } | |
386 } | |
387 | |
388 Object.extend(Enumerable, { | |
389 map: Enumerable.collect, | |
390 find: Enumerable.detect, | |
391 select: Enumerable.findAll, | |
392 member: Enumerable.include, | |
393 entries: Enumerable.toArray | |
394 }); | |
395 var $A = Array.from = function(iterable) { | |
396 if (!iterable) return []; | |
397 if (iterable.toArray) { | |
398 return iterable.toArray(); | |
399 } else { | |
400 var results = []; | |
401 for (var i = 0; i < iterable.length; i++) | |
402 results.push(iterable[i]); | |
403 return results; | |
404 } | |
405 } | |
406 | |
407 Object.extend(Array.prototype, Enumerable); | |
408 | |
409 Array.prototype._reverse = Array.prototype.reverse; | |
410 | |
411 Object.extend(Array.prototype, { | |
412 _each: function(iterator) { | |
413 for (var i = 0; i < this.length; i++) | |
414 iterator(this[i]); | |
415 }, | |
416 | |
417 clear: function() { | |
418 this.length = 0; | |
419 return this; | |
420 }, | |
421 | |
422 first: function() { | |
423 return this[0]; | |
424 }, | |
425 | |
426 last: function() { | |
427 return this[this.length - 1]; | |
428 }, | |
429 | |
430 compact: function() { | |
431 return this.select(function(value) { | |
432 return value != undefined || value != null; | |
433 }); | |
434 }, | |
435 | |
436 flatten: function() { | |
437 return this.inject([], function(array, value) { | |
438 return array.concat(value.constructor == Array ? | |
439 value.flatten() : [value]); | |
440 }); | |
441 }, | |
442 | |
443 without: function() { | |
444 var values = $A(arguments); | |
445 return this.select(function(value) { | |
446 return !values.include(value); | |
447 }); | |
448 }, | |
449 | |
450 indexOf: function(object) { | |
451 for (var i = 0; i < this.length; i++) | |
452 if (this[i] == object) return i; | |
453 return -1; | |
454 }, | |
455 | |
456 reverse: function(inline) { | |
457 return (inline !== false ? this : this.toArray())._reverse(); | |
458 }, | |
459 | |
460 shift: function() { | |
461 var result = this[0]; | |
462 for (var i = 0; i < this.length - 1; i++) | |
463 this[i] = this[i + 1]; | |
464 this.length--; | |
465 return result; | |
466 }, | |
467 | |
468 inspect: function() { | |
469 return '[' + this.map(Object.inspect).join(', ') + ']'; | |
470 } | |
471 }); | |
472 var Hash = { | |
473 _each: function(iterator) { | |
474 for (key in this) { | |
475 var value = this[key]; | |
476 if (typeof value == 'function') continue; | |
477 | |
478 var pair = [key, value]; | |
479 pair.key = key; | |
480 pair.value = value; | |
481 iterator(pair); | |
482 } | |
483 }, | |
484 | |
485 keys: function() { | |
486 return this.pluck('key'); | |
487 }, | |
488 | |
489 values: function() { | |
490 return this.pluck('value'); | |
491 }, | |
492 | |
493 merge: function(hash) { | |
494 return $H(hash).inject($H(this), function(mergedHash, pair) { | |
495 mergedHash[pair.key] = pair.value; | |
496 return mergedHash; | |
497 }); | |
498 }, | |
499 | |
500 toQueryString: function() { | |
501 return this.map(function(pair) { | |
502 return pair.map(encodeURIComponent).join('='); | |
503 }).join('&'); | |
504 }, | |
505 | |
506 inspect: function() { | |
507 return '#<Hash:{' + this.map(function(pair) { | |
508 return pair.map(Object.inspect).join(': '); | |
509 }).join(', ') + '}>'; | |
510 } | |
511 } | |
512 | |
513 function $H(object) { | |
514 var hash = Object.extend({}, object || {}); | |
515 Object.extend(hash, Enumerable); | |
516 Object.extend(hash, Hash); | |
517 return hash; | |
518 } | |
519 ObjectRange = Class.create(); | |
520 Object.extend(ObjectRange.prototype, Enumerable); | |
521 Object.extend(ObjectRange.prototype, { | |
522 initialize: function(start, end, exclusive) { | |
523 this.start = start; | |
524 this.end = end; | |
525 this.exclusive = exclusive; | |
526 }, | |
527 | |
528 _each: function(iterator) { | |
529 var value = this.start; | |
530 do { | |
531 iterator(value); | |
532 value = value.succ(); | |
533 } while (this.include(value)); | |
534 }, | |
535 | |
536 include: function(value) { | |
537 if (value < this.start) | |
538 return false; | |
539 if (this.exclusive) | |
540 return value < this.end; | |
541 return value <= this.end; | |
542 } | |
543 }); | |
544 | |
545 var $R = function(start, end, exclusive) { | |
546 return new ObjectRange(start, end, exclusive); | |
547 } | |
548 | |
549 var Ajax = { | |
550 getTransport: function() { | |
551 return Try.these( | |
552 function() {return new ActiveXObject('Msxml2.XMLHTTP')}, | |
553 function() {return new ActiveXObject('Microsoft.XMLHTTP')}, | |
554 function() {return new XMLHttpRequest()} | |
555 ) || false; | |
556 }, | |
557 | |
558 activeRequestCount: 0 | |
559 } | |
560 | |
561 Ajax.Responders = { | |
562 responders: [], | |
563 | |
564 _each: function(iterator) { | |
565 this.responders._each(iterator); | |
566 }, | |
567 | |
568 register: function(responderToAdd) { | |
569 if (!this.include(responderToAdd)) | |
570 this.responders.push(responderToAdd); | |
571 }, | |
572 | |
573 unregister: function(responderToRemove) { | |
574 this.responders = this.responders.without(responderToRemove); | |
575 }, | |
576 | |
577 dispatch: function(callback, request, transport, json) { | |
578 this.each(function(responder) { | |
579 if (responder[callback] && typeof responder[callback] == 'function') { | |
580 try { | |
581 responder[callback].apply(responder, [request, transport, json]); | |
582 } catch (e) {} | |
583 } | |
584 }); | |
585 } | |
586 }; | |
587 | |
588 Object.extend(Ajax.Responders, Enumerable); | |
589 | |
590 Ajax.Responders.register({ | |
591 onCreate: function() { | |
592 Ajax.activeRequestCount++; | |
593 }, | |
594 | |
595 onComplete: function() { | |
596 Ajax.activeRequestCount--; | |
597 } | |
598 }); | |
599 | |
600 Ajax.Base = function() {}; | |
601 Ajax.Base.prototype = { | |
602 setOptions: function(options) { | |
603 this.options = { | |
604 method: 'post', | |
605 asynchronous: true, | |
606 parameters: '' | |
607 } | |
608 Object.extend(this.options, options || {}); | |
609 }, | |
610 | |
611 responseIsSuccess: function() { | |
612 return this.transport.status == undefined | |
613 || this.transport.status == 0 | |
614 || (this.transport.status >= 200 && this.transport.status < 300); | |
615 }, | |
616 | |
617 responseIsFailure: function() { | |
618 return !this.responseIsSuccess(); | |
619 } | |
620 } | |
621 | |
622 Ajax.Request = Class.create(); | |
623 Ajax.Request.Events = | |
624 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; | |
625 | |
626 Ajax.Request.prototype = Object.extend(new Ajax.Base(), { | |
627 initialize: function(url, options) { | |
628 this.transport = Ajax.getTransport(); | |
629 this.setOptions(options); | |
630 this.request(url); | |
631 }, | |
632 | |
633 request: function(url) { | |
634 var parameters = this.options.parameters || ''; | |
635 if (parameters.length > 0) parameters += '&_='; | |
636 | |
637 try { | |
638 this.url = url; | |
639 if (this.options.method == 'get' && parameters.length > 0) | |
640 this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; | |
641 | |
642 Ajax.Responders.dispatch('onCreate', this, this.transport); | |
643 | |
644 this.transport.open(this.options.method, this.url, | |
645 this.options.asynchronous); | |
646 | |
647 if (this.options.asynchronous) { | |
648 this.transport.onreadystatechange = this.onStateChange.bind(this); | |
649 setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); | |
650 } | |
651 | |
652 this.setRequestHeaders(); | |
653 | |
654 var body = this.options.postBody ? this.options.postBody : parameters; | |
655 this.transport.send(this.options.method == 'post' ? body : null); | |
656 | |
657 } catch (e) { | |
658 this.dispatchException(e); | |
659 } | |
660 }, | |
661 | |
662 setRequestHeaders: function() { | |
663 var requestHeaders = | |
664 ['X-Requested-With', 'XMLHttpRequest', | |
665 'X-Prototype-Version', Prototype.Version]; | |
666 | |
667 if (this.options.method == 'post') { | |
668 requestHeaders.push('Content-type', | |
669 'application/x-www-form-urlencoded'); | |
670 | |
671 /* Force "Connection: close" for Mozilla browsers to work around | |
672 * a bug where XMLHttpReqeuest sends an incorrect Content-length | |
673 * header. See Mozilla Bugzilla #246651. | |
674 */ | |
675 if (this.transport.overrideMimeType) | |
676 requestHeaders.push('Connection', 'close'); | |
677 } | |
678 | |
679 if (this.options.requestHeaders) | |
680 requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); | |
681 | |
682 for (var i = 0; i < requestHeaders.length; i += 2) | |
683 this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); | |
684 }, | |
685 | |
686 onStateChange: function() { | |
687 var readyState = this.transport.readyState; | |
688 if (readyState != 1) | |
689 this.respondToReadyState(this.transport.readyState); | |
690 }, | |
691 | |
692 header: function(name) { | |
693 try { | |
694 return this.transport.getResponseHeader(name); | |
695 } catch (e) {} | |
696 }, | |
697 | |
698 evalJSON: function() { | |
699 try { | |
700 return eval(this.header('X-JSON')); | |
701 } catch (e) {} | |
702 }, | |
703 | |
704 evalResponse: function() { | |
705 try { | |
706 return eval(this.transport.responseText); | |
707 } catch (e) { | |
708 this.dispatchException(e); | |
709 } | |
710 }, | |
711 | |
712 respondToReadyState: function(readyState) { | |
713 var event = Ajax.Request.Events[readyState]; | |
714 var transport = this.transport, json = this.evalJSON(); | |
715 | |
716 if (event == 'Complete') { | |
717 try { | |
718 (this.options['on' + this.transport.status] | |
719 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] | |
720 || Prototype.emptyFunction)(transport, json); | |
721 } catch (e) { | |
722 this.dispatchException(e); | |
723 } | |
724 | |
725 if ((this.header('Content-type') || '').match(/^text\/javascript/i)) | |
726 this.evalResponse(); | |
727 } | |
728 | |
729 try { | |
730 (this.options['on' + event] || Prototype.emptyFunction)(transport, json); | |
731 Ajax.Responders.dispatch('on' + event, this, transport, json); | |
732 } catch (e) { | |
733 this.dispatchException(e); | |
734 } | |
735 | |
736 /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ | |
737 if (event == 'Complete') | |
738 this.transport.onreadystatechange = Prototype.emptyFunction; | |
739 }, | |
740 | |
741 dispatchException: function(exception) { | |
742 (this.options.onException || Prototype.emptyFunction)(this, exception); | |
743 Ajax.Responders.dispatch('onException', this, exception); | |
744 } | |
745 }); | |
746 | |
747 Ajax.Updater = Class.create(); | |
748 | |
749 Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { | |
750 initialize: function(container, url, options) { | |
751 this.containers = { | |
752 success: container.success ? $(container.success) : $(container), | |
753 failure: container.failure ? $(container.failure) : | |
754 (container.success ? null : $(container)) | |
755 } | |
756 | |
757 this.transport = Ajax.getTransport(); | |
758 this.setOptions(options); | |
759 | |
760 var onComplete = this.options.onComplete || Prototype.emptyFunction; | |
761 this.options.onComplete = (function(transport, object) { | |
762 this.updateContent(); | |
763 onComplete(transport, object); | |
764 }).bind(this); | |
765 | |
766 this.request(url); | |
767 }, | |
768 | |
769 updateContent: function() { | |
770 var receiver = this.responseIsSuccess() ? | |
771 this.containers.success : this.containers.failure; | |
772 var response = this.transport.responseText; | |
773 | |
774 if (!this.options.evalScripts) | |
775 response = response.stripScripts(); | |
776 | |
777 if (receiver) { | |
778 if (this.options.insertion) { | |
779 new this.options.insertion(receiver, response); | |
780 } else { | |
781 Element.update(receiver, response); | |
782 } | |
783 } | |
784 | |
785 if (this.responseIsSuccess()) { | |
786 if (this.onComplete) | |
787 setTimeout(this.onComplete.bind(this), 10); | |
788 } | |
789 } | |
790 }); | |
791 | |
792 Ajax.PeriodicalUpdater = Class.create(); | |
793 Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { | |
794 initialize: function(container, url, options) { | |
795 this.setOptions(options); | |
796 this.onComplete = this.options.onComplete; | |
797 | |
798 this.frequency = (this.options.frequency || 2); | |
799 this.decay = (this.options.decay || 1); | |
800 | |
801 this.updater = {}; | |
802 this.container = container; | |
803 this.url = url; | |
804 | |
805 this.start(); | |
806 }, | |
807 | |
808 start: function() { | |
809 this.options.onComplete = this.updateComplete.bind(this); | |
810 this.onTimerEvent(); | |
811 }, | |
812 | |
813 stop: function() { | |
814 this.updater.onComplete = undefined; | |
815 clearTimeout(this.timer); | |
816 (this.onComplete || Prototype.emptyFunction).apply(this, arguments); | |
817 }, | |
818 | |
819 updateComplete: function(request) { | |
820 if (this.options.decay) { | |
821 this.decay = (request.responseText == this.lastText ? | |
822 this.decay * this.options.decay : 1); | |
823 | |
824 this.lastText = request.responseText; | |
825 } | |
826 this.timer = setTimeout(this.onTimerEvent.bind(this), | |
827 this.decay * this.frequency * 1000); | |
828 }, | |
829 | |
830 onTimerEvent: function() { | |
831 this.updater = new Ajax.Updater(this.container, this.url, this.options); | |
832 } | |
833 }); | |
834 document.getElementsByClassName = function(className, parentElement) { | |
835 var children = ($(parentElement) || document.body).getElementsByTagName('*'); | |
836 return $A(children).inject([], function(elements, child) { | |
837 if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) | |
838 elements.push(child); | |
839 return elements; | |
840 }); | |
841 } | |
842 | |
843 /*--------------------------------------------------------------------------*/ | |
844 | |
845 if (!window.Element) { | |
846 var Element = new Object(); | |
847 } | |
848 | |
849 Object.extend(Element, { | |
850 visible: function(element) { | |
851 return $(element).style.display != 'none'; | |
852 }, | |
853 | |
854 toggle: function() { | |
855 for (var i = 0; i < arguments.length; i++) { | |
856 var element = $(arguments[i]); | |
857 Element[Element.visible(element) ? 'hide' : 'show'](element); | |
858 } | |
859 }, | |
860 | |
861 hide: function() { | |
862 for (var i = 0; i < arguments.length; i++) { | |
863 var element = $(arguments[i]); | |
864 element.style.display = 'none'; | |
865 } | |
866 }, | |
867 | |
868 show: function() { | |
869 for (var i = 0; i < arguments.length; i++) { | |
870 var element = $(arguments[i]); | |
871 element.style.display = ''; | |
872 } | |
873 }, | |
874 | |
875 remove: function(element) { | |
876 element = $(element); | |
877 element.parentNode.removeChild(element); | |
878 }, | |
879 | |
880 update: function(element, html) { | |
881 $(element).innerHTML = html.stripScripts(); | |
882 setTimeout(function() {html.evalScripts()}, 10); | |
883 }, | |
884 | |
885 getHeight: function(element) { | |
886 element = $(element); | |
887 return element.offsetHeight; | |
888 }, | |
889 | |
890 classNames: function(element) { | |
891 return new Element.ClassNames(element); | |
892 }, | |
893 | |
894 hasClassName: function(element, className) { | |
895 if (!(element = $(element))) return; | |
896 return Element.classNames(element).include(className); | |
897 }, | |
898 | |
899 addClassName: function(element, className) { | |
900 if (!(element = $(element))) return; | |
901 return Element.classNames(element).add(className); | |
902 }, | |
903 | |
904 removeClassName: function(element, className) { | |
905 if (!(element = $(element))) return; | |
906 return Element.classNames(element).remove(className); | |
907 }, | |
908 | |
909 // removes whitespace-only text node children | |
910 cleanWhitespace: function(element) { | |
911 element = $(element); | |
912 for (var i = 0; i < element.childNodes.length; i++) { | |
913 var node = element.childNodes[i]; | |
914 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) | |
915 Element.remove(node); | |
916 } | |
917 }, | |
918 | |
919 empty: function(element) { | |
920 return $(element).innerHTML.match(/^\s*$/); | |
921 }, | |
922 | |
923 scrollTo: function(element) { | |
924 element = $(element); | |
925 var x = element.x ? element.x : element.offsetLeft, | |
926 y = element.y ? element.y : element.offsetTop; | |
927 window.scrollTo(x, y); | |
928 }, | |
929 | |
930 getStyle: function(element, style) { | |
931 element = $(element); | |
932 var value = element.style[style.camelize()]; | |
933 if (!value) { | |
934 if (document.defaultView && document.defaultView.getComputedStyle) { | |
935 var css = document.defaultView.getComputedStyle(element, null); | |
936 value = css ? css.getPropertyValue(style) : null; | |
937 } else if (element.currentStyle) { | |
938 value = element.currentStyle[style.camelize()]; | |
939 } | |
940 } | |
941 | |
942 if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) | |
943 if (Element.getStyle(element, 'position') == 'static') value = 'auto'; | |
944 | |
945 return value == 'auto' ? null : value; | |
946 }, | |
947 | |
948 setStyle: function(element, style) { | |
949 element = $(element); | |
950 for (name in style) | |
951 element.style[name.camelize()] = style[name]; | |
952 }, | |
953 | |
954 getDimensions: function(element) { | |
955 element = $(element); | |
956 if (Element.getStyle(element, 'display') != 'none') | |
957 return {width: element.offsetWidth, height: element.offsetHeight}; | |
958 | |
959 // All *Width and *Height properties give 0 on elements with display none, | |
960 // so enable the element temporarily | |
961 var els = element.style; | |
962 var originalVisibility = els.visibility; | |
963 var originalPosition = els.position; | |
964 els.visibility = 'hidden'; | |
965 els.position = 'absolute'; | |
966 els.display = ''; | |
967 var originalWidth = element.clientWidth; | |
968 var originalHeight = element.clientHeight; | |
969 els.display = 'none'; | |
970 els.position = originalPosition; | |
971 els.visibility = originalVisibility; | |
972 return {width: originalWidth, height: originalHeight}; | |
973 }, | |
974 | |
975 makePositioned: function(element) { | |
976 element = $(element); | |
977 var pos = Element.getStyle(element, 'position'); | |
978 if (pos == 'static' || !pos) { | |
979 element._madePositioned = true; | |
980 element.style.position = 'relative'; | |
981 // Opera returns the offset relative to the positioning context, when an | |
982 // element is position relative but top and left have not been defined | |
983 if (window.opera) { | |
984 element.style.top = 0; | |
985 element.style.left = 0; | |
986 } | |
987 } | |
988 }, | |
989 | |
990 undoPositioned: function(element) { | |
991 element = $(element); | |
992 if (element._madePositioned) { | |
993 element._madePositioned = undefined; | |
994 element.style.position = | |
995 element.style.top = | |
996 element.style.left = | |
997 element.style.bottom = | |
998 element.style.right = ''; | |
999 } | |
1000 }, | |
1001 | |
1002 makeClipping: function(element) { | |
1003 element = $(element); | |
1004 if (element._overflow) return; | |
1005 element._overflow = element.style.overflow; | |
1006 if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') | |
1007 element.style.overflow = 'hidden'; | |
1008 }, | |
1009 | |
1010 undoClipping: function(element) { | |
1011 element = $(element); | |
1012 if (element._overflow) return; | |
1013 element.style.overflow = element._overflow; | |
1014 element._overflow = undefined; | |
1015 } | |
1016 }); | |
1017 | |
1018 var Toggle = new Object(); | |
1019 Toggle.display = Element.toggle; | |
1020 | |
1021 /*--------------------------------------------------------------------------*/ | |
1022 | |
1023 Abstract.Insertion = function(adjacency) { | |
1024 this.adjacency = adjacency; | |
1025 } | |
1026 | |
1027 Abstract.Insertion.prototype = { | |
1028 initialize: function(element, content) { | |
1029 this.element = $(element); | |
1030 this.content = content.stripScripts(); | |
1031 | |
1032 if (this.adjacency && this.element.insertAdjacentHTML) { | |
1033 try { | |
1034 this.element.insertAdjacentHTML(this.adjacency, this.content); | |
1035 } catch (e) { | |
1036 if (this.element.tagName.toLowerCase() == 'tbody') { | |
1037 this.insertContent(this.contentFromAnonymousTable()); | |
1038 } else { | |
1039 throw e; | |
1040 } | |
1041 } | |
1042 } else { | |
1043 this.range = this.element.ownerDocument.createRange(); | |
1044 if (this.initializeRange) this.initializeRange(); | |
1045 this.insertContent([this.range.createContextualFragment(this.content)]); | |
1046 } | |
1047 | |
1048 setTimeout(function() {content.evalScripts()}, 10); | |
1049 }, | |
1050 | |
1051 contentFromAnonymousTable: function() { | |
1052 var div = document.createElement('div'); | |
1053 div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; | |
1054 return $A(div.childNodes[0].childNodes[0].childNodes); | |
1055 } | |
1056 } | |
1057 | |
1058 var Insertion = new Object(); | |
1059 | |
1060 Insertion.Before = Class.create(); | |
1061 Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { | |
1062 initializeRange: function() { | |
1063 this.range.setStartBefore(this.element); | |
1064 }, | |
1065 | |
1066 insertContent: function(fragments) { | |
1067 fragments.each((function(fragment) { | |
1068 this.element.parentNode.insertBefore(fragment, this.element); | |
1069 }).bind(this)); | |
1070 } | |
1071 }); | |
1072 | |
1073 Insertion.Top = Class.create(); | |
1074 Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { | |
1075 initializeRange: function() { | |
1076 this.range.selectNodeContents(this.element); | |
1077 this.range.collapse(true); | |
1078 }, | |
1079 | |
1080 insertContent: function(fragments) { | |
1081 fragments.reverse(false).each((function(fragment) { | |
1082 this.element.insertBefore(fragment, this.element.firstChild); | |
1083 }).bind(this)); | |
1084 } | |
1085 }); | |
1086 | |
1087 Insertion.Bottom = Class.create(); | |
1088 Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { | |
1089 initializeRange: function() { | |
1090 this.range.selectNodeContents(this.element); | |
1091 this.range.collapse(this.element); | |
1092 }, | |
1093 | |
1094 insertContent: function(fragments) { | |
1095 fragments.each((function(fragment) { | |
1096 this.element.appendChild(fragment); | |
1097 }).bind(this)); | |
1098 } | |
1099 }); | |
1100 | |
1101 Insertion.After = Class.create(); | |
1102 Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { | |
1103 initializeRange: function() { | |
1104 this.range.setStartAfter(this.element); | |
1105 }, | |
1106 | |
1107 insertContent: function(fragments) { | |
1108 fragments.each((function(fragment) { | |
1109 this.element.parentNode.insertBefore(fragment, | |
1110 this.element.nextSibling); | |
1111 }).bind(this)); | |
1112 } | |
1113 }); | |
1114 | |
1115 /*--------------------------------------------------------------------------*/ | |
1116 | |
1117 Element.ClassNames = Class.create(); | |
1118 Element.ClassNames.prototype = { | |
1119 initialize: function(element) { | |
1120 this.element = $(element); | |
1121 }, | |
1122 | |
1123 _each: function(iterator) { | |
1124 this.element.className.split(/\s+/).select(function(name) { | |
1125 return name.length > 0; | |
1126 })._each(iterator); | |
1127 }, | |
1128 | |
1129 set: function(className) { | |
1130 this.element.className = className; | |
1131 }, | |
1132 | |
1133 add: function(classNameToAdd) { | |
1134 if (this.include(classNameToAdd)) return; | |
1135 this.set(this.toArray().concat(classNameToAdd).join(' ')); | |
1136 }, | |
1137 | |
1138 remove: function(classNameToRemove) { | |
1139 if (!this.include(classNameToRemove)) return; | |
1140 this.set(this.select(function(className) { | |
1141 return className != classNameToRemove; | |
1142 }).join(' ')); | |
1143 }, | |
1144 | |
1145 toString: function() { | |
1146 return this.toArray().join(' '); | |
1147 } | |
1148 } | |
1149 | |
1150 Object.extend(Element.ClassNames.prototype, Enumerable); | |
1151 var Field = { | |
1152 clear: function() { | |
1153 for (var i = 0; i < arguments.length; i++) | |
1154 $(arguments[i]).value = ''; | |
1155 }, | |
1156 | |
1157 focus: function(element) { | |
1158 $(element).focus(); | |
1159 }, | |
1160 | |
1161 present: function() { | |
1162 for (var i = 0; i < arguments.length; i++) | |
1163 if ($(arguments[i]).value == '') return false; | |
1164 return true; | |
1165 }, | |
1166 | |
1167 select: function(element) { | |
1168 $(element).select(); | |
1169 }, | |
1170 | |
1171 activate: function(element) { | |
1172 element = $(element); | |
1173 element.focus(); | |
1174 if (element.select) | |
1175 element.select(); | |
1176 } | |
1177 } | |
1178 | |
1179 /*--------------------------------------------------------------------------*/ | |
1180 | |
1181 var Form = { | |
1182 serialize: function(form) { | |
1183 var elements = Form.getElements($(form)); | |
1184 var queryComponents = new Array(); | |
1185 | |
1186 for (var i = 0; i < elements.length; i++) { | |
1187 var queryComponent = Form.Element.serialize(elements[i]); | |
1188 if (queryComponent) | |
1189 queryComponents.push(queryComponent); | |
1190 } | |
1191 | |
1192 return queryComponents.join('&'); | |
1193 }, | |
1194 | |
1195 getElements: function(form) { | |
1196 form = $(form); | |
1197 var elements = new Array(); | |
1198 | |
1199 for (tagName in Form.Element.Serializers) { | |
1200 var tagElements = form.getElementsByTagName(tagName); | |
1201 for (var j = 0; j < tagElements.length; j++) | |
1202 elements.push(tagElements[j]); | |
1203 } | |
1204 return elements; | |
1205 }, | |
1206 | |
1207 getInputs: function(form, typeName, name) { | |
1208 form = $(form); | |
1209 var inputs = form.getElementsByTagName('input'); | |
1210 | |
1211 if (!typeName && !name) | |
1212 return inputs; | |
1213 | |
1214 var matchingInputs = new Array(); | |
1215 for (var i = 0; i < inputs.length; i++) { | |
1216 var input = inputs[i]; | |
1217 if ((typeName && input.type != typeName) || | |
1218 (name && input.name != name)) | |
1219 continue; | |
1220 matchingInputs.push(input); | |
1221 } | |
1222 | |
1223 return matchingInputs; | |
1224 }, | |
1225 | |
1226 disable: function(form) { | |
1227 var elements = Form.getElements(form); | |
1228 for (var i = 0; i < elements.length; i++) { | |
1229 var element = elements[i]; | |
1230 element.blur(); | |
1231 element.disabled = 'true'; | |
1232 } | |
1233 }, | |
1234 | |
1235 enable: function(form) { | |
1236 var elements = Form.getElements(form); | |
1237 for (var i = 0; i < elements.length; i++) { | |
1238 var element = elements[i]; | |
1239 element.disabled = ''; | |
1240 } | |
1241 }, | |
1242 | |
1243 findFirstElement: function(form) { | |
1244 return Form.getElements(form).find(function(element) { | |
1245 return element.type != 'hidden' && !element.disabled && | |
1246 ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); | |
1247 }); | |
1248 }, | |
1249 | |
1250 focusFirstElement: function(form) { | |
1251 Field.activate(Form.findFirstElement(form)); | |
1252 }, | |
1253 | |
1254 reset: function(form) { | |
1255 $(form).reset(); | |
1256 } | |
1257 } | |
1258 | |
1259 Form.Element = { | |
1260 serialize: function(element) { | |
1261 element = $(element); | |
1262 var method = element.tagName.toLowerCase(); | |
1263 var parameter = Form.Element.Serializers[method](element); | |
1264 | |
1265 if (parameter) { | |
1266 var key = encodeURIComponent(parameter[0]); | |
1267 if (key.length == 0) return; | |
1268 | |
1269 if (parameter[1].constructor != Array) | |
1270 parameter[1] = [parameter[1]]; | |
1271 | |
1272 return parameter[1].map(function(value) { | |
1273 return key + '=' + encodeURIComponent(value); | |
1274 }).join('&'); | |
1275 } | |
1276 }, | |
1277 | |
1278 getValue: function(element) { | |
1279 element = $(element); | |
1280 var method = element.tagName.toLowerCase(); | |
1281 var parameter = Form.Element.Serializers[method](element); | |
1282 | |
1283 if (parameter) | |
1284 return parameter[1]; | |
1285 } | |
1286 } | |
1287 | |
1288 Form.Element.Serializers = { | |
1289 input: function(element) { | |
1290 switch (element.type.toLowerCase()) { | |
1291 case 'submit': | |
1292 case 'hidden': | |
1293 case 'password': | |
1294 case 'text': | |
1295 return Form.Element.Serializers.textarea(element); | |
1296 case 'checkbox': | |
1297 case 'radio': | |
1298 return Form.Element.Serializers.inputSelector(element); | |
1299 } | |
1300 return false; | |
1301 }, | |
1302 | |
1303 inputSelector: function(element) { | |
1304 if (element.checked) | |
1305 return [element.name, element.value]; | |
1306 }, | |
1307 | |
1308 textarea: function(element) { | |
1309 return [element.name, element.value]; | |
1310 }, | |
1311 | |
1312 select: function(element) { | |
1313 return Form.Element.Serializers[element.type == 'select-one' ? | |
1314 'selectOne' : 'selectMany'](element); | |
1315 }, | |
1316 | |
1317 selectOne: function(element) { | |
1318 var value = '', opt, index = element.selectedIndex; | |
1319 if (index >= 0) { | |
1320 opt = element.options[index]; | |
1321 value = opt.value; | |
1322 if (!value && !('value' in opt)) | |
1323 value = opt.text; | |
1324 } | |
1325 return [element.name, value]; | |
1326 }, | |
1327 | |
1328 selectMany: function(element) { | |
1329 var value = new Array(); | |
1330 for (var i = 0; i < element.length; i++) { | |
1331 var opt = element.options[i]; | |
1332 if (opt.selected) { | |
1333 var optValue = opt.value; | |
1334 if (!optValue && !('value' in opt)) | |
1335 optValue = opt.text; | |
1336 value.push(optValue); | |
1337 } | |
1338 } | |
1339 return [element.name, value]; | |
1340 } | |
1341 } | |
1342 | |
1343 /*--------------------------------------------------------------------------*/ | |
1344 | |
1345 var $F = Form.Element.getValue; | |
1346 | |
1347 /*--------------------------------------------------------------------------*/ | |
1348 | |
1349 Abstract.TimedObserver = function() {} | |
1350 Abstract.TimedObserver.prototype = { | |
1351 initialize: function(element, frequency, callback) { | |
1352 this.frequency = frequency; | |
1353 this.element = $(element); | |
1354 this.callback = callback; | |
1355 | |
1356 this.lastValue = this.getValue(); | |
1357 this.registerCallback(); | |
1358 }, | |
1359 | |
1360 registerCallback: function() { | |
1361 setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); | |
1362 }, | |
1363 | |
1364 onTimerEvent: function() { | |
1365 var value = this.getValue(); | |
1366 if (this.lastValue != value) { | |
1367 this.callback(this.element, value); | |
1368 this.lastValue = value; | |
1369 } | |
1370 } | |
1371 } | |
1372 | |
1373 Form.Element.Observer = Class.create(); | |
1374 Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | |
1375 getValue: function() { | |
1376 return Form.Element.getValue(this.element); | |
1377 } | |
1378 }); | |
1379 | |
1380 Form.Observer = Class.create(); | |
1381 Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { | |
1382 getValue: function() { | |
1383 return Form.serialize(this.element); | |
1384 } | |
1385 }); | |
1386 | |
1387 /*--------------------------------------------------------------------------*/ | |
1388 | |
1389 Abstract.EventObserver = function() {} | |
1390 Abstract.EventObserver.prototype = { | |
1391 initialize: function(element, callback) { | |
1392 this.element = $(element); | |
1393 this.callback = callback; | |
1394 | |
1395 this.lastValue = this.getValue(); | |
1396 if (this.element.tagName.toLowerCase() == 'form') | |
1397 this.registerFormCallbacks(); | |
1398 else | |
1399 this.registerCallback(this.element); | |
1400 }, | |
1401 | |
1402 onElementEvent: function() { | |
1403 var value = this.getValue(); | |
1404 if (this.lastValue != value) { | |
1405 this.callback(this.element, value); | |
1406 this.lastValue = value; | |
1407 } | |
1408 }, | |
1409 | |
1410 registerFormCallbacks: function() { | |
1411 var elements = Form.getElements(this.element); | |
1412 for (var i = 0; i < elements.length; i++) | |
1413 this.registerCallback(elements[i]); | |
1414 }, | |
1415 | |
1416 registerCallback: function(element) { | |
1417 if (element.type) { | |
1418 switch (element.type.toLowerCase()) { | |
1419 case 'checkbox': | |
1420 case 'radio': | |
1421 Event.observe(element, 'click', this.onElementEvent.bind(this)); | |
1422 break; | |
1423 case 'password': | |
1424 case 'text': | |
1425 case 'textarea': | |
1426 case 'select-one': | |
1427 case 'select-multiple': | |
1428 Event.observe(element, 'change', this.onElementEvent.bind(this)); | |
1429 break; | |
1430 } | |
1431 } | |
1432 } | |
1433 } | |
1434 | |
1435 Form.Element.EventObserver = Class.create(); | |
1436 Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | |
1437 getValue: function() { | |
1438 return Form.Element.getValue(this.element); | |
1439 } | |
1440 }); | |
1441 | |
1442 Form.EventObserver = Class.create(); | |
1443 Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { | |
1444 getValue: function() { | |
1445 return Form.serialize(this.element); | |
1446 } | |
1447 }); | |
1448 if (!window.Event) { | |
1449 var Event = new Object(); | |
1450 } | |
1451 | |
1452 Object.extend(Event, { | |
1453 KEY_BACKSPACE: 8, | |
1454 KEY_TAB: 9, | |
1455 KEY_RETURN: 13, | |
1456 KEY_ESC: 27, | |
1457 KEY_LEFT: 37, | |
1458 KEY_UP: 38, | |
1459 KEY_RIGHT: 39, | |
1460 KEY_DOWN: 40, | |
1461 KEY_DELETE: 46, | |
1462 | |
1463 element: function(event) { | |
1464 return event.target || event.srcElement; | |
1465 }, | |
1466 | |
1467 isLeftClick: function(event) { | |
1468 return (((event.which) && (event.which == 1)) || | |
1469 ((event.button) && (event.button == 1))); | |
1470 }, | |
1471 | |
1472 pointerX: function(event) { | |
1473 return event.pageX || (event.clientX + | |
1474 (document.documentElement.scrollLeft || document.body.scrollLeft)); | |
1475 }, | |
1476 | |
1477 pointerY: function(event) { | |
1478 return event.pageY || (event.clientY + | |
1479 (document.documentElement.scrollTop || document.body.scrollTop)); | |
1480 }, | |
1481 | |
1482 stop: function(event) { | |
1483 if (event.preventDefault) { | |
1484 event.preventDefault(); | |
1485 event.stopPropagation(); | |
1486 } else { | |
1487 event.returnValue = false; | |
1488 event.cancelBubble = true; | |
1489 } | |
1490 }, | |
1491 | |
1492 // find the first node with the given tagName, starting from the | |
1493 // node the event was triggered on; traverses the DOM upwards | |
1494 findElement: function(event, tagName) { | |
1495 var element = Event.element(event); | |
1496 while (element.parentNode && (!element.tagName || | |
1497 (element.tagName.toUpperCase() != tagName.toUpperCase()))) | |
1498 element = element.parentNode; | |
1499 return element; | |
1500 }, | |
1501 | |
1502 observers: false, | |
1503 | |
1504 _observeAndCache: function(element, name, observer, useCapture) { | |
1505 if (!this.observers) this.observers = []; | |
1506 if (element.addEventListener) { | |
1507 this.observers.push([element, name, observer, useCapture]); | |
1508 element.addEventListener(name, observer, useCapture); | |
1509 } else if (element.attachEvent) { | |
1510 this.observers.push([element, name, observer, useCapture]); | |
1511 element.attachEvent('on' + name, observer); | |
1512 } | |
1513 }, | |
1514 | |
1515 unloadCache: function() { | |
1516 if (!Event.observers) return; | |
1517 for (var i = 0; i < Event.observers.length; i++) { | |
1518 Event.stopObserving.apply(this, Event.observers[i]); | |
1519 Event.observers[i][0] = null; | |
1520 } | |
1521 Event.observers = false; | |
1522 }, | |
1523 | |
1524 observe: function(element, name, observer, useCapture) { | |
1525 var element = $(element); | |
1526 useCapture = useCapture || false; | |
1527 | |
1528 if (name == 'keypress' && | |
1529 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | |
1530 || element.attachEvent)) | |
1531 name = 'keydown'; | |
1532 | |
1533 this._observeAndCache(element, name, observer, useCapture); | |
1534 }, | |
1535 | |
1536 stopObserving: function(element, name, observer, useCapture) { | |
1537 var element = $(element); | |
1538 useCapture = useCapture || false; | |
1539 | |
1540 if (name == 'keypress' && | |
1541 (navigator.appVersion.match(/Konqueror|Safari|KHTML/) | |
1542 || element.detachEvent)) | |
1543 name = 'keydown'; | |
1544 | |
1545 if (element.removeEventListener) { | |
1546 element.removeEventListener(name, observer, useCapture); | |
1547 } else if (element.detachEvent) { | |
1548 element.detachEvent('on' + name, observer); | |
1549 } | |
1550 } | |
1551 }); | |
1552 | |
1553 /* prevent memory leaks in IE */ | |
1554 Event.observe(window, 'unload', Event.unloadCache, false); | |
1555 var Position = { | |
1556 // set to true if needed, warning: firefox performance problems | |
1557 // NOT neeeded for page scrolling, only if draggable contained in | |
1558 // scrollable elements | |
1559 includeScrollOffsets: false, | |
1560 | |
1561 // must be called before calling withinIncludingScrolloffset, every time the | |
1562 // page is scrolled | |
1563 prepare: function() { | |
1564 this.deltaX = window.pageXOffset | |
1565 || document.documentElement.scrollLeft | |
1566 || document.body.scrollLeft | |
1567 || 0; | |
1568 this.deltaY = window.pageYOffset | |
1569 || document.documentElement.scrollTop | |
1570 || document.body.scrollTop | |
1571 || 0; | |
1572 }, | |
1573 | |
1574 realOffset: function(element) { | |
1575 var valueT = 0, valueL = 0; | |
1576 do { | |
1577 valueT += element.scrollTop || 0; | |
1578 valueL += element.scrollLeft || 0; | |
1579 element = element.parentNode; | |
1580 } while (element); | |
1581 return [valueL, valueT]; | |
1582 }, | |
1583 | |
1584 cumulativeOffset: function(element) { | |
1585 var valueT = 0, valueL = 0; | |
1586 do { | |
1587 valueT += element.offsetTop || 0; | |
1588 valueL += element.offsetLeft || 0; | |
1589 element = element.offsetParent; | |
1590 } while (element); | |
1591 return [valueL, valueT]; | |
1592 }, | |
1593 | |
1594 positionedOffset: function(element) { | |
1595 var valueT = 0, valueL = 0; | |
1596 do { | |
1597 valueT += element.offsetTop || 0; | |
1598 valueL += element.offsetLeft || 0; | |
1599 element = element.offsetParent; | |
1600 if (element) { | |
1601 p = Element.getStyle(element, 'position'); | |
1602 if (p == 'relative' || p == 'absolute') break; | |
1603 } | |
1604 } while (element); | |
1605 return [valueL, valueT]; | |
1606 }, | |
1607 | |
1608 offsetParent: function(element) { | |
1609 if (element.offsetParent) return element.offsetParent; | |
1610 if (element == document.body) return element; | |
1611 | |
1612 while ((element = element.parentNode) && element != document.body) | |
1613 if (Element.getStyle(element, 'position') != 'static') | |
1614 return element; | |
1615 | |
1616 return document.body; | |
1617 }, | |
1618 | |
1619 // caches x/y coordinate pair to use with overlap | |
1620 within: function(element, x, y) { | |
1621 if (this.includeScrollOffsets) | |
1622 return this.withinIncludingScrolloffsets(element, x, y); | |
1623 this.xcomp = x; | |
1624 this.ycomp = y; | |
1625 this.offset = this.cumulativeOffset(element); | |
1626 | |
1627 return (y >= this.offset[1] && | |
1628 y < this.offset[1] + element.offsetHeight && | |
1629 x >= this.offset[0] && | |
1630 x < this.offset[0] + element.offsetWidth); | |
1631 }, | |
1632 | |
1633 withinIncludingScrolloffsets: function(element, x, y) { | |
1634 var offsetcache = this.realOffset(element); | |
1635 | |
1636 this.xcomp = x + offsetcache[0] - this.deltaX; | |
1637 this.ycomp = y + offsetcache[1] - this.deltaY; | |
1638 this.offset = this.cumulativeOffset(element); | |
1639 | |
1640 return (this.ycomp >= this.offset[1] && | |
1641 this.ycomp < this.offset[1] + element.offsetHeight && | |
1642 this.xcomp >= this.offset[0] && | |
1643 this.xcomp < this.offset[0] + element.offsetWidth); | |
1644 }, | |
1645 | |
1646 // within must be called directly before | |
1647 overlap: function(mode, element) { | |
1648 if (!mode) return 0; | |
1649 if (mode == 'vertical') | |
1650 return ((this.offset[1] + element.offsetHeight) - this.ycomp) / | |
1651 element.offsetHeight; | |
1652 if (mode == 'horizontal') | |
1653 return ((this.offset[0] + element.offsetWidth) - this.xcomp) / | |
1654 element.offsetWidth; | |
1655 }, | |
1656 | |
1657 clone: function(source, target) { | |
1658 source = $(source); | |
1659 target = $(target); | |
1660 target.style.position = 'absolute'; | |
1661 var offsets = this.cumulativeOffset(source); | |
1662 target.style.top = offsets[1] + 'px'; | |
1663 target.style.left = offsets[0] + 'px'; | |
1664 target.style.width = source.offsetWidth + 'px'; | |
1665 target.style.height = source.offsetHeight + 'px'; | |
1666 }, | |
1667 | |
1668 page: function(forElement) { | |
1669 var valueT = 0, valueL = 0; | |
1670 | |
1671 var element = forElement; | |
1672 do { | |
1673 valueT += element.offsetTop || 0; | |
1674 valueL += element.offsetLeft || 0; | |
1675 | |
1676 // Safari fix | |
1677 if (element.offsetParent==document.body) | |
1678 if (Element.getStyle(element,'position')=='absolute') break; | |
1679 | |
1680 } while (element = element.offsetParent); | |
1681 | |
1682 element = forElement; | |
1683 do { | |
1684 valueT -= element.scrollTop || 0; | |
1685 valueL -= element.scrollLeft || 0; | |
1686 } while (element = element.parentNode); | |
1687 | |
1688 return [valueL, valueT]; | |
1689 }, | |
1690 | |
1691 clone: function(source, target) { | |
1692 var options = Object.extend({ | |
1693 setLeft: true, | |
1694 setTop: true, | |
1695 setWidth: true, | |
1696 setHeight: true, | |
1697 offsetTop: 0, | |
1698 offsetLeft: 0 | |
1699 }, arguments[2] || {}) | |
1700 | |
1701 // find page position of source | |
1702 source = $(source); | |
1703 var p = Position.page(source); | |
1704 | |
1705 // find coordinate system to use | |
1706 target = $(target); | |
1707 var delta = [0, 0]; | |
1708 var parent = null; | |
1709 // delta [0,0] will do fine with position: fixed elements, | |
1710 // position:absolute needs offsetParent deltas | |
1711 if (Element.getStyle(target,'position') == 'absolute') { | |
1712 parent = Position.offsetParent(target); | |
1713 delta = Position.page(parent); | |
1714 } | |
1715 | |
1716 // correct by body offsets (fixes Safari) | |
1717 if (parent == document.body) { | |
1718 delta[0] -= document.body.offsetLeft; | |
1719 delta[1] -= document.body.offsetTop; | |
1720 } | |
1721 | |
1722 // set position | |
1723 if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; | |
1724 if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; | |
1725 if(options.setWidth) target.style.width = source.offsetWidth + 'px'; | |
1726 if(options.setHeight) target.style.height = source.offsetHeight + 'px'; | |
1727 }, | |
1728 | |
1729 absolutize: function(element) { | |
1730 element = $(element); | |
1731 if (element.style.position == 'absolute') return; | |
1732 Position.prepare(); | |
1733 | |
1734 var offsets = Position.positionedOffset(element); | |
1735 var top = offsets[1]; | |
1736 var left = offsets[0]; | |
1737 var width = element.clientWidth; | |
1738 var height = element.clientHeight; | |
1739 | |
1740 element._originalLeft = left - parseFloat(element.style.left || 0); | |
1741 element._originalTop = top - parseFloat(element.style.top || 0); | |
1742 element._originalWidth = element.style.width; | |
1743 element._originalHeight = element.style.height; | |
1744 | |
1745 element.style.position = 'absolute'; | |
1746 element.style.top = top + 'px';; | |
1747 element.style.left = left + 'px';; | |
1748 element.style.width = width + 'px';; | |
1749 element.style.height = height + 'px';; | |
1750 }, | |
1751 | |
1752 relativize: function(element) { | |
1753 element = $(element); | |
1754 if (element.style.position == 'relative') return; | |
1755 Position.prepare(); | |
1756 | |
1757 element.style.position = 'relative'; | |
1758 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); | |
1759 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); | |
1760 | |
1761 element.style.top = top + 'px'; | |
1762 element.style.left = left + 'px'; | |
1763 element.style.height = element._originalHeight; | |
1764 element.style.width = element._originalWidth; | |
1765 } | |
1766 } | |
1767 | |
1768 // Safari returns margins on body which is incorrect if the child is absolutely | |
1769 // positioned. For performance reasons, redefine Position.cumulativeOffset for | |
1770 // KHTML/WebKit only. | |
1771 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { | |
1772 Position.cumulativeOffset = function(element) { | |
1773 var valueT = 0, valueL = 0; | |
1774 do { | |
1775 valueT += element.offsetTop || 0; | |
1776 valueL += element.offsetLeft || 0; | |
1777 if (element.offsetParent == document.body) | |
1778 if (Element.getStyle(element, 'position') == 'absolute') break; | |
1779 | |
1780 element = element.offsetParent; | |
1781 } while (element); | |
1782 | |
1783 return [valueL, valueT]; | |
1784 } | |
1785 } |