Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a textarea with auto-resize

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:

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 )     }; } 
like image 391
DisgruntledGoat Avatar asked Jan 17 '09 22:01

DisgruntledGoat


People also ask

How do I automatically resize textarea?

# Auto Resize a `<textarea>` with an `autosize` Attribute First, a regular `<textarea>`. <textarea>Will NOT auto resize. </textarea> Now add an attribute to tell the element to automatically resize on input, i.e. `<textarea autosize>`. <textarea autosize>Will auto resize.

How do you make a textbox resizable?

Resize a text box Select the text box. Select one of the handles and drag until the text box is the size you want.

How do I make textarea draggable?

All you need to do is define draggable=true in your element and code the relevant ondragstart and ondragend logic. This works with both vanilla JS and frameworks like React.


2 Answers

A COMPLETE YET SIMPLE SOLUTION

Updated 2020-05-14 (Improved browser support for mobiles and tablets)

The following code will work:

  • On key input.
  • With pasted text (right click & ctrl+v).
  • With cut text (right click & ctrl+x).
  • With pre-loaded text.
  • With all textarea's (multiline textbox's) site wide.
  • With Firefox (v31-67 tested).
  • With Chrome (v37-74 tested).
  • With IE (v9-v11 tested).
  • With Edge (v14-v18 tested).
  • With IOS Safari.
  • With Android Browser.
  • With JavaScript strict mode.
  • Is w3c validated.
  • And is streamlined and efficient.

OPTION 1 (With jQuery)

This option requires jQuery and has been tested and is working with 1.7.2 - 3.6

Simple (Add this jquery code to your master script file and forget about it.)

$("textarea").each(function () {   this.setAttribute("style", "height:" + (this.scrollHeight) + "px;overflow-y:hidden;"); }).on("input", function () {   this.style.height = "auto";   this.style.height = (this.scrollHeight) + "px"; });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This javascript should now add better support for IOS browsers and Android browsers.</textarea> <textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


OPTION 2 (Pure JavaScript)

Simple (Add this JavaScript to your master script file and forget about it.)

const tx = document.getElementsByTagName("textarea"); for (let i = 0; i < tx.length; i++) {   tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;");   tx[i].addEventListener("input", OnInput, false); }  function OnInput() {   this.style.height = "auto";   this.style.height = (this.scrollHeight) + "px"; }
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea> <textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


OPTION 3 (jQuery Extension)

Useful if you want to apply further chaining to the textareas you want to be auto-sized.

jQuery.fn.extend({   autoHeight: function () {     function autoHeight_(element) {       return jQuery(element)         .css({ "height": "auto", "overflow-y": "hidden" })         .height(element.scrollHeight);     }     return this.each(function() {       autoHeight_(this).on("input", function() {         autoHeight_(this);       });     });   } }); 

Invoke with $("textarea").autoHeight()


UPDATING TEXTAREA VIA JAVASCRIPT

When injecting content into a textarea via JavaScript append the following code to invoke the function in option 1.

$("textarea").trigger("input"); 

PRESET TEXTAREA HEIGHT

To fix the initial height of the textarea you will need to add an additional condition:

const txHeight = 16; const tx = document.getElementsByTagName("textarea");  for (let i = 0; i < tx.length; i++) {   if (tx[i].value == '') {     tx[i].setAttribute("style", "height:" + txHeight + "px;overflow-y:hidden;");   } else {     tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;");   }   tx[i].addEventListener("input", OnInput, false); }  function OnInput(e) {   this.style.height = "auto";   this.style.height = (this.scrollHeight) + "px"; }
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea> <textarea placeholder="Type, paste, cut text here..."></textarea>
like image 96
DreamTeK Avatar answered Oct 04 '22 23:10

DreamTeK


This works for me (Firefox 3.6/4.0 and Chrome 10/11):

var observe;  if (window.attachEvent) {      observe = function (element, event, handler) {          element.attachEvent('on'+event, handler);      };  }  else {      observe = function (element, event, handler) {          element.addEventListener(event, handler, false);      };  }  function init () {      var text = document.getElementById('text');      function resize () {          text.style.height = 'auto';          text.style.height = text.scrollHeight+'px';      }      /* 0-timeout to get the already changed text */      function delayedResize () {          window.setTimeout(resize, 0);      }      observe(text, 'change',  resize);      observe(text, 'cut',     delayedResize);      observe(text, 'paste',   delayedResize);      observe(text, 'drop',    delayedResize);      observe(text, 'keydown', delayedResize);        text.focus();      text.select();      resize();  }
textarea {      border: 0 none white;      overflow: hidden;      padding: 0;      outline: none;      background-color: #D0D0D0;  }
<body onload="init();">  <textarea rows="1" style="height:1em;" id="text"></textarea>  </body>

If you want try it on jsfiddle It starts with a single line and grows only the exact amount necessary. It is ok for a single textarea, but I wanted to write something where I would have many many many such textareas (about as much as one would normally have lines in a large text document). In that case it is really slow. (In Firefox it's insanely slow.) So I really would like an approach that uses pure CSS. This would be possible with contenteditable, but I want it to be plaintext-only.

like image 29
panzi Avatar answered Oct 05 '22 01:10

panzi