mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-09-27 13:01:03 +00:00
properly trim ids in `hx-select-oob` and also support hyperscript-style query literals in attributes like `hx-target`
This commit is contained in:
parent
32edfba6f2
commit
6cc92bf12d
21
src/htmx.js
21
src/htmx.js
@ -540,21 +540,30 @@ return (function () {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeSelector(selector) {
|
||||
var trimmedSelector = selector.trim();
|
||||
if (trimmedSelector.startsWith("<") && trimmedSelector.endsWith("/>")) {
|
||||
return trimmedSelector.substring(1, trimmedSelector.length - 2);
|
||||
} else {
|
||||
return trimmedSelector;
|
||||
}
|
||||
}
|
||||
|
||||
function querySelectorAllExt(elt, selector) {
|
||||
if (selector.indexOf("closest ") === 0) {
|
||||
return [closest(elt, selector.substr(8))];
|
||||
return [closest(elt, normalizeSelector(selector.substr(8)))];
|
||||
} else if (selector.indexOf("find ") === 0) {
|
||||
return [find(elt, selector.substr(5))];
|
||||
return [find(elt, normalizeSelector(selector.substr(5)))];
|
||||
} else if (selector.indexOf("next ") === 0) {
|
||||
return [scanForwardQuery(elt, selector.substr(5))];
|
||||
return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))];
|
||||
} else if (selector.indexOf("previous ") === 0) {
|
||||
return [scanBackwardsQuery(elt, selector.substr(9))];
|
||||
return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))];
|
||||
} else if (selector === 'document') {
|
||||
return [document];
|
||||
} else if (selector === 'window') {
|
||||
return [window];
|
||||
} else {
|
||||
return getDocument().querySelectorAll(selector);
|
||||
return getDocument().querySelectorAll(normalizeSelector(selector));
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,7 +779,7 @@ return (function () {
|
||||
var oobSelectValues = oobSelects.split(",");
|
||||
for (let i = 0; i < oobSelectValues.length; i++) {
|
||||
var oobSelectValue = oobSelectValues[i].split(":", 2);
|
||||
var id = oobSelectValue[0];
|
||||
var id = oobSelectValue[0].trim();
|
||||
if (id.indexOf("#") === 0) {
|
||||
id = id.substring(1);
|
||||
}
|
||||
|
@ -20,6 +20,23 @@ describe("hx-select-oob attribute", function () {
|
||||
div2.innerHTML.should.equal("bar");
|
||||
});
|
||||
|
||||
it('multiple hx-select-oobs works', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "<div id='d1'>foo</div><div id='d2'>bar</div><div id='d3'>bar</div>");
|
||||
var div = make('<div hx-get="/test" hx-select="#d1" hx-select-oob="#d2, #d3"></div>');
|
||||
make('<div id="d2"></div>');
|
||||
make('<div id="d3"></div>');
|
||||
div.click();
|
||||
this.server.respond();
|
||||
div.innerHTML.should.equal("<div id=\"d1\">foo</div>");
|
||||
|
||||
var div2 = byId('d2');
|
||||
div2.innerHTML.should.equal("bar");
|
||||
|
||||
var div3 = byId('d2');
|
||||
div3.innerHTML.should.equal("bar");
|
||||
});
|
||||
|
||||
it('basic hx-select-oob ignores bad selector', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "<div id='d1'>foo</div><div id='d2'>bar</div>");
|
||||
|
@ -48,6 +48,16 @@ describe("hx-target attribute", function(){
|
||||
div1.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('targets a `closest` element properly w/ hyperscript syntax', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
var div1 = make('<div><p><i><button id="b1" hx-target="closest <div/>" hx-get="/test">Click Me!</button></i></p></div>')
|
||||
var btn = byId("b1")
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
div1.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('targets a `find` element properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
@ -60,6 +70,18 @@ describe("hx-target attribute", function(){
|
||||
span2.innerHTML.should.equal("");
|
||||
});
|
||||
|
||||
it('targets a `find` element properly w/ hyperscript syntax', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
var div1 = make('<div hx-target="find <span/>" hx-get="/test">Click Me! <div><span id="s1"></span><span id="s2"></span></div></div>')
|
||||
div1.click();
|
||||
this.server.respond();
|
||||
var span1 = byId("s1")
|
||||
var span2 = byId("s2")
|
||||
span1.innerHTML.should.equal("Clicked!");
|
||||
span2.innerHTML.should.equal("");
|
||||
});
|
||||
|
||||
it('targets an inner element properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
@ -70,6 +92,15 @@ describe("hx-target attribute", function(){
|
||||
div1.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('targets an inner element properly w/ hyperscript syntax', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
var btn = make('<button hx-target="<#d1/>" hx-get="/test">Click Me!<div id="d1"></div></button>')
|
||||
var div1 = byId("d1")
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
div1.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('handles bad target gracefully', function()
|
||||
{
|
||||
@ -111,6 +142,26 @@ describe("hx-target attribute", function(){
|
||||
div3.innerHTML.should.equal("");
|
||||
});
|
||||
|
||||
it('targets a `next` element properly w/ hyperscript syntax', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
make('<div>' +
|
||||
' <div id="d3"></div>' +
|
||||
' <button id="b1" hx-target="next <div/>" hx-get="/test">Click Me!</button>' +
|
||||
' <div id="d1"></div>' +
|
||||
' <div id="d2"></div>' +
|
||||
'</div>')
|
||||
var btn = byId("b1")
|
||||
var div1 = byId("d1")
|
||||
var div2 = byId("d2")
|
||||
var div3 = byId("d3")
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
div1.innerHTML.should.equal("Clicked!");
|
||||
div2.innerHTML.should.equal("");
|
||||
div3.innerHTML.should.equal("");
|
||||
});
|
||||
|
||||
it('targets a `previous` element properly', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
@ -131,4 +182,24 @@ describe("hx-target attribute", function(){
|
||||
div3.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('targets a `previous` element properly w/ hyperscript syntax', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
make('<div>' +
|
||||
' <div id="d3"></div>' +
|
||||
' <button id="b1" hx-target="previous <div/>" hx-get="/test">Click Me!</button>' +
|
||||
' <div id="d1"></div>' +
|
||||
' <div id="d2"></div>' +
|
||||
'</div>')
|
||||
var btn = byId("b1")
|
||||
var div1 = byId("d1")
|
||||
var div2 = byId("d2")
|
||||
var div3 = byId("d3")
|
||||
btn.click();
|
||||
this.server.respond();
|
||||
div1.innerHTML.should.equal("");
|
||||
div2.innerHTML.should.equal("");
|
||||
div3.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
})
|
||||
|
@ -12,9 +12,14 @@ request. The value of this attribute can be:
|
||||
* `this` which indicates that the element that the `hx-target` attribute is on is the target
|
||||
* `closest <CSS selector>` which will find the closest parent ancestor that matches the given CSS selector.
|
||||
(e.g. `closest tr` will target the closest table row to the element)
|
||||
* `next <CSS selector>` which will find the next element in the DOM from the element that the `hx-target` attribute is on matching the given CSS selector.
|
||||
* `previous <CSS selector>` which will find the next element in the DOM from the element that the `hx-target` attribute is on matching the given CSS selector.
|
||||
* `find <CSS selector>` which will find the first child descendant element that matches the given CSS selector.
|
||||
(e.g `find tr` will target the first child descendant row to the element)
|
||||
|
||||
Note that in all cases, the CSS selector may be wrapped in a `<` and `/>`, mimicking the [query literal](https://hyperscript.org/expressions/query-reference/) syntax of
|
||||
hyperscript.
|
||||
|
||||
Here is an example that targets a div:
|
||||
|
||||
```html
|
||||
|
Loading…
x
Reference in New Issue
Block a user