/*
Slideshow script
js class for running slideshows

Karl Glasgow
code@keg4.com

June 2010
*/

function Slideshow() 
{
    /*@cc_on
        /*@if (true) 
            this.usingIE = true;
        @else @*/
            this.usingIE = false;
        /*@end
    @*/

    this.slides = new Array();
    this.currentSlideIndex = 0;
    this.minimumIntervalLength = 100; // (milliseconds, 100 recommended)
    this.fadeOn = true;
    this.crossFadeOn = true;
    this.slideDelay = 3; // (in seconds)
    this.transitionDelay = 1; // (in seconds)
    this.playAction = null;
    this.fadeAction = null;
    this.iterations = 0;
    this.repeat = 0;
    
    this.loadSlidesById = function(arySlideIds) 
    {
        if (!arySlideIds || !arySlideIds.length) 
        {
            return false;
        }
        
        intSlidesAdded = 0;
        for (i = 0; i < arySlideIds.length; i++) 
        {
            var objSlide = document.getElementById(arySlideIds[i]);
            if (objSlide != null) 
            {
                this.slides[this.slides.length] = objSlide;
                if (this.slides.length == 1) 
                {
                    this.setOpacity(objSlide, 100);
                    objSlide.style.zIndex = 1;
                }
                else 
                {
                    this.setOpacity(objSlide, 0);
                    objSlide.style.zIndex = 0;
                }
                intSlidesAdded++;
            }
        }
        
        return (intSlidesAdded > 0 && intSlidesAdded == arySlideIds.length);
    }
    
    this.addSlide = function(objElement) 
    {
        if (!objElement) 
        {
            return false;
        }
        this.slides[this.slides.length] = objElement;
    }
    
    this.play = function() 
    {
        if (this.playAction != null) 
        {
            // Already playing
            return false;
        }
        if (this.slides.length < 2) 
        {
            // Slideshow must contain two slides to warrant playing
            return false;
        }
        
        var self = this;
        this.playAction = setTimeout(
                function() 
                {
                    self.nextSlide(); 
                }, 
                (self.slideDelay * 1000)
            );
    }

    this.stop = function() 
    {
        if (this.playAction != null) 
        {
            clearInterval(this.playAction);
            this.playAction = null;
        }
        if (this.fadeAction != null) 
        {
            clearInterval(this.fadeAction);
            this.fadeAction = null;
        }
    }
    
    this.isPlaying = function() 
    {
        return (this.playAction != null);
    }
    
    this.loadControls = function(objElement) 
    {
        if (typeof objElement.innerHTML != 'undefined') 
        {
            var strControls = '';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.firstSlide(true);">&lt;&lt;</a> &nbsp;';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.previousSlide(true);">&lt;</a> &nbsp;';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.stop();" class="stop">stop</a> &nbsp;';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.play();" class="play">play</a> &nbsp;';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.nextSlide(true);">&gt;</a> &nbsp;';
            strControls += '<a href="#" onclick="if (objSlideshow) objSlideshow.lastSlide(true);">&gt;&gt;</a><br />';
            objElement.innerHTML = strControls;
        }
    }
    this.loadControlsById = function(strElementId) 
    {
        objElement = document.getElementById(strElementId);
        if (objElement != null) 
        {
            this.loadControls(objElement);
        }
    }

    this.nextSlide = function(bStop) 
    {
        if (typeof bStop != 'undefined' && bStop === true) 
        {
            this.stop();
        }
        
        var intNewSlide = (this.currentSlideIndex + 1);
        if (intNewSlide >= this.slides.length) 
        {
            intNewSlide = 0;
            this.iterations++;
            if (this.playAction != null && this.repeat > 0 && this.iterations >= this.repeat) 
            {
                /*
                If the slideshow is playing and it's been set to repeat a 
                certain number of times only, and that threshold has been met,
                then stop the slideshow.
                
                Also: remove the repeat setting now, to allow the user to 
                replay the slideshow manually--without imposing a limit.
                */
                this.repeat = 0;
                return this.stop();
            }
        }
        this.gotoSlide(intNewSlide);
    }
    
    this.previousSlide = function(bStop) 
    {
        if (typeof bStop != 'undefined' && bStop === true) 
        {
            this.stop();
        }

        var intNewSlide = (this.currentSlideIndex - 1);
        if (intNewSlide < 0) 
        {
            intNewSlide = (this.slides.length - 1);
        }
        this.gotoSlide(intNewSlide);
    }
    
    this.firstSlide = function(bStop) 
    {
        if (typeof bStop != 'undefined' && bStop === true) 
        {
            this.stop();
        }

        this.gotoSlide(0);
    }
    
    this.lastSlide = function(bStop) 
    {
        if (typeof bStop != 'undefined' && bStop === true) 
        {
            this.stop();
        }

        this.gotoSlide(this.slides.length - 1);
    }
    
    this.gotoSlide = function(intSlideIndex, bNoTransition) 
    {
        if (typeof bNoTransition == 'undefined') 
        {
            bNoTransition = (this.playAction == null);
        }

        if (intSlideIndex == this.currentSlideIndex) 
        {
            // Already on this slide, no action required
            return false;
        }
        
        if (intSlideIndex >= 0 && intSlideIndex < this.slides.length) 
        {
            if (this.currentSlideIndex >= 0) 
            {
                this.slides[this.currentSlideIndex].style.zIndex = 0;
                this.slides[intSlideIndex].style.zIndex = 1;
                
                if (this.fadeOn === true && bNoTransition !== true) 
                {
                    this.fade(this.slides[this.currentSlideIndex], this.slides[intSlideIndex], this.transitionDelay);
                } 
                else 
                {
                    this.setOpacity(this.slides[this.currentSlideIndex], 0);
                    this.setOpacity(this.slides[intSlideIndex], 100);
                    
                    if (bNoTransition !== true) 
                    {
                        var self = this;
                        this.playAction = setTimeout(
                                function() 
                                {
                                    self.nextSlide();
                                }, 
                                (self.slideDelay * 1000)
                            );
                    }
                    
                }
            }
            this.currentSlideIndex = intSlideIndex;
        }
    }

    this.fade = function(objOldElement, objNewElement, fltFadeDuration) 
    {
        if (!objNewElement || !objOldElement) 
        {
            return false
        }
        
        if (this.crossFadeOn !== true) 
        {
            this.setOpacity(objOldElement, 0);
        }
        
        var intOpacityStep = (100 / ((fltFadeDuration * 1000) / this.minimumIntervalLength)); // (total opacity change / ((fade duration * 1000ms) / min. interval length))
        var self = this;
        if (this.fadeAction != null) 
        {
            // To prevent transition overlap, kill any current transition action
            clearInterval(this.fadeAction);
            this.fadeAction = null;
        }        
        this.fadeAction = setInterval(
                function() 
                {
                    var intFadeOutOpacity = 0;
                    if (self.crossFadeOn === true) 
                    {
                        intFadeOutOpacity = (self.getOpacity(objOldElement) - intOpacityStep);
                        if (intFadeOutOpacity < 0) 
                        {
                            intFadeOutOpacity = 0;
                        }
                        self.setOpacity(objOldElement, intFadeOutOpacity);
                    } 

                    var intFadeInOpacity = (self.getOpacity(objNewElement) + intOpacityStep);
                    if (intFadeInOpacity > 100) 
                    {
                        intFadeInOpacity = 100;
                    }
                    self.setOpacity(objNewElement, intFadeInOpacity);
                    
                    if (intFadeInOpacity == 100 && intFadeOutOpacity == 0) 
                    {
                        clearInterval(self.fadeAction);
                        self.FadeAction = null;
                        self.playAction = setTimeout(
                                function() 
                                {
                                    self.nextSlide();
                                }, 
                                (self.slideDelay * 1000)
                            );
                    }
                    return;
                }, 
                this.minimumIntervalLength
            );        
    }
    
    this.getOpacity = function(objElement) 
    {
        if (this.usingIE == true && ('filter' in objElement.style)) 
        {
            var reOpacityFilter = /opacity=([0-9\.]+)/i;
            intCurrentOpacity = parseInt(reOpacityFilter.exec(objElement.style.filter)? reOpacityFilter.exec(objElement.style.filter)[1] : 100);
            intCurrentOpacity = (intCurrentOpacity < 0? 0 : (intCurrentOpacity > 100? 100 : intCurrentOpacity));
            return Math.floor(intCurrentOpacity);
        } 
        else if ('opacity' in objElement.style) 
        {
            intCurrentOpacity = (objElement.style.opacity != ''? objElement.style.opacity : 1);
            intCurrentOpacity = (intCurrentOpacity < 0? 0 : (intCurrentOpacity > 1? 1 : intCurrentOpacity));
            return Math.floor(intCurrentOpacity * 100);
        }
        return false;
    }
    
    this.setOpacity = function(objElement, intOpacityPercentage) 
    {
        intOpacityPercentage = Math.ceil(intOpacityPercentage < 0? 0 : (intOpacityPercentage > 100? 100 : intOpacityPercentage));
        if (this.usingIE == true && ('filter' in objElement.style)) 
        {
            objElement.style.filter = ('alpha(opacity=' + intOpacityPercentage + ')');
            return true;
        } 
        else if ('opacity' in objElement.style) 
        {
            objElement.style.opacity = ('' + (intOpacityPercentage / 100));
            return true;
        }
        return false;
    }
}
