@@ -257,7 +257,12 @@ function InterimElementProvider() {
257
257
* A service used to control inserting and removing an element into the DOM.
258
258
*
259
259
*/
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.
261
266
262
267
// Publish instance $$interimElement service;
263
268
// ... used as $mdDialog, $mdToast, $mdMenu, and $mdSelect
@@ -286,26 +291,35 @@ function InterimElementProvider() {
286
291
function show ( options ) {
287
292
options = options || { } ;
288
293
var interimElement = new InterimElement ( options || { } ) ;
294
+
289
295
// When an interim element is currently showing, we have to cancel it.
290
296
// Just hiding it, will resolve the InterimElement's promise, the promise should be
291
297
// 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
+ }
296
308
297
- hideExisting . finally ( function ( ) {
309
+ var showAction = hideAction . then ( function ( ) {
298
310
299
- stack . push ( interimElement ) ;
300
- interimElement
311
+ return interimElement
301
312
. 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 ) ;
305
317
} ) ;
306
318
307
319
} ) ;
308
320
321
+ showPromises . push ( showAction ) ;
322
+
309
323
// Return a promise that will be resolved when the interim
310
324
// element is hidden or cancelled...
311
325
@@ -325,27 +339,34 @@ function InterimElementProvider() {
325
339
*
326
340
*/
327
341
function hide ( reason , options ) {
328
- if ( ! stack . length ) return $q . when ( reason ) ;
342
+ if ( ! showingInterims . length ) {
343
+ return $q . when ( reason ) ;
344
+ }
345
+
329
346
options = options || { } ;
330
347
331
348
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 ) ) ;
335
351
} 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 ) ) ;
337
353
} else {
338
- var interim = stack . pop ( ) ;
354
+ var interim = showingInterims . pop ( ) ;
339
355
return closeElement ( interim ) ;
340
356
}
341
357
342
358
function closeElement ( interim ) {
343
- interim
359
+
360
+ var hideAction = interim
344
361
. 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 ) ;
348
365
} ) ;
366
+
367
+ showingInterims . splice ( showingInterims . indexOf ( interim ) , 1 ) ;
368
+ hidePromises . push ( hideAction ) ;
369
+
349
370
return interim . deferred . promise ;
350
371
}
351
372
}
@@ -363,16 +384,20 @@ function InterimElementProvider() {
363
384
*
364
385
*/
365
386
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 ) ;
374
397
} ) ;
375
398
399
+ hidePromises . push ( cancelAction ) ;
400
+
376
401
// Since Angular 1.6.7, promises will be logged to $exceptionHandler when the promise
377
402
// is not handling the rejection. We create a pseudo catch handler, which will prevent the
378
403
// promise from being logged to the $exceptionHandler.
@@ -383,26 +408,27 @@ function InterimElementProvider() {
383
408
* Special method to quick-remove the interim element without animations
384
409
* Note: interim elements are in "interim containers"
385
410
*/
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 ;
396
413
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
+ }
403
428
}
404
429
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 ) ;
406
432
}
407
433
408
434
/*
0 commit comments