Skip to content

Commit 2284775

Browse files
committed
Attach hx-on handlers before processing nodes
1 parent 5520566 commit 2284775

2 files changed

Lines changed: 65 additions & 36 deletions

File tree

src/htmx.js

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2871,46 +2871,52 @@ var htmx = (function() {
28712871
* @param {Element|HTMLInputElement} elt
28722872
*/
28732873
function initNode(elt) {
2874-
if (eltIsDisabled(elt)) {
2875-
cleanUpElement(elt)
2876-
return
2877-
}
2878-
// Ensure only valid Elements and not shadow DOM roots are inited
2879-
if (!(elt instanceof Element)) return
2880-
const nodeData = getInternalData(elt)
2881-
const attrHash = attributeHash(elt)
2882-
if (nodeData.initHash !== attrHash) {
2883-
// clean up any previously processed info
2884-
deInitNode(elt)
2885-
2886-
nodeData.initHash = attrHash
2874+
triggerEvent(elt, 'htmx:beforeProcessNode')
28872875

2888-
triggerEvent(elt, 'htmx:beforeProcessNode')
2889-
2890-
const triggerSpecs = getTriggerSpecs(elt)
2891-
const hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)
2876+
const nodeData = getInternalData(elt)
2877+
const triggerSpecs = getTriggerSpecs(elt)
2878+
const hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)
28922879

2893-
if (!hasExplicitHttpAction) {
2894-
if (getClosestAttributeValue(elt, 'hx-boost') === 'true') {
2895-
boostElement(elt, nodeData, triggerSpecs)
2896-
} else if (hasAttribute(elt, 'hx-trigger')) {
2897-
triggerSpecs.forEach(function(triggerSpec) {
2898-
// For "naked" triggers, don't do anything at all
2899-
addTriggerHandler(elt, triggerSpec, nodeData, function() {
2900-
})
2880+
if (!hasExplicitHttpAction) {
2881+
if (getClosestAttributeValue(elt, 'hx-boost') === 'true') {
2882+
boostElement(elt, nodeData, triggerSpecs)
2883+
} else if (hasAttribute(elt, 'hx-trigger')) {
2884+
triggerSpecs.forEach(function(triggerSpec) {
2885+
// For "naked" triggers, don't do anything at all
2886+
addTriggerHandler(elt, triggerSpec, nodeData, function() {
29012887
})
2902-
}
2888+
})
29032889
}
2890+
}
29042891

2905-
// Handle submit buttons/inputs that have the form attribute set
2906-
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
2907-
if (elt.tagName === 'FORM' || (getRawAttribute(elt, 'type') === 'submit' && hasAttribute(elt, 'form'))) {
2908-
initButtonTracking(elt)
2909-
}
2892+
// Handle submit buttons/inputs that have the form attribute set
2893+
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
2894+
if (elt.tagName === 'FORM' || (getRawAttribute(elt, 'type') === 'submit' && hasAttribute(elt, 'form'))) {
2895+
initButtonTracking(elt)
2896+
}
2897+
2898+
nodeData.firstInitCompleted = true
2899+
triggerEvent(elt, 'htmx:afterProcessNode')
2900+
}
29102901

2911-
nodeData.firstInitCompleted = true
2912-
triggerEvent(elt, 'htmx:afterProcessNode')
2902+
/**
2903+
* @param {Element} elt
2904+
* @returns {boolean}
2905+
*/
2906+
function maybeDeInitAndHash(elt) {
2907+
// Ensure only valid Elements and not shadow DOM roots are inited
2908+
if (!(elt instanceof Element)) {
2909+
return false
29132910
}
2911+
2912+
const nodeData = getInternalData(elt)
2913+
const hash = attributeHash(elt)
2914+
if (nodeData.initHash !== hash) {
2915+
deInitNode(elt)
2916+
nodeData.initHash = hash
2917+
return true
2918+
}
2919+
return false
29142920
}
29152921

29162922
/**
@@ -2923,12 +2929,21 @@ var htmx = (function() {
29232929
function processNode(elt) {
29242930
elt = resolveTarget(elt)
29252931
if (eltIsDisabled(elt)) {
2926-
cleanUpElement(elt)
29272932
return
29282933
}
2929-
initNode(elt)
2930-
forEach(findElementsToProcess(elt), function(child) { initNode(child) })
2934+
2935+
const elementsToInit = []
2936+
if (maybeDeInitAndHash(elt)) {
2937+
elementsToInit.push(elt)
2938+
}
2939+
forEach(findElementsToProcess(elt), function(child) {
2940+
if (!eltIsDisabled(child) && maybeDeInitAndHash(child)) {
2941+
elementsToInit.push(child)
2942+
}
2943+
})
2944+
29312945
forEach(findHxOnWildcardElements(elt), processHxOnWildcard)
2946+
forEach(elementsToInit, initNode)
29322947
}
29332948

29342949
//= ===================================================================

test/attributes/hx-on-wildcard.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ describe('hx-on:* attribute', function() {
133133
delete window.foo
134134
})
135135

136+
it('should fire when triggered by load', function() {
137+
this.server.respondWith('POST', '/test', 'test')
138+
make("<div hx-trigger='load' hx-post='/test' hx-on:htmx:config-request='foo = true'></div>")
139+
window.foo.should.equal(true)
140+
delete window.foo
141+
})
142+
143+
it('should fire when triggered by revealed', function() {
144+
this.server.respondWith('POST', '/test', 'test')
145+
make("<div hx-trigger='revealed' hx-post='/test' hx-on:htmx:config-request='foo = true' style='position: fixed; top: 1px; left: 1px; border: 3px solid red'></div>")
146+
window.foo.should.equal(true)
147+
delete window.foo
148+
})
149+
136150
it('de-initializes hx-on-* content properly', function() {
137151
window.tempCount = 0
138152
this.server.respondWith('POST', '/test', function(xhr) {

0 commit comments

Comments
 (0)