【问题标题】:Detect all changes to a <input type="text"> (immediately) using JQuery使用 JQuery 检测对 <input type="text"> 的所有更改(立即)
【发布时间】:2010-12-29 05:35:01
【问题描述】:

&lt;input type="text"&gt; 的值可以通过多种方式更改,包括:

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

我希望我的 JavaScript 函数在任何时候被调用(使用当前输入值)。而且我希望它立即被调用,而不仅仅是在输入失去焦点时。

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

【问题讨论】:

标签: javascript jquery html


【解决方案1】:

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

【讨论】:

  • 供大家参考,input 是我认为应该涵盖所有现代浏览器的 HTML5 事件 (MDN reference)。 keyup 应该会赶上其余的,尽管会有一点延迟(input 在按键按下时触发)。 propertychange 是一个专有的 MS 事件,我不确定 paste 是否真的有必要。
  • 我错了吗,或者当通过 document.getElementById('txtInput').value = 'some text'; 之类的 javascript 更改文本时,这无法处理
  • Mehmet,这段代码并不是为了捕捉通过 JS 改变的值。
  • @MehmetAtaş部分正确。 input 事件 here 的引用声明当通过 JavaScript 修改内容时它不会触发。但是,onpropertychange 事件确实会在通过 JS 进行修改时触发(请参阅here)。所以这段代码在 IE 上通过 JS 修改内容时有效,但在其他浏览器上无效。
  • 可以在propertychange、keyup等时触发input上的自定义事件,然后在任何地方使用。
【解决方案2】:

jQuery >= 1.9 的实时精美解决方案

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

如果您还想检测“点击”事件,只需:

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

如果您使用的是 jQuery live 而不是 on

【讨论】:

  • 这有一个缺点。如果您使用 Tab 键离开输入字段 - 即使内容未被编辑,它也会引发 keyup 事件。
  • 如何检测 datetimepicker 何时填充#input-id?所有事件(更改、粘贴)都不起作用。
  • 这太棒了!我用 jquery 1.8.3 试过了,它可以工作。我仍然有一些我必须替换的 livequery() 代码,所以我什至无法升级到 1.9.1。我知道它很旧,但整个网站也是如此。
  • 仅供参考:如果使用键盘选择无效日期,这些事件将以空白值触发。 IE。 2 月 30 日。stackoverflow.com/questions/48564568/…
【解决方案3】:

不幸的是,我认为setInterval 中奖了:

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

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

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

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

【讨论】:

  • 这似乎是使用 Nintendo 3DS 浏览器(版本/1.7552.EU)时检测表单中输入字段更改的唯一方法。
  • 注意:可以缓解过载。如果您在输入获得焦点时启动 setInterval 并在输入失去焦点时启动 clearInterval
  • 为什么要创建一个持续运行的 100 毫秒间隔而没有理由让它持续运行?事件人。使用它们。
  • @Gavin,在这种特殊情况下,JS 缺少事件.. 找到一组可以识别的事件,用户输入、用户粘贴、用户剪切、javascript 插入、javascript 删除、自动完成表单、隐藏表单、不显示表单。
  • @Gavin JS 似乎没有每次更改输入时触发的 onchanged 事件。 (只需执行 document.getElementById(name).value = Math.random() )即可查看所有事件触发解决方案均无效。
【解决方案4】:

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

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

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

【讨论】:

  • oninput 事件不适用于 input[type=reset] 或 javascript 编辑,如您在此测试中所见:codepen.io/yukulele/pen/xtEpb
  • @Yukulélé,至少我们可以比尝试检测所有可能的 用户 操作更容易解决这个问题。
【解决方案5】:

2017 年回答input event 对任何比 IE8 更新的东西都做到了这一点。

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

【讨论】:

  • 对不起,但是......这与上面 HRJ 的 2012 年答案有何不同?无论如何,input 事件未能检测到 JS 更改。
【解决方案6】:

很遗憾,没有任何事件或一组事件符合您的条件。按键和复制/粘贴都可以通过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 在 cmets 中指出的那样,如果您需要查看大量输入,此解决方案可能无法很好地扩展。您可以随时将第二个参数调整为 setInterval() 以增加或减少检查频率。

【讨论】:

  • 仅供参考,实际上有许多事件可以组合起来以在不同程度上匹配跨浏览器的 OP 标准(请参阅第一个问题评论中的链接)。这个答案不使用任何上述事件,具有讽刺意味的是,它可能在所有浏览器中都能正常工作,尽管有一点滞后;)
  • OP 希望通过 JavaScript 捕获对文本框的更改(例如 myTextBox.value = 'foo';。没有 JavaScript 事件可以处理这种情况。
  • 如果有人要关注 50 个字段怎么办?
  • 是的,我的案例中只有 1 个字段,但我不明白为什么这对于许多字段来说不能很好地工作。只有 1 个 setTimeout 来检查所有输入可能是最有效的。
  • @Douglas:没有 JavaScript 事件处理这种情况 - 更正:IE 可以用input.onpropertychange 处理它,而 FF2+、Opera 9.5、Safari 3 和 Chrome 1 可以处理它与input.__defineSetter__('value', ...) 一起使用(尽管它被记录为在 DOM 节点上不起作用,但我可以验证它是否有效)。与 IE 实现的唯一不同之处在于 IE 不仅会在编程设置时触发处理程序,还会在关键事件期间触发处理程序。
【解决方案7】:

如果您不喜欢任何其他答案,这里有一个稍微不同的解决方案:

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() {
【解决方案8】:

这是一个不使用 jQuery 的解决方案(现在它确实已经过时且没有必要)

使用事件"input",您可以查找任何类型的更改:

删除、退格、粘贴、键入以及任何会更改输入值的内容。

input 事件与文本输入直接相关。任何时候以任何方式更改文本,都会发送input

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

function test(e) {
    var a = document.getElementById('output');
    a.innerText += "Detected an Update!\n";
}
<input id="testInput">
<br>
<a id="output"></a>

【讨论】:

  • @Tylor 我提供了一个更简单的解决方案。 jQuery 有太多 XY 问题的例子。如果人们想要捷径,他们真的不应该编程。尤其是当快捷方式的性能更重或资源匮乏时......这个答案也是从 2019 年开始的。当它在这个网络上并积极上传近三年时,抱怨有点晚了。
【解决方案9】:

在某处添加这段代码,这样就可以了。

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() doesn't trigger change() in jQuery找到这个解决方案

【讨论】:

    【解决方案10】:

    虽然这个问题是 10 年前发布的,但我相信它仍然需要一些改进。所以这是我的解决方案。

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

    此解决方案的唯一问题是,如果值从 $('selector').val('some value') 这样的 javascript 更改,它不会触发。当您从 javascript 更改值时,您可以向选择器触发任何事件。

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

    或者单行

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

    【讨论】:

      【解决方案11】:

      我创建了一个示例。愿它对你有用。

      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/

      【讨论】:

        【解决方案12】:

        我们实际上不需要设置循环来检测 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 更改时,才能使用此功能。

        【讨论】:

          【解决方案13】:

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

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

          【讨论】:

          • +1 用于简单的解决方案,尽管 OP 可能无法/不想修改对文本框进行更改的代码。
          • 枚举所有可能的事件对我来说似乎并不可靠。如果用户按住删除键(即重复键),keyup 是否有效?自动完成(或自动填充值的工具栏)呢?或者是否有不触发按键的特殊输入源?我担心你会错过这样的事情。
          【解决方案14】:

          这是一个工作示例,我使用它来实现填充 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>");
                      }
                  }); 
          });
          

          【讨论】:

            【解决方案15】:

            您可以像这样简单地识别表单中的所有更改者

                       //when form change, show aleart
                        $("#FormId").change(function () {
                            aleart('Done some change on form');
                        }); 
            

            【讨论】:

              【解决方案16】:

              你不能用&lt;span contenteditable="true" spellcheck="false"&gt; 元素代替&lt;input type="text"&gt; 吗?

              &lt;span&gt;(以contenteditable="true" spellcheck="false"为属性)与&lt;input&gt;不同主要是因为:

              • 它的样式不像&lt;input&gt;
              • 它没有value 属性,但文本呈现为innerText 并成为其内部主体的一部分。
              • 它是多行的,而&lt;input&gt; 不是尽管您设置了属性multiline="true"

              要完成外观,您当然可以在 CSS 中设置样式,而将值写为 innerText 您可以为其获取一个事件:

              这是fiddle

              不幸的是,有些东西在 IE 和 Edge 中实际上不起作用,我找不到。

              【讨论】:

              • 我认为使用该方法存在可访问性问题。
              【解决方案17】:

              您可以将“输入”事件绑定到&lt;input type="text"&gt;。这将在每次输入更改(例如复制、粘贴、按键等)时触发。

              $("#input-id").on("input", function(){
                  // Your action
              })
              

              【讨论】:

                【解决方案18】:

                您可以查看此示例并选择您感兴趣的事件:

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

                【讨论】:

                • 我想你忘记了事件类型 :)
                【解决方案19】:

                我在这里聚会可能迟到了,但你能不能只使用 jQuery 提供的 .change() 事件。

                你应该能够做类似...

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

                您始终可以将其绑定到具有类似...的控件列表

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

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

                【讨论】:

                • change 事件仅在失去焦点后触发,因此它不会在用户在框中输入时触发,只有在他们完成并继续执行其他操作后才会触发。
                • 像这里的许多其他答案一样,当元素的值从 Javascript 修改时,这将不起作用。我不知道它是否遗漏了 OP 要求的任何其他修改案例。
                【解决方案20】:

                这是最快且干净的方法:

                我正在使用 Jquery-->

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

                对我来说效果很好。

                【讨论】:

                • 这已经被建议了。它只处理简单的情况,当用户键入文本时。
                猜你喜欢
                • 1970-01-01
                • 2013-09-02
                • 2013-06-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-11-29
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多