关于javascript:使用JQuery检测对(立即)的所有更改

Detect all changes to a (immediately) using JQuery

的值可以通过多种方式改变,包括:

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

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

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

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


这个jQuery代码捕获任何元素的即时更改,并且应该适用于所有浏览器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 $('.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的实时奇特解决方案

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

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

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

如果你使用jQuery <= 1.4,只需使用live而不是on


不幸的是,我认为setInterval赢得了奖项:

1
2
3
<input type=text id=input_id />

setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);

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

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

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


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

使用jQuery 1.7+版本,on方法可以绑定到这样的事件:

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


2017答案:输入事件对IE8的最新版本确实如此。

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


遗憾的是,没有符合您条件的事件或事件集。可以使用keyup事件处理Keress和复制/粘贴。通过JS进行的更改比较棘手。如果您可以控制设置文本框的代码,最好将其修改为直接调用函数或触发文本框上的用户事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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()"监视"文本框中的更改:

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

这种主动监控不会立即捕获更新,但似乎足够快,没有明显的滞后。正如DrLouie在评论中指出的那样,如果你需要观察大量的输入,这个解决方案可能无法很好地扩展。您始终可以将第二个参数调整为setInterval()以进行更多或更少的检查。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);

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


在某个地方添加此代码,这将解决问题。

1
2
3
4
5
6
7
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()


我创建了一个样本。愿它适合你。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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">


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


实际上,我们不需要设置循环来检测javaScript更改。
我们已经为要检测的元素设置了许多事件监听器。只是触发任何无害的事件都会成功。

1
2
3
4
5
$("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更改有完全控制权时才能使用此功能。


这是一个工作示例,我用来实现自动完成变体,填充jqueryui选择器(列表),但我不希望它的功能完全像jqueryui自动完成,它执行下拉菜单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$("#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>
"
);
            }
        });
});


那么,最好的办法是覆盖你自己列出的三个基地。一个简单的:onblur,:onkeyup等不适用于你想要的东西,所以只需将它们组合起来。

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


你不能只用元素代替吗?

(contenteditable="true" spellcheck="false"作为属性)区别主要是因为:

  • 它的风格不像
  • 它没有value属性,但文本呈现为innerText并成为其内部主体的一部分。
  • 它是多行,而不是你设置属性multiline="true"

为了实现外观,您当然可以在CSS中设置样式,而将值写为innerText则可以获得一个事件:

这是一个小提琴。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!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">
evetns
</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>

</body>
</html>

$(function(){

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

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

});


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

你应该可以做类似......

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

你总是可以将它绑定到一个控件列表,例如...

1
2
3
4
5
var flds = $("input, textarea", window.document);

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

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


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

我正在使用Jquery - >

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

它对我来说很好。