JavaScript で DOM Range を使った処理をしていたら、FireFox でも IE でも問題なく動くコードが、珍しく Chrome や Safari だとエラーを吐くのです。小一時間悩んだのだけれど、どうやらWebKitのせいらしい。
たまたま見つけたコチラの記事(英語)に上手くまとまっていたのだけれど、例えば、こんなふうにしたらエラーが出ます。
現象:
2013年2月16日現在の、最新の Chrome / Safari(iOS含む)でも、この現象が発生します。Rootノードが Document または Document-Fragment 以外のとき、ノードの最初の子要素を含む Range を指定しようとすると "INVALID_NODE_TYPE_ERR" を吐く。
たまたま見つけたコチラの記事(英語)に上手くまとまっていたのだけれど、例えば、こんなふうにしたらエラーが出ます。
var root = document.createElement( 'DIV' );
root.appendChild( document.createElement( 'SPAN' ) );
var r = document.createRange();
r.setStartBefore( root.firstChild ); // INVALID_NODE_TYPE_ERR !!
r.selectNode( root.firstChild ); // INVALID_NODE_TYPE_ERR !!
これを回避するには、ルートノードを Document か Document Fragment にしてやれば大丈夫。例えば、root を document-fragment の子要素にしてしまう。root.appendChild( document.createElement( 'SPAN' ) );
var r = document.createRange();
r.setStartBefore( root.firstChild ); // INVALID_NODE_TYPE_ERR !!
r.selectNode( root.firstChild ); // INVALID_NODE_TYPE_ERR !!
var root = document.createElement( 'DIV' );
root.appendChild( document.createElement( 'SPAN' );
var r = document.createRange();
var df = document.createDocumentFragment();
df.appendChild( root );
r.setStartBefore( root.firstChild ); // OK !
r.selectNode( root.firstChild ); // OK !
二番目に書いた「WebKitでエラーを出さないコード」は、このまま FireFox、Internet Explorer 8 / 9 で動作するので、とりあえず、そうしておけば無難なのですかな。root.appendChild( document.createElement( 'SPAN' );
var r = document.createRange();
var df = document.createDocumentFragment();
df.appendChild( root );
r.setStartBefore( root.firstChild ); // OK !
r.selectNode( root.firstChild ); // OK !
コメント