jQuery unable to stop form submission on return key even with event.stopPropogation, event.preventDefault and return false
我刚刚使用jquery构建了一个自定义自动完成组件。我的问题是,当有人使用键盘上/下箭头键选择一个自动完成建议并点击返回时,即使我调用event.stopperopogation()和event.preventDefault(),也会发生表单提交,并返回false。
我已经将核心函数绑定到keyup事件:
1 | $('#'+id).keyup(function(event){ getResults(event,this,url,method,data,setEl,makeLink,cssClass); event.preventDefault(); event.stopPropagation(); return false;}); |
getresults对返回JSON对象的服务器脚本进行Ajax调用。getresults伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 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调用的成功处理程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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是一个简单的函数:
1 2 3 4 5 6 7 8 | function killEvent(event) { var keyCode = event.keyCode ? event.keyCode : event.which; if (keyCode == 13) { event.stopPropogation(); event.preventDefault(); return false; } } |
因此,所有的处理程序,甚至是自动完成建议列表的li元素都返回了false,并调用stopperopogation和preventdefault。但是,表单提交仍然会发生!我在这里做错了什么或是错过了什么。对不起,这封长信!
好吧,我找到了一种方法,在使用键盘的上/下键选择自动完成建议并输入时,当按下返回键时,停止浏览器的默认事件!
1 2 | $('#'+id).keydown(function(event){ return handleKey(event); }); $('#'+id).keyup(function(event){ return getResults(event,this,url,method,data,setEl,makeLink,cssClass); }); |
在keydown上,handlekey函数只检查keycode 13,然后调用stoppropagation和preventdefault!
这是手持钥匙的功能
1 2 3 4 5 6 7 8 9 10 | function handleKey(event) { var keyCode = event.keyCode ? event.keyCode : event.which; if (keyCode == 13) { event.preventDefault(); event.stopPropagation(); return false; } else { return true; } } |
因此,我取消了浏览器的默认操作键!在keyup上,getresults只检查并返回是否有选择!
诀窍是,要停止浏览器的默认操作,我们必须对keydown而不是keyup执行操作!
特别感谢克罗诺斯指出这一点!
不处理键向上事件,而是处理提交事件。在那里添加一个签入以确保所有内容都完整,如果不完整,则返回false。