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


397

<input type="text">罐的价值有多种变化方式,包括:

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

我希望我的JavaScript函数在每次更改时都被调用(使用当前输入值)。我希望立即调用它,而不仅仅是输入失去焦点时。

我正在寻找最干净,最可靠的方法来在所有浏览器中执行此操作(最好使用jQuery)。



Answers:


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确实必要。
乔·里斯

71
我是错误的还是无法通过javascript更改文字,例如document.getElementById('txtInput').value = 'some text';
MehmetAtaş2012年

5
对于Mehmet,该代码并非旨在捕获通过JS更改的值。
phatmann

12
@MehmetAtaş 部分正确。这里input事件参考指出,通过JavaScript修改内容时不会触发。但是,该事件确实会通过JS进行修改(请参见此处)。因此,当通过IE上的JS修改内容时,此代码将起作用,但在其他浏览器上将不起作用。onpropertychange
Vicky Chijwani 2012年

2
您可以在属性更改,键盘输入等时在输入上触发自定义事件,然后在任何地方使用它。
伊万·伊夫科维奇(IvanIvković)

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
这有一个缺点。如果使用Tab键保留输入字段-即使内容未编辑,也会引发keyup事件。
2014年

2
如何检测datetimepicker何时填充#input-id?所有事件(更改,粘贴)均无效。
Pathros

这很棒!我尝试使用jQuery 1.8.3,它的工作原理。我仍然有一些livequery()代码需要替换,因此我什至不能完全升级到1.9.1。我知道它很旧,但整个网站也是如此。
Asle,2013年

仅供参考:如果使用键盘来选择无效的日期,则这些事件将以空白值触发。即。二月30 stackoverflow.com/questions/48564568/...
Olmstov

107

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

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

这是最干净的解决方案,只需一行代码。它也是最强大的,因为您不必担心所有不同的事件/方式input都可以获取价值。

在这种情况下,使用'setInterval'的缺点似乎并不适用:

  • 100ms的延迟? 对于许多应用而言,100ms足够快。
  • 在浏览器上增加了负载? 通常,在页面上添加很多重量级的setIntervals是不好的。但是在这种特殊情况下,无法检测到增加的页面加载。
  • 它不能扩展到很多输入吗? 大多数页面没有几个输入,您可以在同一setInterval中嗅探所有输入。

21
使用Nintendo 3DS浏览器(Version / 1.7552.EU)时,这似乎是检测表单中输入字段更改的唯一方法。
约翰·约翰·

4
注意:过载可以缓解。如果您在输入获得焦点时启动setInterval并在输入失去焦点时启动clearInterval
Tebe 2014年

10
您为什么要创建一个持续运行的100ms间隔,而没有理由使其持续运行呢?事件的人。使用它们。
加文2014年

15
@Gavin,在这种特殊情况下,JS缺少事件..找到我们可以识别的事件集,用户输入,用户粘贴,用户剪切,javascript插入,javascript删除,表格的自动完成,隐藏的表格,未显示形式。
Naramsim 2015年

2
@Gavin JS似乎没有每次更改输入都会触发的onchanged事件。(只需执行document.getElementById(name).value = Math.random()),就不会看到任何事件触发解决方案。
Joeri,2015年

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é,至少我们比尝试检测所有可能的用户操作更容易解决此问题。
Pacerier,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在评论中指出的那样,如果您需要观察大量输入,则此解决方案可能无法很好地扩展。您始终可以将2nd参数调整为setInterval()或多或少地进行检查。


仅供参考,实际上有很多事件可以组合在一起以在不同浏览器中以不同程度匹配OP条件(请参阅第一个问题注释中的链接)。这个答案没有使用任何上述事件,而且具有讽刺意味的是,尽管稍有滞后,它在所有浏览器中也可能同样有效;)
Crescent Fresh 2009年

在OP想通过JavaScript捕获更改文本框(如myTextBox.value = 'foo';无JavaScript事件处理这种情况。
安娜贝尔

1
如果有人拥有50个字段以保持标签状态怎么办?
DoctorLouie

1
是的,在我的情况下,我只有1个字段,但是我不明白为什么这对于许多字段都不能很好地起作用。仅使用1个setTimeout来检查所有输入可能是最有效的。
达斯汀·博斯韦尔

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 2012年

4

将此代码添加到某处,即可解决问题。

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()发现此解决方案不会触发jQuery中的change()


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

好吧,最好的方法是覆盖您自己列出的这三个基础。简单的:onblur,:onkeyup等无法满足您的需求,因此只需将它们组合即可。

KeyUp应该涵盖前两个,如果Javascript修改了输入框,那么我当然希望它是您自己的javascript,因此只需在修改它的函数中添加一个回调即可。


1
+1是简单的解决方案,尽管OP可能会/不希望修改对文本框进行更改的代码。
Annabelle

枚举所有可能的事件对我来说似乎并不可靠。如果用户按住Delete键(即重复键),则keyup是否有效?自动完成(或自动填充值的工具栏)如何处理?还是有不触发按键的特殊输入源?我担心您会错过这样的事情。
达斯汀·博斯韦尔

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

没有JQUERY!(无论如何,这几天过时了)

编辑:我删除了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"as属性)的区别<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
我认为您忘记了事件类型:)
Dustin Boswell

-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
更改事件仅在失去焦点后才触发,因此只有在用户完成操作并继续执行其他操作后,才在用户在框中键入内容时才触发。
伊莱·桑德

2
像这里的许多其他答案一样,当从Javascript修改元素的值时,这将不起作用。我不知道它是否错过了OP要求的其他任何修改案例。
马克·阿默里

-4

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

我正在使用Jquery->

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

对我来说一切正常。


7
已经有人建议这样做。当用户键入文本时,仅解决简单的情况。
Christophe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.