何度使ってもなかなか覚えられないのでメモ。
javascript:(function(){ var s='<div>hoge</div>'; var range = document.createRange(); var df = range.createContextualFragment(s); document.body.appendChild(df); })()
一見大丈夫そうだけど、Firefox でしか意図した通りに動いてくれない。
Safari では、range.createContextualFragment(s) のところで
Error: NOT_SUPPORTED_ERR: DOM Exception 9
というエラーが出る。
Opera では、
<body><div>hoge</div></body>
というノードが挿入されてしまう。この理由は、document.createRange() した瞬間には Range の始点が HTMLDocument になるため (以下のブックマークレットで試すと Firefox、Safari、Opera のどれも HTMLDocument が得られる)、div 要素を作成しようとしたとき本来無くてはならないはずの body タグを補完するため。(contextual な実装)
javascript:alert(document.createRange().startContainer);
そういうわけで、range の始点として body の中のどこかを指定してやる必要がある。
javascript:(function(){ var s='<div>hoge</div>'; var range=document.createRange(); range.selectNodeContents(document.body); /*この一行が大事!*/ var df=range.createContextualFragment(s); document.body.appendChild(df); })()
こうすることによって、Safari でも先のエラーが出なくなり、挿入されるノードも3ブラウザで等しくなる。
Safari のエラーの原因は不明。
参考
Safari で div に入れているのは、 createHTMLDocument を使うと Safari が高確率で落ちるという致命的なバグのためです。 div に入れると、元の Document にくっつける形になるので、id関数が使えなくなります…
http://javascript.g.hatena.ne.jp/edvakf/20090224/1235462786
このテストページでは Safari は落ちないっぽいので、何か条件があるんでしょうかね。