【问题标题】:Way to know if user clicked Cancel on a Javascript onbeforeunload Dialog?如何知道用户是否在 Javascript onbeforeunload 对话框上单击了取消?
【发布时间】:2011-01-10 19:34:09
【问题描述】:

当有人试图在未保存其工作的情况下离开特定页面时,我会弹出一个对话框。我使用 Javascript 的 onbeforeunload 事件,效果很好。

现在我想在用户在出现的对话框上单击“取消”时运行一些 Javascript 代码(表示他们不想离开页面)。

这可能吗?我也在使用 jQuery,所以是否有像 beforeunloadcancel 这样的事件可以绑定?

更新:这个想法是在用户选择取消时实际保存并将其引导到不同的网页

【问题讨论】:

  • 我不认为这是可能的......但我希望我错了。
  • 我真的很好奇您如何使用自定义对话框阻止导航器。能否提供代码?
  • @jAndy,在 Javascript 中查找 onbeforeunload 事件,它就是这样做的。
  • @at:我知道该事件,但这仅适用于弹出的默认模式对话框。您的帖子听起来像是在事件处理程序中创建自定义 UI 对话框或其他内容。

标签: javascript jquery dom-events onbeforeunload


【解决方案1】:

你可以这样做:

$(function() {
    $(window).bind('beforeunload', function() {
        setTimeout(function() {
            setTimeout(function() {
                $(document.body).css('background-color', 'red');
            }, 1000);
        },1);
        return 'are you sure';
    });
}); 

第一个setTimeout 方法中的代码有1ms 的延迟。这只是将函数添加到UI queue 中。由于setTimeout 异步运行,Javascript 解释器将继续直接调用return 语句,这反过来又触发浏览器modal dialog。这将阻塞UI queue,并且第一个setTimeout 中的代码不会执行,直到模态关闭。如果用户按下取消,它将触发另一个 setTimeout,它会在大约一秒内触发。如果用户用 ok 确认,用户将重定向并且第二个 setTimeout 永远不会被触发。

示例:http://www.jsfiddle.net/NdyGJ/2/

【讨论】:

  • @jAndy。当用户选择离开此页面选项时,SetTimeOut 也会触发。我们怎样才能阻止它。
  • 截至 2014 年 1 月,此方法不适用于 chrome。
  • @ScottEvernden 我刚刚用两个最新版本的 Chrome 对其进行了测试,它(又一次?)可以工作,包括版本 40.0.2214.94
  • 这不适用于慢速连接:无论确认选择如何,都会调用第二个超时,并且可以在实际卸载之前执行(在受限制的 Chrome 上)。
  • 在 Chrome 64 中不起作用。它真的不希望你执行任何代码。我正在保存 onblur。如果您单击“重新加载”,它会保存,因为已触发模糊。如果你只是按回车,它不会触发 onblur,因此不会保存。
【解决方案2】:

我知道这个问题现在已经过时了,但如果有人对此仍有疑问,我找到了一个似乎对我有用的解决方案,

基本上unload 事件在beforeunload 事件之后触发。我们可以使用它来取消在beforeunload 事件中创建的超时,修改 jAndy 的答案:

$(function() {
    var beforeUnloadTimeout = 0 ;
    $(window).bind('beforeunload', function()  {
        console.log('beforeunload');
        beforeUnloadTimeout = setTimeout(function() {
            console.log('settimeout function');
            $(document.body).css('background-color', 'red');
        },500);
        return 'are you sure';
    });
    $(window).bind('unload', function() {
        console.log('unload');
        if(typeof beforeUnloadTimeout !=='undefined' && beforeUnloadTimeout != 0)
            clearTimeout(beforeUnloadTimeout);
    });
}); 

编辑: jsfiddle here

【讨论】:

  • 这对你有用吗?因为在我的情况下,我在计时器函数执行后得到unload 类似的方式......(我在 Firefox 35 中测试过)
  • 是的,这对我有用,尝试增加超时功能的时间。
  • 我进行了更多测试,发现如果我放置大约 5 秒(而不是 0.5 秒),它会按预期工作。但我认为,如果您取消对话,那就太过分了......太糟糕了,我们没有得到更好的反馈。
  • 这是个好主意。但是,它受到延迟的影响。在最坏的情况下,Web 服务器被关闭,并且 beforeunload 超时的长度必须等于浏览器的超时。
【解决方案3】:

不可能。也许有人会证明我错了......你想运行什么代码?你想在他们点击取消时自动保存吗?这听起来违反直觉。如果您还没有自动保存,我认为当他们点击“取消”时自动保存几乎没有意义。也许您可以在 onbeforeunload 处理程序中突出显示保存按钮,以便用户在离开之前看到他们需要做什么。

【讨论】:

  • 我们的想法是,如果他们选择取消,则实际保存并引导他们到不同的网页。
【解决方案4】:

我不认为这是可能的,但只是尝试了这个想法并且它有效(尽管它有点像黑客,并且可能在所有浏览器中都无法正常工作):

window.onbeforeunload = function () {   
  $('body').mousemove(checkunload);
  return "Sure thing"; 
};

function checkunload() {   
  $('body').unbind("mousemove");
  //ADD CODE TO RUN IF CANCEL WAS CLICKED
}

【讨论】:

  • 如果您在点击确定离开站点后移动鼠标,“取消代码”仍然会运行...
  • 我想你可以在绑定 mousemove 事件之前添加一个超时,这可能会修复它,尽管这使它更像是一个 hack。
  • 现有窗口消失需要超过 1 秒,如果您移动鼠标,它看起来就像取消。有一个计时器与 jAndy 的答案有同样的缺点,这对我来说不合适。
【解决方案5】:

另一种变化 第一个 setTimeout 等待用户响应浏览器的离开/取消弹出窗口。第二个 setTimeout 等待 1 秒,然后只有在用户取消时才调用 CancelSelected。否则页面会被卸载,setTimeout 会丢失。

window.onbeforeunload  = function(e) {
    e.returnValue = "message to user";
    setTimeout(function () { setTimeout(CancelSelected, 1000); }, 100);
}

function CancelSelected() {
    alert("User selected stay/cancel");
}

【讨论】:

  • 如果我刷新页面并选择退出并且新页面需要一些时间才能加载,则会显示警报...不好
【解决方案6】:
window.onbeforeunload  = function() {
    if (confirm('Do you want to navigate away from this page?')) {
        alert('Saving work...(OK clicked)')
    } else {
        alert('Saving work...(canceled clicked)')
        return false
    }
 }

如果用户在 IE8 中单击“取消”,则使用此代码也会出现默认导航对话框。

【讨论】:

  • 你不能在附加到onbeforeunload的函数中使用confirm()
  • @jyoti:看来你是想评论someone else's answer。为此,请单击具体答案下方的add a comment 链接。请从线程中删除此答案,因为它现在是错误答案的副本,否则很快就会被否决。
猜你喜欢
  • 1970-01-01
  • 2013-07-30
  • 2014-11-26
  • 1970-01-01
  • 2016-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多