masahirorの気まま記録簿

個人的な出来事や意見、生活などの記録を思うままにブログに記録

FireFoxでJavascript「window.close()」を使うには

昨日今日とWebでアンケート入力するASPを作成。その中で、アンケートが終了したら「閉じる」ボタンが表示され、クリックするとウインドウを閉じるというレイアウトにしたかったので、一般的なJavascriptを使った「windows.close();」を利用した。
【ボタンの場合】

<input type=button value=ウインドウを閉じる onclick="window.close()">

【リンクの場合】

<A HREF="#" onClick="window.close()">ウインドウを閉じる</A>
または
<A HREF="javascript:window.close()">ウインドウを閉じる</A>

この方法でばっちり!・・・と思っていたら、IEだと問題なく動作するが、FireFoxでは動作しないとの指摘があった。確かにFireFoxでは動作しない。テスト環境はWindowsXP&Mozilla FireFox1.0.X。
情報を検索してみると、

FirefoxJavaScriptで開いたウィンドウじゃないと window.close() が利いてくれません(ぇー

とのこと。そして、上記のページとtextbox.jp のネタ帳 :: 050311 :: 備忘録 :: Firefoxとwindow.close()で分かったことは、

  • 普通に開いた画面なら効かない
  • 「target=_blank」で開かれたページなら有効になる
  • 「onClick="window.open('ページのURL')」で開かれたページなら有効になる

というように、通常のページ移動で開かれたページでは有効にならない様子。
これを元に対策を2つ考えた。

「閉じる」ボタンが先にあるページの手前で「target=_blank」でウインドウを開かせる
検索等でそのリンクの途中のページから開かれると効果ないし、リンクをアドレスバーへドラッグ&ドロップして同じウインドウに開かれると効果がない。
同じように手前で「"window.open('ページのURL')」で開かせる
こちらだとリンクをアドレスバーにドラッグ&ドロップされる心配はないが、上記と同様途中のページから開かれると効果がなくなる。

この2つの「新しいウインドウ」案である程度回避することもできるが、どうも勝手悪い。例えば、今作成してるアンケート入力画面はメールでページのURLを通知するので、メーラーによるかもしれないがメーラーからクリック等でURLを開かれると「新しいウインドウ」で開いたことにはならない。同様にURLのコピペで開かれても同じ。フォーム自体の「target」を「_blank(新しいウインドウ)」にするのもありだが、入力画面が残ってしまうので「登録」ボタンを再度押されると重複登録される可能性がある*1
この例の場合、回避方法として「一つ中間ページを入れる」という手が考えられる。通知するURLは「アンケートを入力する」というボタンだけ配置したページにしておいて、そこのボタンを押すと新しいページが開き入力画面になり、そしてSubmitを押すと完了画面と「閉じる」ボタンが表示される、というものであればいいかもしれない。しかし、勝手悪いというより、IEで普通に閉じるのだから同じように動かせないとなんか納得いかない。
という訳で、先ほどのページを何度も読んでいたら、コメント欄に解決策が投稿されていたので、これを元にテストページを作り、FireFoxで動作確認すると・・・無事動作!その内容を以下に紹介。

手順

まず、ページのどこか(HEADの中がよい)に以下ソースを記述。

<script type="text/javascript" language="JavaScript">
<!--
function close_win(){
  var nvua = navigator.userAgent;
    if(nvua.indexOf('MSIE') >= 0){
      if(nvua.indexOf('MSIE 5.0') == -1) {
        top.opener = '';
      }
    }
    else if(nvua.indexOf('Gecko') >= 0){
      top.name = 'CLOSE_WINDOW';
      wid = window.open('','CLOSE_WINDOW');
    }
    top.close();
}
-->
</script>

次に、閉じるボタンを置きたい場所に以下タグを記述。

<INPUT type="button" value="閉じる" onclick="close_win()">

閉じるリンクの場合は以下タグ。

<A HREF="#" onClick="close_win()">ウインドウを閉じる</A>
または
<A HREF="javascript:close_win()">ウインドウを閉じる</A>

はてなでは直接貼れないので、動作サンプルページを作成。

動作サンプル
http://www.geocities.jp/masahiror/firefox/

※上のリンクを新しいウインドウで開いてしまっては元も子もないので、コピー&ペーストでFireFoxのアドレスバーに貼り付けて移動。
ただし、1つだけ問題が。FireFoxはタブとウインドウの2種類あるが、1つのウインドウで複数のタブを開いているときに上記方法で閉じると、他のタブも一緒に閉じてしまう。他のウインドウや他のウインドウのタブは閉じませんが。しかしこれは、上記の「新しいウインドウ」案でも同じ動きをしたので、仕方ないのかな。

2006/03/02 追記

Firefoxのポリシーでは、「スクリプトによって開いたウインドウ以外はスクリプトで閉じれない」とのこと。なので、このやり方でできてしまうのは問題である。
しかし、イントラ内のページ作成において、ボタンがあるのに動かない方がインフラ管理者にとって大変になってしまう。わざわざポリシーの説明をするのもいいが、目的は業務の効率化であり、PCに詳しく無い人も多いので、読まなかったり理解されない可能性の方が高い。むしろ「なぜ動かないのか」「自分のPCが壊れた」などの問合せが増えてサポートが大変になってしまう。(自らFirefoxを選ばなくても、開発の要件でプロジェクトに入ったらFirefoxが入っていてなんとなく使ってる人や、言われるがままで使ってる人もいるだろう)
イントラなどにおいては、どうしてもとりあえず動くことの方が大事になってしまう。もちろん、プログラマとしてはその辺のポリシーにのっとって、うまいことプログラムで別の方法で回避する事も大事。もしそれが業務に深く関わるシステムなどだったら、しっかり検討してがちがちに作る必要があるが、ちょっとしたアンケートシステムにそんなに時間をとるわけにもいかないし、時間自体ももらえない。
そうなれば、とりあえず最低限のエラーだけ出ないものであればよしとなってしまう。
ここはプログラマとしてジレンマを感じる部分でもある。

さらに追記

FireFox3以上では動かないようです。

*1:Javascriptでボタンを無効にするという手はあるけど