ちょっと柔軟なscrollIntoView
grep を 作っていて
ヒットした位置にスクロールする処理で困りました。
DOMNode には、scrollIntoViewで スクロールできますが、
textnode に対してできないので、
多きなtextnodeの一部の場合 画面内含まれる保証がありません。
(あとセンタリングできない)
そのため、自力算出前提で調べていたら、良いものを見つけたのでメモ
nsISelection2のscrollIntoViewです。
いい加減な説明は
void scrollIntoView( //nsISelectionController.SELECTION_ANCHOR_REGION だと 先頭基準 //nsISelectionController.SELECTION_FOCUS_REGION だと 末尾基準 in short aRegion, //true で 即反映 false で 後で反映 in boolean aIsSynchronous, //垂直水平方向移動位置 を 割合で指定 //0 で上(左)寄せ //50 で センタリング //100 で 下(右)寄せ //-1 でスクロール量を最小限 in short aVPercent, in short aHPercent)
となります。
選択範囲 を 画面に 対して 水平垂直に 割合指定 でスクロールができます。
これで、自力計算しないですみましす。ヽ(´ー`)ノ
とりあず、frame,iframe, overflow要素内 1 つ づつ試したところ
上手くやってくれました。
以下に、Node に 適応してみました
(function(){ function scrollIntoView2(aNode, aVPercent, aHPercent){ var doc = aNode.ownerDocument; var win = doc.defaultView; var selection = win.getSelection(); var ranges = function(selection){ var selection = win.getSelection(); for(var i=0,j=selection.rangeCount;i<j;++i){ yield selection.getRangeAt(i); } }; var back = [r for(r in ranges(selection))]; selection.removeAllRanges(); var r = doc.createRange(); r.selectNode(aNode); selection.addRange(r); selection .QueryInterface(Components.interfaces.nsISelection2) .scrollIntoView( Components.interfaces.nsISelectionController.SELECTION_ANCHOR_REGION ,true,aVPercent,aHPercent); selection.removeAllRanges(); for(let [,r] in Iterator(back)){ selection.addRange(r); } } //nodeは 適当に選択する //node.scrollIntoView(true)相当 scrollIntoView2(node, 0, 0); //センタリング scrollIntoView2(node, 50, 50); //node.scrollIntoView(false)相当 scrollIntoView2(node, 100, 100); //最小スクロール量で画面内に納める scrollIntoView2(node, -1, -1); })();