]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Dropdown: fix case with invalid markup (#37190)
authorGeoSot <geo.sotis@gmail.com>
Tue, 27 Sep 2022 07:39:11 +0000 (10:39 +0300)
committerGitHub <noreply@github.com>
Tue, 27 Sep 2022 07:39:11 +0000 (10:39 +0300)
This fixes a backward incompatible change in v5.2.1 where `.drodown-toggle` isn't present in the markup.

js/src/dropdown.js
js/tests/unit/dropdown.spec.js

index 607ab27ba7a68c7752b6a91265f9ce3c3aaada18..f8dafc21bda6e0a4b22c32af68d708f847a882d4 100644 (file)
@@ -96,7 +96,9 @@ class Dropdown extends BaseComponent {
     this._popper = null
     this._parent = this._element.parentNode // dropdown wrapper
     // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
-    this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0]
+    this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
+      SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||
+      SelectorEngine.findOne(SELECTOR_MENU, this._parent)
     this._inNavbar = this._detectNavbar()
   }
 
@@ -407,7 +409,12 @@ class Dropdown extends BaseComponent {
     event.preventDefault()
 
     // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/
-    const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0]
+    const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?
+      this :
+      (SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] ||
+        SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] ||
+        SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode))
+
     const instance = Dropdown.getOrCreateInstance(getToggleButton)
 
     if (isUpOrDownEvent) {
index ea7ddace30f85486d43ca866d09b441f2f68ad46..2bbd7c00a794a6813bf1d70147f13296575325c2 100644 (file)
@@ -57,6 +57,28 @@ describe('Dropdown', () => {
       expect(dropdownByElement._element).toEqual(btnDropdown)
     })
 
+    it('should work on invalid markup', () => {
+      return new Promise(resolve => {
+        // TODO: REMOVE in v6
+        fixtureEl.innerHTML = [
+          '<div class="dropdown">',
+          '  <div class="dropdown-menu">',
+          '    <a class="dropdown-item" href="#">Link</a>',
+          '  </div>',
+          '</div>'
+        ].join('')
+
+        const dropdownElem = fixtureEl.querySelector('.dropdown-menu')
+        const dropdown = new Dropdown(dropdownElem)
+
+        dropdownElem.addEventListener('shown.bs.dropdown', () => {
+          resolve()
+        })
+
+        dropdown.show()
+      })
+    })
+
     it('should create offset modifier correctly when offset option is a function', () => {
       return new Promise(resolve => {
         fixtureEl.innerHTML = [