Move events from <event name>.htmx (jQuery style) to htmx:<event name> (zepto style)

fixes https://github.com/bigskysoftware/htmx/issues/109
This commit is contained in:
carson 2020-06-30 10:45:30 -07:00
parent 70d770a1b5
commit 4f3cf2d889
19 changed files with 234 additions and 150 deletions

View File

@ -1,6 +1,6 @@
htmx.defineExtension('ajax-header', {
onEvent: function (name, evt) {
if (name === "configRequest.htmx") {
if (name === "htmx:configRequest") {
evt.detail.headers['X-Requested-With'] = 'XMLHttpRequest';
}
}

View File

@ -69,7 +69,7 @@
htmx.defineExtension('class-tools', {
onEvent: function (name, evt) {
if (name === "processedNode.htmx") {
if (name === "htmx:processedNode") {
var elt = evt.detail.elt;
maybeProcessClasses(elt);
if (elt.querySelectorAll) {

View File

@ -11,7 +11,7 @@
htmx.defineExtension('include-vals', {
onEvent: function (name, evt) {
if (name === "configRequest.htmx") {
if (name === "htmx:configRequest") {
var includeValsElt = htmx.closest(evt.detail.elt, "[include-vals],[data-include-vals]");
if (includeValsElt) {
var includeVals = includeValsElt.getAttribute("include-vals") || includeValsElt.getAttribute("data-include-vals");

View File

@ -1,6 +1,6 @@
htmx.defineExtension('json-enc', {
onEvent: function (name, evt) {
if (name === "configRequest.htmx") {
if (name === "htmx:configRequest") {
evt.detail.headers['Content-Type'] = "application/json";
}
},

View File

@ -1,6 +1,6 @@
htmx.defineExtension('method-override', {
onEvent: function (name, evt) {
if (name === "configRequest.htmx") {
if (name === "htmx:configRequest") {
var method = evt.detail.verb;
if (method !== "get" || method !== "post") {
evt.detail.headers['X-HTTP-Method-Override'] = method.toUpperCase();

View File

@ -17,7 +17,7 @@
htmx.defineExtension('path-deps', {
onEvent: function (name, evt) {
if (name === "afterRequest.htmx") {
if (name === "htmx:afterRequest") {
var xhr = evt.detail.xhr;
// mutating call
if (xhr.method !== "GET") {

View File

@ -10,7 +10,7 @@
htmx.defineExtension('remove-me', {
onEvent: function (name, evt) {
if (name === "processedNode.htmx") {
if (name === "htmx:processedNode") {
var elt = evt.detail.elt;
if (elt.getAttribute) {
maybeRemoveMe(elt);

View File

@ -205,7 +205,7 @@ return (function () {
}
function onLoadHelper(callback) {
var value = htmx.on("load.htmx", function(evt) {
var value = htmx.on("htmx:load", function(evt) {
callback(evt.detail.elt);
});
return value;
@ -378,7 +378,7 @@ return (function () {
swap(oobValue, target, target, fragment, settleInfo);
} else {
child.parentNode.removeChild(child);
triggerErrorEvent(getDocument().body, "oobErrorNoTarget.htmx", {content: child})
triggerErrorEvent(getDocument().body, "htmx:oobErrorNoTarget", {content: child})
}
return oobValue;
}
@ -411,7 +411,7 @@ return (function () {
return function () {
processNode(child, true);
processScripts(child);
triggerEvent(child, 'load.htmx', {});
triggerEvent(child, 'htmx:load', {});
};
}
@ -752,7 +752,7 @@ return (function () {
function processWebSocketSource(elt, wssSource) {
var socket = htmx.createWebSocket(wssSource);
socket.onerror = function (e) {
triggerErrorEvent(elt, "wsError.htmx", {error:e, socket:socket});
triggerErrorEvent(elt, "htmx:wsError", {error:e, socket:socket});
maybeCloseWebSocketSource(elt);
};
getInternalData(elt).webSocket = socket;
@ -802,7 +802,7 @@ return (function () {
}
});
} else {
triggerErrorEvent(elt, "noWebSocketSourceError.htmx");
triggerErrorEvent(elt, "htmx:noWebSocketSourceError");
}
}
@ -826,7 +826,7 @@ return (function () {
function processSSESource(elt, sseSrc) {
var source = htmx.createEventSource(sseSrc);
source.onerror = function (e) {
triggerErrorEvent(elt, "sseError.htmx", {error:e, source:source});
triggerErrorEvent(elt, "htmx:sseError", {error:e, source:source});
maybeCloseSSESource(elt);
};
getInternalData(elt).sseEventSource = source;
@ -850,7 +850,7 @@ return (function () {
getInternalData(elt).sseListener = sseListener;
sseEventSource.addEventListener(sseEventName, sseListener);
} else {
triggerErrorEvent(elt, "noSSESourceError.htmx");
triggerErrorEvent(elt, "htmx:noSSESourceError");
}
}
@ -957,7 +957,7 @@ return (function () {
if (wsInfo) {
processWebSocketInfo(elt, nodeData, wsInfo);
}
triggerEvent(elt, "processedNode.htmx");
triggerEvent(elt, "htmx:processedNode");
}
}
@ -986,7 +986,7 @@ return (function () {
}
function ignoreEventForLogging(eventName) {
return eventName === "processedNode.htmx"
return eventName === "htmx:processedNode"
}
function withExtensions(elt, toDo) {
@ -1018,7 +1018,7 @@ return (function () {
}
if (detail.error) {
logError(detail.error);
triggerEvent(elt, "error.htmx", {errorInfo:detail})
triggerEvent(elt, "htmx:error", {errorInfo:detail})
}
var eventResult = elt.dispatchEvent(event);
withExtensions(elt, function (extension) {
@ -1065,7 +1065,7 @@ return (function () {
function saveHistory() {
var elt = getHistoryElement();
var path = currentPathForHistory || location.pathname+location.search;
triggerEvent(getDocument().body, "beforeHistorySave.htmx", {path:path, historyElt:elt});
triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path:path, historyElt:elt});
if(htmx.config.historyEnabled) history.replaceState({}, getDocument().title, window.location.href);
saveToHistoryCache(path, elt.innerHTML, getDocument().title, window.scrollY);
}
@ -1084,11 +1084,11 @@ return (function () {
function loadHistoryFromServer(path) {
var request = new XMLHttpRequest();
var details = {path: path, xhr:request};
triggerEvent(getDocument().body, "historyCacheMiss.htmx", details);
triggerEvent(getDocument().body, "htmx:historyCacheMiss", details);
request.open('GET', path, true);
request.onload = function () {
if (this.status >= 200 && this.status < 400) {
triggerEvent(getDocument().body, "historyCacheMissLoad.htmx", details);
triggerEvent(getDocument().body, "htmx:historyCacheMissLoad", details);
var fragment = makeFragment(this.response);
fragment = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment;
var historyElement = getHistoryElement();
@ -1097,7 +1097,7 @@ return (function () {
settleImmediately(settleInfo.tasks);
currentPathForHistory = path;
} else {
triggerErrorEvent(getDocument().body, "historyCacheMissLoadError.htmx", details);
triggerErrorEvent(getDocument().body, "htmx:historyCacheMissLoadError", details);
}
};
request.send();
@ -1106,7 +1106,7 @@ return (function () {
function restoreHistory(path) {
saveHistory(currentPathForHistory);
path = path || location.pathname+location.search;
triggerEvent(getDocument().body, "historyRestore.htmx", {path:path});
triggerEvent(getDocument().body, "htmx:historyRestore", {path:path});
var cached = getCachedHistory(path);
if (cached) {
var fragment = makeFragment(cached.content);
@ -1398,7 +1398,7 @@ return (function () {
function issueAjaxRequest(elt, verb, path, eventTarget) {
var target = getTarget(elt);
if (target == null) {
triggerErrorEvent(elt, 'targetError.htmx', {target: getAttributeValue(elt, "hx-target")});
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
return;
}
var eltData = getInternalData(elt);
@ -1415,7 +1415,7 @@ return (function () {
var promptResponse = prompt(promptQuestion);
// prompt returns null if cancelled and empty string if accepted with no entry
if (promptResponse === null ||
!triggerEvent(elt, 'prompt.htmx', {prompt: promptResponse, target:target}))
!triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target}))
return endRequestLock();
}
@ -1448,7 +1448,7 @@ return (function () {
verb:verb,
path:path
};
if(!triggerEvent(elt, 'configRequest.htmx', requestConfig)) return endRequestLock();
if(!triggerEvent(elt, 'htmx:configRequest', requestConfig)) return endRequestLock();
// copy out in case the object was overwritten
path = requestConfig.path;
verb = requestConfig.verb;
@ -1489,7 +1489,7 @@ return (function () {
var eventDetail = {xhr: xhr, target: target};
xhr.onload = function () {
try {
if (!triggerEvent(elt, 'beforeOnLoad.htmx', eventDetail)) return;
if (!triggerEvent(elt, 'htmx:beforeOnLoad', eventDetail)) return;
handleTrigger(elt, this.getResponseHeader("HX-Trigger"));
var pushedUrl = this.getResponseHeader("HX-Push");
@ -1502,7 +1502,7 @@ return (function () {
}
// don't process 'No Content' response
if (this.status !== 204) {
if (!triggerEvent(target, 'beforeSwap.htmx', eventDetail)) return;
if (!triggerEvent(target, 'htmx:beforeSwap', eventDetail)) return;
var resp = this.response;
withExtensions(elt, function(extension){
@ -1543,7 +1543,7 @@ return (function () {
if (elt.classList) {
elt.classList.add("htmx-settling");
}
triggerEvent(elt, 'afterSwap.htmx', eventDetail);
triggerEvent(elt, 'htmx:afterSwap', eventDetail);
});
if (anchor) {
location.hash = anchor;
@ -1556,13 +1556,13 @@ return (function () {
if (elt.classList) {
elt.classList.remove("htmx-settling");
}
triggerEvent(elt, 'afterSettle.htmx', eventDetail);
triggerEvent(elt, 'htmx:afterSettle', eventDetail);
});
// push URL and save new page
if (shouldSaveHistory) {
var pathToPush = pushedUrl || finalPathForGet || path;
pushUrlIntoHistory(pathToPush);
triggerEvent(getDocument().body, 'pushedIntoHistory.htmx', {path:pathToPush});
triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path:pathToPush});
}
updateScrollState(target, settleInfo.elts, swapSpec);
}
@ -1573,7 +1573,7 @@ return (function () {
doSettle();
}
} catch (e) {
triggerErrorEvent(elt, 'swapError.htmx', eventDetail);
triggerErrorEvent(elt, 'htmx:swapError', eventDetail);
throw e;
}
};
@ -1585,25 +1585,25 @@ return (function () {
}
}
} else {
triggerErrorEvent(elt, 'responseError.htmx', mergeObjects({error: "Response Status Error Code " + this.status + " from " + path}, eventDetail));
triggerErrorEvent(elt, 'htmx:responseError', mergeObjects({error: "Response Status Error Code " + this.status + " from " + path}, eventDetail));
}
} catch (e) {
triggerErrorEvent(elt, 'onLoadError.htmx', mergeObjects({error:e}, eventDetail));
triggerErrorEvent(elt, 'htmx:onLoadError', mergeObjects({error:e}, eventDetail));
throw e;
} finally {
removeRequestIndicatorClasses(elt);
triggerEvent(elt, 'afterRequest.htmx', eventDetail);
triggerEvent(elt, 'afterOnLoad.htmx', eventDetail);
triggerEvent(elt, 'htmx:afterRequest', eventDetail);
triggerEvent(elt, 'htmx:afterOnLoad', eventDetail);
endRequestLock();
}
}
xhr.onerror = function () {
removeRequestIndicatorClasses(elt);
triggerErrorEvent(elt, 'afterRequest.htmx', eventDetail);
triggerErrorEvent(elt, 'sendError.htmx', eventDetail);
triggerErrorEvent(elt, 'htmx:afterRequest', eventDetail);
triggerErrorEvent(elt, 'htmx:sendError', eventDetail);
endRequestLock();
}
if(!triggerEvent(elt, 'beforeRequest.htmx', eventDetail)) return endRequestLock();
if(!triggerEvent(elt, 'htmx:beforeRequest', eventDetail)) return endRequestLock();
addRequestIndicatorClasses(elt);
xhr.send(verb === 'get' ? null : encodeParamsForBody(xhr, elt, filteredParameters));
}
@ -1696,7 +1696,7 @@ return (function () {
mergeMetaConfig();
var body = getDocument().body;
processNode(body, true);
triggerEvent(body, 'load.htmx', {});
triggerEvent(body, 'htmx:load', {});
window.onpopstate = function () {
restoreHistory();
};

View File

@ -8,21 +8,21 @@ describe("hx-ext attribute", function() {
clearWorkArea();
htmx.defineExtension("ext-1", {
onEvent : function(name, evt) {
if(name === "afterRequest.htmx"){
if(name === "htmx:afterRequest"){
ext1Calls++;
}
}
});
htmx.defineExtension("ext-2", {
onEvent : function(name, evt) {
if(name === "afterRequest.htmx"){
if(name === "htmx:afterRequest"){
ext2Calls++;
}
}
});
htmx.defineExtension("ext-3", {
onEvent : function(name, evt) {
if(name === "afterRequest.htmx"){
if(name === "htmx:afterRequest"){
ext3Calls++;
}
}

View File

@ -114,7 +114,7 @@ describe("hx-push-url attribute", function() {
it("afterSettle.htmx is called when replacing outerHTML", function () {
var called = false;
var handler = htmx.on("afterSettle.htmx", function (evt) {
var handler = htmx.on("htmx:afterSettle", function (evt) {
called = true;
});
try {
@ -126,13 +126,13 @@ describe("hx-push-url attribute", function() {
this.server.respond();
should.equal(called, true);
} finally {
htmx.off("afterSettle.htmx", handler);
htmx.off("htmx:afterSettle", handler);
}
});
it("should include parameters on a get", function () {
var path = "";
var handler = htmx.on("pushedIntoHistory.htmx", function (evt) {
var handler = htmx.on("htmx:pushedIntoHistory", function (evt) {
path = evt.detail.path;
});
try {
@ -145,7 +145,7 @@ describe("hx-push-url attribute", function() {
form.textContent.should.equal("second")
path.should.equal("/test?foo=bar")
} finally {
htmx.off("pushedIntoHistory.htmx", handler);
htmx.off("htmx:pushedIntoHistory", handler);
}
});

View File

@ -439,7 +439,7 @@ describe("Core htmx AJAX Tests", function(){
{
var path = null;
var div = make("<div hx-get=''/>");
htmx.on(div, "configRequest.htmx", function (evt) {
htmx.on(div, "htmx:configRequest", function (evt) {
path = evt.detail.path;
return false;
});
@ -452,7 +452,7 @@ describe("Core htmx AJAX Tests", function(){
{
var path = null;
var div = make("<div hx-get/>");
htmx.on(div, "configRequest.htmx", function (evt) {
htmx.on(div, "htmx:configRequest", function (evt) {
path = evt.detail.path;
return false;
});

View File

@ -20,7 +20,7 @@ describe("Core htmx API test", function(){
this.server.respond();
byId("d1").getAttribute("foo").should.equal("bar");
} finally {
htmx.off("load.htmx", helper);
htmx.off("htmx:load", helper);
}
});

View File

@ -10,7 +10,7 @@ describe("Core htmx Events", function() {
it("load.htmx fires properly", function () {
var called = false;
var handler = htmx.on("load.htmx", function (evt) {
var handler = htmx.on("htmx:load", function (evt) {
called = true;
});
try {
@ -21,12 +21,12 @@ describe("Core htmx Events", function() {
this.server.respond();
should.equal(called, true);
} finally {
htmx.off("load.htmx", handler);
htmx.off("htmx:load", handler);
}
});
it("configRequest.htmx allows attribute addition", function () {
var handler = htmx.on("configRequest.htmx", function (evt) {
var handler = htmx.on("htmx:configRequest", function (evt) {
evt.detail.parameters['param'] = "true";
});
try {
@ -40,13 +40,13 @@ describe("Core htmx Events", function() {
this.server.respond();
param.should.equal("true");
} finally {
htmx.off("configRequest.htmx", handler);
htmx.off("htmx:configRequest", handler);
}
});
it("configRequest.htmx allows attribute removal", function () {
var param = "foo";
var handler = htmx.on("configRequest.htmx", function (evt) {
var handler = htmx.on("htmx:configRequest", function (evt) {
delete evt.detail.parameters['param'];
});
try {
@ -59,13 +59,13 @@ describe("Core htmx Events", function() {
this.server.respond();
should.equal(param, undefined);
} finally {
htmx.off("configRequest.htmx", handler);
htmx.off("htmx:configRequest", handler);
}
});
it("configRequest.htmx allows header tweaking", function () {
var header = "foo";
var handler = htmx.on("configRequest.htmx", function (evt) {
var handler = htmx.on("htmx:configRequest", function (evt) {
evt.detail.headers['X-My-Header'] = "bar";
});
try {
@ -78,13 +78,13 @@ describe("Core htmx Events", function() {
this.server.respond();
should.equal(header, "bar");
} finally {
htmx.off("configRequest.htmx", handler);
htmx.off("htmx:configRequest", handler);
}
});
it("afterSwap.htmx is called when replacing outerHTML", function () {
var called = false;
var handler = htmx.on("afterSwap.htmx", function (evt) {
var handler = htmx.on("htmx:afterSwap", function (evt) {
called = true;
});
try {
@ -96,13 +96,13 @@ describe("Core htmx Events", function() {
this.server.respond();
should.equal(called, true);
} finally {
htmx.off("afterSwap.htmx", handler);
htmx.off("htmx:afterSwap", handler);
}
});
it("afterSettle.htmx is called when replacing outerHTML", function () {
var called = false;
var handler = htmx.on("afterSettle.htmx", function (evt) {
var handler = htmx.on("htmx:afterSettle", function (evt) {
called = true;
});
try {
@ -114,7 +114,7 @@ describe("Core htmx Events", function() {
this.server.respond();
should.equal(called, true);
} finally {
htmx.off("afterSettle.htmx", handler);
htmx.off("htmx:afterSettle", handler);
}
});

View File

@ -9,7 +9,7 @@ describe("default extensions behavior", function() {
htmx.defineExtension("ext-testswap", {
onEvent : function(name, evt) {
if (name === "load.htmx") {
if (name === "htmx:load") {
loadCalls.push(evt.detail.elt);
}
},

View File

@ -18,7 +18,7 @@ describe("hyperscript integration", function() {
it('can handle htmx driven events', function () {
this.server.respondWith("GET", "/test", "Clicked!");
var btn = make('<button _="on afterSettle.htmx add .afterSettle" hx-get="/test">Click Me!</button>')
var btn = make('<button _="on htmx:afterSettle add .afterSettle" hx-get="/test">Click Me!</button>')
btn.classList.contains("afterSettle").should.equal(false);
btn.click();
this.server.respond();
@ -28,7 +28,7 @@ describe("hyperscript integration", function() {
it('can handle htmx error events', function () {
this.server.respondWith("GET", "/test", [404, {}, "Bad request"]);
var div = make('<div id="d1"></div>')
var btn = make('<button _="on error.htmx(errorInfo) put errorInfo.error into #d1.innerHTML" hx-get="/test">Click Me!</button>')
var btn = make('<button _="on htmx:error(errorInfo) put errorInfo.error into #d1.innerHTML" hx-get="/test">Click Me!</button>')
btn.click();
this.server.respond();
div.innerHTML.should.equal("Response Status Error Code 404 from /test");

View File

@ -554,13 +554,9 @@
ctx = ctx || {};
var compiled = _parser.parseElement(type, _lexer.tokenize(src) ).transpile();
var evalString = "(function(" + Object.keys(ctx).join(",") + "){return " + compiled + "})";
// TODO parser debugging
if(false) console.log("transpile: " + compiled);
if(false) console.log("evalString: " + evalString);
var args = Object.keys(ctx).map(function (key) {
return ctx[key]
});
if(false) console.log("args", args);
return eval(evalString).apply(null, args);
}
@ -570,7 +566,9 @@
var tokens = _lexer.tokenize(src);
var hyperScript = _parser.parseHyperScript(tokens);
var transpiled = _parser.transpile(hyperScript);
if(true) console.log(transpiled);
if (elt.getAttribute('debug') === "true") {
console.log(transpiled);
}
var hyperscriptObj = eval(transpiled);
hyperscriptObj.applyEventListenersTo(elt);
}
@ -579,7 +577,7 @@
function ajax(method, url, callback, data) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(this.response)
callback(this.response, xhr);
};
xhr.open(method, url);
xhr.send(JSON.stringify(data));
@ -657,7 +655,7 @@
type: "nakedString",
tokens: tokenArr,
transpile: function () {
return "'" + tokenArr.map(function(t){return t.value}).join("") + "'";
return "'" + tokenArr.map(function(t){return t.value}).join("") + "'";
}
}
}
@ -755,6 +753,32 @@
}
})
_parser.addGrammarElement("namedArgumentList", function (parser, tokens) {
if (tokens.matchOpToken("(")) {
var fields = []
if (!tokens.matchOpToken(")")) {
do {
var name = tokens.requireTokenType("IDENTIFIER");
tokens.requireOpToken(":");
var value = parser.parseElement("expression", tokens);
fields.push({name: name, value: value});
} while (tokens.matchOpToken(","))
tokens.requireOpToken(")");
}
return {
type: "namedArgumentList",
fields: fields,
transpile: function () {
return "({_namedArgList_:true, " + fields.map(function (field) {
return field.name.value + ":" + parser.transpile(field.value)
}).join(", ") + "})";
}
}
}
})
_parser.addGrammarElement("symbol", function (parser, tokens) {
@ -1106,8 +1130,8 @@
});
_parser.addGrammarElement("command", function (parser, tokens) {
return parser.parseAnyOf(["onCmd", "addCmd", "removeCmd", "toggleCmd", "waitCmd", "sendCmd",
"takeCmd", "logCmd", "callCmd", "putCmd", "ifCmd", "ajaxCmd"], tokens);
return parser.parseAnyOf(["onCmd", "addCmd", "removeCmd", "toggleCmd", "waitCmd", "sendCmd", "triggerCmd",
"takeCmd", "logCmd", "callCmd", "putCmd", "setCmd", "ifCmd", "ajaxCmd"], tokens);
})
_parser.addGrammarElement("commandList", function (parser, tokens) {
@ -1134,9 +1158,9 @@
return "(function(){\n" +
"var eventListeners = []\n" +
eventListeners.map(function (el) {
return "eventListeners.push(" + parser.transpile(el) + ");\n"
}) +
" function applyEventListenersTo(elt) { _hyperscript.runtime.applyEventListeners(this, elt) }" +
return " eventListeners.push(" + parser.transpile(el) + ");\n"
}).join("") +
" function applyEventListenersTo(elt) { _hyperscript.runtime.applyEventListeners(this, elt) }\n" +
" return {eventListeners:eventListeners, applyEventListenersTo:applyEventListenersTo}\n" +
"})()"
}
@ -1146,7 +1170,7 @@
_parser.addGrammarElement("eventListener", function (parser, tokens) {
tokens.requireToken("on");
var on = parser.parseElement("dotPath", tokens);
var on = parser.parseElement("dotOrColonPath", tokens);
if (on == null) {
parser.raiseParseError(tokens, "Expected event name")
}
@ -1326,18 +1350,24 @@
}
})
_parser.addGrammarElement("dotPath", function (parser, tokens) {
// TODO - colon path needs to eventually become part of ruby-style symbols
_parser.addGrammarElement("dotOrColonPath", function (parser, tokens) {
var root = tokens.matchTokenType("IDENTIFIER");
if (root) {
var path = [root.value];
while (tokens.matchOpToken(".")) {
path.push(tokens.requireTokenType("IDENTIFIER").value);
var separator = tokens.matchOpToken(".") || tokens.matchOpToken(":");
if (separator) {
do {
path.push(tokens.requireTokenType("IDENTIFIER").value);
} while (tokens.matchOpToken(separator.value))
}
return {
type: "dotPath",
type: "dotOrColonPath",
path: path,
transpile: function () {
return path.join(".");
return path.join(separator ? separator.value : "");
}
}
}
@ -1346,9 +1376,9 @@
_parser.addGrammarElement("sendCmd", function (parser, tokens) {
if (tokens.matchToken("send")) {
var eventName = parser.parseElement("dotPath", tokens);
var eventName = parser.parseElement("dotOrColonPath", tokens);
var details = parser.parseElement("objectLiteral", tokens);
var details = parser.parseElement("namedArgumentList", tokens);
if (tokens.matchToken("to")) {
var to = parser.parseElement("target", tokens);
} else {
@ -1369,6 +1399,23 @@
}
})
_parser.addGrammarElement("triggerCmd", function (parser, tokens) {
if (tokens.matchToken("trigger")) {
var eventName = parser.parseElement("dotOrColonPath", tokens);
var details = parser.parseElement("namedArgumentList", tokens);
return {
type: "triggerCmd",
eventName: eventName,
details: details,
transpile: function () {
return "_hyperscript.runtime.triggerEvent(me, '" + parser.transpile(eventName) + "'," + parser.transpile(details, "{}") + ");";
}
}
}
})
_parser.addGrammarElement("takeCmd", function (parser, tokens) {
if (tokens.matchToken("take")) {
var classRef = tokens.requireTokenType(tokens, "CLASS_REF");
@ -1430,7 +1477,7 @@
})
_parser.addGrammarElement("callCmd", function (parser, tokens) {
if (tokens.matchToken("call")) {
if (tokens.matchToken("call") || tokens.matchToken("get")) {
return {
type: "callCmd",
expr: parser.parseElement("expression", tokens),
@ -1448,12 +1495,16 @@
var operation = tokens.matchToken("into") ||
tokens.matchToken("before") ||
tokens.matchToken("afterbegin") ||
tokens.matchToken("beforeend") ||
tokens.matchToken("after");
if (operation == null && tokens.matchToken("at")) {
operation = tokens.matchToken("start") ||
tokens.matchToken("end");
tokens.requireToken("of");
}
if (operation == null) {
parser.raiseParseError(tokens, "Expected one of 'into', 'before', 'afterbegin', 'beforeend', 'after'")
parser.raiseParseError(tokens, "Expected one of 'into', 'before', 'at start of', 'at end of', 'after'");
}
var target = parser.parseElement("target", tokens);
@ -1482,11 +1533,11 @@
return "_hyperscript.runtime.forEach( " + parser.transpile(target) + ", function (target) {" +
" target.insertAdjacentHTML('beforebegin', " + parser.transpile(value) + ")" +
"})";
} else if (this.op === "afterbegin") {
} else if (this.op === "start") {
return "_hyperscript.runtime.forEach( " + parser.transpile(target) + ", function (target) {" +
" target.insertAdjacentHTML('afterbegin', " + parser.transpile(value) + ")" +
"})";
} else if (this.op === "beforeend") {
} else if (this.op === "end") {
return "_hyperscript.runtime.forEach( " + parser.transpile(target) + ", function (target) {" +
" target.insertAdjacentHTML('beforeend', " + parser.transpile(value) + ")" +
"})";
@ -1501,9 +1552,44 @@
}
})
_parser.addGrammarElement("setCmd", function (parser, tokens) {
if (tokens.matchToken("set")) {
var target = parser.parseElement("target", tokens);
tokens.requireToken("to");
var value = parser.parseElement("expression", tokens);
var directWrite = target.propPath.length === 0;
var symbolWrite = directWrite && target.root.type === "symbol";
if (directWrite && !symbolWrite) {
parser.raiseParseError(tokens, "Can only put directly into symbols, not references")
}
return {
type: "setCmd",
target: target,
symbolWrite: symbolWrite,
value: value,
transpile: function () {
if (this.symbolWrite) {
return "var " + target.root.name + " = " + parser.transpile(value);
} else {
var lastProperty = target.propPath.pop(); // steal last property for assignment
return "_hyperscript.runtime.forEach( " + parser.transpile(target) + ", function (target) {" +
" target." + lastProperty + "=" + parser.transpile(value) +
"})";
}
}
}
}
})
_parser.addGrammarElement("ifCmd", function (parser, tokens) {
if (tokens.matchToken("if")) {
var expr = parser.parseElement("expression", tokens);
tokens.matchToken("then"); // optional 'then'
var trueBranch = parser.parseElement("commandList", tokens);
if (tokens.matchToken("else")) {
var falseBranch = parser.parseElement("commandList", tokens);
@ -1531,9 +1617,7 @@
if (method == null) {
parser.raiseParseError(tokens, "Requires either GET or POST");
}
if (method.value === "GET") {
tokens.requireToken("from");
} else {
if (method.value !== "GET") {
if (!tokens.matchToken("to")) {
var data = parser.parseElement("expression", tokens);
tokens.requireToken("to");
@ -1553,7 +1637,7 @@
delete this.next;
return "_hyperscript.runtime.ajax('" + method.value + "', " +
parser.transpile(url) + ", " +
"function(response){ " + parser.transpile(capturedNext) + " }," +
"function(response, xhr){ " + parser.transpile(capturedNext) + " }," +
parser.transpile(data, "null") + ")";
}
};

View File

@ -340,7 +340,7 @@ with a CSS selector of all the elements whose values you want to include in the
If you wish to filter out some parameters you can use the [hx-params](/attributes/hx-params) attribute.
Finally, if you want to programatically modify the parameters, you can use the [configRequest.htmx](/events#configRequest.htmx)
Finally, if you want to programatically modify the parameters, you can use the [htmx:configRequest](/events#htmx:configRequest)
event.
#### <a name="vars"></a> [Variables](#variables)
@ -454,10 +454,10 @@ HTML into the document at the target specified and with the swap strategy specif
Sometimes you might want to do nothing in the swap, but still perhaps trigger a client side event ([see below](#response-headers)).
For this situation you can return a `204 - No Content` response code, and htmx will ignore the content of the response.
In the event of an error response from the server (e.g. a 404 or a 501), htmx will trigger the [`responseError.htmx`](/events#responseError.htmx)
In the event of an error response from the server (e.g. a 404 or a 501), htmx will trigger the [`htmx:responseError`](/events#htmx:responseError)
event, which you can handle.
In the event of a connection error, the `sendError.htmx` event will be triggered.
In the event of a connection error, the `htmx:sendError` event will be triggered.
### <a name="request-header"></a> [Request Headers](#request-headers)
@ -542,7 +542,7 @@ Htmx has an extensive events mechanism, which doubles as the logging system.
If you want to register for a given htmx event you can use the following javascript:
```javascript
htmx.on("load.htmx", function(evt) {
htmx.on("htmx.load", function(evt) {
myJavascriptLib.init(evt.details.elt);
});
```
@ -598,12 +598,12 @@ directly, in a more flexible and open manner. One of its prime features is the
on a DOM element, using the `on` syntax:
```html
<div _="on afterSettle.htmx log 'Settled!'">
<div _="on htmx:afterSettle log 'Settled!'">
...
</div>
```
This will log `Settled!` to the console when the `afterSettle.htmx` event is triggered.
This will log `Settled!` to the console when the `htmx:afterSettle` event is triggered.
#### intercooler.js features & hyperscript implementations
@ -628,7 +628,7 @@ for posting errors that occured during requests and responses.
In hyperscript similar functionality is implemented like so:
```html
<body _="on error.htmx(errorInfo) ajax POST errorInfo to /errors">
<body _="on htmx:error(errorInfo) ajax POST errorInfo to /errors">
...
</body>
```
@ -641,7 +641,7 @@ let you switch a class between siblings.
In hyperscript you can implement similar functionality like so:
```html
<div hx-target="#content" _="on beforeOnLoad.htmx take .active from .tabs for event.target">
<div hx-target="#content" _="on htmx:beforeOnLoad take .active from .tabs for event.target">
<a class="tabs active" hx-get="/tabl1" >Tab 1</a>
<a class="tabs" hx-get="/tabl2">Tab 2</a>
<a class="tabs" hx-get="/tabl3">Tab 3</a>

View File

@ -8,7 +8,7 @@ title: </> htmx - high power tools for html
Htmx provides an extensive events system that can be used to modify and enhance behavior. Events
are listed below.
### <a name="afterOnLoad.htmx"></a> Event - [`afterOnLoad.htmx`](#afterOnLoad.htmx)
### <a name="htmx:afterOnLoad"></a> Event - [`htmx:afterOnLoad`](#htmx:afterOnLoad)
This event is triggered after an AJAX `onload` has finished. Note that this does not mean that the content
has been swapped or settled yet, only that the request has finished.
@ -19,11 +19,11 @@ has been swapped or settled yet, only that the request has finished.
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="afterRequest.htmx"></a> Event - [`afterRequest.htmx`](#afterRequest.htmx)
### <a name="htmx:afterRequest"></a> Event - [`htmx:afterRequest`](#htmx:afterRequest)
This event is triggered after an AJAX request has finished either in the case of a successful request (although
one that may have returned a remote error code such as a `404`) or in a network error situation. This event
can be paried with [`beforeRequest.htmx`](#beforeRequest.htmx) to wrap behavior around a request cycle.
can be paried with [`htmx:beforeRequest`](#htmx:beforeRequest) to wrap behavior around a request cycle.
##### Details
@ -31,7 +31,7 @@ can be paried with [`beforeRequest.htmx`](#beforeRequest.htmx) to wrap behavior
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="afterSettle.htmx"></a> Event - [`afterSettle.htmx`](#afterSettle.htmx)
### <a name="htmx:afterSettle"></a> Event - [`htmx:afterSettle`](#htmx:afterSettle)
This event is triggered after the DOM has [settled](/docs#settling).
@ -41,7 +41,7 @@ This event is triggered after the DOM has [settled](/docs#settling).
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="afterSwap.htmx"></a> Event - [`afterSwap.htmx`](#afterSwap.htmx)
### <a name="htmx:afterSwap"></a> Event - [`htmx:afterSwap`](#htmx:afterSwap)
This event is triggered after new content has been [swapped into the DOM](/docs#swapping).
@ -51,7 +51,7 @@ This event is triggered after new content has been [swapped into the DOM](/docs
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="beforeOnLoad.htmx"></a> Event - [`beforeOnLoad.htmx`](#beforeOnLoad.htmx)
### <a name="htmx:beforeOnLoad"></a> Event - [`htmx:beforeOnLoad`](#htmx:beforeOnLoad)
This event is triggered before any response processing occurs. If the event is cancelled, no swap will occur.
@ -61,7 +61,7 @@ This event is triggered before any response processing occurs. If the event is
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="beforeRequest.htmx"></a> Event - [`beforeRequest.htmx`](#beforeRequest.htmx)
### <a name="htmx:beforeRequest"></a> Event - [`htmx:beforeRequest`](#htmx:beforeRequest)
This event is triggered before an AJAX request is issued. If the event is cancelled, no request will occur.
@ -71,7 +71,7 @@ This event is triggered before an AJAX request is issued. If the event is cance
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="beforeSwap.htmx"></a> Event - [`beforeSwap.htmx`](#beforeSwap.htmx)
### <a name="htmx:beforeSwap"></a> Event - [`htmx:beforeSwap`](#htmx:beforeSwap)
This event is triggered before any new content has been [swapped into the DOM](/docs#swapping). If the event is cancelled, no swap will occur.
@ -81,13 +81,13 @@ This event is triggered before any new content has been [swapped into the DOM](/
* `detail.xhr` - the `XMLHttpRequest`
* `detail.target` - the target of the request
### <a name="configRequest.htmx"></a> Event - [`configRequest.htmx`](#configRequest.htmx)
### <a name="htmx:configRequest"></a> Event - [`htmx:configRequest`](#htmx:configRequest)
This event is triggered after htmx has collected parameters for inclusion in the request. It can be
used to include or update the parameters that htmx will send:
```javascript
document.body.addEventListener('configRequest.htmx', function(evt) {
document.body.addEventListener('htmx:configRequest', function(evt) {
evt.detail.parameters['auth_token'] = getAuthToken(); // add a new parameter into the mix
});
```
@ -104,7 +104,7 @@ than a single value.
* `detail.target` - the target of the request
* `detail.verb` - the HTTP verb in use
### <a name="historyCacheMiss.htmx"></a> Event - [`historyCacheMiss.htmx`](#historyCacheMiss.htmx)
### <a name="htmx:historyCacheMiss"></a> Event - [`htmx:historyCacheMiss`](#htmx:historyCacheMiss)
This event is triggered when a cache miss occurs when restoring history
@ -113,7 +113,7 @@ This event is triggered when a cache miss occurs when restoring history
* `detail.xhr` - the `XMLHttpRequest` that will retrieve the remote content for restoration
* `detail.path` - the path and query of the page being restored
### <a name="historyCacheMissError.htmx"></a> Event - [`historyCacheMissError.htmx`](#historyCacheMissError.htmx)
### <a name="htmx:historyCacheMissError"></a> Event - [`htmx:historyCacheMissError`](#htmx:historyCacheMissError)
This event is triggered when a cache miss occurs and a response has been retrieved from the server
for the content to restore, but the response is an error (e.g. `404`)
@ -123,7 +123,7 @@ for the content to restore, but the response is an error (e.g. `404`)
* `detail.xhr` - the `XMLHttpRequest`
* `detail.path` - the path and query of the page being restored
### <a name="historyCacheMissLoad.htmx"></a> Event - [`historyCacheMissLoad.htmx`](#historyCacheMissLoad.htmx)
### <a name="htmx:historyCacheMissLoad"></a> Event - [`htmx:historyCacheMissLoad`](#htmx:historyCacheMissLoad)
This event is triggered when a cache miss occurs and a response has been retrieved succesfully from the server
for the content to restore
@ -133,7 +133,7 @@ for the content to restore
* `detail.xhr` - the `XMLHttpRequest`
* `detail.path` - the path and query of the page being restored
### <a name="historyRestore.htmx"></a> Event - [`historyRestore.htmx`](#historyRestore.htmx)
### <a name="htmx:historyRestore"></a> Event - [`htmx:historyRestore`](#htmx:historyRestore)
This event is triggered when htmx handles a history restoration action
@ -141,7 +141,7 @@ This event is triggered when htmx handles a history restoration action
* `detail.path` - the path and query of the page being restored
### <a name="beforeHistorySave.htmx"></a> Event - [`beforeHistorySave.htmx`](#beforeHistorySave.htmx)
### <a name="htmx:beforeHistorySave"></a> Event - [`htmx:beforeHistorySave`](#htmx:beforeHistorySave)
This event is triggered when htmx handles a history restoration action
@ -154,7 +154,7 @@ This event is triggered when htmx handles a history restoration action
* `detail.config` - the config that will be passed to the `EventSource` contstructor
### <a name="load.htmx"></a> Event - [`load.htmx`](#load.htmx)
### <a name="htmx:load"></a> Event - [`htmx:load`](#htmx:load)
This event is triggered when a new node is loaded into the DOM by htmx.
@ -162,7 +162,7 @@ This event is triggered when a new node is loaded into the DOM by htmx.
* `detail.elt` - the newly added element
### <a name="noSSESourceError.htmx"></a> Event - [`noSSESourceError.htmx`](#noSSESourceError.htmx)
### <a name="htmx:noSSESourceError"></a> Event - [`htmx:noSSESourceError`](#htmx:noSSESourceError)
This event is triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined
@ -170,7 +170,7 @@ This event is triggered when an element refers to a SSE event in its trigger, bu
* `detail.elt` - the element with the bad SSE trigger
### <a name="onLoadError.htmx"></a> Event - [`onLoadError.htmx`](#onLoadError.htmx)
### <a name="htmx:onLoadError"></a> Event - [`htmx:onLoadError`](#htmx:onLoadError)
This event is triggered when an error occurs during the `load` handling of an AJAX call
@ -181,7 +181,7 @@ This event is triggered when an error occurs during the `load` handling of an AJ
* `detail.target` - the target of the request
* `detail.exception` - the exception that occurred
### <a name="oobErrorNoTarget.htmx"></a> Event - [`oobErrorNoTarget.htmx`](#oobErrorNoTarget.htmx)
### <a name="htmx:oobErrorNoTarget"></a> Event - [`htmx:oobErrorNoTarget`](#htmx:oobErrorNoTarget)
This event is triggered when an [out of band swap](/docs##oob_swaps) does not have a corresponding element
in the DOM to switch with.
@ -190,7 +190,7 @@ in the DOM to switch with.
* `detail.content` - the element with the bad oob `id`
### <a name="prompt.htmx"></a> Event - [`prompt.htmx`](#prompt.htmx)
### <a name="htmx:prompt"></a> Event - [`htmx:prompt`](#htmx:prompt)
This event is triggered after a prompt has been shown to the user with the [`hx-prompt`](/attributes/hx-prompt)
attribute. If this event is cancelled, the AJAX request will not occur.
@ -201,7 +201,7 @@ attribute. If this event is cancelled, the AJAX request will not occur.
* `detail.target` - the target of the request
* `detail.prompt` - the user response to the prompt
### <a name="responseError.htmx"></a> Event - [`responseError.htmx`](#responseError.htmx)
### <a name="htmx:responseError"></a> Event - [`htmx:responseError`](#htmx:responseError)
This event is triggered when an HTTP error response occurs
@ -211,7 +211,7 @@ This event is triggered when an HTTP error response occurs
* `detail.elt` - the element that triggered the request
* `detail.target` - the target of the request
### <a name="sendError.htmx"></a> Event - [`sendError.htmx`](#sendError.htmx)
### <a name="htmx:sendError"></a> Event - [`htmx:sendError`](#htmx:sendError)
This event is triggered when a network error prevents an HTTP request from occurring
@ -221,7 +221,7 @@ This event is triggered when a network error prevents an HTTP request from occur
* `detail.elt` - the element that triggered the request
* `detail.target` - the target of the request
### <a name="sseError.htmx"></a> Event - [`sseError.htmx`](#sseError.htmx)
### <a name="htmx:sseError"></a> Event - [`htmx:sseError`](#htmx:sseError)
This event is triggered when an error occurs with a SSE source
@ -231,7 +231,7 @@ This event is triggered when an error occurs with a SSE source
* `detail.error` - the error
* `detail.source` - the SSE source
### <a name="swapError.htmx"></a> Event - [`swapError.htmx`](#swapError.htmx)
### <a name="htmx:swapError"></a> Event - [`htmx:swapError`](#htmx:swapError)
This event is triggered when an error occurs during the swap phase
@ -241,7 +241,7 @@ This event is triggered when an error occurs during the swap phase
* `detail.elt` - the element that triggered the request
* `detail.target` - the target of the request
### <a name="targetError.htmx"></a> Event - [`targetError.htmx`](#targetError.htmx)
### <a name="htmx:targetError"></a> Event - [`htmx:targetError`](#htmx:targetError)
This event is triggered when a bad selector is used for a [`hx-target`](/attributes/hx-target) attribute (e.g. an
element id without a preceding `#`)

View File

@ -95,29 +95,29 @@ title: </> htmx - Attributes
| Event | Description |
|-------|-------------|
| [`afterOnLoad.htmx`](/events#afterOnLoad.htmx) | triggered after an AJAX request has completed processing a successful response
| [`afterRequest.htmx`](/events#afterRequest.htmx) | triggered after an AJAX request has completed
| [`afterSettle.htmx`](/events#afterSettle.htmx) | triggered after the DOM has settled
| [`afterSwap.htmx`](/events#afterSwap.htmx) | triggered after new content has been swapped in
| [`beforeOnLoad.htmx`](/events#beforeOnLoad.htmx) | triggered before any response processing occurs
| [`beforeRequest.htmx`](/events#beforeRequest.htmx) | triggered before an AJAX request is made
| [`beforeSwap.htmx`](/events#beforeSwap.htmx) | triggered before a swap is done
| [`configRequest.htmx`](/events#configRequest.htmx) | triggered before the request, allows you to customize parameters, headers
| [`historyCacheMiss.htmx`](/events#historyCacheMiss.htmx) | triggered on a cache miss in the history subsystem
| [`historyCacheMissError.htmx`](/events#historyCacheMissError.htmx) | triggered on a unsuccessful remote retrieval
| [`historyCacheMissLoad.htmx`](/events#historyCacheMissLoad.htmx) | triggered on a succesful remote retrieval
| [`historyRestore.htmx`](/events#historyRestore.htmx) | triggered when htmx handles a history restoration action
| [`beforeHistorySave.htmx`](/events#beforeHistorySave.htmx) | triggered before content is saved to the history cache
| [`load.htmx`](/events#load.htmx) | triggered when new content is added to the DOM
| [`noSSESourceError.htmx`](/events#noSSESourceError.htmx) | triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined
| [`onLoadError.htmx`](/events#onLoadError.htmx) | triggered when an exception occurs during the onLoad handling in htmx
| [`oobErrorNoTarget.htmx`](/events#oobErrorNoTarget.htmx) | triggered when an out of band element does not have a matching ID in the current DOM
| [`prompt.htmx`](/events#prompt.htmx) | triggered after a prompt is shown
| [`responseError.htmx`](/events#responseError.htmx) | triggered when an HTTP response error (non-`200` or `300` response code) occurs
| [`sendError.htmx`](/events#sendError.htmx) | triggered when a network error prevents an HTTP request from happening
| [`sseError.htmx`](/events#sseError.htmx) | triggered when an error occurs with a SSE source
| [`swapError.htmx`](/events#swapError.htmx) | triggered when an error occurs during the swap phase
| [`targetError.htmx`](/events#targetError.htmx) | triggered when an invalid target is specified
| [`htmx:afterOnLoad`](/events#htmx:afterOnLoad) | triggered after an AJAX request has completed processing a successful response
| [`htmx:afterRequest`](/events#htmx:afterRequest) | triggered after an AJAX request has completed
| [`htmx:afterSettle`](/events#htmx:afterSettle) | triggered after the DOM has settled
| [`htmx:afterSwap`](/events#htmx:afterSwap) | triggered after new content has been swapped in
| [`htmx:beforeOnLoad`](/events#htmx:beforeOnLoad) | triggered before any response processing occurs
| [`htmx:beforeRequest`](/events#htmx:beforeRequest) | triggered before an AJAX request is made
| [`htmx:beforeSwap`](/events#htmx:beforeSwap) | triggered before a swap is done
| [`htmx:configRequest`](/events#htmx:configRequest) | triggered before the request, allows you to customize parameters, headers
| [`htmx:historyCacheMiss`](/events#htmx:historyCacheMiss) | triggered on a cache miss in the history subsystem
| [`htmx:historyCacheMissError`](/events#htmx:historyCacheMissError) | triggered on a unsuccessful remote retrieval
| [`htmx:historyCacheMissLoad`](/events#htmx:historyCacheMissLoad) | triggered on a succesful remote retrieval
| [`htmx:historyRestore`](/events#htmx:historyRestore) | triggered when htmx handles a history restoration action
| [`htmx:beforeHistorySave`](/events#htmx:beforeHistorySave) | triggered before content is saved to the history cache
| [`htmx:load`](/events#htmx:load) | triggered when new content is added to the DOM
| [`htmx:noSSESourceError`](/events#htmx:noSSESourceError) | triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined
| [`htmx:onLoadError`](/events#htmx:onLoadError) | triggered when an exception occurs during the onLoad handling in htmx
| [`htmx:oobErrorNoTarget`](/events#htmx:oobErrorNoTarget) | triggered when an out of band element does not have a matching ID in the current DOM
| [`htmx:prompt`](/events#htmx:prompt) | triggered after a prompt is shown
| [`htmx:responseError`](/events#htmx:responseError) | triggered when an HTTP response error (non-`200` or `300` response code) occurs
| [`htmx:sendError`](/events#htmx:sendError) | triggered when a network error prevents an HTTP request from happening
| [`htmx:sseError`](/events#htmx:sseError) | triggered when an error occurs with a SSE source
| [`htmx:swapError`](/events#htmx:swapError) | triggered when an error occurs during the swap phase
| [`htmx:targetError`](/events#htmx:targetError) | triggered when an invalid target is specified
</div>