diff --git a/src/htmx.js b/src/htmx.js index b535e90d..b3787498 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -821,7 +821,26 @@ return (function () { } } - function cleanUpElement(element) { + function stringHash(string, hash) { + for (var i = 0; i < string.length; i++) { + var char = string.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; + } + return hash; + } + + function attributeHash(elt) { + var hash = 0; + for (let i = 0; i < elt.attributes.length; i++) { + const attribute = elt.attributes[i]; + hash = stringHash(attribute.name, hash); + hash = stringHash(attribute.value, hash); + } + return hash; + } + + function deInitNode(element) { var internalData = getInternalData(element); if (internalData.webSocket) { internalData.webSocket.close(); @@ -829,16 +848,18 @@ return (function () { if (internalData.sseEventSource) { internalData.sseEventSource.close(); } - - triggerEvent(element, "htmx:beforeCleanupElement") - if (internalData.listenerInfos) { - forEach(internalData.listenerInfos, function(info) { - if (element !== info.on) { + forEach(internalData.listenerInfos, function (info) { + if (info.on) { info.on.removeEventListener(info.trigger, info.listener); } }); } + } + + function cleanUpElement(element) { + triggerEvent(element, "htmx:beforeCleanupElement") + deInitNode(element); if (element.children) { // IE forEach(element.children, function(child) { cleanUpElement(child) }); } @@ -1390,7 +1411,7 @@ return (function () { if (!hasAttribute(elt,'data-hx-revealed') && isScrolledIntoView(elt)) { elt.setAttribute('data-hx-revealed', 'true'); var nodeData = getInternalData(elt); - if (nodeData.initialized) { + if (nodeData.initHash === attributeHash(elt)) { triggerEvent(elt, 'revealed'); } else { // if the node isn't initialized, wait for it before triggering the request @@ -1756,8 +1777,13 @@ return (function () { return; } var nodeData = getInternalData(elt); - if (!nodeData.initialized) { - nodeData.initialized = true; + if (nodeData.initHash !== attributeHash(elt)) { + + nodeData.initHash = attributeHash(elt); + + // clean up any previously processed info + deInitNode(elt); + triggerEvent(elt, "htmx:beforeProcessNode") if (elt.value) { diff --git a/test/core/api.js b/test/core/api.js index 25bc9d22..5e4f26c1 100644 --- a/test/core/api.js +++ b/test/core/api.js @@ -318,4 +318,22 @@ describe("Core htmx API test", function(){ div.innerHTML.should.equal("Clicked!"); }); + it('can re-init with new attributes', function () { + this.server.respondWith("PATCH", "/test", "patch"); + this.server.respondWith("DELETE", "/test", "delete"); + + var div = make('
click me
'); + div.click(); + this.server.respond(); + div.innerHTML.should.equal("patch"); + + div.removeAttribute("hx-patch"); + div.setAttribute("hx-delete", "/test"); + htmx.process(div); + + div.click(); + this.server.respond(); + div.innerHTML.should.equal("delete"); + }) + })