我们的用户抱怨说,当他们在jQuery自动完成小部件中粘贴或键入值后按Enter键时,表单就会被提交。
当他们复制粘贴自动填充选项中存在的值以及自动填充小部件打开以显示单个值时,他们非常讨厌,他们按Enter键接受该值但是在填写所有字段之前提交表单因为(by default而且我们不想更改它)小部件不会选择菜单中的第一个选项。
<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"]
});
我们如何更改单击Enter将仅关闭自动填充建议?
答案 0 :(得分: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);
};
})();
备注:强>
$.fn
is an alias to $.prototype
。$.fn.autocomplete
,否则您所做的更改将不适用于这些小部件。this
函数中的autocomplete
实际上是一个jQuery对象,因此您不需要用$(this)
keypress
事件注册回调。好吧,这正是我正在做的以及为什么我将回调写为命名函数。如果您将同一个回调传递给addEventListener
,它只会注册一次。 MDN,Specifications 答案 1 :(得分:2)
使用jQuery autocomplete的autocompleteclose
和autocompleteopen
事件,我可能会有一个更简单的解决方案。
请参阅以下代码:
var flag = 0; //global variable
$("#autocomplete").on({
autocompleteclose: function (event, ui) {
flag = 1;
//set flag back to 0 with a short delay so the next keypress can submit form
setTimeout(function () {
flag = 0;
}, 100);
},
//if the autocomplete widget is open, don't submit form on keypress
autocompleteopen: function (event, ui) {
flag = 1;
}
});
$('body').keypress(function(e) {
if (e.keyCode == '13') {
if (flag != 0) {
e.preventDefault();
} else {
//submit form
}
}
});
var flag = 0; //global variable
$("#autocomplete").on({
autocompleteclose: function (event, ui) {
flag = 1;
//set flag back to 0 with a short delay so the next keypress can submit form
setTimeout(function () {
flag = 0;
}, 100);
},
//if the autocomplete widget is open, don't submit form on keypress
autocompleteopen: function (event, ui) {
flag = 1;
}
});
$('body').keypress(function (e) {
if (e.keyCode == '13') {
if (flag != 0) {
e.preventDefault();
} else {
//submit form
}
}
});
$('form').submit(function () {
alert('You submitted the form');
return false;
});
$('#autocomplete').autocomplete({
source: ["c#", "c", "c++", "java", "php", "coldfusion", "javascript", "asp", "ruby"]
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<form>Type C and press Enter:
<input id="autocomplete" />
<input type="submit" value="submit" />
</form>
&#13;
答案 2 :(得分:0)
我在某种程度上反对覆盖jqueryui实现并执行以下操作:
它背后的基本思想是,jqueryui的close事件在keyup或submit事件之前触发,并为你提供密钥代码。所以你可以在另一个地方(keyup,submit等)使用那个不需要的输入或其他按键。
答案 3 :(得分:0)
此问题与this one类似。虽然该页面上的解决方案很简单,但它们依赖于页面上ID的元素。我在很多页面上使用自动完成功能,因此我更喜欢gdoron的方法(在此页面上)。感谢他做了繁重的工作。
但是,我认为他的代码中存在错误。如果您转到已包含内容并键入退货的自动填充字段,则会提交表单。这是一个修复(更改是第二个&#34; if cancelAutocompleteSumbission中的块):
function cancelAutocompleteSumbission(e) {
// Make sure this is a nodeElement and the button pressed was Enter-Return
if (!this.nodeType || e.which != 13)
return;
if (!$(this).autocomplete('widget').is(':visible') && e.which === 13){
return false;
}
// 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);
};
})();