scrollspy.js 9.51 KB
Newer Older
Mark Otto's avatar
grunt    
Mark Otto committed
1
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
fat's avatar
fat committed
2

Mark Otto's avatar
grunt    
Mark Otto committed
3
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
fat's avatar
fat committed
4

Mark Otto's avatar
grunt    
Mark Otto committed
5
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
fat's avatar
fat committed
6
7
8

/**
 * --------------------------------------------------------------------------
Mark Otto's avatar
Mark Otto committed
9
 * Bootstrap (v4.0.0-alpha.5): scrollspy.js
fat's avatar
fat committed
10
11
12
13
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

Mark Otto's avatar
grunt    
Mark Otto committed
14
var ScrollSpy = function ($) {
fat's avatar
fat committed
15
16
17
18
19
20
21
22

  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */

  var NAME = 'scrollspy';
Mark Otto's avatar
Mark Otto committed
23
  var VERSION = '4.0.0-alpha.5';
fat's avatar
fat committed
24
  var DATA_KEY = 'bs.scrollspy';
fat's avatar
fat committed
25
26
  var EVENT_KEY = '.' + DATA_KEY;
  var DATA_API_KEY = '.data-api';
fat's avatar
fat committed
27
28
  var JQUERY_NO_CONFLICT = $.fn[NAME];

29
  var Default = {
30
    offset: 10,
fat's avatar
fat committed
31
32
    method: 'auto',
    target: ''
fat's avatar
fat committed
33
34
  };

fat's avatar
fat committed
35
36
37
38
39
40
  var DefaultType = {
    offset: 'number',
    method: 'string',
    target: '(string|element)'
  };

fat's avatar
fat committed
41
  var Event = {
fat's avatar
fat committed
42
43
    ACTIVATE: 'activate' + EVENT_KEY,
    SCROLL: 'scroll' + EVENT_KEY,
Jacob Thornton's avatar
Jacob Thornton committed
44
    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
fat's avatar
fat committed
45
46
47
  };

  var ClassName = {
Jacob Thornton's avatar
Jacob Thornton committed
48
    DROPDOWN_ITEM: 'dropdown-item',
fat's avatar
fat committed
49
    DROPDOWN_MENU: 'dropdown-menu',
50
51
    NAV_LINK: 'nav-link',
    NAV: 'nav',
fat's avatar
fat committed
52
53
54
55
56
57
    ACTIVE: 'active'
  };

  var Selector = {
    DATA_SPY: '[data-spy="scroll"]',
    ACTIVE: '.active',
58
    LIST_ITEM: '.list-item',
fat's avatar
fat committed
59
    LI: 'li',
fat's avatar
fat committed
60
    LI_DROPDOWN: 'li.dropdown',
Jacob Thornton's avatar
Jacob Thornton committed
61
    NAV_LINKS: '.nav-link',
62
63
64
    DROPDOWN: '.dropdown',
    DROPDOWN_ITEMS: '.dropdown-item',
    DROPDOWN_TOGGLE: '.dropdown-toggle'
fat's avatar
fat committed
65
66
  };

67
68
69
70
71
  var OffsetMethod = {
    OFFSET: 'offset',
    POSITION: 'position'
  };

fat's avatar
fat committed
72
73
74
75
76
77
  /**
   * ------------------------------------------------------------------------
   * Class Definition
   * ------------------------------------------------------------------------
   */

Mark Otto's avatar
grunt    
Mark Otto committed
78
  var ScrollSpy = function () {
fat's avatar
fat committed
79
80
81
    function ScrollSpy(element, config) {
      _classCallCheck(this, ScrollSpy);

fat's avatar
fat committed
82
      this._element = element;
fat's avatar
fat committed
83
      this._scrollElement = element.tagName === 'BODY' ? window : element;
fat's avatar
fat committed
84
      this._config = this._getConfig(config);
Jacob Thornton's avatar
Jacob Thornton committed
85
      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
fat's avatar
fat committed
86
87
88
89
90
      this._offsets = [];
      this._targets = [];
      this._activeTarget = null;
      this._scrollHeight = 0;

91
      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
fat's avatar
fat committed
92
93
94
95
96

      this.refresh();
      this._process();
    }

Jacob Thornton's avatar
Jacob Thornton committed
97
98
    // getters

Mark Otto's avatar
grunt    
Mark Otto committed
99
    // public
fat's avatar
fat committed
100

Mark Otto's avatar
grunt    
Mark Otto committed
101
102
    ScrollSpy.prototype.refresh = function refresh() {
      var _this = this;
fat's avatar
fat committed
103

Mark Otto's avatar
grunt    
Mark Otto committed
104
      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
fat's avatar
fat committed
105

Mark Otto's avatar
grunt    
Mark Otto committed
106
      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
107

Mark Otto's avatar
grunt    
Mark Otto committed
108
      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
fat's avatar
fat committed
109

Mark Otto's avatar
grunt    
Mark Otto committed
110
111
      this._offsets = [];
      this._targets = [];
fat's avatar
fat committed
112

Mark Otto's avatar
grunt    
Mark Otto committed
113
      this._scrollHeight = this._getScrollHeight();
fat's avatar
fat committed
114

Mark Otto's avatar
grunt    
Mark Otto committed
115
      var targets = $.makeArray($(this._selector));
fat's avatar
fat committed
116

Mark Otto's avatar
grunt    
Mark Otto committed
117
118
119
      targets.map(function (element) {
        var target = void 0;
        var targetSelector = Util.getSelectorFromElement(element);
fat's avatar
fat committed
120

Mark Otto's avatar
grunt    
Mark Otto committed
121
122
123
        if (targetSelector) {
          target = $(targetSelector)[0];
        }
fat's avatar
fat committed
124

Mark Otto's avatar
grunt    
Mark Otto committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
        if (target && (target.offsetWidth || target.offsetHeight)) {
          // todo (fat): remove sketch reliance on jQuery position/offset
          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
        }
        return null;
      }).filter(function (item) {
        return item;
      }).sort(function (a, b) {
        return a[0] - b[0];
      }).forEach(function (item) {
        _this._offsets.push(item[0]);
        _this._targets.push(item[1]);
      });
    };

    ScrollSpy.prototype.dispose = function dispose() {
      $.removeData(this._element, DATA_KEY);
      $(this._scrollElement).off(EVENT_KEY);

      this._element = null;
      this._scrollElement = null;
      this._config = null;
      this._selector = null;
      this._offsets = null;
      this._targets = null;
      this._activeTarget = null;
      this._scrollHeight = null;
    };
fat's avatar
fat committed
153

Mark Otto's avatar
grunt    
Mark Otto committed
154
    // private
fat's avatar
fat committed
155

Mark Otto's avatar
grunt    
Mark Otto committed
156
157
    ScrollSpy.prototype._getConfig = function _getConfig(config) {
      config = $.extend({}, Default, config);
fat's avatar
fat committed
158

Mark Otto's avatar
grunt    
Mark Otto committed
159
160
161
162
163
      if (typeof config.target !== 'string') {
        var id = $(config.target).attr('id');
        if (!id) {
          id = Util.getUID(NAME);
          $(config.target).attr('id', id);
fat's avatar
fat committed
164
        }
Mark Otto's avatar
grunt    
Mark Otto committed
165
166
        config.target = '#' + id;
      }
fat's avatar
fat committed
167

Mark Otto's avatar
grunt    
Mark Otto committed
168
      Util.typeCheckConfig(NAME, config, DefaultType);
fat's avatar
fat committed
169

Mark Otto's avatar
grunt    
Mark Otto committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
      return config;
    };

    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
    };

    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
    };

    ScrollSpy.prototype._process = function _process() {
      var scrollTop = this._getScrollTop() + this._config.offset;
      var scrollHeight = this._getScrollHeight();
      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;

      if (this._scrollHeight !== scrollHeight) {
        this.refresh();
fat's avatar
fat committed
188
189
      }

Mark Otto's avatar
grunt    
Mark Otto committed
190
191
      if (scrollTop >= maxScroll) {
        var target = this._targets[this._targets.length - 1];
fat's avatar
fat committed
192

Mark Otto's avatar
grunt    
Mark Otto committed
193
194
        if (this._activeTarget !== target) {
          this._activate(target);
fat's avatar
fat committed
195
        }
Mark Otto's avatar
grunt    
Mark Otto committed
196
      }
fat's avatar
fat committed
197

Mark Otto's avatar
grunt    
Mark Otto committed
198
199
200
201
202
      if (this._activeTarget && scrollTop < this._offsets[0]) {
        this._activeTarget = null;
        this._clear();
        return;
      }
fat's avatar
fat committed
203

Mark Otto's avatar
grunt    
Mark Otto committed
204
205
      for (var i = this._offsets.length; i--;) {
        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
fat's avatar
fat committed
206

Mark Otto's avatar
grunt    
Mark Otto committed
207
208
        if (isActiveTarget) {
          this._activate(this._targets[i]);
fat's avatar
fat committed
209
210
        }
      }
Mark Otto's avatar
grunt    
Mark Otto committed
211
    };
fat's avatar
fat committed
212

Mark Otto's avatar
grunt    
Mark Otto committed
213
214
    ScrollSpy.prototype._activate = function _activate(target) {
      this._activeTarget = target;
fat's avatar
fat committed
215

Mark Otto's avatar
grunt    
Mark Otto committed
216
      this._clear();
fat's avatar
fat committed
217

Mark Otto's avatar
grunt    
Mark Otto committed
218
219
220
221
      var queries = this._selector.split(',');
      queries = queries.map(function (selector) {
        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
      });
fat's avatar
fat committed
222

Mark Otto's avatar
grunt    
Mark Otto committed
223
      var $link = $(queries.join(','));
fat's avatar
fat committed
224

Mark Otto's avatar
grunt    
Mark Otto committed
225
226
227
228
229
230
231
      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
        $link.addClass(ClassName.ACTIVE);
      } else {
        // todo (fat) this is kinda sus...
        // recursively add actives to tested nav-links
        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
fat's avatar
fat committed
232
233
      }

Mark Otto's avatar
grunt    
Mark Otto committed
234
235
236
237
      $(this._scrollElement).trigger(Event.ACTIVATE, {
        relatedTarget: target
      });
    };
fat's avatar
fat committed
238

Mark Otto's avatar
grunt    
Mark Otto committed
239
240
241
    ScrollSpy.prototype._clear = function _clear() {
      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
    };
fat's avatar
fat committed
242

Mark Otto's avatar
grunt    
Mark Otto committed
243
    // static
fat's avatar
fat committed
244

Mark Otto's avatar
grunt    
Mark Otto committed
245
246
247
248
249
250
251
252
253
254
255
256
257
    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
      return this.each(function () {
        var data = $(this).data(DATA_KEY);
        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;

        if (!data) {
          data = new ScrollSpy(this, _config);
          $(this).data(DATA_KEY, data);
        }

        if (typeof config === 'string') {
          if (data[config] === undefined) {
            throw new Error('No method named "' + config + '"');
fat's avatar
fat committed
258
          }
Mark Otto's avatar
grunt    
Mark Otto committed
259
260
261
262
263
264
          data[config]();
        }
      });
    };

    _createClass(ScrollSpy, null, [{
Jacob Thornton's avatar
Jacob Thornton committed
265
266
267
268
269
270
271
272
273
      key: 'VERSION',
      get: function get() {
        return VERSION;
      }
    }, {
      key: 'Default',
      get: function get() {
        return Default;
      }
fat's avatar
fat committed
274
275
276
    }]);

    return ScrollSpy;
Mark Otto's avatar
grunt    
Mark Otto committed
277
278
279
280
281
282
283
  }();

  /**
   * ------------------------------------------------------------------------
   * Data Api implementation
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
284

fat's avatar
fat committed
285
  $(window).on(Event.LOAD_DATA_API, function () {
fat's avatar
fat committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
    var scrollSpys = $.makeArray($(Selector.DATA_SPY));

    for (var i = scrollSpys.length; i--;) {
      var $spy = $(scrollSpys[i]);
      ScrollSpy._jQueryInterface.call($spy, $spy.data());
    }
  });

  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
   */

  $.fn[NAME] = ScrollSpy._jQueryInterface;
  $.fn[NAME].Constructor = ScrollSpy;
  $.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return ScrollSpy._jQueryInterface;
  };

  return ScrollSpy;
Mark Otto's avatar
grunt    
Mark Otto committed
308
}(jQuery);
Jacob Thornton's avatar
Jacob Thornton committed
309
//# sourceMappingURL=scrollspy.js.map