<select> событие изменения не запускается при использовании клавиатуры - PullRequest
21 голосов
/ 21 марта 2012

http://jsfiddle.net/rFEER/

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

ЯШ:

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

почему событие изменения не вызывается при использовании (keyup / keydown), пока не нажата мышь

Ответы [ 6 ]

29 голосов
/ 21 марта 2012

почему событие изменения не вызывается при использовании (keyup / keydown), пока не нажата мышь

Также срабатывает, когда фокус покидает select. Вот как работает событие change.

Если вы хотите упреждающее уведомление, вы должны следить за change и keydown (по крайней мере, вы можете также хотеть click) и обрабатывать случай получения события, когда значение фактически не изменилось , и вы должны учитывать тот факт, что некоторые из этих событий (например, keydown) запускаются до того, как значение будет изменено, поэтому вам придется подождать минуту перед обработкой событие. Или см. ответ SpYk3HH , в котором вместо него используется keyup & mdash; это будет менее активно (не обновлять до выпуска ключа, что может быть желательно), но тогда вам не понадобится задержка (setTimeout), которую имеет мой код ниже.

Пример ( живая копия ):

HTML (я позволил себе сменить значения, чтобы было понятнее с каждым именем):

<select id="users">
<option value="j">jack</option>
<option value="b">brill</option>
<option value="a">antony</option>
</select>​

JavaScript:

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

Примечание в 2016 году: bind в значительной степени заменено на on. В приведенном выше тексте вы буквально замените «bind» на «on».

17 голосов
/ 21 марта 2012

Попробуйте изменить

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

до

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

, который должен ограничивать вашу функцию как для события onchange, так и для нажатия клавиши со стрелкой вниз или вверх

обратите внимание, вы также можете использовать 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 of Plugin Мини Fied

Uncut Plugin Fiddle

PS. У меня почти есть готовый JavaScript-код Vanilla для этой функции, за исключением того, что часть метода «set to last option» продолжает умирать, либо становится нулевой, либо пропускается со второго до последнего. Я просто не могу заставить его установить правильно. Если кто-то захочет исправить это и обновить, я буду очень признателен. См ЗДЕСЬ

5 голосов
/ 21 марта 2012

Это нормальное поведение ...

Цитирование w3c спецификаций

изменение
Событие изменения происходит, когда элемент управления теряет фокус ввода и его значение было изменено с момента получения фокуса. Это событие действительно для INPUT, SELECT и TEXTAREA. элемент.

1 голос
/ 30 января 2015

Используя ответы выше, я смог получить нужное мне поведение, используя:

$( "select" ).bind('keyup', function(e) {
    $(  '#' + e.target.id ).trigger('change');
});
0 голосов
/ 20 декабря 2014
/*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>
0 голосов
/ 22 февраля 2014
$("#users").bind('change keyup', function(e) {

было достаточно

...