/*
Animator JScript
Developed by: W3Fix
Author: Jason K. Fulton
Create Date: 6/26/2009
Last Update: 3/5/2010
Version: 0.7.4

http://www.w3fix.com
W3Fix gives permission to use this code and greatly appreciates link backs, mentions, posts, etc.
We would be happy to hear feed back for future enhancements or bug fixes.
Email detailed information to info@w3fix.com
*/
var isIE=(navigator.userAgent.indexOf('MSIE')!==-1)?1:0;

function Animator(){
    var boundObj = 'undefined';
    var easing = 3.1;
    var initPos = -1; 
    var start, end, moveType;
    var currentAmt = 0;
    var isMoving = false; 
    var intervalRate = 50;
    var intervalObj = 'undefined';
    var traceStatus = false;
    var actionList = new Array();
    var actionDelimiter = '|';
    var actionValueDelimiter = ':';
    var totalActionSteps = 0;
    var curActionStep = 0;
    
    this.bindObj = function(inObj){boundObj = inObj;}
    this.getBoundObj = function(){return boundObj;}
    this.setEasing = function(doubleEasing){easing = doubleEasing;}
    this.getEasing = function(){return easing;}
    this.getStartPos = function(){return start;}
    this.setStartPos = function(inStart){start = inStart;}
    this.setInitPos = function(inInitPos){initPos = inInitPos;}
    this.getInitPos = function(){if(initPos === -1){return initPos;}else{return initPos - 1;}}
    this.getEnd = function(){return end;}
    this.setEnd = function(inEnd){end = inEnd;}
    this.setMoveType = function(inStr){moveType = inStr;}
    this.getMoveType = function(){return moveType;}
    this.getMoveAmt = function(){return Math.round((end - start) / easing);}
    this.setIsMoving = function(inBool){isMoving = inBool;}
    this.isMoving = function(){return isMoving;}
    this.getIntervalRate = function(){return intervalRate;}
    this.setIntervalRate = function(inRate){intervalRate = inRate;}
    this.setIntervalObj = function(inInterval){intervalObj = inInterval;}
    this.getIntervalObj = function(){return intervalObj;}
    this.onComplete = 'undefined';
    this.getActionList = function(){return actionList;}
    this.getAction = function(intIndex){return actionList[intIndex];}
    this.setActionDelimiter = function(strDelimiter){actionDelimiter = strDelimiter;}
    this.getActionDelimiter = function(){return actionDelimiter;}
    this.getActionValueDelimiter = function(){return actionValueDelimiter;}
    this.setActionList = function(strActionList){
        if(strActionList.indexOf(actionDelimiter)===-1){
            // check if adding single action
            if(strActionList.indexOf(actionValueDelimiter)===-1){
                this.trace('setActionList - call failed, ' + strActionList + ' bad value.\n');
                return;
            }else{
                var actionNameVal = strActionList.split(actionValueDelimiter);
                if(this.isValidMoveType(actionNameVal[0])){
                    actionList.push(strActionList);
                }else{
                    this.trace('setActionList - call failed, invalid move type.\n');
                    return;
                }
            }    
        }else{
            // process action list
            var actionNameValueList = strActionList.split(actionDelimiter);
            for(var i = 0; i < actionNameValueList.length; i++){
                var actionNameVal = actionNameValueList[i].split(actionValueDelimiter);
                if(this.isValidMoveType(actionNameVal[0])){
                    actionList.push(actionNameValueList[i]);
                }else{
                    this.trace('setActionList - skipped a list item, invalid move type.\n');
                }    
            }
        }
        this.setTotalActionSteps(actionList.length);     
    }
    this.setTotalActionSteps = function(intTotalSteps){totalActionSteps = intTotalSteps;}
    this.getTotalActionSteps = function(){return totalActionSteps;}
    this.setActionStep = function(intStep){curActionStep = intStep;}
    this.getActionStep = function(){return curActionStep;}
    this.traceOn = function(){traceStatus = true;}
    this.traceOff = function(){traceStatus = false;}
    this.getTraceStatus = function(){return traceStatus;}   
}

Animator.prototype.activateActionStep = function(intIndex){
    var thisObj = this;
    var nameval = thisObj.getAction(intIndex);
    var name = nameval.split(thisObj.getActionValueDelimiter())[0];
    var val = nameval.split(thisObj.getActionValueDelimiter())[1];
    switch(name){
        case 'width':
            thisObj.widthTo(val);
        break;
        case 'height':
            thisObj.heightTo(val); 
        break;
        case 'xpos':
            thisObj.xposTo(val); 
        break;
        case 'ypos':
            thisObj.yposTo(val); 
        break;
        case 'opacity':
            thisObj.opacityTo(val);
        break;
        case 'scrollVerticalTo':
            thisObj.scrollVerticalTo(val);
        break;
        case 'scrollHorizontalTo':
            thisObj.scrollHorizontalTo(val);
        break;
    }
}

Animator.prototype.heightTo = function(toHeight){
    this.setEnd(toHeight);
    this.setMoveType('height');
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(this.getBoundObj().style.height));
    }
    this.setStartPos(parseInt(this.getBoundObj().style.height));
}

Animator.prototype.widthTo = function(toWidth){
    this.setEnd(toWidth);
    this.setMoveType('width');
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(this.getBoundObj().style.width));
    }
    this.setStartPos(parseInt(this.getBoundObj().style.width));
}

Animator.prototype.yposTo = function(toPos){
    this.setEnd(toPos);
    this.setMoveType('ypos');
    var elemObj = this.getBoundObj();
    elemObj.style.top = this.getBoundObjAbsoluteYPos() + 'px';
    elemObj.style.left = this.getBoundObjAbsoluteXPos() + 'px';
    elemObj.style.position = 'absolute';
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(elemObj.style.top));
    }
    this.setStartPos(parseInt(elemObj.style.top));
}

Animator.prototype.xposTo = function(toPos){
    this.setEnd(toPos);
    this.setMoveType('xpos');
    var elemObj = this.getBoundObj();
    elemObj.style.top = this.getBoundObjAbsoluteYPos() + 'px';
    elemObj.style.left = this.getBoundObjAbsoluteXPos() + 'px';
    elemObj.style.position = 'absolute';
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(elemObj.style.left));
    }
    this.setStartPos(parseInt(elemObj.style.left));
}

Animator.prototype.scrollVerticalTo = function(toScrollPos){
    this.setEnd(toScrollPos);
    this.setMoveType('scrollVerticalTo');
    var elemObj = this.getBoundObj();
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(elemObj.scrollTop));
    }
    this.setStartPos(parseInt(elemObj.scrollTop));
}

Animator.prototype.scrollHorizontalTo = function(toScrollPos){
    this.setEnd(toScrollPos);
    this.setMoveType('scrollHorizontalTo');
    var elemObj = this.getBoundObj();
    if(this.getInitPos() === -1){
        this.setInitPos(parseInt(elemObj.scrollLeft));
    }
    this.setStartPos(parseInt(elemObj.scrollLeft));
}

Animator.prototype.makeBlockScroller = function(switchInterval){
    var sDiv = this.getBoundObj();
    var inDivs = sDiv.getElementsByTagName('div');
    var ani = new Animator();
    ani.bindObj(sDiv);
    var divsScrollTos = new Array();
    for(var i=0;i<inDivs.length;i++){
        divsScrollTos[i] = inDivs[i].offsetTop;
    }
    var interval = setInterval(function(){
        if(isNaN(ani.step)){
            ani.step = 1;
        }
        ani.scrollVerticalTo(divsScrollTos[ani.step]);
        if(ani.step>=divsScrollTos.length){
            ani.scrollVerticalTo(0);
            ani.step=0;
        }
        ani.start();
        ani.step++;
    },switchInterval);    
}

Animator.prototype.opacityTo = function(toOpacity){
    this.setMoveType('opacity'); 
    var elemObj = this.getBoundObj();
    if(this.getInitPos() === -1){
        if(isIE){
            if(elemObj.style.filter){
                this.setInitPos(getOpacityByFilter(elemObj.style.filter));    
            }else{
                this.setInitPos(100);
            }
        }else{
            if(elemObj.style.opacity){
                // converting decimal value to percent equivalent in integer form
                this.setInitPos(parseInt(100 * parseFloat(elemObj.style.opacity)));    
            }else{
                this.setInitPos(100);
            }
        }
    }
    if(isIE){
        if(elemObj.style.filter){
            this.setStartPos(getOpacityByFilter(elemObj.style.filter));    
        }else{
            elemObj.style.filter = 'alpha(opacity=100)';
            elemObj.style.zoom=1;
            this.setStartPos(100);
        }    
    }else{
        if(elemObj.style.opacity){
            // converting decimal value to percent equivalent in integer form
            this.setStartPos(parseInt(100 * parseFloat(elemObj.style.opacity)));    
        }else{
            elemObj.style.opacity=1;
            this.setStartPos(100);
        }    
    }
    var endOpacity;
    if(toOpacity<=1){
        endOpacity = parseInt(100 * toOpacity);
    }else{
        endOpacity = toOpacity;
    }
    this.setEnd(endOpacity);  
}

Animator.prototype.heightMouseOver = function(toPos){
    var thisObj = this;
    var elemObj = thisObj.getBoundObj();
    elemObj.onmouseover = function(){
        if(thisObj.isMoving()){
            thisObj.heightTo(toPos);
        }else{
            thisObj.heightTo(toPos);
            thisObj.start();
        }
    }
    elemObj.onmouseout = function(){
        if(thisObj.isMoving()){
            thisObj.heightTo(thisObj.getInitPos());
        }else{
            thisObj.heightTo(thisObj.getInitPos());
            thisObj.start();
        }
    }
}

Animator.prototype.widthMouseOver = function(toPos){
    var thisObj = this;
    var elemObj = thisObj.getBoundObj();
    elemObj.onmouseover = function(){
        if(thisObj.isMoving()){
            thisObj.widthTo(toPos);
        }else{
            thisObj.widthTo(toPos);
            thisObj.start();
        }
    }
    elemObj.onmouseout = function(){
        if(thisObj.isMoving()){
            thisObj.widthTo(thisObj.getInitPos());
        }else{
            thisObj.widthTo(thisObj.getInitPos());
            thisObj.start();
        }
    }
}
//main engine for driving animation of the dom
Animator.prototype.move = function(){
    var thisObj = this;
    var elemObj = thisObj.getBoundObj();
    
    switch(thisObj.getMoveType()){
        case 'height':
            var elemNum = parseInt(elemObj.style.height);
            thisObj.setStartPos(elemNum);
            // setting elemObj new height here
            elemObj.style.height = (parseInt(elemObj.style.height) + thisObj.getMoveAmt()) + 'px';
            thisObj.trace('current height is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
        case 'width':
            var elemNum = parseInt(elemObj.style.width);
            thisObj.setStartPos(elemNum);
            // setting elemObj new height here
            elemObj.style.width = (parseInt(elemObj.style.width) + thisObj.getMoveAmt()) + 'px';
            thisObj.trace('current width is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
        case 'ypos':
            var elemNum = parseInt(elemObj.style.top);
            thisObj.setStartPos(elemNum);
            // setting elemObj new height here
            elemObj.style.top = (parseInt(elemObj.style.top) + thisObj.getMoveAmt()) + 'px';
            thisObj.trace('current ypos is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
        case 'xpos':
            var elemNum = parseInt(elemObj.style.left);
            thisObj.setStartPos(elemNum);
            // setting elemObj new height here
            elemObj.style.left = (parseInt(elemObj.style.left) + thisObj.getMoveAmt()) + 'px';
            thisObj.trace('current xpos is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
        case 'opacity':
            var elemNum;
            if(isIE){
                elemNum = getOpacityByFilter(elemObj.style.filter);
            }else{
                elemNum = parseInt(100 * parseFloat(elemObj.style.opacity));
            }
            thisObj.setStartPos(elemNum);
            // changing opacity here
            if(isIE){
                elemObj.style.filter = 'alpha(opacity=' + (getOpacityByFilter(elemObj.style.filter) + thisObj.getMoveAmt()) + ')';
            }else{
                elemObj.style.opacity =  (parseFloat(elemObj.style.opacity) + (thisObj.getMoveAmt() / 100));
            }
        break;
        case 'scrollVerticalTo':
            var elemNum = parseInt(elemObj.scrollTop);
            thisObj.setStartPos(elemNum);
            // setting elemObj new scrollTop here
            elemObj.scrollTop = (parseInt(elemObj.scrollTop) + thisObj.getMoveAmt());
            thisObj.trace('current scrollTop is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
        case 'scrollHorizontalTo':
            var elemNum = parseInt(elemObj.scrollLeft);
            thisObj.setStartPos(elemNum);
            // setting elemObj new scrollLeft here
            elemObj.scrollLeft = (parseInt(elemObj.scrollLeft) + thisObj.getMoveAmt());
            thisObj.trace('current scrollLeft is ' + elemNum + ' moving = ' + thisObj.isMoving() + ' <br />');
        break;
    }
}

//stops the animation and fires any defined oncomplete functions
Animator.prototype.stop = function(){
    var thisObj = this;
    if((typeof thisObj.onComplete) === 'function'){
        thisObj.onComplete();
        thisObj.onComplete = 'undefined';
    }else{
        clearInterval(thisObj.getIntervalObj());
        thisObj.setIntervalObj('undefined');
    }
    
}

//starts and initializes values for animation, controls the creation and use of intervals use for motion
Animator.prototype.start = function(){
    var thisObj = this;
    var elemObj = this.getBoundObj();
    if(thisObj.getIntervalObj() === 'undefined'){
        if(thisObj.getTotalActionSteps()>0){
            thisObj.setActionStep(0);
            thisObj.activateActionStep(0);
        }
        thisObj.setIntervalObj(setInterval(function(){
            // moving elemObj
            thisObj.setIsMoving(true);
            thisObj.move();
            if(thisObj.getMoveAmt() === 0){
                thisObj.setActionStep(thisObj.getActionStep() + 1);
                if(thisObj.getActionStep()<thisObj.getTotalActionSteps()){
                    thisObj.activateActionStep(thisObj.getActionStep());
                }else{
                    thisObj.stop();
                    thisObj.setIsMoving(false);    
                } 
            }
        },thisObj.getIntervalRate()));
    }else{
        //supress creation of interval
    }
}

// fires all actions at once, instead of sequential
Animator.prototype.forkActionList = function(){
    var thisObj = this;
    var elemObj = this.getBoundObj();
    var animatorList = new Array();
    var completeSteps = 0;
    var i = 0;
    for(i=0;i<thisObj.getTotalActionSteps();i++){
        animatorList[i] = new Animator();
        animatorList[i].bindObj(elemObj);
        animatorList[i].setActionList(thisObj.getAction(i));
        animatorList[i].setEasing(thisObj.getEasing());
        animatorList[i].setIntervalRate(thisObj.getIntervalRate());
        animatorList[i].onComplete = function(){
            completeSteps+=1;
            if(completeSteps===thisObj.getTotalActionSteps()){
                thisObj.onComplete();
            }
        }
    }
    for(i=0;i<animatorList.length;i++){
        animatorList[i].start();
    }   
}

//verifies valid move types
Animator.prototype.isValidMoveType = function(strMoveType){
    var isValid = true;
    switch(strMoveType){
        case 'width':
        break;
        case 'height':
        break;
        case 'xpos':
        break;
        case 'ypos':
        break;
        case 'opacity':
        break;
        case 'scrollVerticalTo':
        break;
        case 'scrollHorizontalTo':
        break;
        default:
        isValid = false;
        break;
    }
    return isValid;
}

// gets the absolute y position of the bound object through interation of containing elements
Animator.prototype.getBoundObjAbsoluteYPos = function(){
    var yPos = 0;
    var elemObj = this.getBoundObj();
    while(elemObj != null){
        yPos += elemObj.offsetTop;
        elemObj = elemObj.offsetParent;
    }
    return yPos;
}

// gets the absolute x position of the bound object through interation of containing elements  
Animator.prototype.getBoundObjAbsoluteXPos = function(){
    var xPos = 0;
    var elemObj = this.getBoundObj();
    while(elemObj != null){
        xPos += elemObj.offsetLeft;
        elemObj = elemObj.offsetParent;
    }
    return xPos;
}

//spits out trace info into the bound object -- mainly for dev
Animator.prototype.trace = function(inMsg,overrideOnce){
	var overOnce = false;
	if(overrideOnce){
		overOnce = true;
	}
	if(this.getTraceStatus()){
		this.getBoundObj().innerHTML += inMsg;
	}else{
	    if(overOnce){
	        this.getBoundObj().innerHTML += inMsg;
	    }
	}
}

//e is the event from which you want the mouse x and y
function getMouseXY(e){
	var xpos, ypos;
	if(!isIE){document.captureEvents(Event.MOUSEMOVE);}
	if(isIE){
		xpos = event.clientX + document.body.scrollLeft;
		ypos = event.clientY + document.body.scrollTop;
	}else{
		xpos = e.pageX;
		ypos = e.pageY;
	}  
	if(xpos < 0){xpos = 0;}
	if(ypos < 0){ypos = 0;}  
	return (xpos + ',' + ypos);
}

//function for IE
function getOpacityByFilter(strFilter){
    return parseInt(strFilter.replace('alpha(opacity=','').replace(')','')); 
}