Bootstrapプラグインscrollspyソースの勉強
7948 ワード
使い方
3つの部分に分けることができます.スクロールの要素を監視し、aラベルを含む容器、対応するアンカーポイントを含むcontentスクロールをモニターする要素にdata-spy=「scroll」data-ta-ta-taget=「〓example」を追加します.これらの値は、Pluginを初期化する際に、オプトモーションオブジェクトとしての属性がSrollSpyに入る aタグを含む容器には、data-targetに対応するクラスまたはidが必要です.aラベルは、data-targetまたはhrefで対応するcontentにおけるアンカーポイントを指定するid コンテントにはそれぞれのアンカーポイントに対応するidが必要で、aラベルと関連 ページローディングが完了したら、すべてのdata-spy=「scroll」要素をScrrollSpyの一例として実装します.スクロールイベントをバインドし、ナビゲーションバーを見つけ、対応するアンカーポイントとアンカーポイントのoffsets スクロール時に、スクロール高さが最大のスクロール高さより大きいかどうかを判断し、最後のナビゲーションバーをハイライトする.スクロールの高さが最小offsetより小さいかどうかを再判定し、高明をクリアします.最後に最大スクロール高さより小さくて、最小スクロール高さより大きくて、どのセグメントoffsetにあるかを3つの&&&&&&で判断して、より高い明るさで対応するナビゲーションバー 現在の明るいナビゲーションバーをクリアし、現在対応するナビゲーションバーをハイライトする ナビゲーションバーがaタグの場合、hrefはidを指すので、ナビゲーションバーをクリックすると自動的に対応するConttent 初期化
オンラインの後、data-spy属性を含むラベルごとに、Pluginの初期化を完了します.コンストラクション get ScrrollHeight方法 refresh方法 process方法 activate方法 clear方法 $el.data()元素上のdataキャッシュデータの対象 Math.max互換性を利用して要素の内容高さを得る jqueryのoffset()は、現在のビューの相対オフセット(bodyでロールを傍受する時に使う)を得ることができ、position()は、要素がその親要素に対するオフセット(要素内でロールを傍受する時に使う)を取得することができる jqueryのmap()の奇妙な表現 フォーサイクルを利用して3つを追加すると、スクロール高さが条件を満たしているかどうかを判断することができる
3つの部分に分けることができます.スクロールの要素を監視し、aラベルを含む容器、対応するアンカーポイントを含むcontent
@item1
@item2
@item3
核心的な考えオンラインの後、data-spy属性を含むラベルごとに、Pluginの初期化を完了します.
$(window).on('load.bs.scrollspy.data-api', function () {
$('[data-spy="scroll"]').each(function () {
var $spy = $(this)
Plugin.call($spy, $spy.data())
})
})
Plugin入口分析/**
* [data-spy="scroll"] dom , property ScrollSpy
* @param {object} option property , spy target
* content , {target: '#nav-example'}
*/
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.scrollspy')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
if (typeof option == 'string') data[option]()
})
}
構造分析// , 、nav (selector),
function ScrollSply(element, options){};
// scrollHeigth( ), body
ScrollSpy.prototype.getScrollHeight = function () {};
// content
ScrollSpy.prototype.refresh = function () {};
//
ScrollSpy.prototype.process = function () {};
// target li
ScrollSpy.prototype.activate = function (target) {};
//
ScrollSpy.prototype.clear = function () {};
具体的に分析する/**
* 、nav 、 、 refresh() process()
* @param {object} element [data-spy="scroll"] dom
* @param {object} options offsets
*/
function ScrollSpy(element, options) {
this.$body = $(document.body)
// , body , window,
this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
// target( nav) a selector
// 'target .nav li > a', target .nav
this.selector = (this.options.target || '') + ' .nav li > a'
this.offsets = []
this.targets = []
this.activeTarget = null
this.scrollHeight = 0
this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
this.refresh()
this.process()
}
/**
* , body
* @return {number}
*/
ScrollSpy.prototype.getScrollHeight = function () {
// scrollHeigth , overflow
// this.$body[0].scrollHeight document.body.scrollHeight
// DTD ,document.documentElement.scrollHeight document.body.scrollHeight
// Math.max
return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
}
/**
* a ( targets ), ( offsets )
* @return {undefined}
*/
ScrollSpy.prototype.refresh = function () {
var that = this
var offsetMethod = 'offset'
var offsetBase = 0
this.offsets = []
this.targets = []
this.scrollHeight = this.getScrollHeight()
// body, position offsets
// jquery offset()
// position()
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
this.$body
//
.find(this.selector)
.map(function () {
var $el = $(this)
var href = $el.data('target') || $el.attr('href')
var $href = /^#./.test(href) && $(href)
// [offsets, ]
// jquery map ,return return[ ] 。return [[ ]]
return ($href
&& $href.length
&& $href.is(':visible')
&& [[$href[offsetMethod]().top + offsetBase, href]]) || null
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
that.offsets.push(this[0])
that.targets.push(this[1])
})
}
/**
* this.offsets scrollTop , activate
* @return {undefined}
*/
ScrollSpy.prototype.process = function () {
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset // offset ,
var scrollHeight = this.getScrollHeight() //
var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() // offset + -
var offsets = this.offsets
var targets = this.targets
var activeTarget = this.activeTarget // nav
var i
if (this.scrollHeight != scrollHeight) {
this.refresh()
}
// , nav
if (scrollTop >= maxScroll) {
return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
}
// offset,
if (activeTarget && scrollTop < offsets[0]) {
this.activeTarget = null
return this.clear()
}
// ,
for (i = offsets.length; i--;) {
activeTarget != targets[i] // target
&& scrollTop >= offsets[i] // offset
&& (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) // ,
&& this.activate(targets[i]) // nav
}
}
/**
* dom ( active )
* @param {object} target dom
* @return {undefined}
*/
ScrollSpy.prototype.activate = function (target) {
this.activeTarget = target //
this.clear() //
var selector = this.selector +
'[data-target="' + target + '"],' +
this.selector + '[href="' + target + '"]'
// a li active
var active = $(selector)
.parents('li')
.addClass('active')
if (active.parent('.dropdown-menu').length) {
active = active
.closest('li.dropdown')
.addClass('active')
}
//
active.trigger('activate.bs.scrollspy')
}
/**
* nav
* @return {[type]} [description]
*/
ScrollSpy.prototype.clear = function () {
$(this.selector)
.parentsUntil(this.options.target, '.active')
.removeClass('active')
}
締め括りをつける