From dc5e3328c12058de7fb6404edbe5dcee61f3400f Mon Sep 17 00:00:00 2001 From: Rohit Sharma Date: Mon, 22 Feb 2021 12:31:04 +0530 Subject: [PATCH] Allow constructors to accept a CSS selector (#32245) Co-authored-by: XhmikosR Co-authored-by: Mark Otto --- js/src/base-component.js | 4 +++- js/src/collapse.js | 6 +++--- js/src/modal.js | 2 +- js/src/scrollspy.js | 2 +- js/tests/unit/alert.spec.js | 11 +++++++++++ js/tests/unit/button.spec.js | 10 ++++++++++ js/tests/unit/carousel.spec.js | 11 +++++++++++ js/tests/unit/collapse.spec.js | 11 +++++++++++ js/tests/unit/dropdown.spec.js | 18 ++++++++++++++++++ js/tests/unit/modal.spec.js | 13 +++++++++++++ js/tests/unit/scrollspy.spec.js | 11 +++++++++++ js/tests/unit/tab.spec.js | 16 ++++++++++++++++ js/tests/unit/toast.spec.js | 11 +++++++++++ js/tests/unit/tooltip.spec.js | 11 +++++++++++ .../docs/5.0/getting-started/javascript.md | 9 +++++++++ site/content/docs/5.0/migration.md | 11 +++++++++++ 16 files changed, 151 insertions(+), 6 deletions(-) diff --git a/js/src/base-component.js b/js/src/base-component.js index 9de274bd0978..989a64156195 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 0a1b475470cd..f86166765924 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 79a2f143a38b..4f42e733eba5 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 43a91e5e9326..0c51eab0fef6 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 916c7fd07c6d..194da420e9b5 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 = '
' + + 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 e442fd90d0a1..e7d92cb6d208 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 = '' + 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 533e1ba7e253..c475489c0605 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 = '' + + 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 = [ '