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

Commit a08ad70

Browse files
Pem Tairawesleycho
Pem Taira
authored andcommitted
fix(modal): ensure correct index is set
- Fixes index set to avoid potential concurrent z-index values for multiple modals Closes #5733 Fixes #5670
1 parent 4ec35e4 commit a08ad70

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

src/modal/modal.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
257257
var $modalStack = {
258258
NOW_CLOSING_EVENT: 'modal.stack.now-closing'
259259
};
260+
var topModalIndex = 0;
261+
var previousTopOpenedModal = null;
260262

261263
//Modal focus behavior
262264
var tabableSelector = 'a[href], area[href], input:not([disabled]), ' +
@@ -278,6 +280,12 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
278280
topBackdropIndex = i;
279281
}
280282
}
283+
284+
// If any backdrop exist, ensure that it's index is always
285+
// right below the top modal
286+
if (topBackdropIndex > -1 && topBackdropIndex < topModalIndex) {
287+
topBackdropIndex = topModalIndex;
288+
}
281289
return topBackdropIndex;
282290
}
283291

@@ -293,6 +301,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
293301

294302
//clean up the stack
295303
openedWindows.remove(modalInstance);
304+
previousTopOpenedModal = openedWindows.top();
305+
if (previousTopOpenedModal) {
306+
topModalIndex = parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10);
307+
}
296308

297309
removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {
298310
var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;
@@ -432,6 +444,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
432444
modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;
433445

434446
toggleTopWindowClass(false);
447+
448+
// Store the current top first, to determine what index we ought to use
449+
// for the current top modal
450+
previousTopOpenedModal = openedWindows.top();
435451

436452
openedWindows.add(modalInstance, {
437453
deferred: modal.deferred,
@@ -468,13 +484,15 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
468484
$animate.enter(backdropDomEl, appendToElement);
469485
}
470486

487+
// Set the top modal index based on the index of the previous top modal
488+
topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
471489
var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
472490
angularDomEl.attr({
473491
'template-url': modal.windowTemplateUrl,
474492
'window-class': modal.windowClass,
475493
'window-top-class': modal.windowTopClass,
476494
'size': modal.size,
477-
'index': openedWindows.length() - 1,
495+
'index': topModalIndex,
478496
'animate': 'animate'
479497
}).html(modal.content);
480498
if (modal.animation) {

src/modal/test/modal.spec.js

+101
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,107 @@ describe('$uibModal', function() {
16151615
expect($document.find('div.modal1')).toHaveClass('modal-top');
16161616
expect($document).toHaveModalsOpen(1);
16171617
});
1618+
1619+
it('should have top modal with highest index', function() {
1620+
var modal2Index = null;
1621+
var modal3Index = null;
1622+
1623+
var modal1Instance = {
1624+
result: $q.defer(),
1625+
opened: $q.defer(),
1626+
closed: $q.defer(),
1627+
rendered: $q.defer(),
1628+
close: function(result) {
1629+
return $uibModalStack.close(modal1Instance, result);
1630+
},
1631+
dismiss: function(reason) {
1632+
return $uibModalStack.dismiss(modal1Instance, reason);
1633+
}
1634+
};
1635+
var modal2Instance = {
1636+
result: $q.defer(),
1637+
opened: $q.defer(),
1638+
closed: $q.defer(),
1639+
rendered: $q.defer(),
1640+
close: function(result) {
1641+
return $uibModalStack.close(modal2Instance, result);
1642+
},
1643+
dismiss: function(reason) {
1644+
return $uibModalStack.dismiss(modal2Instance, reason);
1645+
}
1646+
};
1647+
var modal3Instance = {
1648+
result: $q.defer(),
1649+
opened: $q.defer(),
1650+
closed: $q.defer(),
1651+
rendered: $q.defer(),
1652+
close: function(result) {
1653+
return $uibModalStack.close(modal13nstance, result);
1654+
},
1655+
dismiss: function(reason) {
1656+
return $uibModalStack.dismiss(modal3Instance, reason);
1657+
}
1658+
};
1659+
1660+
var modal1 = $uibModalStack.open(modal1Instance, {
1661+
appendTo: angular.element(document.body),
1662+
scope: $rootScope.$new(),
1663+
deferred: modal1Instance.result,
1664+
renderDeferred: modal1Instance.rendered,
1665+
closedDeferred: modal1Instance.closed,
1666+
content: '<div>Modal1</div>'
1667+
});
1668+
1669+
expect($document).toHaveModalsOpen(0);
1670+
$rootScope.$digest();
1671+
$animate.flush();
1672+
expect($document).toHaveModalsOpen(1);
1673+
1674+
expect(parseInt($uibModalStack.getTop().value.modalDomEl.attr('index'), 10)).toEqual(0);
1675+
1676+
var modal2 = $uibModalStack.open(modal2Instance, {
1677+
appendTo: angular.element(document.body),
1678+
scope: $rootScope.$new(),
1679+
deferred: modal2Instance.result,
1680+
renderDeferred: modal2Instance.rendered,
1681+
closedDeferred: modal2Instance.closed,
1682+
content: '<div>Modal2</div>'
1683+
});
1684+
1685+
modal2Instance.rendered.promise.then(function() {
1686+
modal2Index = parseInt($uibModalStack.getTop().value.modalDomEl.attr('index'), 10);
1687+
});
1688+
1689+
expect($document).toHaveModalsOpen(1);
1690+
$rootScope.$digest();
1691+
$animate.flush();
1692+
expect($document).toHaveModalsOpen(2);
1693+
1694+
expect(modal2Index).toEqual(1);
1695+
close(modal1Instance);
1696+
expect($document).toHaveModalsOpen(1);
1697+
1698+
var modal3 = $uibModalStack.open(modal3Instance, {
1699+
appendTo: angular.element(document.body),
1700+
scope: $rootScope.$new(),
1701+
deferred: modal3Instance.result,
1702+
renderDeferred: modal3Instance.rendered,
1703+
closedDeferred: modal3Instance.closed,
1704+
content: '<div>Modal3</div>'
1705+
});
1706+
1707+
modal3Instance.rendered.promise.then(function() {
1708+
modal3Index = parseInt($uibModalStack.getTop().value.modalDomEl.attr('index'), 10);
1709+
});
1710+
1711+
expect($document).toHaveModalsOpen(1);
1712+
$rootScope.$digest();
1713+
$animate.flush();
1714+
expect($document).toHaveModalsOpen(2);
1715+
1716+
expect(modal3Index).toEqual(2);
1717+
expect(modal2Index).toBeLessThan(modal3Index);
1718+
});
16181719
});
16191720

16201721
describe('modal.closing event', function() {

0 commit comments

Comments
 (0)