如何覆盖 OnBeforeUnload 对话框并将其替换为我自己的?
Posted
技术标签:
【中文标题】如何覆盖 OnBeforeUnload 对话框并将其替换为我自己的?【英文标题】:How can I override the OnBeforeUnload dialog and replace it with my own? 【发布时间】:2010-09-21 13:22:54 【问题描述】:我需要在用户离开页面之前警告用户未保存的更改(这是一个很常见的问题)。
window.onbeforeunload = handler
这可行,但它会引发一个默认对话框,其中包含我自己的文本的令人讨厌的标准消息。我需要完全替换标准消息,以便我的文本清晰,或者(甚至更好)使用 jQuery 将整个对话框替换为模态对话框。
到目前为止,我失败了,我还没有找到其他人似乎有答案。有可能吗?
我的页面中的javascript:
<script type="text/javascript">
window.onbeforeunload = closeIt;
</script>
closeIt() 函数:
function closeIt()
if (changes == "true" || files == "true")
return "Here you can append a custom message to the default dialog.";
使用 jQuery 和 jqModal 我已经尝试过这种事情(使用自定义确认对话框):
$(window).beforeunload(function ()
confirm('new message: ' + this.href + ' !', this.href);
return false;
);
这也不起作用 - 我似乎无法绑定到 beforeunload
事件。
【问题讨论】:
你能举例说明你当前的代码以及它产生了什么吗? 欧文是正确的。而且,这背后的原因是安全性。阻止页面卸载在 Web 表单等中很有用,但它很容易被恶意网站利用来欺骗用户留在页面上。这就是网络浏览器实现标准消息并具有插入自定义文本的机制的原因。 查看这里了解更多信息:***.com/questions/140460 更多信息:***.com/questions/7389554/crossbrowser-onbeforeunload/… 无法在 chrome 中使用,参考:***.com/questions/37782104/… 【参考方案1】:试试这个
$(window).bind('beforeunload', function (event)
setTimeout(function ()
var retVal = confirm("Do you want to continue ?");
if (retVal == true)
alert("User wants to continue!");
return true;
else
window.stop();
return false;
);
return;
);
【讨论】:
【参考方案2】:Angular 9 方法:
constructor()
window.addEventListener('beforeunload', (event: BeforeUnloadEvent) =>
if (this.generatedBarcodeIndex)
event.preventDefault(); // for Firefox
event.returnValue = ''; // for Chrome
return '';
return false;
);
浏览器支持和删除自定义消息:
Chrome 在 51 分钟版本中移除了对自定义消息的支持 Opera 在 38 分钟版本中删除了对自定义消息的支持 Firefox 在 44.0 分钟版本中删除了对自定义消息的支持 Safari 在 9.1 分钟版本中移除了对自定义消息的支持【讨论】:
【参考方案3】:使用 jQuery 并在 IE8、Chrome 和 Firefox 中测试对我有用的是:
$(window).bind("beforeunload",function(event)
if(hasChanged) return "You have unsaved changes";
);
如果不需要提示,请务必不要返回任何内容,因为此处的 IE 和其他浏览器行为之间存在差异。
【讨论】:
有趣,event.returnValue
是 IE 中唯一“认可”的方法。 IE goes on to say “此属性的值优先于函数返回的值,例如通过 Microsoft JScript 返回语句。” .. 很高兴看到return
(来自事件)和event.returnValue
之间有保证的相关性..【参考方案4】:
您无法修改onbeforeunload
的默认对话框,因此最好的办法是使用它。
window.onbeforeunload = function()
return 'You have unsaved changes!';
Here's a reference 来自微软:
将字符串分配给 window.event 的 returnValue 属性时,会出现一个对话框,让用户可以选择留在当前页面并保留分配给它的字符串。对话框中显示的默认语句“您确定要离开此页面吗?...按 OK 继续,或按 Cancel 留在当前页面。”无法删除或更改。
问题似乎是:
-
当
onbeforeunload
被调用时,它将处理程序的返回值作为window.event.returnValue
。
然后它将返回值解析为字符串(除非它为空)。
由于false
被解析为字符串,对话框将触发,然后传递适当的true
/false
。
结果是,似乎没有办法将false
分配给onbeforeunload
以防止其进入默认对话。
关于 jQuery 的补充说明:
在 jQuery 中设置事件可能有问题,因为这也允许其他onbeforeunload
事件发生。如果你只希望你的卸载事件发生,我会坚持使用普通的 JavaScript。
jQuery 没有 onbeforeunload
的快捷方式,因此您必须使用通用的 bind
语法。
$(window).bind('beforeunload', function() );
编辑 09/04/2018:自 chrome-51 以来,onbeforeunload 对话框中的自定义消息已被弃用(参见:release note)
【讨论】:
我发现最后给出的 JQuery 示例在 Firefox 中不起作用。坚持使用简单的方法:window.onbeforeunload = function() ... 请注意,Firefox 最近已更改,因此对话框中的文本甚至无法自定义:bugzilla.mozilla.org/show_bug.cgi?id=588292 那么facebook是如何提供自定义对话框的呢?例如,转到消息页面,回复您朋友的消息,然后在单击发送之前,尝试单击另一个链接。你会看到一个自定义对话框弹出 @Varun - 旧消息,但 Facebook 可能会在其所有锚点的点击事件上放置处理程序,但如果您在浏览器中重写 URL 或关闭窗口,它会恢复为他们的标准方法无法控制。 @Varun 我也很惊讶,这个不可能的答案被标记为答案并有 150 个赞成票......刚刚意识到,FB 的自定义消息只能通过其网站内的链接获得。如果您只是导航离开...【参考方案5】:如何使用“绑定”命令“一”的专用版本。一旦事件处理程序第一次执行,它会作为事件处理程序自动删除。
$(window).one("beforeunload", BeforeUnload);
【讨论】:
很确定这是 .on("beforeunload" @SergiuMindras 不,它是.one()
- 附加一个事件侦听器以侦听仅发生一次的事件:“将处理程序附加到元素的事件。处理程序最多执行一次每个事件类型的每个元素。” api.jquery.com/one【参考方案6】:
为了避免垃圾邮件,现在无法在 chrome 中执行此操作,请参阅javascript onbeforeunload not showing custom message 了解更多详细信息。
【讨论】:
【参考方案7】:我遇到了同样的问题,我可以在自己的对话框中显示我的消息,但我遇到的问题是: 1)它在所有导航上都给出消息,我只希望它用于关闭点击。 2)如果用户选择取消,我自己的确认消息仍然显示浏览器的默认对话框。
以下是我找到的解决方案代码,我写在我的母版页上。
function closeMe(evt)
if (typeof evt == 'undefined')
evt = window.event;
if (evt && evt.clientX >= (window.event.screenX - 150) &&
evt.clientY >= -150 && evt.clientY <= 0)
return "Do you want to log out of your current session?";
window.onbeforeunload = closeMe;
【讨论】:
【参考方案8】:尝试放置 return;
而不是消息。这对我来说适用于大多数浏览器。
(这只会真正阻止对话框的呈现)
window.onbeforeunload = function(evt)
//Your Extra Code
return;
【讨论】:
return null 将阻止对话框打开 return null 不会阻止对话框打开。我在 Chrome 中尝试过,但不是这样。 我也可以在 IE 中确认 Ray 的评论。返回null
将打开一个带有“null”文本的对话框。但是,return void(0);
不会打开对话框。
在 beforeunload 函数中不放任何 return 语句,对话框将不会打开。【参考方案9】:
1) 使用 onbeforeunload,而不是 onunload。
2) 重要的是避免执行 return 语句。我并不是说要避免从您的处理程序返回。您可以正常返回,但是您要确保到达函数的末尾并且不要执行 return 语句。在这些情况下,不会出现内置标准对话框。
3) 如果你使用 onbeforeunload,你可以在你的 unbeforeunload 处理程序中运行一个 ajax 调用来整理服务器,但它必须是一个同步的,你必须等待并处理你的 onbeforeunload 处理程序中的回复(仍然尊重上述条件(2))。我这样做并且效果很好。如果您执行同步 ajax 调用,则一切都会暂停,直到响应返回。如果您执行异步操作,并认为您不关心来自服务器的回复,则页面卸载继续并且您的 ajax 调用被此进程中止 - 包括远程脚本(如果它正在运行)。
【讨论】:
仅供阅读的任何人阅读此内容^ Chrome 正在 unbeforeunload 中弃用同步 AJAX 调用【参考方案10】:虽然在某些情况下您无法对该框执行任何操作,但您可以拦截点击链接的人。对我来说,这在大多数情况下都是值得的,作为后备,我已经离开了 unload 事件。
我使用 Boxy 而不是标准的 jQuery Dialog,它可以在这里找到:http://onehackoranother.com/projects/jquery/boxy/
$(':input').change(function()
if(!is_dirty)
// When the user changes a field on this page, set our is_dirty flag.
is_dirty = true;
);
$('a').mousedown(function(e)
if(is_dirty)
// if the user navigates away from this page via an anchor link,
// popup a new boxy confirmation.
answer = Boxy.confirm("You have made some changes which you might want to save.");
);
window.onbeforeunload = function()
if((is_dirty)&&(!answer))
// call this if the box wasn't shown.
return 'You have made some changes which you might want to save.';
;
您可以附加到另一个事件,并根据单击的锚点进行更多过滤,但这适用于我和我想要做的事情,并且可以作为其他人使用或改进的示例。以为我会为那些想要这个解决方案的人分享这个。
我已经剪掉了代码,所以这可能无法正常工作。
【讨论】:
return '你做了一些你可能想要保存的更改。'对我不起作用。我不得不将消息存储在一个变量中,比如“warning_message”,并且我确实返回了warning_message。然后只有它对我有用!。 你在 IE、Chrome、Firefox 中测试过吗?【参考方案11】: <script type="text/javascript">
window.onbeforeunload = function(evt)
var message = 'Are you sure you want to leave?';
if (typeof evt == 'undefined')
evt = window.event;
if (evt)
evt.returnValue = message;
return message;
</script>
参考http://www.codeprojectdownload.com
【讨论】:
【参考方案12】:您可以检测用户按下了哪个按钮(确定或取消),因为仅当用户选择离开页面时才会调用 onunload 函数。尽管在这个函数中可能性是有限的,因为 DOM 正在被折叠。您可以运行 javascript,但 ajax POST 不执行任何操作,因此您不能使用此方法进行自动注销。但是有一个解决方案。在 onunload 函数中执行 window.open('logout.php') ,因此用户将在新窗口打开时注销。
function onunload = ()
window.open('logout.php');
当用户离开页面或关闭活动窗口并且用户通过'logout.php'注销时调用此代码。 注销php包含代码时新窗口立即关闭:
window.close();
【讨论】:
可以在 beforeunload 和 unload 函数中使用同步 post。特别是如果您需要从服务器返回数据。在页面卸载时,这些块中的任何异步代码都可能无法完成。以上是关于如何覆盖 OnBeforeUnload 对话框并将其替换为我自己的?的主要内容,如果未能解决你的问题,请参考以下文章
捕获window.onbeforeunload确认对话框的结果
从 Selenium 测试 onbeforeunload 事件