@@ -257,7 +257,12 @@ 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
@@ -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 . when ( true ) : $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,34 @@ function InterimElementProvider() {
325339 *
326340 */
327341 function hide ( reason , options ) {
328- if ( ! stack . length ) return $q . when ( reason ) ;
342+ if ( ! showingInterims . length ) {
343+ return $q . when ( reason ) ;
344+ }
345+
329346 options = options || { } ;
330347
331348 if ( options . closeAll ) {
332- var promise = $q . all ( stack . reverse ( ) . map ( closeElement ) ) ;
333- stack = [ ] ;
334- return promise ;
349+ // We have to make a shallow copy of the array, because otherwise the map will break.
350+ return $q . all ( showingInterims . slice ( ) . reverse ( ) . map ( closeElement ) ) ;
335351 } else if ( options . closeTo !== undefined ) {
336- return $q . all ( stack . splice ( options . closeTo ) . map ( closeElement ) ) ;
352+ return $q . all ( showingInterims . slice ( options . closeTo ) . map ( closeElement ) ) ;
337353 } else {
338- var interim = stack . pop ( ) ;
354+ var interim = showingInterims . pop ( ) ;
339355 return closeElement ( interim ) ;
340356 }
341357
342358 function closeElement ( interim ) {
343- interim
359+
360+ var hideAction = interim
344361 . remove ( reason , false , options || { } )
345- . catch ( function ( reason ) {
346- //$log.error("InterimElement.hide () error: " + reason );
347- return reason ;
362+ . catch ( function ( reason ) { return reason ; } )
363+ . finally ( function ( ) {
364+ hidePromises . splice ( hidePromises . indexOf ( hideAction ) , 1 ) ;
348365 } ) ;
366+
367+ showingInterims . splice ( showingInterims . indexOf ( interim ) , 1 ) ;
368+ hidePromises . push ( hideAction ) ;
369+
349370 return interim . deferred . promise ;
350371 }
351372 }
@@ -363,16 +384,20 @@ function InterimElementProvider() {
363384 *
364385 */
365386 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 ;
387+ var interim = showingInterims . pop ( ) ;
388+ if ( ! interim ) {
389+ return $q . when ( reason ) ;
390+ }
391+
392+ var cancelAction = interim
393+ . remove ( reason , true , options || { } )
394+ . catch ( function ( reason ) { return reason ; } )
395+ . finally ( function ( ) {
396+ hidePromises . splice ( hidePromises . indexOf ( cancelAction ) , 1 ) ;
374397 } ) ;
375398
399+ hidePromises . push ( cancelAction ) ;
400+
376401 // Since Angular 1.6.7, promises will be logged to $exceptionHandler when the promise
377402 // is not handling the rejection. We create a pseudo catch handler, which will prevent the
378403 // promise from being logged to the $exceptionHandler.
@@ -383,26 +408,27 @@ function InterimElementProvider() {
383408 * Special method to quick-remove the interim element without animations
384409 * Note: interim elements are in "interim containers"
385410 */
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- } ) ;
411+ function destroy ( targetEl ) {
412+ var interim = ! targetEl ? showingInterims . shift ( ) : null ;
396413
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- }
414+ var parentEl = angular . element ( targetEl ) . length && angular . element ( targetEl ) [ 0 ] . parentNode ;
415+
416+ if ( parentEl ) {
417+ // Try to find the interim in the stack which corresponds to the supplied DOM element.
418+ var filtered = showingInterims . filter ( function ( entry ) {
419+ return entry . options . element [ 0 ] === parentEl ;
420+ } ) ;
421+
422+ // Note: This function might be called when the element already has been removed,
423+ // in which case we won't find any matches.
424+ if ( filtered . length > 0 ) {
425+ interim = filtered [ 0 ] ;
426+ showingInterims . splice ( showingInterims . indexOf ( interim ) , 1 ) ;
427+ }
403428 }
404429
405- return interim ? interim . remove ( SHOW_CANCELLED , false , { '$destroy' :true } ) : $q . when ( SHOW_CANCELLED ) ;
430+ return interim ? interim . remove ( SHOW_CANCELLED , false , { '$destroy' : true } ) :
431+ $q . when ( SHOW_CANCELLED ) ;
406432 }
407433
408434 /*
0 commit comments