0
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-02-17 14:54:30 +01:00

Dropdowns: Modified Dropdown's _parent to use a new method called 'closest', to allow dropdown menus to not necessarily be the sibling of the trigger button element. So instead of trying to use dropdown wrapper as the direct parent, it can be an ancestor.

This commit is contained in:
Michael Tran 2024-11-19 11:01:47 +11:00
parent cacbdc680e
commit 0fabd40453
3 changed files with 28 additions and 1 deletions

View File

@ -57,6 +57,10 @@ const SelectorEngine = {
return parents
},
closest(element, selector) {
return Element.prototype.closest.call(element, selector)
},
prev(element, selector) {
let previous = element.previousElementSibling

View File

@ -95,7 +95,8 @@ class Dropdown extends BaseComponent {
super(element, config)
this._popper = null
this._parent = this._element.parentNode // dropdown wrapper
const wrapperSelector = `:has(${SELECTOR_MENU})`
this._parent = SelectorEngine.closest(element, wrapperSelector) // dropdown wrapper
// TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||

View File

@ -81,6 +81,28 @@ describe('SelectorEngine', () => {
})
})
describe('closest', () => {
it('should return one element when element with selector is the direct parent', () => {
const testId = 'test'
fixtureEl.innerHTML = `<div id="${testId}"><div id="element"></div></div>`
const element = fixtureEl.querySelector('#element')
const parent = fixtureEl.querySelector(`#${testId}`)
expect(SelectorEngine.closest(element, `#${testId}`)).toEqual(parent)
})
it('should return one element when element with selector is an ancestor', () => {
const testId = 'test'
fixtureEl.innerHTML = `<div id="${testId}"><div><div id="element"></div></div></div>`
const element = fixtureEl.querySelector('#element')
const ancestor = fixtureEl.querySelector(`#${testId}`)
expect(SelectorEngine.closest(element, `#${testId}`)).toEqual(ancestor)
})
})
describe('prev', () => {
it('should return previous element', () => {
fixtureEl.innerHTML = '<div class="test"></div><button class="btn"></button>'