用户点击后,在ajax调用后打开新标签页而不受弹出窗口阻止器的影响

41

我有一个页面,允许用户通过HTML5画布执行图像操作,在页面上,有一个Facebook分享按钮,用于在Facebook上分享生成的画布图像。

当链接被点击时,会向服务器(ASP.NET MVC)发送ajax请求以执行图像生成,在服务器上保存图像,然后生成一个url(链接到图像),该url作为ajax响应返回。 我想将返回的url作为参数传递给Facebook共享。问题是当我调用“window.open”时,弹出窗口阻止程序阻止Facebook共享对话框。

是否有其他方法可以打开新选项卡而不受弹出窗口阻止程序的影响。 我相信由于用户启动了此操作,所以应该有一种方式可以绕过弹出窗口阻止程序。谢谢。


检查此处给出的解决方案 https://dev59.com/aW445IYBdhLWcg3wWY8U - Pal Singh
1
答案中的任何解决方案都对我无效。仍然遇到弹出窗口拦截器。 - Syma
这并不是直接回答问题,但如果你无法以其他方式完成它,这是最后的选择:不要在新的浏览器标签页中打开URL,而是在页面上创建一个链接,供用户单击以在新标签页中打开URL。 - John Gilmer
3个回答

59

2014年10月更新:

评论中指出,Firefox于2014年6月停用了同步设置,但在该浏览器中仍可正常工作。

此外,Chrome已经更新,只有当ajax调用在一秒内返回时才能按照预期工作。这是相当难以保证的。我创建了另一个问题专门讨论Chrome超时问题:Synchronous Ajax - does Chrome have a timeout on trusted events?

链接的文章包含一个JSFiddle演示了这个概念和问题。

原始答案

简短回答:将ajax请求设置为同步。

详细回答:只有当打开标签/弹出窗口的命令来自可信事件时,浏览器才会打开一个没有弹出窗口警告的标签/弹出窗口。这意味着:用户必须积极地点击某个地方才能打开弹出窗口。

在你的情况下,用户执行了点击操作,因此你有可信事件。但是,通过执行Ajax请求,你失去了可信上下文。你的成功处理程序不再具有该事件。 唯一的解决办法是执行同步Ajax请求,它会在运行时阻止你的浏览器,但会保留事件上下文。

在jQuery中,应该这样做:

$.ajax({
 url: 'http://yourserver/',
 data: 'your image',
 success: function(){window.open(someUrl);},
 async: false
});

1
@AnkitChauhan,你可以详细说明一下吗?我知道它在所有我知道的浏览器中仍在工作... - Christopher Lörken
2
在Chrome上它不能工作,对于Firefox来说,async false已经被弃用了。 - Kunal Vashist
@kunal-vashist 感谢您的留言,Mozilla确实在2014年6月发布的Firefox 30中弃用了同步XHR请求(https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests)。它仍然可以在Firefox和Chrome中使用。值得注意的一点是:Chrome似乎有一个1秒的超时时间,在这个时间内调用需要完成。请参阅此相关条目:https://dev59.com/N18e5IYBdhLWcg3wucRT(我不知道从什么时候开始)。 - Christopher Lörken
这里对我来说关键部分在于它是“受信任的事件”,这避免了弹出拦截器的问题(至少在Chrome中)。 - Steven Anderson
1
请将更新内容上移,将旧版本的解决方案移到底部。 - prasanthv
显示剩余2条评论

25

以下是我解决异步 ajax 请求失去信任上下文问题的方法:

我直接在用户点击时打开弹出窗口,并将 URL 定向到 about:blank,然后获取该窗口的句柄。你可能可以将弹出窗口定向到“加载”URL,同时进行 ajax 请求。

var myWindow = window.open("about:blank",'name','height=500,width=550');

然后,当我的请求成功时,我在窗口中打开我的回调URL

function showWindow(win, url) {
    win.open(url,'name','height=500,width=550');
}

8
wsgeorge的答案让我找到了正确的方向。下面是一个函数,希望更清晰地说明这种技巧。

function openNewAjaxTab(url) {
    var tabOpen = window.open("about:blank", 'newtab'),
        xhr = new XMLHttpRequest();

    xhr.open("GET", '/get_url?url=' + encodeURIComponent(url), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            tabOpen.location = xhr.responseText;
        }
    }
    xhr.send(null);
}

window.open("about:blank", 'newtab') 起作用时,它会打开一个新标签页。当 tabOpen.location = xhr.responseText; 起作用时,它会更改 tabOpen 对象的 location 属性,但是,新窗口的 URL 不会重定向到 tabOpen 上设置的 URL。 - efirat

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