diff options
Diffstat (limited to 'vendor/twbs/bootstrap/js/src/scrollspy.js')
-rw-r--r-- | vendor/twbs/bootstrap/js/src/scrollspy.js | 526 |
1 files changed, 260 insertions, 266 deletions
diff --git a/vendor/twbs/bootstrap/js/src/scrollspy.js b/vendor/twbs/bootstrap/js/src/scrollspy.js index 5cbffc650..e8cd6bf98 100644 --- a/vendor/twbs/bootstrap/js/src/scrollspy.js +++ b/vendor/twbs/bootstrap/js/src/scrollspy.js @@ -1,332 +1,326 @@ -import $ from 'jquery' -import Util from './util' - /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.3): scrollspy.js + * Bootstrap (v4.3.1): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ -const ScrollSpy = (($) => { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - - const NAME = 'scrollspy' - const VERSION = '4.1.3' - const DATA_KEY = 'bs.scrollspy' - const EVENT_KEY = `.${DATA_KEY}` - const DATA_API_KEY = '.data-api' - const JQUERY_NO_CONFLICT = $.fn[NAME] - - const Default = { - offset : 10, - method : 'auto', - target : '' - } +import $ from 'jquery' +import Util from './util' - const DefaultType = { - offset : 'number', - method : 'string', - target : '(string|element)' - } +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - const Event = { - ACTIVATE : `activate${EVENT_KEY}`, - SCROLL : `scroll${EVENT_KEY}`, - LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` - } +const NAME = 'scrollspy' +const VERSION = '4.3.1' +const DATA_KEY = 'bs.scrollspy' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const Default = { + offset : 10, + method : 'auto', + target : '' +} + +const DefaultType = { + offset : 'number', + method : 'string', + target : '(string|element)' +} + +const Event = { + ACTIVATE : `activate${EVENT_KEY}`, + SCROLL : `scroll${EVENT_KEY}`, + LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}` +} + +const ClassName = { + DROPDOWN_ITEM : 'dropdown-item', + DROPDOWN_MENU : 'dropdown-menu', + ACTIVE : 'active' +} + +const 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' +} + +const OffsetMethod = { + OFFSET : 'offset', + POSITION : 'position' +} - const ClassName = { - DROPDOWN_ITEM : 'dropdown-item', - DROPDOWN_MENU : 'dropdown-menu', - ACTIVE : 'active' - } +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - const 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' +class ScrollSpy { + constructor(element, config) { + 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, (event) => this._process(event)) + + this.refresh() + this._process() } - const OffsetMethod = { - OFFSET : 'offset', - POSITION : 'position' - } + // Getters - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - class ScrollSpy { - constructor(element, config) { - 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, (event) => this._process(event)) + static get VERSION() { + return VERSION + } - this.refresh() - this._process() - } + static get Default() { + return Default + } - // Getters + // Public - static get VERSION() { - return VERSION - } + refresh() { + const autoMethod = this._scrollElement === this._scrollElement.window + ? OffsetMethod.OFFSET : OffsetMethod.POSITION - static get Default() { - return Default - } + const offsetMethod = this._config.method === 'auto' + ? autoMethod : this._config.method - // Public + const offsetBase = offsetMethod === OffsetMethod.POSITION + ? this._getScrollTop() : 0 - refresh() { - const autoMethod = this._scrollElement === this._scrollElement.window - ? OffsetMethod.OFFSET : OffsetMethod.POSITION + this._offsets = [] + this._targets = [] - const offsetMethod = this._config.method === 'auto' - ? autoMethod : this._config.method + this._scrollHeight = this._getScrollHeight() - const offsetBase = offsetMethod === OffsetMethod.POSITION - ? this._getScrollTop() : 0 + const targets = [].slice.call(document.querySelectorAll(this._selector)) - this._offsets = [] - this._targets = [] + targets + .map((element) => { + let target + const targetSelector = Util.getSelectorFromElement(element) - this._scrollHeight = this._getScrollHeight() + if (targetSelector) { + target = document.querySelector(targetSelector) + } - const targets = [].slice.call(document.querySelectorAll(this._selector)) + if (target) { + const targetBCR = target.getBoundingClientRect() + if (targetBCR.width || targetBCR.height) { + // TODO (fat): remove sketch reliance on jQuery position/offset + return [ + $(target)[offsetMethod]().top + offsetBase, + targetSelector + ] + } + } + return null + }) + .filter((item) => item) + .sort((a, b) => a[0] - b[0]) + .forEach((item) => { + this._offsets.push(item[0]) + this._targets.push(item[1]) + }) + } - targets - .map((element) => { - let target - const targetSelector = Util.getSelectorFromElement(element) + 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 + } - if (targetSelector) { - target = document.querySelector(targetSelector) - } + // Private - if (target) { - const targetBCR = target.getBoundingClientRect() - if (targetBCR.width || targetBCR.height) { - // TODO (fat): remove sketch reliance on jQuery position/offset - return [ - $(target)[offsetMethod]().top + offsetBase, - targetSelector - ] - } - } - return null - }) - .filter((item) => item) - .sort((a, b) => a[0] - b[0]) - .forEach((item) => { - this._offsets.push(item[0]) - this._targets.push(item[1]) - }) + _getConfig(config) { + config = { + ...Default, + ...typeof config === 'object' && config ? config : {} } - 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 + if (typeof config.target !== 'string') { + let id = $(config.target).attr('id') + if (!id) { + id = Util.getUID(NAME) + $(config.target).attr('id', id) + } + config.target = `#${id}` } - // Private - - _getConfig(config) { - config = { - ...Default, - ...typeof config === 'object' && config ? config : {} - } + Util.typeCheckConfig(NAME, config, DefaultType) - if (typeof config.target !== 'string') { - let id = $(config.target).attr('id') - if (!id) { - id = Util.getUID(NAME) - $(config.target).attr('id', id) - } - config.target = `#${id}` - } + return config + } - Util.typeCheckConfig(NAME, config, DefaultType) + _getScrollTop() { + return this._scrollElement === window + ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop + } - return config - } + _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max( + document.body.scrollHeight, + document.documentElement.scrollHeight + ) + } - _getScrollTop() { - return this._scrollElement === window - ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop - } + _getOffsetHeight() { + return this._scrollElement === window + ? window.innerHeight : this._scrollElement.getBoundingClientRect().height + } - _getScrollHeight() { - return this._scrollElement.scrollHeight || Math.max( - document.body.scrollHeight, - document.documentElement.scrollHeight - ) - } + _process() { + const scrollTop = this._getScrollTop() + this._config.offset + const scrollHeight = this._getScrollHeight() + const maxScroll = this._config.offset + + scrollHeight - + this._getOffsetHeight() - _getOffsetHeight() { - return this._scrollElement === window - ? window.innerHeight : this._scrollElement.getBoundingClientRect().height + if (this._scrollHeight !== scrollHeight) { + this.refresh() } - _process() { - const scrollTop = this._getScrollTop() + this._config.offset - const scrollHeight = this._getScrollHeight() - const maxScroll = this._config.offset + - scrollHeight - - this._getOffsetHeight() - - if (this._scrollHeight !== scrollHeight) { - this.refresh() - } - - if (scrollTop >= maxScroll) { - const target = this._targets[this._targets.length - 1] + if (scrollTop >= maxScroll) { + const target = this._targets[this._targets.length - 1] - if (this._activeTarget !== target) { - this._activate(target) - } - return + 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 - } + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null + this._clear() + return + } - const offsetLength = this._offsets.length - for (let i = offsetLength; i--;) { - const isActiveTarget = this._activeTarget !== this._targets[i] && - scrollTop >= this._offsets[i] && - (typeof this._offsets[i + 1] === 'undefined' || - scrollTop < this._offsets[i + 1]) + const offsetLength = this._offsets.length + for (let i = offsetLength; i--;) { + const 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]) - } + if (isActiveTarget) { + this._activate(this._targets[i]) } } + } - _activate(target) { - this._activeTarget = target + _activate(target) { + this._activeTarget = target - this._clear() + this._clear() - let queries = this._selector.split(',') - // eslint-disable-next-line arrow-body-style - queries = queries.map((selector) => { - return `${selector}[data-target="${target}"],` + - `${selector}[href="${target}"]` - }) + const queries = this._selector + .split(',') + .map((selector) => `${selector}[data-target="${target}"],${selector}[href="${target}"]`) - const $link = $([].slice.call(document.querySelectorAll(queries.join(',')))) - - 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 - $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 - $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE) - } + const $link = $([].slice.call(document.querySelectorAll(queries.join(',')))) - $(this._scrollElement).trigger(Event.ACTIVATE, { - relatedTarget: target - }) + 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 + $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 + $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE) } - _clear() { - const nodes = [].slice.call(document.querySelectorAll(this._selector)) - $(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE) - } + $(this._scrollElement).trigger(Event.ACTIVATE, { + relatedTarget: target + }) + } - // Static + _clear() { + [].slice.call(document.querySelectorAll(this._selector)) + .filter((node) => node.classList.contains(ClassName.ACTIVE)) + .forEach((node) => node.classList.remove(ClassName.ACTIVE)) + } - static _jQueryInterface(config) { - return this.each(function () { - let data = $(this).data(DATA_KEY) - const _config = typeof config === 'object' && config + // Static - if (!data) { - data = new ScrollSpy(this, _config) - $(this).data(DATA_KEY, data) - } + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + const _config = typeof config === 'object' && config - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) - } - data[config]() + if (!data) { + data = new ScrollSpy(this, _config) + $(this).data(DATA_KEY, data) + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) } - }) - } + data[config]() + } + }) } +} - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - $(window).on(Event.LOAD_DATA_API, () => { - const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)) +$(window).on(Event.LOAD_DATA_API, () => { + const scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)) + const scrollSpysLength = scrollSpys.length - const scrollSpysLength = scrollSpys.length - for (let i = scrollSpysLength; i--;) { - const $spy = $(scrollSpys[i]) - ScrollSpy._jQueryInterface.call($spy, $spy.data()) - } - }) - - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - $.fn[NAME] = ScrollSpy._jQueryInterface - $.fn[NAME].Constructor = ScrollSpy - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT - return ScrollSpy._jQueryInterface + for (let i = scrollSpysLength; i--;) { + const $spy = $(scrollSpys[i]) + ScrollSpy._jQueryInterface.call($spy, $spy.data()) } +}) + +/** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - return ScrollSpy -})($) +$.fn[NAME] = ScrollSpy._jQueryInterface +$.fn[NAME].Constructor = ScrollSpy +$.fn[NAME].noConflict = () => { + $.fn[NAME] = JQUERY_NO_CONFLICT + return ScrollSpy._jQueryInterface +} export default ScrollSpy |