]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Restore offset option for dropdown component
authorjoke2k <daniele.faraglia@gmail.com>
Sat, 12 Dec 2020 00:54:29 +0000 (02:54 +0200)
committerXhmikosR <xhmikosr@gmail.com>
Thu, 28 Jan 2021 10:23:33 +0000 (12:23 +0200)
js/src/dropdown.js
js/tests/unit/dropdown.spec.js
site/content/docs/5.0/components/dropdowns.md

index bada537c9c8e74b767d11a4223e4d7e61b71cf2a..66ff8cc4fcf78b26d4881072a74956106c9ec800 100644 (file)
@@ -72,7 +72,7 @@ const PLACEMENT_RIGHT = isRTL ? 'left-start' : 'right-start'
 const PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start'
 
 const Default = {
-  offset: 0,
+  offset: [0, 0],
   flip: true,
   boundary: 'clippingParents',
   reference: 'toggle',
@@ -81,7 +81,7 @@ const Default = {
 }
 
 const DefaultType = {
-  offset: '(number|string|function)',
+  offset: '(array|string|function)',
   flip: 'boolean',
   boundary: '(string|element)',
   reference: '(string|element|object)',
@@ -298,6 +298,20 @@ class Dropdown extends BaseComponent {
     return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null
   }
 
+  _getOffset() {
+    const { offset } = this._config
+
+    if (typeof offset === 'string') {
+      return offset.split(',').map(val => Number.parseInt(val, 10))
+    }
+
+    if (typeof offset === 'function') {
+      return popperData => offset(popperData, this._element)
+    }
+
+    return offset
+  }
+
   _getPopperConfig() {
     const popperConfig = {
       placement: this._getPlacement(),
@@ -313,6 +327,12 @@ class Dropdown extends BaseComponent {
         options: {
           fallbackPlacements: ['top', 'right', 'bottom', 'left']
         }
+      },
+      {
+        name: 'offset',
+        options: {
+          offset: this._getOffset()
+        }
       }]
     }
 
index cc41396034cb853e89abeb255e2bddf3b27e8b2a..8b477ba38f8084263ac5c788b16d5ebd030d0489 100644 (file)
@@ -54,6 +54,54 @@ describe('Dropdown', () => {
       expect(dropdown.toggle).toHaveBeenCalled()
     })
 
+    it('should create offset modifier correctly when offset option is a function', 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 getOffset = jasmine.createSpy('getOffset').and.returnValue([10, 20])
+      const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
+      const dropdown = new Dropdown(btnDropdown, {
+        offset: getOffset,
+        popperConfig: {
+          onFirstUpdate: state => {
+            expect(getOffset).toHaveBeenCalledWith({
+              popper: state.rects.popper,
+              reference: state.rects.reference,
+              placement: state.placement
+            }, btnDropdown)
+            done()
+          }
+        }
+      })
+      const offset = dropdown._getOffset()
+
+      expect(typeof offset).toEqual('function')
+
+      dropdown.show()
+    })
+
+    it('should create offset modifier correctly when offset option is a string into data attribute', () => {
+      fixtureEl.innerHTML = [
+        '<div class="dropdown">',
+        '  <button class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="10,20">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 dropdown = new Dropdown(btnDropdown)
+
+      expect(dropdown._getOffset()).toEqual([10, 20])
+    })
+
     it('should allow to pass config to Popper with `popperConfig`', () => {
       fixtureEl.innerHTML = [
         '<div class="dropdown">',
index a50dcf0f5c00621750594ea940e912354dc5a657..b2abbc7bd8741dfcb4218c2c908868ea6f239e86 100644 (file)
@@ -896,6 +896,16 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
       <td><code>'dynamic'</code></td>
       <td>By default, we use Popper for dynamic positioning. Disable this with <code>static</code>.</td>
     </tr>
+    <tr>
+      <td><code>offset</code></td>
+      <td>array | string | function</td>
+      <td><code>[0, 0]</code></td>
+      <td>
+        <p>Offset of the dropdown relative to its target.</p>
+        <p>When a function is used to determine the offset, it is called with an object containing the <code>popper</code> instance, the <code>refecence</code> Element and the <code>placement</code> as its first argument. The function must return an array with two numbers: <code>[<a href="https://popper.js.org/docs/v2/modifiers/offset/#skidding-1">skidding</a>, <a href="https://popper.js.org/docs/v2/modifiers/offset/#distance-1">distance</a>]</code>. The triggering element DOM node is passed as the second argument.</p>
+        <p>For more information refer to Popper.js's <a href="https://popper.js.org/docs/v2/modifiers/offset/#options">offset docs</a>.</p>
+      </td>
+    </tr>
     <tr>
       <td><code>popperConfig</code></td>
       <td>null | object</td>