- ECMA-262第3版のStringのreplace()に似せる
- 置換する値としてNodeを許可する (置換する値として関数を渡した場合、その関数が返す値としてでも可)
- 置換した結果が複数のNodeになる場合はDocumentFragmentを、正規化などをして結果が1つのTextになる場合はTextを返す
- DOMインタフェースのprototypeの拡張、DOM2 Core、DOM2 Rangeが必要
例
var dummy = document.createElement("div");
var t = document.createTextNode("a\nb\nc");
var df = t.replace(/\n/g, document.createElement("br"));
dummy.appendChild(df);
alert(dummy.innerHTML);
dummy.innerHTML = "";
t = document.createTextNode("#a10#b20#c30");
df = t.replace(/#(.)/g, function(m, n){
var a = document.createElement("a");
a.href = n;
a.textContent = m;
a.addEventListener("mouseover", function(e){ }, false);
return a;
});
dummy.appendChild(df);
alert(dummy.innerHTML);
コード
Text.prototype.replace = function(searchValue, replaceValue){
var doc = this.ownerDocument;
if (replaceValue && typeof replaceValue.nodeType == "number") {
var node = replaceValue;
replaceValue = function(){ return node.cloneNode(true); };
}
if (typeof replaceValue == "function") {
var global = false;
if (searchValue instanceof RegExp) {
global = searchValue.global;
var sv = searchValue.toString().split("/");
var flags = sv[sv.length-1].replace("g", "");
searchValue = new RegExp(searchValue.source, flags);
}
var range = doc.createRange();
var result = doc.createDocumentFragment();
var text = this.cloneNode(false);
result.appendChild(text);
do {
var m = text.nodeValue.match(searchValue);
if (!m) break;
var index = text.nodeValue.search(searchValue);
m.push(index, text);
var r = replaceValue.apply(null, m);
if (!r || typeof r.nodeType != "number") {
r = doc.createTextNode(String(r));
}
range.setEndAfter(document.documentElement);
range.setStart(text, index);
range.setEnd(text, index + m[0].length);
range.deleteContents();
range.insertNode(r);
text = r.nextSibling;
} while (global);
result.normalize();
if (result.childNodes.length == 1) result = result.firstChild;
} else {
result =
doc.createTextNode(this.nodeValue.replace(searchValue, replaceValue));
}
return result;
};
問題
- もっとコンパクトにしたい
- 正規化するかどうか
- 一部のTextノードにイベントリスナが登録されていた場合でも正規化される
- Nodeの判別にx instanceof Nodeを使うかnodeTypeを調べるか