﻿///compress=false
///cache=false
Ekina.UI.Effects = {};

Ekina.UI.Effects.Tween = function(object, property, begin, finish, duration, func, unit, scalar, args) { this.onBeforeStart = null; this.type = "Tween"; this.queue = null; this.scalar = scalar ? scalar : 1; this.element = object; this.property = property; this.begin = begin; this.finish = finish; this.ticks = duration * Ekina.UI.Effects.Tween.FPS; this.func = func ? func : Ekina.UI.Effects.Tween.None; this.change = this.finish - this.begin; this.unit = unit ? unit : ""; this.currentTick = 0; this.timer = null; this.tweenId = Ekina.UI.Effects.Tween.pushTween(this); this.args = args; this.onTweenFinished = null; this.onTweenStep = null; };
Ekina.UI.Effects.Tween.FPS = 25;
Ekina.UI.Effects.Tween.all = new Array();
Ekina.UI.Effects.Tween.prototype.start = function() { this.fireEvent(this.onBeforeStart); this.setupTimer(); };
Ekina.UI.Effects.Tween.pushTween = function(tween) { Ekina.UI.Effects.Tween.all.push(tween); return Ekina.UI.Effects.Tween.all.length-1; };
Ekina.UI.Effects.Tween.prototype.stop = function() { if(this.timer) { window.clearInterval(this.timer); this.timer = null; } };
Ekina.UI.Effects.Tween.prototype.setupTimer = function() { this.timer = window.setInterval("Ekina.UI.Effects.Tween.step(" + this.tweenId + ")", 1000 / Ekina.UI.Effects.Tween.FPS); };
Ekina.UI.Effects.Tween.step = function(id) { var tween = Ekina.UI.Effects.Tween.all[id]; tween.step(); };
Ekina.UI.Effects.Tween.prototype.step = function() { this.setTime(this.currentTick+1); };
Ekina.UI.Effects.Tween.prototype.setTime = function(t) { if(t > this.ticks) { this.stop(); this.fireEvent(this.onTweenFinished, this.args); } else { this.currentTick = t; this.update(); } };
Ekina.UI.Effects.Tween.prototype.update = function() { this.setPosition(this.getPosition()); this.fireEvent(this.onTweenStep, this.args); };
Ekina.UI.Effects.Tween.prototype.setPosition = function(pos) { var value = pos * this.scalar; value = this.unit == "" ? parseFloat(value) : value + this.unit; try{this.element[this.property] = value;}catch(ex){} };
Ekina.UI.Effects.Tween.prototype.getPosition = function() { return this.func(this.currentTick, this.begin, this.change, this.ticks); };
Ekina.UI.Effects.Tween.prototype.fireEvent = function(evt, args) { if(evt) evt(this, args);};
Ekina.UI.Effects.Tween.None = function(t, b, c, d) {	return c * t / d + b; };
Ekina.UI.Effects.Tween.Bounce = new Object();
Ekina.UI.Effects.Tween.Bounce.In = function(t, b, c, d) {return c - Ekina.UI.Effects.Tween.Bounce.Out(d - t, 0, c, d) + b};
Ekina.UI.Effects.Tween.Bounce.Out = function(t, b, c, d) {if ((t /= d) < (1 / 2.75)) return c * (7.5625 * t * t) + b;else if (t < (2 / 2.75)) return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;	else if (t < (2.5 / 2.75)) return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;	else return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;};
Ekina.UI.Effects.Tween.Bounce.InOut = function(t, b, c, d) { var s = 1.70158; if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= 1.525) + 1) * t - s)) + b; return c / 2 * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b; };
Ekina.UI.Effects.Tween.Elastic = new Object();
Ekina.UI.Effects.Tween.Elastic.In = function(t, b, c, d) { if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d *.3;	return -(c * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - (p / 4)) * (2 * Math.PI) / p)) + b; };
Ekina.UI.Effects.Tween.Elastic.Out = function(t, b, c, d) { if (t == 0) return b; if ((t /= d) == 1) return b + c; var p = d * .3; return (c * Math.pow(2, -10 * t) * Math.sin((t * d - (p / 4)) * (2 * Math.PI) / p) + c + b); };
Ekina.UI.Effects.Tween.Elastic.InOut = function(t, b, c, d) { if (t == 0)  return b; if ((t /= d / 2) == 2) return b + c; var p = d * (.3 * 1.5); if (t < 1) return -.5 * (c * Math.pow(2, 10 * (t-=1)) * Math.sin((t * d - (p / 4)) * (2 * Math.PI) / p)) + b; return c * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - (p / 4)) * (2 * Math.PI) / p) * .5 + c + b; };
Ekina.UI.Effects.Tween.Regular = new Object();
Ekina.UI.Effects.Tween.Regular.In = function(t, b, c, d) { return c * (t /= d) * t + b };
Ekina.UI.Effects.Tween.Regular.Out = function(t, b, c, d) { return -c * (t /= d) * (t - 2) + b; };
Ekina.UI.Effects.Tween.Regular.InOut = function(t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; };
Ekina.UI.Effects.Tween.Strong = new Object();
Ekina.UI.Effects.Tween.Strong.In = function(t, b, c, d) { return c * (t /= d) * t * t * t * t + b; };
Ekina.UI.Effects.Tween.Strong.Out = function (t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; };
Ekina.UI.Effects.Tween.Strong.InOut = function (t, b, c, d) { if((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; };

//returns percent if alphad or -1 if not alphad (by not alphad I mean IE doesnt have an alsph filter
Ekina.UI.Effects.GetAlpha = function(obj){ if (Ekina.Browser.ie) { if (!$null(obj.filters["Alpha"])) return obj.filters["Alpha"].opacity;} else { if ($number(obj.style.opacity)) return obj.style.opacity * 100;} return -1;};
//based on percent (100 = 100%)
Ekina.UI.Effects.SetAlpha = function(obj, newAlpha) { if (Ekina.Browser.ie) { if ($null(obj.filters["Alpha"])) obj.style.filter += "Alpha(opacity='"+newAlpha+"')";	else obj.filters["Alpha"].opacity= newAlpha;} else { obj.style.opacity = newAlpha / 100; }};

Ekina.UI.Effects.Tween.alpha = function(obj, to, options) { options = Ekina.UI.Effects.Tween._validateOptions(options);	if (Ekina.Browser.ie) {	if ($null(obj.filters["Alpha"])) obj.style.filter += "Alpha(opacity='100')"; } else { if (!$number(obj.style.opacity)) obj.style.opacity = 1; }	var currentOpacity = Ekina.Browser.ie ? obj.filters["Alpha"].opacity : obj.style.opacity;var t;	if(Ekina.Browser.ie)t = new Ekina.UI.Effects.Tween(obj.filters["Alpha"], "opacity", currentOpacity, to, options["duration"], options["func"]);else t = new Ekina.UI.Effects.Tween(obj.style, "opacity", currentOpacity * 100, to, options["duration"], options["func"], "", .01); t.type = "Tween {Alpha}";	return t;};
Ekina.UI.Effects.Tween.move = function(obj, toX, toY, options) {options = Ekina.UI.Effects.Tween._validateOptions(options);	options["unit"] = "px";	var queue = new Ekina.UI.Effects.TweenQueue();	queue._add("prop", obj.style, {prop: "left", to: toX}, options);	queue._add("prop", obj.style, {prop: "top", to: toY}, options);	queue.type = "TweenQueue {Move}";return queue;};

Ekina.UI.Effects.ResizeMode = {
	Normal : 1,
	WidthFirst : 2,
	HeightFirst : 4
};

Ekina.UI.Effects.Tween.resize = function(obj, toW, toH, options) {
	options = Ekina.UI.Effects.Tween._validateOptions(options);
	options["unit"] = "px";
	var queue = new Ekina.UI.Effects.TweenQueue();
	var resizeType = $number(options["resizeType"]) ? options.resizeType : Ekina.UI.Effects.ResizeMode.Normal;
	switch (resizeType) {
		case Ekina.UI.Effects.ResizeMode.WidthFirst: var optW = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "width", to: toW}, optW); if (options.keepCenter) { var l = parseInt(obj.style.left); var toX = parseInt(obj.style.width) < toW ? l - (toW / 2) : l + ((parseInt(obj.style.width) / 2) - (toW / 2)); var optL = {duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "left", to: toX}, optL); } var optH = { duration: options.duration, callback: options.callback, func: options.func, wait: true, unit: "px" }; queue._add("prop", obj.style, {prop: "height", to: toH}, optH); if (options.keepCenter) { var t = parseInt(obj.style.top); var toY = parseInt(obj.style.height) < toH ? t - (toH / 2) : t + ((parseInt(obj.style.height) / 2) - (toH / 2)); var optT = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "top", to: toY}, optT); } break;
		case Ekina.UI.Effects.ResizeMode.HeightFirst: var optH = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "height", to: toH}, optH); if (options.keepCenter) {	var t = parseInt(obj.style.top); var toY = parseInt(obj.style.height) < toH ? t - (toH / 2) : t + ((parseInt(obj.style.top) / 2) - (toH / 2)); var optT = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "top", to: toY}, optT); }	var optW = { duration: options.duration, callback: options.callback, func: options.func, wait: true, unit: "px"	}; queue._add("prop", obj.style, {prop: "width", to: toW}, optW); if (options.keepCenter) { var l = parseInt(obj.style.left); var toX = parseInt(obj.style.width) < toW ? l - (toW / 2) : l + ((parseInt(obj.style.left) / 2) - (toW / 2)); var optL = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "left", to: toX}, optL); } break;
		default: var optW = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "width", to: toW}, optW); queue._add("prop", obj.style, {prop: "height", to: toH}, options); if (options.keepCenter) { var t = parseInt(obj.style.top); var toY = parseInt(obj.style.height) < toH ? t - (toH / 2) : t + ((parseInt(obj.style.height) / 2) - (toH / 2)); var optT = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "top", to: toY}, optT); var l = parseInt(obj.style.left); var toX = parseInt(obj.style.width) < toW ? l - (toW / 2) : l + ((parseInt(obj.style.width) / 2) - (toW / 2)); var optL = { duration: options.duration, callback: null, func: options.func, wait: false, unit: "px" }; queue._add("prop", obj.style, {prop: "left", to: toX}, optL); } break;
	}
	queue.type = "TweenQueue {Resize}";
	return queue;
};

Ekina.UI.Effects.Tween._validateOptions = function(options) {
	if (!$number(options["duration"]))
		options["duration"] = 2;
	if (!$function(options["func"]))
		options["func"] = Ekina.UI.Effects.Tween.None;
	return options;
};

Ekina.UI.Effects.TweenQueue = function(name) {
	this.type = "TweenQueue";
	this.tweens = [];
	this.runningTweens = [];
	this.onTweenFinished = null;
	this.current = null;
	this.queue = null;
	this.isFinished = false;
	this.name = name;
};

Ekina.UI.Effects.TweenQueue.prototype.stop = function() {
	if ($null(this.current))
		return;
		
	this.runningTweens.forEach(function(tween) {
		tween.stop();
	});
};

Ekina.UI.Effects.TweenQueue.prototype.clear = function() {
	this.stop();
	
	this.current = null;
	this.tweens.clear();
	this.runningTweens.clear();
	this.queue = null;
	this.isFinished = false;
};

Ekina.UI.Effects.TweenQueue.prototype.start = function() {
	this.isFinished = false;
	this.nextTween();
};

Ekina.UI.Effects.TweenQueue.prototype._isTweenQueue = function() {
	return true;
};

Ekina.UI.Effects.TweenQueue.prototype._add = function(type, object, props, options) {
	
	if (typeof object == "string")
		object = $(object);
	
	this.tweens.add({type: type, object: object, props: props, options: options});
};

Ekina.UI.Effects.TweenQueue.prototype.addAlpha = function(object, to, options) { this._add("alpha", object, {to: to}, options); };
Ekina.UI.Effects.TweenQueue.prototype.addMove = function(object, toX, toY, options) { this._add("move", object, {toX: toX, toY: toY}, options); };
Ekina.UI.Effects.TweenQueue.prototype.addResize = function(object, toW, toH, options) { this._add("resize", object, {toW:toW, toH:toH}, options); };

Ekina.UI.Effects.TweenQueue._onTweenFinished = function(sender, args) {
	if (typeof sender.oldOnTweenFinished == "function")
		sender.oldOnTweenFinished(sender, args);
	if (sender != sender.queue.current) 
		return;
	sender.queue.runningTweens.remove(sender);
	sender.queue.nextTween();
};

Ekina.UI.Effects.TweenQueue.prototype.nextTween = function() {
	if (this.isFinished)
		return;

	this.current = null;

	if (this.tweens.length == 0) {
		if (!this.isFinished)
			if (typeof this.onTweenFinished == "function")
				this.onTweenFinished(this, []);
		this.onTweenFinished = null;
		this.isFinished = true;
		return;
	}
	
	var tweenProps = this.tweens.removeAt(0);
	var tween = this.createTween(tweenProps);
		
	if (Ekina.UI.Effects.TweenQueue.isQueue(tween))
		tween.nextTween();
	else {
		if ($number(tweenProps.options["delay"]) && tweenProps.options["delay"] > 0)
			window.setTimeout(function(){Ekina.UI.Effects.TweenQueue._startTween(tween);}, tweenProps.options["delay"] * 1000);
		else
			tween.start();
	}
	
	this.runningTweens.add(tween);
	this.current = tween;
	
	if (this.tweens.length == 0)
		return;
	
	if (!this.tweens[0].options["wait"])
		this.nextTween();
};

Ekina.UI.Effects.TweenQueue._startTween = function(t) {
	t.start();
};

Ekina.UI.Effects.TweenQueue.prototype.createTween = function(tweenProps) {
	var tween = null;
	switch (tweenProps.type.toLowerCase()) {
		case "alpha":
			tween = Ekina.UI.Effects.Tween.alpha(tweenProps.object, tweenProps.props.to, tweenProps.options);
			break;
		case "move":
			tween = Ekina.UI.Effects.Tween.move(tweenProps.object, tweenProps.props.toX, tweenProps.props.toY, tweenProps.options);
			break;
		case "resize":
			tween = Ekina.UI.Effects.Tween.resize(tweenProps.object, tweenProps.props.toW, tweenProps.props.toH, tweenProps.options);
			break;
		case "prop":
			var current = parseInt(tweenProps.object[tweenProps.props.prop]);
			var to = tweenProps.options.relative ? current + tweenProps.props.to : tweenProps.props.to;
			tween = new Ekina.UI.Effects.Tween(tweenProps.object, tweenProps.props.prop, current, to, tweenProps.options.duration, tweenProps.options.func, tweenProps.options.unit);
			tween.type = "Tween {Property: " + tweenProps.props.prop + "}";
			break;
	};
	
	tween.oldOnTweenFinished = tweenProps.options.callback;
	tween.queue = this;
	tween.onTweenFinished = Ekina.UI.Effects.TweenQueue._onTweenFinished;
	
	return tween;
};

Ekina.UI.Effects.TweenQueue.isQueue = function(obj) {
	return typeof obj._isTweenQueue == "function";
};

Ekina.DOM.extendElement("effectTweenQueue", null);

Ekina.DOM.extendElement("stopTweenQueue", function() {
	if ($null(this.effectTweenQueue))
		return;
	
	this.effectTweenQueue.stop();
});

Ekina.DOM.extendElement("checkTweenQueue", function() {
	if ($null(this.effectTweenQueue))
		this.effectTweenQueue = new Ekina.UI.Effects.TweenQueue();
	else
		this.effectTweenQueue.clear();
});

Ekina.DOM.extendElement("fadeIn", function(to, duration, callback, func) {	
	this.stopTweenQueue();
	to = $number(to) ? Math.min(to, 100) : 100;
	duration = $number(duration) ? duration : 1;
	this.checkTweenQueue();
	this.effectTweenQueue.addAlpha(this, to, {duration: duration, callback: callback, func: func});
	this.effectTweenQueue.start();
	return this;
});

Ekina.DOM.extendElement("fadeOut", function(to, duration, callback, func) {
	this.stopTweenQueue();
	to = $number(to) ? Math.max(to, 0) : 0;
	duration = $number(duration) ? duration : 1;
	this.checkTweenQueue();
	this.effectTweenQueue.addAlpha(this, to, {duration: duration, callback: callback, func: func});
	this.effectTweenQueue.start();
	return this;
});

Ekina.DOM.extendElement("resize", function(toW, toH, duration, callback, resizeType, keepCenter, func) {
	if ($null(duration) && $null(callback) && $null(resizeType) && $null(keepCenter) && $null(func)) {
		this.css({
			width: toW + "px",
			height: toH + "px"
		});
		return this;
	}
	this.stopTweenQueue();
	toW = $number(toW) ? Math.max(toW, 0) : 0;
	toH = $number(toH) ? Math.max(toH, 0) : 0;
	duration = $number(duration) ? duration : 1;
	keepCenter = $bool(keepCenter) ? $bool(keepCenter) : false;
	this.checkTweenQueue();
	this.effectTweenQueue.addResize(this, toW, toH, {duration: duration, callback: callback, func: func, resizeType: resizeType, keepCenter: keepCenter});
	this.effectTweenQueue.start();
	return this;
});

Ekina.DOM.extendElement("move", function(toX, toY, duration, callback, func) {
	if ($null(duration) && $null(callback) && $null(func)) {
		this.css({
			left: toX + "px",
			top: toY + "px"
		});
		return this;
	}
	this.stopTweenQueue();
	toX = toX || 0;
	toY = toY || 0;
	duration = $number(duration) ? duration : 1;
	this.checkTweenQueue();
	this.effectTweenQueue.addMove(this, toX, toY, {duration: duration, callback: callback, func: func});
	this.effectTweenQueue.start();
	return this;
});
