Shrinking font-size at a user types to fit in an input using Javascript

I made another one from a hodgepodge of other answers. I think this provides the simplest one-property-change solution.

It's likely overly verbose or could be refactored for clarity in some ways, any suggestions welcomed!

$(document).ready(function(){

    // get the current styles size, in px integer.
    var maxSize = parseInt($('.fields').css("font-size"));

    function isOverflowed (element){

        if ( $(element)[0].scrollWidth > $(element).innerWidth() ) {
            return true;
        } else {
            return false;
        }
    };

    function decreaseSize (element){

        var fontSize = parseInt($(element).css("font-size"));
        fontSize = fontSize - 1 + "px";
        $(element).css({'font-size':fontSize});

    }

    function maximizeSize (element){

        var fontSize = parseInt($(element).css("font-size"));
        while (!isOverflowed(element) && fontSize < maxSize){
            fontSize = fontSize + 1 + "px";
            $(element).css({'font-size':fontSize});

            // if this loop increases beyond the width, decrease again. 
            // hacky.
            if (isOverflowed(element)){
                while (isOverflowed(element)) {
                    decreaseSize(element);
                }            
            }     

        }        

    }

    function fixSize (element){
        if (isOverflowed(element)){
            while (isOverflowed(element)) {
                decreaseSize(element);
            }            
        } else {
            maximizeSize(element);
        }
    }

    // execute it onready.
    $('.fields').each(function(){
        fixSize(this);
    });

    // bind to it.
    $(function() {
        $('.fields').keyup(function() {
            fixSize(this);
        })
    });    

});

I've done this in the past using jQuery. You can measure the size of a piece of text like this:

// txt is the text to measure, font is the full CSS font declaration,
// e.g. "bold 12px Verdana"
function measureText(txt, font) {
    var id = 'text-width-tester',
        $tag = $('#' + id);
    if (!$tag.length) {
        $tag = $('<span id="' + id + '" style="display:none;font:' + font + ';">' + txt + '</span>');
        $('body').append($tag);
    } else {
        $tag.css({font:font}).html(txt);
    }
    return {
        width: $tag.width(),
        height: $tag.height()
    }
}

var size = measureText("spam", "bold 12px Verdana");
console.log(size.width + ' x ' + size.height); // 35 x 12.6

In order to fit this to a given space, it's a little trickier - you need to separate out the font-size declaration and scale it appropriately. Depending on how you're doing things, this might be easiest if you break out the different parts of the font declaration. A resize function might look like this (again, obviously, this is jQuery-dependent):

function shrinkToFill(input, fontSize, fontWeight, fontFamily) {
    var $input = $(input),
        txt = $input.val(),
        maxWidth = $input.width() + 5, // add some padding
        font = fontWeight + " " + fontSize + "px " + fontFamily;
    // see how big the text is at the default size
    var textWidth = measureText(txt, font).width;
    if (textWidth > maxWidth) {
        // if it's too big, calculate a new font size
        // the extra .9 here makes up for some over-measures
        fontSize = fontSize * maxWidth / textWidth * .9;
        font = fontWeight + " " + fontSize + "px " + fontFamily;
        // and set the style on the input
        $input.css({font:font});
    } else {
        // in case the font size has been set small and 
        // the text was then deleted
        $input.css({font:font});
}

You can see this in action here: http://jsfiddle.net/nrabinowitz/9BFQ8/5/

Testing seems to show that this is a little jumpy, at least in Google Chrome, because only full-integer font sizes are used. You might be able to do better with a em-based font declaration, though this might be a little tricky - you'd need to ensure that the 1em size for the text width tester is the same as that for the input.