From adfdf7160b5822aae12eea677e7dd3128d2569bf Mon Sep 17 00:00:00 2001 From: Johann-S Date: Fri, 19 Jun 2020 11:17:01 +0300 Subject: Update to popper.js v2.x --- js/src/dropdown.js | 56 ++++----------- js/src/tooltip.js | 109 ++++++++++++++---------------- js/tests/integration/bundle-modularity.js | 2 +- js/tests/integration/bundle.js | 1 - js/tests/integration/rollup.bundle.js | 4 ++ js/tests/karma.conf.js | 4 ++ js/tests/unit/dropdown.spec.js | 95 +------------------------- js/tests/unit/tooltip.spec.js | 24 +------ js/tests/visual/dropdown.html | 15 +--- js/tests/visual/popover.html | 2 +- js/tests/visual/tooltip.html | 2 +- 11 files changed, 84 insertions(+), 230 deletions(-) (limited to 'js') diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 0ac108ab8..04c299600 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -5,6 +5,8 @@ * -------------------------------------------------------------------------- */ +import * as Popper from '@popperjs/core' + import { getjQuery, onDOMContentLoaded, @@ -18,7 +20,6 @@ import { import Data from './dom/data' import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' -import Popper from 'popper.js' import SelectorEngine from './dom/selector-engine' import BaseComponent from './base-component' @@ -58,7 +59,6 @@ const CLASS_NAME_DROPEND = 'dropend' const CLASS_NAME_DROPSTART = 'dropstart' const CLASS_NAME_MENUEND = 'dropdown-menu-end' const CLASS_NAME_NAVBAR = 'navbar' -const CLASS_NAME_POSITION_STATIC = 'position-static' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]' const SELECTOR_FORM_CHILD = '.dropdown form' @@ -76,7 +76,7 @@ const PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start' const Default = { offset: 0, flip: true, - boundary: 'scrollParent', + boundary: 'clippingParents', reference: 'toggle', display: 'dynamic', popperConfig: null @@ -176,14 +176,7 @@ class Dropdown extends BaseComponent { } } - // If boundary is not `scrollParent`, then set position to `static` - // to allow the menu to "escape" the scroll parent's boundaries - // https://github.com/twbs/bootstrap/issues/24251 - if (this._config.boundary !== 'scrollParent') { - parent.classList.add(CLASS_NAME_POSITION_STATIC) - } - - this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()) + this._popper = Popper.createPopper(referenceElement, this._menu, this._getPopperConfig()) } // If this is a touch-enabled device we add extra @@ -233,6 +226,7 @@ class Dropdown extends BaseComponent { super.dispose() EventHandler.off(this._element, EVENT_KEY) this._menu = null + if (this._popper) { this._popper.destroy() this._popper = null @@ -242,7 +236,7 @@ class Dropdown extends BaseComponent { update() { this._inNavbar = this._detectNavbar() if (this._popper) { - this._popper.scheduleUpdate() + this._popper.update() } } @@ -296,44 +290,24 @@ class Dropdown extends BaseComponent { return Boolean(this._element.closest(`.${CLASS_NAME_NAVBAR}`)) } - _getOffset() { - const offset = {} - - if (typeof this._config.offset === 'function') { - offset.fn = data => { - data.offsets = { - ...data.offsets, - ...(this._config.offset(data.offsets, this._element) || {}) - } - - return data - } - } else { - offset.offset = this._config.offset - } - - return offset - } - _getPopperConfig() { const popperConfig = { placement: this._getPlacement(), - modifiers: { - offset: this._getOffset(), - flip: { - enabled: this._config.flip - }, - preventOverflow: { - boundariesElement: this._config.boundary + modifiers: [{ + name: 'preventOverflow', + options: { + altBoundary: this._config.flip, + rootBoundary: this._config.boundary } - } + }] } // Disable Popper if we have a static display if (this._config.display === 'static') { - popperConfig.modifiers.applyStyle = { + popperConfig.modifiers = [{ + name: 'applyStyles', enabled: false - } + }] } return { diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 17148ed9a..dc2f83a8a 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -5,6 +5,8 @@ * -------------------------------------------------------------------------- */ +import * as Popper from '@popperjs/core' + import { getjQuery, onDOMContentLoaded, @@ -25,7 +27,6 @@ import { import Data from './dom/data' import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' -import Popper from 'popper.js' import SelectorEngine from './dom/selector-engine' import BaseComponent from './base-component' @@ -51,9 +52,8 @@ const DefaultType = { html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', - offset: '(number|string|function)', container: '(string|element|boolean)', - fallbackPlacement: '(string|array)', + fallbackPlacements: '(null|array)', boundary: '(string|element)', customClass: '(string|function)', sanitize: 'boolean', @@ -82,10 +82,9 @@ const Default = { html: false, selector: false, placement: 'top', - offset: 0, container: false, - fallbackPlacement: 'flip', - boundary: 'scrollParent', + fallbackPlacements: null, + boundary: 'clippingParents', customClass: '', sanitize: true, sanitizeFn: null, @@ -287,7 +286,7 @@ class Tooltip extends BaseComponent { EventHandler.trigger(this._element, this.constructor.Event.INSERTED) - this._popper = new Popper(this._element, tip, this._getPopperConfig(attachment)) + this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment)) tip.classList.add(CLASS_NAME_SHOW) @@ -307,13 +306,9 @@ class Tooltip extends BaseComponent { } const complete = () => { - if (this.config.animation) { - this._fixTransition() - } - const prevHoverState = this._hoverState - this._hoverState = null + this._hoverState = null EventHandler.trigger(this._element, this.constructor.Event.SHOWN) if (prevHoverState === HOVER_STATE_OUT) { @@ -345,7 +340,11 @@ class Tooltip extends BaseComponent { this._cleanTipClass() this._element.removeAttribute('aria-describedby') EventHandler.trigger(this._element, this.constructor.Event.HIDDEN) - this._popper.destroy() + + if (this._popper) { + this._popper.destroy() + this._popper = null + } } const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE) @@ -380,7 +379,7 @@ class Tooltip extends BaseComponent { update() { if (this._popper !== null) { - this._popper.scheduleUpdate() + this._popper.update() } } @@ -469,26 +468,45 @@ class Tooltip extends BaseComponent { // Private _getPopperConfig(attachment) { + const flipModifier = { + name: 'flip', + options: { + altBoundary: true + } + } + + if (this.config.fallbackPlacements) { + flipModifier.options.fallbackPlacements = this.config.fallbackPlacements + } + const defaultBsConfig = { placement: attachment, - modifiers: { - offset: this._getOffset(), - flip: { - behavior: this.config.fallbackPlacement + modifiers: [ + flipModifier, + { + name: 'preventOverflow', + options: { + rootBoundary: this.config.boundary + } }, - arrow: { - element: `.${this.constructor.NAME}-arrow` + { + name: 'arrow', + options: { + element: `.${this.constructor.NAME}-arrow` + } }, - preventOverflow: { - boundariesElement: this.config.boundary + { + name: 'onChange', + enabled: true, + phase: 'afterWrite', + fn: data => this._handlePopperPlacementChange(data) } - }, - onCreate: data => { - if (data.originalPlacement !== data.placement) { + ], + onFirstUpdate: data => { + if (data.options.placement !== data.placement) { this._handlePopperPlacementChange(data) } - }, - onUpdate: data => this._handlePopperPlacementChange(data) + } } return { @@ -501,25 +519,6 @@ class Tooltip extends BaseComponent { this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`) } - _getOffset() { - const offset = {} - - if (typeof this.config.offset === 'function') { - offset.fn = data => { - data.offsets = { - ...data.offsets, - ...(this.config.offset(data.offsets, this._element) || {}) - } - - return data - } - } else { - offset.offset = this.config.offset - } - - return offset - } - _getContainer() { if (this.config.container === false) { return document.body @@ -743,23 +742,15 @@ class Tooltip extends BaseComponent { } _handlePopperPlacementChange(popperData) { - this.tip = popperData.instance.popper - this._cleanTipClass() - this._addAttachmentClass(this._getAttachment(popperData.placement)) - } + const { state } = popperData - _fixTransition() { - const tip = this.getTipElement() - const initConfigAnimation = this.config.animation - if (tip.getAttribute('x-placement') !== null) { + if (!state) { return } - tip.classList.remove(CLASS_NAME_FADE) - this.config.animation = false - this.hide() - this.show() - this.config.animation = initConfigAnimation + this.tip = state.elements.popper + this._cleanTipClass() + this._addAttachmentClass(this._getAttachment(state.placement)) } // Static diff --git a/js/tests/integration/bundle-modularity.js b/js/tests/integration/bundle-modularity.js index 003f84021..8546141b1 100644 --- a/js/tests/integration/bundle-modularity.js +++ b/js/tests/integration/bundle-modularity.js @@ -1,5 +1,5 @@ -import 'popper.js' import Tooltip from '../../dist/tooltip' +import '../../dist/carousel' window.addEventListener('load', () => { [].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]')) diff --git a/js/tests/integration/bundle.js b/js/tests/integration/bundle.js index 75982f76f..452088a7d 100644 --- a/js/tests/integration/bundle.js +++ b/js/tests/integration/bundle.js @@ -1,4 +1,3 @@ -import 'popper.js' import { Tooltip } from '../../../dist/js/bootstrap.esm.js' window.addEventListener('load', () => { diff --git a/js/tests/integration/rollup.bundle.js b/js/tests/integration/rollup.bundle.js index 9e2ed26c1..288f40961 100644 --- a/js/tests/integration/rollup.bundle.js +++ b/js/tests/integration/rollup.bundle.js @@ -2,6 +2,7 @@ const { babel } = require('@rollup/plugin-babel') const { nodeResolve } = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') module.exports = { input: 'js/tests/integration/bundle.js', @@ -10,6 +11,9 @@ module.exports = { format: 'iife' }, plugins: [ + replace({ + 'process.env.NODE_ENV': '"production"' + }), nodeResolve(), babel({ exclude: 'node_modules/**', diff --git a/js/tests/karma.conf.js b/js/tests/karma.conf.js index 0728a8cfa..d0dd8bdd9 100644 --- a/js/tests/karma.conf.js +++ b/js/tests/karma.conf.js @@ -5,6 +5,7 @@ const ip = require('ip') const { babel } = require('@rollup/plugin-babel') const istanbul = require('rollup-plugin-istanbul') const { nodeResolve } = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') const { browsers, @@ -74,6 +75,9 @@ const conf = { }, rollupPreprocessor: { plugins: [ + replace({ + 'process.env.NODE_ENV': '"dev"' + }), istanbul({ exclude: [ 'node_modules/**', diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js index f6a5feb1b..d2171f369 100644 --- a/js/tests/unit/dropdown.spec.js +++ b/js/tests/unit/dropdown.spec.js @@ -1,5 +1,3 @@ -import Popper from 'popper.js' - import Dropdown from '../../src/dropdown' import EventHandler from '../../src/dom/event-handler' @@ -36,50 +34,6 @@ describe('Dropdown', () => { }) describe('constructor', () => { - it('should create offset modifier correctly when offset option is a function', () => { - fixtureEl.innerHTML = [ - '' - ].join('') - - const getOffset = offsets => offsets - const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') - const dropdown = new Dropdown(btnDropdown, { - offset: getOffset - }) - - const offset = dropdown._getOffset() - - expect(offset.offset).toBeUndefined() - expect(typeof offset.fn).toEqual('function') - }) - - it('should create offset modifier correctly when offset option is not a function', () => { - fixtureEl.innerHTML = [ - '' - ].join('') - - const myOffset = 7 - const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]') - const dropdown = new Dropdown(btnDropdown, { - offset: myOffset - }) - - const offset = dropdown._getOffset() - - expect(offset.offset).toEqual(myOffset) - expect(offset.fn).toBeUndefined() - }) - it('should add a listener on trigger which do not have data-bs-toggle="dropdown"', () => { fixtureEl.innerHTML = [ ' +
-
- -
-
- + diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html index c75825396..ddc068708 100644 --- a/js/tests/visual/popover.html +++ b/js/tests/visual/popover.html @@ -31,7 +31,7 @@ - + diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html index bade26a6c..36f0a7057 100644 --- a/js/tests/visual/tooltip.html +++ b/js/tests/visual/tooltip.html @@ -68,7 +68,7 @@
- + -- cgit v1.2.3