scrollspy.js 4.95 KB
Newer Older
1
/* ========================================================================
Mark Otto's avatar
Mark Otto committed
2
 * Bootstrap: scrollspy.js v3.1.1
3
 * http://getbootstrap.com/javascript/#scrollspy
4
 * ========================================================================
5
 * Copyright 2011-2014 Twitter, Inc.
6
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
 * ======================================================================== */
Jacob Thornton's avatar
Jacob Thornton committed
8

9

10
+function () { 'use strict';
fat's avatar
fat committed
11

12
13
14
15
  (function (o_o) {
    typeof define  == 'function' && define.amd ? define(['jquery'], o_o) :
    typeof exports == 'object' ? o_o(require('jquery')) : o_o(jQuery)
  })(function ($) {
16

17
18
    // SCROLLSPY CLASS DEFINITION
    // ==========================
XhmikosR's avatar
XhmikosR committed
19

20
21
    function ScrollSpy(element, options) {
      var process  = $.proxy(this.process, this)
fat's avatar
fat committed
22

23
24
25
26
27
28
29
30
31
32
      this.$body          = $('body')
      this.$scrollElement = $(element).is('body') ? $(window) : $(element)
      this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
      this.selector       = (this.options.target || '') + ' .nav li > a'
      this.offsets        = []
      this.targets        = []
      this.activeTarget   = null
      this.scrollHeight   = 0

      this.$scrollElement.on('scroll.bs.scrollspy', process)
33
      this.refresh()
34
      this.process()
35
36
    }

37
38
39
40
    ScrollSpy.VERSION  = '3.1.1'

    ScrollSpy.DEFAULTS = {
      offset: 10
fat's avatar
fat committed
41
42
    }

43
44
    ScrollSpy.prototype.getScrollHeight = function () {
      return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
45
46
    }

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    ScrollSpy.prototype.refresh = function () {
      var offsetMethod = 'offset'
      var offsetBase   = 0

      if (!$.isWindow(this.$scrollElement[0])) {
        offsetMethod = 'position'
        offsetBase   = this.$scrollElement.scrollTop()
      }

      this.offsets = []
      this.targets = []
      this.scrollHeight = this.getScrollHeight()

      var self     = this

      this.$body
        .find(this.selector)
        .map(function () {
          var $el   = $(this)
          var href  = $el.data('target') || $el.attr('href')
          var $href = /^#./.test(href) && $(href)

          return ($href
            && $href.length
            && $href.is(':visible')
            && [[$href[offsetMethod]().top + offsetBase, href]]) || null
        })
        .sort(function (a, b) { return a[0] - b[0] })
        .each(function () {
          self.offsets.push(this[0])
          self.targets.push(this[1])
        })
fat's avatar
fat committed
79
    }
Jacob Thornton's avatar
Jacob Thornton committed
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    ScrollSpy.prototype.process = function () {
      var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
      var scrollHeight = this.getScrollHeight()
      var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
      var offsets      = this.offsets
      var targets      = this.targets
      var activeTarget = this.activeTarget
      var i

      if (this.scrollHeight != scrollHeight) {
        this.refresh()
      }

      if (scrollTop >= maxScroll) {
        return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
      }

      if (activeTarget && scrollTop <= offsets[0]) {
        return activeTarget != (i = targets[0]) && this.activate(i)
      }

      for (i = offsets.length; i--;) {
        activeTarget != targets[i]
          && scrollTop >= offsets[i]
          && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
          && this.activate(targets[i])
      }
    }
fat's avatar
fat committed
109

110
111
    ScrollSpy.prototype.activate = function (target) {
      this.activeTarget = target
fat's avatar
fat committed
112

113
114
115
      $(this.selector)
        .parentsUntil(this.options.target, '.active')
        .removeClass('active')
116

117
118
119
      var selector = this.selector +
          '[data-target="' + target + '"],' +
          this.selector + '[href="' + target + '"]'
fat's avatar
fat committed
120

121
122
      var active = $(selector)
        .parents('li')
fat's avatar
fat committed
123
124
        .addClass('active')

125
126
127
128
129
      if (active.parent('.dropdown-menu').length) {
        active = active
          .closest('li.dropdown')
          .addClass('active')
      }
fat's avatar
fat committed
130

131
132
      active.trigger('activate.bs.scrollspy')
    }
fat's avatar
fat committed
133

134

135
136
    // SCROLLSPY PLUGIN DEFINITION
    // ===========================
fat's avatar
fat committed
137

138
139
140
141
142
    function Plugin(option) {
      return this.each(function () {
        var $this   = $(this)
        var data    = $this.data('bs.scrollspy')
        var options = typeof option == 'object' && option
143

144
145
146
147
        if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
        if (typeof option == 'string') data[option]()
      })
    }
148

149
    var old = $.fn.scrollspy
150

151
152
    $.fn.scrollspy             = Plugin
    $.fn.scrollspy.Constructor = ScrollSpy
153

154

155
156
    // SCROLLSPY NO CONFLICT
    // =====================
157

158
159
160
161
    $.fn.scrollspy.noConflict = function () {
      $.fn.scrollspy = old
      return this
    }
162

163

164
165
166
167
168
169
170
171
    // SCROLLSPY DATA-API
    // ==================

    $(window).on('load.bs.scrollspy.data-api', function () {
      $('[data-spy="scroll"]').each(function () {
        var $spy = $(this)
        Plugin.call($spy, $spy.data())
      })
172
    })
173

174
  })
175

176
}();