@@ -144,6 +144,11 @@ var Idiomorph = (function () {
144144 restoreFocus : true ,
145145 } ;
146146
147+ let plugins = { } ;
148+ function addPlugin ( plugin ) {
149+ plugins [ plugin . name ] = plugin ;
150+ }
151+
147152 /**
148153 * Core idiomorph function for morphing one DOM tree to another
149154 *
@@ -348,6 +353,26 @@ var Idiomorph = (function () {
348353 }
349354 }
350355
356+ function withNodeCallbacks ( ctx , name , node , fn ) {
357+ const allPlugins = [ ...Object . values ( plugins ) , ctx . callbacks ] ;
358+
359+ const shouldAbort = allPlugins . some ( ( plugin ) => {
360+ const beforeFn = plugin [ `beforeNode${ name } ` ] ;
361+ return beforeFn && beforeFn ( node ) === false ;
362+ } ) ;
363+
364+ if ( shouldAbort ) return ;
365+
366+ const resultNode = fn ( ) ;
367+
368+ allPlugins . reverse ( ) . forEach ( ( plugin ) => {
369+ const afterFn = plugin [ `afterNode${ name } ` ] ;
370+ afterFn && afterFn ( resultNode ) ;
371+ } ) ;
372+
373+ return resultNode ;
374+ }
375+
351376 /**
352377 * This performs the action of inserting a new node while handling situations where the node contains
353378 * elements with persistent ids and possible state info we can still preserve by moving in and then morphing
@@ -359,23 +384,22 @@ var Idiomorph = (function () {
359384 * @returns {Node|null }
360385 */
361386 function createNode ( oldParent , newChild , insertionPoint , ctx ) {
362- if ( ctx . callbacks . beforeNodeAdded ( newChild ) === false ) return null ;
363- if ( ctx . idMap . has ( newChild ) ) {
364- // node has children with ids with possible state so create a dummy elt of same type and apply full morph algorithm
365- const newEmptyChild = document . createElement (
366- /** @type {Element } */ ( newChild ) . tagName ,
367- ) ;
368- oldParent . insertBefore ( newEmptyChild , insertionPoint ) ;
369- morphNode ( newEmptyChild , newChild , ctx ) ;
370- ctx . callbacks . afterNodeAdded ( newEmptyChild ) ;
371- return newEmptyChild ;
372- } else {
373- // optimisation: no id state to preserve so we can just insert a clone of the newChild and its descendants
374- const newClonedChild = document . importNode ( newChild , true ) ; // importNode to not mutate newParent
375- oldParent . insertBefore ( newClonedChild , insertionPoint ) ;
376- ctx . callbacks . afterNodeAdded ( newClonedChild ) ;
377- return newClonedChild ;
378- }
387+ return withNodeCallbacks ( ctx , "Added" , newChild , ( ) => {
388+ if ( ctx . idMap . has ( newChild ) ) {
389+ // node has children with ids with possible state so create a dummy elt of same type and apply full morph algorithm
390+ const newEmptyChild = document . createElement (
391+ /** @type {Element } */ ( newChild ) . tagName ,
392+ ) ;
393+ oldParent . insertBefore ( newEmptyChild , insertionPoint ) ;
394+ morphNode ( newEmptyChild , newChild , ctx ) ;
395+ return newEmptyChild ;
396+ } else {
397+ // optimisation: no id state to preserve so we can just insert a clone of the newChild and its descendants
398+ const newClonedChild = document . importNode ( newChild , true ) ; // importNode to not mutate newParent
399+ oldParent . insertBefore ( newClonedChild , insertionPoint ) ;
400+ return newClonedChild ;
401+ }
402+ } ) ;
379403 }
380404
381405 //=============================================================================
@@ -505,9 +529,9 @@ var Idiomorph = (function () {
505529 moveBefore ( ctx . pantry , node , null ) ;
506530 } else {
507531 // remove for realsies
508- if ( ctx . callbacks . beforeNodeRemoved ( node ) === false ) return ;
509- node . parentNode ?. removeChild ( node ) ;
510- ctx . callbacks . afterNodeRemoved ( node ) ;
532+ withNodeCallbacks ( ctx , "Removed" , node , ( ) => {
533+ return node . parentNode ?. removeChild ( node ) ;
534+ } ) ;
511535 }
512536 }
513537
@@ -1300,5 +1324,6 @@ var Idiomorph = (function () {
13001324 return {
13011325 morph,
13021326 defaults,
1327+ addPlugin,
13031328 } ;
13041329} ) ( ) ;
0 commit comments