Ajax でポップアップブロックを回避する方法
最近のブラウザでは、JavaScript からウィンドウを開こうとした際、 ポップアップブロックによってブロックされてしまうことがあります。 通常のユーザーによる操作であれば問題ないのですが、 Ajax と組み合わせた際にもブロックされてしまうのは困りものです。 回避策を調査しましたので、ここに書いておきます。 少々ハマってしまったのと、忘れてしまいそうな自分への備忘録です。 誰かのお役にたてれば幸いです。
やりたいこと
ユーザーが送信ボタンをクリックすると、フォームに入力された内容をサーバーに Ajax する。
サーバーから帰ってきた結果が OK ならウィンドウを開く。NG ならウィンドウは開かない。
ポップアップブロックの主な振る舞い
JavaScript からウィンドウを開く際、 ユーザーからの操作に関係がない場合はブロックし、 ユーザーからの操作に関係がある場合はブロックされません。
例えば、jQuery.ready や onload イベントなど、ページ読み込み時に自動でウィンドウを開いたりする場合は、 ユーザーの操作に関係が無いのでブロックされます。 この場合、onload イベント内で click イベントを実行させてもブロックされます。 しかし、ユーザーがボタンをクリックした際の onclick イベント等では、 ユーザーの操作なのでブロックされません。
では、ユーザーがボタンをクリックした際の onclick イベントで、Ajax(非同期通信)した場合はどうでしょう? この場合、リクエストを送信するプロセスはブロックされませんが、 レスポンスを受け取るプロセスはブロックされます。
$(function() { window.open(~); // ここではブロックされる $('#hoge').on('click', function() { window.open(~); // ここではブロックされない $.ajax({ url: ~, success: function(data) { window.open(~); // ここではブロックされる } }); }); });
なぜなら、Ajax は非同期通信であり、レスポンスを受け取るプロセスが別のプロセスになってしまうからです。 その別プロセスはユーザーの操作とは関係がないためブロックされます。 良くできてますよね。
ブロックされてしまうパターン
- jQuery.ready や onload イベント
- Ajax (非同期通信)
ブロックされないパターン
- ユーザーが操作して発生したイベント(onclick 等)
回避策
しかしながら、今回はブロックさせたくないのです。ではどうするか。 Ajax(非同期通信)により、ユーザーの操作と通信処理が分断され、ブロックされてしまうのであれば、 ユーザーの操作と通信処理を分断させなければ良いわけです。 非同期通信ではなく、同期通信を使います。
$(function() { window.open(~); // ここではブロックされる $('#hoge').on('click', function() { window.open(~); // ここではブロックされない $.ajax({ url: ~, async: false, // 非同期ではなく同期通信にする success: function(data) { window.open(~); // ここではブロックされない } }); }); });
jQuery では非同期も同期も同じ ajax
というメソッドなので混乱しやすいですが、
async
フラグを false
にすることで同期通信になります。
同期通信なので通信が終わるまで待ち状態になってしまいますが、
それはつまりユーザーの操作と関係しているプロセスということですので、
ポップアップブロックを回避してウィンドウを開くことが可能です。
まとめ
Ajax(Asynchronous JavaScript + XML)ではなく、 Sjax(Synchronous JavaScript + XML)です。