Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--js/src/base-component.js4
-rw-r--r--js/src/collapse.js6
-rw-r--r--js/src/modal.js2
-rw-r--r--js/src/scrollspy.js2
-rw-r--r--js/tests/unit/alert.spec.js11
-rw-r--r--js/tests/unit/button.spec.js10
-rw-r--r--js/tests/unit/carousel.spec.js11
-rw-r--r--js/tests/unit/collapse.spec.js11
-rw-r--r--js/tests/unit/dropdown.spec.js18
-rw-r--r--js/tests/unit/modal.spec.js13
-rw-r--r--js/tests/unit/scrollspy.spec.js11
-rw-r--r--js/tests/unit/tab.spec.js16
-rw-r--r--js/tests/unit/toast.spec.js11
-rw-r--r--js/tests/unit/tooltip.spec.js11
-rw-r--r--site/content/docs/5.0/getting-started/javascript.md9
-rw-r--r--site/content/docs/5.0/migration.md11
16 files changed, 151 insertions, 6 deletions
diff --git a/js/src/base-component.js b/js/src/base-component.js
index 9de274bd09..989a641561 100644
--- a/js/src/base-component.js
+++ b/js/src/base-component.js
@@ -17,12 +17,14 @@ const VERSION = '5.0.0-beta2'
class BaseComponent {
constructor(element) {
+ element = typeof element === 'string' ? document.querySelector(element) : element
+
if (!element) {
return
}
this._element = element
- Data.setData(element, this.constructor.DATA_KEY, this)
+ Data.setData(this._element, this.constructor.DATA_KEY, this)
}
dispose() {
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 0a1b475470..f861667659 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -72,8 +72,8 @@ class Collapse extends BaseComponent {
this._isTransitioning = false
this._config = this._getConfig(config)
this._triggerArray = SelectorEngine.find(
- `${SELECTOR_DATA_TOGGLE}[href="#${element.id}"],` +
- `${SELECTOR_DATA_TOGGLE}[data-bs-target="#${element.id}"]`
+ `${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` +
+ `${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`
)
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
@@ -82,7 +82,7 @@ class Collapse extends BaseComponent {
const elem = toggleList[i]
const selector = getSelectorFromElement(elem)
const filterElement = SelectorEngine.find(selector)
- .filter(foundElem => foundElem === element)
+ .filter(foundElem => foundElem === this._element)
if (selector !== null && filterElement.length) {
this._selector = selector
diff --git a/js/src/modal.js b/js/src/modal.js
index 79a2f143a3..4f42e733eb 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -83,7 +83,7 @@ class Modal extends BaseComponent {
super(element)
this._config = this._getConfig(config)
- this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, element)
+ this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element)
this._backdrop = null
this._isShown = false
this._isBodyOverflowing = false
diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js
index 43a91e5e93..0c51eab0fe 100644
--- a/js/src/scrollspy.js
+++ b/js/src/scrollspy.js
@@ -68,7 +68,7 @@ const METHOD_POSITION = 'position'
class ScrollSpy extends BaseComponent {
constructor(element, config) {
super(element)
- this._scrollElement = element.tagName === 'BODY' ? window : element
+ this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
this._config = this._getConfig(config)
this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`
this._offsets = []
diff --git a/js/tests/unit/alert.spec.js b/js/tests/unit/alert.spec.js
index 916c7fd07c..194da420e9 100644
--- a/js/tests/unit/alert.spec.js
+++ b/js/tests/unit/alert.spec.js
@@ -15,6 +15,17 @@ describe('Alert', () => {
clearFixture()
})
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<div class="alert"></div>'
+
+ const alertEl = fixtureEl.querySelector('.alert')
+ const alertBySelector = new Alert('.alert')
+ const alertByElement = new Alert(alertEl)
+
+ expect(alertBySelector._element).toEqual(alertEl)
+ expect(alertByElement._element).toEqual(alertEl)
+ })
+
it('should return version', () => {
expect(typeof Alert.VERSION).toEqual('string')
})
diff --git a/js/tests/unit/button.spec.js b/js/tests/unit/button.spec.js
index e442fd90d0..e7d92cb6d2 100644
--- a/js/tests/unit/button.spec.js
+++ b/js/tests/unit/button.spec.js
@@ -18,6 +18,16 @@ describe('Button', () => {
clearFixture()
})
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<button data-bs-toggle="button">Placeholder</button>'
+ const buttonEl = fixtureEl.querySelector('[data-bs-toggle="button"]')
+ const buttonBySelector = new Button('[data-bs-toggle="button"]')
+ const buttonByElement = new Button(buttonEl)
+
+ expect(buttonBySelector._element).toEqual(buttonEl)
+ expect(buttonByElement._element).toEqual(buttonEl)
+ })
+
describe('VERSION', () => {
it('should return plugin version', () => {
expect(Button.VERSION).toEqual(jasmine.any(String))
diff --git a/js/tests/unit/carousel.spec.js b/js/tests/unit/carousel.spec.js
index 533e1ba7e2..c475489c06 100644
--- a/js/tests/unit/carousel.spec.js
+++ b/js/tests/unit/carousel.spec.js
@@ -52,6 +52,17 @@ describe('Carousel', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<div id="myCarousel" class="carousel slide"></div>'
+
+ const carouselEl = fixtureEl.querySelector('#myCarousel')
+ const carouselBySelector = new Carousel('#myCarousel')
+ const carouselByElement = new Carousel(carouselEl)
+
+ expect(carouselBySelector._element).toEqual(carouselEl)
+ expect(carouselByElement._element).toEqual(carouselEl)
+ })
+
it('should go to next item if right arrow key is pressed', done => {
fixtureEl.innerHTML = [
'<div id="myCarousel" class="carousel slide">',
diff --git a/js/tests/unit/collapse.spec.js b/js/tests/unit/collapse.spec.js
index cd30ed8daa..bc7c157714 100644
--- a/js/tests/unit/collapse.spec.js
+++ b/js/tests/unit/collapse.spec.js
@@ -34,6 +34,17 @@ describe('Collapse', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<div class="my-collapse"></div>'
+
+ const collapseEl = fixtureEl.querySelector('div.my-collapse')
+ const collapseBySelector = new Collapse('div.my-collapse')
+ const collapseByElement = new Collapse(collapseEl)
+
+ expect(collapseBySelector._element).toEqual(collapseEl)
+ expect(collapseByElement._element).toEqual(collapseEl)
+ })
+
it('should allow jquery object in parent config', () => {
fixtureEl.innerHTML = [
'<div class="my-collapse">',
diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js
index 658cb65b04..b7e771c950 100644
--- a/js/tests/unit/dropdown.spec.js
+++ b/js/tests/unit/dropdown.spec.js
@@ -40,6 +40,24 @@ describe('Dropdown', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ 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="#">Link</a>',
+ ' </div>',
+ '</div>'
+ ].join('')
+
+ const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
+ const dropdownBySelector = new Dropdown('[data-bs-toggle="dropdown"]')
+ const dropdownByElement = new Dropdown(btnDropdown)
+
+ expect(dropdownBySelector._element).toEqual(btnDropdown)
+ expect(dropdownByElement._element).toEqual(btnDropdown)
+ })
+
it('should add a listener on trigger which do not have data-bs-toggle="dropdown"', () => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
diff --git a/js/tests/unit/modal.spec.js b/js/tests/unit/modal.spec.js
index 8a159eef6c..7f16bfc1d0 100644
--- a/js/tests/unit/modal.spec.js
+++ b/js/tests/unit/modal.spec.js
@@ -62,6 +62,19 @@ describe('Modal', () => {
})
})
+ describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
+
+ const modalEl = fixtureEl.querySelector('.modal')
+ const modalBySelector = new Modal('.modal')
+ const modalByElement = new Modal(modalEl)
+
+ expect(modalBySelector._element).toEqual(modalEl)
+ expect(modalByElement._element).toEqual(modalEl)
+ })
+ })
+
describe('toggle', () => {
it('should toggle a modal', done => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js
index a00da485f8..f7258ba355 100644
--- a/js/tests/unit/scrollspy.spec.js
+++ b/js/tests/unit/scrollspy.spec.js
@@ -54,6 +54,17 @@ describe('ScrollSpy', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<nav id="navigation"></nav><div class="content"></div>'
+
+ const sSpyEl = fixtureEl.querySelector('#navigation')
+ const sSpyBySelector = new ScrollSpy('#navigation')
+ const sSpyByElement = new ScrollSpy(sSpyEl)
+
+ expect(sSpyBySelector._element).toEqual(sSpyEl)
+ expect(sSpyByElement._element).toEqual(sSpyEl)
+ })
+
it('should generate an id when there is not one', () => {
fixtureEl.innerHTML = [
'<nav></nav>',
diff --git a/js/tests/unit/tab.spec.js b/js/tests/unit/tab.spec.js
index c52812f52e..35d17e16b9 100644
--- a/js/tests/unit/tab.spec.js
+++ b/js/tests/unit/tab.spec.js
@@ -20,6 +20,22 @@ describe('Tab', () => {
})
})
+ describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = [
+ '<ul class="nav"><li><a href="#home" role="tab">Home</a></li></ul>',
+ '<ul><li id="home"></li></ul>'
+ ].join('')
+
+ const tabEl = fixtureEl.querySelector('[href="#home"]')
+ const tabBySelector = new Tab('[href="#home"]')
+ const tabByElement = new Tab(tabEl)
+
+ expect(tabBySelector._element).toEqual(tabEl)
+ expect(tabByElement._element).toEqual(tabEl)
+ })
+ })
+
describe('show', () => {
it('should activate element by tab id (using buttons, the preferred semantic way)', done => {
fixtureEl.innerHTML = [
diff --git a/js/tests/unit/toast.spec.js b/js/tests/unit/toast.spec.js
index f8ef6e54b4..d298dc9931 100644
--- a/js/tests/unit/toast.spec.js
+++ b/js/tests/unit/toast.spec.js
@@ -27,6 +27,17 @@ describe('Toast', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<div class="toast"></div>'
+
+ const toastEl = fixtureEl.querySelector('.toast')
+ const toastBySelector = new Toast('.toast')
+ const toastByElement = new Toast(toastEl)
+
+ expect(toastBySelector._element).toEqual(toastEl)
+ expect(toastByElement._element).toEqual(toastEl)
+ })
+
it('should allow to config in js', done => {
fixtureEl.innerHTML = [
'<div class="toast">',
diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js
index 84f5abcdad..7bf6aa3ab8 100644
--- a/js/tests/unit/tooltip.spec.js
+++ b/js/tests/unit/tooltip.spec.js
@@ -63,6 +63,17 @@ describe('Tooltip', () => {
})
describe('constructor', () => {
+ it('should take care of element either passed as a CSS selector or DOM element', () => {
+ fixtureEl.innerHTML = '<a href="#" id="tooltipEl" rel="tooltip" title="Nice and short title">'
+
+ const tooltipEl = fixtureEl.querySelector('#tooltipEl')
+ const tooltipBySelector = new Tooltip('#tooltipEl')
+ const tooltipByElement = new Tooltip(tooltipEl)
+
+ expect(tooltipBySelector._element).toEqual(tooltipEl)
+ expect(tooltipByElement._element).toEqual(tooltipEl)
+ })
+
it('should not take care of disallowed data attributes', () => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-sanitize="false" title="Another tooltip">'
diff --git a/site/content/docs/5.0/getting-started/javascript.md b/site/content/docs/5.0/getting-started/javascript.md
index 53845fdfc2..f57a3aedf6 100644
--- a/site/content/docs/5.0/getting-started/javascript.md
+++ b/site/content/docs/5.0/getting-started/javascript.md
@@ -93,6 +93,15 @@ var modal = new bootstrap.Modal(myModalEl, { keyboard: false }) // initialized w
If you'd like to get a particular plugin instance, each plugin exposes a `getInstance` method. In order to retrieve it directly from an element, do this: `bootstrap.Popover.getInstance(myPopoverEl)`.
+### CSS selectors in constructors
+
+You can also use a CSS selector as the first argument instead of a DOM element to initialize the plugin. Currently the element for the plugin is found by the `querySelector` method since our plugins support a single element only.
+
+```js
+var modal = new bootstrap.Modal('#myModal')
+var dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
+```
+
### Asynchronous functions and transitions
All programmatic API methods are **asynchronous** and return to the caller once the transition is started but **before it ends**.
diff --git a/site/content/docs/5.0/migration.md b/site/content/docs/5.0/migration.md
index 94f2214d70..903b282cf6 100644
--- a/site/content/docs/5.0/migration.md
+++ b/site/content/docs/5.0/migration.md
@@ -9,6 +9,17 @@ toc: true
## v5.0.0-beta3
+### JavaScript
+
+- All plugins can now accept a CSS selector as the first argument. You can either pass a DOM element or any valid CSS selector to create a new instance of the plugin:
+
+ ```js
+ var modal = new bootstrap.Modal('#myModal')
+ var dropdown = new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
+ ```
+
+## v5.0.0-beta2
+
### Utilities
- Dropped the `0` entry in `$border-widths` map to remove the duplicated `.border-0` class.