mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-10-03 07:45:21 +00:00
Merge branch 'dev' of https://github.com/bigskysoftware/htmx
This commit is contained in:
commit
8d655da761
@ -5,7 +5,7 @@
|
|||||||
"AJAX",
|
"AJAX",
|
||||||
"HTML"
|
"HTML"
|
||||||
],
|
],
|
||||||
"version": "1.2.1",
|
"version": "1.3.0",
|
||||||
"homepage": "https://htmx.org/",
|
"homepage": "https://htmx.org/",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/bigskysoftware/htmx/issues"
|
"url": "https://github.com/bigskysoftware/htmx/issues"
|
||||||
|
59
src/htmx.js
59
src/htmx.js
@ -847,12 +847,17 @@ return (function () {
|
|||||||
triggerSpec.changed = true;
|
triggerSpec.changed = true;
|
||||||
} else if (token === "once") {
|
} else if (token === "once") {
|
||||||
triggerSpec.once = true;
|
triggerSpec.once = true;
|
||||||
|
} else if (token === "consume") {
|
||||||
|
triggerSpec.consume = true;
|
||||||
} else if (token === "delay" && tokens[0] === ":") {
|
} else if (token === "delay" && tokens[0] === ":") {
|
||||||
tokens.shift();
|
tokens.shift();
|
||||||
triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
|
triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
|
||||||
} else if (token === "from" && tokens[0] === ":") {
|
} else if (token === "from" && tokens[0] === ":") {
|
||||||
tokens.shift();
|
tokens.shift();
|
||||||
triggerSpec.from = consumeUntil(tokens, WHITESPACE_OR_COMMA);
|
triggerSpec.from = consumeUntil(tokens, WHITESPACE_OR_COMMA);
|
||||||
|
} else if (token === "target" && tokens[0] === ":") {
|
||||||
|
tokens.shift();
|
||||||
|
triggerSpec.target = consumeUntil(tokens, WHITESPACE_OR_COMMA);
|
||||||
} else if (token === "throttle" && tokens[0] === ":") {
|
} else if (token === "throttle" && tokens[0] === ":") {
|
||||||
tokens.shift();
|
tokens.shift();
|
||||||
triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
|
triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
|
||||||
@ -962,9 +967,20 @@ return (function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var eventData = getInternalData(evt);
|
var eventData = getInternalData(evt);
|
||||||
|
if (eventData.handledFor == null) {
|
||||||
|
eventData.handledFor = [];
|
||||||
|
}
|
||||||
var elementData = getInternalData(elt);
|
var elementData = getInternalData(elt);
|
||||||
if (!eventData.handled) {
|
if (eventData.handledFor.indexOf(elt) < 0) {
|
||||||
eventData.handled = true;
|
eventData.handledFor.push(elt);
|
||||||
|
if (triggerSpec.consume) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
}
|
||||||
|
if (triggerSpec.target && evt.target) {
|
||||||
|
if (!evt.target.matches(triggerSpec.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (triggerSpec.once) {
|
if (triggerSpec.once) {
|
||||||
if (elementData.triggeredOnce) {
|
if (elementData.triggeredOnce) {
|
||||||
return;
|
return;
|
||||||
@ -1174,6 +1190,7 @@ return (function () {
|
|||||||
var settleInfo = makeSettleInfo(elt);
|
var settleInfo = makeSettleInfo(elt);
|
||||||
|
|
||||||
selectAndSwap(swapSpec.swapStyle, elt, target, response, settleInfo)
|
selectAndSwap(swapSpec.swapStyle, elt, target, response, settleInfo)
|
||||||
|
settleImmediately(settleInfo.tasks)
|
||||||
triggerEvent(elt, "htmx:sseMessage", event)
|
triggerEvent(elt, "htmx:sseMessage", event)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1427,7 +1444,7 @@ return (function () {
|
|||||||
while(historyCache.length > 0){
|
while(historyCache.length > 0){
|
||||||
try {
|
try {
|
||||||
localStorage.setItem("htmx-history-cache", JSON.stringify(historyCache));
|
localStorage.setItem("htmx-history-cache", JSON.stringify(historyCache));
|
||||||
return;
|
break;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
triggerErrorEvent(getDocument().body, "htmx:historyCacheError", {cause:e, cache: historyCache})
|
triggerErrorEvent(getDocument().body, "htmx:historyCacheError", {cause:e, cache: historyCache})
|
||||||
historyCache.shift(); // shrink the cache and retry
|
historyCache.shift(); // shrink the cache and retry
|
||||||
@ -1923,16 +1940,22 @@ return (function () {
|
|||||||
function ajaxHelper(verb, path, context) {
|
function ajaxHelper(verb, path, context) {
|
||||||
if (context) {
|
if (context) {
|
||||||
if (context instanceof Element || isType(context, 'String')) {
|
if (context instanceof Element || isType(context, 'String')) {
|
||||||
issueAjaxRequest(verb, path, null, null, null, resolveTarget(context));
|
return issueAjaxRequest(verb, path, null, null, null, resolveTarget(context));
|
||||||
} else {
|
} else {
|
||||||
issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, context.handler, resolveTarget(context.target));
|
return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, context.handler, resolveTarget(context.target));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
issueAjaxRequest(verb, path);
|
return issueAjaxRequest(verb, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function issueAjaxRequest(verb, path, elt, event, responseHandler, targetOverride) {
|
function issueAjaxRequest(verb, path, elt, event, responseHandler, targetOverride) {
|
||||||
|
var resolve = null;
|
||||||
|
var reject = null;
|
||||||
|
var promise = new Promise(function (_resolve, _reject) {
|
||||||
|
resolve = _resolve;
|
||||||
|
reject = _reject;
|
||||||
|
});
|
||||||
if(elt == null) {
|
if(elt == null) {
|
||||||
elt = getDocument().body;
|
elt = getDocument().body;
|
||||||
}
|
}
|
||||||
@ -1970,12 +1993,18 @@ return (function () {
|
|||||||
// prompt returns null if cancelled and empty string if accepted with no entry
|
// prompt returns null if cancelled and empty string if accepted with no entry
|
||||||
if (promptResponse === null ||
|
if (promptResponse === null ||
|
||||||
!triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target}))
|
!triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target}))
|
||||||
return endRequestLock();
|
resolve();
|
||||||
|
endRequestLock();
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
|
var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
|
||||||
if (confirmQuestion) {
|
if (confirmQuestion) {
|
||||||
if(!confirm(confirmQuestion)) return endRequestLock();
|
if(!confirm(confirmQuestion)) {
|
||||||
|
resolve();
|
||||||
|
endRequestLock()
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
@ -2018,7 +2047,9 @@ return (function () {
|
|||||||
|
|
||||||
if(errors && errors.length > 0){
|
if(errors && errors.length > 0){
|
||||||
triggerEvent(elt, 'htmx:validation:halted', requestConfig)
|
triggerEvent(elt, 'htmx:validation:halted', requestConfig)
|
||||||
return endRequestLock();
|
resolve();
|
||||||
|
endRequestLock();
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
var splitPath = path.split("#");
|
var splitPath = path.split("#");
|
||||||
@ -2071,6 +2102,7 @@ return (function () {
|
|||||||
}
|
}
|
||||||
triggerEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
triggerEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
||||||
triggerEvent(finalElt, 'htmx:afterOnLoad', responseInfo);
|
triggerEvent(finalElt, 'htmx:afterOnLoad', responseInfo);
|
||||||
|
resolve();
|
||||||
endRequestLock();
|
endRequestLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2082,6 +2114,7 @@ return (function () {
|
|||||||
}
|
}
|
||||||
triggerErrorEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
triggerErrorEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
||||||
triggerErrorEvent(finalElt, 'htmx:sendError', responseInfo);
|
triggerErrorEvent(finalElt, 'htmx:sendError', responseInfo);
|
||||||
|
reject();
|
||||||
endRequestLock();
|
endRequestLock();
|
||||||
}
|
}
|
||||||
xhr.onabort = function() {
|
xhr.onabort = function() {
|
||||||
@ -2092,9 +2125,14 @@ return (function () {
|
|||||||
}
|
}
|
||||||
triggerErrorEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
triggerErrorEvent(finalElt, 'htmx:afterRequest', responseInfo);
|
||||||
triggerErrorEvent(finalElt, 'htmx:sendAbort', responseInfo);
|
triggerErrorEvent(finalElt, 'htmx:sendAbort', responseInfo);
|
||||||
|
reject();
|
||||||
endRequestLock();
|
endRequestLock();
|
||||||
}
|
}
|
||||||
if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)) return endRequestLock();
|
if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)){
|
||||||
|
resolve();
|
||||||
|
endRequestLock()
|
||||||
|
return promise
|
||||||
|
}
|
||||||
var indicators = addRequestIndicatorClasses(elt);
|
var indicators = addRequestIndicatorClasses(elt);
|
||||||
|
|
||||||
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
|
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
|
||||||
@ -2109,6 +2147,7 @@ return (function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
xhr.send(verb === 'get' ? null : encodeParamsForBody(xhr, elt, filteredParameters));
|
xhr.send(verb === 'get' ? null : encodeParamsForBody(xhr, elt, filteredParameters));
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAjaxResponse(elt, responseInfo) {
|
function handleAjaxResponse(elt, responseInfo) {
|
||||||
|
@ -73,26 +73,22 @@ describe("hx-swap attribute", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="afterbegin">*</div>')
|
var div = make('<div hx-get="/test" hx-swap="afterbegin">*</div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1*");
|
div.innerText.should.equal("1*");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**");
|
div.innerText.should.equal("21*");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("2**");
|
div.innerText.should.equal("321*");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("***");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('swap afterbegin properly with no initial content', function()
|
it('swap afterbegin properly with no initial content', function()
|
||||||
@ -100,26 +96,22 @@ describe("hx-swap attribute", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="afterbegin"></div>')
|
var div = make('<div hx-get="/test" hx-swap="afterbegin"></div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1");
|
div.innerText.should.equal("1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*");
|
div.innerText.should.equal("21");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("2*");
|
div.innerText.should.equal("321");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("**");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('swap afterend properly', function()
|
it('swap afterend properly', function()
|
||||||
@ -152,58 +144,50 @@ describe("hx-swap attribute", function(){
|
|||||||
removeWhiteSpace(parent.innerText).should.equal("***");
|
removeWhiteSpace(parent.innerText).should.equal("***");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('swap beforeend properly', function()
|
it('handles beforeend properly', function()
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="beforeend">*</div>')
|
var div = make('<div hx-get="/test" hx-swap="beforeend">*</div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*1");
|
div.innerText.should.equal("*1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**");
|
div.innerText.should.equal("*12");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**2");
|
div.innerText.should.equal("*123");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("***");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('swap beforeend properly with no initial content', function()
|
it('handles beforeend properly with no initial content', function()
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="beforeend"></div>')
|
var div = make('<div hx-get="/test" hx-swap="beforeend"></div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1");
|
div.innerText.should.equal("1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*");
|
div.innerText.should.equal("12");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*2");
|
div.innerText.should.equal("123");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("**");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('properly parses various swap specifications', function(){
|
it('properly parses various swap specifications', function(){
|
||||||
|
@ -385,15 +385,18 @@ describe("hx-trigger attribute", function(){
|
|||||||
this.server.respond();
|
this.server.respond();
|
||||||
requests.should.equal(1);
|
requests.should.equal(1);
|
||||||
|
|
||||||
|
requests.should.equal(1);
|
||||||
|
|
||||||
div1.click();
|
div1.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div1.innerHTML.should.equal("Clicked");
|
div1.innerHTML.should.equal("Clicked");
|
||||||
|
|
||||||
|
requests.should.equal(2);
|
||||||
|
|
||||||
document.body.click();
|
document.body.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
|
|
||||||
// event listener should have been removed when this element was removed
|
requests.should.equal(2);
|
||||||
requests.should.equal(1);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('multiple triggers with from clauses mixed in work', function()
|
it('multiple triggers with from clauses mixed in work', function()
|
||||||
@ -414,4 +417,57 @@ describe("hx-trigger attribute", function(){
|
|||||||
div1.innerHTML.should.equal("Requests: 2");
|
div1.innerHTML.should.equal("Requests: 2");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('event listeners can filter on target', function()
|
||||||
|
{
|
||||||
|
var requests = 0;
|
||||||
|
this.server.respondWith("GET", "/test", function (xhr) {
|
||||||
|
requests++;
|
||||||
|
xhr.respond(200, {}, "Requests: " + requests);
|
||||||
|
});
|
||||||
|
|
||||||
|
var div1 = make('<div>' +
|
||||||
|
'<div id="d1" hx-trigger="click from:body target:#d3" hx-get="/test">Requests: 0</div>' +
|
||||||
|
'<div id="d2"></div>' +
|
||||||
|
'<div id="d3"></div>' +
|
||||||
|
'</div>');
|
||||||
|
var div1 = byId("d1");
|
||||||
|
var div2 = byId("d2");
|
||||||
|
var div3 = byId("d3");
|
||||||
|
|
||||||
|
div1.innerHTML.should.equal("Requests: 0");
|
||||||
|
document.body.click();
|
||||||
|
this.server.respond();
|
||||||
|
requests.should.equal(0);
|
||||||
|
|
||||||
|
div1.click();
|
||||||
|
this.server.respond();
|
||||||
|
requests.should.equal(0);
|
||||||
|
|
||||||
|
div2.click();
|
||||||
|
this.server.respond();
|
||||||
|
requests.should.equal(0);
|
||||||
|
|
||||||
|
div3.click();
|
||||||
|
this.server.respond();
|
||||||
|
requests.should.equal(1);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('consume prevents event propogation', function()
|
||||||
|
{
|
||||||
|
this.server.respondWith("GET", "/foo", "foo");
|
||||||
|
this.server.respondWith("GET", "/bar", "bar");
|
||||||
|
var div = make("<div hx-trigger='click' hx-get='/foo'>" +
|
||||||
|
" <div id='d1' hx-trigger='click consume' hx-get='/bar'></div>" +
|
||||||
|
"</div>");
|
||||||
|
|
||||||
|
byId("d1").click();
|
||||||
|
this.server.respond();
|
||||||
|
|
||||||
|
// should not have been replaced by click
|
||||||
|
byId("d1").parentElement.should.equal(div);
|
||||||
|
byId("d1").innerText.should.equal("bar");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -84,26 +84,22 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="afterbegin">*</div>')
|
var div = make('<div hx-get="/test" hx-swap="afterbegin">*</div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1*");
|
div.innerText.should.equal("1*");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**");
|
div.innerText.should.equal("21*");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("2**");
|
div.innerText.should.equal("321*");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("***");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles afterbegin properly with no initial content', function()
|
it('handles afterbegin properly with no initial content', function()
|
||||||
@ -111,26 +107,22 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="afterbegin"></div>')
|
var div = make('<div hx-get="/test" hx-swap="afterbegin"></div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1");
|
div.innerText.should.equal("1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*");
|
div.innerText.should.equal("21");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("2*");
|
div.innerText.should.equal("321");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("**");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles afterend properly', function()
|
it('handles afterend properly', function()
|
||||||
@ -168,26 +160,22 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="beforeend">*</div>')
|
var div = make('<div hx-get="/test" hx-swap="beforeend">*</div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*1");
|
div.innerText.should.equal("*1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**");
|
div.innerText.should.equal("*12");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("**2");
|
div.innerText.should.equal("*123");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("***");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles beforeend properly with no initial content', function()
|
it('handles beforeend properly with no initial content', function()
|
||||||
@ -195,26 +183,22 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
this.server.respondWith("GET", "/test", function(xhr){
|
this.server.respondWith("GET", "/test", function(xhr){
|
||||||
i++;
|
i++;
|
||||||
xhr.respond(200, {}, '<a id="a' + i + '" hx-get="/test2" hx-swap="innerHTML">' + i + '</a>');
|
xhr.respond(200, {}, "" + i);
|
||||||
});
|
});
|
||||||
this.server.respondWith("GET", "/test2", "*");
|
|
||||||
|
|
||||||
var div = make('<div hx-get="/test" hx-swap="beforeend"></div>')
|
var div = make('<div hx-get="/test" hx-swap="beforeend"></div>')
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("1");
|
div.innerText.should.equal("1");
|
||||||
|
|
||||||
byId("a1").click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*");
|
div.innerText.should.equal("12");
|
||||||
|
|
||||||
div.click();
|
div.click();
|
||||||
this.server.respond();
|
this.server.respond();
|
||||||
div.innerText.should.equal("*2");
|
div.innerText.should.equal("123");
|
||||||
|
|
||||||
byId("a2").click();
|
|
||||||
this.server.respond();
|
|
||||||
div.innerText.should.equal("**");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles hx-target properly', function()
|
it('handles hx-target properly', function()
|
||||||
@ -551,7 +535,7 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
|
|
||||||
it('text nodes dont screw up settling via variable capture', function()
|
it('text nodes dont screw up settling via variable capture', function()
|
||||||
{
|
{
|
||||||
this.server.respondWith("GET", "/test", "<div id='d1' hx-get='/test2'></div>fooo");
|
this.server.respondWith("GET", "/test", "<div id='d1' hx-trigger='click consume' hx-get='/test2'></div>fooo");
|
||||||
this.server.respondWith("GET", "/test2", "clicked");
|
this.server.respondWith("GET", "/test2", "clicked");
|
||||||
var div = make("<div hx-get='/test'/>");
|
var div = make("<div hx-get='/test'/>");
|
||||||
div.click();
|
div.click();
|
||||||
@ -561,7 +545,6 @@ describe("Core htmx AJAX Tests", function(){
|
|||||||
byId("d1").innerHTML.should.equal("clicked");
|
byId("d1").innerHTML.should.equal("clicked");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('script nodes evaluate', function()
|
it('script nodes evaluate', function()
|
||||||
{
|
{
|
||||||
var globalWasCalled = false;
|
var globalWasCalled = false;
|
||||||
|
@ -261,5 +261,36 @@ describe("Core htmx API test", function(){
|
|||||||
calledEvent.should.equal(true);
|
calledEvent.should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('ajax api works', function()
|
||||||
|
{
|
||||||
|
this.server.respondWith("GET", "/test", "foo!");
|
||||||
|
var div = make("<div></div>");
|
||||||
|
htmx.ajax("GET", "/test", div)
|
||||||
|
this.server.respond();
|
||||||
|
div.innerHTML.should.equal("foo!");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ajax api works by ID', function()
|
||||||
|
{
|
||||||
|
this.server.respondWith("GET", "/test", "foo!");
|
||||||
|
var div = make("<div id='d1'></div>");
|
||||||
|
htmx.ajax("GET", "/test", "#d1")
|
||||||
|
this.server.respond();
|
||||||
|
div.innerHTML.should.equal("foo!");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ajax returns a promise', function(done)
|
||||||
|
{
|
||||||
|
this.server.respondWith("GET", "/test", "foo!");
|
||||||
|
var div = make("<div id='d1'></div>");
|
||||||
|
var promise = htmx.ajax("GET", "/test", "#d1");
|
||||||
|
this.server.respond();
|
||||||
|
div.innerHTML.should.equal("foo!");
|
||||||
|
promise.then(function(){
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -41,4 +41,24 @@ describe("Core htmx internals Tests", function() {
|
|||||||
chai.expect(htmx._("tokenizeString")("aa.aa")).to.be.deep.equal(['aa', '.', 'aa']);
|
chai.expect(htmx._("tokenizeString")("aa.aa")).to.be.deep.equal(['aa', '.', 'aa']);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("tags respond correctly to shouldCancel", function() {
|
||||||
|
var anchorThatShouldCancel = make("<a href='/foo'></a>");
|
||||||
|
htmx._("shouldCancel")(anchorThatShouldCancel).should.equal(true);
|
||||||
|
|
||||||
|
var anchorThatShouldNotCancel = make("<a href='#'></a>");
|
||||||
|
htmx._("shouldCancel")(anchorThatShouldNotCancel).should.equal(false);
|
||||||
|
|
||||||
|
var form = make("<form></form>");
|
||||||
|
htmx._("shouldCancel")(form).should.equal(true);
|
||||||
|
|
||||||
|
var form = make("<form><input id='i1' type='submit'></form>");
|
||||||
|
var input = byId("i1");
|
||||||
|
htmx._("shouldCancel")(input).should.equal(true);
|
||||||
|
|
||||||
|
var form = make("<form><button id='b1' type='submit'></form>");
|
||||||
|
var button = byId("b1");
|
||||||
|
htmx._("shouldCancel")(button).should.equal(true);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
@ -110,4 +110,21 @@ describe("Core htmx Regression Tests", function(){
|
|||||||
defaultPrevented.should.equal(true);
|
defaultPrevented.should.equal(true);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('two elements can listen for the same event on another element', function() {
|
||||||
|
this.server.respondWith("GET", "/test", "triggered");
|
||||||
|
|
||||||
|
make('<div id="d1" hx-trigger="click from:body" hx-get="/test"></div>' +
|
||||||
|
' <div id="d2" hx-trigger="click from:body" hx-get="/test"></div>');
|
||||||
|
|
||||||
|
|
||||||
|
var div1 = byId("d1");
|
||||||
|
var div2 = byId("d2");
|
||||||
|
|
||||||
|
document.body.click();
|
||||||
|
this.server.respond();
|
||||||
|
|
||||||
|
div2.innerHTML.should.equal("triggered");
|
||||||
|
div1.innerHTML.should.equal("triggered");
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -58,6 +58,9 @@ is seen again it will reset the delay.
|
|||||||
* `throttle:<timing declaration>` - a throttle will occur before an event triggers a request. If the event
|
* `throttle:<timing declaration>` - a throttle will occur before an event triggers a request. If the event
|
||||||
is seen again before the delay completes it is ignored, the element will trigger at the end of the delay.
|
is seen again before the delay completes it is ignored, the element will trigger at the end of the delay.
|
||||||
* `from:<CSS selector>` - allows the event that triggers a request to come from another element in the document (e.g. listening to a key event on the body, to support hot keys)
|
* `from:<CSS selector>` - allows the event that triggers a request to come from another element in the document (e.g. listening to a key event on the body, to support hot keys)
|
||||||
|
* `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 listening on the body, but with a target filter for a
|
||||||
|
child
|
||||||
|
|
||||||
Here is an example of a search box that searches on `keyup`, but only if the search value has changed
|
Here is an example of a search box that searches on `keyup`, but only if the search value has changed
|
||||||
and the user hasn't typed anything new for 1 second:
|
and the user hasn't typed anything new for 1 second:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user