﻿// Dynamis PLC - Chris Leow 2008.

// Instantiate with variable name, holder (i.e. kalaedescope viewer) div ID, card (as in backing card) div ID
// and item width in pixels.
function Carousel(varName, viewDivId, cardDivId, itemWidth, numberOfItems) {
    this.varName = varName;
    this.viewDiv = document.getElementById(viewDivId);
    this.cardStyle = document.getElementById(cardDivId).style;
    this.itemWidth = itemWidth;
    this.numberOfItems = numberOfItems;
    this.acceptCommand = true;
    this.state = 'sliding'; // can be 'sliding', 'moving' or 'hover'
    this.slideDelay = null; // this is a timeout that can be cleared.
};

Carousel.prototype = {
    currentPos : function() {
        return Math.round((-parseFloat(this.cardStyle.left)) / this.itemWidth);
    },

    timeoutFunction : function(step, steps, start, disp, term) {
    
        // Quadratic shift profile, this is the integral.
        function x(t) {
            return Math.round((27/4)*(disp / (steps*steps*steps)) * ((steps/2)*(t*t) - (t*t*t/3))) + start;
        };
        
        this.state = 'moving'
               
        var self = this;
        if (step <= (3/4)*steps) {
            self.cardStyle.left = x(step)+'px';
            setTimeout(self.varName+'.timeoutFunction('+(step+1)+', ' +steps+', '+start+', '+disp+', '+term+')', 20);
        } else {
        
            // termination position may be different to the real termination position (start+disp), but should work the same!
            self.cardStyle.left = term+'px';
            self.acceptCommand = true;
            self.state = 'hover'
        }
    },
    
    moveTo : function(newPos) {      
        var oldPos = this.currentPos();
        var steps = 20;
               
        // This is the terminal position, and may include a "hidden jump" to make the carousel appear to be a real carousel.
        var termPos = newPos
        termPos = (newPos>=this.numberOfItems)?0:termPos;
        termPos = (newPos<0)?this.numberOfItems-1:termPos;

        this.timeoutFunction(0, steps, -this.itemWidth*oldPos, (oldPos-newPos)*this.itemWidth, -termPos*this.itemWidth);
    },
    
    moveUp : function() {
        if (this.acceptCommand == true && this.currentPos() < this.numberOfItems) {
            this.acceptCommand = false;
            this.moveTo(this.currentPos() + 1);
        }
    },
    
    moveDown : function() {
        if (this.acceptCommand == true && this.currentPos() >= 0) {
            this.acceptCommand = false;
            this.moveTo(this.currentPos() - 1);
        }
    },
       
    slideTimeoutCycle : function() {
        if (this.state == 'sliding') {
            var x = parseInt(this.cardStyle.left) - 1;
            if (x < (-this.itemWidth*this.numberOfItems))
                x = 0;
                
            this.cardStyle.left = x+'px';
            setTimeout(this.varName+'.slideTimeoutCycle()', 20);
        }
    },
    
    startSlide : function() {
        if (this.state == 'hover' || this.state == 'sliding') {
            this.state = 'sliding';
            this.slideTimeoutCycle();
        } else {
            this.startSlideDelay();
        }
    },
    
    startSlideDelay : function() {
        if (this.slideDelay != null) {
            clearTimeout(this.slideDelay);
        }
        this.slideDelay = setTimeout(this.varName+'.startSlide();', 5*1000);
    },
    
    stopSlide : function(moveToPos) {
        clearTimeout(this.slideDelay);
        if (this.state == 'sliding') {
            if (moveToPos != null) {
                this.cardStyle.left = -this.itemWidth*moveToPos+'px';
            } else {
                this.moveTo(this.currentPos());
            }
            this.state = 'hover';
        }
    }
};