(function($){
    var defaults = {
        activeClass: 'active',
        previousClass: 'previous',
        itemSelector: 'li.traverserSelector',
        delay: 2000,
        initialDelay: 6000,
        mouseoverDelay: 80,
        mouseoutDelay: 1000,
        preTraversion: function(before, after){},
        postTraversion: function(before, after){}
    };
    
    var traversers = [];

    function isTraverser(element){
        for (x in traversers) {
            if (traversers[x] == element) {
                return true;
            }
        }
        return false;
    }

    $.fn.itemTraverser = function(options){
        var options = options || {};
        var settings = $.extend({}, defaults, options);

        this.each(function(){
            if (!isTraverser(this)) {
                traversers[traversers.length] = this;
                
                var current = 0;
                var items = [];
                var timer = null;
                var mouseTimer = null;
                var $this = $(this);

                function traverseTo(index){
                    if (index >= items.length){
                        index = 0;
                    } else if (index < 0) {
                        index = items.length -1;
                    }
                    
                    if (index == current) {
                        return;
                    }
                    
                    settings.preTraversion({
                        index: current, 
                        item: items[current]
                    },
                    {
                        index: index, 
                        item: items[index]
                    });
                    
                    var previous = current;
                    current = index;
                    $this.children(settings.itemSelector)
                        .removeClass(settings.activeClass)
                        .removeClass(settings.previousClass);
                    $(items[previous]).addClass(settings.previousClass);
                    $(items[current]).addClass(settings.activeClass);
                    settings.postTraversion({
                        index: previous, 
                        item: items[previous]
                    },
                    {
                        index: current, 
                        item: items[current]
                    });
                }

                function next(){
                    traverseTo(current + 1);
                }

                function previous(){
                    traverseTo(current + 1);
                }

                function autoTraverse(){
                    next();
                    timer = setTimeout(autoTraverse, settings.delay);
                }

                $(this).children(settings.itemSelector).each(function(){
                    var index = items.length;
                    items[index] = this;
                    if ($(this).hasClass(settings.activeClass) && (current == 0)) {
                        current = index;
                    }
                    $(this).mouseover(function(){
                        clearTimeout(mouseTimer);
                        function doTraverse(){
                            traverseTo(index);
                        }
                        mouseTimer = setTimeout(doTraverse, settings.mouseoverDelay);
                    });
                });

                $(this).mouseover(function(){
                    clearTimeout(timer);
                });

                $(this).mouseout(function(){
                    timer = setTimeout(autoTraverse, settings.mouseoutDelay);
                    clearTimeout(mouseTimer);
                });

                timer = setTimeout(autoTraverse, settings.initialDelay);
            }
        });
        
        return this;
    };
})(jQuery);
