Chromeではwindow.showModalDialogは使用できません。
「WEBサイトでポップアップが開かれて、開かれた画面(子画面)で何か選択すると、
元の画面(親画面)に選択された内容が反映される。」
ていうやつWEBサイトを開発してたらよくありますよね?
そんな時のやりたいこと、、、、、、
- 子画面が開いている時は親画面をいじられたくない。
- 親画面のElementを操作したい。
- 子画面を閉じると、親画面にフォーカスを当てたい。
window.showModalDialogを使って子画面を開き、
子画面で親画面のElementを取得し、
子画面を閉じると親画面にフォーカスが当たってくれます。
親画面の処理
// windowをモードダルで開く
// 第一引数Url、第二引数子画面をに渡す値
window.showModalDialog('sub.html',this,'width=400, height=300');
子画面でボタンを押した時などの処理
// 親画面から渡ってきた値を取得
// 今回は親画面のElementを操作する為windowを渡した
var parentWindowObject = window.dialogArguments;
// 親画面のelement1を取得
var element1 = parentWindowObject.document.getElementById('hoge1');
// element1に値を設定
element1.value = '値1';
// 親画面のelement2を取得
var element2 = parentWindowObject.document.getElementById('hoge2');
// element1に値を設定
element2.value = '値2';
// 子画面の終了
window.close();
簡単ですね・・・・
でも
ChromeではshowModalDialogが使えません。
クリックイベントなどでshowModalDialogを記載して、ボタンを押しても
Chromeだとウンともスンとも言ってくれませんでしたorz
なので、僕は以下の方法で、やりたいことを実現しました。
##showModalDialogが使えない時
親画面の処理
// 適当に高さを指定してwindow.openでポップアップ画面を開く
var openWindow = window.open('sub.html','sub','width=400, height=300');
// 親画面にシェードをかける処理を実施
~ 処理の内容は省略 ~
// 1秒間隔で子画面の状態を監視
var interval = setInterval(function()
{
// 子画面が閉じていたら
if(!openWindow || openWindow.closed)
{
// 親画面のシェードを外す処理
~ 処理の内容は省略 ~
// Intervalを破棄
clearInterval(interval);
// 画面が起動していたら
}
else
{
// 子画面にフォーカスを当てる
if(!openWindow.document.hasFocus())
{
openWindow.focus();
}
}
},1000);
子画面の処理① ~ボタン押下等の処理~
// 親画面の存在確認
// 存在しなかったら次画面(子画面)を閉じる
if(!window.opener || window.opener.closed)
{
window.close();
}
else
{
// 親画面を取得
var parentWindowObject = window.opener;
// 親画面のelement1を取得
var element1 = parentWindowObject.document.getElementById('hoge1');
// element1に値を設定
element1.value = '値1';
// 親画面のelement2を取得
var element2 = parentWindowObject.document.getElementById('hoge2');
// element1に値を設定
element2.value = '値2';
// 子画面の終了
window.close();
}
子画面の処理② ~子画面自身の状態確認~
$(document).ready(function()
{
$(window).on("beforeunload",function(e)
{
window.opener.focus();
});
});
です。
##まとめ
window.showModalDialogで渡した親画面のObjectについては
window.openの場合はwindow.openerで取得することができます。
window.openの戻り値は子画面のObjectになります。
またjQueryの処理になりますが、
子画面起動後、setIntervalを行うことにより、
Timer処理で子画面の状態を監視できます。
while等を使ってループさせてしまうと、画面が固まるので
setIntervalでTimer処理を行います。
子画面が閉じられたと判断したら
clearIntervalでTimer処理を破棄します。
子画面が開いているときは、
openWindow.document.hasFocus
で子画面にフォーカスが当たっているか判断して、
当たっていなかったらopenWindow.focusでフォーカスを当てます。
openWindow.document.hasFocusの判定を行わずに
フォーカスを当て続けると、テキストボックス等に値を入力しているときに
Window全体にフォーカスが当たってしまうので、入力が途中でキャンセルされちゃいます
最後に子画面の監視処理です。
今回はjQueryを使ってwindowのbeforeunloadイベントをバインドしました。
これにより×ボタンでWindowを閉じてもイベントをひろうことができます。
完全なモーダルの場合は子画面を閉じると親画面にフォーカスがあたるのですが、
window.openで起動するとモードレスになるので、
親画面を最小化したりして親画面のIEを見失った時には便利です。
以上