PageSourceSearch

https://koregos.org/Koregos/OWS/validation1.5.4.1/EN/scriptaculous/src/effects.js

js koregos.org collected 2026-10-02 11:43:06 UTC 38,042 bytes, 1,079 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.