プロトタイプを使用してテキストエリアを自動サイズ調整する方法は?


121

現在、勤務先の会社の社内販売アプリケーションに取り組んでおり、ユーザーが配送先住所を変更できるフォームを持っています。

メインアドレスの詳細に使用しているtextareaがその中のテキストの領域を占めるだけで、テキストが変更された場合は自動的にサイズが変更される場合は、もっと見栄えがよくなると思います。

これが現在のスクリーンショットです。

ISOアドレス

何か案は?


@クリス

良い点ですが、サイズを変更する理由があります。私はそれが占める領域がそれに含まれる情報の領域であることを望みます。スクリーンショットからわかるように、固定テキスト領域がある場合、垂直方向のスペースがかなり大きくなります。

フォントを減らすことはできますが、大きくて読みやすいアドレスにする必要があります。テキスト領域のサイズを小さくできるようになりましたが、3行または4行(1行は5行)の住所行がある人には問題があります。ユーザーがスクロールバーを使用する必要があるのは、大したことではありません。

私はもう少し具体的であるべきだと思います。私は垂直方向のサイズ変更をした後、幅はそれほど重要ではありません。これで発生する唯一の問題は、ウィンドウの幅が小さすぎると(スクリーンショットで確認できるように)、ISO番号(大きな「1」)がアドレスの下にプッシュされることです。

それはギミックを持つことではありません。それは、ユーザーが編集できるテキストフィールドを用意することで、不要なスペースを取りませんが、その中にすべてのテキストが表示されます。

誰かが問題に取り組む別の方法を思いついたとしても、私もそれを受け入れます。


コードが少し変わっているため、コードを少し変更しました。入力した文字が考慮されないため、キーアップ時にアクティブになるように変更しました。

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;
};

職場でこれを見ることができるデモサイトを作成できますか?
EinarÓlafsson2012

3
このプラグインは良いようですjacklmoore.com/autosize
Gaurav Shah

JQueryのバージョンはありますか?JQueryでTextAreaの列と行にアクセスする方法は?
Zach

ほぼ同じですが、テキストが削除されたときに小さくなるべき明確な要件を持つ:stackoverflow.com/questions/454202/...
チロSantilli郝海东冠状病六四事件法轮功

回答:


75

Facebookは、あなたが人々の壁に書いたときにそれを行いますが、垂直方向にのみサイズ変更します。

水平方向のサイズ変更は、ワードラップや長い行などが原因で混乱しているように見えますが、垂直方向のサイズ変更は非常に安全で優れているようです。

私が知っているFacebookを使用する初心者は、これについて何も言及したことも、混乱したこともありません。これを事例証拠として使用して、「先に進んで実装してください」と言います。

プロトタイプを使用してそれを行うためのいくつかのJavaScriptコード(これは私がよく知っているためです):

<!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:このJavaScriptコードは非常にナイーブで十分にテストされていないのは明らかです。おそらく、小説が含まれているテキストボックスで使用したくないでしょうが、一般的なアイデアは得られます。


2
これは、ブラウザが任意の文字で壊れることを想定していますが、これは正しくありません。それをお試しください<textarea cols='5'>0 12345 12345 0</textarea>。(私はほぼ同じ実装を作成し、1か月使用するまでこれを理解しませんでした。)空白行の場合も失敗します。
st-boost

このためのjQueryバージョンはありますか?
emeraldhieu 2015

$ A(str.split( "\ n"))のバックスラッシュには別のバックスラッシュが必要です。(上記の回答の私の編集は、何らかの理由で存続しませんでした。)
ガーソン

67

これらの回答のいくつかの改良点の1つは、CSSにさらに多くの作業を行わせることです。

基本的なルートは次のようです:

  1. textareaおよび非表示を保持するコンテナ要素を作成しますdiv
  2. JavaScriptを使用して、維持textarea「で同期の内容divs」を
  3. ブラウザにそのdivの高さを計算させる
  4. ブラウザは非表示のレンダリング/サイズ変更を処理するため、の高さをdiv明示的に設定することは避けtextareaます。

document.addEventListener('DOMContentLoaded', () => {
    textArea.addEventListener('change', autosize, false)
    textArea.addEventListener('keydown', autosize, false)
    textArea.addEventListener('keyup', autosize, false)
    autosize()
}, false)

function autosize() {
    // Copy textarea contents to div browser will calculate correct height
    // of copy, which will make overall container taller, which will make
    // textarea taller.
    textCopy.innerHTML = textArea.value.replace(/\n/g, '<br/>')
}
html, body, textarea {
    font-family: sans-serif;
    font-size: 14px;
}

.textarea-container {
    position: relative;
}

.textarea-container > div, .textarea-container > textarea {
    word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
    box-sizing: border-box;
    padding: 2px;
    width: 100%;
}

.textarea-container > textarea {
    overflow: hidden;
    position: absolute;
    height: 100%;
}

.textarea-container > div {
    padding-bottom: 1.5em; /* A bit more than one additional line of text. */ 
    visibility: hidden;
}
<div class="textarea-container">
    <textarea id="textArea"></textarea>
    <div id="textCopy"></div>
</div>


5
これは素晴らしいソリューションです!唯一の注意点は、ボックスサイズをサポートしない(IE <7)ブラウザーでは幅が適切に計算されないため、精度がいくらか失われますが、最後に行のスペースに相当する値を残すと、あなたはまだ大丈夫なはずです。シンプルさのために間違いなく大好きです。
Antonio Salazar Cardozo

4
私はこのソリューションをスタンドアロンとして実装する際に自由を取り、マークアップやスタイル設定を必要とせず、jQueryプラグインを簡単に使用できるようにしました。xion.io/jQuery.xarea誰かがそれを使用する可能性がある場合:)
Xion

2
textCopyを非表示に設定すると、非表示のdivがマークアップのスペースを占めるため、textCopyの内容が大きくなると、最終的にページの全長に沿ってスクロールバーが表示されます...
topwik

1
これに対するもう1つの素晴らしい調整。var text = $("#textArea").val().replace(/\n/g, '<br/>') + '&nbsp;';非表示のdivがnbspに確実にラップするため、textareaの終わりにある空の新しい行から空でない行に移動するときに、ぎくしゃくした動作にならないようにします。
知らない

1
「&nbsp;」を追加する際の素晴らしい呼び出し 新しい行に最初の文字を追加するときのサイズの突然の増加を取り除くために-私にはこれなしで壊れています-これは答えに追加する必要があります!
davnicwil 2015

40

次に、textareaを自動サイズ調整する別の方法を示します。

  • 行の高さの代わりにピクセルの高さを使用:プロポーショナルフォントが使用されている場合の行の折り返しのより正確な処理。
  • IDまたは要素のいずれかを入力として受け入れます
  • オプションの最大高さパラメーターを受け入れます。テキスト領域が特定のサイズを超えて大きくならないようにしたい場合に便利です(すべてを画面上に維持したり、レイアウトの破損を回避したりするなど)。
  • Firefox 3およびInternet Explorer 6でテスト済み

コード:( プレーンバニラJavaScript)

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

   /* Accounts for rows being deleted, pixel value may need adjusting */
   if (text.clientHeight == text.scrollHeight) {
      text.style.height = "30px";
   }

   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";
   }
}

デモ: (jQueryを使用し、今入力しているテキスト領域をターゲットにします。Firebugがインストールされている場合は、両方のサンプルをコンソールに貼り付け、このページでテストします)

$("#post-text").keyup(function()
{
   FitToContent(this, document.documentElement.clientHeight)
});

@SMB-おそらく実装するのはそれほど難しくありません。別の条件を追加してください
Jason

@Jason:ボックス内のテキストは、それを埋める、しないclientHeightscrollHeight、あなたのテキストエリアの成長だけでなく、縮小したい場合は、このメソッドを使用することはできませんので、同じです。
Brant Bobby、

単にそれが縮むようにするには、あなただけの6行目の前にこのコードを追加する必要がありますif (text.clientHeight == text.scrollHeight) text.style.height = "20px";
Gapipro

14

おそらく最も短い解決策:

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

この方法では、隠されたdivなどは必要ありません。

注:this.style.height = (this.scrollHeight) + "px";テキストエリアのスタイル方法(行の高さ、パディングなど)によっては、操作が必要になる場合があります。


スクロールバーの点滅を気にしない場合の最良の解決策。
cfillol 2014

キーアップイベントのみをキャッチすれば十分です。そう思いませんか?
cfillol 2014

2
スクロールバーの点滅を回避するには、textareaオーバーフロープロパティを「非表示」に設定します。
cfillol 2014

keyup十分かもしれませんが、よくわかりません。私はそれを理解できて、他のことをやめたのでとても幸せでした。
Eduard Luca

なぜthis.style.height = "1px";を追加したのか、まだ学習中です。またはthis.style.height = "auto"; 前。この行を追加しない場合、コンテンツを削除してもtextareaのサイズは変更されません。誰かが説明してもいいですか?
Balasubramani M

8

これがプロトタイプですは、テキストエリアの列数に依存しないテキストエリアのサイズ変更のバージョンです。CSSを使用してテキスト領域を制御したり、可変幅のテキスト領域を使用したりできるため、これは優れた手法です。さらに、このバージョンでは残りの文字数が表示されます。要求されていませんが、これはかなり便利な機能であり、不要な場合は簡単に削除できます。

//inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
if (window.Widget == undefined) window.Widget = {}; 

Widget.Textarea = Class.create({
  initialize: function(textarea, options)
  {
    this.textarea = $(textarea);
    this.options = $H({
      'min_height' : 30,
      'max_length' : 400
    }).update(options);

    this.textarea.observe('keyup', this.refresh.bind(this));

    this._shadow = new Element('div').setStyle({
      lineHeight : this.textarea.getStyle('lineHeight'),
      fontSize : this.textarea.getStyle('fontSize'),
      fontFamily : this.textarea.getStyle('fontFamily'),
      position : 'absolute',
      top: '-10000px',
      left: '-10000px',
      width: this.textarea.getWidth() + 'px'
    });
    this.textarea.insert({ after: this._shadow });

    this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
    this.textarea.insert({after: this._remainingCharacters});  
    this.refresh();  
  },

  refresh: function()
  { 
    this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
    this.textarea.setStyle({
      height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
    });

    var remaining = this.options.get('max_length') - $F(this.textarea).length;
    this._remainingCharacters.update(Math.abs(remaining)  + ' characters ' + (remaining > 0 ? 'remaining' : 'over the limit'));
  }
});

を呼び出してウィジェットを作成しますnew Widget.Textarea('element_id')。デフォルトのオプションは、オブジェクトなどとして渡すことで上書きできますnew Widget.Textarea('element_id', { max_length: 600, min_height: 50})。それをページ上のすべてのテキストエリアに作成したい場合は、次のようにします。

Event.observe(window, 'load', function() {
  $$('textarea').each(function(textarea) {
    new Widget.Textarea(textarea);
  });   
});

7

ここに解決策がありJQueryます:

$(document).ready(function() {
    var $abc = $("#abc");
    $abc.css("height", $abc.attr("scrollHeight"));
})

abcですteaxtarea


5

以下のリンクを確認してください:http : //james.padolsey.com/javascript/jquery-plugin-autoresize/

$(document).ready(function () {
    $('.ExpandableTextCSS').autoResize({
        // On resize:
        onResize: function () {
            $(this).css({ opacity: 0.8 });
        },
        // After resize:
        animateCallback: function () {
            $(this).css({ opacity: 1 });
        },
        // Quite slow animation:
        animateDuration: 300,
        // More extra space:
        extraSpace:20,
        //Textarea height limit
        limit:10
    });
});


3

これを再検討するだけで、私はそれを少し整頓しました(ただし、Prototype / JavaScriptのボトルがいっぱいの人は改善を提案できますか?)。

var TextAreaResize = Class.create();
TextAreaResize.prototype = {
  initialize: function(element, options) {
    element = $(element);
    this.element = element;

    this.options = Object.extend(
      {},
      options || {});

    Event.observe(this.element, 'keyup',
      this.onKeyUp.bindAsEventListener(this));
    this.onKeyUp();
  },

  onKeyUp: function() {
    // We need this variable because "this" changes in the scope of the
    // function below.
    var cols = this.element.cols;

    var linecount = 0;
    $A(this.element.value.split("\n")).each(function(l) {
      // We take long lines into account via the cols divide.
      linecount += 1 + Math.floor(l.length / cols);
    })

    this.element.rows = linecount;
  }
}

それだけで呼び出す:

new TextAreaResize('textarea_id_name_here');

3

私はかなり簡単なものを作りました。まず、TextAreaをDIVに入れます。次に、readyこのスクリプトに関数を呼び出しました。

<div id="divTable">
  <textarea ID="txt" Rows="1" TextMode="MultiLine" />
</div>

$(document).ready(function () {
  var heightTextArea = $('#txt').height();
  var divTable = document.getElementById('divTable');
  $('#txt').attr('rows', parseInt(parseInt(divTable .style.height) / parseInt(altoFila)));
});

シンプル。これは、レンダリングされたdivの最大の高さであり、1行の1つのTextAreaの高さで割ったものです。


2

私はこの機能を自分で必要としていましたが、ここからの機能はどれも必要なように機能しませんでした。

そこで、Orionのコードを使用して変更しました。

破壊時に小さすぎないように、最低の高さを追加しました。

function resizeIt( id, maxHeight, minHeight ) {
    var text = id && id.style ? id : document.getElementById(id);
    var str = text.value;
    var cols = text.cols;
    var linecount = 0;
    var arStr = str.split( "\n" );
    $(arStr).each(function(s) {
        linecount = linecount + 1 + Math.floor(arStr[s].length / cols); // take into account long lines
    });
    linecount++;
    linecount = Math.max(minHeight, linecount);
    linecount = Math.min(maxHeight, linecount);
    text.rows = linecount;
};

2

@memicalの答えのように。

しかし、私はいくつかの改善を見つけました。jQuery height()関数を使用できます。ただし、パディング上部とパディング下部のピクセルに注意してください。そうしないと、textareaの成長が速すぎます。

$(document).ready(function() {
  $textarea = $("#my-textarea");

  // There is some diff between scrollheight and height:
  //    padding-top and padding-bottom
  var diff = $textarea.prop("scrollHeight") - $textarea.height();
  $textarea.live("keyup", function() {
    var height = $textarea.prop("scrollHeight") - diff;
    $textarea.height(height);
  });
});

2

jQueryを使用しない私のソリューション(時々、同じものである必要がないため)は以下のとおりです。Internet Explorer 7でのみテストされているため、コミュニティはこれが間違っているすべての理由を指摘できます。

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

これまでのところ、私はそれがどのように機能するかを本当に気に入っており、他のブラウザは気にしないので、おそらくすべてのテキスト領域に適用します。

// 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
}

1

Jeremyが6月4日に投稿したPrototypeウィジェットの拡張機能を次に示します。

textareasで制限を使用している場合、ユーザーは文字を入力できなくなります。文字が残っているかどうかをチェックします。ユーザーがテキストをテキストエリアにコピーすると、テキストは最大で切り取られます。長さ:

/**
 * Prototype Widget: Textarea
 * Automatically resizes a textarea and displays the number of remaining chars
 * 
 * From: http://stackoverflow.com/questions/7477/autosizing-textarea
 * Inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
 */
if (window.Widget == undefined) window.Widget = {}; 

Widget.Textarea = Class.create({
  initialize: function(textarea, options){
    this.textarea = $(textarea);
    this.options = $H({
      'min_height' : 30,
      'max_length' : 400
    }).update(options);

    this.textarea.observe('keyup', this.refresh.bind(this));

    this._shadow = new Element('div').setStyle({
      lineHeight : this.textarea.getStyle('lineHeight'),
      fontSize : this.textarea.getStyle('fontSize'),
      fontFamily : this.textarea.getStyle('fontFamily'),
      position : 'absolute',
      top: '-10000px',
      left: '-10000px',
      width: this.textarea.getWidth() + 'px'
    });
    this.textarea.insert({ after: this._shadow });

    this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
    this.textarea.insert({after: this._remainingCharacters});  
    this.refresh();  
  },

  refresh: function(){ 
    this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
    this.textarea.setStyle({
      height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
    });

    // Keep the text/character count inside the limits:
    if($F(this.textarea).length > this.options.get('max_length')){
      text = $F(this.textarea).substring(0, this.options.get('max_length'));
        this.textarea.value = text;
        return false;
    }

    var remaining = this.options.get('max_length') - $F(this.textarea).length;
    this._remainingCharacters.update(Math.abs(remaining)  + ' characters remaining'));
  }
});

1

@memicalには、jQueryを使用してページロード時にテキストエリアの高さを設定するための素晴らしいソリューションがありましたが、私のアプリケーションでは、ユーザーがコンテンツを追加するにつれてテキストエリアの高さを増やしたいと考えました。memicalのソリューションを次のように構築しました。

$(document).ready(function() {
    var $textarea = $("p.body textarea");
    $textarea.css("height", ($textarea.attr("scrollHeight") + 20));
    $textarea.keyup(function(){
        var current_height = $textarea.css("height").replace("px", "")*1;
        if (current_height + 5 <= $textarea.attr("scrollHeight")) {
            $textarea.css("height", ($textarea.attr("scrollHeight") + 20));
        }
    });
});

あまり滑らかではありませんが、クライアント向けのアプリケーションでもないため、滑らかさは重要ではありません。(これがクライアント向けだったとしたら、おそらく自動サイズ変更jQueryプラグインを使用しただけでしょう。)


1

IEをコーディングしていて、この問題が発生している場合。IEには、100%CSSにする小さなトリックがあります。

<TEXTAREA style="overflow: visible;" cols="100" ....></TEXTAREA>

IEが無視するrows = "n"の値を指定することもできますが、他のブラウザが使用します。IEハックを実装するコーディングは本当に嫌いですが、これは非常に役立ちます。Quirksモードでのみ機能する可能性があります。


1

Internet Explorer、Safari、Chrome、Operaのユーザーは、CSSで行の高さの値を明示的に設定することを忘れないでください。次のように、すべてのテキストボックスの初期プロパティを設定するスタイルシートを作成します。

<style>
    TEXTAREA { line-height: 14px; font-size: 12px; font-family: arial }
</style>

1

これは私がjQueryで書いたばかりの関数です-あなたはそれをプロトタイプに移植できますに、jQueryの「活性」をサポートしていないため、Ajaxリクエストによって追加された要素は応答しません。

このバージョンは拡張するだけでなく、削除またはバックスペースを押すと縮小します。

このバージョンはjQuery 1.4.2に依存しています。

楽しい ;)

http://pastebin.com/SUKeBtnx

使用法:

$("#sometextarea").textareacontrol();

または(jQueryセレクタなど)

$("textarea").textareacontrol();

Internet Explorer 7 / Internet Explorer 8、Firefox 3.5、Chromeでテストされています。すべて正常に動作します。


1

ASP.NETを使用して、これを行うだけです。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Automatic Resize TextBox</title>
        <script type="text/javascript">
            function setHeight(txtarea) {
                txtarea.style.height = txtdesc.scrollHeight + "px";
            }
        </script>
    </head>

    <body>
        <form id="form1" runat="server">
            <asp:TextBox ID="txtarea" runat= "server" TextMode="MultiLine"  onkeyup="setHeight(this);" onkeydown="setHeight(this);" />
        </form>
    </body>
</html>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.