jQuery не может остановить отправку формы на ключ возврата даже с событием.стоппропогация, событие.preventDefault и return false
Я только что построил пользовательский компонент автозаполнения с помощью jquery. Моя проблема заключается в том, что когда кто-то использует клавиатуру со стрелками вверх/вниз для выбора одного из предложений автозаполнения и нажимает return, отправка формы происходит, даже если я вызываю событие.stopPropogation () и событие.функция preventDefault () также возвращает false.
Я привязал основную функцию к событию keyup:
$('#'+id).keyup(function(event){ getResults(event,this,url,method,data,setEl,makeLink,cssClass); event.preventDefault(); event.stopPropagation(); return false;});
GetResults вызывает ajax-скрипт сервера, который возвращает объект json. getResults псевдокод заключается в следующем:
function getResults(event,element,url,method,data,setEl,makeLink,cssClass) {
$(element).css("position","inherit");
var keyCode = event.keyCode ? event.keyCode : event.which;
if (keyCode == 40){ //down arrow key
if ($("#ac_"+element.id+" .hover").is("li")) { // some li is already on hover!
if ($("#ac_"+element.id+" .hover").is($("#ac_"+element.id+" li").last())) {
$("#ac_"+element.id+" .hover").removeClass("hover");
$("#ac_"+element.id+" li").first().addClass("hover");
} else {
$("#ac_"+element.id+" .hover").removeClass("hover").next().addClass("hover");
}
} else {
$("#ac_"+element.id+" li").first().addClass("hover");
}
event.stopPropagation();
event.preventDefault();
return false;
} else if (keyCode == 38){ //up arrow key
if ($("#ac_"+element.id+" .hover").is("li")) { // some li is already on hover!
if ($("#ac_"+element.id+" .hover").is($("#ac_"+element.id+" li").first())) {
$("#ac_"+element.id+" .hover").removeClass("hover");
$("#ac_"+element.id+" li").last().addClass("hover");
} else {
$("#ac_"+element.id+" .hover").removeClass("hover").prev().addClass("hover");
}
} else {
$("#ac_"+element.id+" li").last().addClass("hover");
}
event.stopPropagation();
event.preventDefault();
return false;
} else if (keyCode == 13){ //return key
if ($("#ac_"+element.id+" .hover").is("li")) { // some li is already on hover!
$("#ac_"+element.id+" .hover").removeClass("hover").trigger("click");
}
event.stopPropagation();
event.preventDefault();
return false;
}
if (setEl) { if (!$(element).val() || $(element).val()=="") { $("#"+setEl).val('');} }
if ($(element).val() != autocomplete_prev_search[element.id]) {
$("#ac_"+element.id).remove();
}
autocomplete_prev_search[element.id] = $(element).val();
if ($(element).val().length>=3) {
if (!url){return;}
if (!data) {
data = {match:$(element).val()};
} else {
data.match = $(element).val();
}
if (!method) { method = "POST"; }
$.ajax({
type: method,
url: url,
data: data,
success: function(result){ return resultHandler(result,element.id,setEl,makeLink,event); },
beforeSend: function(){ $(element).css("background-image","url('/kit/icons/indeterminate.gif')").css("background-repeat","no-repeat").css("background-position","right center"); },
complete:function(){ $(element).css("background-image","none"); },
error: errorHandler,
timeout: 1000,
dataType: "json"
});
}
return false;
}
Наконец, обработчик успеха вызова ajax выглядит следующим образом:
function resultHandler(result, id, setEl, makeLink, event) {
$("#ac_"+id).remove();
if (result && result.length>0) {
var $ul = $("<ul id='ac_"+id+"' class='autocomplete'></ul>");
var $li;
for (var i=0; i<result.length; i++) {
if (result[i]) {
if (makeLink) {
$li = $("<li onclick="location.href='/"+result[i].type+"/"+result[i].id+"'">"+result[i].type+" '"+result[i].title+"'</li>");
} else {
if (!setEl) {
$li = $("<li onclick="$('#"+id+"').val('"+result[i].id+"'); return killEvent(event);">"+result[i].type+" '"+result[i].title+"'</li>");
} else {
$li = $("<li onclick="$('#"+setEl+"').val('"+result[i].id+"'); $('#"+id+"').val('"+result[i].title+"');return killEvent(event);">"+result[i].type+" '"+result[i].title+"'</li>");
}
}
//$li.click(function(){ location.href="/"+result[i].type+"/"+result[i].id; });
// doesn't work as the click function has no access to result[i] object
$ul.append($li);
}
}
var left = $('#'+id).offset().left;
var top = $('#'+id).offset().top+$('#'+id).outerHeight();
$ul.css("width",$("#"+id).css("width")).css("left",left+"px").css("top",top+"px");
$ul.insertAfter('#'+id);
}
return false;
}
И, наконец, killEvent-это простая функция:
function killEvent(event) {
var keyCode = event.keyCode ? event.keyCode : event.which;
if (keyCode == 13) {
event.stopPropogation();
event.preventDefault();
return false;
}
}
Таким образом, все обработчики и даже щелчок по элементу li списка предложений автозаполнения возвращают false и вызывают stopPropogation и preventDefault. Однако подача формы все равно происходит! Что я здесь делаю неправильно или упускаю? Извините за длинный пост!
2 ответа:
Ну я нашел способ, чтобы остановить событие по умолчанию браузера, когда клавиша return нажата, делая выбор предложения автозаполнения с помощью клавиши up/down клавиатуры и enter!
$('#'+id).keydown(function(event){ return handleKey(event); }); $('#'+id).keyup(function(event){ return getResults(event,this,url,method,data,setEl,makeLink,cssClass); });
Где на keydown функция handleKey просто проверяет наличие ключевого кода 13, а затем вызывает stopPropagation и preventDefault!
Вот функция handleKey
function handleKey(event) { var keyCode = event.keyCode ? event.keyCode : event.which; if (keyCode == 13) { event.preventDefault(); event.stopPropagation(); return false; } else { return true; } }
Таким образом, я отменяю действие браузера по умолчанию на keydown! На keyup, getResults просто проверяет и возвращает, если есть выбор!
Фокус в том, что чтобы остановить действие браузера по умолчанию, мы должны действовать на keydown, а не на keyup!Спасибо всем, особенно Кроноссу, что указал на это!