adhearsion 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/LICENSE +339 -0
  2. data/Rakefile +108 -0
  3. data/ahn +195 -0
  4. data/lib/adhearsion.rb +402 -0
  5. data/lib/constants.rb +20 -0
  6. data/lib/core_extensions.rb +157 -0
  7. data/lib/database_functions.rb +76 -0
  8. data/lib/rami.rb +822 -0
  9. data/lib/servlet_container.rb +146 -0
  10. data/new_projects/Rakefile +100 -0
  11. data/new_projects/config/adhearsion.sqlite3 +0 -0
  12. data/new_projects/config/adhearsion.yml +11 -0
  13. data/new_projects/config/database.rb +50 -0
  14. data/new_projects/config/database.yml +10 -0
  15. data/new_projects/config/helpers/drb_server.yml +43 -0
  16. data/new_projects/config/helpers/factorial.alien.c.yml +1 -0
  17. data/new_projects/config/helpers/manager_proxy.yml +7 -0
  18. data/new_projects/config/helpers/micromenus.yml +1 -0
  19. data/new_projects/config/helpers/micromenus/collab.rb +55 -0
  20. data/new_projects/config/helpers/micromenus/images/tux.bmp +0 -0
  21. data/new_projects/config/helpers/micromenus/javascripts/builder.js +131 -0
  22. data/new_projects/config/helpers/micromenus/javascripts/controls.js +834 -0
  23. data/new_projects/config/helpers/micromenus/javascripts/dragdrop.js +944 -0
  24. data/new_projects/config/helpers/micromenus/javascripts/effects.js +956 -0
  25. data/new_projects/config/helpers/micromenus/javascripts/prototype.js +2319 -0
  26. data/new_projects/config/helpers/micromenus/javascripts/scriptaculous.js +51 -0
  27. data/new_projects/config/helpers/micromenus/javascripts/slider.js +278 -0
  28. data/new_projects/config/helpers/micromenus/javascripts/unittest.js +557 -0
  29. data/new_projects/config/helpers/micromenus/stylesheets/firefox.css +10 -0
  30. data/new_projects/config/helpers/micromenus/stylesheets/firefox.xul.css +44 -0
  31. data/new_projects/config/helpers/weather.yml +1 -0
  32. data/new_projects/config/helpers/xbmc.yml +1 -0
  33. data/new_projects/config/migration.rb +53 -0
  34. data/new_projects/extensions.rb +56 -0
  35. data/new_projects/helpers/drb_server.rb +32 -0
  36. data/new_projects/helpers/factorial.alien.c +32 -0
  37. data/new_projects/helpers/manager_proxy.rb +43 -0
  38. data/new_projects/helpers/micromenus.rb +374 -0
  39. data/new_projects/helpers/oscar_wilde_quotes.rb +197 -0
  40. data/new_projects/helpers/weather.rb +85 -0
  41. data/new_projects/helpers/xbmc.rb +12 -0
  42. data/new_projects/logs/database.log +0 -0
  43. data/test/core_extensions_test.rb +26 -0
  44. data/test/dial_test.rb +43 -0
  45. data/test/stress_tests/test.rb +13 -0
  46. data/test/stress_tests/test.yml +13 -0
  47. data/test/test_micromenus.rb +0 -0
  48. metadata +131 -0
@@ -0,0 +1,956 @@
1
+ // script.aculo.us effects.js v1.6.5, Wed Nov 08 14:17:49 CET 2006
2
+
3
+ // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // Contributors:
5
+ // Justin Palmer (http://encytemedia.com/)
6
+ // Mark Pilgrim (http://diveintomark.org/)
7
+ // Martin Bialasinki
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
+ // converts rgb() and #xxx to #xxxxxx format,
13
+ // returns self (or first argument) if not convertable
14
+ String.prototype.parseColor = function() {
15
+ var color = '#';
16
+ if(this.slice(0,4) == 'rgb(') {
17
+ var cols = this.slice(4,this.length-1).split(',');
18
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
19
+ } else {
20
+ if(this.slice(0,1) == '#') {
21
+ if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
22
+ if(this.length==7) color = this.toLowerCase();
23
+ }
24
+ }
25
+ return(color.length==7 ? color : (arguments[0] || this));
26
+ }
27
+
28
+ /*--------------------------------------------------------------------------*/
29
+
30
+ Element.collectTextNodes = function(element) {
31
+ return $A($(element).childNodes).collect( function(node) {
32
+ return (node.nodeType==3 ? node.nodeValue :
33
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
34
+ }).flatten().join('');
35
+ }
36
+
37
+ Element.collectTextNodesIgnoreClass = function(element, className) {
38
+ return $A($(element).childNodes).collect( function(node) {
39
+ return (node.nodeType==3 ? node.nodeValue :
40
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
41
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
42
+ }).flatten().join('');
43
+ }
44
+
45
+ Element.setContentZoom = function(element, percent) {
46
+ element = $(element);
47
+ element.setStyle({fontSize: (percent/100) + 'em'});
48
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
49
+ return element;
50
+ }
51
+
52
+ Element.getOpacity = function(element){
53
+ element = $(element);
54
+ var opacity;
55
+ if (opacity = element.getStyle('opacity'))
56
+ return parseFloat(opacity);
57
+ if (opacity = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
58
+ if(opacity[1]) return parseFloat(opacity[1]) / 100;
59
+ return 1.0;
60
+ }
61
+
62
+ Element.setOpacity = function(element, value){
63
+ element= $(element);
64
+ if (value == 1){
65
+ element.setStyle({ opacity:
66
+ (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ?
67
+ 0.999999 : 1.0 });
68
+ if(/MSIE/.test(navigator.userAgent) && !window.opera)
69
+ element.setStyle({filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});
70
+ } else {
71
+ if(value < 0.00001) value = 0;
72
+ element.setStyle({opacity: value});
73
+ if(/MSIE/.test(navigator.userAgent) && !window.opera)
74
+ element.setStyle(
75
+ { filter: element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
76
+ 'alpha(opacity='+value*100+')' });
77
+ }
78
+ return element;
79
+ }
80
+
81
+ Element.getInlineOpacity = function(element){
82
+ return $(element).style.opacity || '';
83
+ }
84
+
85
+ Element.forceRerendering = function(element) {
86
+ try {
87
+ element = $(element);
88
+ var n = document.createTextNode(' ');
89
+ element.appendChild(n);
90
+ element.removeChild(n);
91
+ } catch(e) { }
92
+ };
93
+
94
+ /*--------------------------------------------------------------------------*/
95
+
96
+ Array.prototype.call = function() {
97
+ var args = arguments;
98
+ this.each(function(f){ f.apply(this, args) });
99
+ }
100
+
101
+ /*--------------------------------------------------------------------------*/
102
+
103
+ var Effect = {
104
+ _elementDoesNotExistError: {
105
+ name: 'ElementDoesNotExistError',
106
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
107
+ },
108
+ tagifyText: function(element) {
109
+ if(typeof Builder == 'undefined')
110
+ throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
111
+
112
+ var tagifyStyle = 'position:relative';
113
+ if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
114
+
115
+ element = $(element);
116
+ $A(element.childNodes).each( function(child) {
117
+ if(child.nodeType==3) {
118
+ child.nodeValue.toArray().each( function(character) {
119
+ element.insertBefore(
120
+ Builder.node('span',{style: tagifyStyle},
121
+ character == ' ' ? String.fromCharCode(160) : character),
122
+ child);
123
+ });
124
+ Element.remove(child);
125
+ }
126
+ });
127
+ },
128
+ multiple: function(element, effect) {
129
+ var elements;
130
+ if(((typeof element == 'object') ||
131
+ (typeof element == 'function')) &&
132
+ (element.length))
133
+ elements = element;
134
+ else
135
+ elements = $(element).childNodes;
136
+
137
+ var options = Object.extend({
138
+ speed: 0.1,
139
+ delay: 0.0
140
+ }, arguments[2] || {});
141
+ var masterDelay = options.delay;
142
+
143
+ $A(elements).each( function(element, index) {
144
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
145
+ });
146
+ },
147
+ PAIRS: {
148
+ 'slide': ['SlideDown','SlideUp'],
149
+ 'blind': ['BlindDown','BlindUp'],
150
+ 'appear': ['Appear','Fade']
151
+ },
152
+ toggle: function(element, effect) {
153
+ element = $(element);
154
+ effect = (effect || 'appear').toLowerCase();
155
+ var options = Object.extend({
156
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
157
+ }, arguments[2] || {});
158
+ Effect[element.visible() ?
159
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
160
+ }
161
+ };
162
+
163
+ var Effect2 = Effect; // deprecated
164
+
165
+ /* ------------- transitions ------------- */
166
+
167
+ Effect.Transitions = {
168
+ linear: Prototype.K,
169
+ sinoidal: function(pos) {
170
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
171
+ },
172
+ reverse: function(pos) {
173
+ return 1-pos;
174
+ },
175
+ flicker: function(pos) {
176
+ return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
177
+ },
178
+ wobble: function(pos) {
179
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
180
+ },
181
+ pulse: function(pos, pulses) {
182
+ pulses = pulses || 5;
183
+ return (
184
+ Math.round((pos % (1/pulses)) * pulses) == 0 ?
185
+ ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
186
+ 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
187
+ );
188
+ },
189
+ none: function(pos) {
190
+ return 0;
191
+ },
192
+ full: function(pos) {
193
+ return 1;
194
+ }
195
+ };
196
+
197
+ /* ------------- core effects ------------- */
198
+
199
+ Effect.ScopedQueue = Class.create();
200
+ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
201
+ initialize: function() {
202
+ this.effects = [];
203
+ this.interval = null;
204
+ },
205
+ _each: function(iterator) {
206
+ this.effects._each(iterator);
207
+ },
208
+ add: function(effect) {
209
+ var timestamp = new Date().getTime();
210
+
211
+ var position = (typeof effect.options.queue == 'string') ?
212
+ effect.options.queue : effect.options.queue.position;
213
+
214
+ switch(position) {
215
+ case 'front':
216
+ // move unstarted effects after this effect
217
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
218
+ e.startOn += effect.finishOn;
219
+ e.finishOn += effect.finishOn;
220
+ });
221
+ break;
222
+ case 'with-last':
223
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
224
+ break;
225
+ case 'end':
226
+ // start effect after last queued effect has finished
227
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
228
+ break;
229
+ }
230
+
231
+ effect.startOn += timestamp;
232
+ effect.finishOn += timestamp;
233
+
234
+ if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
235
+ this.effects.push(effect);
236
+
237
+ if(!this.interval)
238
+ this.interval = setInterval(this.loop.bind(this), 40);
239
+ },
240
+ remove: function(effect) {
241
+ this.effects = this.effects.reject(function(e) { return e==effect });
242
+ if(this.effects.length == 0) {
243
+ clearInterval(this.interval);
244
+ this.interval = null;
245
+ }
246
+ },
247
+ loop: function() {
248
+ var timePos = new Date().getTime();
249
+ this.effects.invoke('loop', timePos);
250
+ }
251
+ });
252
+
253
+ Effect.Queues = {
254
+ instances: $H(),
255
+ get: function(queueName) {
256
+ if(typeof queueName != 'string') return queueName;
257
+
258
+ if(!this.instances[queueName])
259
+ this.instances[queueName] = new Effect.ScopedQueue();
260
+
261
+ return this.instances[queueName];
262
+ }
263
+ }
264
+ Effect.Queue = Effect.Queues.get('global');
265
+
266
+ Effect.DefaultOptions = {
267
+ transition: Effect.Transitions.sinoidal,
268
+ duration: 1.0, // seconds
269
+ fps: 25.0, // max. 25fps due to Effect.Queue implementation
270
+ sync: false, // true for combining
271
+ from: 0.0,
272
+ to: 1.0,
273
+ delay: 0.0,
274
+ queue: 'parallel'
275
+ }
276
+
277
+ Effect.Base = function() {};
278
+ Effect.Base.prototype = {
279
+ position: null,
280
+ start: function(options) {
281
+ this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
282
+ this.currentFrame = 0;
283
+ this.state = 'idle';
284
+ this.startOn = this.options.delay*1000;
285
+ this.finishOn = this.startOn + (this.options.duration*1000);
286
+ this.event('beforeStart');
287
+ if(!this.options.sync)
288
+ Effect.Queues.get(typeof this.options.queue == 'string' ?
289
+ 'global' : this.options.queue.scope).add(this);
290
+ },
291
+ loop: function(timePos) {
292
+ if(timePos >= this.startOn) {
293
+ if(timePos >= this.finishOn) {
294
+ this.render(1.0);
295
+ this.cancel();
296
+ this.event('beforeFinish');
297
+ if(this.finish) this.finish();
298
+ this.event('afterFinish');
299
+ return;
300
+ }
301
+ var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
302
+ var frame = Math.round(pos * this.options.fps * this.options.duration);
303
+ if(frame > this.currentFrame) {
304
+ this.render(pos);
305
+ this.currentFrame = frame;
306
+ }
307
+ }
308
+ },
309
+ render: function(pos) {
310
+ if(this.state == 'idle') {
311
+ this.state = 'running';
312
+ this.event('beforeSetup');
313
+ if(this.setup) this.setup();
314
+ this.event('afterSetup');
315
+ }
316
+ if(this.state == 'running') {
317
+ if(this.options.transition) pos = this.options.transition(pos);
318
+ pos *= (this.options.to-this.options.from);
319
+ pos += this.options.from;
320
+ this.position = pos;
321
+ this.event('beforeUpdate');
322
+ if(this.update) this.update(pos);
323
+ this.event('afterUpdate');
324
+ }
325
+ },
326
+ cancel: function() {
327
+ if(!this.options.sync)
328
+ Effect.Queues.get(typeof this.options.queue == 'string' ?
329
+ 'global' : this.options.queue.scope).remove(this);
330
+ this.state = 'finished';
331
+ },
332
+ event: function(eventName) {
333
+ if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
334
+ if(this.options[eventName]) this.options[eventName](this);
335
+ },
336
+ inspect: function() {
337
+ return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
338
+ }
339
+ }
340
+
341
+ Effect.Parallel = Class.create();
342
+ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
343
+ initialize: function(effects) {
344
+ this.effects = effects || [];
345
+ this.start(arguments[1]);
346
+ },
347
+ update: function(position) {
348
+ this.effects.invoke('render', position);
349
+ },
350
+ finish: function(position) {
351
+ this.effects.each( function(effect) {
352
+ effect.render(1.0);
353
+ effect.cancel();
354
+ effect.event('beforeFinish');
355
+ if(effect.finish) effect.finish(position);
356
+ effect.event('afterFinish');
357
+ });
358
+ }
359
+ });
360
+
361
+ Effect.Event = Class.create();
362
+ Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
363
+ initialize: function() {
364
+ var options = Object.extend({
365
+ duration: 0
366
+ }, arguments[0] || {});
367
+ this.start(options);
368
+ },
369
+ update: Prototype.emptyFunction
370
+ });
371
+
372
+ Effect.Opacity = Class.create();
373
+ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
374
+ initialize: function(element) {
375
+ this.element = $(element);
376
+ if(!this.element) throw(Effect._elementDoesNotExistError);
377
+ // make this work on IE on elements without 'layout'
378
+ if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
379
+ this.element.setStyle({zoom: 1});
380
+ var options = Object.extend({
381
+ from: this.element.getOpacity() || 0.0,
382
+ to: 1.0
383
+ }, arguments[1] || {});
384
+ this.start(options);
385
+ },
386
+ update: function(position) {
387
+ this.element.setOpacity(position);
388
+ }
389
+ });
390
+
391
+ Effect.Move = Class.create();
392
+ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
393
+ initialize: function(element) {
394
+ this.element = $(element);
395
+ if(!this.element) throw(Effect._elementDoesNotExistError);
396
+ var options = Object.extend({
397
+ x: 0,
398
+ y: 0,
399
+ mode: 'relative'
400
+ }, arguments[1] || {});
401
+ this.start(options);
402
+ },
403
+ setup: function() {
404
+ // Bug in Opera: Opera returns the "real" position of a static element or
405
+ // relative element that does not have top/left explicitly set.
406
+ // ==> Always set top and left for position relative elements in your stylesheets
407
+ // (to 0 if you do not need them)
408
+ this.element.makePositioned();
409
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
410
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
411
+ if(this.options.mode == 'absolute') {
412
+ // absolute movement, so we need to calc deltaX and deltaY
413
+ this.options.x = this.options.x - this.originalLeft;
414
+ this.options.y = this.options.y - this.originalTop;
415
+ }
416
+ },
417
+ update: function(position) {
418
+ this.element.setStyle({
419
+ left: Math.round(this.options.x * position + this.originalLeft) + 'px',
420
+ top: Math.round(this.options.y * position + this.originalTop) + 'px'
421
+ });
422
+ }
423
+ });
424
+
425
+ // for backwards compatibility
426
+ Effect.MoveBy = function(element, toTop, toLeft) {
427
+ return new Effect.Move(element,
428
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
429
+ };
430
+
431
+ Effect.Scale = Class.create();
432
+ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
433
+ initialize: function(element, percent) {
434
+ this.element = $(element);
435
+ if(!this.element) throw(Effect._elementDoesNotExistError);
436
+ var options = Object.extend({
437
+ scaleX: true,
438
+ scaleY: true,
439
+ scaleContent: true,
440
+ scaleFromCenter: false,
441
+ scaleMode: 'box', // 'box' or 'contents' or {} with provided values
442
+ scaleFrom: 100.0,
443
+ scaleTo: percent
444
+ }, arguments[2] || {});
445
+ this.start(options);
446
+ },
447
+ setup: function() {
448
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
449
+ this.elementPositioning = this.element.getStyle('position');
450
+
451
+ this.originalStyle = {};
452
+ ['top','left','width','height','fontSize'].each( function(k) {
453
+ this.originalStyle[k] = this.element.style[k];
454
+ }.bind(this));
455
+
456
+ this.originalTop = this.element.offsetTop;
457
+ this.originalLeft = this.element.offsetLeft;
458
+
459
+ var fontSize = this.element.getStyle('font-size') || '100%';
460
+ ['em','px','%','pt'].each( function(fontSizeType) {
461
+ if(fontSize.indexOf(fontSizeType)>0) {
462
+ this.fontSize = parseFloat(fontSize);
463
+ this.fontSizeType = fontSizeType;
464
+ }
465
+ }.bind(this));
466
+
467
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
468
+
469
+ this.dims = null;
470
+ if(this.options.scaleMode=='box')
471
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
472
+ if(/^content/.test(this.options.scaleMode))
473
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
474
+ if(!this.dims)
475
+ this.dims = [this.options.scaleMode.originalHeight,
476
+ this.options.scaleMode.originalWidth];
477
+ },
478
+ update: function(position) {
479
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
480
+ if(this.options.scaleContent && this.fontSize)
481
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
482
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
483
+ },
484
+ finish: function(position) {
485
+ if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
486
+ },
487
+ setDimensions: function(height, width) {
488
+ var d = {};
489
+ if(this.options.scaleX) d.width = Math.round(width) + 'px';
490
+ if(this.options.scaleY) d.height = Math.round(height) + 'px';
491
+ if(this.options.scaleFromCenter) {
492
+ var topd = (height - this.dims[0])/2;
493
+ var leftd = (width - this.dims[1])/2;
494
+ if(this.elementPositioning == 'absolute') {
495
+ if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
496
+ if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
497
+ } else {
498
+ if(this.options.scaleY) d.top = -topd + 'px';
499
+ if(this.options.scaleX) d.left = -leftd + 'px';
500
+ }
501
+ }
502
+ this.element.setStyle(d);
503
+ }
504
+ });
505
+
506
+ Effect.Highlight = Class.create();
507
+ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
508
+ initialize: function(element) {
509
+ this.element = $(element);
510
+ if(!this.element) throw(Effect._elementDoesNotExistError);
511
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
512
+ this.start(options);
513
+ },
514
+ setup: function() {
515
+ // Prevent executing on elements not in the layout flow
516
+ if(this.element.getStyle('display')=='none') { this.cancel(); return; }
517
+ // Disable background image during the effect
518
+ this.oldStyle = {
519
+ backgroundImage: this.element.getStyle('background-image') };
520
+ this.element.setStyle({backgroundImage: 'none'});
521
+ if(!this.options.endcolor)
522
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
523
+ if(!this.options.restorecolor)
524
+ this.options.restorecolor = this.element.getStyle('background-color');
525
+ // init color calculations
526
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
527
+ 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));
528
+ },
529
+ update: function(position) {
530
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
531
+ return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
532
+ },
533
+ finish: function() {
534
+ this.element.setStyle(Object.extend(this.oldStyle, {
535
+ backgroundColor: this.options.restorecolor
536
+ }));
537
+ }
538
+ });
539
+
540
+ Effect.ScrollTo = Class.create();
541
+ Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
542
+ initialize: function(element) {
543
+ this.element = $(element);
544
+ this.start(arguments[1] || {});
545
+ },
546
+ setup: function() {
547
+ Position.prepare();
548
+ var offsets = Position.cumulativeOffset(this.element);
549
+ if(this.options.offset) offsets[1] += this.options.offset;
550
+ var max = window.innerHeight ?
551
+ window.height - window.innerHeight :
552
+ document.body.scrollHeight -
553
+ (document.documentElement.clientHeight ?
554
+ document.documentElement.clientHeight : document.body.clientHeight);
555
+ this.scrollStart = Position.deltaY;
556
+ this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
557
+ },
558
+ update: function(position) {
559
+ Position.prepare();
560
+ window.scrollTo(Position.deltaX,
561
+ this.scrollStart + (position*this.delta));
562
+ }
563
+ });
564
+
565
+ /* ------------- combination effects ------------- */
566
+
567
+ Effect.Fade = function(element) {
568
+ element = $(element);
569
+ var oldOpacity = element.getInlineOpacity();
570
+ var options = Object.extend({
571
+ from: element.getOpacity() || 1.0,
572
+ to: 0.0,
573
+ afterFinishInternal: function(effect) {
574
+ if(effect.options.to!=0) return;
575
+ effect.element.hide().setStyle({opacity: oldOpacity});
576
+ }}, arguments[1] || {});
577
+ return new Effect.Opacity(element,options);
578
+ }
579
+
580
+ Effect.Appear = function(element) {
581
+ element = $(element);
582
+ var options = Object.extend({
583
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
584
+ to: 1.0,
585
+ // force Safari to render floated elements properly
586
+ afterFinishInternal: function(effect) {
587
+ effect.element.forceRerendering();
588
+ },
589
+ beforeSetup: function(effect) {
590
+ effect.element.setOpacity(effect.options.from).show();
591
+ }}, arguments[1] || {});
592
+ return new Effect.Opacity(element,options);
593
+ }
594
+
595
+ Effect.Puff = function(element) {
596
+ element = $(element);
597
+ var oldStyle = {
598
+ opacity: element.getInlineOpacity(),
599
+ position: element.getStyle('position'),
600
+ top: element.style.top,
601
+ left: element.style.left,
602
+ width: element.style.width,
603
+ height: element.style.height
604
+ };
605
+ return new Effect.Parallel(
606
+ [ new Effect.Scale(element, 200,
607
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
608
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
609
+ Object.extend({ duration: 1.0,
610
+ beforeSetupInternal: function(effect) {
611
+ Position.absolutize(effect.effects[0].element)
612
+ },
613
+ afterFinishInternal: function(effect) {
614
+ effect.effects[0].element.hide().setStyle(oldStyle); }
615
+ }, arguments[1] || {})
616
+ );
617
+ }
618
+
619
+ Effect.BlindUp = function(element) {
620
+ element = $(element);
621
+ element.makeClipping();
622
+ return new Effect.Scale(element, 0,
623
+ Object.extend({ scaleContent: false,
624
+ scaleX: false,
625
+ restoreAfterFinish: true,
626
+ afterFinishInternal: function(effect) {
627
+ effect.element.hide().undoClipping();
628
+ }
629
+ }, arguments[1] || {})
630
+ );
631
+ }
632
+
633
+ Effect.BlindDown = function(element) {
634
+ element = $(element);
635
+ var elementDimensions = element.getDimensions();
636
+ return new Effect.Scale(element, 100, Object.extend({
637
+ scaleContent: false,
638
+ scaleX: false,
639
+ scaleFrom: 0,
640
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
641
+ restoreAfterFinish: true,
642
+ afterSetup: function(effect) {
643
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
644
+ },
645
+ afterFinishInternal: function(effect) {
646
+ effect.element.undoClipping();
647
+ }
648
+ }, arguments[1] || {}));
649
+ }
650
+
651
+ Effect.SwitchOff = function(element) {
652
+ element = $(element);
653
+ var oldOpacity = element.getInlineOpacity();
654
+ return new Effect.Appear(element, Object.extend({
655
+ duration: 0.4,
656
+ from: 0,
657
+ transition: Effect.Transitions.flicker,
658
+ afterFinishInternal: function(effect) {
659
+ new Effect.Scale(effect.element, 1, {
660
+ duration: 0.3, scaleFromCenter: true,
661
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
662
+ beforeSetup: function(effect) {
663
+ effect.element.makePositioned().makeClipping();
664
+ },
665
+ afterFinishInternal: function(effect) {
666
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
667
+ }
668
+ })
669
+ }
670
+ }, arguments[1] || {}));
671
+ }
672
+
673
+ Effect.DropOut = function(element) {
674
+ element = $(element);
675
+ var oldStyle = {
676
+ top: element.getStyle('top'),
677
+ left: element.getStyle('left'),
678
+ opacity: element.getInlineOpacity() };
679
+ return new Effect.Parallel(
680
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
681
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
682
+ Object.extend(
683
+ { duration: 0.5,
684
+ beforeSetup: function(effect) {
685
+ effect.effects[0].element.makePositioned();
686
+ },
687
+ afterFinishInternal: function(effect) {
688
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
689
+ }
690
+ }, arguments[1] || {}));
691
+ }
692
+
693
+ Effect.Shake = function(element) {
694
+ element = $(element);
695
+ var oldStyle = {
696
+ top: element.getStyle('top'),
697
+ left: element.getStyle('left') };
698
+ return new Effect.Move(element,
699
+ { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
700
+ new Effect.Move(effect.element,
701
+ { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
702
+ new Effect.Move(effect.element,
703
+ { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
704
+ new Effect.Move(effect.element,
705
+ { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
706
+ new Effect.Move(effect.element,
707
+ { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
708
+ new Effect.Move(effect.element,
709
+ { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
710
+ effect.element.undoPositioned().setStyle(oldStyle);
711
+ }}) }}) }}) }}) }}) }});
712
+ }
713
+
714
+ Effect.SlideDown = function(element) {
715
+ element = $(element).cleanWhitespace();
716
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
717
+ var oldInnerBottom = element.down().getStyle('bottom');
718
+ var elementDimensions = element.getDimensions();
719
+ return new Effect.Scale(element, 100, Object.extend({
720
+ scaleContent: false,
721
+ scaleX: false,
722
+ scaleFrom: window.opera ? 0 : 1,
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().setStyle({height: '0px'}).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.undoClipping().undoPositioned();
737
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
738
+ }, arguments[1] || {})
739
+ );
740
+ }
741
+
742
+ Effect.SlideUp = function(element) {
743
+ element = $(element).cleanWhitespace();
744
+ var oldInnerBottom = element.down().getStyle('bottom');
745
+ return new Effect.Scale(element, window.opera ? 0 : 1,
746
+ Object.extend({ scaleContent: false,
747
+ scaleX: false,
748
+ scaleMode: 'box',
749
+ scaleFrom: 100,
750
+ restoreAfterFinish: true,
751
+ beforeStartInternal: function(effect) {
752
+ effect.element.makePositioned();
753
+ effect.element.down().makePositioned();
754
+ if(window.opera) effect.element.setStyle({top: ''});
755
+ effect.element.makeClipping().show();
756
+ },
757
+ afterUpdateInternal: function(effect) {
758
+ effect.element.down().setStyle({bottom:
759
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
760
+ },
761
+ afterFinishInternal: function(effect) {
762
+ effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
763
+ effect.element.down().undoPositioned();
764
+ }
765
+ }, arguments[1] || {})
766
+ );
767
+ }
768
+
769
+ // Bug in opera makes the TD containing this element expand for a instance after finish
770
+ Effect.Squish = function(element) {
771
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
772
+ restoreAfterFinish: true,
773
+ beforeSetup: function(effect) {
774
+ effect.element.makeClipping();
775
+ },
776
+ afterFinishInternal: function(effect) {
777
+ effect.element.hide().undoClipping();
778
+ }
779
+ });
780
+ }
781
+
782
+ Effect.Grow = function(element) {
783
+ element = $(element);
784
+ var options = Object.extend({
785
+ direction: 'center',
786
+ moveTransition: Effect.Transitions.sinoidal,
787
+ scaleTransition: Effect.Transitions.sinoidal,
788
+ opacityTransition: Effect.Transitions.full
789
+ }, arguments[1] || {});
790
+ var oldStyle = {
791
+ top: element.style.top,
792
+ left: element.style.left,
793
+ height: element.style.height,
794
+ width: element.style.width,
795
+ opacity: element.getInlineOpacity() };
796
+
797
+ var dims = element.getDimensions();
798
+ var initialMoveX, initialMoveY;
799
+ var moveX, moveY;
800
+
801
+ switch (options.direction) {
802
+ case 'top-left':
803
+ initialMoveX = initialMoveY = moveX = moveY = 0;
804
+ break;
805
+ case 'top-right':
806
+ initialMoveX = dims.width;
807
+ initialMoveY = moveY = 0;
808
+ moveX = -dims.width;
809
+ break;
810
+ case 'bottom-left':
811
+ initialMoveX = moveX = 0;
812
+ initialMoveY = dims.height;
813
+ moveY = -dims.height;
814
+ break;
815
+ case 'bottom-right':
816
+ initialMoveX = dims.width;
817
+ initialMoveY = dims.height;
818
+ moveX = -dims.width;
819
+ moveY = -dims.height;
820
+ break;
821
+ case 'center':
822
+ initialMoveX = dims.width / 2;
823
+ initialMoveY = dims.height / 2;
824
+ moveX = -dims.width / 2;
825
+ moveY = -dims.height / 2;
826
+ break;
827
+ }
828
+
829
+ return new Effect.Move(element, {
830
+ x: initialMoveX,
831
+ y: initialMoveY,
832
+ duration: 0.01,
833
+ beforeSetup: function(effect) {
834
+ effect.element.hide().makeClipping().makePositioned();
835
+ },
836
+ afterFinishInternal: function(effect) {
837
+ new Effect.Parallel(
838
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
839
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
840
+ new Effect.Scale(effect.element, 100, {
841
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
842
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
843
+ ], Object.extend({
844
+ beforeSetup: function(effect) {
845
+ effect.effects[0].element.setStyle({height: '0px'}).show();
846
+ },
847
+ afterFinishInternal: function(effect) {
848
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
849
+ }
850
+ }, options)
851
+ )
852
+ }
853
+ });
854
+ }
855
+
856
+ Effect.Shrink = function(element) {
857
+ element = $(element);
858
+ var options = Object.extend({
859
+ direction: 'center',
860
+ moveTransition: Effect.Transitions.sinoidal,
861
+ scaleTransition: Effect.Transitions.sinoidal,
862
+ opacityTransition: Effect.Transitions.none
863
+ }, arguments[1] || {});
864
+ var oldStyle = {
865
+ top: element.style.top,
866
+ left: element.style.left,
867
+ height: element.style.height,
868
+ width: element.style.width,
869
+ opacity: element.getInlineOpacity() };
870
+
871
+ var dims = element.getDimensions();
872
+ var moveX, moveY;
873
+
874
+ switch (options.direction) {
875
+ case 'top-left':
876
+ moveX = moveY = 0;
877
+ break;
878
+ case 'top-right':
879
+ moveX = dims.width;
880
+ moveY = 0;
881
+ break;
882
+ case 'bottom-left':
883
+ moveX = 0;
884
+ moveY = dims.height;
885
+ break;
886
+ case 'bottom-right':
887
+ moveX = dims.width;
888
+ moveY = dims.height;
889
+ break;
890
+ case 'center':
891
+ moveX = dims.width / 2;
892
+ moveY = dims.height / 2;
893
+ break;
894
+ }
895
+
896
+ return new Effect.Parallel(
897
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
898
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
899
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
900
+ ], Object.extend({
901
+ beforeStartInternal: function(effect) {
902
+ effect.effects[0].element.makePositioned().makeClipping();
903
+ },
904
+ afterFinishInternal: function(effect) {
905
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
906
+ }, options)
907
+ );
908
+ }
909
+
910
+ Effect.Pulsate = function(element) {
911
+ element = $(element);
912
+ var options = arguments[1] || {};
913
+ var oldOpacity = element.getInlineOpacity();
914
+ var transition = options.transition || Effect.Transitions.sinoidal;
915
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
916
+ reverser.bind(transition);
917
+ return new Effect.Opacity(element,
918
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
919
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
920
+ }, options), {transition: reverser}));
921
+ }
922
+
923
+ Effect.Fold = function(element) {
924
+ element = $(element);
925
+ var oldStyle = {
926
+ top: element.style.top,
927
+ left: element.style.left,
928
+ width: element.style.width,
929
+ height: element.style.height };
930
+ element.makeClipping();
931
+ return new Effect.Scale(element, 5, Object.extend({
932
+ scaleContent: false,
933
+ scaleX: false,
934
+ afterFinishInternal: function(effect) {
935
+ new Effect.Scale(element, 1, {
936
+ scaleContent: false,
937
+ scaleY: false,
938
+ afterFinishInternal: function(effect) {
939
+ effect.element.hide().undoClipping().setStyle(oldStyle);
940
+ } });
941
+ }}, arguments[1] || {}));
942
+ };
943
+
944
+ ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
945
+ 'collectTextNodes','collectTextNodesIgnoreClass'].each(
946
+ function(f) { Element.Methods[f] = Element[f]; }
947
+ );
948
+
949
+ Element.Methods.visualEffect = function(element, effect, options) {
950
+ s = effect.gsub(/_/, '-').camelize();
951
+ effect_class = s.charAt(0).toUpperCase() + s.substring(1);
952
+ new Effect[effect_class](element, options);
953
+ return $(element);
954
+ };
955
+
956
+ Element.addMethods();