﻿/* 
* Ninja Gallery Plugin
* v. 1.0 
* Jon Cazier
* 10/14/09
*
*/

jQuery.fn.ninjaGallery = function(options) {
    //-----------------------------------------------------------------------------------------------
    // Configuration Defaults and Options
    //-----------------------------------------------------------------------------------------------

    var defaults = {
        wrapperClass: "ninjaGallery", // Sets the class that wraps around the Ninja Gallery
        spacerWidth: 10, // Adds a margin to the sides of each item
        smallSize: 100, // Sets the size of the inactive items
        largeSize: 200, // Sets the size of the active item
        wrapperWidth: null, // If null it'll try to grab it dynamically, otherwise it'll use an integer value
        startOn: "random", // Sets which item is active at page load. 
        //Available options are "random", "first", "last", or the index position of the item as an integer value. Starts at 0.
        offset: "center", // Sets the x position where the active item is displayed.
        // Available options are "random", "first", "last", or the x position as any positive integer value.
        verticalOffset: 0, // Sets the y position of the active item. Use any integer value.
        moveSpeed: 500, // Speed at which the gallery slides. In milliseconds as an integer value.
        resizeSpeed: 200, // Speed at which the gallery items resize. In milliseconds as an integer value.
        useKeyboard: false, // Boolean value that determines if keyboard navigation is active.
        objToAnimate: null, // If set to 'null' the li itself is resized ... otherwise, the items inside of the li are resized. Can have multiple values. eg: "img, h2, p".
        extraContentId: null, // Class or ID of additional content within the li that needs to be animated seperately.
        offActiveCss: null, // CSS for extra content on inactive items. eg {display: "none", border: "solid 1px red"}.
        offActiveAnimation: null, // Animation for extra content on inactive items. eg {top: "100px", opacity: ".5"}.
        onActiveCss: null, // CSS for extra content on the active item. eg {display: "none", border: "solid 1px red"}.
        onActiveAnimation: null, // Animation for extra content on the active item. eg {top: "-100px", opacity: "1"}.
        slider: false // Boolean value that determines whether or not a slider is added to the control
    };

    var d = jQuery.extend(defaults, options)

    jQuery(this).each(function() {

        var $this = jQuery(this);

        //-----------------------------------------------------------------------------------------------
        // Build Additional Layout
        //-----------------------------------------------------------------------------------------------

        jQuery(this)
			.wrap("<div class='" + d.wrapperClass + "'></div>")
			.before("<a href='#' class='movebutton left'>&lt;</a>")
			.after("<a href='#' class='movebutton right'>&gt;</a>");

        //-----------------------------------------------------------------------------------------------
        // Private Variables
        //-----------------------------------------------------------------------------------------------

        var totalItems = jQuery(this).children().length;
        var wrapperSize = d.wrapperWidth || jQuery(this).parent().width();
        var currentImage = d.startOn;

        //-----------------------------------------------------------------------------------------------
        // Methods
        //-----------------------------------------------------------------------------------------------

        jQuery(this).find("li").each(function() {
            jQuery(this).css({ margin: "0 " + d.spacerWidth + "px" });
            shrinkItem(jQuery(this));
        });

        function shrinkItem(obj) {
            obj.removeClass("active");
            if (d.objToAnimate) {
                obj
                    .stop()
                    .animate({ width: d.smallSize, top: 0 }, offActive(obj));
            } else {
                obj.find(d.objToAnimate)
				    .stop()
				    .animate({ width: d.smallSize, top: 0 }, offActive(obj));
            }
        };

        function enlargeItem(obj) {
            resetActive();
            obj.addClass("active")

            if (d.objToAnimate) {
                obj
                .stop()
                .animate({ width: d.largeSize, top: getVerticalOffset() }, function() { onActive(obj) });
            } else {
                obj
                .find(d.objToAnimate)
                .stop()
                .animate({ width: d.largeSize, top: getVerticalOffset() }, function() { onActive(obj) });
            }
        };

        function offActive(obj) {
            d.offActiveAnimation = d.offActiveAnimation || {};
            d.offActiveCss = d.offActiveCss || {};

            if (d.extraContentId) {
                obj
					.find(d.extraContentId)
					.stop()
					.animate(d.offActiveAnimation)
					.css(d.offActiveCss)
            };
        };

        function onActive(obj) {
            d.onActiveAnimation = d.onActiveAnimation || {};
            d.onActiveCss = d.onActiveCss || {};

            if (d.extraContentId) {
                obj
					.find(d.extraContentId)
					.css(d.onActiveCss)
					.stop()
					.animate(d.onActiveAnimation)
            };
        };

        function moveIt(num) {
            shrinkItem($this.find(".active"));
            $this
				.stop()
				.animate(
					{ left: -((num * (d.smallSize + (d.spacerWidth * 2))) + getOffset(num)) },
					d.moveSpeed,
					function() { enlargeItem($this.find("li").eq(num)); }
				), d.resizeSpeed;

            currentImage = num;

            // if a slider exists
            //if (d.slider) {
            //    jQuery('.slider').slider('value', num);
            //};



        };

        // Removes the "active" class from all items
        function resetActive() {
            $this.find("li.active").removeClass("active");
        };

        //get

        // Return an integer that determines where the active item appears within the panel. 
        // Available options are "center", "left", "right", "dynamic", or any integer value.
        function getOffset(index) {
            var o = 0;
            switch (d.offset) {
                case "center":
                    o = (d.largeSize - wrapperSize) / 2;
                    break;
                case "left":
                    o = 0;
                    break;
                case "right":
                    o = (d.largeSize - wrapperSize) + d.spacerWidth * 2;
                    break;
                case "dynamic":
                    if (index == 0) { // first item
                        o = 0;
                    } else if (index == 1) { // second item
                        o = -(d.smallSize + d.spacerWidth * 2);
                    } else if (index == 2) { // third item
                        o = -(d.smallSize + d.spacerWidth * 2) * 2;
                    }

                    else if (index == totalItems - 1) { // last item
                        o = (d.largeSize - wrapperSize) + d.spacerWidth * 2;
                    } else if (index == totalItems - 2) { // second to last item
                        o = ((d.largeSize - wrapperSize) + d.spacerWidth * 2) + d.smallSize;
                    } else if (index == totalItems - 3) { // third to last item
                        o = ((d.largeSize - wrapperSize) + d.spacerWidth * 2) + d.smallSize * 2;

                    } else { // everything else is centered
                        o = (d.largeSize - wrapperSize) / 2;
                    }
                    break;
                default:
                    o = d.offset;
            };
            return o;
        };

        // Return an integer that determines the active items vertical position.
        function getVerticalOffset() {
            var vo = 0;
            switch (d.verticalOffset) {
                case "middle":
                    vo = -(d.largeSize - d.smallSize) / 2;
                    break;
                case "top":
                    $.trace($this.find("li").height());
                    vo = -(d.smallSize);
                    break;
                case "bottom":
                    vo = 0;
                    break;
                default:
                    vo = d.verticalOffset;
            };
            return vo;
        };

        // Return an integer that determines which item is shown as the default. 
        // Available options are "random", "first", "last", or any positive integer value.
        function getStartOn() {
            var s = 0;
            switch (d.startOn) {
                case "random":
                    s = Math.floor(Math.random() * totalItems);
                    break;
                case "first":
                    s = 0;
                    break;
                case "last":
                    s = totalItems - 1;
                    break;
                default:
                    if (d.startOn > totalItems - 1) {
                        s = totalItems - 1;
                        $.trace(s);
                    } else if (d.startOn < 0) {
                        s = 0;
                    } else {
                        s = d.startOn;
                    };
            };
            return s;
        };

        // Moves gallery one step to the left
        function moveLeft() {
            if (currentImage > 0) {
                moveIt(currentImage - 1);
            };
        };

        // Moves gallery one step to the right
        function moveRight() {
            if (currentImage < totalItems - 1) {
                moveIt(currentImage + 1);
            };
        };

        //-----------------------------------------------------------------------------------------------
        // Navigational Methods
        //-----------------------------------------------------------------------------------------------

        // Navigates to the item that has been clicked on
        jQuery(this).find("li").click(function() {
            if (!jQuery(this).hasClass("active")) {
                moveIt(jQuery(this).parent().find("li").index(this));
            };
        });

        // Moves gallery when the left button is clicked
        jQuery(this).parent().find("a.left").click(function() {
            moveLeft();
            return false;
        });

        // Moves gallery when the right button is clicked
        jQuery(this).parent().find("a.right").click(function() {
            moveRight();
            return false;
        });

        // Uses keyboard keys to navigate gallery
        jQuery(window).keydown(function(event) {
            if (d.useKeyboard) {
                switch (event.keyCode) {
                    case 13: //enter
                        moveRight();
                        break;
                    case 32: //space
                        moveRight();
                        break;
                    case 37: //left arrow
                        moveLeft();
                        break;
                    case 39: //right arrow
                        moveRight();
                        break;
                };
            };
        });

        //-----------------------------------------------------------------------------------------------
        // Init
        //-----------------------------------------------------------------------------------------------

        // Sets the default active item on startup
        var startingValue = getStartOn();

        moveIt(startingValue);

        // Initialize a slider if needed
        //        if (d.slider) {
        //            var currentValue;

        //            jQuery('.slider').slider({
        //                max: totalItems - 1,
        //                value: startingValue,
        //                stop: function(e, ui) { moveIt(ui.value) }
        //            });
        //        }

    });
};