2022年11月4日

ポップアップとウィンドウメソッド

ポップアップウィンドウは、追加のドキュメントをユーザーに表示するための最も古い方法の1つです。

基本的には、次のように実行するだけです。

window.open('https://javascriptinfo.dokyumento.jp/')

…そして、指定されたURLで新しいウィンドウが開きます。ほとんどの最新ブラウザは、別ウィンドウではなく新しいタブでURLを開くように設定されています。

ポップアップは非常に昔から存在します。当初のアイデアは、メインウィンドウを閉じずに別のコンテンツを表示することでした。現在では、他の方法でそれを実現できます。fetchを使用してコンテンツを動的にロードし、動的に生成された<div>に表示できます。そのため、ポップアップは日常的に使用するものではありません。

また、ポップアップは複数のウィンドウを同時に表示しないモバイルデバイスでは扱いにくいものです。

それでも、OAuth認証(Google/Facebook/…でのログインなど)のように、ポップアップがまだ使用されるタスクがあります。なぜなら

  1. ポップアップは、独自の独立したJavaScript環境を持つ別のウィンドウです。そのため、サードパーティの信頼できないサイトからポップアップを開くのは安全です。
  2. ポップアップを開くのは非常に簡単です。
  3. ポップアップはナビゲート(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はこのようなウィンドウをフルスクリーンになるように全幅/全高で開きます。

通常のポジショニングオプションと妥当なwidthheightlefttopの座標を追加しましょう。

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.documentDOMContentLoadedハンドラーを使用することもできます。

同一オリジンポリシー

ウィンドウは、同じオリジン(同じ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()は、windowwindow.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.closedtrue になります。

  • focus() メソッドと blur() メソッドは、ウィンドウをフォーカス/アンフォーカスできます。ただし、常に機能するとは限りません。
  • focus イベントと blur イベントを使用すると、ウィンドウの切り替えを追跡できます。ただし、blur の後でも、ウィンドウがバックグラウンド状態でも表示されている可能性があることに注意してください。
チュートリアルマップ

コメント

コメントする前にこれを読んでください…
  • 改善点についてご提案がある場合は、コメントする代わりに GitHub issue を送信するか、プルリクエストを送信してください。
  • 記事の内容が理解できない場合は、詳しく説明してください。
  • 数語のコードを挿入するには、<code> タグを使用し、複数行の場合は <pre> タグで囲み、10行を超える場合はサンドボックスを使用してください(plnkr, jsbin, codepen...)。