diff options
| author | Alessandro Chitolina <[email protected]> | 2017-09-26 10:04:31 +0200 |
|---|---|---|
| committer | XhmikosR <[email protected]> | 2019-02-20 22:05:45 +0200 |
| commit | 7f08061eca035d8f75651e9c3c32503e91f86fae (patch) | |
| tree | 1fcc2e4b252774265df7788359a6d2f509ddd594 /js/src/dom | |
| parent | 90261b484c7637407b310acecdfe56093738800d (diff) | |
| download | bootstrap-7f08061eca035d8f75651e9c3c32503e91f86fae.tar.xz bootstrap-7f08061eca035d8f75651e9c3c32503e91f86fae.zip | |
rewritten tab without jquery
Diffstat (limited to 'js/src/dom')
| -rw-r--r-- | js/src/dom/selectorEngine.js | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/js/src/dom/selectorEngine.js b/js/src/dom/selectorEngine.js index d132d7d24..a3e88ad6e 100644 --- a/js/src/dom/selectorEngine.js +++ b/js/src/dom/selectorEngine.js @@ -1,3 +1,5 @@ +import Util from '../util' + /** * -------------------------------------------------------------------------- * Bootstrap (v4.0.0-beta): dom/selectorEngine.js @@ -27,17 +29,13 @@ const SelectorEngine = (() => { if (!Element.prototype.closest) { fnClosest = (element, selector) => { let ancestor = element - if (!document.documentElement.contains(element)) { - return null - } - do { if (fnMatches.call(ancestor, selector)) { return ancestor } ancestor = ancestor.parentElement - } while (ancestor !== null) + } while (ancestor !== null && ancestor.nodeType === Node.ELEMENT_NODE) return null } @@ -48,12 +46,67 @@ const SelectorEngine = (() => { } } + const scopeSelectorRegex = /:scope\b/ + const supportScopeQuery = (() => { + const element = document.createElement('div') + try { + element.querySelectorAll(':scope *') + } catch (e) { + return false + } + + return true + })() + + let findFn = null + let findOneFn = null + if (supportScopeQuery) { + findFn = Element.prototype.querySelectorAll + findOneFn = Element.prototype.querySelector + } else { + findFn = function (selector) { + if (!scopeSelectorRegex.test(selector)) { + return this.querySelectorAll(selector) + } + + const hasId = Boolean(this.id) + if (!hasId) { + this.id = Util.getUID('scope') + } + + let nodeList = null + try { + selector = selector.replace(scopeSelectorRegex, `#${this.id}`) + nodeList = this.querySelectorAll(selector) + } finally { + if (!hasId) { + this.removeAttribute('id') + } + } + + return nodeList + } + + findOneFn = function (selector) { + if (!scopeSelectorRegex.test(selector)) { + return this.querySelector(selector) + } + + const matches = findFn.call(this, selector) + if (typeof matches[0] !== 'undefined') { + return matches[0] + } + + return null + } + } + return { matches(element, selector) { return fnMatches.call(element, selector) }, - find(selector, element = document) { + find(selector, element = document.documentElement) { if (typeof selector !== 'string') { return null } @@ -62,21 +115,24 @@ const SelectorEngine = (() => { return SelectorEngine.findOne(selector, element) } - return element.querySelectorAll(selector) + return findFn.call(element, selector) }, - findOne(selector, element = document) { + findOne(selector, element = document.documentElement) { if (typeof selector !== 'string') { return null } - let selectorType = 'querySelector' - if (selector.indexOf('#') === 0) { - selectorType = 'getElementById' - selector = selector.substr(1, selector.length) + return findOneFn.call(element, selector) + }, + + children(element, selector) { + if (typeof selector !== 'string') { + return null } - return element[selectorType](selector) + const children = Util.makeArray(element.children) + return children.filter((child) => this.matches(child, selector)) }, closest(element, selector) { |
