Smooth Marquee

HTML

<p>
    <label for=demo>Marquee:</label>
    <input id=marquee readonly>
</p>
<p>
    <label for=text>Input:</label>
    <input id=text value="Hello, World! The quick brown fox jumps over the lazy dog! ">
</p>
<p>
    <label for=speed>Speed:</label>
    <input id=speed type=range min=10 max=500 value=150>
    <label for=speed><span id='speed-ms'>150</span>ms</label>
</p>

CSS

#marquee {
    font-size:30px;
    width:100%;
    display:block;
}
p {
    margin-top:1em;
    margin-bottom:em;
}
#text {
    width:300px;
}


footer {
    display:block;
    margin-top:1em;
    border-top:solid 1px gray;
    padding-top:0.5em;
    font-size:smaller;
    font-style:italic;
}

JavaScript

var $ = jQuery;

var spaces = [
    //"\u2004", // Thick Space
    //"\u2005", // Mid Space
    "\u2008", // Punctuation Space
    //"\u2006", // Six-Per-Em Space
    "\u2009", // Thin Space
    "\u200A"  // Hair Space
];
var reStartsWithSpace = new RegExp('^([' + spaces.join('') + '])');
var rePuncSpaceOK = /^[^iIl!\.,']/;

function updateMarquee(){
    var marquee = $('#marquee').val();
    
    // Classic lazy marquee
    if(!$('#smoothen').prop('checked')){
        marquee = marquee.replace(reStartsWithSpace, '');
        marquee = marquee.substr(1)+marquee.substr(0,1);
    }
    // Smoothened marquee
    else {
        var match = marquee.match(reStartsWithSpace);
        if(match){
            var i = spaces.indexOf(match[1]);
            
            // Remove the last space (hair-space)
            if(i == spaces.length-1){
                marquee = marquee.substr(1);
            }
            // Swap out current space with next smallest one
            else {
                marquee = spaces[i+1]+marquee.substr(1);
            }
        }
        // Strip off the first character and prepend biggest space
        else {
            var smallestSpace = rePuncSpaceOK.test(marquee.substr(1,1)) ? spaces[0] : spaces[1];
            marquee = smallestSpace+marquee.substr(1)+marquee.substr(0,1);
        }
    }
    $('#marquee').val(marquee);
    setTimeout(updateMarquee, +$('#speed').val());
}
updateMarquee();


$('form').submit(function(event){
    event.preventDefault(); 
});

$('#speed').change(function(){
    $('#speed-ms').text(this.value);
});

$('#text').bind('input', function(){
    $('#marquee').val(this.value);
}).trigger('input');