textareaの高さを自動調節するjQueryプラグイン。
textareaの入力内容の量・行数などに応じて,
textareaの要素の高さを自動的に増減・調節し,
タイピング中に自動的にタテに伸びたり縮んだりして,スクロールバーが表示されないようにする。
そのようなjQueryプラグイン「jQuery.autoHeightTextarea」の紹介と,サンプルコード。
HTMLファイル
sample.html
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>textareaの高さを自動調節するjQueryプラグインのサンプルコード</title> <script src="jquery-3.3.1.min.js"></script> <script src="jquery.auto_height_textarea.js"></script> </head> <body> <h1>textareaの高さを自動調節するjQueryプラグインのサンプル</h1> <br> <textarea id="ta" >ここに文章を入力します。行数を変えてみましょう。</textarea> <script> $(function(){ // テキストエリアの高さを自動調節 $("#ta").autoHeightTextarea({ // 初期の幅(指定必須) initial_width : "300px", // 初期の高さ(指定必須) initial_height : "30px", // 初期の高さを適用した後で,直後に高さの自動調節をするかどうか initial_height_auto : true, // 行高(指定必須) line_height : "20px" }); }); function log(s){ console.log(s); } </script> </body> </html>
jQueryプラグイン
jquery.auto_height_textarea.js
/* Textareaの高さを行数に応じて自動調節するjQueryプラグイン @author : id:SourceCode-Student ver0.1 : 2019/05/27 MIT License */ (function( $ ){ // ---------- 公開メソッド ---------- // jQueryオブジェクトのプロトタイプチェーンに,メソッドを登録する $.fn.autoHeightTextarea = function( obj ) { // 初期化 _init_textarea({ initial_width : obj.initial_width, initial_height : obj.initial_height, initial_height_auto : obj.initial_height_auto, line_height : obj.line_height, jq_elem : this // NOTE: // jQueryオブジェクトが渡るので,scrollHeightプロパティなどを // 直接読みだせない点に注意。(undefinedになる) // https://stackoverflow.com/questions/9392099/scrollheight-of-an-element-gives-undefined-value }); }; // ---------- 以下,非公開 ---------- // 要素の初期化 var _init_textarea = function( obj ){ // 設定を取り出し var jq_elem = obj.jq_elem; var initial_width = obj.initial_width; var initial_height = obj.initial_height; if( ! initial_height ){ // 指定し忘れると無限ループになるので initial_height = "20px"; } var initial_height_auto = obj.initial_height_auto; var line_height = obj.line_height; // 属性を初期化 jq_elem.css( "resize", "none" ); // 手動で高さを調節させない jq_elem.css( "width", initial_width ); jq_elem.css( "lineHeight", line_height ); jq_elem.height( initial_height ); // 初回自動調節の有無にかかわらず,指定は必須 //log( "offsetHeight = " + jq_elem[0].offsetHeight + ", scrollHeight = " + jq_elem[0].scrollHeight ); // 初回に高さを調節するか if( initial_height_auto ){ // NOTE: // いったんsetTimeoutして処理を切らないと, // CSSの値が反映されないので // offsetHeightなどの値がブラウザ上で未計算でundefinedになり, // 無限ループになってしまう。 setTimeout(function(){ // 0ミリ秒後の遅延実行 _adjust_textarea_height( jq_elem[0] ); }, 0 ); } // 入力イベントを登録 jq_elem.on( "input", _onTextareaInput ); }; // 入力イベント発生時のリスナ var _onTextareaInput = function( evt ){ // 対象要素 var elem = evt.target; //log( "elem = " + elem ); // 高さの調節を実行 _adjust_textarea_height( elem ); }; // あるtextarea要素に,縦方向のスクロールバーが表示されてしまっているかどうか var _textarea_showing_scroll_bar = function( elem ){ // NOTE: // // ・scrollHeight : // あふれた(overflowした)画面上に表示されていないコンテンツを含む // 要素の内容の高さ // // ・offsetHeight : // 要素の height,padding,border を足したピクセル単位の数値 //log( "elem.offsetHeight = " + elem.offsetHeight + ", elem.scrollHeight = " + elem.scrollHeight ); // 要素の見かけ上の高さよりも,コンテンツ全体の高さのほうが長かったら // スクロールバーが表示されていることになる。 return ( elem.offsetHeight < elem.scrollHeight ); } // ある要素の高さを調節実行する var _adjust_textarea_height = function( elem ){ // NOTE: // 引数には,jQueryオブジェクトではなく // DOM要素が渡る点に注意する。 // CSSの値が未計算ではないか? if( elem.offsetHeight && elem.scrollHeight ){ // 値がセットされているのでOK } else { // 無限ループを避けるために逃げる return false; } // NOTE: // これだけをやってもうまくいかない。・・・(★) // ENTERキーとBACKSPACEキーを交互に何度も押すと, // コンテンツの行数はそのままなのに,テキストエリアの高さだけが少しずつ増えてゆく。 // なので,反復法による微調節が不可欠。 //$( elem ).height( elem.scrollHeight ); //return false; // textarea内にスクロールバーが表示されてしまっている? if( _textarea_showing_scroll_bar( elem ) ) { // スクロールバーを消すために,要素を高くするべき // コンテンツの高さだけ,見かけも高くする $( elem ).height( elem.scrollHeight ); } else { // textarea内にスクロールバーは表示されていないが, // 要素が高すぎるので // 低くすべき // textarea内の行高を取得 var line_height = parseInt( $( elem ).css("lineHeight").split("px")[0], 10 ); // ちょっとずつ低くしてゆく var continue_flag = true; while( continue_flag ){ // 現在の要素の高さ var current_height = $( elem ).height(); // 1行低くする var new_height = current_height - line_height; $( elem ).height( new_height ); // 要素を低くしたせいで, // textarea内にスクロールバーが表示されてしまっている? if( _textarea_showing_scroll_bar( elem ) ) { // 要素の高さをコンテンツの高さに揃える $( elem ).height( elem.scrollHeight ); // SOLVED: 謎 // どうして初めからそうしないのか?↑ // なぜ,わざわざ1行ずつ減らしてるの?ワカラ~ン // →結果:上記(★)で理解しました。このwhileループは必須。 continue_flag = false; } } } }; // 参考資料 // 入力内容の量に応じたtextareaの自動サイズ変更(whileで反復調節) // https://qiita.com/YoshiyukiKato/items/507b8022e6df5e996a59 // 下記のコードはダメ。「lineHeight * 改行コードの個数」では,行が長く折り返した時に対応できない。 // textareaを改行に応じて自動で高さが変わるようにする方法 // https://qiita.com/ampersand/items/ceaa5066d44990d30df3 // jQueryプラグインの作り方の参考 // https://language-and-engineering.hatenablog.jp/entry/20121204/jQueryFakeTicTacToeJs })( jQuery );
参考
入力内容の量に応じたtextareaの自動サイズ変更
https://qiita.com/YoshiyukiKato/items/507b8022e6df5e996a59
- whileで反復調節
textareaを改行に応じて自動で高さが変わるようにする方法
https://qiita.com/ampersand/items/ceaa5066d44990d30df3
- このコードはダメ。「lineHeight * 改行コードの個数」では,行が長く折り返した時に対応できないから。
jQueryプラグインの作り方の参考
https://language-and-engineering.hatenablog.jp/entry/20121204/jQueryFakeTicTacToeJs