diff --git a/src/htmx.js b/src/htmx.js index 7fb43b6f..8fba09b9 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -523,6 +523,10 @@ return (function () { return [closest(elt, selector.substr(8))]; } else if (selector.indexOf("find ") === 0) { return [find(elt, selector.substr(5))]; + } else if (selector.indexOf("next ") === 0) { + return [scanForwardQuery(elt, selector.substr(5))]; + } else if (selector.indexOf("previous ") === 0) { + return [scanBackwardsQuery(elt, selector.substr(9))]; } else if (selector === 'document') { return [document]; } else if (selector === 'window') { @@ -532,6 +536,26 @@ return (function () { } } + var scanForwardQuery = function(start, match) { + var results = getDocument().querySelectorAll(match); + for (var i = 0; i < results.length; i++) { + var elt = results[i]; + if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_PRECEDING) { + return elt; + } + } + } + + var scanBackwardsQuery = function(start, match) { + var results = getDocument().querySelectorAll(match); + for (var i = results.length - 1; i >= 0; i--) { + var elt = results[i]; + if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_FOLLOWING) { + return elt; + } + } + } + function querySelectorExt(eltOrSelector, selector) { if (selector) { return querySelectorAllExt(eltOrSelector, selector)[0]; @@ -1111,7 +1135,7 @@ return (function () { } else if (token === "from" && tokens[0] === ":") { tokens.shift(); var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); - if (from_arg === "closest" || from_arg === "find") { + if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { tokens.shift(); from_arg += " " + diff --git a/test/attributes/hx-target.js b/test/attributes/hx-target.js index 5969c728..da48ea03 100644 --- a/test/attributes/hx-target.js +++ b/test/attributes/hx-target.js @@ -91,5 +91,44 @@ describe("hx-target attribute", function(){ div1.innerHTML.should.equal("Clicked!"); }); + it('targets a `next` element properly', function() + { + this.server.respondWith("GET", "/test", "Clicked!"); + make('
' + + '
' + + ' ' + + '
' + + '
' + + '
') + 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!"); + make('
' + + '
' + + ' ' + + '
' + + '
' + + '
') + 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!"); + }); })