﻿
(function($) {
    $.fn.itemScroll = function(options) {

        var elem = this.data("itemScroll");
        if (elem) { return elem; }

        options = $.extend({
            itemSpeed: 2000
					, direction: "left"
        }, options || {}
				)

        this.each(function() {
            elem = new ItemScroll($(this), options);
            $(this).data("itemScroll", elem);
        });

        return options.api ? elem : this;

        function ItemScroll($this, opt) {
            //return this.each( function() {

            var self = this,
				$scrollItems = $this.children(), //.hide(),						
				$itemStrip = $this.wrapInner("<div id='itemStrip' style='clear:both; padding: 0px; margin: 0px;'></div>").children("div#itemStrip"),
				animateDist = 0,
				animateFunc = "marginLeft",
				animateSign = "-=",
				animationStarted = false;

            $.extend(self, {
                direction: function(val) {
                    if (val) {
                        if (opt.direction == val)
                            return self;

                        opt.direction = val;
                        setAnimationValues();
                        $itemStrip.stop();
                        animationUpdate();
                        return self;
                    }
                    return opt.direction;
                },
                stopScroll: function() {
                    $itemStrip.stop();
                    return self;
                },
                startScroll: function() {
                    $itemStrip.stop();
                    animationUpdate();
                    return self;
                },
                scrollItems: function() {
                    return $itemStrip.children();
                }

            });

            // callbacks	
            $.each(['onMouseIn', 'onMouseOut'], function(i, name) {

                // check options
                if ($.isFunction(options[name])) {
                    $this.bind(name, options[name]);
                }

                this[name] = function(fn) {
                    if (fn) { $this.bind(name, fn); }
                    return this;
                };
            });

            //add scroll items to ensure there are enough to keep smooth scrolling			
            if (opt.direction == "left" || opt.direction == "right") {
                $itemStrip.width($this.width() - 1);

                while ($itemStrip.width() < $this.width()) {
                    $scrollItems.each(function() {
                        $itemStrip.append($(this).clone());
                    });

                    if (animateDist == 0)
                        animateDist = $itemStrip.children(":eq(1)").offset().left - $itemStrip.children(":eq(0)").offset().left;

                    $itemStrip.width($itemStrip.width() + animateDist * $scrollItems.length);
                }
            }
            else {
                $itemStrip.height($this.height() - 1);

                while ($itemStrip.height() < $this.height()) {
                    $scrollItems.each(function() {
                        $itemStrip.append($(this).clone()).height($itemStrip.height() + $(this).height());
                    });

                    if (animateDist == 0)
                        animateDist = $itemStrip.children(":eq(0)").offset().top - $itemStrip.children(":eq(1)").offset().top;

                    $itemStrip.height($itemStrip.height() + animateWidth * $scrollItems.length);
                }

                animateFunc = "marginTop";
            }

            function animationUpdate() {

                switch (opt.direction) {
                    case "left":
                    case "top":
                    case "up":
                        distance = animateDist + parseInt($itemStrip.css(animateFunc).replace("px", ""));
                        break;

                    case "right":
                    case "bottom":
                    case "down":
                        distance = Math.abs(parseInt($itemStrip.css(animateFunc).replace("px", "")));
                        break;
                }
                //calculate the remaining distance to move and the relative time it remaining to move it					
                animateItems(distance, distance / animateDist * opt.itemSpeed);
            }
            
            function setAnimationValues() {
                switch (opt.direction) {
                    case "left":
                        animateFunc = "marginLeft";
                        animateSign = "-=";
                        break;

                    case "right":
                        animateFunc = "marginLeft";
                        animateSign = "+=";
                        break;

                    case "up":
                    case "top":
                        animateFunc = "marginTop";
                        animateSign = "-=";
                        break;

                    case "down":
                    case "bottom":
                        animateFunc = "marginTop";
                        animateSign = "+=";
                        break;
                }

            }

            function animateItems(distance, time) {

                switch (opt.direction) {
                    case "left":
                    case "right":
                        $itemStrip.animate({ "marginLeft": animateSign + distance }, time, "linear", animateComplete);
                        break;
                    case "top":
                    case "up":
                    case "down":
                    case "bottom":
                        $itemStrip.animate({ "marginTop": animateSign + distance }, time, "linear", animateComplete);
                        break;
                }
            }

            function animateComplete() {
                var margin = parseInt($itemStrip.css(animateFunc).replace("px", ""));

                switch (opt.direction) {
                    case "left":
                    case "up":
                    case "top":
                        $itemStrip.append($itemStrip.children(":eq(0)")).css(animateFunc, margin + animateDist);
                        break;

                    case "right":
                    case "down":
                    case "bottom":
                        $itemStrip.prepend($itemStrip.children(":last")).css(animateFunc, margin - animateDist);
                        break;
                }

                animateItems(animateDist, opt.itemSpeed);
            }

            setAnimationValues();

            switch (opt.direction) {
                case "right":
                case "down":
                case "bottom":
                    animateComplete();
                    break;
                default:
                    animateItems(animateDist, opt.itemSpeed);
                    break;
            }


        }
    };
})(jQuery);

