Skip to content

Commit 54893d9

Browse files
committed
Inherit keyword in hx-include / hx-indicator
1 parent d8f7afe commit 54893d9

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed

src/htmx.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,27 @@ return (function () {
684684
return [findThisElement(elt, attrName)];
685685
} else {
686686
var result = querySelectorAllExt(elt, attrTarget);
687+
// find `inherit` in string, make sure it's surrounded by commas or is at the start/end of string
688+
var shouldInherit = new RegExp(/(^|,)(\s*)inherit(\s*)($|,)/).test(attrTarget)
689+
if (shouldInherit) {
690+
var eltToInheritFrom = getClosestMatch(elt, function (parent) {
691+
return parent !== elt && parent.hasAttribute(attrName)
692+
})
693+
if (eltToInheritFrom) {
694+
var targetsToInherit = findAttributeTargets(eltToInheritFrom, attrName)
695+
if (targetsToInherit) {
696+
// Can't push to a NodeList (returned by document.querySelectorAll), and Array.from is IE11 incompatible
697+
var newResult = [], i
698+
for (i = 0; i < result.length; i++) {
699+
newResult.push(result[i])
700+
}
701+
for (i = 0; i < targetsToInherit.length; i++) {
702+
newResult.push(targetsToInherit[i])
703+
}
704+
result = newResult
705+
}
706+
}
707+
}
687708
if (result.length === 0) {
688709
logError('The selector "' + attrTarget + '" on ' + attrName + " returned no matches!");
689710
return [DUMMY_ELT]

test/attributes/hx-include.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,87 @@ describe("hx-include attribute", function() {
225225
btn.innerHTML.should.equal("Clicked!");
226226
})
227227

228+
it('`inherit` can be used to expand parent hx-include', function () {
229+
this.server.respondWith("POST", "/include", function (xhr) {
230+
var params = getParameters(xhr);
231+
params['i1'].should.equal("test1");
232+
params['i2'].should.equal("test2");
233+
xhr.respond(200, {}, "Clicked!")
234+
});
235+
make('<div hx-include="#i1">' +
236+
' <button id="btn" hx-include="inherit, #i2" hx-post="/include"></button>' +
237+
'</div>' +
238+
'<input id="i1" name="i1" value="test1"/>' +
239+
'<input id="i2" name="i2" value="test2"/>');
240+
var btn = byId('btn')
241+
btn.click();
242+
this.server.respond();
243+
btn.innerHTML.should.equal("Clicked!");
244+
})
245+
246+
it('`inherit` can be used to expand multiple parents hx-include', function () {
247+
this.server.respondWith("POST", "/include", function (xhr) {
248+
var params = getParameters(xhr);
249+
params['i1'].should.equal("test1");
250+
params['i2'].should.equal("test2");
251+
params['i3'].should.equal("test3");
252+
xhr.respond(200, {}, "Clicked!")
253+
});
254+
make('<div hx-include="#i1">' +
255+
' <div hx-include="inherit, #i2">' +
256+
' <button id="btn" hx-include="inherit, #i3" hx-post="/include"></button>' +
257+
' </div>' +
258+
'</div>' +
259+
'<input id="i1" name="i1" value="test1"/>' +
260+
'<input id="i2" name="i2" value="test2"/>' +
261+
'<input id="i3" name="i3" value="test3"/>');
262+
var btn = byId('btn')
263+
btn.click();
264+
this.server.respond();
265+
btn.innerHTML.should.equal("Clicked!");
266+
})
267+
268+
it('`inherit` chain breaks properly', function () {
269+
this.server.respondWith("POST", "/include", function (xhr) {
270+
var params = getParameters(xhr);
271+
should.not.exist(params['i1'])
272+
params['i2'].should.equal("test2");
273+
params['i3'].should.equal("test3");
274+
xhr.respond(200, {}, "Clicked!")
275+
});
276+
make('<div hx-include="#i1">' +
277+
' <div hx-include="#i2">' +
278+
' <button id="btn" hx-include="inherit, #i3" hx-post="/include"></button>' +
279+
' </div>' +
280+
'</div>' +
281+
'<input id="i1" name="i1" value="test1"/>' +
282+
'<input id="i2" name="i2" value="test2"/>' +
283+
'<input id="i3" name="i3" value="test3"/>');
284+
var btn = byId('btn')
285+
btn.click();
286+
this.server.respond();
287+
btn.innerHTML.should.equal("Clicked!");
288+
})
289+
290+
it('`inherit` syntax regex properly catches keyword', function () {
291+
this.server.respondWith("POST", "/include", function (xhr) {
292+
var params = getParameters(xhr);
293+
params['i1'].should.equal("test1");
294+
params['i2'].should.equal("test2");
295+
params['i3'].should.equal("test3");
296+
xhr.respond(200, {}, "Clicked!")
297+
});
298+
make('<div hx-include="#i1">' +
299+
' <div hx-include="#i2, inherit,.nonexistent-class">' +
300+
' <button id="btn" hx-include="customtag,inherit , #i3" hx-post="/include"></button>' +
301+
' </div>' +
302+
'</div>' +
303+
'<input id="i1" name="i1" value="test1"/>' +
304+
'<input id="i2" name="i2" value="test2"/>' +
305+
'<input id="i3" name="i3" value="test3"/>');
306+
var btn = byId('btn')
307+
btn.click();
308+
this.server.respond();
309+
btn.innerHTML.should.equal("Clicked!");
310+
})
228311
});

test/attributes/hx-indicator.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,67 @@ describe("hx-indicator attribute", function(){
133133

134134
});
135135

136+
it('`inherit` can be used to expand parent hx-indicator', function () {
137+
this.server.respondWith("GET", "/test", "Clicked!");
138+
make('<div hx-indicator="#a1">' +
139+
' <button id="btn" hx-get="/test" hx-indicator="inherit, #a2">Click Me!</button>' +
140+
'</div>')
141+
var btn = byId("btn")
142+
var a1 = make('<a id="a1"></a>')
143+
var a2 = make('<a id="a2"></a>')
144+
btn.click();
145+
btn.classList.contains("htmx-request").should.equal(false);
146+
a1.classList.contains("htmx-request").should.equal(true);
147+
a2.classList.contains("htmx-request").should.equal(true);
148+
this.server.respond();
149+
btn.classList.contains("htmx-request").should.equal(false);
150+
a1.classList.contains("htmx-request").should.equal(false);
151+
a2.classList.contains("htmx-request").should.equal(false);
152+
});
153+
154+
it('`inherit` can be used to expand multiple parents hx-indicator', function () {
155+
this.server.respondWith("GET", "/test", "Clicked!");
156+
make('<div hx-indicator="#a1">' +
157+
' <div hx-indicator="inherit, #a2">' +
158+
' <button id="btn" hx-get="/test" hx-indicator="inherit, #a3">Click Me!</button>' +
159+
' </div>' +
160+
'</div>')
161+
var btn = byId("btn")
162+
var a1 = make('<a id="a1"></a>')
163+
var a2 = make('<a id="a2"></a>')
164+
var a3 = make('<a id="a3"></a>')
165+
btn.click();
166+
btn.classList.contains("htmx-request").should.equal(false);
167+
a1.classList.contains("htmx-request").should.equal(true);
168+
a2.classList.contains("htmx-request").should.equal(true)
169+
a3.classList.contains("htmx-request").should.equal(true);
170+
this.server.respond();
171+
btn.classList.contains("htmx-request").should.equal(false);
172+
a1.classList.contains("htmx-request").should.equal(false);
173+
a2.classList.contains("htmx-request").should.equal(false);
174+
a3.classList.contains("htmx-request").should.equal(false);
175+
});
136176

177+
it('`inherit` chain breaks properly', function () {
178+
this.server.respondWith("GET", "/test", "Clicked!");
179+
make('<div hx-indicator="#a1">' +
180+
' <div hx-indicator="#a2">' +
181+
' <button id="btn" hx-get="/test" hx-indicator="inherit, #a3">Click Me!</button>' +
182+
' </div>' +
183+
'</div>')
184+
var btn = byId("btn")
185+
var a1 = make('<a id="a1"></a>')
186+
var a2 = make('<a id="a2"></a>')
187+
var a3 = make('<a id="a3"></a>')
188+
btn.click();
189+
btn.classList.contains("htmx-request").should.equal(false);
190+
a1.classList.contains("htmx-request").should.equal(false);
191+
a2.classList.contains("htmx-request").should.equal(true)
192+
a3.classList.contains("htmx-request").should.equal(true);
193+
this.server.respond();
194+
btn.classList.contains("htmx-request").should.equal(false);
195+
a1.classList.contains("htmx-request").should.equal(false);
196+
a2.classList.contains("htmx-request").should.equal(false);
197+
a3.classList.contains("htmx-request").should.equal(false);
198+
})
137199
})

0 commit comments

Comments
 (0)