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


98

ハイパーリンクのクリックイベントで条件付きで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();コードから削除しても、ポップアップブロッカーはページをブロックしませんが、condition1の場合はダイアログを開き、 'href'ページを開きます。

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

この問題の解決を手伝っていただけませんか?

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


1
廃止予定の.liveと.on()へのポインタを使用しないようにしてください。
mas-designs 2012

@EvilP:他の人が前回あなたに言ったように、1.7以上でのみ。多くのプロジェクトはまだ1.5または1.6になります。
TJクラウダー、2012年

10
ダウン投票:ポップアップが気に入らないからといって、この質問にダウン投票する必要があるという意味ではありません。「...調査の結果がまったく表示されない、不明である、または役に立たない」場合は、質問に反対票を投じる必要があります。問題は明確で、怠惰ではないように思われ、重要な要因の組み合わせから生じます。
TJクラウダー、2012年

@TJCrowder:彼は彼が使っているバージョンを特定しなかった。だから彼は最新バージョンを使っていると考えるべきです。彼が別のバージョンを使用している場合、私は彼がそのことを言及するだろうと確信している。誰も私に「最後」の時間を教えてくれなかったので、私はあなたが休憩を取り、落ち着くようにすべきです。それほど厳格である必要はありません...
mas-designs

それに関する通知はありませんでした。しかし、誰かが自分のバージョンを指定しない場合、最新のものを使用していると見なすのは普通ではないでしょうか?理由のために1.3を使用する必要があることを意味し、より新しくより優れたバージョンがあることを認識しています。
mas-designs 2012

回答:


144

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

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

  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");
          }
        });
      });
    });
    

3
どうもありがとう。呼び出しを同期させるというあなたの提案は魅力のように機能しました。同じことが、対話のOKイベントでのナビゲーションの処理に関する私の予想される次の問題でも役立ちました。
mavaze、2012年

TJ Crowderは2つの質問を開いたままにしているため、[1。window.open]および[2。ajax同期呼び出しを避けてください]それらに関する提案はコミュニティの利益のために歓迎されています。
そうでなけれ

4
私は、target = "_ blank"のリンクを追加して、ユーザーにクリックを促すようにしました。
hiroshi 2012

1
@Evan:XHRを直接使用する必要があります。チケットに同期リクエストのサポートを終了する例があります
TJクラウダー2012年

2
@mavaze最初にウィンドウを開く(同期)ように制御フローを変更し、次にAJax要求(非同期)を実行してから、応答を使用してエラーメッセージを表示するかリダイレクトすることで、両方の問題を回避できると思います。
Stijn de Witt 2017

61

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

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

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

2
これはSafari Mobileでは機能しません(iPhone 4でテスト済み)。他にもいくつかのアイデアを試しましたが(例myWindow.postMessage:)、バックグラウンドでJavaScriptを実行しないというSafarisの制限のため、親ウィンドウはその場所の変更を送信できません。
ラウンドロビン2014年

@BausTheBig私はiPhone 6、IOS8でテストしました。それは魅力のように働きました。
lvarayut 2015年

ポップアップをブロックせずにGoogle Analyticsで外部リンクを追跡する方法を探していました。これはまさに私が必要としたものでした。iOS7(実際の電話)およびiOS 8(iOSシミュレーター)のiPhone 4sで正常に動作するようです。
notacouch 2015年

37

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

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

1
このソリューションを使用して新しいウィンドウを開き、ポップアップブロッカーをバイパスしました
VeldMuijz

ポップアップを開く必要があるかどうか事前にわからない場合はどうなりますか?のように: action().then(doWindowOpenThing).catch(doSomethingElseThatDoesntOpenAPopup) それで、後でそれを使用しない場合は、事前にウィンドウを開くことはできません(参照を維持するためなど)。
Luiz、2016年

いいえ、毎回新しいタブが開くので、使用しない場合はそうしたくないと思います。ブラウザーはクリック機能(ユーザーが開始したアクション)で新しいタブを開くことのみを許可します。そうでない場合、ポップアップブロッカーはこれをユーザーの許可なしに新しいタブを開くスクリプトとして認識し、ブロックします。
KnuturO

newWinがnullかどうかをテストしてください!
FrancescoMM

どうして ?これには理由がありません。
KnuturO

18

これを試してください、それは私にとってはうまくいきます、

$('#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/のフィドルです


1
ありがとう、私のためにも働いた-それがそのフィドルのためでなければ、私はおそらくそれを信じなかっただろう、笑!
rmcsharry

3
これは受け入れられる答えになるはずです!URLを構築するために非同期データが必要な場合は、redirectWindow.location.assign( 'new_url')を使用することもできます。
matheusr 2016年

いい解決策です。それを
維持

redirectWindowがnullかどうかをテストしてください!さまざまなブラウザオプションに応じて、ブロックされるかどうかが決まります。
FrancescoMM

8

ウィンドウは、ユーザーが開始したイベント(クリックコールバックなど)と同じスタック(マイクロタスクとも呼ばれます)上に作成する必要があるため、後で非同期に作成することはできません。

ただし、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はほとんど問題ありません。代わりに、ユーザーが待機している間に読み込みメッセージ(または何か)をウィンドウにレンダリングする場合は、データURIを使用できます

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

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

    });
});

3

リンク要素を使用して 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

これは私のために空白のウィンドウを扱うことを避けました。
ponder275 2018年

これは、iPhoneがポップアップとしてウィンドウをブロックするという私の問題を解決しないことがわかりました。
ponder275

2

イベントをユーザーが開始する必要があるという観察は、この最初の部分を理解するのに役立ちましたが、その後も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');
});


1

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

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

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

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

popupWindow.document.write(resonse.url)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.