残念ながら、jQuery は関数が初めて呼び出されたdata-*
ときに一度だけ属性を取得します。$().data(...)
またscrollspy
、初期化時に一度だけオプションを読み取ります。scrollspyのrefresh
機能は、どのオプションもリロードしません。同じ要素を再度呼び出す$(..).scrollspy(...)
と、新しいデータ オプションが無視されます (以前に初期化された値が使用されます)。
ただし、scrollspyはオプション値をキーの下の要素データに保存します'bs.scrollspy'
。したがって、options.offset
そのデータキー内のフィールドを変更できます。
動的に変化する navbar の高さと scrollspy オフセット値を変更する必要性を考慮して、可変高さの固定トップ navbar に次の例を使用できます。
以下は、いくつかのことを行います。
- (イベントが発生した後) javascript を介して scrollspy を初期化
window.load
し、navbar の現在の高さのオフセットから開始します (また、本体のpadding-top
値を navbar の高さと同じになるように調整します)。
- サイズ変更イベントが監視され、本体
padding-top
が調整され、スクロールスパイoffset
がそれに合わせて微調整されます。次にrefresh
、アンカー オフセットを再計算するために a が実行されます。
HTML
<body>
<style type="text/css">
/* prevent navbar from collapsing on small screens */
#navtop .navbar-nav > li { float: left !important; }
</style>
<nav id="navtop" class="navbar-fixed-top" role="navigation">
<div class="container">
<ul class="nav nav-pills navbar-nav">
<li><a href="#one">One</a></li>
<li><a href="#two">Two</a></li>
<li><a href="#three">Three</a></li>
... some more navlinks, or dynamically added links that affect the height ...
</ul>
</div>
</nav>
<section id="one">
...
</section>
<section id="two">
...
</section>
<section id="three">
...
</section>
....
</body>
JavaScript
$(window).on('load',function(){
var $body = $('body'),
$navtop = $('#navtop'),
offset = $navtop.outerHeight();
// fix body padding (in case navbar size is different than the padding)
$body.css('padding-top', offset);
// Enable scrollSpy with correct offset based on height of navbar
$body.scrollspy({target: '#navtop', offset: offset });
// function to do the tweaking
function fixSpy() {
// grab a copy the scrollspy data for the element
var data = $body.data('bs.scrollspy');
// if there is data, lets fiddle with the offset value
if (data) {
// get the current height of the navbar
offset = $navtop.outerHeight();
// adjust the body's padding top to match
$body.css('padding-top', offset);
// change the data's offset option to match
data.options.offset = offset;
// now stick it back in the element
$body.data('bs.scrollspy', data);
// and finally refresh scrollspy
$body.scrollspy('refresh');
}
}
// Now monitor the resize events and make the tweaks
var resizeTimer;
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(fixSpy, 200);
});
});
以上です。きれいではありませんが、間違いなく機能します。上記の私の HTML には微調整が必要な場合があります。
navbar に要素を動的に追加する場合は、要素fixSpy()
が挿入された後に呼び出す必要があります。または、タイマーをfixSpy()
介して呼び出して、常に実行することもできます。setInterval(...)