【问题标题】:jQuery unable to stop form submission on return key even with event.stopPropogation, event.preventDefault and return false即使使用 event.stopPropogation、event.preventDefault 和 return false,jQuery 也无法在返回键上停止表单提交
【发布时间】:2012-02-05 00:31:49
【问题描述】:

我刚刚使用 jquery 构建了一个自定义的自动完成组件。我的问题是,当有人使用键盘上/下箭头键选择自动完成建议之一并点击返回时,即使我调用 event.stopPropogation()event.preventDefault() 并返回 false,表单提交也会发生。

我已经将核心函数绑定到keyup事件:

$('#'+id).keyup(function(event){ getResults(event,this,url,method,data,setEl,makeLink,cssClass); event.preventDefault(); event.stopPropagation(); return false;});

getResults 对返回 json 对象的服务器脚本进行 ajax 调用。 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调用的成功handler如下:

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 并调用 stopPropogationpreventDefault。但是,表单提交仍然发生!我在这里做错了什么或错过了什么。抱歉发了这么长的帖子!

【问题讨论】:

    标签: jquery autocomplete form-submit preventdefault stoppropagation


    【解决方案1】:

    好吧,我找到了一种方法,可以在按下返回键时停止浏览器的默认事件,同时使用键盘的向上/向下键选择自动完成建议并输入!

    $('#'+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!

    这里是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 进行操作!

    特别感谢 CronosS 指出这一点!

    【讨论】:

      【解决方案2】:

      处理提交事件,而不是处理按键事件。在那里添加一个检查以确保一切都完成,如果没有,则返回 false。

      【讨论】:

      • 不,整个自动完成设置绑定到它必须操作的文本框上的 keyup 事件!另一个问题是我想让这个自动完成功能通用。所以我想要实现的只是它在它绑定的文本框上捕获返回键并简单地使用选择的值,但是不让表单提交!
      • @DeeTee 这就是重点。您阻止浏览器在按键时的默认操作,而浏览器在之前发送表单:按键时。
      • @DeeTee 如果您不想提交表单,您可以做的最简单的事情是处理提交事件,以便仅在满足所有条件时提交。否则,不要在您的 html 中使用表单进行提交,而是通过单击提交按钮进行 Ajax 发布。
      • @CronosS 我不知道浏览器对 keydown 起作用。我将尝试更改绑定以触发自动完成到 keydown 并查看!同时感谢:)
      猜你喜欢
      • 2012-09-26
      • 2021-09-01
      • 2020-11-02
      • 1970-01-01
      • 1970-01-01
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 2018-11-28
      相关资源
      最近更新 更多