views:

3059

answers:

5

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

A: 

If you want the textbox to grow when the string within it extends past its width, maybe something like this would work for you... It detects the size attribute of the textbox. If the length of the string goes over that attribute, it extends the textbox to the length of the string on keyup.

In the below script, "#test" is a textbox ID.

<script language="javascript" type="text/javascript">
$(document).ready(function(){
 $("#test").keyup(function(){
  if($("#test").attr("size") < $("#test").val().length){
   size = $("#test").val().length;
   $("#test").attr("size",size);
  }
 })
});
</script>
BraedenP
This relies on the text being a fixed-width typeface; so it won't work with fonts like Arial, verdana etc.
J-P
+20  A: 

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://jsbin.com/ahaxe

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);
J-P
Awesome plugin, James! One suggestion though: perhaps it would be cool if the INPUTs would also decrease in size when text is removed.
Mathias Bynens
Thanks Mathias; just fixed it - it should decrease as expected now :)
J-P
Perfect! You should totally blog this.
Mathias Bynens
Great! This is totally what I was looking for, you should definitely blog about this and get some link bait around this so others can find it in Google.
Brad Gessler
Is there a reason why you use `var escaped = val.replace(/testSubject.html(escaped);` instead of `testSubject.text(val)`
Ghommey
wicked script, James! Don't know if I'll use it, but it's been a while since I last felt that surge of joy that nice javascript creates!
Morten Bergfall
+1  A: 

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.

JP
A: 

Hi there, 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.

Miquel
A: 

Is it possible to create the same effect for the height of the box with a fixed width? ie the more the user types the taller the input field gets. Thanks

ASW
As this is no answer you might want to start a new question.
Ghommey