在用户单击ajax调用后打开没有弹出窗口阻止程序的新选项卡

Sym*_*yma 37 javascript popupwindow popup-blocker

我有一个页面,使用户能够通过HTML5画布执行图像处理,在页面上,有一个Facebook分享按钮,用于在Facebook上共享生成的画布图像.

单击链接时,会向服务器(ASP.NET MVC)发送ajax请求以执行映像生成,将映像保存在服务器上,然后生成作为ajax返回的URL(链接到映像)响应.返回的url是我想要传递的Facebook要分享的参数.问题是,当我调用"window.open"时,弹出窗口阻止程序阻止了facebook共享对话框.

有没有其他方法可以在没有弹出窗口阻止程序的情况下打开新选项卡.我相信,既然用户发起了动作,我应该有办法绕过弹出窗口拦截器.谢谢.

Chr*_*ken 59

简短回答:使ajax请求同步.

完整答案:如果打开选项卡/弹出窗口的命令来自可信任事件,则浏览器只会在没有弹出窗口阻止程序警告的情况下打开选项卡/弹出窗口.这意味着:用户必须主动点击某处才能打开弹出窗口.

在您的情况下,用户执行单击以便您拥有受信任的事件.但是,通过执行Ajax请求,您确实失去了可信上下文.您的成功处理程序不再具有该事件.避免这种情况的唯一方法是执行同步Ajax请求,该请求会在浏览器运行时阻止它,但会保留事件上下文.

在jQuery中,这应该可以解决问题:

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

2014年10月更新:

在评论中正确地指出,Firefox已于2014年6月弃用了同步设置,但它仍然在此浏览器中工作.

此外,如果ajax调用在不到一秒的时间内返回,则Chrome会收到更新,这些更新只会允许其按预期工作.这是很难保证的.我创建了另一个专门针对Chrome超时的问题: 同步Ajax - Chrome在可信事件上是否超时?

链接的帖子包含一个JSFiddle,演示了这个概念和问题.

  • 在Chrome上它不适用于firefox async false已被弃用 (2认同)

wsg*_*rge 23

这是我如何解决我的异步ajax请求丢失可信上下文的问题:

我直接在用户点击上打开了弹出窗口,将URL指向about:blank并在该窗口上获得了一个句柄.您可以在发出ajax请求时将弹出窗口指向"加载"URL

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

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

function showWindow(win, url) {
    win.open(url,'name','height=500,width=550');
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ski 6

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);
}
Run Code Online (Sandbox Code Playgroud)