aboutsummaryrefslogtreecommitdiff
path: root/js/src
diff options
context:
space:
mode:
authorGeoSot <[email protected]>2022-11-06 20:31:43 +0200
committerGitHub <[email protected]>2022-11-06 20:31:43 +0200
commite81e7cda90026cdb2a05fcdadd2d66f48f0bbdc4 (patch)
treeea2459eebdf22e47438e3494a4955e173b5e9b66 /js/src
parent2b21094074b1bdabf9ebc4095c29398f8b2de237 (diff)
downloadbootstrap-e81e7cda90026cdb2a05fcdadd2d66f48f0bbdc4.tar.xz
bootstrap-e81e7cda90026cdb2a05fcdadd2d66f48f0bbdc4.zip
Move `getElementFromSelector` & `getSelectorFromElement` to SelectorEngine (#36027)
* Move `getElementFromSelector` & getSelectorFromElement` inside selector-engine.js, in order to use SelectorEngine methods, avoiding raw querySelector usage * add `getMultipleElementsFromSelector` helper Co-authored-by: Julien Déramond <[email protected]>
Diffstat (limited to 'js/src')
-rw-r--r--js/src/carousel.js3
-rw-r--r--js/src/collapse.js13
-rw-r--r--js/src/dom/selector-engine.js47
-rw-r--r--js/src/modal.js4
-rw-r--r--js/src/offcanvas.js3
-rw-r--r--js/src/tab.js8
-rw-r--r--js/src/util/component-functions.js5
-rw-r--r--js/src/util/index.js43
8 files changed, 62 insertions, 64 deletions
diff --git a/js/src/carousel.js b/js/src/carousel.js
index e25395628..8ba9f351a 100644
--- a/js/src/carousel.js
+++ b/js/src/carousel.js
@@ -7,7 +7,6 @@
import {
defineJQueryPlugin,
- getElementFromSelector,
getNextActiveElement,
isRTL,
isVisible,
@@ -431,7 +430,7 @@ class Carousel extends BaseComponent {
*/
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, function (event) {
- const target = getElementFromSelector(this)
+ const target = SelectorEngine.getElementFromSelector(this)
if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
return
diff --git a/js/src/collapse.js b/js/src/collapse.js
index 04a5f4cdf..937174011 100644
--- a/js/src/collapse.js
+++ b/js/src/collapse.js
@@ -8,8 +8,6 @@
import {
defineJQueryPlugin,
getElement,
- getElementFromSelector,
- getSelectorFromElement,
reflow
} from './util/index.js'
import EventHandler from './dom/event-handler.js'
@@ -68,7 +66,7 @@ class Collapse extends BaseComponent {
const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE)
for (const elem of toggleList) {
- const selector = getSelectorFromElement(elem)
+ const selector = SelectorEngine.getSelectorFromElement(elem)
const filterElement = SelectorEngine.find(selector)
.filter(foundElement => foundElement === this._element)
@@ -185,7 +183,7 @@ class Collapse extends BaseComponent {
this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW)
for (const trigger of this._triggerArray) {
- const element = getElementFromSelector(trigger)
+ const element = SelectorEngine.getElementFromSelector(trigger)
if (element && !this._isShown(element)) {
this._addAriaAndCollapsedClass([trigger], false)
@@ -229,7 +227,7 @@ class Collapse extends BaseComponent {
const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE)
for (const element of children) {
- const selected = getElementFromSelector(element)
+ const selected = SelectorEngine.getElementFromSelector(element)
if (selected) {
this._addAriaAndCollapsedClass([element], this._isShown(selected))
@@ -285,10 +283,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
event.preventDefault()
}
- const selector = getSelectorFromElement(this)
- const selectorElements = SelectorEngine.find(selector)
-
- for (const element of selectorElements) {
+ for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {
Collapse.getOrCreateInstance(element, { toggle: false }).toggle()
}
})
diff --git a/js/src/dom/selector-engine.js b/js/src/dom/selector-engine.js
index 63bc2d176..ad10a6083 100644
--- a/js/src/dom/selector-engine.js
+++ b/js/src/dom/selector-engine.js
@@ -77,6 +77,53 @@ const SelectorEngine = {
].map(selector => `${selector}:not([tabindex^="-"])`).join(',')
return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))
+ },
+
+ getSelector(element) {
+ let selector = element.getAttribute('data-bs-target')
+
+ if (!selector || selector === '#') {
+ let hrefAttribute = element.getAttribute('href')
+
+ // The only valid content that could double as a selector are IDs or classes,
+ // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
+ // `document.querySelector` will rightfully complain it is invalid.
+ // See https://github.com/twbs/bootstrap/issues/32273
+ if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
+ return null
+ }
+
+ // Just in case some CMS puts out a full URL with the anchor appended
+ if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
+ hrefAttribute = `#${hrefAttribute.split('#')[1]}`
+ }
+
+ selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
+ }
+
+ return selector
+ },
+
+ getSelectorFromElement(element) {
+ const selector = SelectorEngine.getSelector(element)
+
+ if (selector) {
+ return SelectorEngine.findOne(selector) ? selector : null
+ }
+
+ return null
+ },
+
+ getElementFromSelector(element) {
+ const selector = SelectorEngine.getSelector(element)
+
+ return selector ? SelectorEngine.findOne(selector) : null
+ },
+
+ getMultipleElementsFromSelector(element) {
+ const selector = SelectorEngine.getSelector(element)
+
+ return selector ? SelectorEngine.find(selector) : []
}
}
diff --git a/js/src/modal.js b/js/src/modal.js
index 11efab20a..aba3b34a6 100644
--- a/js/src/modal.js
+++ b/js/src/modal.js
@@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/
-import { defineJQueryPlugin, getElementFromSelector, isRTL, isVisible, reflow } from './util/index.js'
+import { defineJQueryPlugin, isRTL, isVisible, reflow } from './util/index.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import ScrollBarHelper from './util/scrollbar.js'
@@ -336,7 +336,7 @@ class Modal extends BaseComponent {
*/
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
- const target = getElementFromSelector(this)
+ const target = SelectorEngine.getElementFromSelector(this)
if (['A', 'AREA'].includes(this.tagName)) {
event.preventDefault()
diff --git a/js/src/offcanvas.js b/js/src/offcanvas.js
index a857c4d7e..6fd709920 100644
--- a/js/src/offcanvas.js
+++ b/js/src/offcanvas.js
@@ -7,7 +7,6 @@
import {
defineJQueryPlugin,
- getElementFromSelector,
isDisabled,
isVisible
} from './util/index.js'
@@ -231,7 +230,7 @@ class Offcanvas extends BaseComponent {
*/
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
- const target = getElementFromSelector(this)
+ const target = SelectorEngine.getElementFromSelector(this)
if (['A', 'AREA'].includes(this.tagName)) {
event.preventDefault()
diff --git a/js/src/tab.js b/js/src/tab.js
index 19d3bfc36..d9e71b5ba 100644
--- a/js/src/tab.js
+++ b/js/src/tab.js
@@ -5,7 +5,7 @@
* --------------------------------------------------------------------------
*/
-import { defineJQueryPlugin, getElementFromSelector, getNextActiveElement, isDisabled } from './util/index.js'
+import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import BaseComponent from './base-component.js'
@@ -106,7 +106,7 @@ class Tab extends BaseComponent {
element.classList.add(CLASS_NAME_ACTIVE)
- this._activate(getElementFromSelector(element)) // Search and activate/show the proper section
+ this._activate(SelectorEngine.getElementFromSelector(element)) // Search and activate/show the proper section
const complete = () => {
if (element.getAttribute('role') !== 'tab') {
@@ -133,7 +133,7 @@ class Tab extends BaseComponent {
element.classList.remove(CLASS_NAME_ACTIVE)
element.blur()
- this._deactivate(getElementFromSelector(element)) // Search and deactivate the shown section too
+ this._deactivate(SelectorEngine.getElementFromSelector(element)) // Search and deactivate the shown section too
const complete = () => {
if (element.getAttribute('role') !== 'tab') {
@@ -203,7 +203,7 @@ class Tab extends BaseComponent {
}
_setInitialAttributesOnTargetPanel(child) {
- const target = getElementFromSelector(child)
+ const target = SelectorEngine.getElementFromSelector(child)
if (!target) {
return
diff --git a/js/src/util/component-functions.js b/js/src/util/component-functions.js
index 2298ac371..6896faf56 100644
--- a/js/src/util/component-functions.js
+++ b/js/src/util/component-functions.js
@@ -6,7 +6,8 @@
*/
import EventHandler from '../dom/event-handler.js'
-import { getElementFromSelector, isDisabled } from './index.js'
+import { isDisabled } from './index.js'
+import SelectorEngine from '../dom/selector-engine.js'
const enableDismissTrigger = (component, method = 'hide') => {
const clickEvent = `click.dismiss${component.EVENT_KEY}`
@@ -21,7 +22,7 @@ const enableDismissTrigger = (component, method = 'hide') => {
return
}
- const target = getElementFromSelector(this) || this.closest(`.${name}`)
+ const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`)
const instance = component.getOrCreateInstance(target)
// Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
diff --git a/js/src/util/index.js b/js/src/util/index.js
index ad99f85ed..b92eddba2 100644
--- a/js/src/util/index.js
+++ b/js/src/util/index.js
@@ -30,47 +30,6 @@ const getUID = prefix => {
return prefix
}
-const getSelector = element => {
- let selector = element.getAttribute('data-bs-target')
-
- if (!selector || selector === '#') {
- let hrefAttribute = element.getAttribute('href')
-
- // The only valid content that could double as a selector are IDs or classes,
- // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
- // `document.querySelector` will rightfully complain it is invalid.
- // See https://github.com/twbs/bootstrap/issues/32273
- if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
- return null
- }
-
- // Just in case some CMS puts out a full URL with the anchor appended
- if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
- hrefAttribute = `#${hrefAttribute.split('#')[1]}`
- }
-
- selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
- }
-
- return selector
-}
-
-const getSelectorFromElement = element => {
- const selector = getSelector(element)
-
- if (selector) {
- return document.querySelector(selector) ? selector : null
- }
-
- return null
-}
-
-const getElementFromSelector = element => {
- const selector = getSelector(element)
-
- return selector ? document.querySelector(selector) : null
-}
-
const getTransitionDurationFromElement = element => {
if (!element) {
return 0
@@ -316,10 +275,8 @@ export {
executeAfterTransition,
findShadowRoot,
getElement,
- getElementFromSelector,
getjQuery,
getNextActiveElement,
- getSelectorFromElement,
getTransitionDurationFromElement,
getUID,
isDisabled,