jQuery - auto size text input (not textarea!) [duplicate]

Here's a plugin that'll do what you're after:

The plugin:

(function($){

$.fn.autoGrowInput = function(o) {

    o = $.extend({
        maxWidth: 1000,
        minWidth: 0,
        comfortZone: 70
    }, o);

    this.filter('input:text').each(function(){

        var minWidth = o.minWidth || $(this).width(),
            val = '',
            input = $(this),
            testSubject = $('<tester/>').css({
                position: 'absolute',
                top: -9999,
                left: -9999,
                width: 'auto',
                fontSize: input.css('fontSize'),
                fontFamily: input.css('fontFamily'),
                fontWeight: input.css('fontWeight'),
                letterSpacing: input.css('letterSpacing'),
                whiteSpace: 'nowrap'
            }),
            check = function() {

                if (val === (val = input.val())) {return;}

                // Enter new content into testSubject
                var escaped = val.replace(/&/g, '&amp;').replace(/\s/g,' ').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                testSubject.html(escaped);

                // Calculate new width + whether to change
                var testerWidth = testSubject.width(),
                    newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
                    currentWidth = input.width(),
                    isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
                                         || (newWidth > minWidth && newWidth < o.maxWidth);

                // Animate width
                if (isValidWidthChange) {
                    input.width(newWidth);
                }

            };

        testSubject.insertAfter(input);

        $(this).bind('keyup keydown blur update', check);

    });

    return this;

};

})(jQuery);

EDIT: Found on: Is there a jQuery autogrow plugin for text fields?


I don't think there is a perfect solution to that problem because you cannot detect the actual width of the text entered to the input element. It all depends of the font you are using, zoom settings in browser etc.

However if you can choose a font where you can actually calculate the number of pixels that text have (this is the hardest part but I guess you can try to estimate it somehow). You can use this to change the width of your input field.

 $('input').keyup(function () {
     // I'm assuming that 1 letter will expand the input by 10 pixels
     var oneLetterWidth = 10;

     // I'm also assuming that input will resize when at least five characters
     // are typed
     var minCharacters = 5;
     var len = $(this).val().length;
     if (len > minCharacters) {
         // increase width
         $(this).width(len * oneLetterWidth);
     } else {
         // restore minimal width;
         $(this).width(50);
     }
 });

(Edited: using the .text() method instead of .html() to get all formatting right.)

Hello I dont know if you are still looking but i came across this when i was looking for a script to do the same thing. So hope this helps anyone who is trying to do this, or something similar.

function editing_key_press(e){
    if(!e.which)editing_restore(this.parentNode);
    var text = $('<span>')
        .text($(this).val())
        .appendTo(this.parentNode);
    var w = text.innerWidth();
    text.remove();
    $(this).width(w+10);
}

The logic to this code is to put the content onto the page in a span and then gets the width of this content and removes it. The problem i did have was with it was that i had to get it to run on both keydown and keyup for it to work successfully.

Hope this helps, Might not as i have only been doing jquery for a short amount of time.

Thanks

George


I have a jQuery plugin on GitHub: https://github.com/MartinF/jQuery.Autosize.Input

It uses the same approach as seize's answer but have some of the changes mentioned in the comments.

You can see an live example here: http://jsfiddle.net/mJMpw/6/

Example:

<input type="text" value="" placeholder="Autosize" data-autosize-input='{ "space": 40 }' />

input[type="data-autosize-input"] {
  width: 90px;
  min-width: 90px;
  max-width: 300px;
  transition: width 0.25s;    
}

You just use css to set min/max-width and use a transition on the width if you want a nice effect.

You can specify the space / distance to the end as the value in json notation for the data-autosize-input attribute on the input element.

Of course you can also just initialize it using jQuery

$("selector").autosizeInput();

I used seize's answer, but made these changes:

  • Between setting isValidWidthChange and // Animate width:

    if (!isValidWidthChange && newWidth > minWidth && newWidth > o.maxWidth) {
        newWidth = o.maxWidth;
        isValidWidthChange = true;
    }
    

    This way the input will grow as big as you've allowed it when its contents are too big to fit within the max width.

  • After $(this).bind('keyup keydown blur update', check);:

    // Auto-size when page first loads
    check();