使用JQuery检测对<input type =“text”>(立即)的所有更改

有一个<input type =“text”>的值可以改变的方法很多,包括:

  • 按键
  • 复制粘贴
  • 用JavaScript修改
  • 通过浏览器或工具栏自动完成

我希望我的JavaScript函数可以随时调用(使用当前的input值)。 而且我希望马上就被调用,而不仅仅是当input失去焦点时。

我正在寻找最干净,最健壮的方法来跨越所有浏览器(最好使用jQuery)来做到这一点。

示例用例:在Twitter注册页面上, 用户名字段的值显示在其下面的url“ http:// twitter / username ”中。

这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 .... } }); }); 

jquery> = 1.9的实时花式解决scheme

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

如果你还想检测“点击”事件,只是:

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

如果你的jquery <= 1.4,只需使用“live”而不是“on”。

不幸的是,我认为setInterval获奖:

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

这是最简洁的解决scheme,只需要一行代码。 这也是最强大的,因为你不必担心input可以获得价值的所有不同事件/方式。

使用'setInterval'的缺点似乎不适用于这种情况:

  • 100毫秒的延迟? 对于许多应用程序来说,100ms足够快。
  • 增加了浏览器的负载? 一般来说,在页面上添加大量的重量setIntervals是不好的。 但在这种特殊情况下,添加的页面加载是无法察觉的。
  • 它不能扩展到许多input? 大多数页面没有多lessinput,您可以在同一个setInterval中嗅探所有input。

绑定到oninput事件似乎在大多数理智的浏览器中工作正常。 IE9也支持它,但是实现是错误的(删除字符时不会触发事件)。

使用jQuery版本1.7+, on方法对于像这样的事件绑定是有用的:

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

2017年回答 : input事件正是为了比IE8更近的东西。

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

不幸的是,没有任何事件或一组事件符合您的标准。 按键和复制/粘贴都可以通过按键事件来处理。 通过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在评论中指出的那样,如果您需要观看大量input,则此解决scheme可能无法很好地扩展。 你总是可以调整第二个参数setInterval()来检查或多或less。

如果你不喜欢任何其他的答案,这是一个稍微不同的解决scheme:

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

考虑到你不能依靠点击和键盘来捕获上下文菜单粘贴。

我已经创build了一个样本。 愿它能为你工作。

 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/

添加这个代码的地方,这将做的伎俩。

 var originalVal = $.fn.val; $.fn.val = function(){ var result =originalVal.apply(this,arguments); if(arguments.length>0) $(this).change(); // OR with custom event $(this).trigger('value-changed'); return result; }; 

在val()find这个解决scheme不会触发jQuery中的change()

那么最好的方法就是覆盖你自己列出的三个基地。 一个简单的:onblur,:onkeyup等不会为你想要的,所以只是把它们结合起来。

KeyUp应该覆盖前两个,如果Javascript正在修改input框,那么我当然希望它是你自己的JavaScript,所以只需要在修改它的函数中添加一个callback。

这里有一个工作的例子,我用来实现一个自动完成的变化填充jqueryuiselect器(列表),但我不希望它完全像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>"); } }); }); 

实际上,我们不需要设置用于检测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改变时才可用。

你可以看到这个例子,并select你感兴趣的事件:

 <!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> 

我可能会迟到这里的派对,但是不能只使用jQuery提供的.change()事件。

你应该可以做一些像…

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

你总是可以将它绑定到一个类似于…的控件列表

 var flds = $("input, textarea", window.document); flds.live('change keyup', function() { do your code here ... }); 

活动活页夹确保处理现在和将来在页面上存在的所有元素。

这是最快和最干净的方法:

我正在使用Jquery – >

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

这对我来说工作得很好。