]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Add `getOrCreateInstance` method in base-component (#33276)
authorGeoSot <geo.sotis@gmail.com>
Thu, 3 Jun 2021 15:53:27 +0000 (18:53 +0300)
committerGitHub <noreply@github.com>
Thu, 3 Jun 2021 15:53:27 +0000 (18:53 +0300)
Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
Co-authored-by: XhmikosR <xhmikosr@gmail.com>
39 files changed:
js/src/alert.js
js/src/base-component.js
js/src/button.js
js/src/carousel.js
js/src/collapse.js
js/src/dropdown.js
js/src/modal.js
js/src/offcanvas.js
js/src/popover.js
js/src/scrollspy.js
js/src/tab.js
js/src/toast.js
js/src/tooltip.js
js/tests/unit/alert.spec.js
js/tests/unit/base-component.spec.js
js/tests/unit/button.spec.js
js/tests/unit/carousel.spec.js
js/tests/unit/collapse.spec.js
js/tests/unit/dropdown.spec.js
js/tests/unit/modal.spec.js
js/tests/unit/offcanvas.spec.js
js/tests/unit/popover.spec.js
js/tests/unit/scrollspy.spec.js
js/tests/unit/tab.spec.js
js/tests/unit/toast.spec.js
js/tests/unit/tooltip.spec.js
site/content/docs/5.0/components/alerts.md
site/content/docs/5.0/components/buttons.md
site/content/docs/5.0/components/carousel.md
site/content/docs/5.0/components/collapse.md
site/content/docs/5.0/components/dropdowns.md
site/content/docs/5.0/components/list-group.md
site/content/docs/5.0/components/modal.md
site/content/docs/5.0/components/navs-tabs.md
site/content/docs/5.0/components/offcanvas.md
site/content/docs/5.0/components/popovers.md
site/content/docs/5.0/components/scrollspy.md
site/content/docs/5.0/components/toasts.md
site/content/docs/5.0/components/tooltips.md

index 679a90cdb475ecd7bfcfbf99c9b4cb47c3ed656e..e5e5e2a5d24dce02d024cfb6f36dab39f4949c8f 100644 (file)
@@ -9,7 +9,6 @@ import {
   defineJQueryPlugin,
   getElementFromSelector
 } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import BaseComponent from './base-component'
 
@@ -87,11 +86,7 @@ class Alert extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      let data = Data.get(this, DATA_KEY)
-
-      if (!data) {
-        data = new Alert(this)
-      }
+      const data = Alert.getOrCreateInstance(this)
 
       if (config === 'close') {
         data[config](this)
index 368cc99c88882743c94dcf22f4ea022c1721bf59..cadd53d26a013f7b5080462631805f6a4a47f8c1 100644 (file)
@@ -51,6 +51,10 @@ class BaseComponent {
     return Data.get(element, this.DATA_KEY)
   }
 
+  static getOrCreateInstance(element, config = {}) {
+    return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
+  }
+
   static get VERSION() {
     return VERSION
   }
index 6ef753136705bb13833f4e6bc17245d96ac6f484..c0e6b5d2b1da4fed4d805a007a69ffcc9a68247f 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 import { defineJQueryPlugin } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import BaseComponent from './base-component'
 
@@ -51,11 +50,7 @@ class Button extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      let data = Data.get(this, DATA_KEY)
-
-      if (!data) {
-        data = new Button(this)
-      }
+      const data = Button.getOrCreateInstance(this)
 
       if (config === 'toggle') {
         data[config]()
@@ -74,11 +69,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
   event.preventDefault()
 
   const button = event.target.closest(SELECTOR_DATA_TOGGLE)
-
-  let data = Data.get(button, DATA_KEY)
-  if (!data) {
-    data = new Button(button)
-  }
+  const data = Button.getOrCreateInstance(button)
 
   data.toggle()
 })
index 7d197ab1eef68ac90606f1d38ef59f9e2ff85504..a956ebc8bbc1eca8adbb0d16a205c88397f9ef32 100644 (file)
@@ -15,7 +15,6 @@ import {
   triggerTransitionEnd,
   typeCheckConfig
 } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import Manipulator from './dom/manipulator'
 import SelectorEngine from './dom/selector-engine'
@@ -219,7 +218,8 @@ class Carousel extends BaseComponent {
   _getConfig(config) {
     config = {
       ...Default,
-      ...config
+      ...Manipulator.getDataAttributes(this._element),
+      ...(typeof config === 'object' ? config : {})
     }
     typeCheckConfig(NAME, config, DefaultType)
     return config
@@ -496,25 +496,11 @@ class Carousel extends BaseComponent {
   // Static
 
   static carouselInterface(element, config) {
-    let data = Data.get(element, DATA_KEY)
-    let _config = {
-      ...Default,
-      ...Manipulator.getDataAttributes(element)
-    }
-
-    if (typeof config === 'object') {
-      _config = {
-        ..._config,
-        ...config
-      }
-    }
+    const data = Carousel.getOrCreateInstance(element, config)
 
+    const { _config } = data
     const action = typeof config === 'string' ? config : _config.slide
 
-    if (!data) {
-      data = new Carousel(element, _config)
-    }
-
     if (typeof config === 'number') {
       data.to(config)
     } else if (typeof action === 'string') {
@@ -555,7 +541,7 @@ class Carousel extends BaseComponent {
     Carousel.carouselInterface(target, config)
 
     if (slideIndex) {
-      Data.get(target, DATA_KEY).to(slideIndex)
+      Carousel.getInstance(target).to(slideIndex)
     }
 
     event.preventDefault()
@@ -574,7 +560,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
   const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE)
 
   for (let i = 0, len = carousels.length; i < len; i++) {
-    Carousel.carouselInterface(carousels[i], Data.get(carousels[i], DATA_KEY))
+    Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]))
   }
 })
 
index fd85fbde2d13bbfe5021528fddcd4ad17fb301c9..2d12ef57f0390202d69cc354df70b28995cb72dd 100644 (file)
@@ -145,7 +145,7 @@ class Collapse extends BaseComponent {
     const container = SelectorEngine.findOne(this._selector)
     if (actives) {
       const tempActiveData = actives.find(elem => container !== elem)
-      activesData = tempActiveData ? Data.get(tempActiveData, DATA_KEY) : null
+      activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null
 
       if (activesData && activesData._isTransitioning) {
         return
@@ -310,7 +310,7 @@ class Collapse extends BaseComponent {
   // Static
 
   static collapseInterface(element, config) {
-    let data = Data.get(element, DATA_KEY)
+    let data = Collapse.getInstance(element)
     const _config = {
       ...Default,
       ...Manipulator.getDataAttributes(element),
@@ -358,7 +358,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
   const selectorElements = SelectorEngine.find(selector)
 
   selectorElements.forEach(element => {
-    const data = Data.get(element, DATA_KEY)
+    const data = Collapse.getInstance(element)
     let config
     if (data) {
       // update parent attribute
index 34beb6512916de9d1d140cebf6923b65f8c13828..e79ac45910216b008dab736ea2e5894d0dc00852 100644 (file)
@@ -19,7 +19,6 @@ import {
   getNextActiveElement,
   typeCheckConfig
 } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import Manipulator from './dom/manipulator'
 import SelectorEngine from './dom/selector-engine'
@@ -369,12 +368,7 @@ class Dropdown extends BaseComponent {
   // Static
 
   static dropdownInterface(element, config) {
-    let data = Data.get(element, DATA_KEY)
-    const _config = typeof config === 'object' ? config : null
-
-    if (!data) {
-      data = new Dropdown(element, _config)
-    }
+    const data = Dropdown.getOrCreateInstance(element, config)
 
     if (typeof config === 'string') {
       if (typeof data[config] === 'undefined') {
@@ -399,7 +393,7 @@ class Dropdown extends BaseComponent {
     const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
 
     for (let i = 0, len = toggles.length; i < len; i++) {
-      const context = Data.get(toggles[i], DATA_KEY)
+      const context = Dropdown.getInstance(toggles[i])
       if (!context || context._config.autoClose === false) {
         continue
       }
index e8eee3b4d00a0fdee4b17ff92a7b379aea58adea..74b608303f9e79c92b176a17b0029c4c0dded8f7 100644 (file)
@@ -209,7 +209,7 @@ class Modal extends BaseComponent {
     config = {
       ...Default,
       ...Manipulator.getDataAttributes(this._element),
-      ...config
+      ...(typeof config === 'object' ? config : {})
     }
     typeCheckConfig(NAME, config, DefaultType)
     return config
@@ -389,7 +389,7 @@ class Modal extends BaseComponent {
 
   static jQueryInterface(config, relatedTarget) {
     return this.each(function () {
-      const data = Modal.getInstance(this) || new Modal(this, typeof config === 'object' ? config : {})
+      const data = Modal.getOrCreateInstance(this, config)
 
       if (typeof config !== 'string') {
         return
@@ -430,7 +430,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
     })
   })
 
-  const data = Modal.getInstance(target) || new Modal(target)
+  const data = Modal.getOrCreateInstance(target)
 
   data.toggle(this)
 })
index fed892f4c77867f5d7b09ececdfb8e92e165037f..f990ff1998a09c6953aac5b0b6327e4df88c7320 100644 (file)
@@ -13,7 +13,6 @@ import {
   typeCheckConfig
 } from './util/index'
 import { hide as scrollBarHide, reset as scrollBarReset } from './util/scrollbar'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import BaseComponent from './base-component'
 import SelectorEngine from './dom/selector-engine'
@@ -211,7 +210,7 @@ class Offcanvas extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      const data = Data.get(this, DATA_KEY) || new Offcanvas(this, typeof config === 'object' ? config : {})
+      const data = Offcanvas.getOrCreateInstance(this, config)
 
       if (typeof config !== 'string') {
         return
@@ -256,14 +255,13 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
     Offcanvas.getInstance(allReadyOpen).hide()
   }
 
-  const data = Data.get(target, DATA_KEY) || new Offcanvas(target)
-
+  const data = Offcanvas.getOrCreateInstance(target)
   data.toggle(this)
 })
 
-EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
-  SelectorEngine.find(OPEN_SELECTOR).forEach(el => (Data.get(el, DATA_KEY) || new Offcanvas(el)).show())
-})
+EventHandler.on(window, EVENT_LOAD_DATA_API, () =>
+  SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show())
+)
 
 /**
  * ------------------------------------------------------------------------
index 929391392a50aa6e6c71c154ee76ac8ad11f03b3..457760c14ce0a02f63595c7f6578cb02219fcb2e 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 import { defineJQueryPlugin } from './util/index'
-import Data from './dom/data'
 import SelectorEngine from './dom/selector-engine'
 import Tooltip from './tooltip'
 
@@ -146,13 +145,7 @@ class Popover extends Tooltip {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      let data = Data.get(this, DATA_KEY)
-      const _config = typeof config === 'object' ? config : null
-
-      if (!data) {
-        data = new Popover(this, _config)
-        Data.set(this, DATA_KEY, data)
-      }
+      const data = Popover.getOrCreateInstance(this, config)
 
       if (typeof config === 'string') {
         if (typeof data[config] === 'undefined') {
index 3297c45c234dd925f105b66bd81024b9acb82540..b7ea2a4e5ffb82ea6f9433e5b36e554f9543a110 100644 (file)
@@ -270,7 +270,7 @@ class ScrollSpy extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      const data = ScrollSpy.getInstance(this) || new ScrollSpy(this, typeof config === 'object' ? config : {})
+      const data = ScrollSpy.getOrCreateInstance(this, config)
 
       if (typeof config !== 'string') {
         return
index 51deb170f89a14382622287d038aed9a099bd893..6de48e4cd0c25d8210e71f2bb7b69faa70b7b015 100644 (file)
@@ -11,7 +11,6 @@ import {
   isDisabled,
   reflow
 } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import SelectorEngine from './dom/selector-engine'
 import BaseComponent from './base-component'
@@ -181,7 +180,7 @@ class Tab extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      const data = Data.get(this, DATA_KEY) || new Tab(this)
+      const data = Tab.getOrCreateInstance(this)
 
       if (typeof config === 'string') {
         if (typeof data[config] === 'undefined') {
@@ -209,7 +208,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
     return
   }
 
-  const data = Data.get(this, DATA_KEY) || new Tab(this)
+  const data = Tab.getOrCreateInstance(this)
   data.show()
 })
 
index 40cd40d9a9520ae07fb1fb08793b409ab9020ca4..8aeaa0148334f8501ffae5d2037e40a52015c105 100644 (file)
@@ -10,7 +10,6 @@ import {
   reflow,
   typeCheckConfig
 } from './util/index'
-import Data from './dom/data'
 import EventHandler from './dom/event-handler'
 import Manipulator from './dom/manipulator'
 import BaseComponent from './base-component'
@@ -218,12 +217,7 @@ class Toast extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      let data = Data.get(this, DATA_KEY)
-      const _config = typeof config === 'object' && config
-
-      if (!data) {
-        data = new Toast(this, _config)
-      }
+      const data = Toast.getOrCreateInstance(this, config)
 
       if (typeof config === 'string') {
         if (typeof data[config] === 'undefined') {
index 2eb91965b259b1412ec5e6998711f6fbb58839dc..78b7c478baf8c00750f10bb04d9816ce61539a7e 100644 (file)
@@ -722,12 +722,7 @@ class Tooltip extends BaseComponent {
 
   static jQueryInterface(config) {
     return this.each(function () {
-      let data = Data.get(this, DATA_KEY)
-      const _config = typeof config === 'object' && config
-
-      if (!data) {
-        data = new Tooltip(this, _config)
-      }
+      const data = Tooltip.getOrCreateInstance(this, config)
 
       if (typeof config === 'string') {
         if (typeof data[config] === 'undefined') {
index 29b99d7921e9922ba75c46cf0a25852e37ae36e8..53dc0700c90d29d2fffc3de654298624c760f4cc 100644 (file)
@@ -207,4 +207,26 @@ describe('Alert', () => {
       expect(Alert.getInstance(div)).toEqual(null)
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return alert instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const alert = new Alert(div)
+
+      expect(Alert.getOrCreateInstance(div)).toEqual(alert)
+      expect(Alert.getInstance(div)).toEqual(Alert.getOrCreateInstance(div, {}))
+      expect(Alert.getOrCreateInstance(div)).toBeInstanceOf(Alert)
+    })
+
+    it('should return new instance when there is no alert instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Alert.getInstance(div)).toEqual(null)
+      expect(Alert.getOrCreateInstance(div)).toBeInstanceOf(Alert)
+    })
+  })
 })
index 7a849be06274838eb0cd5516dd80495160909c9a..1000f2841d7e27442f5fc0be844e1561ae5fb278 100644 (file)
@@ -112,5 +112,22 @@ describe('Base Component', () => {
         expect(DummyClass.getInstance(div)).toEqual(null)
       })
     })
+    describe('getOrCreateInstance', () => {
+      it('should return an instance', () => {
+        createInstance()
+
+        expect(DummyClass.getOrCreateInstance(element)).toEqual(instance)
+        expect(DummyClass.getInstance(element)).toEqual(DummyClass.getOrCreateInstance(element, {}))
+        expect(DummyClass.getOrCreateInstance(element)).toBeInstanceOf(DummyClass)
+      })
+
+      it('should return new instance when there is no alert instance', () => {
+        fixtureEl.innerHTML = '<div id="foo"></div>'
+        element = fixtureEl.querySelector('#foo')
+
+        expect(DummyClass.getInstance(element)).toEqual(null)
+        expect(DummyClass.getOrCreateInstance(element)).toBeInstanceOf(DummyClass)
+      })
+    })
   })
 })
index 90cf766144661b52b3d9c5e345fcc46c995f12d1..be99177e87301a07aceae1b1f60f2efeaa4add2c 100644 (file)
@@ -164,4 +164,26 @@ describe('Button', () => {
       expect(Button.getInstance(div)).toEqual(null)
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return button instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const button = new Button(div)
+
+      expect(Button.getOrCreateInstance(div)).toEqual(button)
+      expect(Button.getInstance(div)).toEqual(Button.getOrCreateInstance(div, {}))
+      expect(Button.getOrCreateInstance(div)).toBeInstanceOf(Button)
+    })
+
+    it('should return new instance when there is no button instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Button.getInstance(div)).toEqual(null)
+      expect(Button.getOrCreateInstance(div)).toBeInstanceOf(Button)
+    })
+  })
 })
index 324ff19a707422a295a2c0cf77743f57a9f48c3a..5120cc601550bbadb87b09e71d217672d2df26a6 100644 (file)
@@ -1202,6 +1202,60 @@ describe('Carousel', () => {
     })
   })
 
+  describe('getOrCreateInstance', () => {
+    it('should return carousel instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const carousel = new Carousel(div)
+
+      expect(Carousel.getOrCreateInstance(div)).toEqual(carousel)
+      expect(Carousel.getInstance(div)).toEqual(Carousel.getOrCreateInstance(div, {}))
+      expect(Carousel.getOrCreateInstance(div)).toBeInstanceOf(Carousel)
+    })
+
+    it('should return new instance when there is no carousel instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Carousel.getInstance(div)).toEqual(null)
+      expect(Carousel.getOrCreateInstance(div)).toBeInstanceOf(Carousel)
+    })
+
+    it('should return new instance when there is no carousel instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Carousel.getInstance(div)).toEqual(null)
+      const carousel = Carousel.getOrCreateInstance(div, {
+        interval: 1
+      })
+      expect(carousel).toBeInstanceOf(Carousel)
+
+      expect(carousel._config.interval).toEqual(1)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const carousel = new Carousel(div, {
+        interval: 1
+      })
+      expect(Carousel.getInstance(div)).toEqual(carousel)
+
+      const carousel2 = Carousel.getOrCreateInstance(div, {
+        interval: 2
+      })
+      expect(carousel).toBeInstanceOf(Carousel)
+      expect(carousel2).toEqual(carousel)
+
+      expect(carousel2._config.interval).toEqual(1)
+    })
+  })
+
   describe('jQueryInterface', () => {
     it('should create a carousel', () => {
       fixtureEl.innerHTML = '<div></div>'
index 0997ae7c205d08ba52277c471b01e835b354e417..11d8d52bf5d0f0ee703156cafefeedf9b96fbe1a 100644 (file)
@@ -862,4 +862,58 @@ describe('Collapse', () => {
       expect(Collapse.getInstance(div)).toEqual(null)
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return collapse instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const collapse = new Collapse(div)
+
+      expect(Collapse.getOrCreateInstance(div)).toEqual(collapse)
+      expect(Collapse.getInstance(div)).toEqual(Collapse.getOrCreateInstance(div, {}))
+      expect(Collapse.getOrCreateInstance(div)).toBeInstanceOf(Collapse)
+    })
+
+    it('should return new instance when there is no collapse instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Collapse.getInstance(div)).toEqual(null)
+      expect(Collapse.getOrCreateInstance(div)).toBeInstanceOf(Collapse)
+    })
+
+    it('should return new instance when there is no collapse instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Collapse.getInstance(div)).toEqual(null)
+      const collapse = Collapse.getOrCreateInstance(div, {
+        toggle: false
+      })
+      expect(collapse).toBeInstanceOf(Collapse)
+
+      expect(collapse._config.toggle).toEqual(false)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const collapse = new Collapse(div, {
+        toggle: false
+      })
+      expect(Collapse.getInstance(div)).toEqual(collapse)
+
+      const collapse2 = Collapse.getOrCreateInstance(div, {
+        toggle: true
+      })
+      expect(collapse).toBeInstanceOf(Collapse)
+      expect(collapse2).toEqual(collapse)
+
+      expect(collapse2._config.toggle).toEqual(false)
+    })
+  })
 })
index 390cddfbfaee25f7161075be62ace42893322406..9703eaab1962d593d7b1bbba19e171a0be8adfef 100644 (file)
@@ -1991,6 +1991,60 @@ describe('Dropdown', () => {
     })
   })
 
+  describe('getOrCreateInstance', () => {
+    it('should return dropdown instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const dropdown = new Dropdown(div)
+
+      expect(Dropdown.getOrCreateInstance(div)).toEqual(dropdown)
+      expect(Dropdown.getInstance(div)).toEqual(Dropdown.getOrCreateInstance(div, {}))
+      expect(Dropdown.getOrCreateInstance(div)).toBeInstanceOf(Dropdown)
+    })
+
+    it('should return new instance when there is no dropdown instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Dropdown.getInstance(div)).toEqual(null)
+      expect(Dropdown.getOrCreateInstance(div)).toBeInstanceOf(Dropdown)
+    })
+
+    it('should return new instance when there is no dropdown instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Dropdown.getInstance(div)).toEqual(null)
+      const dropdown = Dropdown.getOrCreateInstance(div, {
+        display: 'dynamic'
+      })
+      expect(dropdown).toBeInstanceOf(Dropdown)
+
+      expect(dropdown._config.display).toEqual('dynamic')
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const dropdown = new Dropdown(div, {
+        display: 'dynamic'
+      })
+      expect(Dropdown.getInstance(div)).toEqual(dropdown)
+
+      const dropdown2 = Dropdown.getOrCreateInstance(div, {
+        display: 'static'
+      })
+      expect(dropdown).toBeInstanceOf(Dropdown)
+      expect(dropdown2).toEqual(dropdown)
+
+      expect(dropdown2._config.display).toEqual('dynamic')
+    })
+  })
+
   it('should open dropdown when pressing keydown or keyup', done => {
     fixtureEl.innerHTML = [
       '<div class="dropdown">',
index 2974495cacc691b4ed69a7bcc67ea58ddce4d990..0056e82f63db07053b7ba2e934226465726b2b50 100644 (file)
@@ -1058,4 +1058,58 @@ describe('Modal', () => {
       expect(Modal.getInstance(div)).toBeNull()
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return modal instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const modal = new Modal(div)
+
+      expect(Modal.getOrCreateInstance(div)).toEqual(modal)
+      expect(Modal.getInstance(div)).toEqual(Modal.getOrCreateInstance(div, {}))
+      expect(Modal.getOrCreateInstance(div)).toBeInstanceOf(Modal)
+    })
+
+    it('should return new instance when there is no modal instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Modal.getInstance(div)).toEqual(null)
+      expect(Modal.getOrCreateInstance(div)).toBeInstanceOf(Modal)
+    })
+
+    it('should return new instance when there is no modal instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Modal.getInstance(div)).toEqual(null)
+      const modal = Modal.getOrCreateInstance(div, {
+        backdrop: true
+      })
+      expect(modal).toBeInstanceOf(Modal)
+
+      expect(modal._config.backdrop).toEqual(true)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const modal = new Modal(div, {
+        backdrop: true
+      })
+      expect(Modal.getInstance(div)).toEqual(modal)
+
+      const modal2 = Modal.getOrCreateInstance(div, {
+        backdrop: false
+      })
+      expect(modal).toBeInstanceOf(Modal)
+      expect(modal2).toEqual(modal)
+
+      expect(modal2._config.backdrop).toEqual(true)
+    })
+  })
 })
index dfb6c429e2e56618e02b3c97dbeee5c1510a68e3..0f67fef9d1fa74d0ad9a0307c5237fa0d5e39d09 100644 (file)
@@ -620,38 +620,6 @@ describe('Offcanvas', () => {
       }).toThrowError(TypeError, `No method named "${action}"`)
     })
 
-    it('should throw error on protected method', () => {
-      fixtureEl.innerHTML = '<div></div>'
-
-      const div = fixtureEl.querySelector('div')
-      const action = '_getConfig'
-
-      jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
-      jQueryMock.elements = [div]
-
-      try {
-        jQueryMock.fn.offcanvas.call(jQueryMock, action)
-      } catch (error) {
-        expect(error.message).toEqual(`No method named "${action}"`)
-      }
-    })
-
-    it('should throw error if method "constructor" is being called', () => {
-      fixtureEl.innerHTML = '<div></div>'
-
-      const div = fixtureEl.querySelector('div')
-      const action = 'constructor'
-
-      jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
-      jQueryMock.elements = [div]
-
-      try {
-        jQueryMock.fn.offcanvas.call(jQueryMock, action)
-      } catch (error) {
-        expect(error.message).toEqual(`No method named "${action}"`)
-      }
-    })
-
     it('should call offcanvas method', () => {
       fixtureEl.innerHTML = '<div></div>'
 
@@ -675,8 +643,6 @@ describe('Offcanvas', () => {
       jQueryMock.elements = [div]
 
       jQueryMock.fn.offcanvas.call(jQueryMock, { scroll: true })
-      spyOn(Offcanvas.prototype, 'constructor')
-      expect(Offcanvas.prototype.constructor).not.toHaveBeenCalledWith(div, { scroll: true })
 
       const offcanvas = Offcanvas.getInstance(div)
       expect(offcanvas).not.toBeNull()
@@ -703,4 +669,58 @@ describe('Offcanvas', () => {
       expect(Offcanvas.getInstance(div)).toBeNull()
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return offcanvas instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const offcanvas = new Offcanvas(div)
+
+      expect(Offcanvas.getOrCreateInstance(div)).toEqual(offcanvas)
+      expect(Offcanvas.getInstance(div)).toEqual(Offcanvas.getOrCreateInstance(div, {}))
+      expect(Offcanvas.getOrCreateInstance(div)).toBeInstanceOf(Offcanvas)
+    })
+
+    it('should return new instance when there is no Offcanvas instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Offcanvas.getInstance(div)).toEqual(null)
+      expect(Offcanvas.getOrCreateInstance(div)).toBeInstanceOf(Offcanvas)
+    })
+
+    it('should return new instance when there is no offcanvas instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Offcanvas.getInstance(div)).toEqual(null)
+      const offcanvas = Offcanvas.getOrCreateInstance(div, {
+        scroll: true
+      })
+      expect(offcanvas).toBeInstanceOf(Offcanvas)
+
+      expect(offcanvas._config.scroll).toEqual(true)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const offcanvas = new Offcanvas(div, {
+        scroll: true
+      })
+      expect(Offcanvas.getInstance(div)).toEqual(offcanvas)
+
+      const offcanvas2 = Offcanvas.getOrCreateInstance(div, {
+        scroll: false
+      })
+      expect(offcanvas).toBeInstanceOf(Offcanvas)
+      expect(offcanvas2).toEqual(offcanvas)
+
+      expect(offcanvas2._config.scroll).toEqual(true)
+    })
+  })
 })
index def0f5f040ac506cd0124ba5242370aac743ffea..f5a163050e8995b08409ab8943f5376b3db7293d 100644 (file)
@@ -287,4 +287,58 @@ describe('Popover', () => {
       expect(Popover.getInstance(popoverEl)).toEqual(null)
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return popover instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const popover = new Popover(div)
+
+      expect(Popover.getOrCreateInstance(div)).toEqual(popover)
+      expect(Popover.getInstance(div)).toEqual(Popover.getOrCreateInstance(div, {}))
+      expect(Popover.getOrCreateInstance(div)).toBeInstanceOf(Popover)
+    })
+
+    it('should return new instance when there is no popover instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Popover.getInstance(div)).toEqual(null)
+      expect(Popover.getOrCreateInstance(div)).toBeInstanceOf(Popover)
+    })
+
+    it('should return new instance when there is no popover instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Popover.getInstance(div)).toEqual(null)
+      const popover = Popover.getOrCreateInstance(div, {
+        placement: 'top'
+      })
+      expect(popover).toBeInstanceOf(Popover)
+
+      expect(popover._config.placement).toEqual('top')
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const popover = new Popover(div, {
+        placement: 'top'
+      })
+      expect(Popover.getInstance(div)).toEqual(popover)
+
+      const popover2 = Popover.getOrCreateInstance(div, {
+        placement: 'bottom'
+      })
+      expect(popover).toBeInstanceOf(Popover)
+      expect(popover2).toEqual(popover)
+
+      expect(popover2._config.placement).toEqual('top')
+    })
+  })
 })
index 6b2a134302be42f42120de8f25459cbb7fcad414..8724b83690b31f17be4915b9359e8c6965deb974 100644 (file)
@@ -684,6 +684,60 @@ describe('ScrollSpy', () => {
     })
   })
 
+  describe('getOrCreateInstance', () => {
+    it('should return scrollspy instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const scrollspy = new ScrollSpy(div)
+
+      expect(ScrollSpy.getOrCreateInstance(div)).toEqual(scrollspy)
+      expect(ScrollSpy.getInstance(div)).toEqual(ScrollSpy.getOrCreateInstance(div, {}))
+      expect(ScrollSpy.getOrCreateInstance(div)).toBeInstanceOf(ScrollSpy)
+    })
+
+    it('should return new instance when there is no scrollspy instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(ScrollSpy.getInstance(div)).toEqual(null)
+      expect(ScrollSpy.getOrCreateInstance(div)).toBeInstanceOf(ScrollSpy)
+    })
+
+    it('should return new instance when there is no scrollspy instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(ScrollSpy.getInstance(div)).toEqual(null)
+      const scrollspy = ScrollSpy.getOrCreateInstance(div, {
+        offset: 1
+      })
+      expect(scrollspy).toBeInstanceOf(ScrollSpy)
+
+      expect(scrollspy._config.offset).toEqual(1)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const scrollspy = new ScrollSpy(div, {
+        offset: 1
+      })
+      expect(ScrollSpy.getInstance(div)).toEqual(scrollspy)
+
+      const scrollspy2 = ScrollSpy.getOrCreateInstance(div, {
+        offset: 2
+      })
+      expect(scrollspy).toBeInstanceOf(ScrollSpy)
+      expect(scrollspy2).toEqual(scrollspy)
+
+      expect(scrollspy2._config.offset).toEqual(1)
+    })
+  })
+
   describe('event handler', () => {
     it('should create scrollspy on window load event', () => {
       fixtureEl.innerHTML = '<div data-bs-spy="scroll"></div>'
index 76d47652585b19630c8d1af784411121a2a7de89..621012c12e8571030b29a2c068fd7700cc64a5da 100644 (file)
@@ -433,6 +433,28 @@ describe('Tab', () => {
     })
   })
 
+  describe('getOrCreateInstance', () => {
+    it('should return tab instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const tab = new Tab(div)
+
+      expect(Tab.getOrCreateInstance(div)).toEqual(tab)
+      expect(Tab.getInstance(div)).toEqual(Tab.getOrCreateInstance(div, {}))
+      expect(Tab.getOrCreateInstance(div)).toBeInstanceOf(Tab)
+    })
+
+    it('should return new instance when there is no tab instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Tab.getInstance(div)).toEqual(null)
+      expect(Tab.getOrCreateInstance(div)).toBeInstanceOf(Tab)
+    })
+  })
+
   describe('data-api', () => {
     it('should create dynamically a tab', done => {
       fixtureEl.innerHTML = [
index 62cfc966defba216ba0d09c2d69429fa3c484654..59d0247b28cac002b3e560432161db01bc6efb9b 100644 (file)
@@ -591,4 +591,58 @@ describe('Toast', () => {
       expect(Toast.getInstance(div)).toEqual(null)
     })
   })
+
+  describe('getOrCreateInstance', () => {
+    it('should return toast instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const toast = new Toast(div)
+
+      expect(Toast.getOrCreateInstance(div)).toEqual(toast)
+      expect(Toast.getInstance(div)).toEqual(Toast.getOrCreateInstance(div, {}))
+      expect(Toast.getOrCreateInstance(div)).toBeInstanceOf(Toast)
+    })
+
+    it('should return new instance when there is no toast instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Toast.getInstance(div)).toEqual(null)
+      expect(Toast.getOrCreateInstance(div)).toBeInstanceOf(Toast)
+    })
+
+    it('should return new instance when there is no toast instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Toast.getInstance(div)).toEqual(null)
+      const toast = Toast.getOrCreateInstance(div, {
+        delay: 1
+      })
+      expect(toast).toBeInstanceOf(Toast)
+
+      expect(toast._config.delay).toEqual(1)
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const toast = new Toast(div, {
+        delay: 1
+      })
+      expect(Toast.getInstance(div)).toEqual(toast)
+
+      const toast2 = Toast.getOrCreateInstance(div, {
+        delay: 2
+      })
+      expect(toast).toBeInstanceOf(Toast)
+      expect(toast2).toEqual(toast)
+
+      expect(toast2._config.delay).toEqual(1)
+    })
+  })
 })
index b5a34bfe0a02ea83e5a981daebcb2b2e64528958..8f8524c8953fb01260e8df8d9b82964fab8df543 100644 (file)
@@ -3,7 +3,7 @@ import EventHandler from '../../src/dom/event-handler'
 import { noop } from '../../src/util/index'
 
 /** Test helpers */
-import { getFixture, clearFixture, jQueryMock, createEvent } from '../helpers/fixture'
+import { clearFixture, createEvent, getFixture, jQueryMock } from '../helpers/fixture'
 
 describe('Tooltip', () => {
   let fixtureEl
@@ -1306,6 +1306,60 @@ describe('Tooltip', () => {
     })
   })
 
+  describe('getOrCreateInstance', () => {
+    it('should return tooltip instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const tooltip = new Tooltip(div)
+
+      expect(Tooltip.getOrCreateInstance(div)).toEqual(tooltip)
+      expect(Tooltip.getInstance(div)).toEqual(Tooltip.getOrCreateInstance(div, {}))
+      expect(Tooltip.getOrCreateInstance(div)).toBeInstanceOf(Tooltip)
+    })
+
+    it('should return new instance when there is no tooltip instance', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Tooltip.getInstance(div)).toEqual(null)
+      expect(Tooltip.getOrCreateInstance(div)).toBeInstanceOf(Tooltip)
+    })
+
+    it('should return new instance when there is no tooltip instance with given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+
+      expect(Tooltip.getInstance(div)).toEqual(null)
+      const tooltip = Tooltip.getOrCreateInstance(div, {
+        title: () => 'test'
+      })
+      expect(tooltip).toBeInstanceOf(Tooltip)
+
+      expect(tooltip.getTitle()).toEqual('test')
+    })
+
+    it('should return the instance when exists without given configuration', () => {
+      fixtureEl.innerHTML = '<div></div>'
+
+      const div = fixtureEl.querySelector('div')
+      const tooltip = new Tooltip(div, {
+        title: () => 'nothing'
+      })
+      expect(Tooltip.getInstance(div)).toEqual(tooltip)
+
+      const tooltip2 = Tooltip.getOrCreateInstance(div, {
+        title: () => 'test'
+      })
+      expect(tooltip).toBeInstanceOf(Tooltip)
+      expect(tooltip2).toEqual(tooltip)
+
+      expect(tooltip2.getTitle()).toEqual('nothing')
+    })
+  })
+
   describe('jQueryInterface', () => {
     it('should create a tooltip', () => {
       fixtureEl.innerHTML = '<div></div>'
index d0c5685a09fb22af3d20aaa2376cce1446a3bb70..a7e52f5f8937fbc36bca486af979742452e0648f 100644 (file)
@@ -209,6 +209,15 @@ This makes an alert listen for click events on descendant elements which have th
         Static method which allows you to get the alert instance associated to a DOM element, you can use it like this: <code>bootstrap.Alert.getInstance(alert)</code>
       </td>
     </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns an alert instance associated to a DOM element or create a new one in case it wasn't initialised.
+        You can use it like this: <code>bootstrap.Alert.getOrCreateInstance(element)</code>
+      </td>
+    </tr>
   </tbody>
 </table>
 
index 063bae1c4190cd776946dd374e1c5c1a9d6422ab..d62d6e2b6506c12d7d5a52d5ab4bb67f23635be2 100644 (file)
@@ -193,6 +193,23 @@ var bsButton = new bootstrap.Button(button)
         Destroys an element's button. (Removes stored data on the DOM element)
       </td>
     </tr>
+    <tr>
+      <td>
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the button instance associated to a DOM element, you can use it like this: <code>bootstrap.Button.getInstance(element)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns a button instance associated to a DOM element or create a new one in case it wasn't initialised.
+        You can use it like this: <code>bootstrap.Button.getOrCreateInstance(element)</code>
+      </td>
+    </tr>
   </tbody>
 </table>
 
index 9ad7294ecc72db756aa9a31ef84e07b17fa2dc59..e106e76c0ece2a8e1b26bd293a990b1b482381a4 100644 (file)
@@ -413,8 +413,21 @@ var carousel = new bootstrap.Carousel(myCarousel, {
       <td>Destroys an element's carousel. (Removes stored data on the DOM element)</td>
     </tr>
     <tr>
-      <td><code>getInstance</code></td>
-      <td>Static method which allows you to get the carousel instance associated with a DOM element.</td>
+      <td>
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the carousel instance associated to a DOM element, you can use it like this: <code>bootstrap.Carousel.getInstance(element)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns a carousel instance associated to a DOM element or create a new one in case it wasn't initialised.
+        You can use it like this: <code>bootstrap.Carousel.getOrCreateInstance(element)</code>
+      </td>
     </tr>
   </tbody>
 </table>
index fe26918c1f13a9e2922a6d620adda5d0637a5107..ac84ca96491ae9eb95f9d5b4bdeac25e680ef5e6 100644 (file)
@@ -187,8 +187,21 @@ var bsCollapse = new bootstrap.Collapse(myCollapse, {
       <td>Destroys an element's collapse. (Removes stored data on the DOM element)</td>
     </tr>
     <tr>
-      <td><code>getInstance</code></td>
-      <td>Static method which allows you to get the collapse instance associated with a DOM element.</td>
+      <td>
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the collapse instance associated to a DOM element, you can use it like this: <code>bootstrap.Collapse.getInstance(element)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns a collapse instance associated to a DOM element or create a new one in case it wasn't initialised.
+        You can use it like this: <code>bootstrap.Collapse.getOrCreateInstance(element)</code>
+      </td>
     </tr>
   </tbody>
 </table>
index 3ab91f8078065166ce2bcd515e289dde5129e063..e15cc0fe6221370e43ce9889c8b0673fe74d04d0 100644 (file)
@@ -1136,9 +1136,20 @@ var dropdown = new bootstrap.Dropdown(element, {
       </td>
     </tr>
     <tr>
-      <td><code>getInstance</code></td>
       <td>
-        Static method which allows you to get the dropdown instance associated with a DOM element.
+        <code>getInstance</code>
+      </td>
+      <td>
+        Static method which allows you to get the dropdown instance associated to a DOM element, you can use it like this: <code>bootstrap.Dropdown.getInstance(element)</code>
+      </td>
+    </tr>
+    <tr>
+      <td>
+        <code>getOrCreateInstance</code>
+      </td>
+      <td>
+        Static method which returns a dropdown instance associated to a DOM element or create a new one in case it wasn't initialised.
+        You can use it like this: <code>bootstrap.Dropdown.getOrCreateInstance(element)</code>
       </td>
     </tr>
   </tbody>
index 4b450939efe20f6f8a0a940e2eb0b36f62324ad5..76d0013e216737b846ce4e7464c3d6d1016a22e3 100644 (file)
@@ -484,6 +484,15 @@ var triggerEl = document.querySelector('#trigger')
 var tab = bootstrap.Tab.getInstance(triggerEl) // Returns a Bootstrap tab instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the tab instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var triggerEl = document.querySelector('#trigger')
+var tab = bootstrap.Tab.getOrCreateInstance(triggerEl) // Returns a Bootstrap tab instance
+```
+
 ### Events
 
 When showing a new tab, the events fire in the following order:
index 9917656a57cb13e14b970d2706532297a715ebc1..d19957f3e73bb324687db4c643ad2ac96e720c10 100644 (file)
@@ -952,6 +952,15 @@ var myModalEl = document.getElementById('myModal')
 var modal = bootstrap.Modal.getInstance(myModalEl) // Returns a Bootstrap modal instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the modal instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var myModalEl = document.querySelector('#myModal')
+var modal = bootstrap.Modal.getOrCreateInstance(myModalEl) // Returns a Bootstrap modal instance
+```
+
 ### Events
 
 Bootstrap's modal class exposes a few events for hooking into modal functionality. All modal events are fired at the modal itself (i.e. at the `<div class="modal">`).
index 830f71c2577b911b5a7740af87fc366e8aa1bd7e..b839f9754f626d16f8a44375fa4291f7114f16b7 100644 (file)
@@ -624,6 +624,15 @@ var triggerEl = document.querySelector('#trigger')
 var tab = bootstrap.Tab.getInstance(triggerEl) // Returns a Bootstrap tab instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the tab instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var triggerEl = document.querySelector('#trigger')
+var tab = bootstrap.Tab.getOrCreateInstance(triggerEl) // Returns a Bootstrap tab instance
+```
+
 ### Events
 
 When showing a new tab, the events fire in the following order:
index b9dbd7ce8da208f86c27669c8977fc75ccb5bef0..d0c60db2b2947c000493cc7eccd4771e5078e46c 100644 (file)
@@ -241,6 +241,7 @@ var bsOffcanvas = new bootstrap.Offcanvas(myOffcanvas)
 | `show` | Shows an offcanvas element. **Returns to the caller before the offcanvas element has actually been shown** (i.e. before the `shown.bs.offcanvas` event occurs).|
 | `hide` | Hides an offcanvas element. **Returns to the caller before the offcanvas element has actually been hidden** (i.e. before the `hidden.bs.offcanvas` event occurs).|
 | `getInstance` | *Static* method which allows you to get the offcanvas instance associated with a DOM element |
+| `getOrCreateInstance` | *Static* method which allows you to get the offcanvas instance associated with a DOM element, or create a new one in case it wasn't initialised |
 {{< /bs-table >}}
 
 ### Events
index 039a47cc1fe48c91035a00bed5bd66bfbaec50c7..06aa656d96a723edc356d49fe222fe0c061013e0 100644 (file)
@@ -393,6 +393,15 @@ var exampleTriggerEl = document.getElementById('example')
 var popover = bootstrap.Popover.getInstance(exampleTriggerEl) // Returns a Bootstrap popover instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the popover instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var exampleTriggerEl = document.getElementById('example')
+var popover = bootstrap.Popover.getOrCreateInstance(exampleTriggerEl) // Returns a Bootstrap popover instance
+```
+
 ### Events
 
 <table class="table">
index e1d748bca0d014b5c1eda2aa3b8ad3fec3816dc2..580a1e2d55d568125e7f6c23611ef356ea50edfb 100644 (file)
@@ -298,6 +298,15 @@ var scrollSpyContentEl = document.getElementById('content')
 var scrollSpy = bootstrap.ScrollSpy.getInstance(scrollSpyContentEl) // Returns a Bootstrap scrollspy instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the scrollspy instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var scrollSpyContentEl = document.getElementById('content')
+var scrollSpy = bootstrap.ScrollSpy.getOrCreateInstance(scrollSpyContentEl) // Returns a Bootstrap scrollspy instance
+```
+
 ### Options
 
 Options can be passed via data attributes or JavaScript. For data attributes, append the option name to `data-bs-`, as in `data-bs-offset=""`.
index 75713050c8974731b8ef87759ac6fcfdd4e62b4f..2dde09f5ba82e4123271ee9fdb64f1d0c740a9de 100644 (file)
@@ -391,6 +391,24 @@ Hides an element's toast. Your toast will remain on the DOM but won't show anymo
 toast.dispose()
 ```
 
+#### getInstance
+
+*Static* method which allows you to get the scrollspy instance associated with a DOM element
+
+```js
+var myToastEl = document.getElementById('myToastEl')
+var myToast = bootstrap.Toast.getInstance(myToastEl) // Returns a Bootstrap toast instance
+```
+
+#### getOrCreateInstance
+
+*Static* method which allows you to get the scrollspy instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var myToastEl = document.getElementById('myToastEl')
+var myToast = bootstrap.Toast.getOrCreateInstance(myToastEl) // Returns a Bootstrap toast instance
+```
+
 ### Events
 
 <table class="table">
index 6af594ee34e1fd7d7e2ce6c33bfe017f07223889..386d3e9f18817bdd3c30281cf9c422febbf9b559 100644 (file)
@@ -417,6 +417,15 @@ var exampleTriggerEl = document.getElementById('example')
 var tooltip = bootstrap.Tooltip.getInstance(exampleTriggerEl) // Returns a Bootstrap tooltip instance
 ```
 
+#### getOrCreateInstance
+
+*Static* method which allows you to get the tooltip instance associated with a DOM element, or create a new one in case it wasn't initialised
+
+```js
+var exampleTriggerEl = document.getElementById('example')
+var tooltip = bootstrap.Tooltip.getOrCreateInstance(exampleTriggerEl) // Returns a Bootstrap tooltip instance
+```
+
 ### Events
 
 <table class="table">