クロスブラウザでDOM Rangeを扱えるようにした・・・い
IE対応しようとすると、途端にめんどくさくなる。
早さとかいいから、JSのエンジン変え(ry
IE8の開発者ツールは、時代に追いついた感じで素晴らしい。
みんな、せめてIE8にしてくれ。
まだ、途中ですが経過報告。
メソッド毎にDOM Rangeのサポート有無で振り分けるのもなんなので、ラッパーメソッドからして分けてみようと思いました。
ソース
var R = window.R = function(selection) { var // DOM Level 2 Rangeをサポートしているかチェック supportRange = !!document.createRange, // DOM Level 2 Rangeをサポートしているかどうかでラッパーを変える methods = (function() { var m; // DOM Level 2 Rangeをサポートしているブラウザ向けメソッド if (supportRange) { m = { start: function(textNode, index) { this.setStart(textNode, index || 0); return this; }, end: function(textNode, index) { this.setEnd(textNode, index || 0); return this; }, sel: function(node) { this.selectNode(node); return this; }, wrap: function(elem) { this.surroundContents(elem); return this; } } // DOM Level 2 Rangeをサポートしていないブラウザ向けメソッド(IE当て決め) } else { m = { start: function(node, index) { this.moveToElementText(node); this.moveStart('character', index || 0); return this; }, end: function(node, index) { this.moveToElementText(node); this.moveEnd('character', (0 - index || 0)); return this; }, sel: function(node) { this.moveToElementText(node); return this; }, wrap: function(elem) { elem.innerHTML = this.htmlText; this.pasteHTML(elem.outerHTML); return this; }, detach: function() { } }; } return m; })(), // Rangeオブジェクト取得 range = (function() { var r; if (supportRange) r = (selection) ? selection.getRangeAt(0) : document.createRange(); else r = (selection) ? selection.createRange() : document.body.createTextRange(); return r; })(); // Rangeオブジェクトにラッパーメソッドを設定 for (var o in methods) range[o] = methods[o]; return range; };
理想
var test1 = document.getElementById('test1'); var span = document.createElement('span'); span.style.color = 'red'; // id="test1"の3文字目から5文字目を赤くする new R() .start(test1, 3) .end(test1, 5) .wrap(span) .detach();
問題点
STARTとENDが同一要素ならいいが、複数の要素を跨いだ場合の色付けが期待通りにならない。