PageSourceSearch

https://montegeneroso.ch/themes/custom/fmg/assets/js/bootstrap/scrollspy.js?tkfnsv

js montegeneroso.ch collected 2026-10-02 04:14:51 UTC 10,303 bytes, 312 lines download raw bytes

vendor: 6,474 bytes, lines 1-183
1/*!
2  * Bootstrap scrollspy.js v5.2.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('./util/index'), require('./dom/event-handler'), require('./dom/selector-engine'), require('./base-component')) :
8  typeof define === 'function' && define.amd ? define(['./util/index', './dom/event-handler', './dom/selector-engine', './base-component'], factory) :
9  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Scrollspy = factory(global.Index, global.EventHandler, global.SelectorEngine, global.BaseComponent));
10})(this, (function (index, EventHandler, SelectorEngine, BaseComponent) { 'use strict';
11
12  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
14  const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
15  const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
16  const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
17
18  /**
19   * --------------------------------------------------------------------------
20   * Bootstrap (v5.2.2): scrollspy.js
21   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
22   * --------------------------------------------------------------------------
23   */
24  /**
25   * Constants
26   */
27
28  const NAME = 'scrollspy';
29  const DATA_KEY = 'bs.scrollspy';
30  const EVENT_KEY = `.${DATA_KEY}`;
31  const DATA_API_KEY = '.data-api';
32  const EVENT_ACTIVATE = `activate${EVENT_KEY}`;
33  const EVENT_CLICK = `click${EVENT_KEY}`;
34  const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`;
35  const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
36  const CLASS_NAME_ACTIVE = 'active';
37  const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]';
38  const SELECTOR_TARGET_LINKS = '[href]';
39  const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
40  const SELECTOR_NAV_LINKS = '.nav-link';
41  const SELECTOR_NAV_ITEMS = '.nav-item';
42  const SELECTOR_LIST_ITEMS = '.list-group-item';
43  const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;
44  const SELECTOR_DROPDOWN = '.dropdown';
45  const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
46  const Default = {
47    offset: null,
48    // TODO: v6 @deprecated, keep it for backwards compatibility reasons
49    rootMargin: '0px 0px -25%',
50    smoothScroll: false,
51    target: null,
52    threshold: [0.1, 0.5, 1]
53  };
54  const DefaultType = {
55    offset: '(number|null)',
56    // TODO v6 @deprecated, keep it for backwards compatibility reasons
57    rootMargin: 'string',
58    smoothScroll: 'boolean',
59    target: 'element',
60    threshold: 'array'
61  };
62  /**
63   * Class definition
64   */
65
66  class ScrollSpy extends BaseComponent__default.default {
67    constructor(element, config) {
68      super(element, config); // this._element is the observablesContainer and config.target the menu links wrapper
69
70      this._targetLinks = new Map();
71      this._observableSections = new Map();
72      this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element;
73      this._activeTarget = null;
74      this._observer = null;
75      this._previousScrollData = {
76        visibleEntryTop: 0,
77        parentScrollTop: 0
78      };
79      this.refresh(); // initialize
80    } // Getters
81
82
83    static get Default() {
84      return Default;
85    }
86
87    static get DefaultType() {
88      return DefaultType;
89    }
90
91    static get NAME() {
92      return NAME;
93    } // Public
94
95
96    refresh() {
97      this._initializeTargetsAndObservables();
98
99      this._maybeEnableSmoothScroll();
100
101      if (this._observer) {
102        this._observer.disconnect();
103      } else {
104        this._observer = this._getNewObserver();
105      }
106
107      for (const section of this._observableSections.values()) {
108        this._observer.observe(section);
109      }
110    }
111
112    dispose() {
113      this._observer.disconnect();
114
115      super.dispose();
116    } // Private
117
118
119    _configAfterMerge(config) {
120      // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
121      config.target = index.getElement(config.target) || document.body; // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
122
123      config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin;
124
125      if (typeof config.threshold === 'string') {
126        config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value));
127      }
128
129      return config;
130    }
131
132    _maybeEnableSmoothScroll() {
133      if (!this._config.smoothScroll) {
134        return;
135      } // unregister any previous listeners
136
137
138      EventHandler__default.default.off(this._config.target, EVENT_CLICK);
139      EventHandler__default.default.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {
140        const observableSection = this._observableSections.get(event.target.hash);
141
142        if (observableSection) {
143          event.preventDefault();
144          const root = this._rootElement || window;
145          const height = observableSection.offsetTop - this._element.offsetTop;
146
147          if (root.scrollTo) {
148            root.scrollTo({
149              top: height,
150              behavior: 'smooth'
151            });
152            return;
153          } // Chrome 60 doesn't support `scrollTo`
154
155
156          root.scrollTop = height;
157        }
158      });
159    }
160
161    _getNewObserver() {
162      const options = {
163        root: this._rootElement,
164        threshold: this._config.threshold,
165        rootMargin: this._config.rootMargin
166      };
167      return new IntersectionObserver(entries => this._observerCallback(entries), options);
168    } // The logic of selection
169
170
171    _observerCallback(entries) {
172      const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`);
173
174      const activate = entry => {
175        this._previousScrollData.visibleEntryTop = entry.target.offsetTop;
176
177        this._process(targetElement(entry));
178      };
179
180      const parentScrollTop = (this._rootElement || document.documentElement).scrollTop;
181      const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop;
182      this._previousScrollData.parentScrollTop = parentScrollTop;
183
184      for (const entry of entries) {
185        if (!entry.isIntersecting) {
186          this._activeTarget = null;
187
188          this._clearActiveClass(targetElement(entry));
189
190          continue;
191        }
192
193        const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop; // if we are scrolling down, pick the bigger offsetTop
194
195        if (userScrollsDown && entryIsLowerThanPrevious) {
196          activate(entry); // if parent isn't scrolled, let's keep the first visible item, breaking the iteration
197
198          if (!parentScrollTop) {
199            return;
200          }
201
202          continue;
203        } // if we are scrolling up, pick the smallest offsetTop
204
205
206        if (!userScrollsDown && !entryIsLowerThanPrevious) {
207          activate(entry);
208        }
209      }
210    }
211
212    _initializeTargetsAndObservables() {
213      this._targetLinks = new Map();
214      this._observableSections = new Map();
215      const targetLinks = SelectorEngine__default.default.find(SELECTOR_TARGET_LINKS, this._config.target);
216
217      for (const anchor of targetLinks) {
218        // ensure that the anchor has an id and is not disabled
219        if (!anchor.hash || index.isDisabled(anchor)) {
220          continue;
221        }
222
223        const observableSection = SelectorEngine__default.default.findOne(anchor.hash, this._element); // ensure that the observableSection exists & is visible
224
225        if (index.isVisible(observableSection)) {
226          this._targetLinks.set(anchor.hash, anchor);
227
228          this._observableSections.set(anchor.hash, observableSection);
229        }
230      }
231    }
232
233    _process(target) {
234      if (this._activeTarget === target) {
235        return;
236      }
237
238      this._clearActiveClass(this._config.target);
239
240      this._activeTarget = target;
241      target.classList.add(CLASS_NAME_ACTIVE);
242
243      this._activateParents(target);
244
245      EventHandler__default.default.trigger(this._element, EVENT_ACTIVATE, {
246        relatedTarget: target
247      });
248    }
249
250    _activateParents(target) {
251      // Activate dropdown parents
252      if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
253        SelectorEngine__default.default.findOne(SELECTOR_DROPDOWN_TOGGLE, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE);
254        return;
255      }
256
257      for (const listGroup of SelectorEngine__default.default.parents(target, SELECTOR_NAV_LIST_GROUP)) {
258        // Set triggered links parents as active
259        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
260        for (const item of SelectorEngine__default.default.prev(listGroup, SELECTOR_LINK_ITEMS)) {
261          item.classList.add(CLASS_NAME_ACTIVE);
262        }
263      }
264    }
265
266    _clearActiveClass(parent) {
267      parent.classList.remove(CLASS_NAME_ACTIVE);
268      const activeNodes = SelectorEngine__default.default.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE}`, parent);
269
270      for (const node of activeNodes) {
271        node.classList.remove(CLASS_NAME_ACTIVE);
272      }
273    } // Static
274
275
276    static jQueryInterface(config) {
277      return this.each(function () {
278        const data = ScrollSpy.getOrCreateInstance(this, config);
279
280        if (typeof config !== 'string') {
281          return;
282        }
283
284        if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
285          throw new TypeError(`No method named "${config}"`);
286        }
287
288        data[config]();
289      });
290    }
291
292  }
293  /**
294   * Data API implementation
295   */
296
297
298  EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
299    for (const spy of SelectorEngine__default.default.find(SELECTOR_DATA_SPY)) {
300      ScrollSpy.getOrCreateInstance(spy);
301    }
302  });
303  /**
304   * jQuery
305   */
306
307  index.defineJQueryPlugin(ScrollSpy);
308
309  return ScrollSpy;
310
311}));
312//# sourceMappingURL=scrollspy.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.