﻿var f = function (id) {
    return "string" == typeof id ? document.getElementById(id) : id;
};

var Extend = function(destination, source) {
	for (var property in source) {
		destination[property] = source[property];
	}
	return destination;
}

var Map = function(array, callback, thisObject){
	if(array.map){
		return array.map(callback, thisObject);
	}else{
		var res = [];
		for (var i = 0, len = array.length; i < len; i++) { res.push(callback.call(thisObject, array[i], i, array)); }
		return res;
	}
}


var ColorGrads = function(options){
	this.SetOptions(options);
	this.StartColor = this.options.StartColor;
	this.EndColor = this.options.EndColor;
	this.Step = Math.abs(this.options.Step);
};
ColorGrads.prototype = {
  //设置默认属性
  SetOptions: function(options) {
    this.options = {//默认值
		StartColor:	"#fff",//开始颜色
		EndColor:	"#000",//结束颜色
		Step:		20//渐变级数
    };
    Extend(this.options, options || {});
  },
  //获取渐变颜色集合
  Create: function() {
	var colors = [],
		startColor = this.GetColor(this.StartColor),
		endColor = this.GetColor(this.EndColor),
		stepR = (endColor[0] - startColor[0]) / this.Step,
		stepG = (endColor[1] - startColor[1]) / this.Step,
		stepB = (endColor[2] - startColor[2]) / this.Step;
	//生成颜色集合
	for(var i = 0, n = this.Step, r = startColor[0], g = startColor[1], b = startColor[2]; i < n; i++){
		colors.push([r, g, b]); r += stepR; g += stepG; b += stepB;
	}
	colors.push(endColor);
	//修正颜色值
	return Map(colors, function(x){ return Map(x, function(x){
		return Math.min(Math.max(0, Math.floor(x)), 255);
	});});
  },
  //获取颜色数据
  GetColor: function(color) {
	if(/^#[0-9a-f]{6}$/i.test(color))
	{//#rrggbb
		return Map([color.substr(1, 2), color.substr(3, 2), color.substr(5, 2)],
			function(x){ return parseInt(x, 16); }
		)
	}
	else if(/^#[0-9a-f]{3}$/i.test(color))
	{//#rgb
		return Map([color.substr(1, 1), color.substr(2, 1), color.substr(3, 1)],
			function(x){ return parseInt(x + x, 16); }
		)
	}
	else if(/^rgb(.*)$/i.test(color))
	{//rgb(n,n,n) or rgb(n%,n%,n%)
		return Map(color.match(/\d+(\.\d+)?\%?/g),
			function(x){ return parseInt(x.indexOf("%") > 0 ? parseFloat(x, 10) * 2.55 : x, 10); }
		)
	}
	else
	{//color
		var mapping = {"red":"#FF0000"};//略
		color = mapping[color.toLowerCase()];
		if(color){
			return Map([color.substr(1, 2), color.substr(3, 2), color.substr(5, 2)],
				function(x){ return parseInt(x, 16); }
			)
		}
	}
  }
};



var CurrentStyle = function(element){
	return element.currentStyle || document.defaultView.getComputedStyle(element, null);
}

var Bind = function(object, fun) {
	var args = Array.prototype.slice.call(arguments).slice(2);
	return function() {
		return fun.apply(object, args.concat(Array.prototype.slice.call(arguments)));
	}
}

//渐变对象
var ColorTrans = function(obj, options){
	
	this._obj = f(obj);
	this._timer = null;//定时器
	this._index = 0;//索引
	this._colors = [];//颜色集合
	this._grads = new ColorGrads();
	
	this.SetOptions(options);
	
	this.Speed = Math.abs(this.options.Speed);
	this.CssColor = this.options.CssColor;
	
	this._startColor = this.options.StartColor || CurrentStyle(this._obj)[this.CssColor];
	this._endColor = this.options.EndColor;
	this._step = Math.abs(this.options.Step);
	
	this.Reset();
	this.SetColor();
};
ColorTrans.prototype = {
  //设置默认属性
  SetOptions: function(options) {
	this.options = {//默认值
		StartColor:	"",//开始颜色
		EndColor:	"#000",//结束颜色
		Step:		20,//渐变级数
		Speed:		20,//渐变速度
		CssColor:	"color"//设置属性（Scripting属性）
	};
    Extend(this.options, options || {});
  },
  //重设颜色集合
  Reset: function(color) {
	//修改颜色后必须重新获取颜色集合
	color = Extend({ StartColor: this._startColor, EndColor: this._endColor, Step: this._step }, color || {});
	//设置属性
	this._grads.StartColor = this._startColor = color.StartColor;
	this._grads.EndColor = this._endColor = color.EndColor;
	this._grads.Step = this._step = color.Step;
	//获取颜色集合
	this._colors = this._grads.Create();
	this._index = 0;
  },
  //颜色渐入
  FadeIn: function() {
	this.Stop(); this._index++; this.SetColor();
	if(this._index < this._colors.length - 1){
		this._timer = setTimeout(Bind(this, this.FadeIn), this.Speed);
	}
  },
  //颜色渐出
  FadeOut: function() {
	this.Stop(); this._index--; this.SetColor();
	if(this._index > 0){
		this._timer = setTimeout(Bind(this, this.FadeOut), this.Speed);
	}
  },
  //颜色设置
  SetColor: function() {
	var color = this._colors[Math.min(Math.max(0, this._index), this._colors.length - 1)];
	this._obj.style[this.CssColor] = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")";
  },
  //停止
  Stop: function() {
	clearTimeout(this._timer);
  }
};