From bcfe210afdd1468bfd19810858f08f94242e5a7a Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 8 Jun 2015 14:50:25 -0500 Subject: [PATCH] fix(popup): close highest overlay Remember a stack of overlays to ensure the highest one is closed when clicking the backdrop. Closes #2157 --- js/angular/service/modal.js | 25 +++++++++++++++++++++++-- js/angular/service/popup.js | 7 +++++-- test/unit/angular/service/popup.unit.js | 1 + 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/js/angular/service/modal.js b/js/angular/service/modal.js index 308d0fa884f..abc89f76628 100644 --- a/js/angular/service/modal.js +++ b/js/angular/service/modal.js @@ -132,6 +132,7 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl // on iOS, clicks will sometimes bleed through/ghost click on underlying // elements $ionicClickBlock.show(600); + stack.add(self); var modalEl = jqLite(self.modalEl); @@ -185,7 +186,7 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl if (!self._isShown) return; //After animating in, allow hide on backdrop click self.$el.on('click', function(e) { - if (self.backdropClickToClose && e.target === self.el) { + if (self.backdropClickToClose && e.target === self.el && stack.isHighest(self)) { self.hide(); } }); @@ -205,6 +206,7 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl // on iOS, clicks will sometimes bleed through/ghost click on underlying // elements $ionicClickBlock.show(600); + stack.remove(self); self.el.classList.remove('active'); modalEl.addClass('ng-leave'); @@ -293,6 +295,23 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl return modal; }; + var modalStack = []; + var stack = { + add: function(modal) { + modalStack.push(modal); + }, + remove: function(modal) { + var index = modalStack.indexOf(modal); + if (index > -1 && index < modalStack.length) { + modalStack.splice(index, 1); + } + }, + isHighest: function(modal) { + var index = modalStack.indexOf(modal); + return (index > -1 && index === modalStack.length - 1); + } + }; + return { /** * @ngdoc method @@ -328,6 +347,8 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl cb && cb(modal); return modal; }); - } + }, + + stack: stack }; }]); diff --git a/js/angular/service/popup.js b/js/angular/service/popup.js index e258714894f..4e708197898 100644 --- a/js/angular/service/popup.js +++ b/js/angular/service/popup.js @@ -113,8 +113,9 @@ IonicModule '$ionicBody', '$compile', '$ionicPlatform', + '$ionicModal', 'IONIC_BACK_PRIORITY', -function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicBody, $compile, $ionicPlatform, IONIC_BACK_PRIORITY) { +function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicBody, $compile, $ionicPlatform, $ionicModal, IONIC_BACK_PRIORITY) { //TODO allow this to be configured var config = { stackPushDelay: 75 @@ -321,6 +322,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB self.show = function() { if (self.isShown || self.removed) return; + $ionicModal.stack.add(self); self.isShown = true; ionic.requestAnimationFrame(function() { //if hidden while waiting for raf, don't show @@ -336,6 +338,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB callback = callback || noop; if (!self.isShown) return callback(); + $ionicModal.stack.remove(self); self.isShown = false; self.element.removeClass('active'); self.element.addClass('popup-hidden'); @@ -343,7 +346,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB }; self.remove = function() { - if (self.removed) return; + if (self.removed || !$ionicModal.stack.isHighest(self)) return; self.hide(function() { self.element.remove(); diff --git a/test/unit/angular/service/popup.unit.js b/test/unit/angular/service/popup.unit.js index 79f3703dace..3f9421f08c5 100644 --- a/test/unit/angular/service/popup.unit.js +++ b/test/unit/angular/service/popup.unit.js @@ -158,6 +158,7 @@ describe('$ionicPopup service', function() { spyOn(popup, 'hide').andCallFake(function(cb) { cb(); }); + popup.show(); spyOn(popup.element, 'remove'); spyOn(popup.scope, '$destroy'); popup.remove();