4

我有一个使用 jQuery与<select>输入事件关联的处理程序:change

$('#myList').change(function () {
   //...
});

当用户Tab输入并开始输入时(没有点击打开下拉列表),不同的浏览器表现不同。

  • Enter在 Firefox 中,除非用户按下或Tab或以其他方式将焦点从选择列表中移开,否则更改事件不会触发。
  • 在 IE 和 Chrome 中,当用户键入导致选择列表中的项目发生更改的内容时,就会触发 change 事件。

因为我的change函数执行 AJAX 请求,所以我希望避免在用户键入或使用箭头键选择选项时让我的函数执行任何操作。但是,如果用户使用鼠标选择特定的下拉元素,或者如果用户按下回车键,我仍然希望触发 change 事件。换句话说,我希望 IE 和 Chrome 表现得像 Firefox。

是否有任何(理想情况下简单的)方法来获得我正在寻找的行为?

4

3 回答 3

2

编辑:

这应该可以满足您的所有要求 - http://jsfiddle.net/yfQ3V/4/

HTML:

<select data-value="one">
    <option>one</option>
    <option>two</option>
    <option>three</option>
</select>
<span></span>

JS:

var $select = $('select');
var $span = $('span');

var onChange = function () {
    setText();
};

var onKeyDown = function () {
    $select.off('change');
    var keyCode = e.keyCode || e.which;

    if(keyCode == 13 || keyCode == 9) {
        $select.on('change', onChange).change(); 
    }
};

var onBlur = function () {
    if($select.val() != $select.data('value')) {
        setText();
    }
};

var setText = function () {
    var val = $select.val();
    $select.data('value', val);
    $span.text(val + ' - ' + new Date());   
};

$select.on('change', onChange)
       .on('keydown', onKeyDown)
       .on('blur', onBlur);
于 2012-04-11T21:32:07.460 回答
1

我最终创建了一种方法,该方法将使我的所有<select>控件都以相同的方式运行,这样我就不必在每种特定情况下都执行一次性的 Javascript。这有点 hacky,但至少我避免了这样的重复代码:

$(function() {
    // Make select lists in Chrome and IE behave more like Firefox: when they are focused
    // but not open and the user starts typing, we don't want the "change" event to fire
    // until the user has actually selected the value they want.
    var invokePendingChanges = function () {
        /// <summary>
        /// Event handler which checks "this" select box for a code that shows that changed
        /// events have been ignored. If it finds the code, it will invoke the 'change'
        /// event on the input.
        /// </summary>
        var t = $(this);
        if (t.data('change-pending')) {
            setTimeout(function () {
                t.data('change-pending', false);
                t.change();
            }, 0);
        }
    };
    $('select')
        .keydown(function(e) {
            // If the user hit the enter key, invoke pending changes.
            if (e.which == 13) {
                invokePendingChanges.call(this);
            } else {
                var t = $(this);
                // Be aware that date('events') isn't part of the official API, so it is subject
                // to change with future versions of jQuery.
                var allHandlers = t.data('events');
                var changeHandlers = allHandlers ? allHandlers['change'] : null;
                delete allHandlers['change'];
                t.change(function() {
                    t.data('change-pending', true);
                    return false;
                });

                var revert = function() {
                    allHandlers['change'] = changeHandlers;
                    clearTimeout(timeout);
                    t.off('blur', revert);
                };
                t.on('blur', revert);
                var timeout = setTimeout(revert, 0);
            }
        })
        .blur(invokePendingChanges);
});
于 2012-06-04T18:50:24.703 回答
1

这是我的解决方案,基于 tjscience 的回答。它被实现为一个 jquery 函数,并且在使用不同的处理程序多次绑定到同一个元素时工作。

$.fn.dropDownChangeEventThatBehavesLikeFirefox = function (handler) {
/// <summary>The change() event behaviour for select boxes is different between Firefox and other browsers when using the keyboard.
/// Firefox only fires the change event when focus is lost, whereas other browsers fire the change event as soon the user uses the
/// keyboard to scroll through the select box.
/// This method should be used instead of the name jquery change() event to get consistent behaviour between Firefox and
/// other browsers (preferring the Firefox method).
/// </summary>
if ($.browser.mozilla) {
    // Firefox already behaves like we want it to, so get out of here.
    $(this).change(handler);
    return;
}

$(this).each(function () {

    var lastValue = $(this).val();

    $(this)
        .change(function () {
            var $this = $(this);

            handler.apply(this);

            lastValue = $this.val();
        })
        .keydown(function (e) {
            var $this = $(this);

            $this.off('change');
            var keyCode = e.keyCode || e.which;

            if (keyCode == 13 || keyCode == 9) {
                $this.on('change', handler).change();
            }
        })
        .on('blur click', function () {
            var $this = $(this);

            if ($this.val() != lastValue) {
                handler.apply(this);
                lastValue = $this.val();
            }
        });
});
};
于 2012-06-20T06:09:39.913 回答