ハイライト

ラボでやってるGoogle詰め合わせ、AutoPager用のハイライト関数の話。findTextを完全に使わないのは無理がありそうでしばらく放置してたけど、さっきプリンに生クリームを載せることの是非について考察している最中に閃いたので早速試してみた。findTextのバグを回避する方法についてはfublogにてfubの作者が述べられている。実際に表示しているDOMを再構築してしまうとmala氏の指摘のような弊害があるので、cloneNodeを使ってdocument.bodyを丸ごと複製しておいてそちらでfindTextを行ってはどうか、と考えた。具体的には、複製したダミーのtextRangeでfindTextを実行してブックマークを取得、document.body側のtextRangeで取得したブックマークへ移動という手順をとる。

function highlight(word)
{
	fwc = new findWordClass(word, _document);
	while (fwc.find()) {
		fwc.range.execCommand("backColor", false, "#ffff80");
		fwc.range.execCommand("foreColor", false, "#000000");
	}
}
/**/
function findWordClass(word, doc)
{
	this.word = word;
	this.dumy = doc.body.cloneNode(true).createTextRange();
	this.range = doc.body.createTextRange();
	this.find = find;
}
function find()
{
	this.dumy.moveStart("character", this.word.length);
	if (this.dumy.findText(this.word, 1, 0)) {
		this.range.moveToBookmark(this.dumy.getBookmark());
		this.range.moveEnd("character", this.dumy.text.length - this.range.text.length);
		return true;
	}
	else {
		return false;
	}
}

結果として、予想に反し速度面では以前までのindexOfつかって大体のあたりをつけてmoveメソッドを使うやり方の最速バージョンに劣る。ただ、全然見当はずれの場所をハイライトすることはあまり無くなった。現状、getBookmark, moveToBookmarkに関してはさっぱり仕様がわかってないのでもうちょっとましにできるのかもしれない。