ある要素が見える位置までスクロール
into_viewport という関数を作ってみた。
Chrome 以外ではチェックしてない。(でも IE 含め、他のブラウザで使えない関数などは使ってないはず)
IE に getComputedStyle が無いのを忘れてた。var s = getComputedStyle(elem, null);
のところを var s = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle;
にしたらいいのかな? (IE 持ってないのでわからない)
微修正。body や html 要素に overflow:auto などが着いてると変なことになる件。あと、Firefox と Opera では互換モードのとき document.body.scrollTop が使えて、標準モードのときは document.documentElement.scrollTop を使わないといけない。Chrome と Safari は標準、互換とも document.body.scrollTop で OK。UserAgent で判定するのは不本意だけど、このへんは好きな判定方法を使ったらいい。
function into_viewport(elem) { var target = elem; while (elem = elem.parentNode) { if (elem === document.body || elem === document.documentElement) break; var s = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle; if (s && /auto|scroll/.test(s.overflowX + s.overflowY)) {alert([target,elem]); scroll_to_element(target, elem); into_viewport(elem); return; } } var origin = (document.compatMode !== 'BackCompat' && (window.opera || navigator.userAgent.indexOf('Gecko/'))) ? document.documentElement : document.body; scroll_to_element(target, origin); } function scroll_to_element(elem, origin) { if (origin === document.body || origin === document.documentElement) { var outer = {left: 0, right: window.innerWidth, top: 0, bottom: window.innerHeight}; } else { var outer = origin.getBoundingClientRect(); } var inner = elem.getBoundingClientRect(); var x = origin.scrollLeft; var y = origin.scrollTop; var flag = 0; if ((outer.left > inner.left || outer.right < inner.right) && ++flag) x += (inner.left + inner.right) / 2 - (outer.left + outer.right) / 2; if ((outer.top > inner.top || outer.bottom < inner.bottom) && ++flag) y += (inner.top + inner.bottom) / 2 - (outer.top + outer.bottom) / 2; //if (flag) {origin.scrollLeft = x; origin.scrollTop = y;} // スムーズスクロールしない場合 if (flag) new Tween(origin, { // スムーズスクロールする場合 time: 0.1, scrollLeft: { to: x }, scrollTop: { to: y } }); }
Prototype.js の Element.scrollTo だと overflow: scroll/auto
な親要素をわざわざスクロールしてくれないと思う。(ちらっとコード見ただけなので違ってるかも)
Tween は id:os0x さんの AutoPatchwork から持ってきたのを微修正して使っている。
ところで、
上のコードは、実は Chrome 用の Migemo ページ内検索を作ってるときに書いたのだけど、もし試したい人がいれば試してください。
正式に公開しました→Migemoでページ内検索するためのGoogle Chrome Extension - by edvakf in hatena
ソースを一つのフォルダに入れ、load unpacked extension でそのフォルダを指定。ChromeMigemo Extension が必須。
今のところキーバインドは、/ キーで検索開始、↓↑で次と前を選択、; でフォーカス。
ほとんど完成しているんだけど、一つだけ気になるのが、普通だったら↓のように "1 or 5" というのがこの位置に出るところが、
何故かこのページだけ右に大きくずれて出てしまう (↓うっすら見える?)。理由が分からなくてお手上げです。この件は修正した。
その他バグを発見したら教えてください。
MigemoFindInPage は最終的に ChromeKeyConfig と連携させるかマージする方向でいこうと思っている。キーハンドリングは出来ればやりたくない。