Issues (141)

resources/bootstrap/js/scrollspy.js (1 issue)

1
/*!
2
  * Bootstrap scrollspy.js v4.6.2 (https://getbootstrap.com/)
3
  * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
(function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
8
  typeof define === 'function' && define.amd ? define(['jquery', './util'], factory) :
9
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ScrollSpy = factory(global.jQuery, global.Util));
10
})(this, (function ($, Util) { 'use strict';
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
15
  var Util__default = /*#__PURE__*/_interopDefaultLegacy(Util);
16
17
  function _defineProperties(target, props) {
18
    for (var i = 0; i < props.length; i++) {
19
      var descriptor = props[i];
20
      descriptor.enumerable = descriptor.enumerable || false;
21
      descriptor.configurable = true;
22
      if ("value" in descriptor) descriptor.writable = true;
23
      Object.defineProperty(target, descriptor.key, descriptor);
24
    }
25
  }
26
27
  function _createClass(Constructor, protoProps, staticProps) {
28
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
29
    if (staticProps) _defineProperties(Constructor, staticProps);
30
    Object.defineProperty(Constructor, "prototype", {
31
      writable: false
32
    });
33
    return Constructor;
34
  }
35
36
  function _extends() {
37
    _extends = Object.assign ? Object.assign.bind() : function (target) {
38
      for (var i = 1; i < arguments.length; i++) {
39
        var source = arguments[i];
40
41
        for (var key in source) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
42
          if (Object.prototype.hasOwnProperty.call(source, key)) {
43
            target[key] = source[key];
44
          }
45
        }
46
      }
47
48
      return target;
49
    };
50
    return _extends.apply(this, arguments);
51
  }
52
53
  /**
54
   * Constants
55
   */
56
57
  var NAME = 'scrollspy';
58
  var VERSION = '4.6.2';
59
  var DATA_KEY = 'bs.scrollspy';
60
  var EVENT_KEY = "." + DATA_KEY;
61
  var DATA_API_KEY = '.data-api';
62
  var JQUERY_NO_CONFLICT = $__default["default"].fn[NAME];
63
  var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
64
  var CLASS_NAME_ACTIVE = 'active';
65
  var EVENT_ACTIVATE = "activate" + EVENT_KEY;
66
  var EVENT_SCROLL = "scroll" + EVENT_KEY;
67
  var EVENT_LOAD_DATA_API = "load" + EVENT_KEY + DATA_API_KEY;
68
  var METHOD_OFFSET = 'offset';
69
  var METHOD_POSITION = 'position';
70
  var SELECTOR_DATA_SPY = '[data-spy="scroll"]';
71
  var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
72
  var SELECTOR_NAV_LINKS = '.nav-link';
73
  var SELECTOR_NAV_ITEMS = '.nav-item';
74
  var SELECTOR_LIST_ITEMS = '.list-group-item';
75
  var SELECTOR_DROPDOWN = '.dropdown';
76
  var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item';
77
  var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
78
  var Default = {
79
    offset: 10,
80
    method: 'auto',
81
    target: ''
82
  };
83
  var DefaultType = {
84
    offset: 'number',
85
    method: 'string',
86
    target: '(string|element)'
87
  };
88
  /**
89
   * Class definition
90
   */
91
92
  var ScrollSpy = /*#__PURE__*/function () {
93
    function ScrollSpy(element, config) {
94
      var _this = this;
95
96
      this._element = element;
97
      this._scrollElement = element.tagName === 'BODY' ? window : element;
98
      this._config = this._getConfig(config);
99
      this._selector = this._config.target + " " + SELECTOR_NAV_LINKS + "," + (this._config.target + " " + SELECTOR_LIST_ITEMS + ",") + (this._config.target + " " + SELECTOR_DROPDOWN_ITEMS);
100
      this._offsets = [];
101
      this._targets = [];
102
      this._activeTarget = null;
103
      this._scrollHeight = 0;
104
      $__default["default"](this._scrollElement).on(EVENT_SCROLL, function (event) {
105
        return _this._process(event);
106
      });
107
      this.refresh();
108
109
      this._process();
110
    } // Getters
111
112
113
    var _proto = ScrollSpy.prototype;
114
115
    // Public
116
    _proto.refresh = function refresh() {
117
      var _this2 = this;
118
119
      var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;
120
      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
121
      var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;
122
      this._offsets = [];
123
      this._targets = [];
124
      this._scrollHeight = this._getScrollHeight();
125
      var targets = [].slice.call(document.querySelectorAll(this._selector));
126
      targets.map(function (element) {
127
        var target;
128
        var targetSelector = Util__default["default"].getSelectorFromElement(element);
129
130
        if (targetSelector) {
131
          target = document.querySelector(targetSelector);
132
        }
133
134
        if (target) {
135
          var targetBCR = target.getBoundingClientRect();
136
137
          if (targetBCR.width || targetBCR.height) {
138
            // TODO (fat): remove sketch reliance on jQuery position/offset
139
            return [$__default["default"](target)[offsetMethod]().top + offsetBase, targetSelector];
140
          }
141
        }
142
143
        return null;
144
      }).filter(Boolean).sort(function (a, b) {
145
        return a[0] - b[0];
146
      }).forEach(function (item) {
147
        _this2._offsets.push(item[0]);
148
149
        _this2._targets.push(item[1]);
150
      });
151
    };
152
153
    _proto.dispose = function dispose() {
154
      $__default["default"].removeData(this._element, DATA_KEY);
155
      $__default["default"](this._scrollElement).off(EVENT_KEY);
156
      this._element = null;
157
      this._scrollElement = null;
158
      this._config = null;
159
      this._selector = null;
160
      this._offsets = null;
161
      this._targets = null;
162
      this._activeTarget = null;
163
      this._scrollHeight = null;
164
    } // Private
165
    ;
166
167
    _proto._getConfig = function _getConfig(config) {
168
      config = _extends({}, Default, typeof config === 'object' && config ? config : {});
169
170
      if (typeof config.target !== 'string' && Util__default["default"].isElement(config.target)) {
171
        var id = $__default["default"](config.target).attr('id');
172
173
        if (!id) {
174
          id = Util__default["default"].getUID(NAME);
175
          $__default["default"](config.target).attr('id', id);
176
        }
177
178
        config.target = "#" + id;
179
      }
180
181
      Util__default["default"].typeCheckConfig(NAME, config, DefaultType);
182
      return config;
183
    };
184
185
    _proto._getScrollTop = function _getScrollTop() {
186
      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
187
    };
188
189
    _proto._getScrollHeight = function _getScrollHeight() {
190
      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
191
    };
192
193
    _proto._getOffsetHeight = function _getOffsetHeight() {
194
      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
195
    };
196
197
    _proto._process = function _process() {
198
      var scrollTop = this._getScrollTop() + this._config.offset;
199
200
      var scrollHeight = this._getScrollHeight();
201
202
      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
203
204
      if (this._scrollHeight !== scrollHeight) {
205
        this.refresh();
206
      }
207
208
      if (scrollTop >= maxScroll) {
209
        var target = this._targets[this._targets.length - 1];
210
211
        if (this._activeTarget !== target) {
212
          this._activate(target);
213
        }
214
215
        return;
216
      }
217
218
      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
219
        this._activeTarget = null;
220
221
        this._clear();
222
223
        return;
224
      }
225
226
      for (var i = this._offsets.length; i--;) {
227
        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
228
229
        if (isActiveTarget) {
230
          this._activate(this._targets[i]);
231
        }
232
      }
233
    };
234
235
    _proto._activate = function _activate(target) {
236
      this._activeTarget = target;
237
238
      this._clear();
239
240
      var queries = this._selector.split(',').map(function (selector) {
241
        return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]";
242
      });
243
244
      var $link = $__default["default"]([].slice.call(document.querySelectorAll(queries.join(','))));
245
246
      if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {
247
        $link.closest(SELECTOR_DROPDOWN).find(SELECTOR_DROPDOWN_TOGGLE).addClass(CLASS_NAME_ACTIVE);
248
        $link.addClass(CLASS_NAME_ACTIVE);
249
      } else {
250
        // Set triggered link as active
251
        $link.addClass(CLASS_NAME_ACTIVE); // Set triggered links parents as active
252
        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
253
254
        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_LINKS + ", " + SELECTOR_LIST_ITEMS).addClass(CLASS_NAME_ACTIVE); // Handle special case when .nav-link is inside .nav-item
255
256
        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_ITEMS).children(SELECTOR_NAV_LINKS).addClass(CLASS_NAME_ACTIVE);
257
      }
258
259
      $__default["default"](this._scrollElement).trigger(EVENT_ACTIVATE, {
260
        relatedTarget: target
261
      });
262
    };
263
264
    _proto._clear = function _clear() {
265
      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {
266
        return node.classList.contains(CLASS_NAME_ACTIVE);
267
      }).forEach(function (node) {
268
        return node.classList.remove(CLASS_NAME_ACTIVE);
269
      });
270
    } // Static
271
    ;
272
273 View Code Duplication
    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
274
      return this.each(function () {
275
        var data = $__default["default"](this).data(DATA_KEY);
276
277
        var _config = typeof config === 'object' && config;
278
279
        if (!data) {
280
          data = new ScrollSpy(this, _config);
281
          $__default["default"](this).data(DATA_KEY, data);
282
        }
283
284
        if (typeof config === 'string') {
285
          if (typeof data[config] === 'undefined') {
286
            throw new TypeError("No method named \"" + config + "\"");
287
          }
288
289
          data[config]();
290
        }
291
      });
292
    };
293
294
    _createClass(ScrollSpy, null, [{
295
      key: "VERSION",
296
      get: function get() {
297
        return VERSION;
298
      }
299
    }, {
300
      key: "Default",
301
      get: function get() {
302
        return Default;
303
      }
304
    }]);
305
306
    return ScrollSpy;
307
  }();
308
  /**
309
   * Data API implementation
310
   */
311
312
313
  $__default["default"](window).on(EVENT_LOAD_DATA_API, function () {
314
    var scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY));
315
    var scrollSpysLength = scrollSpys.length;
316
317
    for (var i = scrollSpysLength; i--;) {
318
      var $spy = $__default["default"](scrollSpys[i]);
319
320
      ScrollSpy._jQueryInterface.call($spy, $spy.data());
321
    }
322
  });
323
  /**
324
   * jQuery
325
   */
326
327
  $__default["default"].fn[NAME] = ScrollSpy._jQueryInterface;
328
  $__default["default"].fn[NAME].Constructor = ScrollSpy;
329
330
  $__default["default"].fn[NAME].noConflict = function () {
331
    $__default["default"].fn[NAME] = JQUERY_NO_CONFLICT;
332
    return ScrollSpy._jQueryInterface;
333
  };
334
335
  return ScrollSpy;
336
337
}));
338
//# sourceMappingURL=scrollspy.js.map
339