JQueryを使用して、<input type =“ text”>へのすべての変更を(即座に)検出します


397

の値を<input type="text">変更するには、次のような多くの方法があります。

  • キープレス
  • コピーペースト
  • JavaScriptで変更
  • ブラウザまたはツールバーによって自動補完

JavaScript関数が変更されるたびに(現在の入力値を使用して)呼び出されるようにしたい。そして、入力がフォーカスを失ったときだけでなく、すぐに呼び出されたいです。

(jQueryを使用することが望ましい)すべてのブラウザーでこれを行うための最もクリーンで最も堅牢な方法を探しています。



回答:


352

このjQueryコードは、あらゆる要素に対する即時の変更をキャッチし、すべてのブラウザーで機能するはずです。

 $('.myElements').each(function() {
   var elem = $(this);

   // Save current value of element
   elem.data('oldVal', elem.val());

   // Look for changes in the value
   elem.bind("propertychange change click keyup input paste", function(event){
      // If value has changed...
      if (elem.data('oldVal') != elem.val()) {
       // Updated stored value
       elem.data('oldVal', elem.val());

       // Do action
       ....
     }
   });
 });

19
参考までinputに、HTML5イベントはすべての最新のブラウザーをカバーする必要があると思います(MDNリファレンス)。keyup残りはキャッチしますが、少し遅れます(inputキーを押すとトリガーされます)。propertychangeは独自のMSイベントであり、paste実際に必要かどうかはわかりません。
Jo Liss、2012

71
私が間違っているのか、それとも次のようなJavaScriptを介してテキストが変更されたときに処理されないのかdocument.getElementById('txtInput').value = 'some text';
MehmetAtaş12年

5
Mehmet、コードはJSを介して変更された値をキャッチするためのものではありません。
phatmann

12
@MehmetAtaşは部分的に正しいです。ここでのinputイベントの参照は、JavaScriptを介してコンテンツが変更されたときに発生しないことを示しています。ただし、イベント JSによる変更時に発生します(こちらを参照)。そのため、このコードはIEでJSを介してコンテンツが変更されたときに機能しますが、他のブラウザーでは機能しません。onpropertychange
Vicky Chijwani

2
propertychange、keyupなどの入力時にカスタムイベントをトリガーし、どこでも使用できます。
IvanIvković2013年

122

jQuery> = 1.9のリアルタイムの洗練されたソリューション

$("#input-id").on("change keyup paste", function(){
    dosomething();
})

「クリック」イベントも検出する場合は、次のようにします。

$("#input-id").on("change keyup paste click", function(){
    dosomething();
})

jQuery <= 1.4を使用している場合は、live代わりにを使用してくださいon


3
これには欠点があります。入力フィールドをタブキーのままにすると、コンテンツが編集されていなくても、キーアップイベントがスローされます。
Pawka、2014

2
datetimepickerが#input-idを満たしたときに検出する方法は?どのイベント(変更、貼り付け)も機能しません。
Pathros 2015年

これは素晴らしい!私はjquery 1.8.3で試してみましたが、うまくいきました。置き換える必要があるlivequery()コードがまだあるので、1.9.1にさえアップグレードできません。古いことは知っていますが、ウェブサイト全体もそうです。
Asle

参考:これらのイベントは、キーボードを使用して無効な日付を選択すると、空白の値で発生します。すなわち。2月30 stackoverflow.com/questions/48564568/...
Olmstov

107

残念ながら、私setIntervalは受賞したと思います:

<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>

たった1行のコードで、これは最もクリーンなソリューションです。また、すべてのさまざまなイベント/方法について心配する必要がないため、最も堅牢inputです。

この場合、「setInterval」を使用することの欠点は当てはまらないようです。

  • 100msのレイテンシー? 多くのアプリケーションでは、100msで十分高速です。
  • ブラウザーに負荷を追加しましたか? 一般に、ページに大量の重いsetIntervalsを追加することは好ましくありません。ただし、この特定のケースでは、追加されたページのロードは検出できません。
  • 多くの入力に対応していませんか? ほとんどのページには少数の入力しかありません。同じsetIntervalですべてを嗅ぐことができます。

21
これは、ニンテンドー3DSブラウザー(バージョン/1.7552.EU)を使用するときにフォームの入力フィールドへの変更を検出する唯一の方法のようです。
ヨハン

4
注:過負荷を緩和することができます。入力がフォーカスを取得したときにsetIntervalを開始し、入力がフォーカスを失ったときにclearIntervalを開始した場合
Tebe

10
常に実行する理由がない理由で、常に実行する100ms間隔を作成するのはなぜですか?人のイベント。それらを使用してください。
Gavin、

15
@Gavin、この特定のケースでは、JSにはイベントがありません。ユーザーの入力、ユーザーの貼り付け、ユーザーの切り取り、JavaScriptの挿入、JavaScriptの削除、フォームのオートコンプリート、非表示フォーム、非表示を認識できる一連のイベントを見つけてくださいフォーム。
Naramsim

2
@Gavin JSには、入力が変更されるたびにトリガーされるonchangedイベントがないようです。(document.getElementById(name).value = Math.random()を実行してください)、イベントトリガーソリューションが機能しないことを確認します。
Joeri

58

oninputイベントへのバインドは、ほとんどの正常なブラウザで正常に機能するようです。IE9もサポートしていますが、実装にバグがあります(文字を削除してもイベントは発生しません)。

jQueryバージョン1.7以降では、このonメソッドは次のようにイベントにバインドするのに役立ちます。

$(".inputElement").on("input", null, null, callbackFunction);

12
oninputイベントで動作していないinput[type=reset]あなたは、このテストで見ることができるようにまたはJavaScriptの編集:codepen.io/yukulele/pen/xtEpb
Yukulélé

2
@Yukulélé、少なくとも私たちは可能なすべてのユーザーアクションを検出するよりも簡単にそれを回避できます
パセリエ2014

30

2017年の回答入力イベントは、IE8より新しいものに対してはまさにこれを行います。

$(el).on('input', callback)

6
申し訳ありませんが、これは上記のHRJの2012年の回答とどう違うのですか?とにかく、inputイベントはJSの変更を検出できません。
デビッド

16

残念ながら、基準に一致するイベントまたはイベントセットはありません。キープレスとコピー/貼り付けはどちらもkeyupイベントで処理できます。JSによる変更はよりトリッキーです。テキストボックスを設定するコードを制御できる場合は、関数を直接呼び出すか、テキストボックスでユーザーイベントをトリガーするようにコードを変更するのが最善策です。

// Compare the textbox's current and last value.  Report a change to the console.
function watchTextbox() {
  var txtInput = $('#txtInput');
  var lastValue = txtInput.data('lastValue');
  var currentValue = txtInput.val();
  if (lastValue != currentValue) {
    console.log('Value changed from ' + lastValue + ' to ' + currentValue);
    txtInput.data('lastValue', currentValue);
  }
}

// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());

// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);

// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
  $('#txtInput').val('abc def').trigger('set');
});

そのコードを制御できない場合はsetInterval()、テキストボックスの変更を「監視」するために使用できます。

// Check the textbox every 100 milliseconds.  This seems to be pretty responsive.
setInterval(watchTextbox, 100);

この種のアクティブな監視は、更新を「すぐに」キャッチしませんが、認識できるほどの遅れがないほど高速であるようです。DrLouieがコメントで指摘したように、多くの入力を監視する必要がある場合、このソリューションはおそらく適切に拡張できません。いつでも2番目のパラメータを調整して、setInterval()チェックの頻度を増減できます。


参考までに、ブラウザ間でさまざまな程度でOP基準に一致させるために組み合わせることができるイベントは多数あります(最初の質問コメントのリンクを参照)。この回答は上記のイベントを使用していません。皮肉なことに、わずかな遅れはありますが、皮肉にもすべてのブラウザで同様に機能します;)
Crescent Fresh

OPはJavaScriptを経由してテキストボックスにキャッチ変化(例えばしたいmyTextBox.value = 'foo';。ノーJavaScriptのイベントはそのような状況を扱う。
アナベル

1
タブを維持するために50個のフィールドがある場合はどうなりますか?
DoctorLouie、2009

1
はい、私の場合は1つのフィールドしかありませんが、これがいくつかのフィールドで適切に機能しない理由はわかりません。すべての入力をチェックするsetTimeoutを1つだけ持つのがおそらく最も効率的です。
ダスティンボズウェル

1
@Douglas:その状況を処理するJavaScriptイベントはありません -修正:IE はで処理できinput.onpropertychange、FF2 +、Opera 9.5、Safari 3、およびChrome 1で処理できますinput.__defineSetter__('value', ...)(DOMノードでは機能しないと記載されていますが、確認できますできます)。IEの実装との唯一の違いは、IEがプログラム設定だけでなく、キーイベント中にもハンドラーを起動することです。
クレセントフレッシュ

6

他の答えのいずれも気に入らなかった場合の少し異なる解決策は次のとおりです。

var field_selectors = ["#a", "#b"];
setInterval(function() { 
  $.each(field_selectors, function() { 
    var input = $(this);
    var old = input.attr("data-old-value");
    var current = input.val();
    if (old !== current) { 
      if (typeof old != 'undefined') { 
        ... your code ...
      }
      input.attr("data-old-value", current);
    }   
  }   
}, 500);

クリックとキーアップに依存してコンテキストメニューの貼り付けをキャプチャできないことに注意してください。


この答えは私にとって最も効果的でした。私が使用するまで、セレクターでいくつかの問題がありました: $("input[id^=Units_]").each(function() {
robr


3

サンプルを作成しました。それはあなたのために働くでしょう。

var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;

var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
    clearTimeout(typingTimer);
    if ($('#tyingBox').val) {
        typingTimer = setTimeout(function () {
            $("p.content").html('Typing...');
        }, doneTypingInterval);
    }
});

$('#tyingBox').keyup(function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function () {
        $("p.content").html(oldData);
    }, finaldoneTypingInterval);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>

http://jsfiddle.net/utbh575s/


3

実際には、javaScriptの変更を検出するためにループを設定する必要はありません。検出したい要素にすでに多くのイベントリスナーを設定しています。害のないイベントをトリガーするだけでうまくいきます。

$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});

$("input[name='test-element']").val("test").trigger("blur");

そして、これは、プロジェクトのJavaScriptの変更を完全に制御できる場合にのみ使用できます。


2

まあ、最善の方法はあなたが自分でリストしたこれらの3つの拠点をカバーすることです。単純な:onblur、:onkeyupなどは希望どおりに機能しないため、組み合わせるだけです。

KeyUpは最初の2つをカバーする必要があります。JavaScriptが入力ボックスを変更している場合は、それが独自のJavaScriptであることを確信しているので、それを変更する関数にコールバックを追加します。


1
シンプルなソリューションの場合は+1。ただし、OPがテキストボックスに変更を加えるコードを変更することはできません。
アナベル

考えられるすべてのイベントを列挙することは、私には頑健に思えません。ユーザーが削除キーを押し続けた場合(つまり、繰り返しキー)、キーアップは機能しますか?オートコンプリート(または値を自動入力するツールバー)はどうですか?または、キープレスを起動しない特別な入力ソースはありますか?私はあなたが見逃すこのようなものがあるのではないかと心配しています。
ダスティンボズウェル

1

以下は、jqueryuiセレクター(リスト)にデータを入力するオートコンプリートのバリエーションを実装するために使用している作業例ですが、ドロップダウンメニューを実行するjqueryuiオートコンプリートとまったく同じように機能させたくありません。

$("#tagFilter").on("change keyup paste", function() {
     var filterText = $("#tagFilter").val();
    $("#tags").empty();
    $.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
        function(data) {
            var i;
            for (i = 0; i < data.length; i++) {
                var tag = data[i].value;
                $("#tags").append("<li class=\"tag\">" + tag + "</li>");
            }
        }); 
});

1

クエリなし!(とにかく最近は時代遅れです)

編集:HTMLイベントを削除しました。HTMLイベントを使用しないでください...代わりにJavaScriptイベントリスナーを使用してください。

document.querySelector("#testInput").addEventListener("input", test);

function test(e) {
 var a = document.getElementById('output');
 var b = /^[ -~]+$/;
 if (e.target.value == '' || b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. Yes";
 } else if (!b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. No";
 }
}
Try pressing Alt+NumPad2+NumPad3 in the input, it will instantly detect a change, whether you Paste, Type, or any other means, rather than waiting for you to unselect the textbox for changes to detect.

<input id="testInput">
<br>
<a id="output">Text is Ascii?.. Yes</a>


0

<span contenteditable="true" spellcheck="false">代わりにelementを使用できません<input type="text">か?

<span>contenteditable="true" spellcheck="false"属性として)<input>主な理由は次のとおりです。

  • のようなスタイルではありません<input>
  • valueプロパティはありませんが、テキストはとしてレンダリングされinnerText、その内部ボディの一部になります。
  • これ<input>は複数行ですが、属性を設定した場合はそうではありませんmultiline="true"

外観を実現するために、もちろん、CSSでスタイルinnerTextを設定できますが、イベントを取得するために値を書き込むことができます。

ここにフィドルがあります。

残念ながら、IEやEdgeでは実際に機能しないものがあり、それを見つけることはできません。


私はその方法を使用することに関してアクセシビリティの懸念があると思います。
Daniel Tonon

0

この質問は10年前に投稿されましたが、まだ改善の余地があると思います。これが私の解決策です。

$(document).on('propertychange change click keyup input paste', 'selector', function (e) {
    // Do something here
});

このソリューションの唯一の問題は、値がjavascriptのように変更されてもトリガーされないことです$('selector').val('some value')。javascriptから値を変更すると、セレクターにイベントを発生させることができます。

$(selector).val('some value');
// fire event
$(selector).trigger('change');

-2

この例を見て、興味のあるイベントを選択できます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>evetns</title>
</head>
<body>
<form>
    <input class="controlevents" id="i1" type="text" /><br />
    <input class="controlevents" id="i2" type="text" /><br />
    <input class="controlevents" id="i3" type="text" /><br />
    <input class="controlevents" id="i4" type="text" /><br />
    <input class="controlevents" id="i5" type="text" /><br />
</form>
<div id="datatext"></div>
</body>
</html>
<script>
$(function(){

function testingevent(ev){
    if (ev.currentTarget.tagName=="INPUT")
        $("#datatext").append("<div>id : " + ev.currentTarget.id + ", tag: " + ev.currentTarget.tagName + ", type: "+ ev.type +"</div>");
}   

    var eventlist = ["resizeend","rowenter","dragleave","beforepaste","dragover","beforecopy","page","beforeactivate","beforeeditfocus","controlselect","blur",
                    "beforedeactivate","keydown","dragstart","scroll","propertychange","dragenter","rowsinserted","mouseup","contextmenu","beforeupdate",
                    "readystatechange","mouseenter","resize","copy","selectstart","move","dragend","rowexit","activate","focus","focusin","mouseover","cut",
                    "mousemove","focusout","filterchange","drop","blclick","rowsdelete","keypress","losecapture","deactivate","datasetchanged","dataavailable",
                    "afterupdate","mousewheel","keyup","movestart","mouseout","moveend","cellchange","layoutcomplete","help","errorupdate","mousedown","paste",
                    "mouseleave","click","drag","resizestart","datasetcomplete","beforecut","change","error","abort","load","select"];

    var inputs = $(".controlevents");

    $.each(eventlist, function(i, el){
        inputs.bind(el, testingevent);
    });

});
</script>

4
イベントのタイプを忘れたと思います:)
ダスティン・ボズウェル

-3

ここでパーティーに遅れる可能性がありますが、jQueryが提供する.change()イベントを使用することはできません。

次のようなことができるはずです...

$(#CONTROLID).change(function(){
    do your stuff here ...
});

あなたはいつもそれを次のようなものでコントロールのリストにバインドすることができます...

var flds = $("input, textarea", window.document);

flds.live('change keyup', function() {
    do your code here ...
});

ライブバインダーは、ページ上に現在および将来存在するすべての要素が確実に処理されるようにします。


2
changeイベントはフォーカスが失われた後にのみ発生するため、ユーザーがボックスに入力している間は発生せず、完了して他のことを実行した後にのみ発生します。
Eli Sand、

2
ここでの他の多くの回答と同様に、要素の値がJavascriptから変更された場合、これは機能しません。OPが要求した他の修正ケースを見逃すかどうかはわかりません。
Mark Amery 2013年

-4

これはそれを行うための最速でクリーンな方法です:

私はjqueryを使用しています->

$('selector').on('change', function () {
    console.log(this.id+": "+ this.value);
});

それは私にとってはかなりうまくいきます。


7
これはすでに提案されています。これは、ユーザーがテキストを入力するときの単純なケースのみを扱います。
クリストフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.