お待たせしても、コードのできは、★1っ!? getStringRange
完成間近か!?経過報告。
さらなる、むちゃ振りを予測しつつ、文字列による検索において、index値と offset値 がマイナスでも機能するように思案中。
- 検索位置の目印を、movePointer で移動しておいて、getOffsetPointer で、相対的な位置のノードを取得する
- 文字列の検索位置からノードを探すより、最初にルート以下のテキストノードとその文字数を配列に保存し、そこから検索したほうがスマートなような気がしてきました。
<!DOCTYPE html> <title></title> <body style="background-color:#666"> <h1><em>洋野町</em>(ひろのちょう)</h1> <h2>プロフィール</h2> <ul> <li> 洋野町は、岩手県の中で、最北端に位置し、東側は太平洋に面しています。 <li> 「リアス式海岸」といえば、「三陸」を連想する人もいると思います。残念ながら洋野町は、 そこより北に位置し、範囲に含まれません。そしてこれといって特徴がありません。 <li> 人口は、7月31日現在で、19420人です。(100歳を超えなくても、所在不明な人はいます。予測) <li> 数年前に、隣の大野村と合併しました。それまでは、種市町(たねいちまち)と呼ばれていました。 <li> 「南部もぐり」と呼ばれ、潜水技術が発展しており、日本中の海洋建設の基礎工事現場などで、本町出身者の方々は活躍しています。 <li>本州最東端は、洋野町から南に100kmほどの地点にある半島です。 </ul> <script> (function () { var root; // ルート var serch; // 検索文字列 or 検索正規表現 var index; // var offset; // var doc; // var text; // var lastIndex; // var pointer; // //正規表現なのか var isRegExp = function ( reg ) { return (reg instanceof RegExp); }; // range の作成 var newRange = function ( ) { return doc.createRange (); }; //次のノードを返す var getNextNode = function ( node ) { var n; if (n = node.firstChild) return n; do { if (n = node.nextSibling) return n; node = node.parentNode; if (root == node) break; } while (node); return null; }; //前のノードを返す var getPreviousNode = function ( node ) { var n; if (n = node.previousSibling) { while (n.hasChildNodes ()) n = n.lastChild; return n; } node = node.parentNode; if (root == node) node = null; return node; }; // テキストノードを得る var getTextNode = function (node, flag) { var n = node; do { n = flag ? getPreviousNode (n) : getNextNode (n); if (! n) return null; } while (3 !== n.nodeType); return n; }; // ポインターの位置からのオフセット位置のノードとオフセットを返す var getOffsetPointer = function (o) { var n = pointer.node; var s, p; if (o < 0) { // オフセットがマイナス p = -pointer.offset; while (p > o) { if (n = getTextNode (n, -1)) p -= n.data.length; else return { 'node': pointer.node, 'offset': 0 }; } return { 'node': n, 'offset': -p + o }; } else { // オフセットがプラス s = pointer.offset; p = n.data.length - s; while (p < o) { if (n = getTextNode (n)) { o -= p; p += n.data.length; } else return { 'node': pointer.node, 'offset': pointer.node.data.length }; } return { 'node': n, 'offset': s + o }; } }; // p で示される位置まで、テキストノードの文字をカウントしながら移動する // ノードとその文字のオフセットを返す var movePointer = function (p) { var n = pointer.node; var max, len; do { len = n.data.length; max = pointer.index + len; if (p < max) break; pointer.index = max; n = getTextNode (n); if (! n) throw new Error; //テキストノードが終端 } while (true); pointer.offset = len - (max - p); pointer.node = n; }; // 正規表現で検索 var collectRegExp = function ( ) { var range, obj, words; var result = [ ]; var i, w, o; do { // search.lastIndex = lastIndex; words = search.exec (text); if (! words) break; range = newRange (); movePointer (words.index) // pointerを移動する for (i = 0; w = words[i++]; ) { o = words[0].indexOf (w); obj = getOffsetPointer (o); range.setStart (obj.node, obj.offset); obj = getOffsetPointer (o + w.length); range.setEnd (obj.node, obj.offset); result.push (range); // lastIndex += words[0].length; } } while (true); return result; }; // 文字列で検索 var collectString = function ( ) { var range, obj, words; var result = [ ]; var len = search.length; var o = 'undefined' === typeof offset ? len - index : offset < 0 ? len - index + offset : offset; do { lastIndex = text.indexOf (search, lastIndex); if (-1 === lastIndex) break; range = newRange (); movePointer (lastIndex) // pointerを移動する obj = getOffsetPointer (index); range.setStart (obj.node, obj.offset); obj = getOffsetPointer (index + o); range.setEnd (obj.node, obj.offset); result.push (range); lastIndex += len; } while (true); return result; }; //初期設定 var init = function (a, b, c, d) { if (2 > arguments.length) return null; root = a; search = b; index = c || 0; offset = d; doc = root.ownerDocument; text = root.textContent; lastIndex = 0; pointer = { 'node': getTextNode (root), 'index': 0, 'offset': 0 }; return isRegExp (search) ? collectRegExp () : collectString (); }; // 選択領域を設定する var setSelectRange = function (range) { var selection = this.getSelection(); var i, r; selection.removeAllRanges (); // 解除 for (i = 0; r = range[i++]; ) selection.addRange (r); }; // グローバルに登録 this.getStringRange = init; this.setSelectRange = setSelectRange; })(); //_______ setSelectRange (getStringRange (document.body, '洋野町', -5, -1)); alert("ok"); setSelectRange (getStringRange (document.body, /(最[東西南北]端)/g)); </script>
友達のヘアーサロンのホームページが検索されるように、ボソッと記載
ビューティーサロン「セピア」です
県外からも大歓迎ってが!