scrollspy.js 4.46 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

Katie Zhu's avatar
Katie Zhu committed
10
11
12
13
14
(function (o_o) {
  typeof define  === 'function' && define.amd ? define(['jquery'], o_o) :
  typeof exports === 'object' ? o_o(require('jquery')) : o_o(this.jQuery)
})(function ($) {

Zlatan Vasović's avatar
Zlatan Vasović committed
15
  'use strict';
16

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

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

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

31
    this.$scrollElement.on('scroll.bs.scrollspy', process)
32
    this.refresh()
33
    this.process()
Jacob Thornton's avatar
Jacob Thornton committed
34
35
  }

fat's avatar
fat committed
36
37
  ScrollSpy.VERSION  = '3.1.1'

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

  ScrollSpy.prototype.refresh = function () {
43
44
45
46
47
48
49
    var offsetMethod = 'offset'
    var offsetBase   = 0

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

51
52
53
    this.offsets = []
    this.targets = []

fat's avatar
fat committed
54
    var self     = this
XhmikosR's avatar
XhmikosR committed
55
56

    this.$body
fat's avatar
fat committed
57
58
59
60
      .find(this.selector)
      .map(function () {
        var $el   = $(this)
        var href  = $el.data('target') || $el.attr('href')
61
        var $href = /^#./.test(href) && $(href)
fat's avatar
fat committed
62
63
64

        return ($href
          && $href.length
65
          && $href.is(':visible')
66
          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
fat's avatar
fat committed
67
68
69
70
71
72
73
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        self.offsets.push(this[0])
        self.targets.push(this[1])
      })
  }
Jacob Thornton's avatar
Jacob Thornton committed
74

fat's avatar
fat committed
75
76
  ScrollSpy.prototype.process = function () {
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
77
    var scrollHeight = this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
78
    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
fat's avatar
fat committed
79
80
81
82
83
84
    var offsets      = this.offsets
    var targets      = this.targets
    var activeTarget = this.activeTarget
    var i

    if (scrollTop >= maxScroll) {
85
      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
fat's avatar
fat committed
86
87
    }

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

fat's avatar
fat committed
92
93
94
95
    for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
XhmikosR's avatar
XhmikosR committed
96
        && this.activate(targets[i])
fat's avatar
fat committed
97
    }
Jacob Thornton's avatar
Jacob Thornton committed
98
99
  }

fat's avatar
fat committed
100
101
102
103
  ScrollSpy.prototype.activate = function (target) {
    this.activeTarget = target

    $(this.selector)
fat's avatar
fat committed
104
      .parentsUntil(this.options.target, '.active')
fat's avatar
fat committed
105
106
      .removeClass('active')

Zlatan Vasović's avatar
Zlatan Vasović committed
107
108
109
    var selector = this.selector +
        '[data-target="' + target + '"],' +
        this.selector + '[href="' + target + '"]'
110

fat's avatar
fat committed
111
112
113
114
    var active = $(selector)
      .parents('li')
      .addClass('active')

Zlatan Vasović's avatar
Zlatan Vasović committed
115
    if (active.parent('.dropdown-menu').length) {
fat's avatar
fat committed
116
117
118
119
120
      active = active
        .closest('li.dropdown')
        .addClass('active')
    }

121
    active.trigger('activate.bs.scrollspy')
fat's avatar
fat committed
122
123
124
125
126
  }


  // SCROLLSPY PLUGIN DEFINITION
  // ===========================
127

128
  function Plugin(option) {
129
    return this.each(function () {
fat's avatar
fat committed
130
      var $this   = $(this)
131
      var data    = $this.data('bs.scrollspy')
fat's avatar
fat committed
132
133
      var options = typeof option == 'object' && option

134
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
135
136
137
138
      if (typeof option == 'string') data[option]()
    })
  }

139
140
141
  var old = $.fn.scrollspy

  $.fn.scrollspy             = Plugin
142
  $.fn.scrollspy.Constructor = ScrollSpy
143
144


fat's avatar
fat committed
145
146
  // SCROLLSPY NO CONFLICT
  // =====================
147
148
149
150
151
152
153

  $.fn.scrollspy.noConflict = function () {
    $.fn.scrollspy = old
    return this
  }


fat's avatar
fat committed
154
155
  // SCROLLSPY DATA-API
  // ==================
156

157
  $(window).on('load.bs.scrollspy.data-api', function () {
158
159
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
160
      Plugin.call($spy, $spy.data())
161
    })
162
  })
163

Katie Zhu's avatar
Katie Zhu committed
164
});