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

mav*_*aze 96 jquery window.open popup-blocker jquery-callback

我想在超链接的单击事件上有条件地显示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);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

如果我e.preventDefault();从代码中删除,popoup阻止程序不会阻止页面,但是对于condition1,它会打开对话框并打开'href'页面.

如果我解决了一个,它会为另一个人带来问题.我无法同时兼顾两种情况.

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

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

T.J*_*der 142

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

您有两种选择:

  1. 做别的事,而不是window.open.

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

    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      success: callback
    });
    
    Run Code Online (Sandbox Code Playgroud)

    ...所以你可以$.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);
            }
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)

    同样,如果你能找到任何其他方法来实现你的目标,我不提倡同步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");
        });
      });
    });
    
    Run Code Online (Sandbox Code Playgroud)

    这是一个使用同步调用的例子:

    实例 | 实时源 (由于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");
          }
        });
      });
    });
    
    Run Code Online (Sandbox Code Playgroud)

  • 对我来说,我添加了一个target ="_ blank"的链接来提示用户点击. (4认同)
  • 太感谢了.你打电话同步的建议就像一个魅力.同样的确有助于我处理对话OK事件导航的下一个问题. (3认同)
  • @mavaze我认为你可以避免这两个问题,如果你可以改变控制流程首先打开窗口,(同步),然后执行AJax请求(异步),然后使用响应显示错误消息或执行重定向. (2认同)

小智 60

只有当用户直接执行某些操作时,才能在没有浏览器阻止的情况下调用window.open.浏览器发送一些标志并确定用户操作打开的窗口.

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

  1. var myWindow = window.open('')
  2. 在此窗口中绘制任何加载消息
  3. 请求完成后,只需调用myWindow.location =' http://google.com '

  • 这不适用于Safari Mobile(在iPhone 4上测试).我尝试了其他一些想法(例如```myWindow.postMessage```)但由于Safaris限制不在后台执行JavaScript,父窗口永远不会发送该位置更改. (2认同)

Knu*_*urO 36

我有这个问题,我没有准备好我的网址,直到回调会返回一些数据.解决方案是在开始回调之前打开空白窗口,然后在回调返回时设置位置.

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


Moh*_*eer 18

试试这个,它对我有用,

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

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

  • 这应该是公认的答案!如果需要异步数据来构建URL,也可以使用redirectWindow.location.assign('new_url'). (3认同)

jay*_*lps 7

必须在与用户启动的事件相同的堆栈(也称为微任务)上创建Windows ,例如单击回调 - 因此不能在以后异步创建它们.

但是,您可以创建一个没有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);
}
Run Code Online (Sandbox Code Playgroud)

现代浏览器将打开带有空白页面(通常称为about:blank)的窗口,并假设您的异步任务获取URL相当快,因此产生的用户体验很好.如果您想在用户等待时将加载消息(或任何内容)呈现到窗口中,则可以使用数据URI.

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