2005/05/18 水
Safari が JavaScript ファイルを動的ロードできない件
Mac OS X の標準ブラウザである Safari だと、createElement で生成した script 要素を appendChild しても、src 属性に指定した JavaScript ファイルが読み込まれない、という現象についてです。って、日本語とは思えない文ですね、これ。
少し前に「最速インターフェース研究会 :: [Ajax] JSAN構想とリモートデータの取得とUserJavaScript」や「川o・-・)<2nd life - bookmarkletの文字数制限を無くす」で話題になっていましたが、JavaScript 上で上記のようにしてやることで外部の JavaScript ファイルを動的にロードできる! ウマー! という話。bookmarklet の外部ソース化ができたり(活用例:川o・-・)<2nd life さん、fladdict.net blog さん)、最速インターフェイス研究会さんのデモ「GoogleSuggestの補完候補を取ってくる」のように XMLHttpRequest なしで Ajax ライクなこと、いや、それ以上のことができるとあってなかなか注目な技術なのですが、我らが Safari ちゃんでは動かないっぽいです。なんかもう慣れっこですが、正直しょぼーんです。
img 要素などは生成・表示できるので、createElement と appendChild はちゃんと動いているのですが、script 要素の場合は src に指定された JavaScript ファイルを有効にしてくれないようです。以下のことを試しましたが、どれも動きませんでした…。なんだよー。
- 読み込み先の js に直に「xxx()」と書く → 実行されず
- 読み込み元の html から 読み込み先の js 上の関数 yyy() を呼ぶ → 実行されず
- 読み込み先の js から 読み込み元の html 上の関数 zzz() を呼ぶ → 実行されず
これが同じ Mac の人気ブラウザである FireFox では動くんですよねー。いまや blog 界隈では FireFox ユーザのほうが多いかも知れませんが、Safari は Apple 謹製の標準ブラウザだけに悩ましいところ。バグというよりポリシーの違いな気もしますが。もし情報が間違っていたり、どんなブラウザでも動く解決策がありましたら教えて下さい。あ、Tiger の Safari では試してません。Tiger いつ買おうかな…。
ちなみに Safari は JavaScript における日本語の扱いも微妙なようで、最速インターフェース研究会さんのかっこいいナビやantipop2.0 さんのインクリメンタル検索などは日本語がバケバケだったり機能しなかったりします(悪い例としてあげてしまってスミマセン)。FeedAmazon のインクリメンタル検索や Amazon Explorer ではなんとか回避できているのですが(たぶん)、この辺の話はまた次の機会に…。
あと、ちょっと期待したのですが、WIPEOUT PUREなどに載っている PSP の Web ブラウザでも動きませんでした。createElement とかの DOM 関係は動かないようです。せっかく「PSP で Ajax!(疑似ですが何か?)」とかいって遊ぼうと思ってたんですが、非常に残念。
■ 追試
ふと思いつき、createElement ではなくて直接「<script type="text/javascript" src="xxx.js"></script>」と書いてみる実験を開始。xxx.js には「window.alert('hello!')」とか書いておいて、以下の実験をしました。
- 適当な div とかに innerHTML で script タグを書いてみる → 実行されず(IE でも動かず)
- document.write で script タグを書いてみる → 実行されるのだけれど元の document が真っ白(用途によっては使える)
- document.write(document.body.innerHTML + '<scr'+...+'ipt>') とかやってみる → 実行されるのだけれど微妙な結果(用途によっては使える)
- 上記は document.write(document.documentElement.innerHTML + '<scr'+...+'ipt>') のほうがよさげ
リンクやボタン、bookmarklet で呼ばれたときの document.write の挙動がよくわかりません。元の document を上書きかと思ったら、何回も実行すると追記になったりするし。「あ、close してないからだ」と思って document.close() するとちゃんと毎回上書きになるんだけど、それだと結局 Safari では一発目で js を実行してくれないし。うむー。最終的には最速インターフェイス研究会さんの GoogleSuggest デモみたいなことができれば満足なんだけどなぁ。もうちょっと研究してみます。
とりあえず、見ているページの URL などを使うタイプの bookmarklet だったら、document.write で script タグを書く方法がどのブラウザでも安定っぽいです(例:「fladdict.net blog: 今見ているサイト内で「はてなブックマーク」されてるエントリ一覧を表示するブックマークレット」の document.write 版)。
■ 追記
セキュリティアップデートかけたら document.write 版も動かなくなりました…(泣)。もー!
参考:
WEBプログラミング NOW!: Security Updateで、いつのまにやらSafariのバージョンに変化!!
WEBプログラミング NOW!: Safari1.3でGoogleサジェスト動かず・・・
Excerpt: 最速インターフェース研究会 :: [Ajax] JSAN構想とリモートデータの取...
Weblog: AUSGANG SOFT
Tracked: 2005年5月20日 12:26
Excerpt: AsociateHelper を AWS に対応させるために、リストマニア作成を...
Weblog: AUSGANG SOFT
Tracked: 2005年10月14日 13:31
Excerpt: 前に書いた「エントリー高速検索Widget」 実は、最初はJSONの読み込み部...
Weblog: Yoshioriの日記
Tracked: 2006年8月26日 02:26








