解決:IEでアドレスバーを出さないようにしても出てしまう謎な現象


UPDATED@2015-10-01

この現象は、Microsoft Edge では修正済みとのことです。素晴らしい。
https://connect.microsoft.com/IE/Feedback/Details/1850614

TL;DR

IE で window.open する時に、fullscreen オプションは絶対に指定してはいけません。何があっても!

経緯

業務アプリで、IE 限定な環境下だと、アドレスバーを出したくないというニーズがあったりします。ブラウザなんだけどアプリっぽく見せて、ユーザーにへんなことさせたくない、とかですね。

イマドキのいけてる環境だったら、Electron 使ってブイブイ言わせるのでしょうが、そうじゃない場合には、まあ、IE で頑張るしかない。

その過程で妙な現象に遭遇して、多大な時間を浪費してしまったので、メモっときます。

消しても消しても出てくるアドレスバー

最初、以下のようなコードを書いていました。実際には自家製フレームワークで自動生成するため、もっと複雑なコードなんですが、焦点を絞るために大幅に簡略化しています。

// 別ウィンドウで起動する
window.open(url, "_blank", "menubar=no,fullscreen=no");
// 元ウィンドウは閉じる
window.open("", "_self").close();

そして、これを実行するとアドレスバーが全く消えない。。。なぜ?

オプションを調べる

window.open の第3引数にはカンマ区切りで複数のオプションを渡せるようになっています。IE のリファレンスによると、第3引数で指定できるオプションは以下の通り(太字はデフォルト値):

  • location = { yes | no | 1 | 0 } - ナビゲーションバーを表示するかどうか。
  • menubar = { yes | no | 1 | 0 } - メニューバーを表示するかどうか。
  • toolbar = { yes | no | 1 | 0 } - ツールバーを表示するかどうか。
  • scrollbars = { yes | no | 1 | 0 } - スクロールバーを表示するかどうか。
  • status = { yes | no | 1 | 0 } - ステータスバーを表示するかどうか。
  • channelmode = { yes | no | 1 | 0 } - シアターモードで表示するかどうか。
  • fullscreen = { yes | no | 1 | 0 } - フルスクリーン表示するかどうか。
  • top = number - ウィンドウの Y 位置(ピクセル単位)。
  • left = number - ウィンドウの X 位置(ピクセル単位)。
  • height = number - ウィンドウの高さ(ピクセル単位)。
  • width = number - ウィンドウの幅(ピクセル単位)。
  • resizable = { yes | no | 1 | 0 } - サイズ変更可能とするかどうか。

ずいぶんいろいろあります。しかも、用語が良くわからない。channelmode なのにシアターモードとはこれいかに? そこでいろいろ試して効果を確認していきました。そして fullscreen=no を取り除いたときのことです。

// 別ウィンドウで起動する
window.open(url, "_blank", "menubar=no");
// 元ウィンドウは閉じる
window.open("", "_self").close();

あ~ら不思議、ついにアドレスバーが消えたではないですか!でもなんで?

オプションの衝突

あらためて、fullscreen オプションの説明を読んでみます。

原文
Specifies whether to display the browser in full-screen mode. The default is no. Use full-screen mode carefully. Because this mode hides the browser's title bar and menus, always provide a button or other visual clue to help the user close the window. ALT+F4 closes the new window.

Internet Explorer 7. A window in full-screen mode doesn't need to be in theater mode.

In Internet Explorer 6, a window in full-screen mode must also be in theater mode (channelmode).
意訳
ブラウザをフルスクリーンモードで表示するかどうかを指定する。デフォルト値は no。フルスクリーンモードは注意して使うこと。このモードはブラウザのタイトルバーとメニューを消すので、ユーザーがウィンドウを閉じるためのボタンやそれに類したビジュアル要素を常に用意すること。ALT+F4 でウィンドウは閉じる。

IE7:フルスクリーンモードのウィンドウは、シアターモードである必要はない。
IE6:フルスクリーンモードのウィンドウは、シアターモードでもある必要がある。

fullscreen=no ということは、デフォルト値のままですから、未指定の場合と同じ挙動を示してもいいはずですが、実際には「タイトルバーとメニューを表示しない」を反転して、「タイトルバーとメニューを表示する」というモードになり、結果として menubar=no を打ち消してしまっていたようです。

ちなみに、fullscreen=no,menubar=no でも結果は変わらなかったため、指定する順番は無関係のようです。ロジックの流れは固定で、fullscreen を後から評価するようになっていると推測。

蛇足ながら、MDN のリファレンスfullscreen の説明を読むと、

原文
fullscreen always upsets users with large monitor screen or with dual monitor screen. Forcing fullscreen onto other users is also extremely unpopular and is considered an outright rude attempt to impose web author's viewing preferences onto users.
意訳
fullscreen は巨大なモニターやデュアルモニターを使っているユーザーをいつもイライラさせる。また、fullscreen を他のユーザーに強制するのは非常な不評を買い、Web 作成者の好みをあからさまにユーザーに押し付ける失礼な行為とみなされる。

といった具合に、かなり強い嫌悪感を示しています。というわけで、fullscreen は何があっても指定してはいけないのです。

振り返り

IE の fullscreen には、実は、{ yes | no | unspecified } の三つのモードがあった。これが最大の問題(というかバグ)であると同時に、我々が設計する時にも、気をつけるべきポイントの一つになると思います。

つまり、オプション未指定時と、デフォルト値を明示的に指定された時の挙動は確実に一致させるということ。単純かつ当たり前なことですが、これをしておかないと非常な混乱が巻き起こるわけです。そして、仮にどうしても unspecified をモードとして用意したい場合には、きちんとドキュメントを残すこと。

そもそも、直交しないオプションの設計が悪いとか、仕様が明確でないとか、いろいろ言いたいことはありますが、ほんの少しでも気づきがあったのが救い、と思いたいです。とほほ。。。