设置 JQuery event.preventDefault() 时绕过 window.open 上的弹出窗口阻止程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9514698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 10:55:16  来源:igfitidea点击:

Bypass popup blocker on window.open when JQuery event.preventDefault() is set

jquerywindow.openjquery-callbackpopup-blocker

提问by mavaze

I want to show a JQuery dialog conditionally on click event of an hyperlink .

我想在超链接的点击事件上有条件地显示一个 JQuery 对话框。

I have a requirement like on condition1 open a JQuery dialogue and if condition1 is not satisfied, navigate to the page as referenced by 'href' tag of whose click event is in question.

我有一个要求,比如在条件 1 上打开一个 JQuery 对话框,如果条件 1 不满足,请导航到点击事件有问题的“href”标签所引用的页面。

I am able to call a function on link's click event. This function now checks the said condition by executing another URL (that executes my Spring controller and returns response).

我可以在链接的点击事件上调用一个函数。该函数现在通过执行另一个 URL(执行我的 Spring 控制器并返回响应)来检查所述条件。

All works perfect with only window.open being blocked by popup blocker.

一切正常,只有 window.open 被弹出窗口阻止程序阻止。

$('a[href*=/viewpage?number]').live('click', function(e) {
    e.preventDefault();
    redirectionURL = this.href;
    pageId= getUrlVars(redirectionURL)["number"];
    $.getJSON("redirect/" + pageId, {}, function(status) {
        if (status == null) {
            alert("Error in verifying the status.");
        } else if(!status) {
            $("#agreement").dialog("open");
        } else {
            window.open(redirectionURL);
        }
    });
});

If I remove e.preventDefault();from code, popoup blocker doesn't block the page, however for condition1 it then opens the dialogue as well as opens the 'href' page.

如果我e.preventDefault();从代码中删除,弹出窗口阻止程序不会阻止页面,但是对于条件 1,它会打开对话框并打开“href”页面。

If I solve one, it creates issue for another. I am not able to give justice to both conditions simultaneously.

如果我解决了一个,它就会为另一个创造问题。我无法同时对这两种情况进行公正处理。

Could you help me solve this issue please?

你能帮我解决这个问题吗?

Once this is solved I have another issue to solve i.e. navigation on dialogue's OK event :)

一旦解决了这个问题,我还有另一个问题要解决,即在对话的 OK 事件上导航:)

回答by T.J. Crowder

Popup blockers will typically only allow window.openif used duringthe processing of a user event (like a click). In your case, you're calling window.openlater, not during the event, because $.getJSONis asynchronous.

弹出阻滞剂通常只允许window.open如果使用的话期间的用户事件(如点击)的处理。在您的情况下,您window.open稍后调用,而不是在事件期间调用,因为它$.getJSON是异步的。

You have two options:

您有两个选择:

  1. Do something else, rather than window.open.

  2. Make the ajax call synchronous, which is something you should normally avoid like the plague as it locks up the UI of the browser. $.getJSONis equivalent to:

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });
    

    ...and so you can make your $.getJSONcall synchronous by mapping your params to the above and adding async: false:

    $.ajax({
        url:      "redirect/" + pageId,
        async:    false,
        dataType: "json",
        data:     {},
        success:  function(status) {
            if (status == null) {
                alert("Error in verifying the status.");
            } else if(!status) {
                $("#agreement").dialog("open");
            } else {
                window.open(redirectionURL);
            }
        }
    });
    

    Again, I don't advocate synchronous ajax calls if you can find any other way to achieve your goal. But if you can't, there you go.

    Here's an example of code that fails the test because of the asynchronous call:

    Live example| Live source(The live links no longer work because of changes to JSBin)

    jQuery(function($) {
      // This version doesn't work, because the window.open is
      // not during the event processing
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.getJSON("http://jsbin.com/uriyip", function() {
          window.open("http://jsbin.com/ubiqev");
        });
      });
    });
    

    And here's an example that does work, using a synchronous call:

    Live example| Live source(The live links no longer work because of changes to JSBin)

    jQuery(function($) {
      // This version does work, because the window.open is
      // during the event processing. But it uses a synchronous
      // ajax call, locking up the browser UI while the call is
      // in progress.
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.ajax({
          url:      "http://jsbin.com/uriyip",
          async:    false,
          dataType: "json",
          success:  function() {
            window.open("http://jsbin.com/ubiqev");
          }
        });
      });
    });
    
  1. 做点别的,而不是window.open

  2. 使 ajax 调用同步,这是您通常应该避免的事情,就像瘟疫一样,因为它会锁定浏览器的 UI。$.getJSON相当于:

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });
    

    ...因此您可以$.getJSON通过将您的参数映射到上面并添加async: false

    $.ajax({
        url:      "redirect/" + pageId,
        async:    false,
        dataType: "json",
        data:     {},
        success:  function(status) {
            if (status == null) {
                alert("Error in verifying the status.");
            } else if(!status) {
                $("#agreement").dialog("open");
            } else {
                window.open(redirectionURL);
            }
        }
    });
    

    同样,如果您能找到任何其他方式来实现您的目标,我不提倡同步 ajax 调用。但如果你不能,那就去吧。

    以下是由于异步调用而导致测试失败的代码示例:

    活生生的例子| 实时源(由于 JSBin 的更改,实时链接不再有效)

    jQuery(function($) {
      // This version doesn't work, because the window.open is
      // not during the event processing
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.getJSON("http://jsbin.com/uriyip", function() {
          window.open("http://jsbin.com/ubiqev");
        });
      });
    });
    

    这是一个使用同步调用确实有效的示例:

    活生生的例子| 实时源(由于 JSBin 的更改,实时链接不再有效)

    jQuery(function($) {
      // This version does work, because the window.open is
      // during the event processing. But it uses a synchronous
      // ajax call, locking up the browser UI while the call is
      // in progress.
      $("#theButton").click(function(e) {
        e.preventDefault();
        $.ajax({
          url:      "http://jsbin.com/uriyip",
          async:    false,
          dataType: "json",
          success:  function() {
            window.open("http://jsbin.com/ubiqev");
          }
        });
      });
    });
    

回答by Evgeniy Kubyshin

you can call window.open without browser blocking only if user does directly some action. Browser send some flag and determine that window opened by user action.

只有当用户直接执行某些操作时,您才能调用 window.open 而不会阻止浏览器。浏览器发送一些标志并确定用户操作打开的窗口。

So, you can try this scenario:

所以,你可以试试这个场景:

  1. var myWindow = window.open('')
  2. draw any loading message in this window
  3. when request done, just call myWindow.location = 'http://google.com'
  1. var myWindow = window.open('')
  2. 在此窗口中绘制任何加载消息
  3. 请求完成后,只需调用 myWindow.location = ' http://google.com'

回答by KnuturO

I had this problem and I didn't have my url ready untill the callback would return some data. The solution was to open blank window before starting the callback and then just set the location when the callback returns.

我遇到了这个问题,直到回调返回一些数据我才准备好我的 url。解决方案是在开始回调之前打开空白窗口,然后在回调返回时设置位置。

$scope.testCode = function () {
    var newWin = $window.open('', '_blank');
    service.testCode().then(function (data) {
        $scope.testing = true;
        newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
    });
};

回答by Mohammed Safeer

try this, it works for me,

试试这个,它对我有用,

$('#myButton').click(function () {
    var redirectWindow = window.open('http://google.com', '_blank');
    $.ajax({
        type: 'POST',
        url: '/echo/json/',
        success: function (data) {
            redirectWindow.location;
        }
    });
});

Is fiddle for this http://jsfiddle.net/safeeronline/70kdacL4/1/

是小提琴这个http://jsfiddle.net/safeeronline/70kdacL4/1/

回答by jayphelps

Windows must be created on the same stack (aka microtask) as the user-initiated event, e.g. a click callback--so they can't be created later, asynchronously.

Windows 必须在与用户启动的事件(例如单击回调)相同的堆栈(又名microtask)上创建,因此它们不能在以后异步创建。

However, you can create a window without a URLand you can then change that window's URL once you do know it, even asynchronously!

但是,您可以创建一个没有 URL 的窗口,然后您可以在知道它后更改该窗口的 URL ,甚至可以异步更改!

window.onclick = () => {
  // You MUST create the window on the same event
  // tick/stack as the user-initiated event (e.g. click callback)
  const googleWindow = window.open();

  // Do your async work
  fakeAjax(response => {
    // Change the URL of the window you created once you
    // know what the full URL is!
    googleWindow.location.replace(`https://google.com?q=${response}`);
  });
};

function fakeAjax(callback) {
  setTimeout(() => {
    callback('example');
  }, 1000);
}

Modern browsers will open the window with a blank page (often called about:blank), and assuming your async task to get the URL is fairly quick, the resulting UX is mostly fine. If you instead want to render a loading message (or anything) into the window while the user waits, you can use Data URIs.

现代浏览器将打开带有空白页面(通常称为about:blank)的窗口,并且假设您获取 URL 的异步任务相当快,那么生成的 UX 基本没问题。如果您想在用户等待时将加载消息(或任何内容)呈现到窗口中,您可以使用Data URIs

window.open('data:text/html,<h1>Loading...<%2Fh1>');

回答by Richard

This code help me. Hope this help some people

此代码帮助我。希望这能帮助一些人

$('formSelector').submit( function( event ) {

    event.preventDefault();

    var newWindow = window.open('', '_blank', 'width=750,height=500');

    $.ajax({

        url: ajaxurl,
        type: "POST",
        data: { data },

    }).done( function( response ) {

        if ( ! response ) newWindow.close();
        else newWindow.location = '/url';

    });
});

回答by Fernando Carvajal

Try using an a linkelement and click it with javascriipt

尝试使用链接元素并使用 javascriipt 单击它

<a id="SimulateOpenLink" href="#" target="_blank" rel="noopener noreferrer"></a>

and the script

和脚本

function openURL(url) {
    document.getElementById("SimulateOpenLink").href = url
    document.getElementById("SimulateOpenLink").click()
}

Use it like this

像这样使用它

//do stuff
var id = 123123141;
openURL("/api/user/" + id + "/print") //this open webpage bypassing pop-up blocker
openURL("https://www.google.com") //Another link

回答by Diego Santa Cruz Mendezú

var url = window.open("", "_blank");
url.location = "url";

this worked for me.

这对我有用。

回答by Alexis Bellido

The observation that the event had to be initiated by the user helped me to figure out the first part of this, but even after that Chrome and Firefox still blocked the new window. The second part was adding target="_blank" to the link, which was mentioned in one comment.

事件必须由用户发起的观察帮助我弄清楚了这一点的第一部分,但即使在此之后 Chrome 和 Firefox 仍然阻止了新窗口。第二部分是将 target="_blank" 添加到链接中,在一个评论中提到过。

In summary: you need to call window.open from an event initiated by the user, in this case clicking on a link, and that link needs to have target="_blank".

总之:您需要从用户发起的事件中调用 window.open,在这种情况下单击链接,并且该链接需要具有 target="_blank"。

In the example below the link is using class="button-twitter".

在下面的示例中,链接使用 class="button-twitter"。

$('.button-twitter').click(function(e) {
  e.preventDefault();
  var href = $(this).attr('href');
  var tweet_popup = window.open(href, 'tweet_popup', 'width=500,height=300');
});

回答by Tabish

I am using this method to avoid the popup blocker in my React code. it will work in all other javascript codes also.

我正在使用这种方法来避免我的 React 代码中的弹出窗口阻止程序。它也适用于所有其他 javascript 代码。

When you are making an async call on click event, just open a blank window first and then write the URL in that later when an async call will complete.

当您对点击事件进行异步调用时,只需先打开一个空白窗口,然后在异步调用完成时在其中写入 URL。

const popupWindow = window.open("", "_blank");
popupWindow.document.write("<div>Loading, Plesae wait...</div>")

on async call's success, write the following

在异步调用成功后,写入以下内容

popupWindow.document.write(resonse.url)