﻿// Carousel Plugin //

(function ($) {
    var settings = {
        fadeDuration: 300,
        slideDelay: 10000,
        pagers: true,
        pause: true,
        prevNextButtons: '.prevNext',
        nextClass: 'next',
        carouselClass: 'carousel',
        sliderEl: 'li',
        activeClass: 'active'
    };

    $.fn.carousel = function (defaults) {
        var defaults = $.extend({}, settings, defaults),
            data = {
                activeTransition: false,
                timeout: ''
            }
        root = $(this),
            carousel = root.find('.' + defaults.carouselClass),
            sliders = carousel.find(defaults.sliderEl);

        init();

        // Fades out the current slide and fades in the new one
        function fadeSliders(slideObj) {
            data.activeTransition = true;
            slideObj.active.fadeOut(defaults.fadeDuration, function () {
                slideObj.active.removeClass(defaults.activeClass);
            });
            slideObj.next.fadeIn(defaults.fadeDuration, function () {
                slideObj.next.addClass(defaults.activeClass);
                data.activeTransition = false;
            });

            changePagers(sliders.index(slideObj.next));
        }

        // Returns an object containing the current active slider and the
        // slider we'll transition to.
        function setSliders(type) {
            var obj = {};
            obj.active = carousel.find('.' + defaults.activeClass);

            if (type == defaults.nextClass) {
                obj.next = obj.active.next().length ? obj.active.next() : sliders.eq(0);
            } else {
                obj.next = obj.active.prev().length ? obj.active.prev() : sliders.eq(sliders.length - 1);
            }

            return obj;
        }

        // Recursive timeout for automatic carousel rotation.
        function rotateCarousel(type) {
            clearTimeout(data.timeout);

            if (!type || type == 'undefined') {
                data.timeout = setTimeout(function () {
                    fadeSliders(setSliders('next'));
                    rotateCarousel();
                }, defaults.slideDelay);
            }
        }

        // Constructs the markup for the pagers
        function buildPagers() {
            if (defaults.pagers) {
                var pagers = [];

                for (i = 0; i < sliders.length; i++) {
                    var page = i + 1;
                    i == 0 ? state = ' class="' + defaults.activeClass + '"' : state = '';

                    pagers.push('<li><a' + state + ' rel="' + page + '">' + page + '</a></li>')
                }

                return pagers.join('');
            }
        }

        // Attaches pagers to the DOM
        function renderPagers() {
            if (sliders.length > 1) {
                var pagers = '<ol class="pagers">' + buildPagers() + '</ol>';

                root.append(pagers);
                $(defaults.prevNextButtons).show();
            }
        }

        // Delegated event to transition slide on pager clicks
        function handlePagerClicks() {
            var pagers = $('.pagers').find('a');

            pagers.live('click', function () {
                var root = $(this);

                if (!root.hasClass(defaults.activeClass) && !data.activeTransition) {
                    var index = parseInt(root.attr('rel')) - 1,
                        obj = {};
                    obj.active = carousel.find('.' + defaults.activeClass);
                    obj.next = carousel.find(defaults.sliderEl).eq(index);

                    fadeSliders(obj);
                    rotateCarousel('pager');
                }
            });
        }

        // Event handler for prev/next button clicks
        function handlePrevNextClicks() {
            root.find(defaults.prevNextButtons).find('a').click(function (e) {
                e.preventDefault();

                if (!data.activeTransition) {
                    var root = $(this),
                        type = root.parents('li').attr('class'),
                        obj = setSliders(type);

                    fadeSliders(obj);
                    rotateCarousel('pager');
                }
            });
        }

        // Event handler to pause carousel rotation on hover
        function handleHovers() {
            if (defaults.pause) {
                root.hover(function () {
                    rotateCarousel('pause');
                }, function () {
                    rotateCarousel();
                });
            } 
        }

        // Updates the pagers to display the currently active selection
        function changePagers(index) {
            var pagers = root.find('.pagers'),
                active = pagers.find(defaults.sliderEl).eq(index).find('a');

            pagers.find('.' + defaults.activeClass).removeClass(defaults.activeClass);
            active.addClass(defaults.activeClass);
        }

        // Initializes the carousel
        function init() {
            renderPagers();
            handlePagerClicks();
            handlePrevNextClicks();
            handleHovers();
            rotateCarousel();
        }
    };
})(jQuery);

