mdb-ui-kit/src/js/bootstrap/dist/scrollspy.js
2020-12-30 15:39:34 +01:00

578 lines
17 KiB
JavaScript

/*!
* Bootstrap scrollspy.js v5.0.0-beta1 (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/main/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',
'./dom/event-handler',
'./dom/manipulator',
'./dom/selector-engine',
], factory)
: ((global = typeof globalThis !== 'undefined' ? globalThis : global || self),
(global.ScrollSpy = factory(
global.Data,
global.EventHandler,
global.Manipulator,
global.SelectorEngine
)));
})(this, function (Data, EventHandler, Manipulator, SelectorEngine) {
'use strict';
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
var Data__default = /*#__PURE__*/ _interopDefaultLegacy(Data);
var EventHandler__default = /*#__PURE__*/ _interopDefaultLegacy(EventHandler);
var Manipulator__default = /*#__PURE__*/ _interopDefaultLegacy(Manipulator);
var SelectorEngine__default = /*#__PURE__*/ _interopDefaultLegacy(SelectorEngine);
/**
* --------------------------------------------------------------------------
* Bootstrap (v5.0.0-beta1): util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/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-bs-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;
};
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-bs-no-jquery')) {
return jQuery;
}
return null;
};
var onDOMContentLoaded = function onDOMContentLoaded(callback) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', callback);
} else {
callback();
}
};
var isRTL = document.documentElement.dir === 'rtl';
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 VERSION = '5.0.0-beta1';
var BaseComponent = /*#__PURE__*/ (function () {
function BaseComponent(element) {
if (!element) {
return;
}
this._element = element;
Data__default['default'].setData(element, this.constructor.DATA_KEY, this);
}
var _proto = BaseComponent.prototype;
_proto.dispose = function dispose() {
Data__default['default'].removeData(this._element, this.constructor.DATA_KEY);
this._element = null;
};
/** Static */
BaseComponent.getInstance = function getInstance(element) {
return Data__default['default'].getData(element, this.DATA_KEY);
};
_createClass(BaseComponent, null, [
{
key: 'VERSION',
get: function get() {
return VERSION;
},
},
]);
return BaseComponent;
})();
function _extends() {
_extends =
Object.assign ||
function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _defineProperties$1(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$1(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
if (staticProps) _defineProperties$1(Constructor, staticProps);
return Constructor;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
var NAME = 'scrollspy';
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-bs-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';
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
var ScrollSpy = /*#__PURE__*/ (function (_BaseComponent) {
_inheritsLoose(ScrollSpy, _BaseComponent);
function ScrollSpy(element, config) {
var _this;
_this = _BaseComponent.call(this, element) || this;
_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__default['default'].on(_this._scrollElement, EVENT_SCROLL, function (event) {
return _this._process(event);
});
_this.refresh();
_this._process();
return _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__default['default'].find(this._selector);
targets
.map(function (element) {
var targetSelector = getSelectorFromElement(element);
var target = targetSelector
? SelectorEngine__default['default'].findOne(targetSelector)
: null;
if (target) {
var targetBCR = target.getBoundingClientRect();
if (targetBCR.width || targetBCR.height) {
return [
Manipulator__default['default'][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() {
_BaseComponent.prototype.dispose.call(this);
EventHandler__default['default'].off(this._scrollElement, EVENT_KEY);
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 = _extends({}, 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;
}
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-bs-target="' + target + '"],' + selector + '[href="' + target + '"]'
);
});
var link = SelectorEngine__default['default'].findOne(queries.join(','));
if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
SelectorEngine__default['default']
.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__default['default']
.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__default['default']
.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__default['default']
.prev(listGroup, SELECTOR_NAV_ITEMS)
.forEach(function (navItem) {
SelectorEngine__default['default']
.children(navItem, SELECTOR_NAV_LINKS)
.forEach(function (item) {
return item.classList.add(CLASS_NAME_ACTIVE);
});
});
});
}
EventHandler__default['default'].trigger(this._scrollElement, EVENT_ACTIVATE, {
relatedTarget: target,
});
};
_proto._clear = function _clear() {
SelectorEngine__default['default']
.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__default['default'].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 + '"');
}
data[config]();
}
});
};
_createClass$1(ScrollSpy, null, [
{
key: 'Default',
get: function get() {
return Default;
},
},
{
key: 'DATA_KEY',
get: function get() {
return DATA_KEY;
},
},
]);
return ScrollSpy;
})(BaseComponent);
/**
* ------------------------------------------------------------------------
* Data Api implementation
* ------------------------------------------------------------------------
*/
EventHandler__default['default'].on(window, EVENT_LOAD_DATA_API, function () {
SelectorEngine__default['default'].find(SELECTOR_DATA_SPY).forEach(function (spy) {
return new ScrollSpy(spy, Manipulator__default['default'].getDataAttributes(spy));
});
});
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
* add .ScrollSpy to jQuery only if jQuery is present
*/
onDOMContentLoaded(function () {
var $ = getjQuery();
/* 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