Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit 7fce2fe

Browse files
fix(modal): backdrop should cover previously opened modals
Closes #922 Closes #931
1 parent 015625d commit 7fce2fe

File tree

4 files changed

+57
-31
lines changed

4 files changed

+57
-31
lines changed

src/modal/modal.js

+48-29
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ angular.module('ui.bootstrap.modal', [])
2323
}
2424
}
2525
},
26+
keys: function() {
27+
var keys = [];
28+
for (var i = 0; i < stack.length; i++) {
29+
keys.push(stack[i].key);
30+
}
31+
return keys;
32+
},
2633
top: function () {
2734
return stack[stack.length - 1];
2835
},
@@ -53,7 +60,6 @@ angular.module('ui.bootstrap.modal', [])
5360
.directive('modalBackdrop', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
5461
return {
5562
restrict: 'EA',
56-
scope: {},
5763
replace: true,
5864
templateUrl: 'template/modal/backdrop.html',
5965
link: function (scope, element, attrs) {
@@ -65,11 +71,10 @@ angular.module('ui.bootstrap.modal', [])
6571

6672
scope.close = function (evt) {
6773
var modal = $modalStack.getTop();
68-
//TODO: this logic is duplicated with the place where modal gets opened
69-
if (modal && modal.window.backdrop && modal.window.backdrop != 'static') {
74+
if (modal && modal.value.backdrop && modal.value.backdrop != 'static') {
7075
evt.preventDefault();
7176
evt.stopPropagation();
72-
$modalStack.dismiss(modal.instance, 'backdrop click');
77+
$modalStack.dismiss(modal.key, 'backdrop click');
7378
}
7479
};
7580
}
@@ -79,7 +84,9 @@ angular.module('ui.bootstrap.modal', [])
7984
.directive('modalWindow', ['$timeout', function ($timeout) {
8085
return {
8186
restrict: 'EA',
82-
scope: {},
87+
scope: {
88+
index: '@'
89+
},
8390
replace: true,
8491
transclude: true,
8592
templateUrl: 'template/modal/window.html',
@@ -97,23 +104,41 @@ angular.module('ui.bootstrap.modal', [])
97104
.factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap',
98105
function ($document, $compile, $rootScope, $$stackedMap) {
99106

107+
var backdropjqLiteEl, backdropDomEl;
108+
var backdropScope = $rootScope.$new(true);
100109
var body = $document.find('body').eq(0);
101110
var openedWindows = $$stackedMap.createNew();
102111
var $modalStack = {};
103112

113+
function backdropIndex() {
114+
var topBackdropIndex = -1;
115+
var opened = openedWindows.keys();
116+
for (var i = 0; i < opened.length; i++) {
117+
if (openedWindows.get(opened[i]).value.backdrop) {
118+
topBackdropIndex = i;
119+
}
120+
}
121+
return topBackdropIndex;
122+
}
123+
124+
$rootScope.$watch(backdropIndex, function(newBackdropIndex){
125+
backdropScope.index = newBackdropIndex;
126+
});
127+
104128
function removeModalWindow(modalInstance) {
105129

106130
var modalWindow = openedWindows.get(modalInstance).value;
107131

108132
//clean up the stack
109133
openedWindows.remove(modalInstance);
110134

111-
//remove DOM element
135+
//remove window DOM element
112136
modalWindow.modalDomEl.remove();
113137

114-
//remove backdrop
115-
if (modalWindow.backdropDomEl) {
116-
modalWindow.backdropDomEl.remove();
138+
//remove backdrop if no longer needed
139+
if (backdropIndex() == -1) {
140+
backdropDomEl.remove();
141+
backdropDomEl = undefined;
117142
}
118143

119144
//destroy scope
@@ -135,27 +160,27 @@ angular.module('ui.bootstrap.modal', [])
135160

136161
$modalStack.open = function (modalInstance, modal) {
137162

138-
var backdropDomEl;
139-
if (modal.backdrop) {
140-
backdropDomEl = $compile(angular.element('<div modal-backdrop></div>'))($rootScope);
141-
body.append(backdropDomEl);
142-
}
163+
openedWindows.add(modalInstance, {
164+
deferred: modal.deferred,
165+
modalScope: modal.scope,
166+
backdrop: modal.backdrop,
167+
keyboard: modal.keyboard
168+
});
143169

144170
var angularDomEl = angular.element('<div modal-window></div>');
145171
angularDomEl.attr('window-class', modal.windowClass);
172+
angularDomEl.attr('index', openedWindows.length() - 1);
146173
angularDomEl.html(modal.content);
147174

148175
var modalDomEl = $compile(angularDomEl)(modal.scope);
176+
openedWindows.top().value.modalDomEl = modalDomEl;
149177
body.append(modalDomEl);
150178

151-
openedWindows.add(modalInstance, {
152-
deferred: modal.deferred,
153-
modalScope: modal.scope,
154-
modalDomEl: modalDomEl,
155-
backdrop: modal.backdrop,
156-
backdropDomEl: backdropDomEl,
157-
keyboard: modal.keyboard
158-
});
179+
if (backdropIndex() >= 0 && !backdropDomEl) {
180+
backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
181+
backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
182+
body.append(backdropDomEl);
183+
}
159184
};
160185

161186
$modalStack.close = function (modalInstance, result) {
@@ -175,13 +200,7 @@ angular.module('ui.bootstrap.modal', [])
175200
};
176201

177202
$modalStack.getTop = function () {
178-
var top = openedWindows.top();
179-
if (top) {
180-
return {
181-
instance: top.key,
182-
window: top.value
183-
};
184-
}
203+
return openedWindows.top();
185204
};
186205

187206
return $modalStack;

src/modal/test/stackedMap.spec.js

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ describe('stacked map', function () {
1919
expect(stackedMap.get('foo')).toBeUndefined();
2020
});
2121

22+
it('should support listing keys', function () {
23+
stackedMap.add('foo', 'foo_value');
24+
stackedMap.add('bar', 'bar_value');
25+
26+
expect(stackedMap.keys()).toEqual(['foo', 'bar']);
27+
});
28+
2229
it('should get topmost element', function () {
2330

2431
stackedMap.add('foo', 'foo_value');

template/modal/backdrop.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div class="modal-backdrop fade" ng-class="{in: animate}" ng-click="close($event)"></div>
1+
<div class="modal-backdrop fade" ng-class="{in: animate}" ng-style="{'z-index': 1040 + index*10}" ng-click="close($event)"></div>

template/modal/window.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div class="modal fade {{ windowClass }}" ng-class="{in: animate}" ng-transclude></div>
1+
<div class="modal fade {{ windowClass }}" ng-class="{in: animate}" ng-style="{'z-index': 1050 + index*10}" ng-transclude></div>

0 commit comments

Comments
 (0)