jQuery.fn.ticker = function(options) {
    var defaults = {
        speed: .03
    };
    var options = jQuery.extend(defaults, options);
    
    function get_distance(html) {
        var clone = jQuery('<div></div>').html(html);
        clone.css({ float: 'left', whiteSpace: 'nowrap', display: 'none' });
        clone.appendTo('body');
        output = clone.width();
        clone.remove();
        return output;
    }
    
    function get_width(el) {
        return jQuery(el).width();
    }
    
    function animate(element, distance, width, speed) {
        var pos = jQuery(element).position();
        var travel = ((distance + width) - (width - pos.left));
        var time = (travel / speed);

        jQuery(element).animate({
            left: -distance
        }, time, "linear", function() {
            jQuery(this).css({
                left: width
            });
            animate(this, distance, width, speed)
        });

        jQuery(element).hover(function() {
            jQuery(this).stop();
        }, function() {
            jQuery(this).unbind('mouseleave'); // keep animation calls from stacking.
            animate(this, distance, width, speed);
        });
    }
    
    return this.each(function() {
        var d;
        var w;
        var s;
        var div;
        
        var content = jQuery(this).html();
        
        d = get_distance(content);
        w = get_width(this);
        s = options.speed
        
        jQuery(this).css({ position: 'relative', overflow: 'hidden' });
        jQuery(this).wrapInner('<div></div>');
        
        div = jQuery(this).find('div').eq(0);
        jQuery(div).css({ left: w, position: 'relative', whiteSpace: 'nowrap' });
                            
        animate(div, d, w, s);
    });
};