getStringRange を書いてみました。がっ!しかし、バグがウジャウジャしていそう!
node::textContents と、range::toString で得られる値が、常に同じなのか確かめていない。
IE未対応、そしてまだまだ、問題あり。
<!DOCTYPE html> <title></title> <head> <script> // getStringRange (root /*Element*/, serachReg /*RegExp*/ ) (function () { // n で指定されたノードを範囲とするテキストを返す var createGetRangeText = function (doc) { var r = doc.createRange (); return function (n) { r.selectNode (n); return r.toString (); }; }; // root の範囲内で、呼ばれるたびテキストノードだけを順次返す var createGetNextTextNode = function (root) { return function (node) { var m; do { if (! (node = (m = node).firstChild)) while (! (node = m.nextSibling)) if (root == (m = m.parentNode)) return null; } while (node && 3 !== node.nodeType) return node; }; }; // p で示される位置まで、テキストノードの文字をカウントしながら移動する // ノードとその文字のオフセットを返す var createMovePointer = function (root) { var pointer = 0; var node = root; var nextTextNode = createGetNextTextNode (root); var getRangeText = createGetRangeText (root.ownerDocument); var text; return function (p) { var m; while (pointer <= p) { if (node = nextTextNode (node)) { m = pointer; text = getRangeText (node); if (p <= (pointer += text.length)) return { element: node, offset: p - m }; } else return null; } return { element: node, offset: text.length - pointer + p }; }; }; // 正規表現でヒットした文字の index からテキストノードを得て範囲を貯める var getRange = function (root, searchReg) { var range, obj, words; var result = [ ]; var doc = root.ownerDocument; var getRangeText = createGetRangeText (doc); var movePointer = createMovePointer (root); var text = getRangeText (root); // = root.textContents while (words = searchReg.exec (text)) { range = doc.createRange (); // start obj = movePointer (words.index); range.setStart (obj.element, obj.offset); // end obj = movePointer (words.index + (words.toString ().length)); range.setEnd (obj.element, obj.offset); result.push (range); }; return result.length ? result: null; }; //_______ this.getStringRange = getRange; })(); //_______ window.onload = function() { var ranges = getStringRange (document.body, /最[東西南北]端|[^、].[町村]/g); var selection = getSelection (); if (ranges.length) { selection.removeAllRanges (); for (var i = 0, r; r = ranges[i++]; ) selection.addRange (r); } } </script> </head> <body> <h1><em>洋野町</em>(ひろのちょう)</h1> <h2>プロフィール</h2> <ul> <li> 洋野町は、岩手県の中で、最北端に位置し、東側は太平洋に面しています。 <li> 「リアス式海岸」といえば、「三陸」を連想する人もいると思います。残念ながら洋野町は、 そこより北に位置し、範囲に含まれません。そしてこれといって特徴がありません。 <li> 人口は、7月31日現在で、19420人です。(100歳を超えなくても、所在不明な人はいます。予測) <li> 数年前に、隣の大野村と合併しました。それまでは、種市町(たねいちまち)と呼ばれていました。 <li> 「南部もぐり」と呼ばれ、潜水技術が発展しており、日本中の海洋建設の基礎工事現場などで、本町出身者の方々は活躍しています。 <li>本州最東端は、洋野町から南に100kmほどの地点にある半島です。 </ul>