views:

9200

answers:

4

There was another thread about this, which I've tried. But there is one problem: the textarea doesn't shrink if you delete the content. I can't find any way to shrink it to the correct size - the clientHeight value comes back as the full size of the textarea, not its contents.

The code from that page is below. I'd appreciate any help or pointers.

function FitToContent(id, maxHeight)
{
   var text = id && id.style ? id : document.getElementById(id);
   if ( !text )
      return;

   var adjustedHeight = text.clientHeight;
   if ( !maxHeight || maxHeight > adjustedHeight )
   {
      adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
      if ( maxHeight )
         adjustedHeight = Math.min(maxHeight, adjustedHeight);
      if ( adjustedHeight > text.clientHeight )
         text.style.height = adjustedHeight + "px";
   }
}

window.onload = function() {
    document.getElementById("ta").onkeyup = function() {
      FitToContent( this, 500 )
    };
}
A: 

if you need just something similar to this site's resizeable textarea check this thread.

perfectDay
Nah, I want it to be automatic, rather than letting the user expand/contract.
DisgruntledGoat
+5  A: 

You're using the higher value of the current clientHeight and the content scrollHeight. When you make the scrollHeight smaller by removing content, the calculated area can't get smaller because the clientHeight, previously set by style.height, is holding it open. You could instead take a max() of scrollHeight and a minimum height value you have predefined or calculated from textarea.rows.

In general you probably shouldn't really rely on scrollHeight on form controls. Apart from scrollHeight being traditionally less widely-supported than some of the other IE extensions, HTML/CSS says nothing about how form controls are implemented internally and you aren't guaranteed scrollHeight will be anything meaningful. (Traditionally some browsers have used OS widgets for the task, making CSS and DOM interaction on their internals impossible.) At least sniff for scrollHeight/clientHeight's existance before trying to enable the effect.

Another possible alternative approach to avoid the issue if it's important that it work more widely might be to use a hidden div sized to the same width as the textarea, and set in the same font. On keyup, you copy the text from the textarea to a text node in hidden div (remembering to replace '\n' with a line break, and escape '<'/'&' properly if you're using innerHTML). Then simply measuring the div's offsetHeight will give you the height you need.

bobince
Voted up for your last paragraph. I have implemented a similar solution in the past and it worked very well.
eyelidlessness
Which browsers are supposed to have problems with `scrollHeight` for textareas? Works fine with current versions of IE, Firefox and Opera...
Christoph
The only one I have to hand is Konqueror, which returns the clientHeight as scrollHeight. This is a behaviour you can expect unless the browser applies the CSS box model to the internals of widgets, something they haven't always done and the standard doesn't say they have to.
bobince
A: 

I have tested script in common browsers, and it failed in Chrome and Safari. It is because of constantly updatable scrollHeight variable.

I have applied DisgruntledGoat script using jQuery and added chrome fix

function fitToContent(/* JQuery */text, /* Number */maxHeight) {
 var adjustedHeight = text.height();
 var relative_error = parseInt(text.attr('relative_error'));
 if (!maxHeight || maxHeight > adjustedHeight) {
  adjustedHeight = Math.max(text[0].scrollHeight, adjustedHeight);
  if (maxHeight)
   adjustedHeight = Math.min(maxHeight, adjustedHeight);
  if ((adjustedHeight - relative_error) > text.height()) {
   text.css('height', (adjustedHeight - relative_error) + "px");
   // chrome fix
   if (text[0].scrollHeight != adjustedHeight) {
    var relative = text[0].scrollHeight - adjustedHeight;
    if (relative_error != relative) {
     text.attr('relative_error', relative + relative_error);
    }
   }
  }
 }
}

function autoResizeText(/* Number */maxHeight) {
 var resize = function() {
  fitToContent($(this), maxHeight);
 };
 $("textarea").attr('relative_error', 0);
 $("textarea").each(resize);
 $("textarea").keyup(resize).keydown(resize);
}
A: 

If scrollHeight could be trusted, then:

textarea.onkeyup=function() {
  this.style.height='';
  this.rows=this.value.split('\n').length;
  this.style.height=this.scrollHeight+'px';
}
rrr