日々のコンピュータ情報の集積と整理

Dr.ウーパのコンピュータ備忘録

2014年6月5日木曜日

JavaScript:新しいウィンドウへHTMLを書き出すブックマークレットを作成した時にハマった罠-匿名関数を利用しないと元のウィンドウの内容が変わる場合がある

イントロダクション

ブラウザのブックマークに JavaScript を登録して実行する”ブックマークレット”というものがあります。

ブックマークレットを利用すると、ブラウザ上で簡単な処理を実行でき、利用する場面によっては非常に便利です。

今回は、新しいウィンドウへ HTML を出力するブックマークレットを作成した時にハマった罠について記載します。




コード

ブックマークレットが実行されたら、新しいウィンドウへ HTML を出力するようにするため、以下のコードを作成しました。

    // 新しいウィンドウにデータを出力
    var win = window.open();
    win.document.write("<html><head><title>test</title></head><body></body></html>");
    win.document.body.innerHTML = "<p>テスト!</p>";


このコードをブックマークレットとして実行するため、一行に圧縮し、javascript:を付けたものが以下のようになります。

javascript:var win=window.open();win.document.write("<html><head><title>test</title></head><body></body></html>");win.document.body.innerHTML="<p>テスト!</p>";


これを Chrome ブラウザのブックマークに登録し、ブックマークレットとして動作させてみました。

すると、確かに新しいウィンドウが開き、そこに HTML が出力されるのですが、ブックマークレットを実行するとき開いていたウィンドウにも同じく HTML が出力されていました。


他のブラウザでも同じブックマークレットを使用して実験した結果、次のようになりました。


Chrome

バージョン:

35.0.1916.114 m

動作:

確かに新しいウィンドウが開き、そこに HTML が出力される。
しかし、ブックマークレットを実行するとき開いていたウィンドウにも同じく HTML が出力される。

Internet Explorer

バージョン:

9.0.8112.16421

動作:

確かに新しいウィンドウが開き、そこに HTML が出力される。
ブックマークレットを実行するとき開いていたウィンドウは変化なし。

Firefox

バージョン:

29.0.1

動作:

確かに新しいウィンドウが開き、そこに HTML が出力される。
しかし、ブックマークレットを実行するとき開いていたウィンドウにも同じく HTML が出力される。


以上のように、ChromeとFirefox の場合には、ブックマークレットを実行するとき開いていたウィンドウにも同じく HTML が出力されるという現象が発生しました。
Internet Explorer では、ブックマークレットを実行するとき開いていたウィンドウは変化がありませんでした。


なぜこのような動作を示すのでしょうか?

一つ仮説をたてました。
ブラウザのアドレスバーへ

javascript:"テスト";

と入力して実行すると、そのときに表示していたページに

テスト

という文字列だけが表示されます。


つまり、プログラムの最後の行の戻り値がブラウザに表示されているのではないでしょうか。

最初に示したプログラムでいえば、

    win.document.body.innerHTML = "<p>テスト!</p>";

が最終行であり、win.document.body.innerHTML がブラウザに表示されているとしたらつじつまが合います。


そこで、各ブラウザに置いて、

javascript:"テスト";

をブックマークレットとして登録して、実行してみました。

結果は予想通り、Chrome と Firefox では、そのときに表示していたページに

テスト

という文字列のみが表示されました。

また、Internet Explorer では、そのときに表示していたページに何の変化も起こりませんでした。


元のウィンドウの内容を変えないためにはどうすればよいか?

元のウィンドウの内容を変えずにブックマークレットを実行するには、ブックマークレットとして実行したい JavaScript を匿名関数として実行すればよいわけです。

匿名関数として実行するには、JavaScript コードを (function () { と })(); で囲みます。


例えば、

(function () { 
    // 新しいウィンドウにデータを出力
    var win = window.open();
    win.document.write("<html><head><title>test</title></head><body></body></html>");
    win.document.body.innerHTML = "<p>テスト!</p>";
)();

とし、これを一行に圧縮すると、

javascript:(function () {var win=window.open();win.document.write("<html><head><title>test</title></head><body></body></html>");win.document.body.innerHTML="<p>テスト!</p>"})();

となります。


このように、匿名関数として実行すれば、戻り値が返らないため、元のウィンドウの内容が変わることはありません。





関連記事

関連記事を読み込み中...

同じラベルの記事を読み込み中...