Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a jQuery autogrow plugin for text fields?

I have found various plugins for auto-growing a textarea, but not input text fields. Does anybody know if any exist?

like image 491
Brad Gessler Avatar asked May 31 '09 03:05

Brad Gessler


4 Answers

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

EDIT: I've fixed the plugin as per Mathias' comment. :)

See a demo here: http://jsfiddle.net/rRHzY

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,'&nbsp;').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);
like image 117
James Avatar answered Nov 01 '22 09:11

James


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

It uses the same approach as James 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();
like image 23
MartinF Avatar answered Nov 01 '22 07:11

MartinF


Good plugin, thank you! I changed two things that seemed to work better in my project though.

  1. I changed the TESTER tag to a DIV, to avoid getting 'Unexpected call to method or property access.' in IE8 (even though your demo does work in IE8. Was there a particular reason for for using a custom HTML tag?
  2. After the bind statement near the end of the code, I added a call to check(), in order to resize the textbox immediately after loading the page, in case the textbox already has content in it on startup.

Hope this helps.

like image 40
JP. Avatar answered Nov 01 '22 07:11

JP.


just wanted to share a small improvement to James's great plugin. Add this code to the CSS declaration for the tester element to account for text-indent:

textIndent: 0

Without it, in some situations the tester element may inadvertently inherit the text-indent from elsewhere, thus throwing off the size of the input.

Like JP, I also wanted to resize the input to the correct size from the beginning, which I did just slightly differently, by chaining "trigger('keyup')" to the autoGrowInput method call, e.g.:

$('#contact_form').autoGrowInput({comfortZone: 7, minWidth: 10, maxWidth: 200}).trigger('keyup');

As a side note, I signed up to this site purely to comment on James's solution and I'm a bit annoyed to find that I can't because I don't have enough reputation points to start with. Sorry if I've missed something, but that seems to mean that I have to post this is a comment on the main question rather than more appropriately on James's solution.

like image 4
Michael Avatar answered Nov 01 '22 07:11

Michael