按下键时,jQuery代码触发两次bind('keyup change')

时间:2022-12-08 00:01:28

I have a number input that should trigger jQuery on every change. To do this, I do a $('#id').bind('keyup change', ...);, which is triggered on any keyup or mouse-controller changed.

我有一个数字输入,应该在每次更改时触发jQuery。为此,我执行了$('#id')。bind('keyup change',...);,这是在任何键盘或鼠标控制器更改时触发的。

This works find for mouse clicks (triggers change) and for typing numbers (triggers keyup). But for the cursor keys it triggers both change and keyup. How can I make it so it only triggers once in all situations?

这适用于鼠标点击(触发器更改)和键入数字(触发器键盘)。但是对于光标键,它会触发更改和键盘。我怎样才能使它在所有情况下只触发一次?

Here's an example showing the problem: http://jsfiddle.net/jSjkE/

这是一个显示问题的示例:http://jsfiddle.net/jSjkE/

2 个解决方案

#1


12  

You have a wrong concept about the onchange event.

你对onchange事件有一个错误的概念。

It does NOT fire when the element's value changes, instead, it fires only when 2 conditions are met:

当元素的值发生变化时,它不会触发,而是仅在满足2个条件时触发:

  • The element blurs (loses focus);
  • 元素模糊(失去焦点);
  • The element has a different value than when it gained focus.
  • 元素具有与获得焦点时不同的值。

Note: The above is for inputs of type text. For types checkbox/radio it fires as soon as their checked property changes, and for select elements as soon as its selected option changes.

注意:以上是输入文本类型。对于类型复选框/无线电,它会在其选中的属性发生更改时立即触发,并在选定的选项发生更改时立即触发。

The onchange event (possibly wrongly) fires when you press Chrome's input type="number" up/down arrows. You should not rely on it, as many other major browsers don't even have an implementation of the number inputs yet and may not follow this behavior.

当您按Chrome的输入类型=“数字”上/下箭头时,onchange事件(可能错误地)会触发。您不应该依赖它,因为许多其他主流浏览器甚至没有实现数字输入,可能不会遵循此行为。

Instead, as you're using HTML5, you should rely on the oninput HTML5 event, which fires whenever the element's value is updated.

相反,当您使用HTML5时,您应该依赖于oninput HTML5事件,该事件会在元素值更新时触发。

$(function() {
    var count = 0;
    $('#num').on('input', function(e) {
        console.log('update ' + (++count) + ' Value: ' + this.value);    
    });
});​

Fiddle

小提琴

edit:

编辑:

For older (and non-HTML5) browsers, you may use the keyup event as a fallback:

对于较旧(和非HTML5)的浏览器,您可以使用keyup事件作为后备:

$('#num').on('input keyup', function(e) {

The most resilient way to do this for non-HTML5 browsers would be having a setInterval constantly checking if the element's value has changed, as keyup does not trigger if you select some text and drag it into the textbox - you could try .on('input keyup mouseup', but then it wouldn't trigger if the user uses the browser's Edit > Paste menu.

对非HTML5浏览器执行此操作的最有弹性的方法是让setInterval不断检查元素的值是否已更改,因为如果选择一些文本并将其拖动到文本框中,则不会触发keyup - 您可以尝试.on('输入keyup mouseup',但如果用户使用浏览器的Edit> Paste菜单,则不会触发。

edit2:

EDIT2:

If you don't want to use setInterval, you can put a huge events map inside the .on/.bind and check if the value has changed by storing the current value in the .data() of the element:

如果您不想使用setInterval,可以在.on / .bind中放置一个巨大的事件映射,并通过将当前值存储在元素的.data()中来检查值是否已更改:

var count = 0;
$('#num').on('input keyup change', function(e) {
    if (this.value == $(this).data('curr_val'))
        return false;
    $(this).data('curr_val', this.value);

    console.log('update ' + (++count) + ' Value: ' + this.value);
});

Fiddle

小提琴

I've added the onchange event to the events map, so even if the oninput and onkeyup fails (non-html5 browser using the browser's menu to paste data), the onchange event will still fire when the element loses focus.

我已将onchange事件添加到事件映射中,因此即使oninput和onkeyup失败(非html5浏览器使用浏览器的菜单粘贴数据),当元素失去焦点时,onchange事件仍将触发。

Here's the final edit with a commented setInterval and .data() to avoid using globals, so you can choose which of the fallbacks to use:

这是使用注释的setInterval和.data()进行的最终编辑,以避免使用全局变量,因此您可以选择要使用的后备:

$(function() {
    var $num = $('#num');
    $num.data('curr_val', $num.val()); //sets initial value

    var count = 0;
    setInterval(function(){
        if ($num.data('curr_val') == $num.val()) //if it still has same value
            return false; //returns false
        $num.data('curr_val', $num.val()); //if val is !=, updates it and
        //do your stuff
        console.log('update ' + (++count) + ' Value: ' + $num.val());
    }, 100); //100 = interval in miliseconds
});

Fiddle

小提琴

#2


0  

$('input').unbind('keyup').bind('keyup',function(e){ ...

#1


12  

You have a wrong concept about the onchange event.

你对onchange事件有一个错误的概念。

It does NOT fire when the element's value changes, instead, it fires only when 2 conditions are met:

当元素的值发生变化时,它不会触发,而是仅在满足2个条件时触发:

  • The element blurs (loses focus);
  • 元素模糊(失去焦点);
  • The element has a different value than when it gained focus.
  • 元素具有与获得焦点时不同的值。

Note: The above is for inputs of type text. For types checkbox/radio it fires as soon as their checked property changes, and for select elements as soon as its selected option changes.

注意:以上是输入文本类型。对于类型复选框/无线电,它会在其选中的属性发生更改时立即触发,并在选定的选项发生更改时立即触发。

The onchange event (possibly wrongly) fires when you press Chrome's input type="number" up/down arrows. You should not rely on it, as many other major browsers don't even have an implementation of the number inputs yet and may not follow this behavior.

当您按Chrome的输入类型=“数字”上/下箭头时,onchange事件(可能错误地)会触发。您不应该依赖它,因为许多其他主流浏览器甚至没有实现数字输入,可能不会遵循此行为。

Instead, as you're using HTML5, you should rely on the oninput HTML5 event, which fires whenever the element's value is updated.

相反,当您使用HTML5时,您应该依赖于oninput HTML5事件,该事件会在元素值更新时触发。

$(function() {
    var count = 0;
    $('#num').on('input', function(e) {
        console.log('update ' + (++count) + ' Value: ' + this.value);    
    });
});​

Fiddle

小提琴

edit:

编辑:

For older (and non-HTML5) browsers, you may use the keyup event as a fallback:

对于较旧(和非HTML5)的浏览器,您可以使用keyup事件作为后备:

$('#num').on('input keyup', function(e) {

The most resilient way to do this for non-HTML5 browsers would be having a setInterval constantly checking if the element's value has changed, as keyup does not trigger if you select some text and drag it into the textbox - you could try .on('input keyup mouseup', but then it wouldn't trigger if the user uses the browser's Edit > Paste menu.

对非HTML5浏览器执行此操作的最有弹性的方法是让setInterval不断检查元素的值是否已更改,因为如果选择一些文本并将其拖动到文本框中,则不会触发keyup - 您可以尝试.on('输入keyup mouseup',但如果用户使用浏览器的Edit> Paste菜单,则不会触发。

edit2:

EDIT2:

If you don't want to use setInterval, you can put a huge events map inside the .on/.bind and check if the value has changed by storing the current value in the .data() of the element:

如果您不想使用setInterval,可以在.on / .bind中放置一个巨大的事件映射,并通过将当前值存储在元素的.data()中来检查值是否已更改:

var count = 0;
$('#num').on('input keyup change', function(e) {
    if (this.value == $(this).data('curr_val'))
        return false;
    $(this).data('curr_val', this.value);

    console.log('update ' + (++count) + ' Value: ' + this.value);
});

Fiddle

小提琴

I've added the onchange event to the events map, so even if the oninput and onkeyup fails (non-html5 browser using the browser's menu to paste data), the onchange event will still fire when the element loses focus.

我已将onchange事件添加到事件映射中,因此即使oninput和onkeyup失败(非html5浏览器使用浏览器的菜单粘贴数据),当元素失去焦点时,onchange事件仍将触发。

Here's the final edit with a commented setInterval and .data() to avoid using globals, so you can choose which of the fallbacks to use:

这是使用注释的setInterval和.data()进行的最终编辑,以避免使用全局变量,因此您可以选择要使用的后备:

$(function() {
    var $num = $('#num');
    $num.data('curr_val', $num.val()); //sets initial value

    var count = 0;
    setInterval(function(){
        if ($num.data('curr_val') == $num.val()) //if it still has same value
            return false; //returns false
        $num.data('curr_val', $num.val()); //if val is !=, updates it and
        //do your stuff
        console.log('update ' + (++count) + ' Value: ' + $num.val());
    }, 100); //100 = interval in miliseconds
});

Fiddle

小提琴

#2


0  

$('input').unbind('keyup').bind('keyup',function(e){ ...