/*!
* Feature Carousel, Version 1.2.1
* http://www.bkosolutions.com
*
* Copyright 2011 Brian Osborne
* Licensed under GPL version 3
* brian@bkosborne.com
*
* http://www.gnu.org/licenses/gpl.txt
*/
(function ($) {
    $.fn.featureCarousel = function (options) {
        options = $.extend({}, $.fn.featureCarousel.defaults, options || {}); return $(this).each(function () {
            var pluginData = { currentCenterNum: options.startingFeature, containerWidth: 0, containerHeight: 0, largeFeatureWidth: 0, largeFeatureHeight: 0, smallFeatureWidth: 0, smallFeatureHeight: 0, totalFeatureCount: $(this).children("div").length, currentlyMoving: false, featuresContainer: $(this), featuresArray: [], containerIDTag: "#" + $(this).attr("id"), timeoutVar: null, rotationsRemaining: 0, itemsToAnimate: 0, borderWidth: 0 }; preload(function () { setupFeatureDimensions(); setupCarousel(); setupFeaturePositions(); setupTrackers(); initiateMove(true, 1); }); function preload(callback) { if (options.preload == true) { var $imageElements = pluginData.featuresContainer.find("img"); var loadedImages = 0; var totalImages = $imageElements.length; $imageElements.each(function () { $(this).load(function () { loadedImages++; if (loadedImages == totalImages) { callback(); } }); if (this.complete || $.browser.msie) { $(this).trigger('load'); } }); } else { callback(); } }
            function getContainer(featureNum) { return pluginData.featuresArray[featureNum - 1]; }
            function getBySetPos(position) {
                $.each(pluginData.featuresArray, function () {
                    if ($(this).data().setPosition == position)
                        return $(this);
                });
            }
            function getPreviousNum(num) { if ((num - 1) == 0) { return pluginData.totalFeatureCount; } else { return num - 1; } }
            function getNextNum(num) { if ((num + 1) > pluginData.totalFeatureCount) { return 1; } else { return num + 1; } }
            function setupFeatureDimensions() {
                pluginData.containerWidth = pluginData.featuresContainer.width(); pluginData.containerHeight = pluginData.featuresContainer.height(); var $firstFeatureImage = $(pluginData.containerIDTag).find(".carousel-image:first"); if (options.largeFeatureWidth > 1)
                    pluginData.largeFeatureWidth = options.largeFeatureWidth; else if (options.largeFeatureWidth > 0 && options.largeFeatureWidth < 1)
                    pluginData.largeFeatureWidth = $firstFeatureImage.width() * options.largeFeatureWidth; else
                    pluginData.largeFeatureWidth = $firstFeatureImage.outerWidth(); if (options.largeFeatureHeight > 1)
                    pluginData.largeFeatureHeight = options.largeFeatureHeight; else if (options.largeFeatureHeight > 0 && options.largeFeatureHeight < 1)
                    pluginData.largeFeatureHeight = $firstFeatureImage.height() * options.largeFeatureHeight; else
                    pluginData.largeFeatureHeight = $firstFeatureImage.outerHeight(); if (options.smallFeatureWidth > 1)
                    pluginData.smallFeatureWidth = options.smallFeatureWidth; else if (options.smallFeatureWidth > 0 && options.smallFeatureWidth < 1)
                    pluginData.smallFeatureWidth = $firstFeatureImage.width() * options.smallFeatureWidth; else
                    pluginData.smallFeatureWidth = $firstFeatureImage.outerWidth() / 2; if (options.smallFeatureHeight > 1)
                    pluginData.smallFeatureHeight = options.smallFeatureHeight; else if (options.smallFeatureHeight > 0 && options.smallFeatureHeight < 1)
                    pluginData.smallFeatureHeight = $firstFeatureImage.height() * options.smallFeatureHeight; else
                    pluginData.smallFeatureHeight = $firstFeatureImage.outerHeight() / 2;
            }
            function setupCarousel() {
                if (options.displayCutoff > 0 && options.displayCutoff < pluginData.totalFeatureCount) { pluginData.totalFeatureCount = options.displayCutoff; }
                pluginData.featuresContainer.find(".carousel-feature").each(function (index) { if (index < pluginData.totalFeatureCount) { pluginData.featuresArray[index] = $(this); } }); if (pluginData.featuresContainer.find(".carousel-feature").first().css("borderLeftWidth") != "medium") { pluginData.borderWidth = parseInt(pluginData.featuresContainer.find(".carousel-feature").first().css("borderLeftWidth")) * 2; }
                pluginData.featuresContainer.find(".carousel-feature").each(function () { $(this).css({ 'left': (pluginData.containerWidth / 2) - (pluginData.smallFeatureWidth / 2) - (pluginData.borderWidth / 2), 'width': pluginData.smallFeatureWidth, 'height': pluginData.smallFeatureHeight, 'top': options.smallFeatureOffset + options.topPadding, 'opacity': 0 }); }).find(".carousel-image").css({ 'width': pluginData.smallFeatureWidth }); if (options.captionBelow) { pluginData.featuresContainer.find('.carousel-caption').css('position', 'relative'); }
                if (pluginData.totalFeatureCount < 4) { pluginData.itemsToAnimate = pluginData.totalFeatureCount; } else { pluginData.itemsToAnimate = 4; }
                pluginData.featuresContainer.find(".carousel-caption").hide();
            }
            function setupFeaturePositions() { $.each(pluginData.featuresArray, function (i) { $(this).data('setPosition', i + 1); }); var oneBeforeStarting = getPreviousNum(options.startingFeature); pluginData.currentCenterNum = oneBeforeStarting; var $centerFeature = getContainer(oneBeforeStarting); $centerFeature.data('position', 1); var $prevFeatures = $centerFeature.prevAll(); $prevFeatures.each(function (i) { $(this).data('position', (pluginData.totalFeatureCount - i)); }); var $nextFeatures = $centerFeature.nextAll(); $nextFeatures.each(function (i) { if ($(this).data('setPosition') != undefined) { $(this).data('position', (i + 2)); } }); if (options.counterStyle == 'caption') { $.each(pluginData.featuresArray, function () { var pos = getPreviousNum($(this).data('position')); var $numberTag = $("<span></span>"); $numberTag.addClass("numberTag"); $numberTag.html("(" + pos + " of " + pluginData.totalFeatureCount + ") "); $(this).find('.carousel-caption p').prepend($numberTag); }); } }
            function setupTrackers() {
                if (options.trackerIndividual) {
                    var $list = $("<ul></ul>"); $list.addClass("tracker-individual-container"); for (var i = 0; i < pluginData.totalFeatureCount; i++) { var counter = i + 1; var $trackerBlip = $("<div>" + counter + "</div>"); $trackerBlip.addClass("tracker-individual-blip"); $trackerBlip.css("cursor", "pointer"); $trackerBlip.attr("id", "tracker-" + (i + 1)); var $listEntry = $("<li></li>"); $listEntry.append($trackerBlip); $listEntry.css("float", "left"); $listEntry.css("list-style-type", "none"); $list.append($listEntry); }
                    $(pluginData.containerIDTag).append($list); $list.hide().show();
                }
                if (options.trackerSummation) { var $tracker = $('<div></div>'); $tracker.addClass('tracker-summation-container'); var $current = $('<span></span>').addClass('tracker-summation-current').text(options.startingFeature); var $total = $('<span></span>').addClass('tracker-summation-total').text(pluginData.totalFeatureCount); var $middle = $('<span></span>').addClass('tracker-summation-middle').text(' / '); $tracker.append($current).append($middle).append($total); $(pluginData.containerIDTag).append($tracker); } 
            }
            function updateTracker(oldCenter, newCenter) {
                if (options.trackerIndividual) { var $trackerContainer = pluginData.featuresContainer.find(".tracker-individual-container"); var $oldCenter = $trackerContainer.find("#tracker-" + oldCenter); var $newCenter = $trackerContainer.find("#tracker-" + newCenter); $oldCenter.removeClass("tracker-individual-blip-selected"); $newCenter.addClass("tracker-individual-blip-selected"); }
                if (options.trackerSummation) { var $trackerContainer = pluginData.featuresContainer.find('.tracker-summation-container'); $trackerContainer.find('.tracker-summation-current').text(newCenter); } 
            }
            function setTimer(stop) { clearTimeout(pluginData.timeoutVar); if (!stop && options.autoPlay != 0) { var autoTime = (Math.abs(options.autoPlay) < options.carouselSpeed) ? options.carouselSpeed : Math.abs(options.autoPlay); pluginData.timeoutVar = setTimeout(function () { (options.autoPlay > 0) ? initiateMove(true, 1) : initiateMove(false, 1); }, autoTime); } }
            function rotatePositions(direction) {
                $.each(pluginData.featuresArray, function () {
                    var newPos; if (direction == false) { newPos = getNextNum($(this).data().position); } else { newPos = getPreviousNum($(this).data().position); }
                    $(this).data('position', newPos);
                });
            }
            function animateFeature($feature, direction) {
                var new_width, new_height, new_top, new_left, new_zindex, new_padding, new_fade; var oldPosition = $feature.data('position'); var newPosition; if (direction == true)
                    newPosition = getPreviousNum(oldPosition); else
                    newPosition = getNextNum(oldPosition); if (oldPosition == 1) { options.leavingCenter($feature); }
                if (newPosition == 1) { new_width = pluginData.largeFeatureWidth; new_height = pluginData.largeFeatureHeight; new_top = options.topPadding; new_zindex = $feature.css("z-index"); new_left = (pluginData.containerWidth / 2) - (pluginData.largeFeatureWidth / 2) - (pluginData.borderWidth / 2); new_fade = 1.0; } else { new_width = pluginData.smallFeatureWidth; new_height = pluginData.smallFeatureHeight; new_top = options.smallFeatureOffset + options.topPadding; new_zindex = 1; new_fade = 0.4; if (newPosition == pluginData.totalFeatureCount) { new_left = options.sidePadding; } else if (newPosition == 2) { new_left = pluginData.containerWidth - pluginData.smallFeatureWidth - options.sidePadding - pluginData.borderWidth; } else { new_left = (pluginData.containerWidth / 2) - (pluginData.smallFeatureWidth / 2) - (pluginData.borderWidth / 2); new_fade = 0; } }
                if (oldPosition == 1) { $feature.find(".carousel-caption").hide(); }
                $feature.animate({ width: new_width, height: new_height, top: new_top, left: new_left, opacity: new_fade }, options.carouselSpeed, options.animationEasing, function () {
                    if (newPosition == 1) {
                        if (options.captionBelow)
                            $feature.css('height', 'auto'); $feature.find(".carousel-caption").fadeTo("fast", 0.85); options.movedToCenter($feature);
                    }
                    pluginData.rotationsRemaining = pluginData.rotationsRemaining - 1; $feature.css("z-index", new_zindex); if (options.trackerIndividual || options.trackerSummation) {
                        if (newPosition == 1) {
                            var newCenterItemNum = pluginData.featuresContainer.find(".carousel-feature").index($feature) + 1; var oldCenterItemNum; if (direction == false)
                                oldCenterItemNum = getNextNum(newCenterItemNum); else
                                oldCenterItemNum = getPreviousNum(newCenterItemNum); updateTracker(oldCenterItemNum, newCenterItemNum);
                        } 
                    }
                    var divide = pluginData.rotationsRemaining / pluginData.itemsToAnimate; if (divide % 1 == 0) {
                        pluginData.currentlyMoving = false; rotatePositions(direction); if (pluginData.rotationsRemaining > 0)
                            move(direction);
                    }
                    setTimer(false);
                }).find('.carousel-image').animate({ width: new_width, height: new_height }, options.carouselSpeed, options.animationEasing).end();
            }
            function move(direction) {
                pluginData.currentlyMoving = true; var $newCenter, $newLeft, $newRight, $newHidden; if (direction == true) { $newCenter = getContainer(getNextNum(pluginData.currentCenterNum)); $newLeft = getContainer(pluginData.currentCenterNum); $newRight = getContainer(getNextNum(getNextNum(pluginData.currentCenterNum))); $newHidden = getContainer(getPreviousNum(pluginData.currentCenterNum)); pluginData.currentCenterNum = getNextNum(pluginData.currentCenterNum); } else { $newCenter = getContainer(getPreviousNum(pluginData.currentCenterNum)); $newLeft = getContainer(getPreviousNum(getPreviousNum(pluginData.currentCenterNum))); $newRight = getContainer(pluginData.currentCenterNum); $newHidden = getContainer(getNextNum(pluginData.currentCenterNum)); pluginData.currentCenterNum = getPreviousNum(pluginData.currentCenterNum); }
                if (direction) { $newLeft.css("z-index", 3); } else { $newRight.css("z-index", 3); }
                $newCenter.css("z-index", 4); animateFeature($newLeft, direction); animateFeature($newCenter, direction); animateFeature($newRight, direction); if (pluginData.totalFeatureCount > 3) { animateFeature($newHidden, direction); } 
            }
            function initiateMove(direction, rotations) { if (pluginData.currentlyMoving == false) { var queue = rotations * pluginData.itemsToAnimate; pluginData.rotationsRemaining = queue; move(direction); } }
            function findShortestDistance(from, to) {
                var goingToLeft = 1, goingToRight = 1, tracker; tracker = from; while ((tracker = getPreviousNum(tracker)) != to) { goingToLeft++; }
                tracker = from; while ((tracker = getNextNum(tracker)) != to) { goingToRight++; }
                return (goingToLeft < goingToRight) ? goingToLeft * -1 : goingToRight;
            }
            $(options.leftButtonTag).live('click', function () { initiateMove(false, 1); }); $(options.rightButtonTag).live('click', function () { initiateMove(true, 1); }); pluginData.featuresContainer.find(".carousel-feature").click(function () { var position = $(this).data('position'); if (position == 2) { initiateMove(true, 1); } else if (position == pluginData.totalFeatureCount) { initiateMove(false, 1); } }).mouseover(function () {
                if (pluginData.currentlyMoving == false) { var position = $(this).data('position'); if (position == 2 || position == pluginData.totalFeatureCount) { $(this).css("opacity", 0.8); } }
                if (options.pauseOnHover) setTimer(true); if (options.stopOnHover) options.autoPlay = 0;
            }).mouseout(function () {
                if (pluginData.currentlyMoving == false) { var position = $(this).data('position'); if (position == 2 || position == pluginData.totalFeatureCount) { $(this).css("opacity", 0.4); } }
                if (options.pauseOnHover) { setTimer(false); } 
            }); $("a", pluginData.containerIDTag).live("click", function (event) {
                var $parents = $(this).parentsUntil(pluginData.containerIDTag); $parents.each(function () {
                    var position = $(this).data('position'); if (position != undefined) {
                        if (position != 1) {
                            if (position == pluginData.totalFeatureCount) { initiateMove(false, 1); } else if (position == 2) { initiateMove(true, 1); }
                            event.preventDefault(); return false;
                        } else { options.clickedCenter($(this)); } 
                    } 
                });
            }); $(".tracker-individual-blip").live("click", function () { var goTo = $(this).attr("id").substring(8); var whereIsIt = pluginData.featuresContainer.find(".carousel-feature").eq(goTo - 1).data('position'); var currentlyAt = pluginData.currentCenterNum; if (goTo != currentlyAt) { var shortest = findShortestDistance(1, whereIsIt); if (shortest < 0) { initiateMove(false, (shortest * -1)); } else { initiateMove(true, shortest); } } });
        });
    }; $.fn.featureCarousel.defaults = { largeFeatureWidth: 0, largeFeatureHeight: 0, smallFeatureWidth: .5, smallFeatureHeight: .5, topPadding: 20, sidePadding: 50, smallFeatureOffset: 50, startingFeature: 1, carouselSpeed: 1000, autoPlay: 4000, pauseOnHover: true, stopOnHover: false, trackerIndividual: true, trackerSummation: true, preload: true, displayCutoff: 0, animationEasing: 'swing', leftButtonTag: '#carousel-left', rightButtonTag: '#carousel-right', captionBelow: false, movedToCenter: $.noop, leavingCenter: $.noop, clickedCenter: $.noop };
})(jQuery);
