/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 */

/**
 * cycler.js
 *
 * Javascript functions for auto cycling images
 *
 * File Path: /DDJS/
 *
 * $Id: Cycler.js 223 2008-02-09 19:10:29Z topdog $
 *
 * LICENSE: copyright 2005 - 2007 Edward Vermillion - Doggydoo Codeworks. 
 * Unless otherwise stated ALL RIGHTS ARE RESERVED. Use or reuse without prior
 * written permission from the author or Doggydoo Codeworks is prohibited.
 * Visit http://www.doggydoo.net/license/DDJS-V1.X.txt for the full license.
 * Installation and use of this software implies agreement to the full
 * license.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 DOGGYDOO
 * CODEWORKS 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.
 *
 * @package     DDJS
 * @author      Edward Vermillion <evermillion@doggydoo.net>
 * @copyright   2005 - 2007 Edward Vermillion, Doggydoo Codeworks
 * @license     http://www.doggydoo.net/license/DDJS-1.x.txt
 * @version     1.0
 */
 
if (typeof DDJS == 'undefined') {
    throw('DDJS.Cycler: DDJS not initialized');
}
 
/**
 * Container for CyclerObject()s
 */
DDJS.Cycler = {
    
    /**
     * init method
     * 
     * Should be defined in the head of the page
     * 
     * @return void
     */
    init: function () {},
    
    /**
     * initCyclerObject method
     * 
     * Creates a new CyclerObject
     * 
     * @return void
     */
    initCyclerObject: function (cyclerID, mainImageID, altImageID, stopLinkID) {
        this[cyclerID] = new this.CyclerObject(cyclerID, mainImageID, altImageID, stopLinkID);
        return this[cyclerID];
    },
    
    /**
     * toString method
     * 
     * @return String
     */
    toString: function () {
        return '[Object] DDJS.Cycler';
    }
    
}; // End DDJS.Cycler

/**
 * Add Cycler to the init cache
 */
DDJS.addInit(DDJS.Cycler);

/**
 * CyclerObject
 * 
 * @param String cyclerID    - Identifier for this CyclerObject, must be unique
 *                             to the container
 * @param String mainImageID - Element id of the main image
 * @param Stinrg altImageID  - Element id of the alternate image
 * @param String stopLinkID  - Element id of the 'Stop Animation' link
 */
DDJS.Cycler.CyclerObject = function (cyclerID, mainImageID, altImageID, stopLinkID) {
    
    /**
     * @type String - Identifier for this cycler object
     */
    this.cyclerID = cyclerID;

    /**
     * @type Array - Collection of image objects to be cycled through
     */
    this.imageCollection = new Array();
    
    /**
     * @type Resource - setTimeout() id for the image cycling
     */
    this.cycleTimer = null;

    /**
     * @type Object - HTMLImageElement The main image element
     */
    this.mainImage = document.getElementById(mainImageID);
    
    /**
     * @type Object - HTMLImageElement The alternate image element
     */
    this.altImage = document.getElementById(altImageID);
    
    /**
     * @type Object - The main image fader object
     */
    this.mainImageFader = new DDJS.Effects.Fader(this.mainImage);
    
    /**
     * @type Object - The alternate image fader object
     */
    this.altImageFader = new DDJS.Effects.Fader(this.altImage);

    /**
     * @type Integer - The number id of the currently displayed image. This
     *                 comes from, and corresponds to, the position id in the
     *                 CMS.
     */
    this.currImage = 1;

    /**
     * @type Bool - Whether the cycler has been stopped
     */
    this.cycleStopped = false;
    
    /**
     * @type Bool - Whether this is the first itteration of the cycler
     */
    this.startCycle = true;
    
    this.delay = 10000;
    
    this.fadeTime = 2;
    
    this.fadeFPS = 12;
    
    /**
     * @type Object - The container for the 'Stop Animation' link/button
     */
    this.stopCycleLink = document.getElementById(stopLinkID);

    /**
     * addImage method
     * 
     * Adds an image to the image collection
     * 
     * @return void
     */
    this.addImage = function (id, src, width, height) {
    	
        this.imageCollection[id] = new Image();
        
        this.imageCollection[id].src = src;
        this.imageCollection[id].width = width;
        this.imageCollection[id].height = height;
    };

    /**
     * cycleImage method
     * 
     * Cycles images in the image collection
     * 
     * @return void
     */
    this.cycleImage = function () {
        
        var lastImage = this.imageCollection.length - 1;
        
        if (this.startCycle) {
        	
            this.startCycle = false;
            this.cycleTimer = setTimeout("DDJS.Cycler['" + this.cyclerID +"'].cycleImage()", this.delay/2);
            this.currImage++;
            
        } else {
            
            this.updateImage(this.currImage);
            
            if (this.currImage < lastImage) {
            	
                this.currImage++;
                
            } else {
                
                this.currImage = 1;
            }
            
            this.cycleTimer = setTimeout("DDJS.Cycler['" + this.cyclerID + "'].cycleImage()", this.delay);
        }
    };

    /**
     * toggleCycle method
     * 
     * Toggles the cycler on and off
     * 
     * @return void
     */
    this.toggleCycle = function () {
    	
    	var stopCycleLabel = 'Start Animation';
        
        if (!this.cycleStopped) {
        	
            clearTimeout(this.cycleTimer);
            
            this.cycleTimer = null;
            this.cycleStopped = true;
            
        } else {
            
            this.cycleImage();
            this.cycleStopped = false;
            
            stopCycleLabel = 'Stop Animation';
        }
        
        if (this.stopCycleLink != null) {
           	this.stopCycleLink.innerHTML = stopCycleLabel;
        }
        
        return false;
    };

    /**
     * swapImage method
     * 
     * Allows for a 'jump' in the order of cycling images
     * 
     * @param Integer id - The id number of the image to 'jump' to
     * @return void
     */
    this.swapImage = function (id) {
        
        if (this.cycleTimer != null) {
        	
            clearTimeout(this.cycleTimer);
            this.cycleTimer = null;
        }

        this.currImage = id;

        if (this.cycleStopped) {
            
            this.updateImage(id);
            
        } else {
            
            this.cycleImage();
        }
    };
    
    /**
     * updateImage method
     * 
     * Performs a single image cycle
     * 
     * Used to change images when the cycler has been stopped.
     * 
     * @param Integer id - The id number of the image to show
     * @private
     * @return void
     */
    this.updateImage = function (id) {
        
        if (this.imageCollection[id] != undefined) {
            
            var src = this.imageCollection[id].src;
            var width = this.imageCollection[id].width;
            var height = this.imageCollection[id].height;

            if (this.mainImage.style.visibility == 'visible' || this.mainImage.style.visibility == '') {
            	
                this.altImage.src = src;
                this.altImage.width = width;
                this.altImage.height = height;

            } else {
            	
                this.mainImage.src = src;
                this.mainImage.width = width;
                this.mainImage.height = height;
            }
            
            this.mainImageFader.fade();
            this.altImageFader.fade();
        }
    };
    
    /**
     * setDelay method
     * 
     * Sets the delay inteval for cycling the images
     * 
     * @param Integer time - The time, in seconds, to wait between cycles.
     * @return void
     * @private
     */
    this.setDelay = function (time) {
    	
    	this.delay = parseInt(time * 1000);
    };
    
    this.setSpeed = function (interval, fadeTime, fadeFPS) {
    	
    	this.mainImageFader.setSpeed(fadeTime, fadeFPS);
    	this.altImageFader.setSpeed(fadeTime, fadeFPS);
    	
    	this.setDelay(parseInt(interval+fadeTime));
    }
    
    /**
     * toString method
     * 
     * @return String
     */
    this.toString = function () {
        return '[Object] DDJS.Cycler.CyclerObject';
    };

}; // End DDJS.Cycler.CyclerObject


