Javascript

【javascript】 親ウィンドウから子ウィンドウデータを受け渡す方法(open、opener)

Javascriptを使って別ウィンドウからデータを受け渡す方法を調べて勉強したので、ここにメモしておきます。

親ウィンドウと子ウィンドのデータの受け渡しは画面が別々になっているので少し混同しがちですが、しっかり整理して理解すればそんなに難しいことではありません。

子ウィンドウから親ウィンドウへデータを渡す

サンプルプログラム

まずは子ウィンドウから親ウィンドウへのデータ渡しの方法から説明します。

Javascriptでウィンドウを開くには以下のコードで行います。

 javascript
window.open(URL, ウィンドウ名, オプション);

ウィンドウを開く側の親ウィンドウのサンプルソースを用意しました。

sample01.html:

<meta http-equiv="content-type" charset="utf-8">
<script type="text/javascript">
<!--
function openWindow1(url, name) {
  window.open(url, name, 'width=400,height=300');
}
-->
</script>

<form name="parent_window">
<b>親ウィンドウ</b>
<p>氏名:<span id="pr_name"></span></p>
<p>年齢:<span id="pr_age"></span></p>
<p><a href="javascript:void(0);" onclick="openWindow1('sample02.html', 'child_window1')">子ウィンドウ1を開く</a></p>
</form>

5行目のスクリプトが子ウィンドウを開くコードになります。

続いて子ウィンドウのサンプルは以下の通りです。

sample02.html:

<meta http-equiv="content-type" charset="utf-8">

<script type="text/javascript">
<!--
  function returnWindow() {
    // 親ウィンドウの存在チェック
    if(!window.opener || window.opener.closed){
       window.alert('親ウィンドウがありません。');
       return false;
    }
    // 子ウィンドから親ウィンドウへ値を渡す
    window.opener.document.getElementById("pr_name").innerHTML = document.getElementById("chl_name").value;
    window.opener.document.getElementById("pr_age").innerHTML  = document.getElementById("chl_age").value;
  }
-->
</script>

<b>子ウィンドウ1</b>
<p>氏名:<input type="text" id="chl_name"></p>
<p>年齢:<input type="text" id="chl_age"></p>
<p><a href="javascript:void(0);" onclick="returnWindow()">親ウィンドウに値を渡す</a></p>

親ウィンドウのデータを渡すには「window.opener」を使います。

子ウィンドウ側で「window.opener.document」(12、13行目)と書けば自動で親ウィンドウのオブジェクト情報が格納されているので、要素の値を取得したり逆に値を挿入したりすることができます。

動作検証

実際に動作を試してみます。

上記では、まず親ウィンドウのリンクをクリックする(①)ことで子ウィンドウが表示(②)されます。

次に子ウィンドウの氏名と年齢のテキストボックスに適当な値を入力(①)しリンクをクリックする(②)と、親ウィンドウのラベルに入力し内容が反映されました(③)

正常に子ウィンドウから親ウィンドウへデータが渡されたのが確認できたと思います。

親ウィンドウが複数存在した場合の動作検証

今度は親ウィンドウと子ウィンドが複数存在した場合はどう動作するのでしょうか。

下図の通り、2窓ある親ウィンドウからそれぞれ表示された子ウィンドウが2つずつあるケースを考えます。

それぞれの親子関係を分かりやすくするように、グループAとグループBのようにグループピングしておきます。

 

グループAの子ウィンドウに氏名と年齢を入力しリンクをクリックすると、グループAの親ウィンドウに入力内容が渡されました。 

同じように今度はグループBの子ウィンドウで同じ操作をすると、ちゃんとグループBの親ウィンドウの方にデータが渡りました。

つまり、複数ウィンドウを立ち上げてもそれぞれの親子関係は自動で識別されて反映されます

これはJavascript側でそれぞれのDOMに対して識別キーを持っており、その識別キーをもって親子関係を判断しているのです。とてもおりこうさんです。

 

親ウィンドウから子ウィンドウへデータを渡す

サンプルプログラム

親ウィンドウから子ウィンドウへのデータの渡し方についても説明していきます。

方法としては「window.open」を引数に渡すことで、呼び出される側(子ウィンドウ)のオブジェクト情報を保持し操作することが可能です。

先ほど使ったsample01.htmlを以下のように修正します。

sample01.html(修正):

<meta http-equiv="content-type" charset="utf-8">
<script type="text/javascript">
<!--
function openWindow1(url, name) {
  window.open(url, name, 'width=400,height=300');
}

function openWindow2(url, name) {
  // windowオブジェクトを変数に格納
  var obj_window = window.open(url, name, 'width=400,height=300');
  // 親ウィンドウから子ウィンドウへ値を渡す
  obj_window.document.getElementById("chl_name").value = document.getElementById("pr_name").innerHTML;
  obj_window.document.getElementById("chl_age").value  = document.getElementById("pr_age").innerHTML;
}
-->
</script>

<form name="parent_window">
<b>親ウィンドウ</b>
<p>氏名:<span id="pr_name"></span></p>
<p>年齢:<span id="pr_age"></span></p>
<p><a href="javascript:void(0);" onclick="openWindow1('sample02.html', 'child_window1')">子ウィンドウ1を開く</a></p>
<p><a href="javascript:void(0);" onclick="openWindow2('sample03.html', 'child_window2')">子ウィンドウ2を開く</a></p>
</form>

12行目と13行目が子ウィンドウへデータを転送している部分になります。

動作としては「子ウィンドウ2を開く」のリンクをクリックすると、親ウィンドウの氏名と年齢の値が子ウィンドウ2のテキストボックスに反映されるイメージです。

動作検証

しかし、ここでトラブル発生。

上記のサンプルをそのまま実行すると、実行エラーになってしまいました。

原因としては、子ウィンドウの開く処理とデータ転送の処理をたて続け行ってしまったため、まだ子ウィンドウが開ききっていないのにも関わらずテキストボックスを操作しようとしたため、「そんな要素はないよ!」と怒られてしまいました。

このエラーを開始するには「ウィンドウを開く処理(10行目)」と「データを転送する処理(12、13行目)」を個別に分けるか、既に開いてるウィドウに対して操作するようにすることです。

もしそれでも開く処理と転送の処理を一連の流れでやりたい場合は、子ウィンドウを開いたタイミングで子ウィンドウの方からデータを取りに行く造りにすると解決できます。

サンプルとしては以下の通りです。

sample03.html:

<meta http-equiv="content-type" charset="utf-8">

<script type="text/javascript">
<!--
  window.onload = function(){
    // 親ウィンドウの存在チェック
    if(!window.opener || window.opener.closed){
       window.alert('親ウィンドウがありません。');
       return false;
    }
    // 子ウィンドから親ウィンドウへ値を渡す
    document.getElementById("chl_name").value = window.opener.document.getElementById("pr_name").innerHTML;
    document.getElementById("chl_age").value = window.opener.document.getElementById("pr_age").innerHTML;

  }
-->
</script>

<b>子ウィンドウ2</b>
<p>氏名:<input type="text" id="chl_name"></p>
<p>年齢:<input type="text" id="chl_age"></p>
<p><a href="javascript:void(0);" onclick="window.close()">ウィンドウを閉じる</a></p>

動かしてみた結果は以下の通りです。

自分が想定した動きをしてくれました。

これでJavasriptのウィンドウ関連の処理は何とかなりそうです。

-Javascript