jQuery <select> 使用键盘时未触发更改事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9806257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 11:20:28  来源:igfitidea点击:

<select> change event not fired when using keyboard

jqueryonchange

提问by mgraph

http://jsfiddle.net/rFEER/

http://jsfiddle.net/rFEER/

<select id="users">
<option value="1">Hyman</option>
<option value="2">brill</option>
<option value="3">antony</option>
</select>?

js:

js:

$("#users").change(function(){
    alert($(this).val());
})?

why change event not fired when using (keyup/keydown) until mouse is clicked

为什么在单击鼠标之前使用(keyup/keydown)时不会触发更改事件

回答by T.J. Crowder

why change event not fired when using (keyup/keydown) until mouse is clicked

为什么在单击鼠标之前使用(keyup/keydown)时不会触发更改事件

It also fires when focus leaves the select. That's just how the changeevent works.

当焦点离开select. 这就是change事件的运作方式。

If you want proactive notification, you have to watch for changeand keydown(at least, you may want clickas well) and handle the case of getting an event when the value hasn't actually changed, andyou have to handle the fact that some of those events (keydown, for instance) are fired beforethe value is changed, so you have to wait a moment before processing the event. Or see SpYk3HH's answerwhich uses keyupinstead — that will be less proactive (not updating until key release, which could be desireable), but then you don't need the delay (setTimeout) my code below has.

如果您想要主动通知,则必须注意changekeydown(至少,您可能也想要click)并处理在值实际上未更改时获取事件的情况,并且您必须处理以下事实:其中一些事件(keydown例如)在值改变之前被触发,所以你必须等待一段时间才能处理事件。或者请参阅SpYk3HH 的答案,它使用keyup代替 - 这将不那么主动(在密钥发布之前不会更新,这可能是可取的),但是您不需要setTimeout我下面的代码所具有的延迟()。

Example (live copy):

示例(实时复制):

HTML (I took the liberty of changing the values so it was clearer which went with each name):

HTML(我随意更改了值,以便更清楚地显示每个名称的含义):

<select id="users">
<option value="j">Hyman</option>
<option value="b">brill</option>
<option value="a">antony</option>
</select>?

JavaScript:

JavaScript:

$("#users").bind("keydown change", function(){
    var box = $(this);
    setTimeout(function() {
        display(box.val());
    }, 0);
});


Note in 2016: bindhas largely been replaced with on. In the above it you'd literally just replace "bind" with "on".

2016 年的注意事项:bind已在很大程度上被替换为on. 在上面它你实际上只是用“on”替换“bind”。

回答by SpYk3HH

Try changing

尝试改变

$("#users").change(function(){

to

$("#users").bind('change keyup', function(e) {

that should bound yyour function for both, onchange event and when down or up arrow key is pressed

应该为 onchange 事件和按下向下或向上箭头键时绑定你的函数

note, you could also use keydown, but it may not preform as expected as your code will run before the select change is made

请注意,您也可以使用 keydown,但它可能不会按预期执行,因为您的代码将在进行选择更改之前运行

And in case you want an infinate scrolling Select box, i have a nifty little func i wrote that so far, for me at least, works perfect and can be assigned all on its own without affecting other keyup actions, of course, and with intent on our sight, this is ment to work on the keyup, and so you still have to actually press the arrow key over and over, but it will continue to loop non stop through all options. Although, im pretty sure it'll work with keydown too, but we dont use it that way, so i've not tested it. Again, keydown, may not perform as intended, especially if the select only has 2 or 3 options.

如果你想要一个无限滚动的选择框,我有一个漂亮的小功能,到目前为止我写的,至少对我来说,工作完美,可以在不影响其他键盘操作的情况下自行分配,当然,并且有意图在我们看来,这是在 keyup 上工作的,所以你仍然需要一遍又一遍地按下箭头键,但它会继续不停地循环所有选项。虽然,我很确定它也可以与 keydown 一起使用,但我们不那样使用它,所以我没有测试过它。再次,键盘可能不会按预期执行,特别是如果选择仅具有2或3个选项。

function selectInfinateScroll() {
    if ($(this).data("lastSelected")) {
        if ($(this).data("lastSelected")[0] == $(this).children("option:selected")[0]) {
            if ($(this).children("option:selected").index() == 0) {
                $(this).children("option:selected").prop("selected", false);
                $(this).children("option:last-child").prop("selected", true).change();
            }
            else {
                $(this).children("option:selected").prop("selected", false);
                $(this).children("option:first-child").prop("selected", true).change();
            };
        };
    };
    $(this).data("lastSelected", $(this).children("option:selected"));
}

$(function() {
    //  Enable 'Scrolling Through' on Select Boxes
    $("select").keyup(selectInfinateScroll);
});


UPDATED!

更新!



I'm leaving the original answer, as it uses an alternate method that may be more useful to some. However, I have come up with both a shorter function that works on "keydown" and a jQuery plugin using said function that allows user to "hold down" and arrow key and still sort through options infinitely!

我要离开原来的答案,因为它使用了一种可能对某些人更有用的替代方法。但是,我想出了一个适用于“keydown”的较短函数和一个使用所述函数的 jQuery 插件,该插件允许用户“按住”和箭头键并仍然无限地对选项进行排序!

First, the new function

一、新功能

function keydownInfiniteSelect(e) {
    var eKey = e.which || e.key,
        selected = $(this).find("option:selected");
    if (eKey == 38 && selected.is(":first-child")) {    //    up arro
        $(this).find("option").last().prop("selected", true);    //    set value to last option
        $(this).change();    //    ensure select triggers change do to return false
        return false;    //    keeps select from skipping to second last option
    }
    else if (eKey == 40 && selected.is(":last-child")) {    //    down arro
        $(this).val($(this).find("option").first().val());    //    set value to first option
        $(this).change();    //    ensure select triggers change
        return false;    //    keeps select from skipping to second option
    }
}

Use like: $("select").keydown(keydownInfiniteSelect);

像这样使用: $("select").keydown(keydownInfiniteSelect);

And the jQuery Plugin Style!

和 jQuery 插件风格!

(function($){$.infiniteSelect||($.extend({infiniteSelect:function(b){return b.each(function(){$(this).data("infiniteSelect")||($.fn.on?$(this).on("keydown",$.infiniteSelect.methods.keydownInfiniteSelect).data("infiniteSelect",!0):$(this).bind("keydown",$.infiniteSelect.methods.keydownInfiniteSelect).data("infiniteSelect",!0))})}}),$.fn.extend({infiniteSelect:function(){return $.infiniteSelect($(this))}}),$.infiniteSelect.methods={keydownInfiniteSelect:function(b){b=b.which||b.key;var c=$(this).find("option:selected");
if(38==b&&c.is(":first-child"))return $(this).find("option").last().prop("selected",!0),$(this).change(),!1;if(40==b&&c.is(":last-child"))return $(this).val($(this).find("option").first().val()),$(this).change(),!1}})})(jQuery);

Use as $("select").infiniteSelect()OR$.infiniteSelect("select")

用作$("select").infiniteSelect()OR$.infiniteSelect("select")

jsFiddle of Plugin Minified

jsFiddle of Plugin Minified

Uncut Plugin Fiddle

未删减插件小提琴

PS. I almost have a Vanilla JavaScript ready for the function except that the "set to last option" part of the method keeps dieing, or going null, or skipping to the second to last. I just can't seem to get it to set correctly. If anyone wants to fix it and update, I'd be much obliged. See HERE

附注。除了方法的“设置为最后一个选项”部分不断消失,或者变为空,或者跳到倒数第二个之外,我几乎已经为该函数准备了一个普通的 JavaScript。我似乎无法正确设置它。如果有人想修复它并更新,我将非常感激。见这里

回答by Gabriele Petrioli

That is the normal behaviour ...

这是正常的行为......

Quoting the w3c specs

引用w3c 规范

change
The change event occurs when a control loses the input focus and its value has been modified since gaining focus. This event is valid for INPUT, SELECT, and TEXTAREA. element.

change
当控件失去输入焦点并且其值在获得焦点后已被修改时,将发生 change 事件。此事件对 INPUT、SELECT 和 TEXTAREA 有效。元素。

回答by Onshop

Using the answers above I was able to get the behaviour I needed using:

使用上面的答案,我能够获得我需要使用的行为:

$( "select" ).bind('keyup', function(e) {
    $(  '#' + e.target.id ).trigger('change');
});

回答by Web Developer

$("#users").bind('change keyup', function(e) {

was enough

够了

回答by Imeksbank

/*After having been searching for hours i wrote my own. */



<script>
jQuery(document).ready(function () {
        /*********** SELECT PLZ ****************/
        /*********** SELECT PLZ ****************/
        /*********** SELECT PLZ ****************/
        jQuery('.dropedZip').html('' +
        '<select name="theName" id="theID" size="4" style="width: 184px" >' +
        '<option value="A">Choice A</option>' +
        '<option value="B">Choice B</option>' +
        '<option value="C">Choice C</option>' +
        '<option value="D">Choice D</option>' +
        '</select>');

        var nextOptValue = 0;
        var prevOptValue = 0;

        jQuery('#prop').keydown(function (e) {

            var key = e.which;
            if(key==13){
                var currOptValue = jQuery('select#theID > option:selected').val();// CURRENT
                alert('ausgesucht: '+currOptValue);
            }
            /* UP */
            if(key==38){
                var currOptValue = jQuery('select#theID > option:selected').val();// CURRENT
                if(currOptValue!=undefined){// CURRENT != undefined ?
                    prevOptValue = jQuery('select#theID > option:selected').prev('option').val();// PREV
                    if(prevOptValue!=undefined){// PREV != undefined ?
                        jQuery('select#theID > option:selected').removeAttr('selected');// REMOVE CURRENT
                        jQuery('select#theID > option[value='+prevOptValue+']').prop('selected',true);// SET PREV
                        jQuery('input#prop').val(prevOptValue);// SET INPUT VALUE : OTHER
                    }
                }
            }
            /* DOWN */
            if(key==40){
                if(jQuery('select#theID > option:selected').val()==undefined){// NULL
                    nextOptValue = jQuery('select#theID > option:first').val();// FIRST
                    jQuery('select#theID > option[value='+nextOptValue+']').prop('selected',true);// SET FIRST
                    jQuery('input#prop').val(nextOptValue);// SET INPUT VALUE : FIRST
                }else{
                    nextOptValue = jQuery('select#theID > option:selected').next('option').val();// NEXT
                    jQuery('select#theID > option:selected').removeAttr('selected');// REMOVE FIRST
                    jQuery('select#theID > option[value='+nextOptValue+']').prop('selected',true);// SET NEXT
                    jQuery('input#prop').val(nextOptValue);// SET INPUT VALUE : OTHER
                }

            }

        });
        /*********** SELECT PLZ ****************/
        /*********** SELECT PLZ ****************/
        /*********** SELECT PLZ ****************/


    });
</script>

        <input id="prop" type="text">
<div class="dropedZip"></div>