bytefx = new function(){

	// public methods
	this.alpha = function(element, opacity){
		var	style = $element(element).style;
		style.opacity = style.MozOpacity = style.KhtmlOpacity = opacity / 100;
		style.filter = "alpha(opacity=" + opacity + ")";
	};
	this.clear = function(element){
		var	interval = ["size", "scroll", "move", "fade", "color"],
			index = interval.length;
		while(index--)
			clearInterval($element(element).bytefx[interval[index]]);
	};
	this.color = function(element, style, start, end, speed, callback){
		end = bytefx.color$(end);
		clearInterval($element(element).bytefx.color);
		element.bytefx.color = setInterval(function(){
			var	color = bytefx.color$(start),
				index = 3;
			while(index--)
				color[index] = $end(color[index], end[index], speed);
			element.style[style] = start = bytefx.$color(color);
			if("" + color == "" + end)
				$callback(element, "color", callback);
		}, 1);
	};
	this.drag = function(element, start, end, callback, position){
		function $callback(evt, callback){
			if(callback)
				callback.call(element, evt);
			return false;
		};
		var	tmp = $element(element).bytefx.drag;
		bytefx.$event(element, "onmousedown", function(evt){
			tmp.start = true;
			tmp.onmousedown = d.onmousedown;
			tmp.onmouseup = d.onmouseup;
			d.onmouseup = element.onmouseup;
			d.onmousedown = $callback;
			return $callback(evt, start);
		});
		bytefx.$event(element, "onmouseup", function(evt){
			tmp.start = false;
			d.onmousedown = tmp.onmousedown;
			d.onmouseup = tmp.onmouseup;
			return $callback(evt, end);
		});
		bytefx.$event(d, "onmousemove", function(evt){
			var	x = evt.clientX,
				y = evt.clientY,
				size = {x: x - tmp.x, y: y - tmp.y};
			if(tmp.start) {
				if(position) {
					size.x = max(size.x, position.$x);
					size.y = max(size.y, position.$y);
					size.x = min(size.x, position.x$);
					size.y = min(size.y, position.y$);
				};
				bytefx.position(element, size);
				$callback(evt, callback);
			}
			else{
				tmp.x = x - element.offsetLeft;
				tmp.y = y - element.offsetTop;
			};
			return false;
		});
	};
	this.fade = function(element, start, end, speed, callback){
		clearInterval($element(element).bytefx.fade);
		element.bytefx.fade = setInterval(function(){
			start = $end(start, end, speed);
			bytefx.alpha(element, start);
			if(start == end)
				$callback(element, "fade", callback);
		}, 1);
	};
	this.move = function(element, position, speed, callback){
		var	start = bytefx.$position($element(element));
		$setInterval(element, "move", speed / 100, start, position, ["x", "y"], "position", callback);
	};
	this.position = function(element, position){
		var	style = $element(element).style;
		//style.position = "absolute";
		style.left = position.x + "px";
		style.top = position.y + "px";
	};
	this.scroll = function(element, speed, callback){
		function scroll(position){
			return d.documentElement ? d.documentElement[position] : d.body[position];
		};
		var	start = bytefx.$scroll(),
			end = {x:start.x, y:min(bytefx.$position(element).y, max(scroll("offsetHeight"), d.body.offsetHeight) - min(scroll("clientHeight"), d.body.clientHeight))};
		$setInterval($element(bytefx), "scroll", speed / 100, start, end, ["x", "y"], "scroll$", callback ? function(){callback.call(element)} : null);
	};
	this.size = function(element, size, speed, callback){
		var	start = bytefx.$size($element(element)),
			tmp = w.opera;
		if(!/msie/i.test(navigator.userAgent) || (tmp && parseInt(tmp.version()) >= 9)){
			if(size.$width)
				start.width -= size.$width;
			if(size.$height)
				start.height -= size.$height;
			if(size.width$)
				size.width -= size.width$;
			if(size.height$)
				size.height -= size.height$;
		};
		element.style.overflow = "hidden";
		$setInterval(element, "size", speed / 100, start, size, ["width", "height"], "size$", callback);
	};
	this.$color = function(color){
		function tmp(index){
			var	tmp = color[index].toString(16);
			return tmp.length == 1 ? "0" + tmp : tmp;
		};
		return "#" + tmp(0) + tmp(1) + tmp(2);
	};
	this.color$ = function(color){
		function tmp(index){
			return color.charAt(index);
		};
		color = color.substring(1);
		if(color.length == 3)
			color = tmp(0) + tmp(0) + tmp(1) + tmp(1) + tmp(2) + tmp(2);
		return [parseInt(tmp(0) + tmp(1), 16), parseInt(tmp(2) + tmp(3), 16), parseInt(tmp(4) + tmp(5), 16)];
	};
	this.$event = function(element, tmp, callback){
		var	value = element[tmp];
		element[tmp] = function(evt){
			if(!evt)
				evt = w.event;
			if(value)
				value.call(this, evt);
			return callback.call(this, evt);
		};
	};
	this.$position = function(element){
		var	position = {x:element.offsetLeft, y:element.offsetTop};
		return position;
	};
	this.$scroll = function(){
		function scroll(position, scroll){
			return (d.documentElement ? d.documentElement[position] : w[scroll] || d.body[position]) || 0;
		};
		return {x:scroll("scrollLeft", "pageXOffset"), y:scroll("scrollTop", "pageYOffset")};
	};
	this.scroll$ = function(element, position){
		w.scrollTo(position.x, position.y);
	};
	this.$size = function(element){
		return {width:element.offsetWidth, height:element.offsetHeight};
	};
	this.size$ = function(element, size){
		var	style = element.style;
		style.width = size.width + "px";
		style.height = size.height + "px";
	};
	function $callback(element, interval, callback){
		clearInterval(element.bytefx[interval]);
		if(callback)
			callback.call(element);
	};
	function $element(element){
		if(!element.bytefx)
			element.bytefx = {color:0, drag:{}, fade:0, move:0, scroll:0, size:0};
		return element;
	};
	function $end(x, y, speed){
		return x < y ? min(x + speed, y) : max(x - speed, y);
	};

	/**
	 * private method,
         * 	[virtual scope]$setInterval(element:Object, intervalName:String, speed:Number, startValues:Object, endValues:Object, propertiesName:Array, methodName:String[, finalCallback:Function]):Void
	 */
	function $setInterval(element, interval, speed, start, position, style, tmp, callback){
		clearInterval(element.bytefx[interval]);
		element.bytefx[interval] = setInterval(function(){
			start[style[0]] += (position[style[0]] - start[style[0]]) * speed;
			start[style[1]] += (position[style[1]] - start[style[1]]) * speed;
			bytefx[tmp](element, start);
			if(round(start[style[0]]) == position[style[0]] && round(start[style[1]]) == position[style[1]]){
				bytefx[tmp](element, position);
				$callback(element, interval, callback);
			}
		}, 1);
	};
	
	var	w = window,
		d = document,
		max = Math.max,
		min = Math.min,
		round = Math.round;
};