add findall and fix find (#3555)

Co-authored-by: MichaelWest22 <michael.west@docuvera.com>
This commit is contained in:
MichaelWest22
2025-11-26 14:36:18 +13:00
committed by GitHub
parent db92b4c755
commit 0c8dff8e4d
3 changed files with 51 additions and 10 deletions

View File

@@ -1792,7 +1792,9 @@ var htmx = (() => {
if (selector.startsWith('closest ')) {
item = elt.closest(selector.slice(8))
} else if (selector.startsWith('find ')) {
item = document.querySelector(elt, selector.slice(5))
item = elt.querySelector(selector.slice(5))
} else if (selector.startsWith('findAll ')) {
result.push(...elt.querySelectorAll(selector.slice(8)))
} else if (selector === 'next' || selector === 'nextElementSibling') {
item = elt.nextElementSibling
} else if (selector.startsWith('next ')) {
@@ -1807,8 +1809,6 @@ var htmx = (() => {
item = window
} else if (selector === 'body') {
item = document.body
} else if (selector === 'root') {
item = this.__getRootNode(elt, !!global)
} else if (selector === 'host') {
item = (elt.getRootNode()).host
} else {

View File

@@ -89,13 +89,6 @@ describe('__findAllExt unit tests', function() {
assert.equal(results[0], document.body)
})
it('handles root keyword', function () {
let div = createProcessedHTML('<div></div>')
let results = htmx.__findAllExt(div, 'root')
assert.equal(results.length, 1)
assert.equal(results[0], document)
})
it('handles hyperscript-style selector', function () {
createProcessedHTML('<div class="foo"></div>')
let results = htmx.__findAllExt(document, '<.foo/>')
@@ -161,4 +154,51 @@ describe('__findAllExt unit tests', function() {
assert.equal(results[1], document)
})
it('handles find keyword - returns first match within element', function () {
let parent = createProcessedHTML('<div id="parent"><span class="target"></span><span class="target"></span></div>')
let results = htmx.__findAllExt(parent, 'find .target')
assert.equal(results.length, 1)
assert.equal(results[0].className, 'target')
})
it('handles find keyword - scopes to element not document', function () {
createProcessedHTML('<div class="outside"></div><div id="parent"><div class="inside"></div></div>')
let parent = document.getElementById('parent')
let results = htmx.__findAllExt(parent, 'find .inside')
assert.equal(results.length, 1)
assert.equal(results[0].className, 'inside')
// Should not find .outside
let results2 = htmx.__findAllExt(parent, 'find .outside')
assert.equal(results2.length, 0)
})
it('handles findAll keyword - returns all matches within element', function () {
let parent = createProcessedHTML('<div id="parent"><span class="target"></span><span class="target"></span><span class="target"></span></div>')
let results = htmx.__findAllExt(parent, 'findAll .target')
assert.equal(results.length, 3)
results.forEach(el => assert.equal(el.className, 'target'))
})
it('handles findAll keyword - scopes to element not document', function () {
createProcessedHTML('<div class="outside"></div><div class="outside"></div><div id="parent"><div class="inside"></div><div class="inside"></div></div>')
let parent = document.getElementById('parent')
let results = htmx.__findAllExt(parent, 'findAll .inside')
assert.equal(results.length, 2)
// Should not find .outside elements
let results2 = htmx.__findAllExt(parent, 'findAll .outside')
assert.equal(results2.length, 0)
})
it('handles find with no matches', function () {
let parent = createProcessedHTML('<div id="parent"><span></span></div>')
let results = htmx.__findAllExt(parent, 'find .nonexistent')
assert.equal(results.length, 0)
})
it('handles findAll with no matches', function () {
let parent = createProcessedHTML('<div id="parent"><span></span></div>')
let results = htmx.__findAllExt(parent, 'findAll .nonexistent')
assert.equal(results.length, 0)
})
});

View File

@@ -14,6 +14,7 @@ request. The value of this attribute can be:
ancestor element or itself, that matches the given CSS selector
(e.g. `closest tr` will target the closest table row to the element).
* `find <CSS selector>` which will find the first child descendant element that matches the given CSS selector.
* `findAll <CSS selector>` which will find all child descendant elements that match the given CSS selector.
* `next` which resolves to [element.nextElementSibling](https://developer.mozilla.org/docs/Web/API/Element/nextElementSibling)
* `next <CSS selector>` which will scan the DOM forward for the first element that matches the given CSS selector.
(e.g. `next .error` will target the closest following sibling element with `error` class)