scrollspy.js 14.69 KiB
/*!
  * Bootstrap scrollspy.js v5.0.0-alpha1 (https://getbootstrap.com/)
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./dom/data.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js')) :
  typeof define === 'function' && define.amd ? define(['./dom/data.js', './dom/event-handler.js', './dom/manipulator.js', './dom/selector-engine.js'], factory) :
  (global = global || self, global.ScrollSpy = factory(global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine));
}(this, (function (Data, EventHandler, Manipulator, SelectorEngine) { 'use strict';
  Data = Data && Object.prototype.hasOwnProperty.call(Data, 'default') ? Data['default'] : Data;
  EventHandler = EventHandler && Object.prototype.hasOwnProperty.call(EventHandler, 'default') ? EventHandler['default'] : EventHandler;
  Manipulator = Manipulator && Object.prototype.hasOwnProperty.call(Manipulator, 'default') ? Manipulator['default'] : Manipulator;
  SelectorEngine = SelectorEngine && Object.prototype.hasOwnProperty.call(SelectorEngine, 'default') ? SelectorEngine['default'] : SelectorEngine;
  /**
   * --------------------------------------------------------------------------
   * Bootstrap (v5.0.0-alpha1): util/index.js
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   * --------------------------------------------------------------------------
  var MAX_UID = 1000000;
  var toType = function toType(obj) {
    if (obj === null || obj === undefined) {
      return "" + obj;
    return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
  /**
   * --------------------------------------------------------------------------
   * Public Util Api
   * --------------------------------------------------------------------------
  var getUID = function getUID(prefix) {
    do {
      prefix += Math.floor(Math.random() * MAX_UID);
    } while (document.getElementById(prefix));
    return prefix;
  var getSelector = function getSelector(element) {
    var selector = element.getAttribute('data-target');
    if (!selector || selector === '#') {
      var hrefAttr = element.getAttribute('href');
      selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
    return selector;
  var getSelectorFromElement = function getSelectorFromElement(element) {
    var selector = getSelector(element);
    if (selector) {
      return document.querySelector(selector) ? selector : null;
    return null;
  var isElement = function isElement(obj) {
    return (obj[0] || obj).nodeType;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
var typeCheckConfig = function typeCheckConfig(componentName, config, configTypes) { Object.keys(configTypes).forEach(function (property) { var expectedTypes = configTypes[property]; var value = config[property]; var valueType = value && isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); } }); }; var getjQuery = function getjQuery() { var _window = window, jQuery = _window.jQuery; if (jQuery && !document.body.hasAttribute('data-no-jquery')) { return jQuery; } return null; }; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 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 _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; } /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ var NAME = 'scrollspy'; var VERSION = '5.0.0-alpha1'; var DATA_KEY = 'bs.scrollspy'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; var Default = { offset: 10, method: 'auto', target: '' }; var DefaultType = { offset: 'number', method: 'string', target: '(string|element)' }; var EVENT_ACTIVATE = "activate" + EVENT_KEY; var EVENT_SCROLL = "scroll" + EVENT_KEY; var EVENT_LOAD_DATA_API = "load" + EVENT_KEY + DATA_API_KEY; var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; var CLASS_NAME_ACTIVE = 'active'; var SELECTOR_DATA_SPY = '[data-spy="scroll"]'; var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; var SELECTOR_NAV_LINKS = '.nav-link'; var SELECTOR_NAV_ITEMS = '.nav-item'; var SELECTOR_LIST_ITEMS = '.list-group-item'; var SELECTOR_DROPDOWN = '.dropdown'; var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; var METHOD_OFFSET = 'offset'; var METHOD_POSITION = 'position'; /** * ------------------------------------------------------------------------
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
* Class Definition * ------------------------------------------------------------------------ */ 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 + " ." + CLASS_NAME_DROPDOWN_ITEM); this._offsets = []; this._targets = []; this._activeTarget = null; this._scrollHeight = 0; EventHandler.on(this._scrollElement, EVENT_SCROLL, function (event) { return _this._process(event); }); this.refresh(); this._process(); Data.setData(element, DATA_KEY, this); } // Getters var _proto = ScrollSpy.prototype; // Public _proto.refresh = function refresh() { var _this2 = this; var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION; var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0; this._offsets = []; this._targets = []; this._scrollHeight = this._getScrollHeight(); var targets = SelectorEngine.find(this._selector); targets.map(function (element) { var target; var targetSelector = getSelectorFromElement(element); if (targetSelector) { target = SelectorEngine.findOne(targetSelector); } if (target) { var targetBCR = target.getBoundingClientRect(); if (targetBCR.width || targetBCR.height) { return [Manipulator[offsetMethod](target).top + offsetBase, targetSelector]; } } return null; }).filter(function (item) { return item; }).sort(function (a, b) { return a[0] - b[0]; }).forEach(function (item) { _this2._offsets.push(item[0]); _this2._targets.push(item[1]); }); }; _proto.dispose = function dispose() { Data.removeData(this._element, DATA_KEY);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
EventHandler.off(this._scrollElement, 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; } // Private ; _proto._getConfig = function _getConfig(config) { config = _objectSpread(_objectSpread({}, Default), typeof config === 'object' && config ? config : {}); if (typeof config.target !== 'string' && isElement(config.target)) { var id = config.target.id; if (!id) { id = getUID(NAME); config.target.id = id; } config.target = "#" + id; } typeCheckConfig(NAME, config, DefaultType); return config; }; _proto._getScrollTop = function _getScrollTop() { return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; }; _proto._getScrollHeight = function _getScrollHeight() { return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); }; _proto._getOffsetHeight = function _getOffsetHeight() { return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; }; _proto._process = function _process() { var scrollTop = this._getScrollTop() + this._config.offset; var scrollHeight = this._getScrollHeight(); var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); if (this._scrollHeight !== scrollHeight) { this.refresh(); } if (scrollTop >= maxScroll) { var target = this._targets[this._targets.length - 1]; if (this._activeTarget !== target) { this._activate(target); } return; } if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { this._activeTarget = null; this._clear(); return; }
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
for (var i = this._offsets.length; i--;) { var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); if (isActiveTarget) { this._activate(this._targets[i]); } } }; _proto._activate = function _activate(target) { this._activeTarget = target; this._clear(); var queries = this._selector.split(',').map(function (selector) { return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]"; }); var link = SelectorEngine.findOne(queries.join(',')); if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE); link.classList.add(CLASS_NAME_ACTIVE); } else { // Set triggered link as active link.classList.add(CLASS_NAME_ACTIVE); SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP).forEach(function (listGroup) { // Set triggered links parents as active // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor SelectorEngine.prev(listGroup, SELECTOR_NAV_LINKS + ", " + SELECTOR_LIST_ITEMS).forEach(function (item) { return item.classList.add(CLASS_NAME_ACTIVE); }); // Handle special case when .nav-link is inside .nav-item SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS).forEach(function (navItem) { SelectorEngine.children(navItem, SELECTOR_NAV_LINKS).forEach(function (item) { return item.classList.add(CLASS_NAME_ACTIVE); }); }); }); } EventHandler.trigger(this._scrollElement, EVENT_ACTIVATE, { relatedTarget: target }); }; _proto._clear = function _clear() { SelectorEngine.find(this._selector).filter(function (node) { return node.classList.contains(CLASS_NAME_ACTIVE); }).forEach(function (node) { return node.classList.remove(CLASS_NAME_ACTIVE); }); } // Static ; ScrollSpy.jQueryInterface = function jQueryInterface(config) { return this.each(function () { var data = Data.getData(this, DATA_KEY); var _config = typeof config === 'object' && config; if (!data) { data = new ScrollSpy(this, _config); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError("No method named \"" + config + "\""); }
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
data[config](); } }); }; ScrollSpy.getInstance = function getInstance(element) { return Data.getData(element, DATA_KEY); }; _createClass(ScrollSpy, null, [{ key: "VERSION", get: function get() { return VERSION; } }, { key: "Default", get: function get() { return Default; } }]); return ScrollSpy; }(); /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(window, EVENT_LOAD_DATA_API, function () { SelectorEngine.find(SELECTOR_DATA_SPY).forEach(function (spy) { return new ScrollSpy(spy, Manipulator.getDataAttributes(spy)); }); }); var $ = getjQuery(); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ /* istanbul ignore if */ if ($) { var JQUERY_NO_CONFLICT = $.fn[NAME]; $.fn[NAME] = ScrollSpy.jQueryInterface; $.fn[NAME].Constructor = ScrollSpy; $.fn[NAME].noConflict = function () { $.fn[NAME] = JQUERY_NO_CONFLICT; return ScrollSpy.jQueryInterface; }; } return ScrollSpy; }))); //# sourceMappingURL=scrollspy.js.map