/*
version 2.3
Jamil Ahmed
www.aunqur.com

20110818 - event added to stop and resume on window focus lost and on focus
         - hoverPause = (true/false) automatically pause if mouse over on slider. false it if you want to run it as continuous background slider. [default:true]
20101104 - start auto play on hover after pause (fixed)

*must load jQuery and its effects core ui to work
*elements can be supplied by jQuery selector

waitTime = number of seconds to wait before each transition
fadeTime = number of seconds for the transition
isRandom = (true/false) is randomly choose selected / active item [default:false]
transition = (slide/fade) transition effects [default:fade]
container = the container holds the slides
slide = each slide class / tag inside the container
paginContainer = container that holds the slide indexes
paginElem = elements / each index of slides
topBottom = (true/false) is the transition direction top to bottom [default:false]
diagonal = (true/false) is the transition moves diagonally ( prototype, special effect ) [default:false]
noAutoSlide = (true/false) automatic transition on/off [default:false]
hideController = (true/false) automatically hide controller if there is only one slide [default:true]
hoverPause = (true/false) automatically pause if mouse over on slider. false it if you want to run it as continuous background slider. [default:true]

next = element that triggers next
previous = element that triggers previous
pauseToggle = element that toggle auto transition [ pause class when paused, play class while playing ]

//event handler
onPause = callback function on pause
onPlay = callback function on play
onChange = callback function on change must recieve an argument as index number of the current item
onNext = callback function on next
onPrevious = callback function on previous

example: new fadeAppear({
    container:'#jContainer',
    slide:'.slide',
    paginContainer:'#paging',
    paginElem:'li',
    fadeTime:0.5,
    waitTime:5.0,
    next:'#next',
    previous:'#prev',
    isRandom:true,
    transition:'slide',
    hoverPause:true,
    onChange:function(index){alert(index);}
    });
*/
var fadeAppear = function(o){
    var ths = new Object;
    ths.container = o.container;
    ths.slide = o.slide;
    ths.paginContainer = o.paginContainer;
    ths.paginElem = o.paginElem;
    ths.waitTime = (o.waitTime?o.waitTime:5.0)*1000;
    ths.fadeTime = (o.fadeTime?o.fadeTime:0.5)*1000;
    ths.isRandom = o.isRandom?o.isRandom:false;
    ths.transition = o.transition?o.transition:'fade';
    ths.topBottom = o.topBottom?o.topBottom:false;
    ths.diagonal = o.diagonal?o.diagonal:false;
    ths.noAutoSlide = o.noAutoSlide?o.noAutoSlide:false;
    ths.hideController = o.hideController?o.hideController:true;
    ths.hoverPause = o.hoverPause == false?false:true;
    
    
    ths.nextId = o.next?o.next:'';
    ths.previousId = o.previous?o.previous:'';
    ths.pauseToggle = o.pauseToggle?o.pauseToggle:'';
    //event handler
    ths.onPause = o.onPause?o.onPause:function(){};
    ths.onPlay = o.onPlay?o.onPlay:function(){};
    ths.onChange = o.onChange?o.onChange:function(index){};
    ths.onNext = o.onNext?o.onNext:function(){};
    ths.onPrevious = o.onPrevious?o.onPrevious:function(){};
    
    //initialize
    ths.init = function(){
        ths.elems = $(ths.container + ' ' + ths.slide);
        ths.paging = $(ths.paginContainer + ' ' + ths.paginElem);
        $(ths.paginContainer + ' a').attr('href','javascript:');
        if( ths.transition == 'slide' ){
            ths.eachWidth = $(ths.container).width();
            ths.eachHeight = $(ths.container).height();
            }
        if( ths.isRandom ) ths.hide = Math.round(Math.random() * (ths.elems.length-1));
        else ths.hide = ths.elems.length-1;
        ths.show = ths.hide+1;
        if( ths.show > ths.elems.length-1 ) ths.show = 0;
        if( ths.hide > ths.elems.length-1 ) ths.hide = 0;
        ths.interval = null;
        ths.isPrev = false;
        ths.transitionInterval = null;
        
        //pre process and initialize if there is more than one slide
        if( ths.elems.length > 1 ){
            //initialize controllers
            if( ths.nextId ) $(ths.nextId).click(ths.next).attr('href','javascript:');
            if( ths.previousId ) $(ths.previousId).click(ths.prev).attr('href','javascript:');
            if( ths.pauseToggle ) $(ths.pauseToggle).toggle(
                function(){
                    $(ths.pauseToggle).addClass('pause').removeClass('play');
                    ths.pause();
                    },
                function(){
                    $(ths.pauseToggle).addClass('play').removeClass('pause');
                    ths.play();
                    }).attr('href','javascript:');
            for( i = 0; i < ths.elems.length; i++ ){
                e = ths.elems[i];
                if( ths.hoverPause ) $(e).mouseover(ths.pause2).mouseout(ths.play2);
                if(ths.paging.length) $(ths.paging[i]).click(ths.directGo);
                if( ths.transition == 'slide' ){
                    if( ths.topBottom ) $(e).css({height:ths.eachHeight+'px'});
                    else $(e).css({width:ths.eachWidth+'px'});
                    }
                if( ths.hide != i ){
                    if( ths.transition == 'fade' ) $(e).fadeOut(20);
                    else if( ths.topBottom ) $(e).css({top:'-'+ths.eachHeight+'px'});
                    else $(e).css({left:'-'+ths.eachWidth+'px'});
                    }
                }
            $(ths.paging[ths.hide]).addClass('active');
            ths.fade();
            
            //stop al transition while not in focus and resume if found focus
            $(window).focus(ths.play).blur(ths.pause);
            }
        else if( ths.hideController ){
            //hide controllers
            $(ths.paging).css({visibility:'hidden'});
            $(ths.nextId).css({visibility:'hidden'});
            $(ths.previousId).css({visibility:'hidden'});
            $(ths.pauseToggle).css({visibility:'hidden'});
            }
        }
    
    //easy swap function
    ths.swap = function(){
        ths.tmp = ths.hide;
        ths.hide = ths.show;
        ths.show = ths.tmp;
        }
        
    //main effect function
    ths.fade = function(){
        if( ths.interval )
            clearInterval(ths.interval);
        if( ths.isPrev && !ths.goingDirect ){
            if( ths.transition == 'fade' ) ths.swap();
            else if( ths.transition == 'slide' ) ths.show-=2;
            }
        if( ths.show > ths.elems.length-1 ) ths.show = 0;
        else if( ths.show < 0 ) ths.show = ths.elems.length-1;
        if( ths.hide > ths.elems.length-1 ) ths.hide = 0;
        else if( ths.hide < 0 ) ths.hide = ths.elems.length-1;
        ths.onChange(ths.show);
        if( ths.transition == 'fade' ){
            $(ths.elems[ths.hide]).fadeOut(ths.fadeTime);
            $(ths.elems[ths.show]).fadeIn(ths.fadeTime);
            }
        else{
            if( ths.topBottom ){
                if( ths.isPrev ){
                    $(ths.elems[ths.show]).css({top:'-'+ths.eachHeight+'px'});
                    $(ths.elems[ths.hide]).css({top:'0px'});
                    $(ths.elems[ths.hide]).animate({top:'+'+ths.eachHeight+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({top:'0px'},ths.fadeTime);
                    }
                else{
                    $(ths.elems[ths.show]).css({top:'+'+ths.eachHeight+'px'});
                    $(ths.elems[ths.hide]).css({top:'0px'});
                    $(ths.elems[ths.hide]).animate({top:'-'+(ths.eachHeight+1)+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({top:'0px'},ths.fadeTime);
                    }
                }
            else if( ths.diagonal ){
                if( ths.isPrev ){
                    $(ths.elems[ths.show]).css({left:'+'+ths.eachWidth+'px',top:'-'+ths.eachHeight+'px'});
                    $(ths.elems[ths.hide]).css({left:'0px',top:'0px'});
                    $(ths.elems[ths.hide]).animate({left:'-'+ths.eachWidth+'px',top:'-'+ths.eachHeight+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({left:'0px',top:'0px'},ths.fadeTime);
                    }
                else{
                    $(ths.elems[ths.show]).css({left:'+'+ths.eachWidth+'px',top:'-'+ths.eachHeight+'px'});
                    $(ths.elems[ths.hide]).css({left:'0px',top:'0px'});
                    $(ths.elems[ths.hide]).animate({left:'-'+(ths.eachWidth+1)+'px',top:'-'+ths.eachHeight+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({left:'0px',top:'0px'},ths.fadeTime);
                    }
                }
            else{
                if( ths.isPrev ){
                    $(ths.elems[ths.show]).css({left:'-'+ths.eachWidth+'px'});
                    $(ths.elems[ths.hide]).css({left:'0px'});
                    $(ths.elems[ths.hide]).animate({left:'+'+ths.eachWidth+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({left:'0px'},ths.fadeTime);
                    }
                else{
                    $(ths.elems[ths.show]).css({left:'+'+ths.eachWidth+'px'});
                    $(ths.elems[ths.hide]).css({left:'0px'});
                    $(ths.elems[ths.hide]).animate({left:'-'+(ths.eachWidth+1)+'px'},ths.fadeTime);
                    $(ths.elems[ths.show]).animate({left:'0px'},ths.fadeTime);
                    }
                }
            }
        
        $(ths.paging[ths.hide]).removeClass('active');
        $(ths.paging[ths.show]).addClass('active');
        
        if( ths.isPrev && !ths.goingDirect ){
            if( ths.transition == 'slide' ){
                ths.show++;
                ths.hide = ths.show-1;
                }
            else{
                ths.swap();
                ths.show = ths.hide--;
                }
            }
        else{
            ths.hide = ths.show++;
            }
        ths.isPrev = false;
        ths.goingDirect = false;
        if( !ths.noAutoSlide ) ths.interval = setInterval(ths.fade,ths.waitTime);
        }
    //pause
    ths.pause = function(){
        clearInterval(ths.interval);
        ths.noAutoSlide = true;
        ths.onPause();
        }
    //for mouseover
    ths.pause2 = function(){
        clearInterval(ths.interval);
        ths.onPause();
        }
    //play
    ths.play = function(){
        clearInterval(ths.interval);
        ths.noAutoSlide = false;
        if( !ths.noAutoSlide ) ths.interval = setInterval(ths.fade,ths.waitTime);
        ths.onPlay();
        }
    //for mouseout
    ths.play2 = function(){
        clearInterval(ths.interval);
        if( !ths.noAutoSlide ) ths.interval = setInterval(ths.fade,ths.waitTime);
        ths.onPlay();
        }
    //next
    ths.next = function(){
        if( ths.transitionInterval ) return;
        ths.transitionInterval = setInterval(ths.clearTransition,ths.fadeTime);
        clearInterval(ths.interval);
        ths.fade();
        ths.onNext();
        }
    ths.prev = function(){
        if( ths.transitionInterval ) return;
        ths.transitionInterval = setInterval(ths.clearTransition,ths.fadeTime);
        clearInterval(ths.interval);
        ths.isPrev = true;
        ths.fade();
        ths.onPrevious();
        }
    //reset / clear transition
    ths.clearTransition = function(){
        clearInterval(ths.transitionInterval);
        ths.transitionInterval = null;
        }
    //external callback to go to specific index
    this.directGo2 = function(index){
        if( ths.transitionInterval ) return;
        ths.havToGo = index;
        if( ths.havToGo == ths.hide ) return; // same slide don't need to go
        ths.goingDirect = true;
        if( ths.havToGo < ths.show ) ths.isPrev = true;
        ths.show = ths.havToGo;
        ths.transitionInterval = setInterval(ths.clearTransition,ths.fadeTime);
        ths.fade();
        }
    //callback to go to index on click of paginator
    ths.directGo = function(){
        if( ths.transitionInterval ) return;
        for( i=0; i<ths.paging.length;i++)
            if( ths.paging[i] == this ) ths.havToGo = i;
        //ths.havToGo = $(this.tagName,$(this).parent()).index(this,$(this).parent());
        if( ths.havToGo == ths.hide ) return; // same slide don't need to go
        ths.goingDirect = true;
        if( ths.havToGo < ths.show ) ths.isPrev = true;
        ths.show = ths.havToGo;
        ths.transitionInterval = setInterval(ths.clearTransition,ths.fadeTime);
        ths.fade();
        }
    
    ths.init();
    
    this.stopAutoSliding = function(){
        clearInterval(ths.interval);
        ths.noAutoSlide = true;
        }
    this.startAutoSliding = function(){
        ths.noAutoSlide = false;
        clearInterval(ths.interval);
        $(ths.container).html($(ths.container).html());
        ths.init();
        }
    
    this.reInitialize = function(){
        clearInterval(ths.interval);
        $(ths.container).html($(ths.container).html());
        ths.init();
        }
    }
