/**********************************************************************************
' ©2010 Inventise Business Solutions - All rights reserved. 
' No part of this code, may be duplicated, used or transmitted in any form used or 
' transmitted in any form or by any means without the prior and explicit prior and 
' explicit written consent of Inventise.
'
' Note: Code based on work by James Edwards, see copyright notice below.
'**********************************************************************************
' Author : Karl Peck
' Date   : 12-01-2009
' Version: 01.00.000
**********************************************************************************/

/**********************************************************************************
' IXF1.11 :: Image cross-fade 
'--------------------------------------------------------------------------------
'Copyright (c) 2004 James Edwards (brothercake)          <cake@brothercake.com>
'BSD License                          See license.txt for licensing information
'Info/Docs       http://www.brothercake.com/site/resources/scripts/transitions/
'--------------------------------------------------------------------------------
**********************************************************************************/

// Define SmartBanner configuration object.
function SmartBannerConfig() {
    this.clock = null; // Clock counter object.
    this.count = 1; // Counter.
    this.resolution = 0; // Amount by which counter is decreased during each fade iteration.
    this.images = null; // Collection of images.
    this.index = 0; // Currently displayed image.
    this.imageCtrl = null; // Image object (i.e. <img> element).
    this.linkCtrl = null; // Link object (i.e. <a> element).
    this.rotations = 0; // Number of times the images have been cycled through so far.
    this.maxRotations = 0; // Number of times to cycle through the images before stopping (on the last image).
    this.display = 1; // Duration to display in between transitions in seconds.
    this.duration = 1; // Duration for transition in seconds.
    this.transition = 0; // Transition type.
    this.swipeStyle = 0; // Used by the cross-swipe only, determines the swipe direction.
    this.cache = null; // Image cache.
    this.type = ""; // Opacity type supported by the browser.
    this.newImage = null; // Transition image, (i.e. next image to be shown).
    this.fade = false; // Used by the swap-fade only to determine whether fading in or out.
    this.size = null; // Used by the cross-swipe only.
}

// Set up methods.
SmartBannerConfig.prototype.cacheImages = smartBannerConfig_CacheImages;

// Cache the images. (This forces the images to be pulled down from the server into the browser cache to speed up transitions).
function smartBannerConfig_CacheImages() {
    var count = this.images.length;
    this.cache = [];
    for (var i = 0; i < count; i++) {
        this.cache[i] = new Image;
        this.cache[i].src = this.images[i].imageUrl;
    }
}

// Gets position of image, coordinate is either 'x' or 'y'.
function smartBannerConfig_GetPosition(imageControl, coordinate) {
    var position = (coordinate == "x") ? imageControl.offsetLeft : imageControl.offsetTop;
    /*
    var parent = imageControl.offsetParent;
    while (parent != null) {
        position += (coordinate == "x") ? parent.offsetLeft : parent.offsetTop;
        parent = parent.offsetParent;
    }
    */
    return position;
}

// Get the supported form of opacity.
function smartBanner_GetOpacitySupport(config) {
    // Store the supported form of opacity.
    if (config.imageCtrl.style.opacity != undefined) {
        return "w3c";
    } else if (config.imageCtrl.style.MozOpacity != undefined) {
        return "moz";
    } else if (config.imageCtrl.style.KhtmlOpacity != undefined) {
        return "khtml";
    } else if (typeof config.imageCtrl.filters == "object") {
        // Weed out win/ie5.0 by testing the length of the filters collection (where filters is an object with no data)
        // then weed out mac/ie5 by testing first the existence of the alpha object (to prevent errors in win/ie5.0)
        // then the returned value type, which should be a number, but in mac/ie5 is an empty string
        return (config.imageCtrl.filters.length > 0 && typeof config.imageCtrl.filters.alpha == "object" && typeof config.imageCtrl.filters.alpha.opacity == "number") ? "ie" : "none";
    } else {
        return "none";
    }
}

// Cross-fade (merge) startup function.
function smartBanner_StartCrossFade(config) {
    config.clock = setInterval(function() { smartBanner_SetupCrossFade(config) }, config.display * 1000); // Start the timer.
}

// Cross-fade (merge) setup function.
function smartBanner_SetupCrossFade(config) {

    // Clear the timer.
    clearInterval(config.clock);
    config.clock = null;

    if (config.cache == null) config.cacheImages();

    config.index += 1;

    // Store the supported form of opacity.
    config.type = smartBanner_GetOpacitySupport(config);

    // Set the image alt text if defined.
    if (config.images[config.index].altText != undefined && config.images[config.index].altText != "") {
        config.imageCtrl.alt = config.images[config.index].altText
    }

    if (config.type != "none") { // Some kind of opacity is supported, start the cycle process.
        // Create a new image object and append it to body.
        // Detect support for namespaced element creation, in case we're in the XML DOM.
        config.newImage = config.imageCtrl.parentNode.appendChild((document.createElementNS != undefined) ? document.createElementNS("http://www.w3.org/1999/xhtml", "img") : document.createElement("img"));
        config.newImage.className = "smartbanner_duplicate"; // Set positioning classname.
        config.newImage.src = config.images[config.index].imageUrl; // Set src to new image src.

        // Move it to superimpose over original image.
        config.newImage.style.left = smartBannerConfig_GetPosition(config.imageCtrl, "x") + "px";
        config.newImage.style.top = smartBannerConfig_GetPosition(config.imageCtrl, "y") + "px";

        var duration = parseInt(config.duration, 10) * 1000; // Copy and convert fade duration argument to milliseconds.
        config.resolution = parseInt(config.duration, 10) * 20; // Create fade resolution argument as 20 steps per transition.
        config.clock = setInterval(function() { smartBanner_CrossFade(config) }, duration / config.resolution); // Start the timer.
    }
}

// Cross-fade (merge) timer function.
function smartBanner_CrossFade(config) {

    // Decrease the counter on a linear scale.
    config.count -= (1 / config.resolution);

    // If the counter has reached the bottom.
    if (config.count < (1 / config.resolution)) {
        // Clear the timer.
        clearInterval(config.clock);
        config.clock = null;

        config.count = 1; // Reset the counter.
        config.imageCtrl.src = config.images[config.index].imageUrl;  // Set the original image to the src of the new image.
    }

    // Set new opacity value on both elements using whatever method is supported.
    switch (config.type) {
        case "ie":
            config.imageCtrl.filters.alpha.opacity = config.count * 100;
            config.newImage.filters.alpha.opacity = (1 - config.count) * 100;
            break;
        case "khtml":
            config.imageCtrl.style.KhtmlOpacity = config.count;
            config.newImage.style.KhtmlOpacity = (1 - config.count);
            break;
        case "moz":
            // Restrict max opacity to prevent a visual popping effect in Firefox.
            config.imageCtrl.style.MozOpacity = (config.count == 1 ? 0.9999999 : config.count);
            config.newImage.style.MozOpacity = (1 - config.count);
            break;
        default:
            // Restrict max opacity to prevent a visual popping effect in Firefox.
            config.imageCtrl.style.opacity = (config.count == 1 ? 0.9999999 : config.count);
            config.newImage.style.opacity = (1 - config.count);
    }

    // Now that we've gone through one fade iteration we can show the image that's fading in.
    config.newImage.style.visibility = "visible";

    // Keep new image in position with original image.
    config.newImage.style.left = smartBannerConfig_GetPosition(config.imageCtrl, "x") + "px";
    config.newImage.style.top = smartBannerConfig_GetPosition(config.imageCtrl, "y") + "px";

    // If the counter is at the top, which is just after a complete cycle has completed.
    if (config.count == 1) {
        // Remove the duplicate image.
        config.newImage.parentNode.removeChild(config.newImage);
        // Set the anchor link so the user can click on it. Links might not be configured so have to allow for this.
        if (config.linkCtrl != undefined) config.linkCtrl.href = config.images[config.index].navigateUrl;                
        // Set up the next image transition.
        if (config.index == config.images.length - 1) {
            config.index = -1; // Reset to start, (it will get incremented to zero in smartBanner_SetupCrossFade().
            if (config.maxRotations > 0) config.rotations += 1;
        }
        // Start fade process on next image, (if maximum number of rotations hasn't been reached or isn't set).
        if (config.maxRotations == 0 || config.rotations < config.maxRotations) smartBanner_StartCrossFade(config); // Start the timer.           
    }
}

// Swap-fade (fade) startup function.
function smartBanner_StartSwapFade(config) {
    config.clock = setInterval(function() { smartBanner_SetupSwapFade(config) }, config.display * 1000); // Start the timer.
}

// Swap-fade (fade) setup function.
function smartBanner_SetupSwapFade(config) {

    // Clear the timer.
    clearInterval(config.clock);
    config.clock = null;

    if (config.cache == null) config.cacheImages();

    config.index += 1;

    // Store the supported form of opacity.
    config.type = smartBanner_GetOpacitySupport(config);

    // Set the image alt text if defined.
    if (config.images[config.index].altText != undefined && config.images[config.index].altText != "") {
        config.imageCtrl.alt = config.images[config.index].altText
    }

    if (config.type != "none") {  // Some kind of opacity is supported, start the cycle process.
        // Copy and convert fade duration argument the duration specifies the whole transition but the swapfade is two distinct transitions.
        config.length = parseInt(config.duration, 10) * 500;

        // Create fade resolution argument as 20 steps per transition again, split for the two distrinct transitions.
        config.resolution = parseInt(config.duration, 10) * 10;

        config.clock = setInterval(function() { smartBanner_SwapFade(config) }, config.length / config.resolution); // Start the timer.
    }
}

// Swap-fade (fade) timer function.
function smartBanner_SwapFade(config) {
    // Increase or reduce the counter on an exponential scale.
    config.count = (config.fade) ? config.count * 0.9 : (config.count * (1 / 0.9));

    // If the counter has reached the bottom.
    if (config.count < (1 / config.resolution)) {
        //Clear the timer.
        clearInterval(config.clock);
        config.clock = null;

        config.imageCtrl.src = config.images[config.index].imageUrl; // Do the image swap.
        config.fade = false; // Reverse the fade direction flag.
                
        config.clock = setInterval(function() { smartBanner_SwapFade(config) }, config.length / config.resolution); // Restart the timer.
    }

    // If the counter has reached the top.
    if (config.count > (1 - (1 / config.resolution))) {
        // Clear the timer.
        clearInterval(config.clock);
        config.clock = null
        
        config.fade = true; // Reset the fade direction flag.
        config.count = 1; // Reset the counter.

        // Set the anchor link so the user can click on it. Links might not be configured so have to allow for this.
        if (config.linkCtrl != undefined) config.linkCtrl.href = config.images[config.index].navigateUrl;         
        // Set up the next image transition.
        if (config.index == config.images.length - 1) {
            config.index = -1; // Reset to start, (it will get incremented to zero in smartBanner_SetupSwapFade().
            if (config.maxRotations > 0) config.rotations += 1;
        }
        // Start fade process on next image, (if maximum number of rotations hasn't been reached or isn't set).
        if (config.maxRotations == 0 || config.rotations < config.maxRotations) smartBanner_StartSwapFade(config); // Start the timer.        
    }

    // Set new opacity value on both elements using whatever method is supported.
    switch (config.type) {
        case "ie":
            config.imageCtrl.filters.alpha.opacity = config.count * 100;
            break;
        case "khtml":
            config.imageCtrl.style.KhtmlOpacity = config.count;
            break;
        case "moz":
            // Restrict max opacity to prevent a visual popping effect in Firefox.
            config.imageCtrl.style.MozOpacity = (config.count == 1 ? 0.9999999 : config.count);
            break;
        default:
            // Restrict max opacity to prevent a visual popping effect in Firefox
            config.imageCtrl.style.opacity = (config.count == 1 ? 0.9999999 : config.count);
    }
}

// Cross-swipe startup function.
function smartBanner_StartCrossSwipe(config) {
    config.clock = setInterval(function() { smartBanner_SetupCrossSwipe(config) }, config.display * 1000); // Start the timer.
}

// Cross-swipe setup function.
function smartBanner_SetupCrossSwipe(config) {
    // Clear the timer.
    clearInterval(config.clock);
    config.clock = null;

    if (config.cache == null) config.cacheImages();

    config.index += 1;

    // Get image dimensions.
    config.size = { "w": config.imageCtrl.width, "h": config.imageCtrl.height };

    // Set the image alt text if defined.
    if (config.images[config.index].altText != undefined && config.images[config.index].altText != "") {
        config.imageCtrl.alt = config.images[config.index].altText
    }

    // Check if dynamic element creation is supported.
    if (document.createElementNS != undefined || document.createElement != undefined) {
        // Create a new image object and append it to body.
        // Detect support for namespaced element creation, in case we're in the XML DOM.
        config.newImage = config.imageCtrl.parentNode.appendChild((document.createElementNS != undefined) ? document.createElementNS("http://www.w3.org/1999/xhtml", "img") : document.createElement("img"));
        config.newImage.className = "smartbanner_duplicate"; // Set positioning classname.
        config.newImage.src = config.images[config.index].imageUrl; // Set src to new image src.

        // Move it to superimpose over original image.
        config.newImage.style.left = smartBannerConfig_GetPosition(config.imageCtrl, "x") + "px";
        config.newImage.style.top = smartBannerConfig_GetPosition(config.imageCtrl, "y") + "px";

        config.newImage.style.clip = "rect(0, 0, 0, 0)"; // Set it to be completely hidden with clip.
        config.newImage.style.visibility = "visible"; // Show the image.

        var duration = parseInt(config.duration, 10) * 1000; // Copy and convert fade duration argument to milliseconds.
        config.resolution = parseInt(config.duration, 10) * 20; // Create fade resolution argument as 20 steps per transition.
        config.clock = setInterval(function() { smartBanner_CrossSwipe(config) }, duration / config.resolution); // Start the timer.
    }
}

// Cross-swipe timer function.
function smartBanner_CrossSwipe(config) {

    // Decrease the counter on a linear scale.
    config.count -= (1 / config.resolution);

    // If the counter has reached the bottom.
    if (config.count < (1 / config.resolution)) {
        // Clear the timer.
        clearInterval(config.clock);
        config.clock = null;

        config.count = 1; // Reset the counter.
        config.imageCtrl.src = config.images[config.index].imageUrl;  // Set the original image to the src of the new image.
    }

    // Animate the clip of the new image using the width and height properties saved earlier.
    config.newImage.style.clip = "rect("
		+ ((/bt|bltr|brtl/.test(config.swipeStyle)) ? (config.size.h * config.count) : (/che|cc/.test(config.swipeStyle)) ? ((config.size.h * config.count) / 2) : (0))
		+ "px, "
		+ ((/lr|tlbr|bltr/.test(config.swipeStyle)) ? (config.size.w - (config.size.w * config.count)) : (/cve|cc/.test(config.swipeStyle)) ? (config.size.w - ((config.size.w * config.count) / 2)) : (config.size.w))
		+ "px, "
		+ ((/tb|tlbr|trbl/.test(config.swipeStyle)) ? (config.size.h - (config.size.h * config.count)) : (/che|cc/.test(config.swipeStyle)) ? (config.size.h - ((config.size.h * config.count) / 2)) : (config.size.h))
		+ "px, "
		+ ((/lr|tlbr|bltr/.test(config.swipeStyle)) ? (0) : (/tb|bt|che/.test(config.swipeStyle)) ? (0) : (/cve|cc/.test(config.swipeStyle)) ? ((config.size.w * config.count) / 2) : (config.size.w * config.count))
		+ "px)";

    // Keep new image in position with original image.
    config.newImage.style.left = smartBannerConfig_GetPosition(config.imageCtrl, "x") + "px";
    config.newImage.style.top = smartBannerConfig_GetPosition(config.imageCtrl, "y") + "px";

    // If the counter is at the top, which is just after a complete cycle has completed.
    if (config.count == 1) {
        // Remove the duplicate image.
        config.newImage.parentNode.removeChild(config.newImage);
        // Set the anchor link so the user can click on it. Links might not be configured so have to allow for this.
        if (config.linkCtrl != undefined) config.linkCtrl.href = config.images[config.index].navigateUrl;        
        // Set up the next image transition.
        if (config.index == config.images.length - 1) {
            config.index = -1; // Reset to start, (it will get incremented to zero in smartBanner_SetupCrossSwipe().
            if (config.maxRotations > 0) config.rotations += 1;
        }
        // Start fade process on next image, (if maximum number of rotations hasn't been reached or isn't set).
        if (config.maxRotations == 0 || config.rotations < config.maxRotations) smartBanner_StartCrossSwipe(config); // Start the timer.
    }
}


