<select>使用键盘时不触发change事件

22

http://jsfiddle.net/rFEER/

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

js:

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

为什么在使用(键盘上的keyup / keydown)时,直到单击鼠标后,更改事件才会触发。


当元素失去焦点时,会触发“change”事件。通过键盘更改值并按下Tab键,就会触发“change”事件。 - James Allardice
截至今天,它可以工作;不需要keyup或任何其他事件。 - irfandar
6个回答

32
当使用(keyup/keydown)时,为什么更改事件直到单击鼠标才被触发?
当焦点离开

@mgraph:就像我所说的那样:您至少需要添加“keydown”(并处理它在值更改之前触发的事实)。请参见我刚刚添加的示例。 - T.J. Crowder
@T.J.Crowder,为什么不用keyup呢?它会在值改变后触发。 - Gabriele Petrioli
对于 jQuery 1.7 及以上版本,现在可以使用 .on('change keyup'... - rybo111
@rybo111:是的,四年后,情况已经改变了。 - T.J. Crowder
@T.J.Crowder 我只是把它放在这里,为了那些像我一样在谷歌上找到这个问题的人。 - rybo111
显示剩余3条评论

18

尝试更改

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

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

这应该同时绑定onchange事件和按下或释放箭头键时的函数范围。

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

如果您想要一个无限滚动的选择框,我写了一个很棒的小函数,至少对我来说,它完美地工作,并且可以单独分配而不影响其他keyup操作。 当然,在我们的意图下,这意味着它应该在keyup上工作,所以您仍然需要一次又一次地按箭头键,但它将继续无限循环遍历所有选项。 虽然,我相当确定它也适用于keydown,但我们不这样使用它,所以我没有测试过。 再次强调,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);
});

已更新!


我会保留原始回答,因为它使用了一种可能对某些人更有用的备选方法。但是,我想出了一个更短的函数,可以在“keydown”时工作,并且使用该函数的jQuery插件允许用户“按住”箭头键并仍然无限制地排序选项!

首先,是新的函数:

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

使用方式:$("select").keydown(keydownInfiniteSelect);

还有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);

使用 $("select").infiniteSelect() 或者 $.infiniteSelect("select")

插件的jsFiddle示例(被压缩)Minified

未被剪裁的插件jsFiddle示例

附注:我几乎已经为这个函数准备好了一个Vanilla JavaScript版本,只是该方法的“设置为最后一个选项”部分一直失败、出现null或跳到倒数第二个。我似乎无法正确地设置它。如果有人想修复并更新它,我将不胜感激。请参见此处


1
我认为这个答案的第一个版本使用了keydown而没有任何警告。如果是我,我不会因此而投反对票,但是现在这个答案看起来是一个完美的选择,并且避免了我的答案所存在的延迟问题。+1 - T.J. Crowder
1
这应该是被接受的答案。使用 keyup 比引入时间延迟更好。前者被设计为按照 OP 的要求工作,而后者则有点像一种 hack,可能会导致竞争条件。 - Nick Coons

5

这是正常的行为...

引用w3c规范

change
当控件在获取焦点后其值被修改并失去输入焦点时,会触发 change 事件。此事件适用于 INPUT、SELECT 和 TEXTAREA 元素。


1

通过以上答案,我能够使用以下方法获得所需的行为:

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

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

我忘记注释了。因此,输出只有一个输入字段和下面的四个选项选择框。您将鼠标焦点放在输入字段上,然后可以使用键盘上的向上和向下箭头键。您的选项将向上和向下切换。使用ENTER键读取所选选项的当前值。希望对某人有所帮助。 - Imeksbank

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

足够了


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接