	/*
	 * create by uoon;
	 * email: mnx2012@gmail.com
	 */
	
	Albus = function(R) {
		var E = (R && R.tagName && R.nodeType == 1) ? R : document.getElementById(R);
		if (!E) {return;}
		
		var _getType = function(style) {
			switch (style) {
				case "backgroundColor": case "color":
					return "color";
				case "fontSize": case "height": case "letterSpacing": case "marginBottom": case "marginLeft": case "marginRight": case "marginTop": case "paddingBottom" : case "paddingLeft": case "paddingRight": case "paddingTop": case "width": case "wordSpacing":
					return "dimension";
				case "opacity":
					return "opacity";
				case "bottom": case "left": case "right": case "top":
					return "position";
				default:
					return "chaos";
			}
		};
		
		var _getColor = function(value) {
			//convert text color to hex;
			var table = document.createElement("table"), match = null;
			table.bgColor = value;
			table.style.color = value;
			table.style.display = "none";
			document.body.appendChild(table);
			if ((/MSIE/).test(navigator.userAgent)) {
				value = table.bgColor;
			} else {
				value = document.defaultView.getComputedStyle(table, null).getPropertyValue('color');
			}
			document.body.removeChild(table);
			if (match = value.match(/^#(\w{2})(\w{2})(\w{2})/)) {
				return "rgb(" + parseInt(match[1], 16) + ", " + parseInt(match[2], 16) + ", " + parseInt(match[3], 16) + ")";
			}
			return value;
		};
		
		var _getStyle = function(element, property) {
			var value, match, type = _getType(property);
			if (element.currentStyle && !(/Opera/).test(navigator.userAgent)) { 
				if (type == "opacity") {
					value = element.currentStyle["filter"];
					match = value.match(/(.*)opacity\s*=\s*(\w+)(.*)/i);
					value = match ? isNaN(parseFloat(match[2])) ? 100 : parseFloat(match[2]) : 100;
				} else { 
					value = element.currentStyle[property];
				}
			} else if (document.defaultView && document.defaultView.getComputedStyle) {
				property = property.replace(/[(A-Z)]/g, function(match){return "-" + match.toLowerCase()});
				value = document.defaultView.getComputedStyle(element, null).getPropertyValue(property);
				value = type == "opacity" ? 100 * value : value; 
			}
			switch (type) {
				case "color": 
					return _getColor(value);
				case "dimension": case "position":
					return (value == "auto" || value == "normal") ? "0px" : value;
				default:
					return value;
			}
		};	
		
		function _parse(type, value) {
			return {
				"value": type == "color" ? _getColor(value) : parseFloat(value),
				"unit": type == "color" ? "color" : value.toString().replace(/^[\d\s]|-[\d\s]/g, "")
			};
		}
		
		function _split(source, target, divide, unit, transition) {
			var r, g, b, delta, range = [];
			if (unit == "color") {
				source = source.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i);
				target = target.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i);
				r = _split(parseInt(source[1]), parseInt(target[1]), divide, "", transition);
				g = _split(parseInt(source[2]), parseInt(target[2]), divide, "", transition);
				b = _split(parseInt(source[3]), parseInt(target[3]), divide, "", transition);
				for (var i = 0; i <= divide; ++i) {
					range.push("rgb(" + parseInt(r[i]) + "," + parseInt(g[i]) + "," + parseInt(b[i]) + ")");			
				}
			} else { 
				delta = target - source;
				for (var i = 0; i <= divide; ++i) {
					range.push((source + transition(i/divide)*delta).toFixed(2) + unit);			
				}
			}
			return range;
		}
		
		function _revolve(element, name, start, delay) {
			var proxy = element.albus[name];
			var divide = proxy.value.length - 1;
			//remove old register;
			if (element.albus['timer'][name]) {
				clearInterval(element.albus['timer'][name]);
			}
			var revolve = function() {
				var index = Math.ceil((new Date().getTime() - start)/delay);
				index = (index - divide > 0) ? divide : index;
				if (_getType(name) == "opacity") {
					element.opacity(parseInt(proxy.value[index]));
				} else {
					element.style[name] = proxy.value[index];
				}
				if (index == divide) {
					clearInterval(element.albus['timer'][name]);
					delete element.albus['timer'][name];
					delete element.albus[name];
					if (element.albus['timer'].length == 0) {
						//slowdown for IE;
						setTimeout(function(){element.albus.finish(element)}, 1);
					}
				} 
			}
			element.albus['timer'][name] = setInterval(revolve, delay); 
		}
		
		E.opacity = function(v) {
			var ADN = this;
			if ((/MSIE/).test(navigator.userAgent)) {
				ADN.style.filter = "alpha(opacity = value)".replace("value", v);
			} else {
				ADN.style.opacity = v/100;
			}
			return ADN;
		}
		
		E.transform = function(r) {
			var ADN = this, styleName = ["background", "backgroundColor", "backgroundImage", "backgroundPosition", "backgroundRepeat", "bottom", "clip", "color", "font", "fontSize", "height", "left", "letterSpacing", "lineHeight", "listStyleImage", "listStylePosition", "margin", "marginTop", "marginRight", "marginBottom", "marginLeft", "opacity", "padding", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft", "right", "top", "width", "wordSpacing", "zIndex"];
			var config = {
				start: r.start || function(){},
				end: r.end || function(){},
				delay: r.delay || 12,
				divide: r.divide || 100,
				transition: r.transition || function(x) {return x * (2 - x)}
			};
			ADN.albus = ADN.albus ? ADN.albus : {'timer': []};
			var proxy, name, type, from, target, start = new Date().getTime();
			config.start();
			for (var o in styleName) {
				name = styleName[o];
				if (r[name] != undefined) {
					type = _getType(name);
					if (type == "position" && _getStyle(ADN, "position") != "absolute") {
						ADN.style.position = "relative";
					}
					proxy = ADN.albus[name] = {'value': null};
					if (r[name].constructor == Array && r[name].length > 2) {
						proxy.value = r[name];
					} else if (r[name].constructor == Array && r[name].length == 2) {
						from = _parse(type, r[name][0]);
						target = _parse(type, r[name][1]);
					} else {
						from = _parse(type, _getStyle(ADN, name));
						target = _parse(type, r[name]);
					}	
					proxy.value = proxy.value ? proxy.value : _split(from.value, target.value, config.divide, target.unit, config.transition);
					//register new transform;
					_revolve(ADN, name, start, config.delay);
				}
			}
			ADN.albus.finish = config.end;
			return ADN;
		}
		return E;
	};
	
	Albus.transition = {
		0: function(x) {
			return x;
		},
		1: function(x) {
			return x*(2 - x);
		},
		2: function(x) {
			return Math.pow(x, 2);
		},
		3: function(x) {
			return Math.pow(x, 1/2);
		},
		//elastic effect;
		4: function(x) {
			var t = 1 + 1 + 1/2 + 1/4, a = t*t/2;
			if (x < (2/t)) {
				return -a*x*x + t*1.5*x;
			} else if (x < (2.5/t)) {
				return a*x*x - t*2.25*x + 3.5;
			} else {
				return -a*x*x + t*2.625*x - 2.4375;
			}
		},
		//bounce effect;
		5: function(x) {
			var t = 1 + 1 + 1/2 + 1/4, a = t*t, b = -2*t;
			//parabol :  a x^2 + bx +  c = 1;
			if (x < (1/t)) {
				return a*x*x;
			} else if (x < (2/t)) {
				return a*x*x + b*1.5*x + 3;
			} else if (x < (2.5/t)) {
				return a*x*x + b*2.25*x + 6;
			} else {
				return a*x*x + b*2.625*x + 7.875;
			}
		},
		6: function(x) {
			return 0.5 - 0.5*Math.cos(x*Math.PI)
		},
		7: function(x) {
			return 0.5 - 0.5*Math.cos(x*10*Math.PI)
		},
		8: function(x) {
			return x + Math.sin(x*10*Math.PI)/5
		},
		9: function(x) {
			return x + 0.5*(x - 1)*Math.sin((x-1)*10*Math.PI)
		},
		10: function(x) {
			return Math.pow(x, 0.25) + (x/5)*Math.sin(x*20*Math.PI)
		},
		11: function(x) {
			return Math.pow(x, 0.25) + 0.5*(x-1)*Math.sin((x-1)*6*Math.PI)
		}
	};
	
	
	