Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ] 

001 // script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
002 
003 // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
004 // Contributors:
005 //  Justin Palmer (http://encytemedia.com/)
006 //  Mark Pilgrim (http://diveintomark.org/)
007 //  Martin Bialasinki
008 // 
009 // script.aculo.us is freely distributable under the terms of an MIT-style license.
010 // For details, see the script.aculo.us web site: http://script.aculo.us/ 
011 
012 // converts rgb() and #xxx to #xxxxxx format,  
013 // returns self (or first argument) if not convertable  
014 String.prototype.parseColor = function() {  
015   var color = '#';
016   if(this.slice(0,4) == 'rgb(') {  
017     var cols = this.slice(4,this.length-1).split(',');  
018     var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
019   } else {  
020     if(this.slice(0,1) == '#') {  
021       if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
022       if(this.length==7) color = this.toLowerCase();  
023     }  
024   }  
025   return(color.length==7 ? color : (arguments[0] || this));  
026 }
027 
028 /*--------------------------------------------------------------------------*/
029 
030 Element.collectTextNodes = function(element) {  
031   return $A($(element).childNodes).collect( function(node) {
032     return (node.nodeType==3 ? node.nodeValue : 
033       (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
034   }).flatten().join('');
035 }
036 
037 Element.collectTextNodesIgnoreClass = function(element, className) {  
038   return $A($(element).childNodes).collect( function(node) {
039     return (node.nodeType==3 ? node.nodeValue : 
040       ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
041         Element.collectTextNodesIgnoreClass(node, className) : ''));
042   }).flatten().join('');
043 }
044 
045 Element.setContentZoom = function(element, percent) {
046   element = $(element);  
047   element.setStyle({fontSize: (percent/100) + 'em'});   
048   if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
049   return element;
050 }
051 
052 Element.getOpacity = function(element){
053   return $(element).getStyle('opacity');
054 }
055 
056 Element.setOpacity = function(element, value){
057   return $(element).setStyle({opacity:value});
058 }
059 
060 Element.getInlineOpacity = function(element){
061   return $(element).style.opacity || '';
062 }
063 
064 Element.forceRerendering = function(element) {
065   try {
066     element = $(element);
067     var n = document.createTextNode(' ');
068     element.appendChild(n);
069     element.removeChild(n);
070   } catch(e) { }
071 };
072 
073 /*--------------------------------------------------------------------------*/
074 
075 Array.prototype.call = function() {
076   var args = arguments;
077   this.each(function(f){ f.apply(this, args) });
078 }
079 
080 /*--------------------------------------------------------------------------*/
081 
082 var Effect = {
083   _elementDoesNotExistError: {
084     name: 'ElementDoesNotExistError',
085     message: 'The specified DOM element does not exist, but is required for this effect to operate'
086   },
087   tagifyText: function(element) {
088     if(typeof Builder == 'undefined')
089       throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
090       
091     var tagifyStyle = 'position:relative';
092     if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
093     
094     element = $(element);
095     $A(element.childNodes).each( function(child) {
096       if(child.nodeType==3) {
097         child.nodeValue.toArray().each( function(character) {
098           element.insertBefore(
099             Builder.node('span',{style: tagifyStyle},
100               character == ' ' ? String.fromCharCode(160) : character), 
101               child);
102         });
103         Element.remove(child);
104       }
105     });
106   },
107   multiple: function(element, effect) {
108     var elements;
109     if(((typeof element == 'object') || 
110         (typeof element == 'function')) && 
111        (element.length))
112       elements = element;
113     else
114       elements = $(element).childNodes;
115       
116     var options = Object.extend({
117       speed: 0.1,
118       delay: 0.0
119     }, arguments[2] || {});
120     var masterDelay = options.delay;
121 
122     $A(elements).each( function(element, index) {
123       new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
124     });
125   },
126   PAIRS: {
127     'slide':  ['SlideDown','SlideUp'],
128     'blind':  ['BlindDown','BlindUp'],
129     'appear': ['Appear','Fade']
130   },
131   toggle: function(element, effect) {
132     element = $(element);
133     effect = (effect || 'appear').toLowerCase();
134     var options = Object.extend({
135       queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
136     }, arguments[2] || {});
137     Effect[element.visible() ? 
138       Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
139   }
140 };
141 
142 var Effect2 = Effect; // deprecated
143 
144 /* ------------- transitions ------------- */
145 
146 Effect.Transitions = {
147   linear: Prototype.K,
148   sinoidal: function(pos) {
149     return (-Math.cos(pos*Math.PI)/2) + 0.5;
150   },
151   reverse: function(pos) {
152     return 1-pos;
153   },
154   flicker: function(pos) {
155     return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
156   },
157   wobble: function(pos) {
158     return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
159   },
160   pulse: function(pos, pulses) { 
161     pulses = pulses || 5; 
162     return (
163       Math.round((pos % (1/pulses)) * pulses) == 0 ? 
164             ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : 
165         1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
166       );
167   },
168   none: function(pos) {
169     return 0;
170   },
171   full: function(pos) {
172     return 1;
173   }
174 };
175 
176 /* ------------- core effects ------------- */
177 
178 Effect.ScopedQueue = Class.create();
179 Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
180   initialize: function() {
181     this.effects  = [];
182     this.interval = null;
183   },
184   _each: function(iterator) {
185     this.effects._each(iterator);
186   },
187   add: function(effect) {
188     var timestamp = new Date().getTime();
189     
190     var position = (typeof effect.options.queue == 'string') ? 
191       effect.options.queue : effect.options.queue.position;
192     
193     switch(position) {
194       case 'front':
195         // move unstarted effects after this effect  
196         this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
197             e.startOn  += effect.finishOn;
198             e.finishOn += effect.finishOn;
199           });
200         break;
201       case 'with-last':
202         timestamp = this.effects.pluck('startOn').max() || timestamp;
203         break;
204       case 'end':
205         // start effect after last queued effect has finished
206         timestamp = this.effects.pluck('finishOn').max() || timestamp;
207         break;
208     }
209     
210     effect.startOn  += timestamp;
211     effect.finishOn += timestamp;
212 
213     if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
214       this.effects.push(effect);
215     
216     if(!this.interval) 
217       this.interval = setInterval(this.loop.bind(this), 15);
218   },
219   remove: function(effect) {
220     this.effects = this.effects.reject(function(e) { return e==effect });
221     if(this.effects.length == 0) {
222       clearInterval(this.interval);
223       this.interval = null;
224     }
225   },
226   loop: function() {
227     var timePos = new Date().getTime();
228     for(var i=0, len=this.effects.length;i<len;i++) 
229       if(this.effects[i]) this.effects[i].loop(timePos);
230   }
231 });
232 
233 Effect.Queues = {
234   instances: $H(),
235   get: function(queueName) {
236     if(typeof queueName != 'string') return queueName;
237     
238     if(!this.instances[queueName])
239       this.instances[queueName] = new Effect.ScopedQueue();
240       
241     return this.instances[queueName];
242   }
243 }
244 Effect.Queue = Effect.Queues.get('global');
245 
246 Effect.DefaultOptions = {
247   transition: Effect.Transitions.sinoidal,
248   duration:   1.0,   // seconds
249   fps:        60.0,  // max. 60fps due to Effect.Queue implementation
250   sync:       false, // true for combining
251   from:       0.0,
252   to:         1.0,
253   delay:      0.0,
254   queue:      'parallel'
255 }
256 
257 Effect.Base = function() {};
258 Effect.Base.prototype = {
259   position: null,
260   start: function(options) {
261     this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
262     this.currentFrame = 0;
263     this.state        = 'idle';
264     this.startOn      = this.options.delay*1000;
265     this.finishOn     = this.startOn + (this.options.duration*1000);
266     this.event('beforeStart');
267     if(!this.options.sync)
268       Effect.Queues.get(typeof this.options.queue == 'string' ? 
269         'global' : this.options.queue.scope).add(this);
270   },
271   loop: function(timePos) {
272     if(timePos >= this.startOn) {
273       if(timePos >= this.finishOn) {
274         this.render(1.0);
275         this.cancel();
276         this.event('beforeFinish');
277         if(this.finish) this.finish(); 
278         this.event('afterFinish');
279         return;  
280       }
281       var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
282       var frame = Math.round(pos * this.options.fps * this.options.duration);
283       if(frame > this.currentFrame) {
284         this.render(pos);
285         this.currentFrame = frame;
286       }
287     }
288   },
289   render: function(pos) {
290     if(this.state == 'idle') {
291       this.state = 'running';
292       this.event('beforeSetup');
293       if(this.setup) this.setup();
294       this.event('afterSetup');
295     }
296     if(this.state == 'running') {
297       if(this.options.transition) pos = this.options.transition(pos);
298       pos *= (this.options.to-this.options.from);
299       pos += this.options.from;
300       this.position = pos;
301       this.event('beforeUpdate');
302       if(this.update) this.update(pos);
303       this.event('afterUpdate');
304     }
305   },
306   cancel: function() {
307     if(!this.options.sync)
308       Effect.Queues.get(typeof this.options.queue == 'string' ? 
309         'global' : this.options.queue.scope).remove(this);
310     this.state = 'finished';
311   },
312   event: function(eventName) {
313     if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
314     if(this.options[eventName]) this.options[eventName](this);
315   },
316   inspect: function() {
317     var data = $H();
318     for(property in this)
319       if(typeof this[property] != 'function') data[property] = this[property];
320     return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
321   }
322 }
323 
324 Effect.Parallel = Class.create();
325 Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
326   initialize: function(effects) {
327     this.effects = effects || [];
328     this.start(arguments[1]);
329   },
330   update: function(position) {
331     this.effects.invoke('render', position);
332   },
333   finish: function(position) {
334     this.effects.each( function(effect) {
335       effect.render(1.0);
336       effect.cancel();
337       effect.event('beforeFinish');
338       if(effect.finish) effect.finish(position);
339       effect.event('afterFinish');
340     });
341   }
342 });
343 
344 Effect.Event = Class.create();
345 Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
346   initialize: function() {
347     var options = Object.extend({
348       duration: 0
349     }, arguments[0] || {});
350     this.start(options);
351   },
352   update: Prototype.emptyFunction
353 });
354 
355 Effect.Opacity = Class.create();
356 Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
357   initialize: function(element) {
358     this.element = $(element);
359     if(!this.element) throw(Effect._elementDoesNotExistError);
360     // make this work on IE on elements without 'layout'
361     if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
362       this.element.setStyle({zoom: 1});
363     var options = Object.extend({
364       from: this.element.getOpacity() || 0.0,
365       to:   1.0
366     }, arguments[1] || {});
367     this.start(options);
368   },
369   update: function(position) {
370     this.element.setOpacity(position);
371   }
372 });
373 
374 Effect.Move = Class.create();
375 Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
376   initialize: function(element) {
377     this.element = $(element);
378     if(!this.element) throw(Effect._elementDoesNotExistError);
379     var options = Object.extend({
380       x:    0,
381       y:    0,
382       mode: 'relative'
383     }, arguments[1] || {});
384     this.start(options);
385   },
386   setup: function() {
387     // Bug in Opera: Opera returns the "real" position of a static element or
388     // relative element that does not have top/left explicitly set.
389     // ==> Always set top and left for position relative elements in your stylesheets 
390     // (to 0 if you do not need them) 
391     this.element.makePositioned();
392     this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
393     this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
394     if(this.options.mode == 'absolute') {
395       // absolute movement, so we need to calc deltaX and deltaY
396       this.options.x = this.options.x - this.originalLeft;
397       this.options.y = this.options.y - this.originalTop;
398     }
399   },
400   update: function(position) {
401     this.element.setStyle({
402       left: Math.round(this.options.x  * position + this.originalLeft) + 'px',
403       top:  Math.round(this.options.y  * position + this.originalTop)  + 'px'
404     });
405   }
406 });
407 
408 // for backwards compatibility
409 Effect.MoveBy = function(element, toTop, toLeft) {
410   return new Effect.Move(element, 
411     Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
412 };
413 
414 Effect.Scale = Class.create();
415 Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
416   initialize: function(element, percent) {
417     this.element = $(element);
418     if(!this.element) throw(Effect._elementDoesNotExistError);
419     var options = Object.extend({
420       scaleX: true,
421       scaleY: true,
422       scaleContent: true,
423       scaleFromCenter: false,
424       scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
425       scaleFrom: 100.0,
426       scaleTo:   percent
427     }, arguments[2] || {});
428     this.start(options);
429   },
430   setup: function() {
431     this.restoreAfterFinish = this.options.restoreAfterFinish || false;
432     this.elementPositioning = this.element.getStyle('position');
433     
434     this.originalStyle = {};
435     ['top','left','width','height','fontSize'].each( function(k) {
436       this.originalStyle[k] = this.element.style[k];
437     }.bind(this));
438       
439     this.originalTop  = this.element.offsetTop;
440     this.originalLeft = this.element.offsetLeft;
441     
442     var fontSize = this.element.getStyle('font-size') || '100%';
443     ['em','px','%','pt'].each( function(fontSizeType) {
444       if(fontSize.indexOf(fontSizeType)>0) {
445         this.fontSize     = parseFloat(fontSize);
446         this.fontSizeType = fontSizeType;
447       }
448     }.bind(this));
449     
450     this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
451     
452     this.dims = null;
453     if(this.options.scaleMode=='box')
454       this.dims = [this.element.offsetHeight, this.element.offsetWidth];
455     if(/^content/.test(this.options.scaleMode))
456       this.dims = [this.element.scrollHeight, this.element.scrollWidth];
457     if(!this.dims)
458       this.dims = [this.options.scaleMode.originalHeight,
459                    this.options.scaleMode.originalWidth];
460   },
461   update: function(position) {
462     var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
463     if(this.options.scaleContent && this.fontSize)
464       this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
465     this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
466   },
467   finish: function(position) {
468     if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
469   },
470   setDimensions: function(height, width) {
471     var d = {};
472     if(this.options.scaleX) d.width = Math.round(width) + 'px';
473     if(this.options.scaleY) d.height = Math.round(height) + 'px';
474     if(this.options.scaleFromCenter) {
475       var topd  = (height - this.dims[0])/2;
476       var leftd = (width  - this.dims[1])/2;
477       if(this.elementPositioning == 'absolute') {
478         if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
479         if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
480       } else {
481         if(this.options.scaleY) d.top = -topd + 'px';
482         if(this.options.scaleX) d.left = -leftd + 'px';
483       }
484     }
485     this.element.setStyle(d);
486   }
487 });
488 
489 Effect.Highlight = Class.create();
490 Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
491   initialize: function(element) {
492     this.element = $(element);
493     if(!this.element) throw(Effect._elementDoesNotExistError);
494     var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
495     this.start(options);
496   },
497   setup: function() {
498     // Prevent executing on elements not in the layout flow
499     if(this.element.getStyle('display')=='none') { this.cancel(); return; }
500     // Disable background image during the effect
501     this.oldStyle = {};
502     if (!this.options.keepBackgroundImage) {
503       this.oldStyle.backgroundImage = this.element.getStyle('background-image');
504       this.element.setStyle({backgroundImage: 'none'});
505     }
506     if(!this.options.endcolor)
507       this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
508     if(!this.options.restorecolor)
509       this.options.restorecolor = this.element.getStyle('background-color');
510     // init color calculations
511     this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
512     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));
513   },
514   update: function(position) {
515     this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
516       return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
517   },
518   finish: function() {
519     this.element.setStyle(Object.extend(this.oldStyle, {
520       backgroundColor: this.options.restorecolor
521     }));
522   }
523 });
524 
525 Effect.ScrollTo = Class.create();
526 Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
527   initialize: function(element) {
528     this.element = $(element);
529     this.start(arguments[1] || {});
530   },
531   setup: function() {
532     Position.prepare();
533     var offsets = Position.cumulativeOffset(this.element);
534     if(this.options.offset) offsets[1] += this.options.offset;
535     var max = window.innerHeight ? 
536       window.height - window.innerHeight :
537       document.body.scrollHeight - 
538         (document.documentElement.clientHeight ? 
539           document.documentElement.clientHeight : document.body.clientHeight);
540     this.scrollStart = Position.deltaY;
541     this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
542   },
543   update: function(position) {
544     Position.prepare();
545     window.scrollTo(Position.deltaX, 
546       this.scrollStart + (position*this.delta));
547   }
548 });
549 
550 /* ------------- combination effects ------------- */
551 
552 Effect.Fade = function(element) {
553   element = $(element);
554   var oldOpacity = element.getInlineOpacity();
555   var options = Object.extend({
556   from: element.getOpacity() || 1.0,
557   to:   0.0,
558   afterFinishInternal: function(effect) { 
559     if(effect.options.to!=0) return;
560     effect.element.hide().setStyle({opacity: oldOpacity}); 
561   }}, arguments[1] || {});
562   return new Effect.Opacity(element,options);
563 }
564 
565 Effect.Appear = function(element) {
566   element = $(element);
567   var options = Object.extend({
568   from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
569   to:   1.0,
570   // force Safari to render floated elements properly
571   afterFinishInternal: function(effect) {
572     effect.element.forceRerendering();
573   },
574   beforeSetup: function(effect) {
575     effect.element.setOpacity(effect.options.from).show(); 
576   }}, arguments[1] || {});
577   return new Effect.Opacity(element,options);
578 }
579 
580 Effect.Puff = function(element) {
581   element = $(element);
582   var oldStyle = { 
583     opacity: element.getInlineOpacity(), 
584     position: element.getStyle('position'),
585     top:  element.style.top,
586     left: element.style.left,
587     width: element.style.width,
588     height: element.style.height
589   };
590   return new Effect.Parallel(
591    [ new Effect.Scale(element, 200, 
592       { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
593      new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
594      Object.extend({ duration: 1.0, 
595       beforeSetupInternal: function(effect) {
596         Position.absolutize(effect.effects[0].element)
597       },
598       afterFinishInternal: function(effect) {
599          effect.effects[0].element.hide().setStyle(oldStyle); }
600      }, arguments[1] || {})
601    );
602 }
603 
604 Effect.BlindUp = function(element) {
605   element = $(element);
606   element.makeClipping();
607   return new Effect.Scale(element, 0,
608     Object.extend({ scaleContent: false, 
609       scaleX: false, 
610       restoreAfterFinish: true,
611       afterFinishInternal: function(effect) {
612         effect.element.hide().undoClipping();
613       } 
614     }, arguments[1] || {})
615   );
616 }
617 
618 Effect.BlindDown = function(element) {
619   element = $(element);
620   var elementDimensions = element.getDimensions();
621   return new Effect.Scale(element, 100, Object.extend({ 
622     scaleContent: false, 
623     scaleX: false,
624     scaleFrom: 0,
625     scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
626     restoreAfterFinish: true,
627     afterSetup: function(effect) {
628       effect.element.makeClipping().setStyle({height: '0px'}).show(); 
629     },  
630     afterFinishInternal: function(effect) {
631       effect.element.undoClipping();
632     }
633   }, arguments[1] || {}));
634 }
635 
636 Effect.SwitchOff = function(element) {
637   element = $(element);
638   var oldOpacity = element.getInlineOpacity();
639   return new Effect.Appear(element, Object.extend({
640     duration: 0.4,
641     from: 0,
642     transition: Effect.Transitions.flicker,
643     afterFinishInternal: function(effect) {
644       new Effect.Scale(effect.element, 1, { 
645         duration: 0.3, scaleFromCenter: true,
646         scaleX: false, scaleContent: false, restoreAfterFinish: true,
647         beforeSetup: function(effect) { 
648           effect.element.makePositioned().makeClipping();
649         },
650         afterFinishInternal: function(effect) {
651           effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
652         }
653       })
654     }
655   }, arguments[1] || {}));
656 }
657 
658 Effect.DropOut = function(element) {
659   element = $(element);
660   var oldStyle = {
661     top: element.getStyle('top'),
662     left: element.getStyle('left'),
663     opacity: element.getInlineOpacity() };
664   return new Effect.Parallel(
665     [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
666       new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
667     Object.extend(
668       { duration: 0.5,
669         beforeSetup: function(effect) {
670           effect.effects[0].element.makePositioned(); 
671         },
672         afterFinishInternal: function(effect) {
673           effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
674         } 
675       }, arguments[1] || {}));
676 }
677 
678 Effect.Shake = function(element) {
679   element = $(element);
680   var oldStyle = {
681     top: element.getStyle('top'),
682     left: element.getStyle('left') };
683     return new Effect.Move(element, 
684       { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
685     new Effect.Move(effect.element,
686       { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
687     new Effect.Move(effect.element,
688       { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
689     new Effect.Move(effect.element,
690       { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
691     new Effect.Move(effect.element,
692       { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
693     new Effect.Move(effect.element,
694       { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
695         effect.element.undoPositioned().setStyle(oldStyle);
696   }}) }}) }}) }}) }}) }});
697 }
698 
699 Effect.SlideDown = function(element) {
700   element = $(element).cleanWhitespace();
701   // SlideDown need to have the content of the element wrapped in a container element with fixed height!
702   var oldInnerBottom = element.down().getStyle('bottom');
703   var elementDimensions = element.getDimensions();
704   return new Effect.Scale(element, 100, Object.extend({ 
705     scaleContent: false, 
706     scaleX: false, 
707     scaleFrom: window.opera ? 0 : 1,
708     scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
709     restoreAfterFinish: true,
710     afterSetup: function(effect) {
711       effect.element.makePositioned();
712       effect.element.down().makePositioned();
713       if(window.opera) effect.element.setStyle({top: ''});
714       effect.element.makeClipping().setStyle({height: '0px'}).show(); 
715     },
716     afterUpdateInternal: function(effect) {
717       effect.element.down().setStyle({bottom:
718         (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
719     },
720     afterFinishInternal: function(effect) {
721       effect.element.undoClipping().undoPositioned();
722       effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
723     }, arguments[1] || {})
724   );
725 }
726 
727 Effect.SlideUp = function(element) {
728   element = $(element).cleanWhitespace();
729   var oldInnerBottom = element.down().getStyle('bottom');
730   return new Effect.Scale(element, window.opera ? 0 : 1,
731    Object.extend({ scaleContent: false, 
732     scaleX: false, 
733     scaleMode: 'box',
734     scaleFrom: 100,
735     restoreAfterFinish: true,
736     beforeStartInternal: function(effect) {
737       effect.element.makePositioned();
738       effect.element.down().makePositioned();
739       if(window.opera) effect.element.setStyle({top: ''});
740       effect.element.makeClipping().show();
741     },  
742     afterUpdateInternal: function(effect) {
743       effect.element.down().setStyle({bottom:
744         (effect.dims[0] - effect.element.clientHeight) + 'px' });
745     },
746     afterFinishInternal: function(effect) {
747       effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
748       effect.element.down().undoPositioned();
749     }
750    }, arguments[1] || {})
751   );
752 }
753 
754 // Bug in opera makes the TD containing this element expand for a instance after finish 
755 Effect.Squish = function(element) {
756   return new Effect.Scale(element, window.opera ? 1 : 0, { 
757     restoreAfterFinish: true,
758     beforeSetup: function(effect) {
759       effect.element.makeClipping(); 
760     },  
761     afterFinishInternal: function(effect) {
762       effect.element.hide().undoClipping(); 
763     }
764   });
765 }
766 
767 Effect.Grow = function(element) {
768   element = $(element);
769   var options = Object.extend({
770     direction: 'center',
771     moveTransition: Effect.Transitions.sinoidal,
772     scaleTransition: Effect.Transitions.sinoidal,
773     opacityTransition: Effect.Transitions.full
774   }, arguments[1] || {});
775   var oldStyle = {
776     top: element.style.top,
777     left: element.style.left,
778     height: element.style.height,
779     width: element.style.width,
780     opacity: element.getInlineOpacity() };
781 
782   var dims = element.getDimensions();    
783   var initialMoveX, initialMoveY;
784   var moveX, moveY;
785   
786   switch (options.direction) {
787     case 'top-left':
788       initialMoveX = initialMoveY = moveX = moveY = 0; 
789       break;
790     case 'top-right':
791       initialMoveX = dims.width;
792       initialMoveY = moveY = 0;
793       moveX = -dims.width;
794       break;
795     case 'bottom-left':
796       initialMoveX = moveX = 0;
797       initialMoveY = dims.height;
798       moveY = -dims.height;
799       break;
800     case 'bottom-right':
801       initialMoveX = dims.width;
802       initialMoveY = dims.height;
803       moveX = -dims.width;
804       moveY = -dims.height;
805       break;
806     case 'center':
807       initialMoveX = dims.width / 2;
808       initialMoveY = dims.height / 2;
809       moveX = -dims.width / 2;
810       moveY = -dims.height / 2;
811       break;
812   }
813   
814   return new Effect.Move(element, {
815     x: initialMoveX,
816     y: initialMoveY,
817     duration: 0.01, 
818     beforeSetup: function(effect) {
819       effect.element.hide().makeClipping().makePositioned();
820     },
821     afterFinishInternal: function(effect) {
822       new Effect.Parallel(
823         [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
824           new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
825           new Effect.Scale(effect.element, 100, {
826             scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
827             sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
828         ], Object.extend({
829              beforeSetup: function(effect) {
830                effect.effects[0].element.setStyle({height: '0px'}).show(); 
831              },
832              afterFinishInternal: function(effect) {
833                effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); 
834              }
835            }, options)
836       )
837     }
838   });
839 }
840 
841 Effect.Shrink = function(element) {
842   element = $(element);
843   var options = Object.extend({
844     direction: 'center',
845     moveTransition: Effect.Transitions.sinoidal,
846     scaleTransition: Effect.Transitions.sinoidal,
847     opacityTransition: Effect.Transitions.none
848   }, arguments[1] || {});
849   var oldStyle = {
850     top: element.style.top,
851     left: element.style.left,
852     height: element.style.height,
853     width: element.style.width,
854     opacity: element.getInlineOpacity() };
855 
856   var dims = element.getDimensions();
857   var moveX, moveY;
858   
859   switch (options.direction) {
860     case 'top-left':
861       moveX = moveY = 0;
862       break;
863     case 'top-right':
864       moveX = dims.width;
865       moveY = 0;
866       break;
867     case 'bottom-left':
868       moveX = 0;
869       moveY = dims.height;
870       break;
871     case 'bottom-right':
872       moveX = dims.width;
873       moveY = dims.height;
874       break;
875     case 'center':  
876       moveX = dims.width / 2;
877       moveY = dims.height / 2;
878       break;
879   }
880   
881   return new Effect.Parallel(
882     [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
883       new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
884       new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
885     ], Object.extend({            
886          beforeStartInternal: function(effect) {
887            effect.effects[0].element.makePositioned().makeClipping(); 
888          },
889          afterFinishInternal: function(effect) {
890            effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
891        }, options)
892   );
893 }
894 
895 Effect.Pulsate = function(element) {
896   element = $(element);
897   var options    = arguments[1] || {};
898   var oldOpacity = element.getInlineOpacity();
899   var transition = options.transition || Effect.Transitions.sinoidal;
900   var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
901   reverser.bind(transition);
902   return new Effect.Opacity(element, 
903     Object.extend(Object.extend({  duration: 2.0, from: 0,
904       afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
905     }, options), {transition: reverser}));
906 }
907 
908 Effect.Fold = function(element) {
909   element = $(element);
910   var oldStyle = {
911     top: element.style.top,
912     left: element.style.left,
913     width: element.style.width,
914     height: element.style.height };
915   element.makeClipping();
916   return new Effect.Scale(element, 5, Object.extend({   
917     scaleContent: false,
918     scaleX: false,
919     afterFinishInternal: function(effect) {
920     new Effect.Scale(element, 1, { 
921       scaleContent: false, 
922       scaleY: false,
923       afterFinishInternal: function(effect) {
924         effect.element.hide().undoClipping().setStyle(oldStyle);
925       } });
926   }}, arguments[1] || {}));
927 };
928 
929 Effect.Morph = Class.create();
930 Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
931   initialize: function(element) {
932     this.element = $(element);
933     if(!this.element) throw(Effect._elementDoesNotExistError);
934     var options = Object.extend({
935       style: {}
936     }, arguments[1] || {});
937     if (typeof options.style == 'string') {
938       if(options.style.indexOf(':') == -1) {
939         var cssText = '', selector = '.' + options.style;
940         $A(document.styleSheets).reverse().each(function(styleSheet) {
941           if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
942           else if (styleSheet.rules) cssRules = styleSheet.rules;
943           $A(cssRules).reverse().each(function(rule) {
944             if (selector == rule.selectorText) {
945               cssText = rule.style.cssText;
946               throw $break;
947             }
948           });
949           if (cssText) throw $break;
950         });
951         this.style = cssText.parseStyle();
952         options.afterFinishInternal = function(effect){
953           effect.element.addClassName(effect.options.style);
954           effect.transforms.each(function(transform) {
955             if(transform.style != 'opacity')
956               effect.element.style[transform.style.camelize()] = '';
957           });
958         }
959       } else this.style = options.style.parseStyle();
960     } else this.style = $H(options.style)
961     this.start(options);
962   },
963   setup: function(){
964     function parseColor(color){
965       if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
966       color = color.parseColor();
967       return $R(0,2).map(function(i){
968         return parseInt( color.slice(i*2+1,i*2+3), 16 ) 
969       });
970     }
971     this.transforms = this.style.map(function(pair){
972       var property = pair[0].underscore().dasherize(), value = pair[1], unit = null;
973 
974       if(value.parseColor('#zzzzzz') != '#zzzzzz') {
975         value = value.parseColor();
976         unit  = 'color';
977       } else if(property == 'opacity') {
978         value = parseFloat(value);
979         if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
980           this.element.setStyle({zoom: 1});
981       } else if(Element.CSS_LENGTH.test(value)) 
982         var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
983           value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
984 
985       var originalValue = this.element.getStyle(property);
986       return $H({ 
987         style: property, 
988         originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), 
989         targetValue: unit=='color' ? parseColor(value) : value,
990         unit: unit
991       });
992     }.bind(this)).reject(function(transform){
993       return (
994         (transform.originalValue == transform.targetValue) ||
995         (
996           transform.unit != 'color' &&
997           (isNaN(transform.originalValue) || isNaN(transform.targetValue))
998         )
999       )
1000     });
1001   },
1002   update: function(position) {
1003     var style = $H(), value = null;
1004     this.transforms.each(function(transform){
1005       value = transform.unit=='color' ?
1006         $R(0,2).inject('#',function(m,v,i){
1007           return m+(Math.round(transform.originalValue[i]+
1008             (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : 
1009         transform.originalValue + Math.round(
1010           ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
1011       style[transform.style] = value;
1012     });
1013     this.element.setStyle(style);
1014   }
1015 });
1016 
1017 Effect.Transform = Class.create();
1018 Object.extend(Effect.Transform.prototype, {
1019   initialize: function(tracks){
1020     this.tracks  = [];
1021     this.options = arguments[1] || {};
1022     this.addTracks(tracks);
1023   },
1024   addTracks: function(tracks){
1025     tracks.each(function(track){
1026       var data = $H(track).values().first();
1027       this.tracks.push($H({
1028         ids:     $H(track).keys().first(),
1029         effect:  Effect.Morph,
1030         options: { style: data }
1031       }));
1032     }.bind(this));
1033     return this;
1034   },
1035   play: function(){
1036     return new Effect.Parallel(
1037       this.tracks.map(function(track){
1038         var elements = [$(track.ids) || $$(track.ids)].flatten();
1039         return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
1040       }).flatten(),
1041       this.options
1042     );
1043   }
1044 });
1045 
1046 Element.CSS_PROPERTIES = $w(
1047   'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 
1048   'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1049   'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1050   'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1051   'fontSize fontWeight height left letterSpacing lineHeight ' +
1052   'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1053   'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1054   'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1055   'right textIndent top width wordSpacing zIndex');
1056   
1057 Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1058 
1059 String.prototype.parseStyle = function(){
1060   var element = Element.extend(document.createElement('div'));
1061   element.innerHTML = '<div style="' + this + '"></div>';
1062   var style = element.down().style, styleRules = $H();
1063   
1064   Element.CSS_PROPERTIES.each(function(property){
1065     if(style[property]) styleRules[property] = style[property]; 
1066   });
1067   if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) {
1068     styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
1069   }
1070   return styleRules;
1071 };
1072 
1073 Element.morph = function(element, style) {
1074   new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
1075   return element;
1076 };
1077 
1078 ['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
1079  'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( 
1080   function(f) { Element.Methods[f] = Element[f]; }
1081 );
1082 
1083 Element.Methods.visualEffect = function(element, effect, options) {
1084   s = effect.gsub(/_/, '-').camelize();
1085   effect_class = s.charAt(0).toUpperCase() + s.substring(1);
1086   new Effect[effect_class](element, options);
1087   return $(element);
1088 };
1089 
1090 Element.addMethods();

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!