
/* 
 * 
 * userAgent.js
 * 
 * @author		http://www.glide.co.jp
 * @version 	1.0
 * @ 2011-06-16
 * 
 */

// common.js

/*
 * tween.js
 * 
 * @author		GLIDE ARTS STUDIO.
 * @version		0.2
 * @2011-08-03
 * 
 * Copyright (C) 2011 GLIDE ARTS STUDIO.
 * 
 */

var Tween = function () {
	
	this._target
	this._id
	this._callBackFunc
	this._transition
	this._len;
	this._top
	this._left
	this._bottom
	this._right
	this._opacity;
	this._startVal;
	this._endVal;
	this._supportsTouches = ("createTouch" in document);
	this._currentFrame    = 0;
	this._duration        = 0;
	this._time            = 0;
	this._running         = false
	this._prop;
	this._unit;
	
	/* 
	 * _prop[n][0] style:String / _prop[n][1] value(include units):String
	 * _unit[n][0] value:Number / _unit[n][1] unit:String
	 *
	 */
}

var TweenPrototype = Tween.prototype;

/* 
 * Tween.prototype.play
 * 
 * @ target			:	Object or String
 * @ properties		:	Object
 * @ [duration]		:	Number
 * @ [callBack]		:	Function
 * @ [transition]	:	Function String
 * 
 */

Tween.prototype.play = function (target, properties, duration, transition, callBack) {
	
	if (this._running === false) {
		this._prop     = new Array();
		this._unit     = new Array();
		this._startVal = new Array();
		this._endVal   = new Array();
		this._target = target == typeof "string" ? document.getElementById(target) : target;
		this._running = true;
		this._currentFrame = 0;
		this._len = 0;
		
		// Strage of Properties.
		for (var i in properties) {
			
			this._prop[this._len] = new Array();
			
			switch (i) {
				case "top"     : this._prop[this._len][0] = "top"    ; this._prop[this._len][1] = properties.top;     break;
				case "left"    : this._prop[this._len][0] = "left"   ; this._prop[this._len][1] = properties.left;    break;
				case "right"   : this._prop[this._len][0] = "right"  ; this._prop[this._len][1] = properties.right;   break;
				case "bottom"  : this._prop[this._len][0] = "bottom" ; this._prop[this._len][1] = properties.bottom;  break;
				case "opacity" : this._prop[this._len][0] = "opacity"; this._prop[this._len][1] = properties.opacity; break;
			}
			this._len++;
		}
		
		// Strage of Value.
		for (var i = 0; i < this._len; i++) {
			
			var prp = this._prop[i][1];
			var hit = String(prp.match(/px|em|%|deg|rem|s|ms|gd|vh|vw|vm|ch/i));
			var prl = prp.length;
			var phl = hit.length;
			
			this._unit[i] = new Array();
			this._unit[i][0] = parseFloat(prp.substring(0, prl - phl));
			this._unit[i][1] = prp.substring(prl - phl, prl);
		}
		
		duration === undefined ? this._duration = 100 : this._duration = duration * 100;
		
		if (transition === undefined) {
			this._transition = easeInOutExpo;
			
		} else {
			typeof transition === "string" ? this._transition = eval(transition) : this._transition = transition;
		}
		
		if (callBack) this._callBackFunc = callBack;
		
		var body = document.getElementsByTagName("body")[0];
		var bodyStyle = body.currentStyle || document.defaultView.getComputedStyle(body, '');
		var bodyMarginTop = parseInt(bodyStyle.marginTop);
		var bodyMarginLeft = parseInt(bodyStyle.marginLeft);
		
		for (var j = 0; j < this._len; j++) {
			this._startVal[j] = getElementPosition(this._target, "relative")[j];
			j === 0 ? this._startVal[j] -= bodyMarginTop : this._startVal[j] -= bodyMarginLeft;
			
			this._endVal[j] = this._unit[j][0] - this._startVal[j];
			j === 0 ? this._endVal[j] -= bodyMarginTop : this._endVal[j] -= bodyMarginLeft;
		}
		
		this.loop();
		
	} else {
		this.cancel(true, target, properties, duration, transition, callBack);
	}
}


Tween.prototype.cancel = function (isRestart, target, properties, duration, transition, callBack) {
	
	this.removeTweens();
	delete this._callBackFunc;
	this._running = false;
	if (isRestart) this.play(target, properties, duration, transition, callBack);
}


Tween.prototype.stop = function (id) {

	window.clearTimeout(id);
	this._running = false;
}


Tween.prototype.removeTweens = function () {

	window.clearTimeout(this._id);
	this._running = false;
}


Tween.prototype.loop = function () {
	
	var t = this;
	
	for (var i = 0; i < t._len; i++) {
		t._target.style[t._prop[i][0]] = t._transition(t._currentFrame, t._startVal[i], t._endVal[i], t._duration) + t._unit[i][1];
	}
	
	if (t._currentFrame >= t._duration) {
		t.removeTweens();
		if (t._callBackFunc != undefined) t._callBackFunc();
		t._callBackFunc = null;
		
	} else {
		t._id = window.setTimeout(function(){t.loop()}, 10);
		t._currentFrame++;
	}
}


/*----------------------------------------------------------------------------------------------- */



// position : absolute
function getElementPosition(element, positionType) {
	
	var target = typeof element == "string" ? document.getElementById(element) : element;
	var left   = 0;
	var top    = 0;
	
	if(positionType == "relative") {
		left = target.offsetLeft;
		top = target.offsetTop;
		
	} else {
		while (target) {
			left  += target.offsetLeft;
			top   += target.offsetTop;
			target = target.offsetParent;
		}
	}
	
	return new Array(left, top);
}



/* ---------------------------------------------------------------------------------------------- */

/*
 * Easing equations quote from Robert Penner's
 * AntionScript Easing Equations.
 * 
 * @author		GLIDE ARTS STUDIO.
 * @version		0.1
 * 
 * 
 * Disclaimer for Robert Penner's Easing Equations license:
 *
 * TERMS OF USE - EASING EQUATIONS v2.0
 * 
 * Open source under the BSD License.
 * Copyright (c) 2001 Robert Penner All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted 
 * provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this list of conditions
 *   and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright notice, this list of 
 *   conditions and the following disclaimer in the documentation and/or other materials provided 
 *   with the distribution.
 * * Neither the name of the author nor the names of contributors may be used to endorse or promote
 *   products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * 
 */


function linear (t, b, c, d) {
	return c * t / d + b;
}

function easeNone (t, b, c, d) {
	return c * t / d + b;
}

function easeInOutExpo(t, b, c, d) {
	if (t == 0) return b;
	if (t == d) return b + c;
	if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
	return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
}

function easeOutExpo(t, b, c, d) {
	return t == d ? b + c : c * 1.001 * (-Math.pow(2, -10 * t / d) + 1) + b;
}

function easeOutExpoCustom(t, b, c, d) {
	return t == d ? b + c : c * 1.000 * (-Math.pow(10, -10 * t / d) + 1) + b;
}
