]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
allow to pass popper.js configuration for tooltip/popover and dropdown
authorJohann-S <johann.servoire@gmail.com>
Wed, 14 Aug 2019 15:27:58 +0000 (17:27 +0200)
committerXhmikosR <xhmikosr@gmail.com>
Sun, 18 Aug 2019 14:19:36 +0000 (17:19 +0300)
js/src/dropdown/dropdown.js
js/src/dropdown/dropdown.spec.js
js/src/tooltip/tooltip.js
js/src/tooltip/tooltip.spec.js
site/content/docs/4.3/components/dropdowns.md
site/content/docs/4.3/components/popovers.md
site/content/docs/4.3/components/tooltips.md

index 2c30ba740a807661ad8adec4768b807a999c349d..26bcf2aa3ac416082a81feaf9f2786b3767d7b98 100644 (file)
@@ -83,7 +83,8 @@ const Default = {
   flip: true,
   boundary: 'scrollParent',
   reference: 'toggle',
-  display: 'dynamic'
+  display: 'dynamic',
+  popperConfig: null
 }
 
 const DefaultType = {
@@ -91,7 +92,8 @@ const DefaultType = {
   flip: 'boolean',
   boundary: '(string|element)',
   reference: '(string|element)',
-  display: 'string'
+  display: 'string',
+  popperConfig: '(null|object)'
 }
 
 /**
@@ -339,7 +341,7 @@ class Dropdown {
   }
 
   _getPopperConfig() {
-    const popperConfig = {
+    let popperConfig = {
       placement: this._getPlacement(),
       modifiers: {
         offset: this._getOffset(),
@@ -359,6 +361,13 @@ class Dropdown {
       }
     }
 
+    if (this._config.popperConfig) {
+      popperConfig = {
+        ...popperConfig,
+        ...this._config.popperConfig
+      }
+    }
+
     return popperConfig
   }
 
index 92d8fea0331d0bcaf8b5ed4ae86a623f41a62ac4..e99e992f3d06f05b129bd1526591d648f95f2915 100644 (file)
@@ -99,6 +99,28 @@ describe('Dropdown', () => {
 
       expect(dropdown.toggle).toHaveBeenCalled()
     })
+
+    it('should allow to pass config to popper.js thanks to popperConfig', () => {
+      fixtureEl.innerHTML = [
+        '<div class="dropdown">',
+        '  <button href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>',
+        '  <div class="dropdown-menu">',
+        '    <a class="dropdown-item" href="#">Secondary link</a>',
+        '  </div>',
+        '</div>'
+      ].join('')
+
+      const btnDropdown = fixtureEl.querySelector('[data-toggle="dropdown"]')
+      const dropdown = new Dropdown(btnDropdown, {
+        popperConfig: {
+          placement: 'left'
+        }
+      })
+
+      const popperConfig = dropdown._getPopperConfig()
+
+      expect(popperConfig.placement).toEqual('left')
+    })
   })
 
   describe('toggle', () => {
index 33f0173a3f8e00c9ab4aa7efade1542b8c1722af..8bf998468c79dc3d69c17f214dc4f8c934a2be62 100644 (file)
@@ -56,7 +56,8 @@ const DefaultType = {
   boundary: '(string|element)',
   sanitize: 'boolean',
   sanitizeFn: '(null|function)',
-  whiteList: 'object'
+  whiteList: 'object',
+  popperConfig: '(null|object)'
 }
 
 const AttachmentMap = {
@@ -84,7 +85,8 @@ const Default = {
   boundary: 'scrollParent',
   sanitize: true,
   sanitizeFn: null,
-  whiteList: DefaultWhitelist
+  whiteList: DefaultWhitelist,
+  popperConfig: null
 }
 
 const HoverState = {
@@ -129,10 +131,6 @@ const Trigger = {
 
 class Tooltip {
   constructor(element, config) {
-    /**
-     * Check for Popper dependency
-     * Popper - https://popper.js.org
-     */
     if (typeof Popper === 'undefined') {
       throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org)')
     }
@@ -247,7 +245,7 @@ class Tooltip {
     this._timeout = null
     this._hoverState = null
     this._activeTrigger = null
-    if (this._popper !== null) {
+    if (this._popper) {
       this._popper.destroy()
     }
 
@@ -301,27 +299,7 @@ class Tooltip {
 
       EventHandler.trigger(this.element, this.constructor.Event.INSERTED)
 
-      this._popper = new Popper(this.element, tip, {
-        placement: attachment,
-        modifiers: {
-          offset: this._getOffset(),
-          flip: {
-            behavior: this.config.fallbackPlacement
-          },
-          arrow: {
-            element: `.${this.constructor.NAME}-arrow`
-          },
-          preventOverflow: {
-            boundariesElement: this.config.boundary
-          }
-        },
-        onCreate: data => {
-          if (data.originalPlacement !== data.placement) {
-            this._handlePopperPlacementChange(data)
-          }
-        },
-        onUpdate: data => this._handlePopperPlacementChange(data)
-      })
+      this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment))
 
       tip.classList.add(ClassName.SHOW)
 
@@ -482,6 +460,40 @@ class Tooltip {
 
   // Private
 
+  _getPopperConfig(attachment) {
+    const defaultBsConfig = {
+      placement: attachment,
+      modifiers: {
+        offset: this._getOffset(),
+        flip: {
+          behavior: this.config.fallbackPlacement
+        },
+        arrow: {
+          element: `.${this.constructor.NAME}-arrow`
+        },
+        preventOverflow: {
+          boundariesElement: this.config.boundary
+        }
+      },
+      onCreate: data => {
+        if (data.originalPlacement !== data.placement) {
+          this._handlePopperPlacementChange(data)
+        }
+      },
+      onUpdate: data => this._handlePopperPlacementChange(data)
+    }
+
+    let resultConfig = defaultBsConfig
+    if (this.config.popperConfig) {
+      resultConfig = {
+        ...defaultBsConfig,
+        ...this.config.popperConfig
+      }
+    }
+
+    return resultConfig
+  }
+
   _addAttachmentClass(attachment) {
     this.getTipElement().classList.add(`${CLASS_PREFIX}-${attachment}`)
   }
index 1e858d369ae5601e2eab66786390a1b9ab2b7ec4..e4bddcf0034d77e898392f7a2ed6090c27df8064 100644 (file)
@@ -108,6 +108,21 @@ describe('Tooltip', () => {
 
       tooltipInContainerEl.click()
     })
+
+    it('should allow to pass config to popper.js thanks to popperConfig', () => {
+      fixtureEl.innerHTML = '<a href="#" rel="tooltip"/>'
+
+      const tooltipEl = fixtureEl.querySelector('a')
+      const tooltip = new Tooltip(tooltipEl, {
+        popperConfig: {
+          placement: 'left'
+        }
+      })
+
+      const popperConfig = tooltip._getPopperConfig('top')
+
+      expect(popperConfig.placement).toEqual('left')
+    })
   })
 
   describe('enable', () => {
index 42bc1bb56ca66f7992f06481d7642831df40178f..6d0f094b572d5a0a3619dfaf047d82b9a9620727 100644 (file)
@@ -855,6 +855,12 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
       <td>'dynamic'</td>
       <td>By default, we use Popper.js for dynamic positioning. Disable this with <code>static</code>.</td>
     </tr>
+    <tr>
+      <td>popperConfig</td>
+      <td>null | object</td>
+      <td>null</td>
+      <td>To change Bootstrap default Popper.js config, see <a href="https://popper.js.org/popper-documentation.html#Popper.Defaults">Popper.js configuration</a></td>
+    </tr>
   </tbody>
 </table>
 
index dfd4904e06ec7ef8763a620f777311b57b1833bb..04ba2f15ce6e0b60eeb80dec7af54fa3a5ebd990 100644 (file)
@@ -281,6 +281,12 @@ Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` opti
       <td>null</td>
       <td>Here you can supply your own sanitize function. This can be useful if you prefer to use a dedicated library to perform sanitization.</td>
     </tr>
+    <tr>
+      <td>popperConfig</td>
+      <td>null | object</td>
+      <td>null</td>
+      <td>To change Bootstrap default Popper.js config, see <a href="https://popper.js.org/popper-documentation.html#Popper.Defaults">Popper.js configuration</a></td>
+    </tr>
   </tbody>
 </table>
 
index 373cc45d52faee2eb7a0f32c0985bbd109af8e30..880e7618512669d32aa398d8ba072bb1fb766e82 100644 (file)
@@ -278,6 +278,12 @@ Note that for security reasons the `sanitize`, `sanitizeFn` and `whiteList` opti
       <td>null</td>
       <td>Here you can supply your own sanitize function. This can be useful if you prefer to use a dedicated library to perform sanitization.</td>
     </tr>
+    <tr>
+      <td>popperConfig</td>
+      <td>null | object</td>
+      <td>null</td>
+      <td>To change Bootstrap default Popper.js config, see <a href="https://popper.js.org/popper-documentation.html#Popper.Defaults">Popper.js configuration</a></td>
+    </tr>
   </tbody>
 </table>