1 /* ========================================================================
2 * Bootstrap: scrollspy.js v3.3.2
3 * http://getbootstrap.com/javascript/#scrollspy
4 * ========================================================================
5 * Copyright 2011-2015 Twitter, Inc.
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 * ======================================================================== */
13 // SCROLLSPY CLASS DEFINITION
14 // ==========================
16 function ScrollSpy(element, options) {
17 var process = $.proxy(this.process, this)
19 this.$body = $('body')
20 this.$scrollElement = $(element).is('body') ? $(window) : $(element)
21 this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
22 this.selector = (this.options.target || '') + ' .nav li > a'
25 this.activeTarget = null
28 this.$scrollElement.on('scroll.bs.scrollspy', process)
33 ScrollSpy.VERSION = '3.3.2'
35 ScrollSpy.DEFAULTS = {
39 ScrollSpy.prototype.getScrollHeight = function () {
40 return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
43 ScrollSpy.prototype.refresh = function () {
44 var offsetMethod = 'offset'
47 if (!$.isWindow(this.$scrollElement[0])) {
48 offsetMethod = 'position'
49 offsetBase = this.$scrollElement.scrollTop()
54 this.scrollHeight = this.getScrollHeight()
62 var href = $el.data('target') || $el.attr('href')
63 var $href = /^#./.test(href) && $(href)
67 && $href.is(':visible')
68 && [[$href[offsetMethod]().top + offsetBase, href]]) || null
70 .sort(function (a, b) { return a[0] - b[0] })
72 self.offsets.push(this[0])
73 self.targets.push(this[1])
77 ScrollSpy.prototype.process = function () {
78 var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
79 var scrollHeight = this.getScrollHeight()
80 var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
81 var offsets = this.offsets
82 var targets = this.targets
83 var activeTarget = this.activeTarget
86 if (this.scrollHeight != scrollHeight) {
90 if (scrollTop >= maxScroll) {
91 return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
94 if (activeTarget && scrollTop < offsets[0]) {
95 this.activeTarget = null
99 for (i = offsets.length; i--;) {
100 activeTarget != targets[i]
101 && scrollTop >= offsets[i]
102 && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
103 && this.activate(targets[i])
107 ScrollSpy.prototype.activate = function (target) {
108 this.activeTarget = target
112 var selector = this.selector +
113 '[data-target="' + target + '"],' +
114 this.selector + '[href="' + target + '"]'
116 var active = $(selector)
120 if (active.parent('.dropdown-menu').length) {
122 .closest('li.dropdown')
126 active.trigger('activate.bs.scrollspy')
129 ScrollSpy.prototype.clear = function () {
131 .parentsUntil(this.options.target, '.active')
132 .removeClass('active')
136 // SCROLLSPY PLUGIN DEFINITION
137 // ===========================
139 function Plugin(option) {
140 return this.each(function () {
142 var data = $this.data('bs.scrollspy')
143 var options = typeof option == 'object' && option
145 if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
146 if (typeof option == 'string') data[option]()
150 var old = $.fn.scrollspy
152 $.fn.scrollspy = Plugin
153 $.fn.scrollspy.Constructor = ScrollSpy
156 // SCROLLSPY NO CONFLICT
157 // =====================
159 $.fn.scrollspy.noConflict = function () {
165 // SCROLLSPY DATA-API
166 // ==================
168 $(window).on('load.bs.scrollspy.data-api', function () {
169 $('[data-spy="scroll"]').each(function () {
171 Plugin.call($spy, $spy.data())