//CSSйصĶĻ࣬ĶҪǴһʼֵֵı仯Ч
Fx.CSS = new Class({

 //̳Fx
 Extends: Fx,

 //prepares the base from/to object

 //Ŀʼͽֵǰڴ
 prepare: function(element, property, values){
  //黯ΪvaluesܴһֵҲһ
  values = $splat(values);
  //ȡеĵڶֵΪĽֵ
  var values1 = values[1];
  //ֻһֵ
  if (!$chk(values1)){
   //ֵΪĽֵ
   values[1] = values[0];
   //ǰֵΪʼֵ
   values[0] = element.getStyle(property);
  }
  //еʹparse
  var parsed = values.map(this.parse);
  //fromtoֵĶ
  return {from: parsed[0], to: parsed[1]};
 },

 //parses a value into an array

 parse: function(value){
  /*
  ʹlambadʽvalueִ֮
  ĺôʹֵfunctionҲǹ̶ֵ
  */
  value = $lambda(value)();
  //黯ַͣʹÿոָ
  value = (typeof value == 'string') ? value.split(' ') : $splat(value);
  //
  return value.map(function(val){
   //תΪַ
   val = String(val);
   var found = false;
   Fx.CSS.Parsers.each(function(parser, key){
    //һʱΪfalseִ棬ҵʵĽfoundжϲΪfalseظ
    if (found) return;
    //ʹýֵ
    var parsed = parser.parse(val);
    //ͳɹ¼ͺֵʹõĽ(ΪҪʹýcomputeserve)
    if ($chk(parsed)) found = {value: parsed, parser: parser};
   });
   //ĬʹֵַĽ
   found = found || {value: val, parser: Fx.CSS.Parsers.String};
   return found;
  });
 },

 //computes by a from and to prepared objects, using their parsers.

 //ǸFxͬͬ㷨ʵֲͬЧ
 compute: function(from, to, delta){
  var computed = [];
  //ȡСı
  (Math.min(from.length, to.length)).times(function(i){
   //ؼֵʹõĽ
   computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
  });
  //Ϊ$typeṩ׼ֵ
  computed.$family = {name: 'fx:css:value'};
  return computed;
 },

 //serves the value as settable

 serve: function(value, unit){
  //ֵδͣҪȽ
  if ($type(value) != 'fx:css:value') value = this.parse(value);
  var returned = [];
  value.each(function(bit){
   //õյʹֵ
   returned = returned.concat(bit.parser.serve(bit.value, unit));
  });
  return returned;
 },

 //renders the change to an element

 //Ϊ౾ǸCSS࣬սͨsetStyleӳelementӦCSS
 render: function(element, property, value, unit){
  element.setStyle(property, this.serve(value, unit));
 },

 //searches inside the page css to find the values for a selector

 //ӵǰҳʽвָѡʽ
 search: function(selector){
  //ģ⻺棬ȴʱӦֵЧ
  if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
  var to = {};
  //ǰҳʽ
  Array.each(document.styleSheets, function(sheet, j){
   var href = sheet.href;
   //Կʽ
   if (href && href.contains('://') && !href.contains(document.domain)) return;
   //ʽ
   var rules = sheet.rules || sheet.cssRules;
   //ÿ
   Array.each(rules, function(rule, i){
    if (!rule.style) return;
    //ѡ(ѡĻתΪСд)
    var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
     return m.toLowerCase();
    }) : null;
    //ƥָʽѡ
    if (!selectorText || !selectorText.test('^' + selector + '$')) return;
    //ʽֵ
    Element.Styles.each(function(value, style){
     //ֵ
     if (!rule.style[style] || Element.ShortStyles[style]) return;
     //תΪַ
     value = String(rule.style[style]);
     //ɫֵ
     to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
    });
   });
  });
  //
  return Fx.CSS.Cache[selector] = to;
 }

});

Fx.CSS.Cache = {};

//CSSмֵ͵Ľÿʵparse/compute/serveӿ
Fx.CSS.Parsers = new Hash({

 //ɫĽʹ
 Color: {
  parse: function(value){
   //ʮƵɫʾRGB
   if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
   //RGBɫʾƥRGB飬ƥ䷵flaseԱ
   return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
  },
  compute: function(from, to, delta){
   //RGBֱĿֵ
   return from.map(function(value, i){
    //ԿȻʹþ̬compute
    return Math.round(Fx.compute(from[i], to[i], delta));
   });
  },
  serve: function(value){
   //RGBתֵ
   return value.map(Number);
  }
 },

 //ֵ͵Ľʹ
 Number: {
  parse: function(value){
   //תΪ
   return parseFloat(value);
  },
  compute: function(from, to, delta){
   //Fxе㷨һ
   return Fx.compute(from, to, delta);
  },
  serve: function(value, unit){
   //ϵλpxpt֮
   return (unit) ? value + unit : value;
  }
 },

 //ַ͵Ľʹ
 String: {
  //false൱parse : function(){return false;}
  parse: $lambda(false),
  //computeִʱص2
  compute: $arguments(1),
  //serveִʱص1
  serve: $arguments(0)
 }

});

