修改jQuery自动完成不要在Enter上急切地提交

gdo*_*ica 2 html javascript jquery jquery-ui jquery-ui-autocomplete

我们的用户抱怨说,当他们在粘贴或在jQuery自动完成小部件中键入值后按Enter键时,表单将被提交.

当他们复制粘贴自动完成选项中存在的值以及自动完成小部件打开以显示单个值时,他们非常烦人,他们按Enter键接受该值但是在填写完所有字段之前提交表单因为(通过默认情况下,我们不想更改它)窗口小部件不会选择菜单中的第一个选项.

<form>Type C and press Enter:
    <input id="autocomplete" />
    <input type="submit" value="submit" />
</form>

$('form').submit(function () {
    alert('You submitted the form');
    return false;
});

$('#autocomplete').autocomplete({
    source: ["c#", "c", "c++", "java", "php", "coldfusion"]
});    
Run Code Online (Sandbox Code Playgroud)

DEMO的问题

我们如何更改单击Enter将仅关闭自动填充建议?

gdo*_*ica 5

似乎jQuery UI没有留下后门来自定义开箱即用的小部件,所以你可以做的是覆盖autocomplete函数来注册onkeypress事件的回调,捕获Enter并停止传播,这样它就不会提交窗体,如果窗口小部件是打开=可见.

它是怎么回事:

function cancelAutocompleteSumbission(e) {
    // Make sure this is a nodeElement and the button pressed was Enter-Return
    if (!this.nodeType || e.which != 13)
        return;

    // If the widget is visible we simply want to close the widget.
    if ($(this).autocomplete('widget').is(':visible')) {
        $(this).autocomplete('close');
        return false;
    }
}
// Making a private scope to avoid naming collision.
$.fn.autocomplete = (function () {
    // Cache the old autocomplete function.
    var oldAutocomplete = $.fn.autocomplete;

    // This will be the new autocomplete function.
    return function () {
        // If the first argument isn't "destroy" which 
        // should restore the input to it's initial state.
        if (!/^destroy$/i.test(arguments[0]))
            // Attach event to the input which will prevent Enter submission as
            // explained above.
            this.keypress(cancelAutocompleteSumbission);                
        // We need to restore the input to it's initial state,
        // detach the keypress callback.    
        else
            this.off('keypress', cancelAutocompleteSumbission);

        // Call the cached function with the give "this" scope and paramteres.
        return oldAutocomplete.apply(this, arguments);
    };
})();
Run Code Online (Sandbox Code Playgroud)

现场演示


笔记:

  • 要更改所有需要使用jQuery原型的自动完成小部件,$.fn是别名$.prototype.
  • 您还需要$.fn.autocomplete在使用之前进行更改,否则您所做的更改将不适用于这些小部件.
  • thisautocomplete函数内部实际上是一个jQuery对象,所以你不需要用它包装它$(this)
  • 你可能会说,嘿,你保持注册keypress事件的回调.好吧,这正是我正在做的以及为什么我将回调写为命名函数.如果您将相同的回调传递给addEventListener它,则只会注册一次.MDN,规格
  • 以编程方式将代码添加到javascript函数