Autosizing Textarea (using Prototype)

Recently, I have been doing a lot of Model-View-Controller work in ASP.NET which has caused me to have to use some more "old school" style HTML controls, instead of the .Net Server-side Controls I am so used to.  I came along an interesting problem where I needed a text area which automatically changed it's height to fit all the text in without a horizontal scroll bar, much like Facebook does with it's wall.

I also wanted the Javascript to use the Javascript library for the event listening so I didn't need to worry about the event handler quirks of the various browsers (and becasue that's what I know).  I post the solution that worked for me in the interest of creative commons.

<!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;
  };
 
  Event.observe('text-area', 'keyup', resizeIt );
  resizeIt(); //initial on load
  </script>
</body>
</html>

If you have a textarea, with the wrap="off" attribute set, then its even easier. Just replace the script tage above with this one:

<script type="text/javascript" language="javascript">
        resizeIt = function() {
            $('text-area').rows = $A($('text-area').value.split("\n")).length + 1;
        };
        Event.observe('text-area', 'keyup', resizeIt);
        resizeIt(); //initial on load
    </script>

2 Comments

  1. Emoreth
    Mar 03, 2009 @ 17:42:12

    I tried your code and it have a gap on empty linebreaks, as well it only works for one textarea because it is ID hard coded. So i made some changes to correct the linebreak gap and avoid this hardcoding…
    I could be usefull

    resizeIt = function(evt) {
    var txArea = evt.element ? evt.element() : $(evt);

    var str = $F(txArea);
    var cols = txArea.readAttribute(‘cols’);

    var linecount = 0;
    $A(str.split(“\n”)).each( function(l)
    {
    linecount += l.length ? Math.ceil( l.length / cols ) : 1;
    });
    txArea.writeAttribute(‘rows’, linecount);
    };

    Event.observe(‘text-area’, ‘keyup’, resizeIt );
    resizeIt(‘text-area’); //initial on load

    Reply

  2. Meroal
    Mar 12, 2009 @ 14:16:04

    Awesome, thanks for that. Very handy indeed.

    Reply

Leave a Reply