@@ -257,15 +257,20 @@ function InterimElementProvider() {
257257       * A service used to control inserting and removing an element into the DOM. 
258258       * 
259259       */ 
260-       var  service ,  stack  =  [ ] ; 
260+ 
261+       var  service ; 
262+ 
263+       var  showPromises  =  [ ] ;  // Promises for the interim's which are currently opening. 
264+       var  hidePromises  =  [ ] ;  // Promises for the interim's which are currently hiding. 
265+       var  showingInterims  =  [ ] ;  // Interim elements which are currently showing up. 
261266
262267      // Publish instance $$interimElement service; 
263268      // ... used as $mdDialog, $mdToast, $mdMenu, and $mdSelect 
264269
265270      return  service  =  { 
266271        show : show , 
267-         hide : hide , 
268-         cancel : cancel , 
272+         hide : waitForInterim ( hide ) , 
273+         cancel : waitForInterim ( cancel ) , 
269274        destroy  : destroy , 
270275        $injector_ : $injector 
271276      } ; 
@@ -286,26 +291,35 @@ function InterimElementProvider() {
286291      function  show ( options )  { 
287292        options  =  options  ||  { } ; 
288293        var  interimElement  =  new  InterimElement ( options  ||  { } ) ; 
294+ 
289295        // When an interim element is currently showing, we have to cancel it. 
290296        // Just hiding it, will resolve the InterimElement's promise, the promise should be 
291297        // rejected instead. 
292-         var  hideExisting  =  ! options . skipHide  &&  stack . length  ? service . cancel ( )  : $q . when ( true ) ; 
293- 
294-         // This hide()s only the current interim element before showing the next, new one 
295-         // NOTE: this is not reversible (e.g. interim elements are not stackable) 
298+         var  hideAction  =  options . multiple  ? $q . resolve ( )  : $q . all ( showPromises ) ; 
299+ 
300+         if  ( ! options . multiple )  { 
301+           // Wait for all opening interim's to finish their transition. 
302+           hideAction  =  hideAction . then ( function ( )  { 
303+             // Wait for all closing and showing interim's to be completely closed. 
304+             var  promiseArray  =  hidePromises . concat ( showingInterims . map ( service . cancel ) ) ; 
305+             return  $q . all ( promiseArray ) ; 
306+           } ) ; 
307+         } 
296308
297-         hideExisting . finally ( function ( )  { 
309+         var   showAction   =   hideAction . then ( function ( )  { 
298310
299-           stack . push ( interimElement ) ; 
300-           interimElement 
311+           return  interimElement 
301312            . show ( ) 
302-             . catch ( function (  reason  )  { 
303-               //$log.error("InterimElement.show() error: " + reason ); 
304-               return  reason ; 
313+             . catch ( function ( reason )  {  return  reason ;  } ) 
314+             . finally ( function ( )  { 
315+               showPromises . splice ( showPromises . indexOf ( showAction ) ,  1 ) ; 
316+               showingInterims . push ( interimElement ) ; 
305317            } ) ; 
306318
307319        } ) ; 
308320
321+         showPromises . push ( showAction ) ; 
322+ 
309323        // Return a promise that will be resolved when the interim 
310324        // element is hidden or cancelled... 
311325
@@ -325,27 +339,30 @@ function InterimElementProvider() {
325339       * 
326340       */ 
327341      function  hide ( reason ,  options )  { 
328-         if  (  ! stack . length  )  return  $q . when ( reason ) ; 
329342        options  =  options  ||  { } ; 
330343
331344        if  ( options . closeAll )  { 
332-           var  promise  =  $q . all ( stack . reverse ( ) . map ( closeElement ) ) ; 
333-           stack  =  [ ] ; 
334-           return  promise ; 
345+           // We have to make a shallow copy of the array, because otherwise the map will break. 
346+           return  $q . all ( showingInterims . slice ( ) . reverse ( ) . map ( closeElement ) ) ; 
335347        }  else  if  ( options . closeTo  !==  undefined )  { 
336-           return  $q . all ( stack . splice ( options . closeTo ) . map ( closeElement ) ) ; 
337-         }  else  { 
338-           var  interim  =  stack . pop ( ) ; 
339-           return  closeElement ( interim ) ; 
348+           return  $q . all ( showingInterims . slice ( options . closeTo ) . map ( closeElement ) ) ; 
340349        } 
341350
351+         // Hide the latest showing interim element. 
352+         return  closeElement ( showingInterims . pop ( ) ) ; 
353+ 
342354        function  closeElement ( interim )  { 
343-           interim 
355+ 
356+           var  hideAction  =  interim 
344357            . remove ( reason ,  false ,  options  ||  {  } ) 
345-             . catch ( function (   reason   )  { 
346-                //$log.error("InterimElement.hide () error: " + reason ); 
347-               return   reason ; 
358+             . catch ( function ( reason )  {   return   reason ;   } ) 
359+             . finally ( function ( )  { 
360+               hidePromises . splice ( hidePromises . indexOf ( hideAction ) ,   1 ) ; 
348361            } ) ; 
362+ 
363+           showingInterims . splice ( showingInterims . indexOf ( interim ) ,  1 ) ; 
364+           hidePromises . push ( hideAction ) ; 
365+ 
349366          return  interim . deferred . promise ; 
350367        } 
351368      } 
@@ -363,46 +380,76 @@ function InterimElementProvider() {
363380       * 
364381       */ 
365382      function  cancel ( reason ,  options )  { 
366-         var  interim  =  stack . pop ( ) ; 
367-         if  (  ! interim  )  return  $q . when ( reason ) ; 
368- 
369-         interim 
370-           . remove ( reason ,  true ,  options  ||  {  } ) 
371-           . catch ( function (  reason  )  { 
372-             //$log.error("InterimElement.cancel() error: " + reason ); 
373-             return  reason ; 
383+         var  interim  =  showingInterims . pop ( ) ; 
384+         if  ( ! interim )  { 
385+           return  $q . when ( reason ) ; 
386+         } 
387+ 
388+         var  cancelAction  =  interim 
389+           . remove ( reason ,  true ,  options  ||  { } ) 
390+           . catch ( function ( reason )  {  return  reason ;  } ) 
391+           . finally ( function ( )  { 
392+             hidePromises . splice ( hidePromises . indexOf ( cancelAction ) ,  1 ) ; 
374393          } ) ; 
375394
395+         hidePromises . push ( cancelAction ) ; 
396+ 
376397        // Since Angular 1.6.7, promises will be logged to $exceptionHandler when the promise 
377398        // is not handling the rejection. We create a pseudo catch handler, which will prevent the 
378399        // promise from being logged to the $exceptionHandler. 
379400        return  interim . deferred . promise . catch ( angular . noop ) ; 
380401      } 
381402
403+       /** 
404+        * Creates a function to wait for at least one interim element to be available. 
405+        * @param  callbackFn Function to be used as callback 
406+        * @returns  {Function } 
407+        */ 
408+       function  waitForInterim ( callbackFn )  { 
409+         return  function ( )  { 
410+           var  fnArguments  =  arguments ; 
411+ 
412+           if  ( ! showingInterims . length )  { 
413+             // When there are still interim's opening, then wait for the first interim element to 
414+             // finish its open animation. 
415+             if  ( showPromises . length )  { 
416+               return  showPromises [ 0 ] . finally ( function  ( )  { 
417+                 return  callbackFn . apply ( service ,  fnArguments ) ; 
418+               } ) ; 
419+             } 
420+ 
421+             return  $q . when ( "No interim elements currently showing up." ) ; 
422+           } 
423+ 
424+           return  callbackFn . apply ( service ,  fnArguments ) ; 
425+         } ; 
426+       } 
427+ 
382428      /* 
383429       * Special method to quick-remove the interim element without animations 
384430       * Note: interim elements are in "interim containers" 
385431       */ 
386-       function  destroy ( target )  { 
387-         var  interim  =  ! target  ? stack . shift ( )  : null ; 
388-         var  cntr  =  angular . element ( target ) . length  ? angular . element ( target ) [ 0 ] . parentNode  : null ; 
389- 
390-         if  ( cntr )  { 
391-             // Try to find the interim element in the stack which corresponds to the supplied DOM element. 
392-             var  filtered  =  stack . filter ( function ( entry )  { 
393-                   var  currNode  =  entry . options . element [ 0 ] ; 
394-                   return   ( currNode  ===  cntr ) ; 
395-                 } ) ; 
432+       function  destroy ( targetEl )  { 
433+         var  interim  =  ! targetEl  ? showingInterims . shift ( )  : null ; 
396434
397-             // Note: this function might be called when the element already has been removed, in which 
398-             //       case we won't find any matches. That's ok. 
399-             if  ( filtered . length  >  0 )  { 
400-               interim  =  filtered [ 0 ] ; 
401-               stack . splice ( stack . indexOf ( interim ) ,  1 ) ; 
402-             } 
435+         var  parentEl  =  angular . element ( targetEl ) . length  &&  angular . element ( targetEl ) [ 0 ] . parentNode ; 
436+ 
437+         if  ( parentEl )  { 
438+           // Try to find the interim in the stack which corresponds to the supplied DOM element. 
439+           var  filtered  =  showingInterims . filter ( function ( entry )  { 
440+             return  entry . options . element [ 0 ]  ===  parentEl ; 
441+           } ) ; 
442+ 
443+           // Note: This function might be called when the element already has been removed, 
444+           // in which case we won't find any matches. 
445+           if  ( filtered . length )  { 
446+             interim  =  filtered [ 0 ] ; 
447+             showingInterims . splice ( showingInterims . indexOf ( interim ) ,  1 ) ; 
448+           } 
403449        } 
404450
405-         return  interim  ? interim . remove ( SHOW_CANCELLED ,  false ,  { '$destroy' :true } )  : $q . when ( SHOW_CANCELLED ) ; 
451+         return  interim  ? interim . remove ( SHOW_CANCELLED ,  false ,  {  '$destroy' : true  } )  :
452+                          $q . when ( SHOW_CANCELLED ) ; 
406453      } 
407454
408455      /* 
0 commit comments