Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorJohann-S <johann.servoire@gmail.com>2020-06-19 11:17:01 +0300
committerXhmikosR <xhmikosr@gmail.com>2020-12-06 19:42:40 +0300
commitadfdf7160b5822aae12eea677e7dd3128d2569bf (patch)
treedc09bbdff9ce3457867d28aadc583f0de6da0ec2 /js
parent5f89ea3a0f9b56547eb03b98afcd189b89d7e5a6 (diff)
Update to popper.js v2.x
Diffstat (limited to 'js')
-rw-r--r--js/src/dropdown.js56
-rw-r--r--js/src/tooltip.js109
-rw-r--r--js/tests/integration/bundle-modularity.js2
-rw-r--r--js/tests/integration/bundle.js1
-rw-r--r--js/tests/integration/rollup.bundle.js4
-rw-r--r--js/tests/karma.conf.js4
-rw-r--r--js/tests/unit/dropdown.spec.js95
-rw-r--r--js/tests/unit/tooltip.spec.js24
-rw-r--r--js/tests/visual/dropdown.html15
-rw-r--r--js/tests/visual/popover.html2
-rw-r--r--js/tests/visual/tooltip.html2
11 files changed, 84 insertions, 230 deletions
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index 0ac108ab81..04c299600e 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 17148ed9a6..dc2f83a8a5 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 003f840210..8546141b19 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 75982f76f9..452088a7d8 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 9e2ed26c1c..288f40961d 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 0728a8cfa4..d0dd8bdd90 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 f6a5feb1b9..d2171f3697 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 = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].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 = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].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 = [
'<div class="dropdown">',
@@ -860,14 +814,11 @@ describe('Dropdown', () => {
expect(dropdown._menu).toBeDefined()
expect(dropdown._element).toBeDefined()
- spyOn(Popper.prototype, 'destroy')
-
dropdown.dispose()
expect(dropdown._popper).toBeNull()
expect(dropdown._menu).toBeNull()
expect(dropdown._element).toBeNull()
- expect(Popper.prototype.destroy).toHaveBeenCalled()
})
})
@@ -889,12 +840,12 @@ describe('Dropdown', () => {
expect(dropdown._popper).toBeDefined()
- spyOn(dropdown._popper, 'scheduleUpdate')
+ spyOn(dropdown._popper, 'update')
spyOn(dropdown, '_detectNavbar')
dropdown.update()
- expect(dropdown._popper.scheduleUpdate).toHaveBeenCalled()
+ expect(dropdown._popper.update).toHaveBeenCalled()
expect(dropdown._detectNavbar).toHaveBeenCalled()
})
@@ -921,48 +872,6 @@ describe('Dropdown', () => {
})
describe('data-api', () => {
- it('should not add class position-static to dropdown if boundary not set', done => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdownEl = fixtureEl.querySelector('.dropdown')
-
- dropdownEl.addEventListener('shown.bs.dropdown', () => {
- expect(dropdownEl.classList.contains('position-static')).toEqual(false)
- done()
- })
-
- btnDropdown.click()
- })
-
- it('should add class position-static to dropdown if boundary not scrollParent', done => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-boundary="viewport">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdownEl = fixtureEl.querySelector('.dropdown')
-
- dropdownEl.addEventListener('shown.bs.dropdown', () => {
- expect(dropdownEl.classList.contains('position-static')).toEqual(true)
- done()
- })
-
- btnDropdown.click()
- })
-
it('should show and hide a dropdown', done => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js
index 9ea9096de9..9fc306dfe1 100644
--- a/js/tests/unit/tooltip.spec.js
+++ b/js/tests/unit/tooltip.spec.js
@@ -483,24 +483,6 @@ describe('Tooltip', () => {
tooltip.show()
})
- it('should show a tooltip with offset as a function', done => {
- fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
-
- const spy = jasmine.createSpy('offset').and.returnValue({})
- const tooltipEl = fixtureEl.querySelector('a')
- const tooltip = new Tooltip(tooltipEl, {
- offset: spy
- })
-
- tooltipEl.addEventListener('shown.bs.tooltip', () => {
- expect(document.querySelector('.tooltip')).toBeDefined()
- expect(spy).toHaveBeenCalled()
- done()
- })
-
- tooltip.show()
- })
-
it('should show a tooltip without the animation', done => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
@@ -789,18 +771,18 @@ describe('Tooltip', () => {
})
describe('update', () => {
- it('should call popper schedule update', done => {
+ it('should call popper update', done => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl)
tooltipEl.addEventListener('shown.bs.tooltip', () => {
- spyOn(tooltip._popper, 'scheduleUpdate')
+ spyOn(tooltip._popper, 'update')
tooltip.update()
- expect(tooltip._popper.scheduleUpdate).toHaveBeenCalled()
+ expect(tooltip._popper.update).toHaveBeenCalled()
done()
})
diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html
index 930940a157..374e46e1ae 100644
--- a/js/tests/visual/dropdown.html
+++ b/js/tests/visual/dropdown.html
@@ -78,7 +78,9 @@
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
+ </div>
+ <div class="col-sm-12 mt-4">
<div class="btn-group dropup">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropup</button>
<ul class="dropdown-menu">
@@ -172,16 +174,6 @@
<div class="row">
<div class="col-sm-3 mt-4">
<div class="btn-group dropdown">
- <button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="10,20">Dropdown offset</button>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </div>
- </div>
- <div class="col-sm-3 mt-4">
- <div class="btn-group dropdown">
<button type="button" class="btn btn-secondary">Dropdown reference</button>
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" data-bs-reference="parent">
<span class="visually-hidden">Dropdown split</span>
@@ -206,10 +198,9 @@
</div>
</div>
</div>
-
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/data.js"></script>
diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html
index c758253969..ddc068708d 100644
--- a/js/tests/visual/popover.html
+++ b/js/tests/visual/popover.html
@@ -31,7 +31,7 @@
</button>
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/manipulator.js"></script>
diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html
index bade26a6c0..36f0a70575 100644
--- a/js/tests/visual/tooltip.html
+++ b/js/tests/visual/tooltip.html
@@ -68,7 +68,7 @@
<div id="customContainer"></div>
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/manipulator.js"></script>