ポップアップウィンドウは、追加のドキュメントをユーザーに表示するための最も古い方法の1つです。
基本的には、次のように実行するだけです。
window.open('https://javascriptinfo.dokyumento.jp/')
…そして、指定されたURLで新しいウィンドウが開きます。ほとんどの最新ブラウザは、別ウィンドウではなく新しいタブでURLを開くように設定されています。
ポップアップは非常に昔から存在します。当初のアイデアは、メインウィンドウを閉じずに別のコンテンツを表示することでした。現在では、他の方法でそれを実現できます。fetchを使用してコンテンツを動的にロードし、動的に生成された<div>
に表示できます。そのため、ポップアップは日常的に使用するものではありません。
また、ポップアップは複数のウィンドウを同時に表示しないモバイルデバイスでは扱いにくいものです。
それでも、OAuth認証(Google/Facebook/…でのログインなど)のように、ポップアップがまだ使用されるタスクがあります。なぜなら
- ポップアップは、独自の独立したJavaScript環境を持つ別のウィンドウです。そのため、サードパーティの信頼できないサイトからポップアップを開くのは安全です。
- ポップアップを開くのは非常に簡単です。
- ポップアップはナビゲート(URLを変更)し、オープナーウィンドウにメッセージを送信できます。
ポップアップブロック
過去には、悪質なサイトがポップアップを悪用していました。悪質なページは、広告付きのポップアップウィンドウを大量に開くことができました。そのため、現在、ほとんどのブラウザはポップアップをブロックしてユーザーを保護しようとしています。
ほとんどのブラウザは、onclick
のようなユーザートリガーイベントハンドラーの外部で呼び出された場合、ポップアップをブロックします。
例えば
// popup blocked
window.open('https://javascriptinfo.dokyumento.jp');
// popup allowed
button.onclick = () => {
window.open('https://javascriptinfo.dokyumento.jp');
};
このようにして、ユーザーはある程度不要なポップアップから保護されますが、機能は完全に無効にはされません。
window.open
ポップアップを開く構文は次のとおりです: window.open(url, name, params)
- url
- 新しいウィンドウにロードするURL。
- name
- 新しいウィンドウの名前。各ウィンドウには
window.name
があり、ここでポップアップに使用するウィンドウを指定できます。そのような名前のウィンドウがすでに存在する場合、指定されたURLがそのウィンドウで開きます。それ以外の場合は、新しいウィンドウが開きます。 - params
- 新しいウィンドウの設定文字列。カンマで区切られた設定が含まれています。paramsにはスペースを含めないでください。例:
width=200,height=100
。
params
の設定
- 位置
left/top
(数値) – 画面上のウィンドウの左上隅の座標。制限があります。新しいウィンドウは画面外に配置できません。width/height
(数値) – 新しいウィンドウの幅と高さ。最小幅/高さに制限があるため、目に見えないウィンドウを作成することはできません。
- ウィンドウ機能
menubar
(yes/no) – 新しいウィンドウにブラウザメニューを表示または非表示にします。toolbar
(yes/no) – 新しいウィンドウにブラウザのナビゲーションバー(戻る、進む、再読み込みなど)を表示または非表示にします。location
(yes/no) – 新しいウィンドウにURLフィールドを表示または非表示にします。FFとIEではデフォルトで非表示にすることはできません。status
(yes/no) – ステータスバーを表示または非表示にします。繰り返しになりますが、ほとんどのブラウザでは強制的に表示されます。resizable
(yes/no) – 新しいウィンドウのサイズ変更を無効にできます。推奨されません。scrollbars
(yes/no) – 新しいウィンドウのスクロールバーを無効にできます。推奨されません。
また、サポートが少ないブラウザ固有の機能も多数ありますが、通常は使用されません。例についてはMDNのwindow.openを確認してください。
例: 最小限のウィンドウ
ブラウザがどの機能を無効にできるかを確認するために、最小限の機能セットでウィンドウを開きましょう。
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=0,height=0,left=-1000,top=-1000`;
open('/', 'test', params);
ここでは、ほとんどの「ウィンドウ機能」が無効になり、ウィンドウは画面外に配置されます。実行して、実際に何が起こるかを確認してください。ほとんどのブラウザは、ゼロのwidth/height
や画面外のleft/top
などの奇妙なことを「修正」します。たとえば、Chromeはこのようなウィンドウをフルスクリーンになるように全幅/全高で開きます。
通常のポジショニングオプションと妥当なwidth
、height
、left
、top
の座標を追加しましょう。
let params = `scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,
width=600,height=300,left=100,top=100`;
open('/', 'test', params);
ほとんどのブラウザは、上記の例を必要に応じて表示します。
省略された設定のルール
open
呼び出しに3番目の引数がない場合、または空の場合、デフォルトのウィンドウパラメーターが使用されます。- paramsの文字列があり、一部の
yes/no
機能が省略されている場合、省略された機能はno
の値を持つと見なされます。したがって、paramsを指定する場合は、必要なすべての機能を明示的にyesに設定してください。 - paramsに
left/top
がない場合、ブラウザは最後に開いたウィンドウの近くに新しいウィンドウを開こうとします。 width/height
がない場合、新しいウィンドウは最後に開いたウィンドウと同じサイズになります。
ウィンドウからポップアップにアクセスする
open
呼び出しは、新しいウィンドウへの参照を返します。これを使用して、プロパティを操作したり、場所を変更したりできます。
この例では、JavaScriptからポップアップコンテンツを生成します。
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write("Hello, world!");
そして、ロード後にコンテンツを変更します。
let newWindow = open('/', 'example', 'width=300,height=300')
newWindow.focus();
alert(newWindow.location.href); // (*) about:blank, loading hasn't started yet
newWindow.onload = function() {
let html = `<div style="font-size:30px">Welcome!</div>`;
newWindow.document.body.insertAdjacentHTML('afterbegin', html);
};
注意してください: window.open
の直後には、新しいウィンドウはまだロードされていません。これは、行(*)
のalert
によって示されます。そのため、変更するためにonload
を待ちます。newWin.document
にDOMContentLoaded
ハンドラーを使用することもできます。
ウィンドウは、同じオリジン(同じprotocol://domain:port)からのものである場合にのみ、互いのコンテンツに自由にアクセスできます。
それ以外の場合、たとえばメインウィンドウがsite.com
からのもので、ポップアップがgmail.com
からのものである場合、ユーザーの安全上の理由から不可能です。詳細については、クロスウィンドウ通信の章を参照してください。
ポップアップからウィンドウにアクセスする
ポップアップは、window.opener
参照を使用して、「オープナー」ウィンドウにもアクセスできます。ポップアップを除くすべてのウィンドウではnull
です。
以下のコードを実行すると、オープナー(現在の)ウィンドウコンテンツが「Test」に置き換えられます。
let newWin = window.open("about:blank", "hello", "width=200,height=200");
newWin.document.write(
"<script>window.opener.document.body.innerHTML = 'Test'<\/script>"
);
したがって、ウィンドウ間の接続は双方向です。メインウィンドウとポップアップは互いに参照を持ちます。
ポップアップを閉じる
ウィンドウを閉じるには: win.close()
。
ウィンドウが閉じているかどうかを確認するには: win.closed
。
技術的には、close()
メソッドは任意のwindow
で使用できますが、window.close()
は、window
がwindow.open()
で作成されていない場合、ほとんどのブラウザで無視されます。したがって、ポップアップでのみ機能します。
ウィンドウが閉じている場合、closed
プロパティはtrue
です。これは、ポップアップ(またはメインウィンドウ)がまだ開いているかどうかを確認するのに役立ちます。ユーザーはいつでも閉じることができ、コードはその可能性を考慮に入れる必要があります。
このコードは、ウィンドウをロードしてから閉じます。
let newWindow = open('/', 'example', 'width=300,height=300');
newWindow.onload = function() {
newWindow.close();
alert(newWindow.closed); // true
};
移動とサイズ変更
ウィンドウを移動/サイズ変更するためのメソッドがあります。
win.moveBy(x,y)
- 現在の位置を基準にして、ウィンドウを右に
x
ピクセル、下にy
ピクセル移動します。負の値も許可されています(左/上に移動)。 win.moveTo(x,y)
- ウィンドウを画面上の座標
(x,y)
に移動します。 win.resizeBy(width,height)
- 現在のサイズを基準にして、指定された
width/height
でウィンドウのサイズを変更します。負の値も許可されています。 win.resizeTo(width,height)
- ウィンドウを指定されたサイズに変更します。
window.onresize
イベントもあります。
悪用を防ぐために、ブラウザは通常これらのメソッドをブロックします。これらのメソッドは、追加のタブがない、開いたポップアップでのみ確実に機能します。
JavaScriptには、ウィンドウを最小化または最大化する方法はありません。これらのOSレベルの機能は、フロントエンド開発者からは隠されています。
最大化/最小化されたウィンドウでは、移動/サイズ変更メソッドは機能しません。
ウィンドウのスクロール
ウィンドウのスクロールについては、ウィンドウのサイズとスクロールの章ですでに説明しました。
win.scrollBy(x,y)
- 現在のスクロールを基準にして、ウィンドウを右に
x
ピクセル、下にy
ピクセルスクロールします。負の値も許可されています。 win.scrollTo(x,y)
- ウィンドウを指定された座標
(x,y)
までスクロールします。 elem.scrollIntoView(top = true)
- ウィンドウをスクロールして、
elem
を上部(デフォルト)またはelem.scrollIntoView(false)
の場合は下部に表示します。
window.onscroll
イベントもあります。
ウィンドウのフォーカス/ブラー
理論的には、ウィンドウをフォーカス/フォーカス解除するためのwindow.focus()
およびwindow.blur()
メソッドがあります。また、訪問者がウィンドウにフォーカスしたり、他の場所に切り替えたりする瞬間をキャッチできるfocus/blur
イベントもあります。
ただし、実際には、過去に悪質なページが悪用していたため、非常に制限されています。
たとえば、このコードを見てください。
window.onblur = () => window.focus();
ユーザーがウィンドウから切り替えようとすると(window.onblur
)、ウィンドウが再びフォーカスされます。その目的は、ユーザーをwindow
内に「ロック」することです。
そのため、ブラウザは、そのようなコードを禁止し、ユーザーを広告や悪質なページから保護するために、多くの制限を導入する必要がありました。それらはブラウザに依存します。
たとえば、モバイルブラウザは通常、window.focus()
を完全に無視します。また、ポップアップが新しいウィンドウではなく別のタブで開く場合、フォーカスは機能しません。
それでも、このような呼び出しが機能し、役立つ可能性のあるユースケースがいくつかあります。
例えば
- ポップアップを開く場合は、念のため、
newWindow.focus()
を実行することをお勧めします。一部のOS/ブラウザの組み合わせでは、ユーザーが現在新しいウィンドウにいることが保証されます。 - 訪問者が実際にWebアプリを使用しているタイミングを追跡したい場合は、
window.onfocus/onblur
を追跡できます。これにより、ページ内アクティビティ、アニメーションなどを一時停止/再開できます。ただし、blur
イベントは、訪問者がウィンドウから切り替えたことを意味しますが、まだ表示される可能性があることに注意してください。ウィンドウはバックグラウンドにありますが、まだ表示される可能性があります。
まとめ
ポップアップウィンドウは、ページ内またはiframeに情報をロードして表示するなど、代替手段があるため、めったに使用されません。
ポップアップを開く場合は、ユーザーにそのことを通知することをお勧めします。リンクまたはボタンの近くに「ウィンドウを開く」アイコンを付けると、訪問者はフォーカスの切り替えを乗り切り、両方のウィンドウを覚えておくことができます。
- ポップアップは、
open(url, name, params)
呼び出しによって開くことができます。新しく開いたウィンドウへの参照が返されます。 - ブラウザは、ユーザーアクション以外のコードからの
open
呼び出しをブロックします。通常、通知が表示され、ユーザーが許可できるようになります。 - ブラウザはデフォルトで新しいタブを開きますが、サイズが指定されている場合はポップアップウィンドウになります。
- ポップアップは、
window.opener
プロパティを使用して、元のウィンドウにアクセスできます。 - メインウィンドウとポップアップは、同じオリジンを持つ場合、互いに自由に読み書きや変更を行うことができます。そうでない場合は、互いの場所を変更したり、メッセージを交換したりできます。
ポップアップを閉じるには、close()
を呼び出します。また、ユーザーは他のウィンドウと同様にポップアップを閉じることができます。その後、window.closed
は true
になります。
focus()
メソッドとblur()
メソッドは、ウィンドウをフォーカス/アンフォーカスできます。ただし、常に機能するとは限りません。focus
イベントとblur
イベントを使用すると、ウィンドウの切り替えを追跡できます。ただし、blur
の後でも、ウィンドウがバックグラウンド状態でも表示されている可能性があることに注意してください。
コメント
<code>
タグを使用し、複数行の場合は<pre>
タグで囲み、10行を超える場合はサンドボックスを使用してください(plnkr, jsbin, codepen...)。