简体   繁体   English

mailto 链接(在 chrome 中)正在触发 window.onbeforeunload - 我可以防止这种情况吗?

[英]mailto link (in chrome) is triggering window.onbeforeunload - can i prevent this?

Possibly related to How to open mailto link in Chrome with Window.open without creating a new tab?可能与如何在 Chrome 中使用 Window.open 打开 mailto 链接而不创建新标签有关?

Hi all.大家好。 I have a form page where i've put a window.onbeforeunload confirm, to stop people navigating away and losing their changes by accident:我有一个表单页面,我在其中放置了 window.onbeforeunload 确认,以阻止人们导航并意外丢失更改:

window.onbeforeunload = function(){
  if(changed)
    return "You have unsaved changes.  Do you really want to leave this page without saving?";
};  

where changed is a variable i set to true whenever the user makes any changes.其中changed是将变量i设置为true,每当用户进行任何更改。 That's all fine.这一切都很好。 However, i've also added some mailto links to the page, like so:但是,我还向页面添加了一些 mailto 链接,如下所示:

<a class="button button-alt" href="mailto:foo@foo.com">Report a problem</a>

Even though the mailto isn't navigating away from the page (it's opening the users default mail app), it's still triggering the onbeforeunload event, prompting the confirm box, which is annoying.即使 mailto 没有离开页面(它正在打开用户默认的邮件应用程序),它仍然会触发 onbeforeunload 事件,提示确认框,这很烦人。 I can get round it setting target="_blank" on the link, but then the user is left sitting in an empty tab.我可以绕过它在链接上设置target="_blank" ,但随后用户会坐在一个空的选项卡中。

Can i set the mailto link to not trigger the onbeforeunload event?我可以将mailto 链接设置为不触发onb​​eforeunload 事件吗? I thought of a horribly hacky way of doing it by having another temporary javascript variable which causes the onbeforeunload confirm to not trigger, but it seems kind of dirty.我想到了一个可怕的hacky方式,通过使用另一个临时javascript变量导致onbeforeunload确认不会触发,但它看起来有点脏。 I'll do it anyway while i wait for a response but does anyone have a nicer solution?无论如何,我会在等待回复时这样做,但有人有更好的解决方案吗?

thanks, max谢谢,最大

A really simple fix to this is to do something like this:一个非常简单的解决方法是做这样的事情:

<a href="mailto:foo@bar.com" target="hidden-iframe">Email me</a>
<iframe name="hidden-iframe" style="visibility:hidden;position:absolute;"></iframe>

(And of course, move the styles to their own stylesheet instead of inlining them.) (当然,将样式移动到它们自己的样式表而不是内联它们。)

Building off of epascarello's solution, the following JQuery code should do the trick:基于 epascarello 的解决方案,以下 JQuery 代码应该可以解决问题:

    var ignore_onbeforeunload = false;
    $('a[href^=mailto]').on('click',function(){
        ignore_onbeforeunload = true;
    });

    window.onbeforeunload = function() {
        if (!ignore_onbeforeunload){
            return "Halt! you are not supposed to leave!";
        }
        ignore_onbeforeunload = false;
    };

I managed to solve this problem inside the onbeforeunload event by checking event.target.我通过检查 event.target 在 onbeforeunload 事件中设法解决了这个问题。 This way you dont have to use outer variables or any extra bindings.这样您就不必使用外部变量或任何额外的绑定。

window.onbeforeunload = function (event) {

    var activeElement = $(event.target.activeElement);
    // console.log('onbeforeunload', activeElement);

    var isMailto = activeElement && activeElement.is('[href^=mailto:]');
    var isTel = activeElement && activeElement.is('[href^=tel:]');

    if(!isMailto && !isTel) {
        // logic when link is "normal"
    }
};

Add a flag and see if it is flipped, set the flag on the link click.添加一个标志,看看它是否被翻转,在链接点击上设置标志。

var ignore = false
window.onbeforeunload = function() {
    if (changed && !ignore) {
        return "You have unsaved changes.  Do you really want to leave this page without saving?";
    } else {
        ignore = false;
    }
}

And the link和链接

<a class="button button-alt" href="mailto:foo@foo.com" onclick="ignore=true">Report a problem</a>

It would be better to add the onclick with JavaScript code.使用 JavaScript 代码添加 onclick 会更好。

Another option, also a bit hacky but a bit more generic way to make the beforeunload ignore certain types of links:另一种选择,也有点老套,但更通用的方法是使 beforeunload 忽略某些类型的链接:

In the beforeunload, inspect the link that caused the beforeunload, and if it is not a http or https link, don't bother the user.在beforeunload中,检查导致beforeunload的链接,如果不是http或https链接,不要打扰用户。

Unfortunately it is not easy to inspect the link that caused the beforeunload, so this is where it gets a little hacky with an onclick handler and global variable.不幸的是,检查导致 beforeunload 的链接并不容易,所以这就是使用 onclick 处理程序和全局变量的地方。

var lastClicked = null;
window.onclick = function(e){
    e = e || window.event;
    lastClicked = e.target
}
window.onbeforeunload = function(e){
    if (changed && lastClicked && lastClicked.href 
        && lastClicked.href.substring(0,4) == 'http')
        return "You have unsaved changes";
}

Edit: Almost forgot, this answer comes from here: https://stackoverflow.com/a/12065766/421243编辑:差点忘了,这个答案来自这里: https : //stackoverflow.com/a/12065766/421243

Some other solution with pure JS and using the focused element:使用纯 JS 并使用焦点元素的其他一些解决方案:

window.addEventListener("beforeunload", () => {
  const isMailTo = document.activeElement.protocol === "mailto:";

  if (!isMailTo) {
    // do your stuff
  }
});

根据John Kurlak 的回答,您可以简单地使用:

<a href="mailto:foo@bar.com" target="_blank">Email me</a>

Based on Theiaz answer, you can add a Boolean global var as protectUnload followed by a regexp to allow all external protocols except links ( http(s) ):根据 Theiaz 的回答,您可以添加一个布尔全局protectUnload作为protectUnload后跟一个正则表达式以允许除链接( http(s) )之外的所有外部协议:

window.onbeforeunload = function (event) {
    return (protectUnload && (typeof document.activeElement.protocol !== "undefined" && /^http(s)?:$/.test(document.activeElement.protocol))) || null; // return null == no confirm
};

It does not prevent for being kick out from the page using location.href but for in that case you can add 1 more boolean to the formula to always be protected for unloading the page (setting it to true before location.href 's new value).它不会阻止使用location.href从页面中踢出,但在这种情况下,您可以在公式中再添加 1 个布尔值以始终保护卸载页面(在location.href的新值之前将其设置为true )。

Set the target of the anchor to a hidden iframe burried in the page.将锚点的目标设置为埋在页面中的隐藏 iframe。 <a href="mailto:x@y.com" target="hiddenIframe" . <a href="mailto:x@y.com" target="hiddenIframe"

If the mailto is called via a javascript function (from a button or anchor or whatever) you could even create the iframe on the fly, set its src to the mailto, then remove it in a timeout.如果通过 javascript 函数(从按钮或锚点或其他方式)调用 mailto,您甚至可以动态创建 iframe,将其 src 设置为 mailto,然后在超时时将其删除。

Either way, the current page is not affected, and no need for pop-up tabs or windows.无论哪种方式,当前页面都不会受到影响,也不需要弹出选项卡或窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM