拦截按钮回发的最佳方法

6

我看到了其他的解决方案,比如这个很直接,但如果 JavaScript 函数除了 confirm('sure?'); 之外还有别的操作呢,我就不知道它何时会返回布尔值。

因此,我决定将我所有的 ASP.NET 按钮都实现为:

<button id="btnDelete" name="btnDelete" class="btn">Delete</button>
<asp:Button ID="_btnDelete" runat="server" OnClick="_btnDelete_Click" style="display:none;" />

$('#btnDelete').click(function (e) {
    $.blockUI({ message: $('#divConfirmDeleteModal'), overlayCSS: { cursor: 'default' }, css: { cursor: 'default' }, baseZ: 5555 });
    return false;
});

$('#btnDeleteYes').click(function () {
    $('#<%=_btnDelete.ClientID%>').trigger('click');
});

$('#<%=_btnDelete.ClientID%>').click(function (e) { 
    // the delay happens here. if i put an alert here, it fires,
    // but then the page just loads until eventually the method gets called
    <%= ClientScript.GetPostBackEventReference(_btnDelete, string.Empty) %>; 
});

一直以来,它都运行良好,但现在我在IE中(甚至版本10)遇到了问题——在单击最终触发它的按钮后,_btnDelete_Click将需要长达2分钟才能被调用。

这种方法感觉太过hacky,我想知道是否有更好的方法。

编辑:这里是另一种“正确”的方法,但我想使用一个更漂亮的模态对话框,并在“是”点击时返回true,而不是使用浏览器的原生确认对话框。

编辑2:我想问的是,是否有一种方法可以为执行多个操作的OnClientClick函数返回bool值。


为什么不在服务器端处理这个问题? - Chris Cannon
你的意思是什么?使用ClientScript.RegisterStartupScript吗?我想要在客户端处理它。 - notAnonymousAnymore
我不会依赖JavaScript,特别是对于公共网站而言。如果JavaScript被禁用或者他们使用的移动浏览器支持JavaScript较差,那该怎么办呢?你想要实现什么目标? - Chris Cannon
我不知道其他拦截按钮点击的方法,而且我想在按钮被点击之前做一些js操作,然后再进行postback。客户对网站依赖启用js没有问题。 - notAnonymousAnymore
我刚刚制作了一个具有相同布局的示例页面,并且发布时间并不长。也许还有其他问题吗?可能是其他JavaScript阻止了吗? - Andrew Walters
非常奇怪 - 延迟只发生在IE浏览器上,而且只有在第二次使用按钮时才会出现。所以ViewState发生了一些奇怪的事情,我懒得去调试,因此提出这个问题。我想我会采用Bikonja的建议 - 这似乎是最安全的方法。我想我可以提供精确的重现问题的步骤,但那只是为了教育目的:P(也许有人可以找出延迟发生的原因) - notAnonymousAnymore
3个回答

3
如果您在客户端脚本中手动触发点击事件,那么您的应用程序将无法与移动浏览器的“转到”按钮正常工作。
以下是如何拦截按钮的服务器端单击事件,而无需在客户端手动触发它。
<script type="text/javascript">
    function clientClick() {
        if (confirm("Are you sure you want to delete?")) {
            // Do something at client side before posting back to server
            return true;
        }
        return false;
    }
</script>

<asp:Button runat="server" ID="DeleteButton" Text="Delete" 
    OnClick="DeleteButton_Click" OnClientClick="return clientClick();" />

ASP.NET MVC提供了很多高级功能,但是在传统的ASP.NET中使用它们会引起很多问题。


我无法理解如何显示一个更高级的模态对话框(例如BlockUI),而不是使用confirm(''),并且在“是”点击时返回true。 - notAnonymousAnymore
1
在按钮的OnClientClick事件中始终返回false,并在更高级的模态对话框中添加实际的PostBack按钮以执行实际的PostBack。除非您有一个iframe或类似的东西,否则这应该没问题。毕竟,这就是您想要做的 - “主”按钮不应该真正执行操作,“确认”按钮应该执行操作,不是吗? - Bikonja

0
如果您想展示一个更加华丽的模态对话框,可以使用jQuery UI对话框小部件。为了与您的示例保持一致,请查看以下代码,用于示例Web表单的body元素:
<form id="form1" runat="server">
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
    <div id="deleteConfirmationDialog" title="Warning!">Are you sure you want to delete?</div>
    <asp:Button ID="_btnDelete" runat="server" Text="Delete" OnClick="_btnDelete_ServerClick" OnClientClick="return _btnDelete_ClientClick();" />
</form>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript">
    function doPostBack(theForm, eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }

    function showConfirmationDialog(dialogSelector, callback, form, target) {
        $(dialogSelector).dialog({
            resizable: false,
            height: 200,
            modal: true,
            buttons: [{
                text: "Yes",
                click: function () {
                    $(this).dialog("close");
                    callback(form, target, null);
                }
            },
            {
                text: "No",
                click: function () {
                    $(this).dialog("close");
                }
            }]
        });
    };

    function _btnDelete_ClientClick() {
        showConfirmationDialog("#deleteConfirmationDialog", doPostBack, $("#form1").get(0), "_btnDelete");
        return false;
    }

    $(document).ready(function () {
        $("#deleteConfirmationDialog").hide();
    });
</script>

与控件“_btnDelete”相关联的代码(方法“_btnDelete_ServerClick”)仅在您单击“删除”按钮后显示的模态对话框中点击“Yes”按钮时才会执行。不要忘记将jQuery UI CSS文件添加到头部部分:
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery.ui.all.css"/>

0

被压抑的记忆被唤醒了 - 我在3.5年前与asp.net Webforms战斗的时候也是如此。我们必须通过按下回车键在网格内实现ajax调用,并显示模态对话框以确认订单,以防产品有一些备注(如翻新等)。

浏览一些旧的代码片段,我发现各种各样的javascript来防止默认和冒泡

// prevent the browser event bubbling for example posting the webform
function stopDefault(e) {

    if (e.preventDefault) {
        e.preventDefault();
        e.stopPropagation();

    } else {
        event.returnValue = false;
        event.cancelBubble = true;
        e.returnValue = false;
        e.cancelBubble = true;              
    }
}

像这样的HTML/ASP

<button type="button" 
     onclick="SearchProducts(event,this);">Search Products</button>
<asp:Button ID="btnSearch" ClientIDMode="Static" runat="server" 
 onclick="btnSearch_Click"  
 OnClientClick="SearchProducts(event,this)"
 UseSubmitBehavior="false"
 Text="Does nothing" />  

最终我只使用了标准的HTML按钮,避免使用asp:Button,因为与asp.net webforms内置功能和后台魔法作斗争会更加麻烦。

如果你可以避免使用asp:button,我真的很推荐这样做。


感谢提供代码片段。在可以避免使用它们的情况下,我会避免使用它们,但对于像文件上传之类的东西,我想我会使用它们。向MVC的转变是缓慢的。 - notAnonymousAnymore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接