getStringRange 完成か!
かなり製作が遅くなりました。
これでも、ドーピングしました^^;
(リポD×7本以上摂取。)
見直しては、書き換えを繰り返し、そして全面書き直し、
何度繰り返したことか・・・。
<!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 getNextNode = function (node) { var n = node.firstChild; if (n) return n; do { if (n = node.nextSibling) return n; node = node.parentNode; if (this == node) return null; // this == root } while (node); throw new Error; // 親ノードが見つからない }; //前のノードを返す var getPreviousNode = function ( node ) { var n; if (n = node.previousSibling) { while (n.hasChildNodes ()) n = n.lastChild; return n; } node = node.parentNode; if (! node) throw new Error; // 親ノードが見つからない if (this == node) // this == root return null; return node; }; // テキストノードを得る var getTextNode = function (node, flag) { var n = node; do { n = flag ? getPreviousNode.call (this, n) : getNextNode.call (this, n); if (! n) return null; } while (3 !== n.nodeType); return n; }; // ポインターの位置からのオフセット位置のノードとオフセットを返す var getOffsetPointer = function (offset) { var pointer = { 'root' : this.root, 'target': this.target, 'index' : this.index }; var index = this.index + this.offset + offset; movePointer.call (pointer, index); return { 'target': pointer.target, 'offset': pointer.offset }; }; // indexで示されるテキストノードと、文字位置を返す var movePointer = function (index) { var n = this.target; var m; var max; if (! n) throw new Error; // テキストノードが見つからない if (index < this.index) { // 前方に検索 do { m = getTextNode.call (this.root, n, true); if (! m || index < 0) { this.target = n; this.index = 0; this.offset = 0; return this; } n = m; this.index -= n.length; } while (index < this.index); } else { // 後方に検索 while ((max = this.index + n.length) < index) { m = getTextNode.call (this.root, n); if (! m) { this.target = n; this.offset = n.length; return this; } n = m; this.index = max; } } this.target = n; this.offset = index - this.index; // return this; }; // 正規表現で検索 var getRangeByRegExp = function (search) { var doc = this.root.ownerDocument; var text = this.root.textContent; var target; var str; var i, offset; var result = [ ]; var range; var obj; // 検索ループ while ((target = search.exec (text))) { movePointer.call (this, target.index) // pointerを移動する for (i = 1; str = target[i++]; ) { // 全体は含めず range = doc.createRange (); offset = target[0].indexOf (str); obj = getOffsetPointer.call (this, offset); range.setStart (obj.target, obj.offset); obj = getOffsetPointer.call (this, offset + str.length); range.setEnd (obj.target, obj.offset); result.push (range); } }; return result; }; // 文字列で検索 var getRangeByString = function (search/*String*/, index/*Number*/, offset/*number*/) { var doc = this.root.ownerDocument; var text = this.root.textContent; // 検索対象の全文字列 var len = search.length; var lastIndex = 0; var result = [ ]; var range; var obj; // index, offset 初期値の設定 offset がマイナスなら最後尾からとする index = index || 0; offset = 'undefined' === typeof offset ? len - index : offset < 0 ? len - index + offset : offset; // 検索ループ while (-1 < (lastIndex = text.indexOf (search, lastIndex))) { range = doc.createRange (); // pointer を検索対象の最初の位置に移動する movePointer.call (this, lastIndex); obj = getOffsetPointer.call (this, index); // 検索文字列の最後をセット range.setStart (obj.target, obj.offset); // ノードとそのオフセット値をセット obj = getOffsetPointer.call (this, index + offset); // 検索文字列の最後をセット range.setEnd (obj.target, obj.offset); result.push (range); lastIndex += len; // 次の検索対象 } return result; }; //search が、文字列 or 正規表現かで振り分ける var getRange = function (root, search, index, offset) { if (arguments.length < 2) return [ ]; var pointer = { // pointer オブジェクトの作成 'root' : root, 'target' : getTextNode.call (root, root), 'index' : 0 /*, 'offset' : 0 */ }; return search instanceof RegExp //正規表現なのかで分岐 ? getRangeByRegExp.call (pointer, search) : getRangeByString.call (pointer, search, index, offset); }; // __________________ // 選択領域を設定する var setSelectRange = function (range) { var selection = this.getSelection (); // this == window var i, r; selection.removeAllRanges (); // 解除 for (i = 0; r = range[i++]; ) selection.addRange (r); }; // グローバルに登録 this.getStringRange = getRange; this.setSelectRange = setSelectRange; })(); //_______ setSelectRange (getStringRange (document.body, '洋野町')); alert("ok"); setSelectRange (getStringRange (document.body, /(洋野|種市)(町)/g)); </script>