Fx.Tween = new Class({

 //̳Fx.CSS
 Extends: Fx.CSS,

 //캯ḲǸĹ캯
 initialize: function(element, options){
  //ǸĹ캯Ϊelement
  this.element = this.subject = $(element);
  /*
  ø̶ͬ÷һҲthis.parent
  1543汾Ѿȫarguments.calleeֱʹthisOpera֧caller
  */
  arguments.callee.parent(options);
 },

 //ֱӸǸͬοFx
 set: function(property, now){
  //ֻṩһ
  if (arguments.length == 1){
   //˲ΪĿֵ
   now = property;
   //ʱȡ
   property = this.property || this.options.property;
  }
  //ȾЧ
  this.render(this.element, property, now, this.options.unit);
  return this;
 },

 //ǸͬοFx
 start: function(property, from, to){
   //鵱ǰЧ״̬ǷЧ
  if (!this.check(property, from, to)) return this;
  //ά
  var args = Array.flatten(arguments);
  //ȡԣȼ
  this.property = this.options.property || args.shift();
  //øFx.CSSprepareͲõfromtoֵ
  var parsed = this.prepare(this.element, this.property, args);
  //Fxͬʼִ
  return arguments.callee.parent(parsed.from, parsed.to);
 }

});

//̬ԣelement.setelement.get
Element.Properties.tween = {

 //setterFx.Tween
 set: function(options){
  //ȴʱȡû浽Fx.Tweenʵ
  var tween = this.retrieve('tween');
  //ڣȡִеЧ
  if (tween) tween.cancel();
  //ɾȥɶΪ¶
  return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
 },

 //getterȡFx.Tween
 get: function(options){
  //ṩδ뵱ǰElementFx.Tweenʵ
  if (options || !this.retrieve('tween')){
   //ṩδFx.TweenʵĲsetterò
   if (options || !this.retrieve('tween:options')) this.set('tween', options);
   //Fx.Tweenʵ
   this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
  }
  return this.retrieve('tween');
 }

};

//Fx.TweenΪElementӵչʵ
Element.implement({

 //Fx.TweenĿݷʽźﲻֲ֧ãҪֹelemenet.set('tween', options)
 tween: function(property, from, to){
  /*
  ʹgetterȡFx.Tweenʵstart
  ΪstartʹArray.flatten
  ֱӴargumentsȥﻹҪжϲ
  */
  this.get('tween').start(arguments);
  return this;
 },

 //ʹFx.TweenʵֵǳЧ
 fade: function(how){
  var fade = this.get('tween'), o = 'opacity', toggle;
  how = $pick(how, 'toggle');
  //ֵ뵭ķʽ
  switch (how){
   //
   case 'in': fade.start(o, 1); break;
   //
   case 'out': fade.start(o, 0); break;
   //ʾ
   case 'show': fade.set(o, 1); break;
   //
   case 'hide': fade.set(o, 0); break;
   //
   case 'toggle':
    //ȡǱ,ڶĬֵ
    var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
    //ݱ״̬Ƶ뻹ǵ
    fade.start(o, (flag) ? 0 : 1);
    //ȡ
    this.store('fade:flag', !flag);
    toggle = true;
   break;
   default: fade.start(o, arguments);
  }
  /*
  ûʹÿطʽɾʱ
  ʹtoggle֮ʹʽtoggleӦ
  */
  if (!toggle) this.eliminate('fade:flag');
  return this;
 },

 //ͨɫʵֵĸʾЧ
 highlight: function(start, end){
  //endΪʹõıɫͨԭָԭɫ
  if (!end){
   //ʱȡֵ
   end = this.retrieve('highlight:original', this.getStyle('background-color'));
   //͸Ļɫ
   end = (end == 'transparent') ? '#fff' : end;
  }
  //ȡFx.Tweenʵ
  var tween = this.get('tween');
  //ʼִ
  tween.start('background-color', start || '#ffff88', end).chain(function(){
   //ָԭɫ
   this.setStyle('background-color', this.retrieve('highlight:original'));
   //ʽִ
   tween.callChain();
  }.bind(this));
  return this;
 }

});

