From e28c7550f976e0e38607d17cf909344b079cd932 Mon Sep 17 00:00:00 2001 From: Tim Branyen Date: Tue, 7 Jun 2016 09:17:40 -0700 Subject: [PATCH] Remove transition hooks on replace/detach --- index.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/index.js b/index.js index f31b4dd..f700515 100644 --- a/index.js +++ b/index.js @@ -6,19 +6,42 @@ const states = [ 'textChanged', ]; +// Stores the transition callback handlers in a flat object, looks like: +// { "attached": fn, "detached": fn, ... } const transitionsMap = new WeakMap(); +/** + * Used to clean up all transition states around an element whenever it is + * detached or replaced. + */ +function cleanup(element) { + if (transitionMap.has(element)) { + const internalMap = transitionsMap.get(element) || {}; + + Object.keys(internalMap).forEach(key => { + removeTransitionState(key, internalMap[key]) + }); + + transitionsMap.delete(element); + } +} + /** * Binds inline transitions to the parent element and triggers for any matching * nested children. */ export default function({ addTransitionState, removeTransitionState }) { + // When the element is attached, trigger the state handler if it exists. addTransitionState('attached', (element) => { if (element.attributes.attached) { return element.attached.call(this, element, element); } }); + // Remove all transitions whenever the element is detached or replaced. + addTransitionState('detached', removeTransitions); + addTransitionstate('replaced', removeTransitions); + // Set a "global" `attributeChanged` to monitor all elements for transition // states being attached. addTransitionState('attributeChanged', (element, name, oldVal, newVal) => { @@ -28,6 +51,7 @@ export default function({ addTransitionState, removeTransitionState }) { return; } + // A new value means to set the internal map. if (newVal) { transitionsMap.set(element, Object.assign(internalMap, { [name]: (...args) => { @@ -39,6 +63,7 @@ export default function({ addTransitionState, removeTransitionState }) { addTransitionState(name, internalMap[name]) } + // No new value indicates a removal. else if (internalMap[name]) { removeTransitionState(name, internalMap[name]) delete internalMap[name];