(function($) {
    $.fn.jSlider = function(params) {
        var defaults = {
            prev: null,
            next: null,
            locator: null,
            itemWidth: 100,
            speed: 200,
            visible: 2,
            start: 0,
            scroll: 1
        };

        var params = $.extend(defaults, params);

        return this.each(function() {
            var paneDiv = $(this);
            var prev = $(params.prev);
            var next = $(params.next);
            var ul = $("ul", paneDiv)
            var li = $("li", ul);
            var itemCount = li.size();

            var sliding = false;
            var startIndex = params.start;

            var steps = Math.ceil(itemCount / params.visible);

            // resize ul
            ul.css("width", (params.itemWidth * itemCount));

            // disable prev button on startup
            prev.addClass("disabled");

            // handle click on prev button
            prev.click(function() {
                return slide(startIndex - params.visible);
            });

            // handle click on next button
            next.click(function() {
                return slide(startIndex + params.visible);
            });

            // locator
            if (params.locator != "") {
                $(params.locator).html(buildLocator(steps, 1));

                // handle locator step click
                $("#sliderbox .locator a").click(function() {
                    return slide(this.id * params.visible);
                });
            }


            function slide(endIndex) {
                if (!sliding) {
                    // still content to slide?
                    if ((endIndex >= 0) && (endIndex < itemCount)) {
                        startIndex = endIndex;
                        leftOffset = -(endIndex * params.itemWidth)
                        sliding = true;
                        ul.animate({ left: leftOffset }, params.speed, null,
                            function() {
                                // enable/disable navigation
                                $(prev).removeClass("disabled");
                                $(next).removeClass("disabled");
                                $((endIndex <= 0 && prev) || ((endIndex + params.visible) >= itemCount && next) || []).addClass("disabled");

                                if (params.locator != "") {
                                    // update locator
                                    $(params.locator).html(buildLocator(steps, (startIndex / params.visible + 1)));
                                    // handle newly built locator step click
                                    $(params.locator + " a").click(function() {
                                        return slide(this.id * params.visible);
                                    });
                                }

                                sliding = false;
                            }
                        );
                    }
                }

                return false;
            }

            function buildLocator(noOfSteps, activeStep) {
                locatorString = '';

                for (i = 1; i <= noOfSteps; i++) {
                    if (i == activeStep)
                        locatorString += '<a class="button current" href="#" onclick="javascript: return false;" onfocus="this.blur();"></a>';
                    else
                        locatorString += '<a class="button" id="' + (i - 1) + '" href="#" onclick="javascript: return false;" onfocus="this.blur();"></a>';
                }

                return locatorString;
            }
            
        });
    };
})(jQuery);