忙しい人向け
- form.submitで開いたサブウィンドウにてメインウィンドウを認識しない
- ターゲットに「_blank」が設定されている場合、暗黙的にリンク種別に「noopener」が設定されるのが原因
- リンク種別に「opener」を設定することで、メインウィンドウを認識するようになる
はじめに
業務で表題の事象に遭遇したのですが、
原因調査の際に情報が少なく、苦労したので備忘として投稿します。
発生事象
-
form.submitにて生成したサブウィンドウでメインウィンドウ(opener)を認識しない。
-
自分が担当しているシステムでは以下のような処理を行ってました。
1.データの登録画面(メインウィンドウ)にて項目Aの検索画面をサブウィンドウで開く
2.項目Aの登録データを検索
3.検索結果から選択した値をメインウィンドウに反映させる(メインウィンドウの関数実行)
メインウィンドウの関数は、opener経由でアクセスしていましたが、
openerが取得できないので、関数を実行できていませんでした。
発生環境
- Microsoft Edge 108.0.1462.54
※上記バージョン以外については、検証できていないため過去バージョンでも発生する可能性あり
発生条件
- JSファイルA、BをHTMLで読み込んでいる
- AからBの関数を呼び出し
- Bの関数でサブウィンドウを生成
以下ソースは事象が発生した環境を再現したものです。
(自環境では、別の理由で再現できませんでした…)
mainWindow.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="text/javascript" src="../js/scriptA.js"></script>
<script type="text/javascript" src="../js/scriptB.js"></script>
</head>
<body>
<form name="formA" encType="multipart/form-data" method="post" action="">
<button onClick="exeScriptB">サブウィンドウで開く</button>
</form>
</body>
</html>
subWindow.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="text/javascript" src="../js/scriptC.js"></script>
</head>
<body>
<button onClick="executeScriptC()">scriptC実行</button>
</body>
</html>
scriptA.js
function exeScriptB(){
generateSubWindow();
}
function alert_(){
alert("メインウィンドウ関数にてアラート表示");
}
scriptB.js
function generateSubWindow(){
document.formA.action="../html/subWindow.html";
document.formA.target="_blank";
document.formA.submit();
}
scriptC.js
function executeScriptC(){
if(!(window.opener==null)){
window.opener.alert_();
}else{
alert("メインウィンドウを認識できません");
}
}
原因
- <a>要素に「target="_blank」が設定された場合、
リンク種別に「noopener」がデフォルトで設定される仕様に変更されたため
mdn web docsのリンク種別ページにて以下のように記載されていました。
セキュリティ的にもopener経由で何かするのは控えたほうがよさそうですね。
target="_blank" を <a> 要素に設定すると、暗黙的に rel の動作が
rel="noopener" を設定した場合と同様、 window.opener を設定しないようになりました。
対応状況についてはブラウザーの互換性を参照してください。
補足
ターゲットとは
- リンク先の文書を開く場所を指定します(
<a>
要素の場合)。 - 受信したレスポンスを表示する場所を指定します(
<form>
要素の場合)。 - 設定する値によってリンク先の開き方が異なります。
- 同じタブで開く:_self
- 新しいタブで開く:_blank
オープナーとは
- 現在のウィンドウを開いたウィンドウへの参照を返します。
- 利用方法として、opener経由で親ウィンドウのJavaScript関数を実行可能
リンク種別とは
- <a>,<area>,<form>,<link> の何れかを用いて他の文書へリンクするときに設定します。
- リンク種別で 2 つの文書間の関係を示します。
再現方法
- aタグでサブウィンドウを開くと簡単に再現できました(VSCodeのLiveServerで実行)。
mainWindow.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script type="text/javascript" src="../js/scriptA.js"></script>
<script type="text/javascript" src="../js/scriptB.js"></script>
</head>
<body>
<table>
<tbody>
<thead>
<tr>
<th>window.opener確認用</th>
</tr>
</thead>
<tr>
<td>
<a href="../html/subWindow.html" target="_blank" >リンク種別なし</a>
</td>
</tr>
<tr>
<td>
<a href="../html/subWindow.html" target="_blank" rel="opener">リンク種別あり(opener)</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
参考
: アンカー要素 - HTML: HyperText Markup Language | MDN