scrollspy.js 11.4 KB
Newer Older
XhmikosR's avatar
Dist    
XhmikosR committed
1
/*!
XhmikosR's avatar
XhmikosR committed
2
  * Bootstrap scrollspy.js v4.3.1 (https://getbootstrap.com/)
Mark Otto's avatar
Mark Otto committed
3
  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
XhmikosR's avatar
Dist    
XhmikosR committed
4
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
Mark Otto's avatar
dist    
Mark Otto committed
6
7
8
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
Mark Otto's avatar
Mark Otto committed
9
10
  (global = global || self, global.ScrollSpy = factory(global.jQuery, global.Util));
}(this, function ($, Util) { 'use strict';
Mark Otto's avatar
dist    
Mark Otto committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;

  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);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _defineProperty(obj, key, value) {
    if (key in obj) {
      Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
      });
    } else {
      obj[key] = value;
    }

    return obj;
  }

  function _objectSpread(target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i] != null ? arguments[i] : {};
      var ownKeys = Object.keys(source);
Mark Otto's avatar
dist    
Mark Otto committed
50

Mark Otto's avatar
dist    
Mark Otto committed
51
52
53
54
55
      if (typeof Object.getOwnPropertySymbols === 'function') {
        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
        }));
      }
Mark Otto's avatar
dist    
Mark Otto committed
56

Mark Otto's avatar
dist    
Mark Otto committed
57
58
59
60
      ownKeys.forEach(function (key) {
        _defineProperty(target, key, source[key]);
      });
    }
Mark Otto's avatar
dist    
Mark Otto committed
61

Mark Otto's avatar
dist    
Mark Otto committed
62
63
    return target;
  }
fat's avatar
fat committed
64

XhmikosR's avatar
Dist    
XhmikosR committed
65
66
67
68
69
70
71
  /**
   * ------------------------------------------------------------------------
   * Constants
   * ------------------------------------------------------------------------
   */

  var NAME = 'scrollspy';
XhmikosR's avatar
XhmikosR committed
72
  var VERSION = '4.3.1';
XhmikosR's avatar
Dist    
XhmikosR committed
73
74
75
76
77
78
79
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
109
110
  var DATA_KEY = 'bs.scrollspy';
  var EVENT_KEY = "." + DATA_KEY;
  var DATA_API_KEY = '.data-api';
  var JQUERY_NO_CONFLICT = $.fn[NAME];
  var Default = {
    offset: 10,
    method: 'auto',
    target: ''
  };
  var DefaultType = {
    offset: 'number',
    method: 'string',
    target: '(string|element)'
  };
  var Event = {
    ACTIVATE: "activate" + EVENT_KEY,
    SCROLL: "scroll" + EVENT_KEY,
    LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
  };
  var ClassName = {
    DROPDOWN_ITEM: 'dropdown-item',
    DROPDOWN_MENU: 'dropdown-menu',
    ACTIVE: 'active'
  };
  var Selector = {
    DATA_SPY: '[data-spy="scroll"]',
    ACTIVE: '.active',
    NAV_LIST_GROUP: '.nav, .list-group',
    NAV_LINKS: '.nav-link',
    NAV_ITEMS: '.nav-item',
    LIST_ITEMS: '.list-group-item',
    DROPDOWN: '.dropdown',
    DROPDOWN_ITEMS: '.dropdown-item',
    DROPDOWN_TOGGLE: '.dropdown-toggle'
  };
  var OffsetMethod = {
    OFFSET: 'offset',
    POSITION: 'position'
Mark Otto's avatar
dist    
Mark Otto committed
111
112
    /**
     * ------------------------------------------------------------------------
XhmikosR's avatar
Dist    
XhmikosR committed
113
     * Class Definition
Mark Otto's avatar
dist    
Mark Otto committed
114
115
     * ------------------------------------------------------------------------
     */
fat's avatar
fat committed
116

XhmikosR's avatar
Dist    
XhmikosR committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  };

  var ScrollSpy =
  /*#__PURE__*/
  function () {
    function ScrollSpy(element, config) {
      var _this = this;

      this._element = element;
      this._scrollElement = element.tagName === 'BODY' ? window : element;
      this._config = this._getConfig(config);
      this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
      this._offsets = [];
      this._targets = [];
      this._activeTarget = null;
      this._scrollHeight = 0;
      $(this._scrollElement).on(Event.SCROLL, function (event) {
        return _this._process(event);
      });
      this.refresh();
Jacob Thornton's avatar
Jacob Thornton committed
137

XhmikosR's avatar
Dist    
XhmikosR committed
138
139
      this._process();
    } // Getters
fat's avatar
fat committed
140
141


XhmikosR's avatar
Dist    
XhmikosR committed
142
    var _proto = ScrollSpy.prototype;
fat's avatar
fat committed
143

XhmikosR's avatar
Dist    
XhmikosR committed
144
145
146
    // Public
    _proto.refresh = function refresh() {
      var _this2 = this;
Mark Otto's avatar
dist    
Mark Otto committed
147

XhmikosR's avatar
Dist    
XhmikosR committed
148
149
150
151
152
153
154
155
156
157
      var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION;
      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
      this._offsets = [];
      this._targets = [];
      this._scrollHeight = this._getScrollHeight();
      var targets = [].slice.call(document.querySelectorAll(this._selector));
      targets.map(function (element) {
        var target;
        var targetSelector = Util.getSelectorFromElement(element);
Mark Otto's avatar
dist    
Mark Otto committed
158

XhmikosR's avatar
Dist    
XhmikosR committed
159
160
161
        if (targetSelector) {
          target = document.querySelector(targetSelector);
        }
162

XhmikosR's avatar
Dist    
XhmikosR committed
163
164
        if (target) {
          var targetBCR = target.getBoundingClientRect();
fat's avatar
fat committed
165

XhmikosR's avatar
Dist    
XhmikosR committed
166
167
168
          if (targetBCR.width || targetBCR.height) {
            // TODO (fat): remove sketch reliance on jQuery position/offset
            return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
Mark Otto's avatar
dist    
Mark Otto committed
169
          }
XhmikosR's avatar
Dist    
XhmikosR committed
170
        }
fat's avatar
fat committed
171

XhmikosR's avatar
Dist    
XhmikosR committed
172
173
174
175
176
177
178
        return null;
      }).filter(function (item) {
        return item;
      }).sort(function (a, b) {
        return a[0] - b[0];
      }).forEach(function (item) {
        _this2._offsets.push(item[0]);
fat's avatar
fat committed
179

XhmikosR's avatar
Dist    
XhmikosR committed
180
181
182
        _this2._targets.push(item[1]);
      });
    };
Mark Otto's avatar
grunt    
Mark Otto committed
183

XhmikosR's avatar
Dist    
XhmikosR committed
184
185
186
187
188
189
190
191
192
193
194
    _proto.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;
Mark Otto's avatar
Mark Otto committed
195
196
    } // Private
    ;
XhmikosR's avatar
Dist    
XhmikosR committed
197
198
199
200
201
202
203
204
205
206

    _proto._getConfig = function _getConfig(config) {
      config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {});

      if (typeof config.target !== 'string') {
        var id = $(config.target).attr('id');

        if (!id) {
          id = Util.getUID(NAME);
          $(config.target).attr('id', id);
Mark Otto's avatar
dist    
Mark Otto committed
207
        }
matus's avatar
matus committed
208

XhmikosR's avatar
Dist    
XhmikosR committed
209
210
        config.target = "#" + id;
      }
Mark Otto's avatar
grunt    
Mark Otto committed
211

XhmikosR's avatar
Dist    
XhmikosR committed
212
213
214
      Util.typeCheckConfig(NAME, config, DefaultType);
      return config;
    };
fat's avatar
fat committed
215

XhmikosR's avatar
Dist    
XhmikosR committed
216
217
218
    _proto._getScrollTop = function _getScrollTop() {
      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
    };
fat's avatar
fat committed
219

XhmikosR's avatar
Dist    
XhmikosR committed
220
221
222
    _proto._getScrollHeight = function _getScrollHeight() {
      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
    };
fat's avatar
fat committed
223

XhmikosR's avatar
Dist    
XhmikosR committed
224
225
226
    _proto._getOffsetHeight = function _getOffsetHeight() {
      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
    };
fat's avatar
fat committed
227

XhmikosR's avatar
Dist    
XhmikosR committed
228
229
    _proto._process = function _process() {
      var scrollTop = this._getScrollTop() + this._config.offset;
fat's avatar
fat committed
230

XhmikosR's avatar
Dist    
XhmikosR committed
231
      var scrollHeight = this._getScrollHeight();
Mark Otto's avatar
dist    
Mark Otto committed
232

XhmikosR's avatar
Dist    
XhmikosR committed
233
      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
Mark Otto's avatar
dist    
Mark Otto committed
234

XhmikosR's avatar
Dist    
XhmikosR committed
235
236
237
      if (this._scrollHeight !== scrollHeight) {
        this.refresh();
      }
Mark Otto's avatar
dist    
Mark Otto committed
238

XhmikosR's avatar
Dist    
XhmikosR committed
239
240
      if (scrollTop >= maxScroll) {
        var target = this._targets[this._targets.length - 1];
fat's avatar
fat committed
241

XhmikosR's avatar
Dist    
XhmikosR committed
242
243
        if (this._activeTarget !== target) {
          this._activate(target);
Mark Otto's avatar
dist    
Mark Otto committed
244
        }
fat's avatar
fat committed
245

XhmikosR's avatar
Dist    
XhmikosR committed
246
247
        return;
      }
Mark Otto's avatar
dist    
Mark Otto committed
248

XhmikosR's avatar
Dist    
XhmikosR committed
249
250
      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
        this._activeTarget = null;
Mark Otto's avatar
dist    
Mark Otto committed
251

XhmikosR's avatar
Dist    
XhmikosR committed
252
        this._clear();
Mark Otto's avatar
dist    
Mark Otto committed
253

XhmikosR's avatar
Dist    
XhmikosR committed
254
255
        return;
      }
fat's avatar
fat committed
256

XhmikosR's avatar
Dist    
XhmikosR committed
257
      var offsetLength = this._offsets.length;
Mark Otto's avatar
dist    
Mark Otto committed
258

XhmikosR's avatar
Dist    
XhmikosR committed
259
260
      for (var i = offsetLength; i--;) {
        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
Mark Otto's avatar
dist    
Mark Otto committed
261

XhmikosR's avatar
Dist    
XhmikosR committed
262
263
264
265
266
        if (isActiveTarget) {
          this._activate(this._targets[i]);
        }
      }
    };
Mark Otto's avatar
dist    
Mark Otto committed
267

XhmikosR's avatar
Dist    
XhmikosR committed
268
269
    _proto._activate = function _activate(target) {
      this._activeTarget = target;
Mark Otto's avatar
dist    
Mark Otto committed
270

XhmikosR's avatar
Dist    
XhmikosR committed
271
      this._clear();
Mark Otto's avatar
dist    
Mark Otto committed
272

XhmikosR's avatar
Dist    
XhmikosR committed
273
274
      var queries = this._selector.split(',').map(function (selector) {
        return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]";
XhmikosR's avatar
Dist    
XhmikosR committed
275
      });
XhmikosR's avatar
Dist    
XhmikosR committed
276

XhmikosR's avatar
Dist    
XhmikosR committed
277
      var $link = $([].slice.call(document.querySelectorAll(queries.join(','))));
Mark Otto's avatar
dist    
Mark Otto committed
278

XhmikosR's avatar
Dist    
XhmikosR committed
279
280
281
282
283
284
285
      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
        $link.addClass(ClassName.ACTIVE);
      } else {
        // Set triggered link as active
        $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
Mark Otto's avatar
dist    
Mark Otto committed
286

XhmikosR's avatar
Dist    
XhmikosR committed
287
        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item
fat's avatar
fat committed
288

XhmikosR's avatar
Dist    
XhmikosR committed
289
290
        $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
      }
Mark Otto's avatar
grunt    
Mark Otto committed
291

XhmikosR's avatar
Dist    
XhmikosR committed
292
293
294
295
      $(this._scrollElement).trigger(Event.ACTIVATE, {
        relatedTarget: target
      });
    };
Mark Otto's avatar
grunt    
Mark Otto committed
296

XhmikosR's avatar
Dist    
XhmikosR committed
297
    _proto._clear = function _clear() {
XhmikosR's avatar
Dist    
XhmikosR committed
298
299
300
301
302
      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {
        return node.classList.contains(ClassName.ACTIVE);
      }).forEach(function (node) {
        return node.classList.remove(ClassName.ACTIVE);
      });
Mark Otto's avatar
Mark Otto committed
303
304
    } // Static
    ;
Mark Otto's avatar
dist    
Mark Otto committed
305

XhmikosR's avatar
Dist    
XhmikosR committed
306
307
308
    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
      return this.each(function () {
        var data = $(this).data(DATA_KEY);
Mark Otto's avatar
dist    
Mark Otto committed
309

XhmikosR's avatar
Dist    
XhmikosR committed
310
        var _config = typeof config === 'object' && config;
Mark Otto's avatar
dist    
Mark Otto committed
311

XhmikosR's avatar
Dist    
XhmikosR committed
312
313
314
315
        if (!data) {
          data = new ScrollSpy(this, _config);
          $(this).data(DATA_KEY, data);
        }
Mark Otto's avatar
dist    
Mark Otto committed
316

XhmikosR's avatar
Dist    
XhmikosR committed
317
318
319
        if (typeof config === 'string') {
          if (typeof data[config] === 'undefined') {
            throw new TypeError("No method named \"" + config + "\"");
Mark Otto's avatar
dist    
Mark Otto committed
320
          }
Mark Otto's avatar
dist    
Mark Otto committed
321

XhmikosR's avatar
Dist    
XhmikosR committed
322
          data[config]();
Mark Otto's avatar
dist    
Mark Otto committed
323
        }
XhmikosR's avatar
Dist    
XhmikosR committed
324
325
      });
    };
Mark Otto's avatar
dist    
Mark Otto committed
326

XhmikosR's avatar
Dist    
XhmikosR committed
327
328
329
330
331
332
333
334
335
336
337
    _createClass(ScrollSpy, null, [{
      key: "VERSION",
      get: function get() {
        return VERSION;
      }
    }, {
      key: "Default",
      get: function get() {
        return Default;
      }
    }]);
fat's avatar
fat committed
338

XhmikosR's avatar
Dist    
XhmikosR committed
339
340
341
342
343
344
345
    return ScrollSpy;
  }();
  /**
   * ------------------------------------------------------------------------
   * Data Api implementation
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
346

Mark Otto's avatar
dist    
Mark Otto committed
347

XhmikosR's avatar
Dist    
XhmikosR committed
348
349
350
  $(window).on(Event.LOAD_DATA_API, function () {
    var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY));
    var scrollSpysLength = scrollSpys.length;
fat's avatar
fat committed
351

XhmikosR's avatar
Dist    
XhmikosR committed
352
353
    for (var i = scrollSpysLength; i--;) {
      var $spy = $(scrollSpys[i]);
Mark Otto's avatar
dist    
Mark Otto committed
354

XhmikosR's avatar
Dist    
XhmikosR committed
355
356
357
358
359
360
361
362
      ScrollSpy._jQueryInterface.call($spy, $spy.data());
    }
  });
  /**
   * ------------------------------------------------------------------------
   * jQuery
   * ------------------------------------------------------------------------
   */
fat's avatar
fat committed
363

XhmikosR's avatar
Dist    
XhmikosR committed
364
365
  $.fn[NAME] = ScrollSpy._jQueryInterface;
  $.fn[NAME].Constructor = ScrollSpy;
Mark Otto's avatar
dist    
Mark Otto committed
366

XhmikosR's avatar
Dist    
XhmikosR committed
367
368
369
370
  $.fn[NAME].noConflict = function () {
    $.fn[NAME] = JQUERY_NO_CONFLICT;
    return ScrollSpy._jQueryInterface;
  };
fat's avatar
fat committed
371
372

  return ScrollSpy;
Mark Otto's avatar
dist    
Mark Otto committed
373

Mark Otto's avatar
Mark Otto committed
374
}));
Mark Otto's avatar
dist    
Mark Otto committed
375
//# sourceMappingURL=scrollspy.js.map