﻿/**
 * Carousel plugin for jQuery
 *
 * HTML structure:
 * <div>      -> mainCarouselFrame
 *    <ul>    -> carouselContianer
 *       <li> -> items
 * Configuration
 * 
 * 
 * Usage:
 *  INIT: $('list_of_ul_container').carousel(overridenConfiguration = {})
 *  NEXT: $('list_of_ul_container').carouselNext();
 *  PREV: $('list_of_ul_container').carouselPrev();
 *  GOTO: $('list_of_ul_container').carouselSelect();
 *  ANIMATION START: $('list_of_ul_container').carouselStart();
 *  ANIMATION STOP : $('list_of_ul_container').carouselStop() ;
 *
 * 
 */



;(function($){
    jQuery.fn.carousel = function(params) {
        jQuery.carouselConf = $.extend({
            unSelectedScale:        0.5,
            selectedScale:          0.8,
            reverse:              false,
            itemSpeed:              800,
            speed:                  500,
            nonSelectedStyle:  "center",
            selectedStyle:     "center",
            selectedItem:             0,
            //CONFIGURACIONES NUEVAS
            itemsOnScreen:            3,
            timeout:                  0,
            onChange:       function(){}
        }, params);

        jQuery.carouselContainer = this;

        //Iteramos para cada lista
        return this.each(function() {
            try {
                //Obtenemos las listas
                $(this).data("_carousel_isCarousel", true);
                var $container = $(this).parent().css("overflow", "hidden");
                //Calculamos el tamaño un hijo en función de el número de
                //hijos que queremos mostrar en pantalla
                var childWidth = $container.width() / jQuery.carouselConf.itemsOnScreen;
                var childHeight = $container.height();

                //Asignamos ese tamaño a cada hijo y el total al padre, como
                //height ponemos el del padre
                var $ulChildren = $(this).children("li");

                //Calculamos el padding de los hijos
                var childHorizontalPadding = parseInt($ulChildren.css("padding-left"))+parseInt($ulChildren.css("padding-right"));


                $(this).data("_carousel_maxIndex", $ulChildren.length)
                $(this).css({
                    position: "relative",
                    width: (childWidth+childHorizontalPadding) * $ulChildren.length + "px"
                });
                $ulChildren.css({
                    width: (childWidth) + "px",
                    height: (childHeight) + "px",
                    display: "block",
                    "float": "left"
                });
                //Escalamos el contenido de los hijos al porcentaje dado
                var $childContent = $ulChildren.children();

                var childContentWidth =  jQuery.carouselConf.unSelectedScale * childWidth;
                var childContentHeight = jQuery.carouselConf.unSelectedScale * childHeight;

                //Comprobamos el nonSelectedStyle para calcular los offsets
                var offsetCSS = calculateOffset([childWidth, childHeight], [childContentWidth, childContentHeight], jQuery.carouselConf.nonSelectedStyle);
                if ($.browser.msie) {
                    $childContent.css({
                        width: childContentWidth +  "px",
                        height:childContentHeight + "px"
                    }).css(offsetCSS);
                } else {
                    $childContent.css({
                        position: "relative",
                        width: childContentWidth +  "px",
                        height:childContentHeight + "px"
                    }).css(offsetCSS);
                }

                if (jQuery.carouselConf.selectedItem != "none") {
                    $(this).carouselSelect(jQuery.carouselConf.selectedItem);
                }
            }
            catch(error) {}
        });
    }

    jQuery.fn.carouselCurrentIndex = function() {
        if ($(this).data("_carousel_isCarousel")) return $(this).data("_carousel_selectedIndex");
        else return 0;
    }
    jQuery.fn.carouselLength = function() {
        if ($(this).data("_carousel_isCarousel")) return $(this).data("_carousel_maxIndex");
        else return 0;
    }


    jQuery.fn.carouselNext = function() {
        return this.each(function() {
            if (!$(this).data("_carousel_isCarousel")) {
                return $(this);
            }

            //Recuperamos el índice actual
            var oldIndex = $(this).data("_carousel_selectedIndex");
            var actualIndex = oldIndex;
            var maxIndex = $(this).data("_carousel_maxIndex");

            if (actualIndex == maxIndex - 1) {
                if (jQuery.carouselConf.reverse) actualIndex = 0;
            } else {
                actualIndex++;
            }

            if (oldIndex != actualIndex) {
                $(this).carouselSelect(actualIndex);
            }
        });
    };

    jQuery.fn.carouselPrev = function() {
        return this.each(function() {
            if (!$(this).data("_carousel_isCarousel")) {
                return $(this);
            }

            //Recuperamos el índice actual
            var oldIndex = $(this).data("_carousel_selectedIndex");
            var actualIndex = oldIndex;
            var maxIndex = $(this).data("_carousel_maxIndex");

            if (actualIndex == 0) {
                if (jQuery.carouselConf.reverse) actualIndex = maxIndex - 1;
            }
            else {
                actualIndex--;
            }
            if (oldIndex != actualIndex) {
                $(this).carouselSelect(actualIndex);
            }
        });
    };

    jQuery.fn.carouselLength = function() {
        if (!$(this).data("_carousel_isCarousel")) {
            return 0;
        }

        return $(this).data("_carousel_maxIndex");
    }

    jQuery.fn.carouselStart= function() {
        if (parseInt(jQuery.carouselConf.timeout) > 0) {
            jQuery.carouselTimeout = setInterval(function(){$(jQuery.carouselContainer).carouselNext()}, jQuery.carouselConf.timeout);
        }
    }
    jQuery.fn.carouselStop = function() {
        if (parseInt(jQuery.carouselConf.timeout) > 0) {
            clearInterval(jQuery.carouselTimeout);
        }
    }

    jQuery.fn.carouselSelect = function(newIndex) {
        return this.each(function() {
            $(this).carouselStop();
            if (!$(this).data("_carousel_isCarousel")) {
                return $(this);
            }

            var oldIndex = $(this).data("_carousel_selectedIndex");
            if (typeof newIndex == "string") {
                if (newIndex == "center") {
                    newIndex = parseInt($(this).carouselLength() / 2);
                }
                else if (newIndex == "selected") {
                    newIndex = oldIndex;
                }
                else if (newIndex == "random") {
                    newIndex = Math.round(Math.random() * ($(this).carouselLength()));
                }
            }
            if (oldIndex == newIndex) {
                return $(this);
            }

            //Obtenemos el elemento actual
            var $actual = $(".selected", this).removeClass("selected");//.css('z-index', 1);
            //Guardamos el tamaño del padre
            var parentWidth = $actual.width();
            var parentHeight = $actual.height();

            //Si había uno seleccionado lo deseleccionamos
            var contentDimension, offset, newCss;
            if ($actual.length > 0) {
                //Obtenemos el width y height del actual en función del estado
                //no seleccionado
                contentDimension = [parentWidth * jQuery.carouselConf.unSelectedScale, parentHeight * jQuery.carouselConf.unSelectedScale]
                //Calculamos el nuevo offset
                offset = calculateOffset([parentWidth, parentHeight], contentDimension, jQuery.carouselConf.nonSelectedStyle);

                //Añadimos al offset width y height y ya tenemos el css listo
                newCss = offset;
                newCss.width = contentDimension[0] + "px";
                newCss.height = contentDimension[1] + "px";

                //Lo aplicamos
                $actual.children().animate(newCss, jQuery.carouselConf.itemSpeed)
            }

            //Calculamos el nuevo seleccionado
            $actual = $("li", this).eq(newIndex).addClass("selected");//.css('z-index', 2);
            parentWidth = $actual.width();
            parentHeight = $actual.height();

            //Si existe el nuevo actual
            if ($actual.length > 0) {
                //Obtenemos el width y el height para el estado seleccionado
                contentDimension = [parentWidth * jQuery.carouselConf.selectedScale, parentHeight * jQuery.carouselConf.selectedScale];
                //Calculamos el nuevo offset
                offset = calculateOffset([parentWidth, parentHeight], contentDimension, jQuery.carouselConf.selectedStyle);

                //Añadimos al offset width y height y ya tenemos el css listo
                newCss = offset;
                newCss.width = contentDimension[0] + "px";
                newCss.height = contentDimension[1] + "px";

                //Lo aplicamos
                $actual.children().animate(newCss, jQuery.carouselConf.itemSpeed);
            }

            //Centramos el contenedor en el elemento seleccionado
            var containerWidth = $(this).parent("div").width();
            var elementWidth = $("li:eq(0)", this).width()
                + parseInt($("li:eq(0)",this).css("padding-left"))
                + parseInt($("li:eq(0)",this).css("padding-right"))
            ;

            $(this).animate({
                left: containerWidth / 2 - newIndex * elementWidth - elementWidth / 2 + "px"
            },
            jQuery.carouselConf.speed);

            $(this).data("_carousel_selectedIndex", newIndex);

            jQuery.carouselConf.onChange();
            $(this).carouselStart();
        });
    };

    //Función privada que calcula los offsets de los contenedores
    function calculateOffset(containerDimension, contentDimension, configuration) {
        offsetFunctions = {
            "center": function() {
                var left = (containerDimension[0] - contentDimension[0]) / 2;
                var top = (containerDimension[1] - contentDimension[1]) / 2;

                return {
                    top: top + "px",
                    left: left + "px"
                };
            },
            "top": function() {
                var top = 0;
                var left = (containerDimension[0] - contentDimension[0]) / 2;

                return {
                    top: top + "px",
                    left: left + "px"
                }
            },
            "bottom": function() {
                var top = (containerDimension[1] - contentDimension[1]);
                var left = (containerDimension[0] - contentDimension[0]) / 2;

                return {
                    top: top + "px",
                    left: left + "px"
                }
            }
        }
        return offsetFunctions[configuration]()
    }
})(jQuery);
