web-dev-qa-db-ja.com

JQuery event.preventDefault()が設定されているときにwindow.openでポップアップブロッカーをバイパスする

ハイパーリンクのクリックイベントで条件付きでJQueryダイアログを表示したい。

Condition1にJQueryダイアログを開くなどの要件があり、condition1が満たされない場合は、クリックイベントが問題の '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();をコードから削除すると、popoupブロッカーはページをブロックしませんが、condition1の場合はダイアログを開き、「href」ページを開きます。

解決したら、別の問題が発生します。私は両方の条件に同時に正義を与えることはできません。

この問題を解決してください。

これが解決したら、解決する別の問題、つまりダイアログのOKイベントのナビゲーションがあります:)

95
mavaze

ポップアップブロッカーでは、通常、window.openが使用されている場合のみ許可されますduringユーザーイベントの処理(クリックなど)。あなたの場合、window.openは非同期であるため、イベント中ではなく、$.getJSONlaterを呼び出しています。

次の2つのオプションがあります。

  1. window.openではなく、何か他のことを行います。

  2. Ajax呼び出しを同期化します。これは、ペストのようにブラウザーのUIをロックするため、通常は避けるべきです。 $.getJSONは次と同等です:

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

    ...そのため、paramsを上記にマッピングして$.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");
          }
        });
      });
    });
    
141
T.J. Crowder

ユーザーが何らかのアクションを直接実行した場合にのみ、ブラウザをブロックせずにwindow.openを呼び出すことができます。ブラウザはいくつかのフラグを送信し、ユーザーのアクションによって開かれたウィンドウを決定します。

したがって、このシナリオを試すことができます。

  1. var myWindow = window.open( '')
  2. このウィンドウに読み込みメッセージを描画します
  3. リクエストが完了したら、myWindow.location = ' http://google.com 'を呼び出すだけです
60

この問題が発生し、コールバックがデータを返すまでURLを準備できませんでした。解決策は、コールバックを開始する前に空白のウィンドウを開き、コールバックが戻るときに場所を設定するだけでした。

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

これを試して、それは私のために働く、

$('#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/

18
Mohammed Safeer

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と呼ばれます)でウィンドウを開きます。URLを取得する非同期タスクがかなり速いと仮定すると、結果のUXはほとんど問題ありません。代わりに、ユーザーが待機している間に読み込みメッセージ(または何か)をウィンドウにレンダリングする場合は、 Data URIs を使用できます。

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

このコードは私を助けます。これが一部の人々を助けることを願っています

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

    });
});
3
Richard

リンク要素を使用してみて、javascriiptでクリックしてください

<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
3

ユーザーがイベントを開始する必要があるという観察は、この最初の部分を理解するのに役立ちましたが、それでもChromeとFirefoxは新しいウィンドウをブロックしました。 2番目の部分は、リンクにtarget = "_ blank"を追加することで、これは1つのコメントで言及されました。

要約すると、ユーザーが開始したイベント(この場合はリンクをクリックする)から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');
});
2
Alexis Bellido
var url = window.open("", "_blank");
url.location = "url";

これは私のために働いた。

Reactコードでポップアップブロッカーを回避するために、このメソッドを使用しています。他のすべてのjavascriptコードでも機能します。

クリックイベントで非同期呼び出しを行う場合は、最初に空白のウィンドウを開いてから、非同期呼び出しが完了するときにその中にURLを書き込むだけです。

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

非同期呼び出しが成功したら、次のように記述します

popupWindow.document.write(resonse.url)
0
Tabish