Description:
fixed javascript/css assets, fixed link_to_remote in problems page
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r322:c744bb196ba4 - - 30 files changed: 1500 inserted, 7498 deleted

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