mirror of
https://github.com/bigskysoftware/htmx.git
synced 2026-01-25 05:06:13 +00:00
[New feature] selector-less next and previous targets (#1478)
* nextElementSibling and previousElementSibling target selectors * Renamed nextElementSibling => next, previousElementSibling => previous
This commit is contained in:
18
src/htmx.js
18
src/htmx.js
@@ -596,8 +596,12 @@ return (function () {
|
||||
return [closest(elt, normalizeSelector(selector.substr(8)))];
|
||||
} else if (selector.indexOf("find ") === 0) {
|
||||
return [find(elt, normalizeSelector(selector.substr(5)))];
|
||||
} else if (selector === "next") {
|
||||
return [elt.nextElementSibling]
|
||||
} else if (selector.indexOf("next ") === 0) {
|
||||
return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))];
|
||||
} else if (selector === "previous") {
|
||||
return [elt.previousElementSibling]
|
||||
} else if (selector.indexOf("previous ") === 0) {
|
||||
return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))];
|
||||
} else if (selector === 'document') {
|
||||
@@ -1279,12 +1283,14 @@ return (function () {
|
||||
var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA);
|
||||
if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") {
|
||||
tokens.shift();
|
||||
from_arg +=
|
||||
" " +
|
||||
consumeUntil(
|
||||
tokens,
|
||||
WHITESPACE_OR_COMMA
|
||||
);
|
||||
var selector = consumeUntil(
|
||||
tokens,
|
||||
WHITESPACE_OR_COMMA
|
||||
)
|
||||
// `next` and `previous` allow a selector-less syntax
|
||||
if (selector.length > 0) {
|
||||
from_arg += " " + selector;
|
||||
}
|
||||
}
|
||||
triggerSpec.from = from_arg;
|
||||
} else if (token === "target" && tokens[0] === ":") {
|
||||
|
||||
@@ -202,4 +202,43 @@ describe("hx-target attribute", function(){
|
||||
div3.innerHTML.should.equal("Clicked!");
|
||||
});
|
||||
|
||||
it('targets a `next` element properly without selector', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
make('<div>' +
|
||||
' <div id="d3"></div>' +
|
||||
' <button id="b1" hx-target="next" 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 without selector', function()
|
||||
{
|
||||
this.server.respondWith("GET", "/test", "Clicked!");
|
||||
make('<div>' +
|
||||
' <div id="d3"></div>' +
|
||||
' <button id="b1" hx-target="previous" 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!");
|
||||
});
|
||||
})
|
||||
|
||||
@@ -506,6 +506,36 @@ describe("hx-trigger attribute", function(){
|
||||
a1.innerHTML.should.equal("Requests: 1");
|
||||
});
|
||||
|
||||
it('from clause works with next', function()
|
||||
{
|
||||
var requests = 0;
|
||||
this.server.respondWith("GET", "/test", function (xhr) {
|
||||
requests++;
|
||||
xhr.respond(200, {}, "Requests: " + requests);
|
||||
});
|
||||
make('<div hx-trigger="click from:next" hx-target="#a1" hx-get="/test"></div><a id="a1">Requests: 0</a>');
|
||||
var a1 = byId('a1');
|
||||
a1.innerHTML.should.equal("Requests: 0");
|
||||
a1.click();
|
||||
this.server.respond();
|
||||
a1.innerHTML.should.equal("Requests: 1");
|
||||
});
|
||||
|
||||
it('from clause works with previous', function()
|
||||
{
|
||||
var requests = 0;
|
||||
this.server.respondWith("GET", "/test", function (xhr) {
|
||||
requests++;
|
||||
xhr.respond(200, {}, "Requests: " + requests);
|
||||
});
|
||||
make('<a id="a1">Requests: 0</a><div hx-trigger="click from:previous" hx-target="#a1" hx-get="/test"></div>');
|
||||
var a1 = byId('a1');
|
||||
a1.innerHTML.should.equal("Requests: 0");
|
||||
a1.click();
|
||||
this.server.respond();
|
||||
a1.innerHTML.should.equal("Requests: 1");
|
||||
});
|
||||
|
||||
it('event listeners on other elements are removed when an element is swapped out', function()
|
||||
{
|
||||
var requests = 0;
|
||||
|
||||
@@ -12,10 +12,14 @@ function make(htmlStr) {
|
||||
var wa = getWorkArea();
|
||||
var child = null;
|
||||
var children = fragment.children || fragment.childNodes; // IE
|
||||
var appendedChildren = []
|
||||
while(children.length > 0) {
|
||||
child = children[0];
|
||||
wa.appendChild(child);
|
||||
htmx.process(child);
|
||||
appendedChildren.push(child)
|
||||
}
|
||||
for (var i = 0; i < appendedChildren.length; i++) {
|
||||
htmx.process(appendedChildren[i]);
|
||||
}
|
||||
return child; // return last added element
|
||||
};
|
||||
|
||||
@@ -11,8 +11,10 @@ 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.
|
||||
* `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)
|
||||
* `previous` which resolves to [element.previousElementSibling](https://developer.mozilla.org/docs/Web/API/Element/previousElementSibling)
|
||||
* `previous <CSS selector>` which will scan the DOM backwards for the first element that matches the given CSS selector.
|
||||
(e.g `previous .error` will target the closest previous sibling with `error` class)
|
||||
|
||||
|
||||
@@ -61,6 +61,12 @@ is seen again before the delay completes, it is ignored, the element will trigge
|
||||
* `window` - listen for events on the window
|
||||
* `closest <CSS selector>` - finds the [closest](https://developer.mozilla.org/docs/Web/API/Element/closest) ancestor element or itself, matching the given css selector
|
||||
* `find <CSS selector>` - finds the closest child matching the given css selector
|
||||
* `next` resolves to [element.nextElementSibling](https://developer.mozilla.org/docs/Web/API/Element/nextElementSibling)
|
||||
* `next <CSS selector>` scans 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)
|
||||
* `previous` resolves to [element.previousElementSibling](https://developer.mozilla.org/docs/Web/API/Element/previousElementSibling)
|
||||
* `previous <CSS selector>` scans the DOM backwards for the first element that matches the given CSS selector.
|
||||
(e.g `previous .error` will target the closest previous sibling with `error` class)
|
||||
* `target:<CSS selector>` - allows you to filter via a CSS selector on the target of the event. This can be useful when you want to listen for
|
||||
triggers from elements that might not be in the DOM at the point of initialization, by, for example, listening on the body,
|
||||
but with a target filter for a child element
|
||||
|
||||
Reference in New Issue
Block a user