UNPKG

diffhtml-middleware-inline-transitions

Version:

Monitors inline attributes and assigns transition hooks

39 lines (35 loc) 3.83 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.inlineTransitions = factory()); }(this, (function () { 'use strict'; var assign=Object.assign,keys=Object.keys;var eventsToTransitionName={attributechanged:"attributeChanged",textchanged:"textChanged"};// Store maps of elements to handlers that are associated to transitions. var transitionsMap={attached:new Map,detached:new Map,replaced:new Map,attributechanged:new Map,textchanged:new Map};// Internal global transition state handlers, allows us to bind once and match. var boundHandlers={};/** * Binds inline transitions to the parent element and triggers for any matching * nested children. */function inlineTransitions(){// Monitors whenever an element changes an attribute, if the attribute is a // valid state name, add this element into the related Set. var attributeChanged=function(domNode,name,_oldVal,newVal){var prefix=name.toLowerCase().slice(0,2);// Don't bother with non-events. if(prefix!=="on"){return}// Normalize the event name to lowercase and without `on`. name=name.toLowerCase().slice(2);var map=transitionsMap[name];var isFunction=typeof newVal==="function";// Abort early if not a valid transition or if the new value exists, but // isn't a function. if(!map||newVal&&!isFunction){return}// Add or remove based on the value existence and type. map[isFunction?"set":"delete"](domNode,newVal);};var Internals=null;var subscribe=function(_Internals){Internals=_Internals;Internals.TransitionCache.get("attributeChanged").add(attributeChanged);// Add a transition for every type. keys(transitionsMap).forEach(function(name){var map=transitionsMap[name];var transitionName=eventsToTransitionName[name]||name;// This handler is bound for every possible transition to help limit the // amount of transitions bound. var handler=function(childNode){for(var _len=arguments.length,rest=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){rest[_key-1]=arguments[_key];}// Abort early if no childNode was present. if(!childNode){return}// If the child element triggered in the transition is the root // element, this is an easy lookup for the handler. if(map.has(childNode)){return map.get(childNode).apply(void 0,[childNode,childNode].concat(rest))}// Text nodes are looked up on the parent. else if(transitionName==="textChanged"){var parentNode=childNode.parentNode;if(map.has(parentNode)){return map.get(parentNode).apply(void 0,[parentNode,childNode].concat(rest))}}// Search if a parent is bound to this. else {var promises=[];map.forEach(function(_,parentNode){if(parentNode.contains(childNode)){var ret=map.get(parentNode).apply(void 0,[parentNode,childNode].concat(rest));ret&&promises.push(ret);}});if(promises.length){return Promise.all(promises)}}};// Save the handler for later unbinding. boundHandlers[transitionName]=handler;// Add the state handler. Internals.TransitionCache.get(transitionName).add(handler);});};// This will unbind any internally bound transition states. var unsubscribe=function(Internals){// Unbind all the transition states. Internals.TransitionCache.get("attributeChanged").delete(attributeChanged);// Remove all elements from the internal cache. keys(transitionsMap).forEach(function(name){var transitionName=eventsToTransitionName[name]||name;// Unbind the associated global handler. var handler=boundHandlers[transitionName];Internals.TransitionCache.get(transitionName).delete(handler);});// Empty the bound handlers. boundHandlers.length=0;};return assign(function(){},{displayName:"inlineTransitionsTask",subscribe:subscribe,unsubscribe:unsubscribe})} return inlineTransitions; })));