テキスト領域の変更検出


132

JavaScriptを使用してtextareaの変更イベントを検出するにはどうすればよいですか?
入力時に使用可能な文字数を検出しようとしています。

onchangeイベントを使用してみましたが、フォーカスが外れたときにのみ起動するようです。

回答:


97

あなたは使用する必要がありますonkeyup し、 onchangeこのために。onchangeはコンテキストメニューの貼り付けを防ぎ、onkeyupはすべてのキーストロークに対して起動します。

コードサンプルについては、textAreamaxlengthを課す方法に関する私の回答を参照してください。


3
Joshがすでに言ったことを強調したかったのですが、これにはkeydownではなくkeyupを使用する必要があります。keydownは実際にtextareaに変更が加えられる前に呼び出されるように見えるため、間違った長さを使用します(そしてあなたがどのようにしているかを本当に知っています:入力または削除である可能性があり、テキストが選択されている可能性があります。
brianmearns 2012

65
ここで-1を与えています、ごめんなさい! onkeyup入力検出のひどいイベントです。oninputand onpropertychange(IEサポート用)を使用します。
アンディE

6
「唯一」の問題はさonchangeませコンテキストメニューカット/ペーストが発生したときに発生します。
トム

4
onkeydownとsetTimeoutを使用する方が応答性がはるかに高いため、キーが解放されるのを待つのではなく、即座に変更を検出できます。カットアンドペーストもキャッチする必要がある場合は、カットアンドペーストイベントを使用します。
Kevin B

1
警告:onkeyupは問題を引き起こす可能性があります。例:入力内容が変更された場合にのみ何かを行う必要があるとしましょう。キーアップが入力を変更すると想定する場合、それは真ではありません。入力に焦点を当てます。「タブ」を使用して次のフィールドに移動します。ここで、「shift + tab」を使用して入力に戻ります。キーアップはまだ発生しますが、入力は実際にはユーザーによって変更されませんでした。
ジグマンデル2015

117

それは2012年、ポストPCの時代が到来した今でも、これと同じくらい基本的なものと格闘する必要があります。これは非常に単純なはずです。

その夢が実現するような時まで、これを実行する最良の方法は、クロスブラウザです。イベントの組み合わせを使用してinputonpropertychange、次のようにします。

var area = container.querySelector('textarea');
if (area.addEventListener) {
  area.addEventListener('input', function() {
    // event handling code for sane browsers
  }, false);
} else if (area.attachEvent) {
  area.attachEvent('onpropertychange', function() {
    // IE-specific event handling code
  });
}

inputイベントは、の世話をIE9 +、FF、クローム、オペラとSafari、とonpropertychangeの世話をIE8(それはまた、IE6で動作し、7が、いくつかのバグがあります)。

inputおよびを使用する利点onpropertychangeは、(CtrlまたはShiftキーを押すときなど)不必要に起動しないことです。したがって、textareaの内容が変更されたときに比較的コストのかかる操作を実行したい場合は、これが適しています

これでIEはいつものように、これをサポートするという半端な仕事をします。テキストエリアから文字が削除されてもIE inputonpropertychange起動したり、起動したりすることはありません。したがって、IEで文字の削除を処理する必要がある場合は、を使用します(ユーザーがキーを押し続けても1回だけ起動されるため、/ を使用するのではなく)。keypresskeyupkeydown

出典:http : //www.alistapart.com/articles/expanding-text-areas-made-elegant/

編集:コメントで正しく指摘されているように、上記のソリューションでさえ完璧でaddEventListenerないようです。textareaにプロパティが存在しても、正常なブラウザで作業しているとは限りませ。同様に、attachEventプロパティの存在はIEを意味しませ。コードを完全に気密にしたい場合は、変更することを検討してください。ポインタについては、Tim Downのコメントを参照してください。


1
これが最良のアプローチです。ここでの推論は好きではありません(ブラウザのサポートaddEventListenerinputイベントのサポートを意味するものではありません)。特徴の検出はより良いでしょう。これについては、このブログ投稿を参照してください。
Tim Down

これについてはティムに完全に同意します。oninputこれは私たちがこれを行うべき方法ですが、おそらくaddEventListenerあなたはブラウザサポートのテストとして使用すべきではありません。いずれにしても+1。
ベンD

1
同意しない。入力はIE9を処理しない。残念ながら、contextmenuを介した切り取り/貼り付けも入力され、バックスペースも同様です。私はテストする気にはなりませんでしたが、IE10 +がその問題を修正したという賭けにはお金をかけませんでした。
Stefan Steiger

1
@StefanSteigerは、私の答えがkeypressIE9でそのケースを処理するためにイベントを使用することも提案している理由です(そしておそらくそれ以降のバージョンも)。
Vicky Chijwani

inputイベントハンドラーは、.oninputobjectプロパティを実装することによっても定義できます。
ハンドル

20
  • Google-Chromeの場合、oninputで十分です(バージョン22.0.1229.94 mのWindows 7でテスト済み)。
  • IE 9の場合、oninputは、contextmenuとバックスペースによるカットを除くすべてをキャッチします。
  • IE 8では、oninputに加えて、貼り付けをキャッチするためにonpropertychangeが必要です。
  • IE 9 + 8の場合、バックスペースをキャッチするにはonkeyupが必要です。
  • IE 9 + 8の場合、onmousemoveは、contextmenuを使用して切断を検出する唯一の方法です

Firefoxではテストされていません。

    var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...

    function SuperDuperFunction() {
        // DoSomething
    }


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
        if(isIE) // For Chrome, oninput works as expected
            SuperDuperFunction();
    }

<textarea id="taSource"
          class="taSplitted"
          rows="4"
          cols="50"
          oninput="SuperDuperFunction();"
          onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>

1
素晴らしい関数名:)
JonasGröger

8

これがあなたの質問ではないことはわかっていますが、役に立つと思いました。特定のアプリケーションでは、キーが押されるたびに変更関数を起動しないと便利です。これは、次のようなもので実現できます。

var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);

text.onkeyup = function(){
var callcount = 0;
    var action = function(){
        alert('changed');
    }
    var delayAction = function(action, time){
        var expectcallcount = callcount;
        var delay = function(){
            if(callcount == expectcallcount){
                action();
            }
        }
        setTimeout(delay, time);
    }
    return function(eventtrigger){
        ++callcount;
        delayAction(action, 1200);
    }
}();

これは、より新しいイベントが特定の遅延期間内に発生したかどうかをテストすることで機能します。幸運を!


1
「スロットリング」の遅延アクションの+1!私のアプリでも似たようなものを使用しています。
psulek 14

7

この質問はJavaScriptに固有のものであることは知っていますが、現在のすべてのブラウザーでtextareaが変更されたときに常に検出するための適切でクリーンな方法はないようです。私はjqueryがそれを処理してくれることを学びました。テキスト領域へのコンテキストメニューの変更も処理します。入力タイプに関係なく、同じ構文が使用されます。

    $('div.lawyerList').on('change','textarea',function(){
      // Change occurred so count chars...
    });

または

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });

4
変更イベントは、単純なJSよりもjQueryと整合性がとれていないことがわかりました。私はjQueryを使用しましたがbind("input cut paste"...、それは魅力のように機能します-入力、キーボードまたはコンテキストメニューを使用したカットアンドペースト; テキストのドラッグ/ドロップもできます。
Lawrence Dol、2013

2
残念ながら、FFはのchangeイベントを起動しませんtextarea
dma_k 2014

4

textareaの変更に関するイベントをリッスンし、必要に応じて変更を行うことができます。一例を示します。

(() => {
	const textArea = document.getElementById('my_text_area');
  textArea.addEventListener('input', () => {
    let textLn =  textArea.value.length;
    if(textLn >= 100) {
      textArea.style.fontSize = '10pt';
    }

  })
})()
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>


1

HTML5の入力検証/パターン属性と組み合わせる場合は、キーアップで十分です。したがって、入力を検証して.checkValidity()ステータスに基づいて動作するパターン(正規表現)を作成します。以下のようなものが機能する可能性があります。あなたの場合、あなたは正規表現が長さに一致することを望みます。私のソリューションはここでオンラインで使用/デモ可能です

<input type="text" pattern="[a-zA-Z]+" id="my-input">

var myInput = document.getElementById = "my-input";

myInput.addEventListener("keyup", function(){
  if(!this.checkValidity() || !this.value){
    submitButton.disabled = true;
  } else {
    submitButton.disabled = false;
  }
});

0

私がjqueryを使用せずに単一のtextareaだけでIE 11に使用したコード:

JavaScript:

// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{ 
    if (internalChange == 1)
    {
        internalChange= 0;
        return;
    }
    internalChange= 1;
    // <form> and <textarea> are the ID's of your form and textarea objects
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}

およびhtml:

<TEXTAREA onpropertychange='limit_char(5)' ...

-1

これを試してみてください。シンプルで、2016年なのでほとんどのブラウザで動作するはずです。

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div>

function check(){
    var string = document.getElementById("url").value
    var left = 15 - string.length;
    document.getElementById("spn").innerHTML = left;
}

したがって、IDでURLを取得していますが、コードには表示されません。
アブソリュート

-8

あなたができる最善のことは、与えられた時間に呼び出される関数を設定することと、この関数があなたのtextareaの内容をチェックすることです。

self.setInterval('checkTextAreaValue()', 50);

7
投票は非常に悪い考えです。パフォーマンスを破壊するだけです。また、他の投稿と同様に、いくつかの解決策が存在します
Pier-Olivier Thibault 2012

2
これは21世紀です。ブラウザは、50ミリ秒ごとに文字列比較を処理するのに問題があってはなりません。セレクターをキャッシュしてください。これは完全に許容できるソリューションです。
null入力可能性2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.