100

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

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

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

只有 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);
        }
    });
});

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

如果我解决了一个问题,就会给另一个问题带来问题。我无法同时为这两种情况伸张正义。

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

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

4

10 回答 10

145

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

你有两个选择:

  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");
          }
        });
      });
    });
    
于 2012-03-01T10:53:33.760 回答
61

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

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

  1. var myWindow = window.open('')
  2. 在此窗口中绘制任何加载消息
  3. 请求完成后,只需调用 myWindow.location = ' http://google.com '
于 2013-10-29T19:01:32.280 回答
39

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

$scope.testCode = function () {
    var newWin = $window.open('', '_blank');
    service.testCode().then(function (data) {
        $scope.testing = true;
        newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
    });
};
于 2015-10-02T13:30:49.733 回答
17

试试这个,它对我有用,

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

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

于 2015-05-28T16:22:11.983 回答
8

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

但是,您可以创建一个没有 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);
}

现代浏览器会打开一个空白页(通常about:blank称为 如果您想在用户等待时将加载消息(或任何内容)呈现到窗口中,则可以使用Data URIs

window.open('data:text/html,<h1>Loading...<%2Fh1>');
于 2016-05-24T23:56:17.500 回答
3

这段代码对我有帮助。希望这可以帮助一些人

$('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';

    });
});
于 2017-05-14T15:46:26.660 回答
2

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

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

在下面的示例中,链接使用 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');
});
于 2014-01-06T16:24:21.797 回答
2

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

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

和脚本

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

像这样使用它

//do stuff
var id = 123123141;
openURL("/api/user/" + id + "/print") //this open webpage bypassing pop-up blocker
openURL("https://www.google.com") //Another link
于 2017-10-16T16:30:46.067 回答
2
var url = window.open("", "_blank");
url.location = "url";

这对我有用。

于 2018-08-29T20:08:48.460 回答
1

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

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

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

在异步调用成功时,编写以下内容

popupWindow.document.write(resonse.url)
于 2019-05-23T05:57:36.127 回答