Autosizing textarea using Prototype

By : Mike
Source: Stackoverflow.com
Question!

I'm currently working on an internal sales application for the company I work for, and I've got a form that allows the user to change the delivery address.

Now I think it would look much nicer, if the textarea I'm using for the main address details would just take up the area of the text in it, and automatically resize if the text was changed.

Here's a screenshot of it currently.

ISO Address

Any ideas?


@Chris

A good point, but there are reasons I want it to resize. I want the area it takes up to be the area of the information contained in it. As you can see in the screen shot, if I have a fixed textarea, it takes up a fair wack of vertical space.

I can reduce the font, but I need address to be large and readable. Now I can reduce the size of the text area, but then I have problems with people who have an address line that takes 3 or 4 (one takes 5) lines. Needing to have the user use a scrollbar is a major no-no.

I guess I should be a bit more specific. I'm after vertical resizing, and the width doesn't matter as much. The only problem that happens with that, is the ISO number (the large "1") gets pushed under the address when the window width is too small (as you can see on the screenshot).

It's not about having a gimick; it's about having a text field the user can edit that won't take up unnecessary space, but will show all the text in it.

Though if someone comes up with another way to approach the problem I'm open to that too.


I've modified the code a little because it was acting a little odd. I changed it to activate on keyup, because it wouldn't take into consideration the character that was just typed.

resizeIt = function() {
  var str = $('iso_address').value;
  var cols = $('iso_address').cols;
  var linecount = 0;

  $A(str.split("\n")).each(function(l) {
    linecount += 1 + Math.floor(l.length / cols); // Take into account long lines
  })

  $('iso_address').rows = linecount;
};
By : Mike


Answers

Facebook does it, when you write on people's walls, but only resizes vertically.

Horizontal resize strikes me as being a mess, due to word-wrap, long lines, and so on, but vertical resize seems to be pretty safe and nice.

None of the Facebook-using-newbies I know have ever mentioned anything about it or been confused. I'd use this as anecdotal evidence to say 'go ahead, implement it'.

Some JavaScript code to do it, using Prototype (because that's what I'm familiar with):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script src="http://www.google.com/jsapi"></script>
        <script language="javascript">
            google.load('prototype', '1.6.0.2');
        </script>
    </head>

    <body>
        <textarea id="text-area" rows="1" cols="50"></textarea>

        <script type="text/javascript" language="javascript">
            resizeIt = function() {
              var str = $('text-area').value;
              var cols = $('text-area').cols;

              var linecount = 0;
              $A(str.split("\n")).each( function(l) {
                  linecount += Math.ceil( l.length / cols ); // Take into account long lines
              })
              $('text-area').rows = linecount + 1;
            };

            // You could attach to keyUp, etc. if keydown doesn't work
            Event.observe('text-area', 'keydown', resizeIt );

            resizeIt(); //Initial on load
        </script>
    </body>
</html>

PS: Obviously this JavaScript code is very naive and not well tested, and you probably don't want to use it on textboxes with novels in them, but you get the general idea.



Probably the shortest solution:

jQuery(document).ready(function(){
    jQuery("#textArea").on("keydown keyup", function(){
        this.style.height = "1px";
        this.style.height = (this.scrollHeight) + "px"; 
    });
});

This way you don't need any hidden divs or anything like that.

Note: you might have to play with this.style.height = (this.scrollHeight) + "px"; depending on how you style the textarea (line-height, padding and that kind of stuff).



My solution not using jQuery (because sometimes they don't have to be the same thing) is below. Though it was only tested in Internet Explorer 7, so the community can point out all the reasons this is wrong:

textarea.onkeyup = function () { this.style.height = this.scrollHeight + 'px'; }

So far I really like how it's working, and I don't care about other browsers, so I'll probably apply it to all my textareas:

// Make all textareas auto-resize vertically
var textareas = document.getElementsByTagName('textarea');

for (i = 0; i<textareas.length; i++)
{
    // Retain textarea's starting height as its minimum height
    textareas[i].minHeight = textareas[i].offsetHeight;

    textareas[i].onkeyup = function () {
        this.style.height = Math.max(this.scrollHeight, this.minHeight) + 'px';
    }
    textareas[i].onkeyup(); // Trigger once to set initial height
}


This video can help you solving your question :)
By: admin