diff options
author | Vincent <vichenzo-thebaud@hotmail.com> | 2024-12-12 19:12:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-12 11:12:01 -0700 |
commit | a3312449237c455243aff5137c988b926a260edf (patch) | |
tree | a77e67d8d98dcfc1cd70f6637680287cbff1423c /src | |
parent | 232667d2c683a57ba52665ffaf8379ae8f432cfd (diff) | |
download | htmx-a3312449237c455243aff5137c988b926a260edf.tar.gz htmx-a3312449237c455243aff5137c988b926a260edf.zip |
Support multiple extended selectors for hx-include, hx-trigger from, and hx-disabled-elt (#2902)
* Initial suggestion (squashed)
Support multiple extended selectors for hx-include
Additional test for nested standard selector
Add @MichaelWest22 hx-disabled-elt multiple selector test
Add hx-trigger `from` test with multiple extended selectors
Simplify
Include #2915 fix
Update htmx.js
Split for readability
Don't apply global to previous selectors
Rewrite loop, restore global recursive call, minimize diff
Use break for better readability
Co-Authored-By: MichaelWest22 <12867972+MichaelWest22@users.noreply.github.com>
* Keep global as a first-position-only keyword
* Wrapped selector syntax
* Replace substring check by individual chars check
* Fix format
---------
Co-authored-by: MichaelWest22 <12867972+MichaelWest22@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/htmx.js | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/src/htmx.js b/src/htmx.js index d3411e2c..eaa4d6c6 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -1126,34 +1126,77 @@ var htmx = (function() { * @returns {(Node|Window)[]} */ function querySelectorAllExt(elt, selector, global) { - elt = resolveTarget(elt) - if (selector.indexOf('closest ') === 0) { - return [closest(asElement(elt), normalizeSelector(selector.slice(8)))] - } else if (selector.indexOf('find ') === 0) { - return [find(asParentNode(elt), normalizeSelector(selector.slice(5)))] - } else if (selector === 'next') { - return [asElement(elt).nextElementSibling] - } else if (selector.indexOf('next ') === 0) { - return [scanForwardQuery(elt, normalizeSelector(selector.slice(5)), !!global)] - } else if (selector === 'previous') { - return [asElement(elt).previousElementSibling] - } else if (selector.indexOf('previous ') === 0) { - return [scanBackwardsQuery(elt, normalizeSelector(selector.slice(9)), !!global)] - } else if (selector === 'document') { - return [document] - } else if (selector === 'window') { - return [window] - } else if (selector === 'body') { - return [document.body] - } else if (selector === 'root') { - return [getRootNode(elt, !!global)] - } else if (selector === 'host') { - return [(/** @type ShadowRoot */(elt.getRootNode())).host] - } else if (selector.indexOf('global ') === 0) { + if (selector.indexOf('global ') === 0) { return querySelectorAllExt(elt, selector.slice(7), true) - } else { - return toArray(asParentNode(getRootNode(elt, !!global)).querySelectorAll(normalizeSelector(selector))) } + + elt = resolveTarget(elt) + + const parts = [] + { + let chevronsCount = 0 + let offset = 0 + for (let i = 0; i < selector.length; i++) { + const char = selector[i] + if (char === ',' && chevronsCount === 0) { + parts.push(selector.substring(offset, i)) + offset = i + 1 + continue + } + if (char === '<') { + chevronsCount++ + } else if (char === '/' && i < selector.length - 1 && selector[i + 1] === '>') { + chevronsCount-- + } + } + if (offset < selector.length) { + parts.push(selector.substring(offset)) + } + } + + const result = [] + const unprocessedParts = [] + while (parts.length > 0) { + const selector = normalizeSelector(parts.shift()) + let item + if (selector.indexOf('closest ') === 0) { + item = closest(asElement(elt), normalizeSelector(selector.substr(8))) + } else if (selector.indexOf('find ') === 0) { + item = find(asParentNode(elt), normalizeSelector(selector.substr(5))) + } else if (selector === 'next' || selector === 'nextElementSibling') { + item = asElement(elt).nextElementSibling + } else if (selector.indexOf('next ') === 0) { + item = scanForwardQuery(elt, normalizeSelector(selector.substr(5)), !!global) + } else if (selector === 'previous' || selector === 'previousElementSibling') { + item = asElement(elt).previousElementSibling + } else if (selector.indexOf('previous ') === 0) { + item = scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)), !!global) + } else if (selector === 'document') { + item = document + } else if (selector === 'window') { + item = window + } else if (selector === 'body') { + item = document.body + } else if (selector === 'root') { + item = getRootNode(elt, !!global) + } else if (selector === 'host') { + item = (/** @type ShadowRoot */(elt.getRootNode())).host + } else { + unprocessedParts.push(selector) + } + + if (item) { + result.push(item) + } + } + + if (unprocessedParts.length > 0) { + const standardSelector = unprocessedParts.join(',') + const rootNode = asParentNode(getRootNode(elt, !!global)) + result.push(...toArray(rootNode.querySelectorAll(standardSelector))) + } + + return result } /** @@ -2327,7 +2370,7 @@ var htmx = (function() { path = getDocument().location.href } if (verb === 'get' && path.includes('?')) { - path = path.replace(/\?[^#]+/, ''); + path = path.replace(/\?[^#]+/, '') } } triggerSpecs.forEach(function(triggerSpec) { |