diff options
author | Joerg Sonnenberger <joerg@bec.de> | 2024-10-03 03:17:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-02 19:17:25 -0600 |
commit | df92b295d6b91291ecef97733ba135ac5de565a5 (patch) | |
tree | 9b605d8b6baee7f8e4fee53b081468582603a2a5 /src | |
parent | 4916ce4d0260072f3ceb2957d75229c88cf59fc2 (diff) | |
download | htmx-df92b295d6b91291ecef97733ba135ac5de565a5.tar.gz htmx-df92b295d6b91291ecef97733ba135ac5de565a5.zip |
Change hx-trigger's changed modifier to work for independent trigger specifications (#2891)
* Adjust hx-trigger's changed modifier for multiple sources
The `changed` trigger modifier can see different event targets, either due
to the `from` modifier or event bubbling. The existing behavior trigger
only for one node (`from` modifier) or inconsistently (bubbling).
Use a nested weak map to keep track of the last value per distinguished
(trigger specification, event target node) pair. The weak map ensures
that Garbage Collection can still recycle the nodes.
If a event target was not seen via `from`, it is assumed changed for the
first time the trigger is hit.
* Add test case for separate triggers with changed modifier
Diffstat (limited to 'src')
-rw-r--r-- | src/htmx.js | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/src/htmx.js b/src/htmx.js index e24dd23a..b51cc165 100644 --- a/src/htmx.js +++ b/src/htmx.js @@ -695,7 +695,7 @@ var htmx = (function() { * @property {boolean} [triggeredOnce] * @property {number} [delayed] * @property {number|null} [throttle] - * @property {string} [lastValue] + * @property {WeakMap<HtmxTriggerSpecification,WeakMap<EventTarget,string>>} [lastValue] * @property {boolean} [loaded] * @property {string} [path] * @property {string} [verb] @@ -2417,10 +2417,15 @@ var htmx = (function() { } // store the initial values of the elements, so we can tell if they change if (triggerSpec.changed) { + if (!('lastValue' in elementData)) { + elementData.lastValue = new WeakMap() + } eltsToListenOn.forEach(function(eltToListenOn) { - const eltToListenOnData = getInternalData(eltToListenOn) + if (!elementData.lastValue.has(triggerSpec)) { + elementData.lastValue.set(triggerSpec, new WeakMap()) + } // @ts-ignore value will be undefined for non-input elements, which is fine - eltToListenOnData.lastValue = eltToListenOn.value + elementData.lastValue.get(triggerSpec).set(eltToListenOn, eltToListenOn.value) }) } forEach(eltsToListenOn, function(eltToListenOn) { @@ -2462,13 +2467,14 @@ var htmx = (function() { } } if (triggerSpec.changed) { - const eltToListenOnData = getInternalData(eltToListenOn) + const node = event.target // @ts-ignore value will be undefined for non-input elements, which is fine - const value = eltToListenOn.value - if (eltToListenOnData.lastValue === value) { + const value = node.value + const lastValue = elementData.lastValue.get(triggerSpec) + if (lastValue.has(node) && lastValue.get(node) === value) { return } - eltToListenOnData.lastValue = value + lastValue.set(node, value) } if (elementData.delayed) { clearTimeout(elementData.delayed) @@ -2846,12 +2852,6 @@ var htmx = (function() { triggerEvent(elt, 'htmx:beforeProcessNode') - // @ts-ignore value will be undefined for non-input elements, which is fine - if (elt.value) { - // @ts-ignore - nodeData.lastValue = elt.value - } - const triggerSpecs = getTriggerSpecs(elt) const hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs) |