dom/tests/mochitest/ajax/scriptaculous/src/effects.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/tests/mochitest/ajax/scriptaculous/src/effects.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1094 @@
     1.4 +// script.aculo.us effects.js v1.7.1_beta2, Tue May 15 15:15:45 EDT 2007
     1.5 +
     1.6 +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
     1.7 +// Contributors:
     1.8 +//  Justin Palmer (http://encytemedia.com/)
     1.9 +//  Mark Pilgrim (http://diveintomark.org/)
    1.10 +//  Martin Bialasinki
    1.11 +// 
    1.12 +// script.aculo.us is freely distributable under the terms of an MIT-style license.
    1.13 +// For details, see the script.aculo.us web site: http://script.aculo.us/ 
    1.14 +
    1.15 +// converts rgb() and #xxx to #xxxxxx format,  
    1.16 +// returns self (or first argument) if not convertable  
    1.17 +String.prototype.parseColor = function() {  
    1.18 +  var color = '#';
    1.19 +  if(this.slice(0,4) == 'rgb(') {  
    1.20 +    var cols = this.slice(4,this.length-1).split(',');  
    1.21 +    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
    1.22 +  } else {  
    1.23 +    if(this.slice(0,1) == '#') {  
    1.24 +      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
    1.25 +      if(this.length==7) color = this.toLowerCase();  
    1.26 +    }  
    1.27 +  }  
    1.28 +  return(color.length==7 ? color : (arguments[0] || this));  
    1.29 +}
    1.30 +
    1.31 +/*--------------------------------------------------------------------------*/
    1.32 +
    1.33 +Element.collectTextNodes = function(element) {  
    1.34 +  return $A($(element).childNodes).collect( function(node) {
    1.35 +    return (node.nodeType==3 ? node.nodeValue : 
    1.36 +      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
    1.37 +  }).flatten().join('');
    1.38 +}
    1.39 +
    1.40 +Element.collectTextNodesIgnoreClass = function(element, className) {  
    1.41 +  return $A($(element).childNodes).collect( function(node) {
    1.42 +    return (node.nodeType==3 ? node.nodeValue : 
    1.43 +      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
    1.44 +        Element.collectTextNodesIgnoreClass(node, className) : ''));
    1.45 +  }).flatten().join('');
    1.46 +}
    1.47 +
    1.48 +Element.setContentZoom = function(element, percent) {
    1.49 +  element = $(element);  
    1.50 +  element.setStyle({fontSize: (percent/100) + 'em'});   
    1.51 +  if(Prototype.Browser.WebKit) window.scrollBy(0,0);
    1.52 +  return element;
    1.53 +}
    1.54 +
    1.55 +Element.getInlineOpacity = function(element){
    1.56 +  return $(element).style.opacity || '';
    1.57 +}
    1.58 +
    1.59 +Element.forceRerendering = function(element) {
    1.60 +  try {
    1.61 +    element = $(element);
    1.62 +    var n = document.createTextNode(' ');
    1.63 +    element.appendChild(n);
    1.64 +    element.removeChild(n);
    1.65 +  } catch(e) { }
    1.66 +};
    1.67 +
    1.68 +/*--------------------------------------------------------------------------*/
    1.69 +
    1.70 +Array.prototype.call = function() {
    1.71 +  var args = arguments;
    1.72 +  this.each(function(f){ f.apply(this, args) });
    1.73 +}
    1.74 +
    1.75 +/*--------------------------------------------------------------------------*/
    1.76 +
    1.77 +var Effect = {
    1.78 +  _elementDoesNotExistError: {
    1.79 +    name: 'ElementDoesNotExistError',
    1.80 +    message: 'The specified DOM element does not exist, but is required for this effect to operate'
    1.81 +  },
    1.82 +  tagifyText: function(element) {
    1.83 +    if(typeof Builder == 'undefined')
    1.84 +      throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
    1.85 +      
    1.86 +    var tagifyStyle = 'position:relative';
    1.87 +    if(Prototype.Browser.IE) tagifyStyle += ';zoom:1';
    1.88 +    
    1.89 +    element = $(element);
    1.90 +    $A(element.childNodes).each( function(child) {
    1.91 +      if(child.nodeType==3) {
    1.92 +        child.nodeValue.toArray().each( function(character) {
    1.93 +          element.insertBefore(
    1.94 +            Builder.node('span',{style: tagifyStyle},
    1.95 +              character == ' ' ? String.fromCharCode(160) : character), 
    1.96 +              child);
    1.97 +        });
    1.98 +        Element.remove(child);
    1.99 +      }
   1.100 +    });
   1.101 +  },
   1.102 +  multiple: function(element, effect) {
   1.103 +    var elements;
   1.104 +    if(((typeof element == 'object') || 
   1.105 +        (typeof element == 'function')) && 
   1.106 +       (element.length))
   1.107 +      elements = element;
   1.108 +    else
   1.109 +      elements = $(element).childNodes;
   1.110 +      
   1.111 +    var options = Object.extend({
   1.112 +      speed: 0.1,
   1.113 +      delay: 0.0
   1.114 +    }, arguments[2] || {});
   1.115 +    var masterDelay = options.delay;
   1.116 +
   1.117 +    $A(elements).each( function(element, index) {
   1.118 +      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
   1.119 +    });
   1.120 +  },
   1.121 +  PAIRS: {
   1.122 +    'slide':  ['SlideDown','SlideUp'],
   1.123 +    'blind':  ['BlindDown','BlindUp'],
   1.124 +    'appear': ['Appear','Fade']
   1.125 +  },
   1.126 +  toggle: function(element, effect) {
   1.127 +    element = $(element);
   1.128 +    effect = (effect || 'appear').toLowerCase();
   1.129 +    var options = Object.extend({
   1.130 +      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
   1.131 +    }, arguments[2] || {});
   1.132 +    Effect[element.visible() ? 
   1.133 +      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
   1.134 +  }
   1.135 +};
   1.136 +
   1.137 +var Effect2 = Effect; // deprecated
   1.138 +
   1.139 +/* ------------- transitions ------------- */
   1.140 +
   1.141 +Effect.Transitions = {
   1.142 +  linear: Prototype.K,
   1.143 +  sinoidal: function(pos) {
   1.144 +    return (-Math.cos(pos*Math.PI)/2) + 0.5;
   1.145 +  },
   1.146 +  reverse: function(pos) {
   1.147 +    return 1-pos;
   1.148 +  },
   1.149 +  flicker: function(pos) {
   1.150 +    var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
   1.151 +    return (pos > 1 ? 1 : pos);
   1.152 +  },
   1.153 +  wobble: function(pos) {
   1.154 +    return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
   1.155 +  },
   1.156 +  pulse: function(pos, pulses) { 
   1.157 +    pulses = pulses || 5; 
   1.158 +    return (
   1.159 +      Math.round((pos % (1/pulses)) * pulses) == 0 ? 
   1.160 +            ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : 
   1.161 +        1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
   1.162 +      );
   1.163 +  },
   1.164 +  none: function(pos) {
   1.165 +    return 0;
   1.166 +  },
   1.167 +  full: function(pos) {
   1.168 +    return 1;
   1.169 +  }
   1.170 +};
   1.171 +
   1.172 +/* ------------- core effects ------------- */
   1.173 +
   1.174 +Effect.ScopedQueue = Class.create();
   1.175 +Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
   1.176 +  initialize: function() {
   1.177 +    this.effects  = [];
   1.178 +    this.interval = null;    
   1.179 +  },
   1.180 +  _each: function(iterator) {
   1.181 +    this.effects._each(iterator);
   1.182 +  },
   1.183 +  add: function(effect) {
   1.184 +    var timestamp = new Date().getTime();
   1.185 +    
   1.186 +    var position = (typeof effect.options.queue == 'string') ? 
   1.187 +      effect.options.queue : effect.options.queue.position;
   1.188 +    
   1.189 +    switch(position) {
   1.190 +      case 'front':
   1.191 +        // move unstarted effects after this effect  
   1.192 +        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
   1.193 +            e.startOn  += effect.finishOn;
   1.194 +            e.finishOn += effect.finishOn;
   1.195 +          });
   1.196 +        break;
   1.197 +      case 'with-last':
   1.198 +        timestamp = this.effects.pluck('startOn').max() || timestamp;
   1.199 +        break;
   1.200 +      case 'end':
   1.201 +        // start effect after last queued effect has finished
   1.202 +        timestamp = this.effects.pluck('finishOn').max() || timestamp;
   1.203 +        break;
   1.204 +    }
   1.205 +    
   1.206 +    effect.startOn  += timestamp;
   1.207 +    effect.finishOn += timestamp;
   1.208 +
   1.209 +    if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
   1.210 +      this.effects.push(effect);
   1.211 +    
   1.212 +    if(!this.interval)
   1.213 +      this.interval = setInterval(this.loop.bind(this), 15);
   1.214 +  },
   1.215 +  remove: function(effect) {
   1.216 +    this.effects = this.effects.reject(function(e) { return e==effect });
   1.217 +    if(this.effects.length == 0) {
   1.218 +      clearInterval(this.interval);
   1.219 +      this.interval = null;
   1.220 +    }
   1.221 +  },
   1.222 +  loop: function() {
   1.223 +    var timePos = new Date().getTime();
   1.224 +    for(var i=0, len=this.effects.length;i<len;i++) 
   1.225 +      this.effects[i] && this.effects[i].loop(timePos);
   1.226 +  }
   1.227 +});
   1.228 +
   1.229 +Effect.Queues = {
   1.230 +  instances: $H(),
   1.231 +  get: function(queueName) {
   1.232 +    if(typeof queueName != 'string') return queueName;
   1.233 +    
   1.234 +    if(!this.instances[queueName])
   1.235 +      this.instances[queueName] = new Effect.ScopedQueue();
   1.236 +      
   1.237 +    return this.instances[queueName];
   1.238 +  }
   1.239 +}
   1.240 +Effect.Queue = Effect.Queues.get('global');
   1.241 +
   1.242 +Effect.DefaultOptions = {
   1.243 +  transition: Effect.Transitions.sinoidal,
   1.244 +  duration:   1.0,   // seconds
   1.245 +  fps:        100,   // 100= assume 66fps max.
   1.246 +  sync:       false, // true for combining
   1.247 +  from:       0.0,
   1.248 +  to:         1.0,
   1.249 +  delay:      0.0,
   1.250 +  queue:      'parallel'
   1.251 +}
   1.252 +
   1.253 +Effect.Base = function() {};
   1.254 +Effect.Base.prototype = {
   1.255 +  position: null,
   1.256 +  start: function(options) {
   1.257 +    function codeForEvent(options,eventName){
   1.258 +      return (
   1.259 +        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
   1.260 +        (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
   1.261 +      );
   1.262 +    }
   1.263 +    if(options.transition === false) options.transition = Effect.Transitions.linear;
   1.264 +    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
   1.265 +    this.currentFrame = 0;
   1.266 +    this.state        = 'idle';
   1.267 +    this.startOn      = this.options.delay*1000;
   1.268 +    this.finishOn     = this.startOn+(this.options.duration*1000);
   1.269 +    this.fromToDelta  = this.options.to-this.options.from;
   1.270 +    this.totalTime    = this.finishOn-this.startOn;
   1.271 +    this.totalFrames  = this.options.fps*this.options.duration;
   1.272 +    
   1.273 +    eval('this.render = function(pos){ '+
   1.274 +      'if(this.state=="idle"){this.state="running";'+
   1.275 +      codeForEvent(options,'beforeSetup')+
   1.276 +      (this.setup ? 'this.setup();':'')+ 
   1.277 +      codeForEvent(options,'afterSetup')+
   1.278 +      '};if(this.state=="running"){'+
   1.279 +      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
   1.280 +      'this.position=pos;'+
   1.281 +      codeForEvent(options,'beforeUpdate')+
   1.282 +      (this.update ? 'this.update(pos);':'')+
   1.283 +      codeForEvent(options,'afterUpdate')+
   1.284 +      '}}');
   1.285 +    
   1.286 +    this.event('beforeStart');
   1.287 +    if(!this.options.sync)
   1.288 +      Effect.Queues.get(typeof this.options.queue == 'string' ? 
   1.289 +        'global' : this.options.queue.scope).add(this);
   1.290 +  },
   1.291 +  loop: function(timePos) {
   1.292 +    if(timePos >= this.startOn) {
   1.293 +      if(timePos >= this.finishOn) {
   1.294 +        this.render(1.0);
   1.295 +        this.cancel();
   1.296 +        this.event('beforeFinish');
   1.297 +        if(this.finish) this.finish(); 
   1.298 +        this.event('afterFinish');
   1.299 +        return;  
   1.300 +      }
   1.301 +      var pos   = (timePos - this.startOn) / this.totalTime,
   1.302 +          frame = Math.round(pos * this.totalFrames);
   1.303 +      if(frame > this.currentFrame) {
   1.304 +        this.render(pos);
   1.305 +        this.currentFrame = frame;
   1.306 +      }
   1.307 +    }
   1.308 +  },
   1.309 +  cancel: function() {
   1.310 +    if(!this.options.sync)
   1.311 +      Effect.Queues.get(typeof this.options.queue == 'string' ? 
   1.312 +        'global' : this.options.queue.scope).remove(this);
   1.313 +    this.state = 'finished';
   1.314 +  },
   1.315 +  event: function(eventName) {
   1.316 +    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
   1.317 +    if(this.options[eventName]) this.options[eventName](this);
   1.318 +  },
   1.319 +  inspect: function() {
   1.320 +    var data = $H();
   1.321 +    for(property in this)
   1.322 +      if(typeof this[property] != 'function') data[property] = this[property];
   1.323 +    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
   1.324 +  }
   1.325 +}
   1.326 +
   1.327 +Effect.Parallel = Class.create();
   1.328 +Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
   1.329 +  initialize: function(effects) {
   1.330 +    this.effects = effects || [];
   1.331 +    this.start(arguments[1]);
   1.332 +  },
   1.333 +  update: function(position) {
   1.334 +    this.effects.invoke('render', position);
   1.335 +  },
   1.336 +  finish: function(position) {
   1.337 +    this.effects.each( function(effect) {
   1.338 +      effect.render(1.0);
   1.339 +      effect.cancel();
   1.340 +      effect.event('beforeFinish');
   1.341 +      if(effect.finish) effect.finish(position);
   1.342 +      effect.event('afterFinish');
   1.343 +    });
   1.344 +  }
   1.345 +});
   1.346 +
   1.347 +Effect.Event = Class.create();
   1.348 +Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
   1.349 +  initialize: function() {
   1.350 +    var options = Object.extend({
   1.351 +      duration: 0
   1.352 +    }, arguments[0] || {});
   1.353 +    this.start(options);
   1.354 +  },
   1.355 +  update: Prototype.emptyFunction
   1.356 +});
   1.357 +
   1.358 +Effect.Opacity = Class.create();
   1.359 +Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
   1.360 +  initialize: function(element) {
   1.361 +    this.element = $(element);
   1.362 +    if(!this.element) throw(Effect._elementDoesNotExistError);
   1.363 +    // make this work on IE on elements without 'layout'
   1.364 +    if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
   1.365 +      this.element.setStyle({zoom: 1});
   1.366 +    var options = Object.extend({
   1.367 +      from: this.element.getOpacity() || 0.0,
   1.368 +      to:   1.0
   1.369 +    }, arguments[1] || {});
   1.370 +    this.start(options);
   1.371 +  },
   1.372 +  update: function(position) {
   1.373 +    this.element.setOpacity(position);
   1.374 +  }
   1.375 +});
   1.376 +
   1.377 +Effect.Move = Class.create();
   1.378 +Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
   1.379 +  initialize: function(element) {
   1.380 +    this.element = $(element);
   1.381 +    if(!this.element) throw(Effect._elementDoesNotExistError);
   1.382 +    var options = Object.extend({
   1.383 +      x:    0,
   1.384 +      y:    0,
   1.385 +      mode: 'relative'
   1.386 +    }, arguments[1] || {});
   1.387 +    this.start(options);
   1.388 +  },
   1.389 +  setup: function() {
   1.390 +    // Bug in Opera: Opera returns the "real" position of a static element or
   1.391 +    // relative element that does not have top/left explicitly set.
   1.392 +    // ==> Always set top and left for position relative elements in your stylesheets 
   1.393 +    // (to 0 if you do not need them) 
   1.394 +    this.element.makePositioned();
   1.395 +    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
   1.396 +    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
   1.397 +    if(this.options.mode == 'absolute') {
   1.398 +      // absolute movement, so we need to calc deltaX and deltaY
   1.399 +      this.options.x = this.options.x - this.originalLeft;
   1.400 +      this.options.y = this.options.y - this.originalTop;
   1.401 +    }
   1.402 +  },
   1.403 +  update: function(position) {
   1.404 +    this.element.setStyle({
   1.405 +      left: Math.round(this.options.x  * position + this.originalLeft) + 'px',
   1.406 +      top:  Math.round(this.options.y  * position + this.originalTop)  + 'px'
   1.407 +    });
   1.408 +  }
   1.409 +});
   1.410 +
   1.411 +// for backwards compatibility
   1.412 +Effect.MoveBy = function(element, toTop, toLeft) {
   1.413 +  return new Effect.Move(element, 
   1.414 +    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
   1.415 +};
   1.416 +
   1.417 +Effect.Scale = Class.create();
   1.418 +Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
   1.419 +  initialize: function(element, percent) {
   1.420 +    this.element = $(element);
   1.421 +    if(!this.element) throw(Effect._elementDoesNotExistError);
   1.422 +    var options = Object.extend({
   1.423 +      scaleX: true,
   1.424 +      scaleY: true,
   1.425 +      scaleContent: true,
   1.426 +      scaleFromCenter: false,
   1.427 +      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
   1.428 +      scaleFrom: 100.0,
   1.429 +      scaleTo:   percent
   1.430 +    }, arguments[2] || {});
   1.431 +    this.start(options);
   1.432 +  },
   1.433 +  setup: function() {
   1.434 +    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
   1.435 +    this.elementPositioning = this.element.getStyle('position');
   1.436 +    
   1.437 +    this.originalStyle = {};
   1.438 +    ['top','left','width','height','fontSize'].each( function(k) {
   1.439 +      this.originalStyle[k] = this.element.style[k];
   1.440 +    }.bind(this));
   1.441 +      
   1.442 +    this.originalTop  = this.element.offsetTop;
   1.443 +    this.originalLeft = this.element.offsetLeft;
   1.444 +    
   1.445 +    var fontSize = this.element.getStyle('font-size') || '100%';
   1.446 +    ['em','px','%','pt'].each( function(fontSizeType) {
   1.447 +      if(fontSize.indexOf(fontSizeType)>0) {
   1.448 +        this.fontSize     = parseFloat(fontSize);
   1.449 +        this.fontSizeType = fontSizeType;
   1.450 +      }
   1.451 +    }.bind(this));
   1.452 +    
   1.453 +    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
   1.454 +    
   1.455 +    this.dims = null;
   1.456 +    if(this.options.scaleMode=='box')
   1.457 +      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
   1.458 +    if(/^content/.test(this.options.scaleMode))
   1.459 +      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
   1.460 +    if(!this.dims)
   1.461 +      this.dims = [this.options.scaleMode.originalHeight,
   1.462 +                   this.options.scaleMode.originalWidth];
   1.463 +  },
   1.464 +  update: function(position) {
   1.465 +    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
   1.466 +    if(this.options.scaleContent && this.fontSize)
   1.467 +      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
   1.468 +    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
   1.469 +  },
   1.470 +  finish: function(position) {
   1.471 +    if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
   1.472 +  },
   1.473 +  setDimensions: function(height, width) {
   1.474 +    var d = {};
   1.475 +    if(this.options.scaleX) d.width = Math.round(width) + 'px';
   1.476 +    if(this.options.scaleY) d.height = Math.round(height) + 'px';
   1.477 +    if(this.options.scaleFromCenter) {
   1.478 +      var topd  = (height - this.dims[0])/2;
   1.479 +      var leftd = (width  - this.dims[1])/2;
   1.480 +      if(this.elementPositioning == 'absolute') {
   1.481 +        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
   1.482 +        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
   1.483 +      } else {
   1.484 +        if(this.options.scaleY) d.top = -topd + 'px';
   1.485 +        if(this.options.scaleX) d.left = -leftd + 'px';
   1.486 +      }
   1.487 +    }
   1.488 +    this.element.setStyle(d);
   1.489 +  }
   1.490 +});
   1.491 +
   1.492 +Effect.Highlight = Class.create();
   1.493 +Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
   1.494 +  initialize: function(element) {
   1.495 +    this.element = $(element);
   1.496 +    if(!this.element) throw(Effect._elementDoesNotExistError);
   1.497 +    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
   1.498 +    this.start(options);
   1.499 +  },
   1.500 +  setup: function() {
   1.501 +    // Prevent executing on elements not in the layout flow
   1.502 +    if(this.element.getStyle('display')=='none') { this.cancel(); return; }
   1.503 +    // Disable background image during the effect
   1.504 +    this.oldStyle = {};
   1.505 +    if (!this.options.keepBackgroundImage) {
   1.506 +      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
   1.507 +      this.element.setStyle({backgroundImage: 'none'});
   1.508 +    }
   1.509 +    if(!this.options.endcolor)
   1.510 +      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
   1.511 +    if(!this.options.restorecolor)
   1.512 +      this.options.restorecolor = this.element.getStyle('background-color');
   1.513 +    // init color calculations
   1.514 +    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
   1.515 +    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));
   1.516 +  },
   1.517 +  update: function(position) {
   1.518 +    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
   1.519 +      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
   1.520 +  },
   1.521 +  finish: function() {
   1.522 +    this.element.setStyle(Object.extend(this.oldStyle, {
   1.523 +      backgroundColor: this.options.restorecolor
   1.524 +    }));
   1.525 +  }
   1.526 +});
   1.527 +
   1.528 +Effect.ScrollTo = Class.create();
   1.529 +Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
   1.530 +  initialize: function(element) {
   1.531 +    this.element = $(element);
   1.532 +    this.start(arguments[1] || {});
   1.533 +  },
   1.534 +  setup: function() {
   1.535 +    Position.prepare();
   1.536 +    var offsets = Position.cumulativeOffset(this.element);
   1.537 +    if(this.options.offset) offsets[1] += this.options.offset;
   1.538 +    var max = window.innerHeight ? 
   1.539 +      window.height - window.innerHeight :
   1.540 +      document.body.scrollHeight - 
   1.541 +        (document.documentElement.clientHeight ? 
   1.542 +          document.documentElement.clientHeight : document.body.clientHeight);
   1.543 +    this.scrollStart = Position.deltaY;
   1.544 +    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
   1.545 +  },
   1.546 +  update: function(position) {
   1.547 +    Position.prepare();
   1.548 +    window.scrollTo(Position.deltaX, 
   1.549 +      this.scrollStart + (position*this.delta));
   1.550 +  }
   1.551 +});
   1.552 +
   1.553 +/* ------------- combination effects ------------- */
   1.554 +
   1.555 +Effect.Fade = function(element) {
   1.556 +  element = $(element);
   1.557 +  var oldOpacity = element.getInlineOpacity();
   1.558 +  var options = Object.extend({
   1.559 +  from: element.getOpacity() || 1.0,
   1.560 +  to:   0.0,
   1.561 +  afterFinishInternal: function(effect) { 
   1.562 +    if(effect.options.to!=0) return;
   1.563 +    effect.element.hide().setStyle({opacity: oldOpacity}); 
   1.564 +  }}, arguments[1] || {});
   1.565 +  return new Effect.Opacity(element,options);
   1.566 +}
   1.567 +
   1.568 +Effect.Appear = function(element) {
   1.569 +  element = $(element);
   1.570 +  var options = Object.extend({
   1.571 +  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
   1.572 +  to:   1.0,
   1.573 +  // force Safari to render floated elements properly
   1.574 +  afterFinishInternal: function(effect) {
   1.575 +    effect.element.forceRerendering();
   1.576 +  },
   1.577 +  beforeSetup: function(effect) {
   1.578 +    effect.element.setOpacity(effect.options.from).show(); 
   1.579 +  }}, arguments[1] || {});
   1.580 +  return new Effect.Opacity(element,options);
   1.581 +}
   1.582 +
   1.583 +Effect.Puff = function(element) {
   1.584 +  element = $(element);
   1.585 +  var oldStyle = { 
   1.586 +    opacity: element.getInlineOpacity(), 
   1.587 +    position: element.getStyle('position'),
   1.588 +    top:  element.style.top,
   1.589 +    left: element.style.left,
   1.590 +    width: element.style.width,
   1.591 +    height: element.style.height
   1.592 +  };
   1.593 +  return new Effect.Parallel(
   1.594 +   [ new Effect.Scale(element, 200, 
   1.595 +      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
   1.596 +     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
   1.597 +     Object.extend({ duration: 1.0, 
   1.598 +      beforeSetupInternal: function(effect) {
   1.599 +        Position.absolutize(effect.effects[0].element)
   1.600 +      },
   1.601 +      afterFinishInternal: function(effect) {
   1.602 +         effect.effects[0].element.hide().setStyle(oldStyle); }
   1.603 +     }, arguments[1] || {})
   1.604 +   );
   1.605 +}
   1.606 +
   1.607 +Effect.BlindUp = function(element) {
   1.608 +  element = $(element);
   1.609 +  element.makeClipping();
   1.610 +  return new Effect.Scale(element, 0,
   1.611 +    Object.extend({ scaleContent: false, 
   1.612 +      scaleX: false, 
   1.613 +      restoreAfterFinish: true,
   1.614 +      afterFinishInternal: function(effect) {
   1.615 +        effect.element.hide().undoClipping();
   1.616 +      } 
   1.617 +    }, arguments[1] || {})
   1.618 +  );
   1.619 +}
   1.620 +
   1.621 +Effect.BlindDown = function(element) {
   1.622 +  element = $(element);
   1.623 +  var elementDimensions = element.getDimensions();
   1.624 +  return new Effect.Scale(element, 100, Object.extend({ 
   1.625 +    scaleContent: false, 
   1.626 +    scaleX: false,
   1.627 +    scaleFrom: 0,
   1.628 +    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
   1.629 +    restoreAfterFinish: true,
   1.630 +    afterSetup: function(effect) {
   1.631 +      effect.element.makeClipping().setStyle({height: '0px'}).show(); 
   1.632 +    },  
   1.633 +    afterFinishInternal: function(effect) {
   1.634 +      effect.element.undoClipping();
   1.635 +    }
   1.636 +  }, arguments[1] || {}));
   1.637 +}
   1.638 +
   1.639 +Effect.SwitchOff = function(element) {
   1.640 +  element = $(element);
   1.641 +  var oldOpacity = element.getInlineOpacity();
   1.642 +  return new Effect.Appear(element, Object.extend({
   1.643 +    duration: 0.4,
   1.644 +    from: 0,
   1.645 +    transition: Effect.Transitions.flicker,
   1.646 +    afterFinishInternal: function(effect) {
   1.647 +      new Effect.Scale(effect.element, 1, { 
   1.648 +        duration: 0.3, scaleFromCenter: true,
   1.649 +        scaleX: false, scaleContent: false, restoreAfterFinish: true,
   1.650 +        beforeSetup: function(effect) { 
   1.651 +          effect.element.makePositioned().makeClipping();
   1.652 +        },
   1.653 +        afterFinishInternal: function(effect) {
   1.654 +          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
   1.655 +        }
   1.656 +      })
   1.657 +    }
   1.658 +  }, arguments[1] || {}));
   1.659 +}
   1.660 +
   1.661 +Effect.DropOut = function(element) {
   1.662 +  element = $(element);
   1.663 +  var oldStyle = {
   1.664 +    top: element.getStyle('top'),
   1.665 +    left: element.getStyle('left'),
   1.666 +    opacity: element.getInlineOpacity() };
   1.667 +  return new Effect.Parallel(
   1.668 +    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
   1.669 +      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
   1.670 +    Object.extend(
   1.671 +      { duration: 0.5,
   1.672 +        beforeSetup: function(effect) {
   1.673 +          effect.effects[0].element.makePositioned(); 
   1.674 +        },
   1.675 +        afterFinishInternal: function(effect) {
   1.676 +          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
   1.677 +        } 
   1.678 +      }, arguments[1] || {}));
   1.679 +}
   1.680 +
   1.681 +Effect.Shake = function(element) {
   1.682 +  element = $(element);
   1.683 +  var oldStyle = {
   1.684 +    top: element.getStyle('top'),
   1.685 +    left: element.getStyle('left') };
   1.686 +    return new Effect.Move(element, 
   1.687 +      { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
   1.688 +    new Effect.Move(effect.element,
   1.689 +      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
   1.690 +    new Effect.Move(effect.element,
   1.691 +      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
   1.692 +    new Effect.Move(effect.element,
   1.693 +      { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
   1.694 +    new Effect.Move(effect.element,
   1.695 +      { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
   1.696 +    new Effect.Move(effect.element,
   1.697 +      { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
   1.698 +        effect.element.undoPositioned().setStyle(oldStyle);
   1.699 +  }}) }}) }}) }}) }}) }});
   1.700 +}
   1.701 +
   1.702 +Effect.SlideDown = function(element) {
   1.703 +  element = $(element).cleanWhitespace();
   1.704 +  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
   1.705 +  var oldInnerBottom = element.down().getStyle('bottom');
   1.706 +  var elementDimensions = element.getDimensions();
   1.707 +  return new Effect.Scale(element, 100, Object.extend({ 
   1.708 +    scaleContent: false, 
   1.709 +    scaleX: false, 
   1.710 +    scaleFrom: window.opera ? 0 : 1,
   1.711 +    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
   1.712 +    restoreAfterFinish: true,
   1.713 +    afterSetup: function(effect) {
   1.714 +      effect.element.makePositioned();
   1.715 +      effect.element.down().makePositioned();
   1.716 +      if(window.opera) effect.element.setStyle({top: ''});
   1.717 +      effect.element.makeClipping().setStyle({height: '0px'}).show(); 
   1.718 +    },
   1.719 +    afterUpdateInternal: function(effect) {
   1.720 +      effect.element.down().setStyle({bottom:
   1.721 +        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
   1.722 +    },
   1.723 +    afterFinishInternal: function(effect) {
   1.724 +      effect.element.undoClipping().undoPositioned();
   1.725 +      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
   1.726 +    }, arguments[1] || {})
   1.727 +  );
   1.728 +}
   1.729 +
   1.730 +Effect.SlideUp = function(element) {
   1.731 +  element = $(element).cleanWhitespace();
   1.732 +  var oldInnerBottom = element.down().getStyle('bottom');
   1.733 +  return new Effect.Scale(element, window.opera ? 0 : 1,
   1.734 +   Object.extend({ scaleContent: false, 
   1.735 +    scaleX: false, 
   1.736 +    scaleMode: 'box',
   1.737 +    scaleFrom: 100,
   1.738 +    restoreAfterFinish: true,
   1.739 +    beforeStartInternal: function(effect) {
   1.740 +      effect.element.makePositioned();
   1.741 +      effect.element.down().makePositioned();
   1.742 +      if(window.opera) effect.element.setStyle({top: ''});
   1.743 +      effect.element.makeClipping().show();
   1.744 +    },  
   1.745 +    afterUpdateInternal: function(effect) {
   1.746 +      effect.element.down().setStyle({bottom:
   1.747 +        (effect.dims[0] - effect.element.clientHeight) + 'px' });
   1.748 +    },
   1.749 +    afterFinishInternal: function(effect) {
   1.750 +      effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
   1.751 +      effect.element.down().undoPositioned();
   1.752 +    }
   1.753 +   }, arguments[1] || {})
   1.754 +  );
   1.755 +}
   1.756 +
   1.757 +// Bug in opera makes the TD containing this element expand for a instance after finish 
   1.758 +Effect.Squish = function(element) {
   1.759 +  return new Effect.Scale(element, window.opera ? 1 : 0, { 
   1.760 +    restoreAfterFinish: true,
   1.761 +    beforeSetup: function(effect) {
   1.762 +      effect.element.makeClipping(); 
   1.763 +    },  
   1.764 +    afterFinishInternal: function(effect) {
   1.765 +      effect.element.hide().undoClipping(); 
   1.766 +    }
   1.767 +  });
   1.768 +}
   1.769 +
   1.770 +Effect.Grow = function(element) {
   1.771 +  element = $(element);
   1.772 +  var options = Object.extend({
   1.773 +    direction: 'center',
   1.774 +    moveTransition: Effect.Transitions.sinoidal,
   1.775 +    scaleTransition: Effect.Transitions.sinoidal,
   1.776 +    opacityTransition: Effect.Transitions.full
   1.777 +  }, arguments[1] || {});
   1.778 +  var oldStyle = {
   1.779 +    top: element.style.top,
   1.780 +    left: element.style.left,
   1.781 +    height: element.style.height,
   1.782 +    width: element.style.width,
   1.783 +    opacity: element.getInlineOpacity() };
   1.784 +
   1.785 +  var dims = element.getDimensions();    
   1.786 +  var initialMoveX, initialMoveY;
   1.787 +  var moveX, moveY;
   1.788 +  
   1.789 +  switch (options.direction) {
   1.790 +    case 'top-left':
   1.791 +      initialMoveX = initialMoveY = moveX = moveY = 0; 
   1.792 +      break;
   1.793 +    case 'top-right':
   1.794 +      initialMoveX = dims.width;
   1.795 +      initialMoveY = moveY = 0;
   1.796 +      moveX = -dims.width;
   1.797 +      break;
   1.798 +    case 'bottom-left':
   1.799 +      initialMoveX = moveX = 0;
   1.800 +      initialMoveY = dims.height;
   1.801 +      moveY = -dims.height;
   1.802 +      break;
   1.803 +    case 'bottom-right':
   1.804 +      initialMoveX = dims.width;
   1.805 +      initialMoveY = dims.height;
   1.806 +      moveX = -dims.width;
   1.807 +      moveY = -dims.height;
   1.808 +      break;
   1.809 +    case 'center':
   1.810 +      initialMoveX = dims.width / 2;
   1.811 +      initialMoveY = dims.height / 2;
   1.812 +      moveX = -dims.width / 2;
   1.813 +      moveY = -dims.height / 2;
   1.814 +      break;
   1.815 +  }
   1.816 +  
   1.817 +  return new Effect.Move(element, {
   1.818 +    x: initialMoveX,
   1.819 +    y: initialMoveY,
   1.820 +    duration: 0.01, 
   1.821 +    beforeSetup: function(effect) {
   1.822 +      effect.element.hide().makeClipping().makePositioned();
   1.823 +    },
   1.824 +    afterFinishInternal: function(effect) {
   1.825 +      new Effect.Parallel(
   1.826 +        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
   1.827 +          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
   1.828 +          new Effect.Scale(effect.element, 100, {
   1.829 +            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
   1.830 +            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
   1.831 +        ], Object.extend({
   1.832 +             beforeSetup: function(effect) {
   1.833 +               effect.effects[0].element.setStyle({height: '0px'}).show(); 
   1.834 +             },
   1.835 +             afterFinishInternal: function(effect) {
   1.836 +               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); 
   1.837 +             }
   1.838 +           }, options)
   1.839 +      )
   1.840 +    }
   1.841 +  });
   1.842 +}
   1.843 +
   1.844 +Effect.Shrink = function(element) {
   1.845 +  element = $(element);
   1.846 +  var options = Object.extend({
   1.847 +    direction: 'center',
   1.848 +    moveTransition: Effect.Transitions.sinoidal,
   1.849 +    scaleTransition: Effect.Transitions.sinoidal,
   1.850 +    opacityTransition: Effect.Transitions.none
   1.851 +  }, arguments[1] || {});
   1.852 +  var oldStyle = {
   1.853 +    top: element.style.top,
   1.854 +    left: element.style.left,
   1.855 +    height: element.style.height,
   1.856 +    width: element.style.width,
   1.857 +    opacity: element.getInlineOpacity() };
   1.858 +
   1.859 +  var dims = element.getDimensions();
   1.860 +  var moveX, moveY;
   1.861 +  
   1.862 +  switch (options.direction) {
   1.863 +    case 'top-left':
   1.864 +      moveX = moveY = 0;
   1.865 +      break;
   1.866 +    case 'top-right':
   1.867 +      moveX = dims.width;
   1.868 +      moveY = 0;
   1.869 +      break;
   1.870 +    case 'bottom-left':
   1.871 +      moveX = 0;
   1.872 +      moveY = dims.height;
   1.873 +      break;
   1.874 +    case 'bottom-right':
   1.875 +      moveX = dims.width;
   1.876 +      moveY = dims.height;
   1.877 +      break;
   1.878 +    case 'center':  
   1.879 +      moveX = dims.width / 2;
   1.880 +      moveY = dims.height / 2;
   1.881 +      break;
   1.882 +  }
   1.883 +  
   1.884 +  return new Effect.Parallel(
   1.885 +    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
   1.886 +      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
   1.887 +      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
   1.888 +    ], Object.extend({            
   1.889 +         beforeStartInternal: function(effect) {
   1.890 +           effect.effects[0].element.makePositioned().makeClipping(); 
   1.891 +         },
   1.892 +         afterFinishInternal: function(effect) {
   1.893 +           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
   1.894 +       }, options)
   1.895 +  );
   1.896 +}
   1.897 +
   1.898 +Effect.Pulsate = function(element) {
   1.899 +  element = $(element);
   1.900 +  var options    = arguments[1] || {};
   1.901 +  var oldOpacity = element.getInlineOpacity();
   1.902 +  var transition = options.transition || Effect.Transitions.sinoidal;
   1.903 +  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
   1.904 +  reverser.bind(transition);
   1.905 +  return new Effect.Opacity(element, 
   1.906 +    Object.extend(Object.extend({  duration: 2.0, from: 0,
   1.907 +      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
   1.908 +    }, options), {transition: reverser}));
   1.909 +}
   1.910 +
   1.911 +Effect.Fold = function(element) {
   1.912 +  element = $(element);
   1.913 +  var oldStyle = {
   1.914 +    top: element.style.top,
   1.915 +    left: element.style.left,
   1.916 +    width: element.style.width,
   1.917 +    height: element.style.height };
   1.918 +  element.makeClipping();
   1.919 +  return new Effect.Scale(element, 5, Object.extend({   
   1.920 +    scaleContent: false,
   1.921 +    scaleX: false,
   1.922 +    afterFinishInternal: function(effect) {
   1.923 +    new Effect.Scale(element, 1, { 
   1.924 +      scaleContent: false, 
   1.925 +      scaleY: false,
   1.926 +      afterFinishInternal: function(effect) {
   1.927 +        effect.element.hide().undoClipping().setStyle(oldStyle);
   1.928 +      } });
   1.929 +  }}, arguments[1] || {}));
   1.930 +};
   1.931 +
   1.932 +Effect.Morph = Class.create();
   1.933 +Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
   1.934 +  initialize: function(element) {
   1.935 +    this.element = $(element);
   1.936 +    if(!this.element) throw(Effect._elementDoesNotExistError);
   1.937 +    var options = Object.extend({
   1.938 +      style: {}
   1.939 +    }, arguments[1] || {});
   1.940 +    if (typeof options.style == 'string') {
   1.941 +      if(options.style.indexOf(':') == -1) {
   1.942 +        var cssText = '', selector = '.' + options.style;
   1.943 +        $A(document.styleSheets).reverse().each(function(styleSheet) {
   1.944 +          if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
   1.945 +          else if (styleSheet.rules) cssRules = styleSheet.rules;
   1.946 +          $A(cssRules).reverse().each(function(rule) {
   1.947 +            if (selector == rule.selectorText) {
   1.948 +              cssText = rule.style.cssText;
   1.949 +              throw $break;
   1.950 +            }
   1.951 +          });
   1.952 +          if (cssText) throw $break;
   1.953 +        });
   1.954 +        this.style = cssText.parseStyle();
   1.955 +        options.afterFinishInternal = function(effect){
   1.956 +          effect.element.addClassName(effect.options.style);
   1.957 +          effect.transforms.each(function(transform) {
   1.958 +            if(transform.style != 'opacity')
   1.959 +              effect.element.style[transform.style] = '';
   1.960 +          });
   1.961 +        }
   1.962 +      } else this.style = options.style.parseStyle();
   1.963 +    } else this.style = $H(options.style)
   1.964 +    this.start(options);
   1.965 +  },
   1.966 +  setup: function(){
   1.967 +    function parseColor(color){
   1.968 +      if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
   1.969 +      color = color.parseColor();
   1.970 +      return $R(0,2).map(function(i){
   1.971 +        return parseInt( color.slice(i*2+1,i*2+3), 16 ) 
   1.972 +      });
   1.973 +    }
   1.974 +    this.transforms = this.style.map(function(pair){
   1.975 +      var property = pair[0], value = pair[1], unit = null;
   1.976 +
   1.977 +      if(value.parseColor('#zzzzzz') != '#zzzzzz') {
   1.978 +        value = value.parseColor();
   1.979 +        unit  = 'color';
   1.980 +      } else if(property == 'opacity') {
   1.981 +        value = parseFloat(value);
   1.982 +        if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
   1.983 +          this.element.setStyle({zoom: 1});
   1.984 +      } else if(Element.CSS_LENGTH.test(value)) {
   1.985 +          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
   1.986 +          value = parseFloat(components[1]);
   1.987 +          unit = (components.length == 3) ? components[2] : null;
   1.988 +      }
   1.989 +
   1.990 +      var originalValue = this.element.getStyle(property);
   1.991 +      return { 
   1.992 +        style: property.camelize(), 
   1.993 +        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), 
   1.994 +        targetValue: unit=='color' ? parseColor(value) : value,
   1.995 +        unit: unit
   1.996 +      };
   1.997 +    }.bind(this)).reject(function(transform){
   1.998 +      return (
   1.999 +        (transform.originalValue == transform.targetValue) ||
  1.1000 +        (
  1.1001 +          transform.unit != 'color' &&
  1.1002 +          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
  1.1003 +        )
  1.1004 +      )
  1.1005 +    });
  1.1006 +  },
  1.1007 +  update: function(position) {
  1.1008 +    var style = {}, transform, i = this.transforms.length;
  1.1009 +    while(i--)
  1.1010 +      style[(transform = this.transforms[i]).style] = 
  1.1011 +        transform.unit=='color' ? '#'+
  1.1012 +          (Math.round(transform.originalValue[0]+
  1.1013 +            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
  1.1014 +          (Math.round(transform.originalValue[1]+
  1.1015 +            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
  1.1016 +          (Math.round(transform.originalValue[2]+
  1.1017 +            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
  1.1018 +        transform.originalValue + Math.round(
  1.1019 +          ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
  1.1020 +    this.element.setStyle(style, true);
  1.1021 +  }
  1.1022 +});
  1.1023 +
  1.1024 +Effect.Transform = Class.create();
  1.1025 +Object.extend(Effect.Transform.prototype, {
  1.1026 +  initialize: function(tracks){
  1.1027 +    this.tracks  = [];
  1.1028 +    this.options = arguments[1] || {};
  1.1029 +    this.addTracks(tracks);
  1.1030 +  },
  1.1031 +  addTracks: function(tracks){
  1.1032 +    tracks.each(function(track){
  1.1033 +      var data = $H(track).values().first();
  1.1034 +      this.tracks.push($H({
  1.1035 +        ids:     $H(track).keys().first(),
  1.1036 +        effect:  Effect.Morph,
  1.1037 +        options: { style: data }
  1.1038 +      }));
  1.1039 +    }.bind(this));
  1.1040 +    return this;
  1.1041 +  },
  1.1042 +  play: function(){
  1.1043 +    return new Effect.Parallel(
  1.1044 +      this.tracks.map(function(track){
  1.1045 +        var elements = [$(track.ids) || $$(track.ids)].flatten();
  1.1046 +        return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
  1.1047 +      }).flatten(),
  1.1048 +      this.options
  1.1049 +    );
  1.1050 +  }
  1.1051 +});
  1.1052 +
  1.1053 +Element.CSS_PROPERTIES = $w(
  1.1054 +  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 
  1.1055 +  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  1.1056 +  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  1.1057 +  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  1.1058 +  'fontSize fontWeight height left letterSpacing lineHeight ' +
  1.1059 +  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
  1.1060 +  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  1.1061 +  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  1.1062 +  'right textIndent top width wordSpacing zIndex');
  1.1063 +  
  1.1064 +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
  1.1065 +
  1.1066 +String.prototype.parseStyle = function(){
  1.1067 +  var element = document.createElement('div');
  1.1068 +  element.innerHTML = '<div style="' + this + '"></div>';
  1.1069 +  var style = element.childNodes[0].style, styleRules = $H();
  1.1070 +  
  1.1071 +  Element.CSS_PROPERTIES.each(function(property){
  1.1072 +    if(style[property]) styleRules[property] = style[property]; 
  1.1073 +  });
  1.1074 +  if(Prototype.Browser.IE && this.indexOf('opacity') > -1) {
  1.1075 +    styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
  1.1076 +  }
  1.1077 +  return styleRules;
  1.1078 +};
  1.1079 +
  1.1080 +Element.morph = function(element, style) {
  1.1081 +  new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
  1.1082 +  return element;
  1.1083 +};
  1.1084 +
  1.1085 +['getInlineOpacity','forceRerendering','setContentZoom',
  1.1086 + 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( 
  1.1087 +  function(f) { Element.Methods[f] = Element[f]; }
  1.1088 +);
  1.1089 +
  1.1090 +Element.Methods.visualEffect = function(element, effect, options) {
  1.1091 +  s = effect.dasherize().camelize();
  1.1092 +  effect_class = s.charAt(0).toUpperCase() + s.substring(1);
  1.1093 +  new Effect[effect_class](element, options);
  1.1094 +  return $(element);
  1.1095 +};
  1.1096 +
  1.1097 +Element.addMethods();
  1.1098 \ No newline at end of file

mercurial