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

Commit e6b105a

Browse files
Tobinowesleycho
authored andcommitted
fix(modal): Fix focus when the dialog is close or cancelled
- Return focus to element with focus before modal opened Closes #2888
1 parent 26b4090 commit e6b105a

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

src/modal/modal.js

+5
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ angular.module('ui.bootstrap.modal', [])
266266

267267
$modalStack.open = function (modalInstance, modal) {
268268

269+
var modalOpener = $document[0].activeElement;
270+
269271
openedWindows.add(modalInstance, {
270272
deferred: modal.deferred,
271273
renderDeferred: modal.renderDeferred,
@@ -303,6 +305,7 @@ angular.module('ui.bootstrap.modal', [])
303305

304306
var modalDomEl = $compile(angularDomEl)(modal.scope);
305307
openedWindows.top().value.modalDomEl = modalDomEl;
308+
openedWindows.top().value.modalOpener = modalOpener;
306309
body.append(modalDomEl);
307310
body.addClass(OPENED_MODAL_CLASS);
308311
};
@@ -316,6 +319,7 @@ angular.module('ui.bootstrap.modal', [])
316319
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
317320
modalWindow.value.deferred.resolve(result);
318321
removeModalWindow(modalInstance);
322+
modalWindow.value.modalOpener.focus();
319323
return true;
320324
}
321325
return !modalWindow;
@@ -326,6 +330,7 @@ angular.module('ui.bootstrap.modal', [])
326330
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
327331
modalWindow.value.deferred.reject(reason);
328332
removeModalWindow(modalInstance);
333+
modalWindow.value.modalOpener.focus();
329334
return true;
330335
}
331336
return !modalWindow;

src/modal/test/modal.spec.js

+51
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,28 @@ describe('$modal', function () {
250250
expect($document).toHaveModalsOpen(0);
251251
});
252252

253+
it('should return to the element which had focus before the dialog is invoked', function () {
254+
var link = '<a href>Link</a>';
255+
var element = angular.element(link);
256+
angular.element(document.body).append(element);
257+
element.focus();
258+
expect(document.activeElement.tagName).toBe('A');
259+
260+
var modal = open({template: '<div>Content<button>inside modal</button></div>'});
261+
$timeout.flush();
262+
expect(document.activeElement.tagName).toBe('DIV');
263+
expect($document).toHaveModalsOpen(1);
264+
265+
triggerKeyDown($document, 27);
266+
$timeout.flush();
267+
$rootScope.$digest();
268+
269+
expect(document.activeElement.tagName).toBe('A');
270+
expect($document).toHaveModalsOpen(0);
271+
272+
element.remove();
273+
});
274+
253275
it('should resolve returned promise on close', function () {
254276
var modal = open({template: '<div>Content</div>'});
255277
close(modal, 'closed ok');
@@ -695,6 +717,35 @@ describe('$modal', function () {
695717
dismiss(modal2);
696718
expect(body).not.toHaveClass('modal-open');
697719
});
720+
721+
it('should return to the element which had focus before the dialog is invoked', function () {
722+
var link = '<a href>Link</a>';
723+
var element = angular.element(link);
724+
angular.element(document.body).append(element);
725+
element.focus();
726+
expect(document.activeElement.tagName).toBe('A');
727+
728+
var modal1 = open({template: '<div>Modal1<button id="focus">inside modal1</button></div>'});
729+
$timeout.flush();
730+
document.getElementById('focus').focus();
731+
expect(document.activeElement.tagName).toBe('BUTTON');
732+
expect($document).toHaveModalsOpen(1);
733+
734+
var modal2 = open({template: '<div>Modal2</div>'});
735+
$timeout.flush();
736+
expect(document.activeElement.tagName).toBe('DIV');
737+
expect($document).toHaveModalsOpen(2);
738+
739+
dismiss(modal2);
740+
expect(document.activeElement.tagName).toBe('BUTTON');
741+
expect($document).toHaveModalsOpen(1);
742+
743+
dismiss(modal1);
744+
expect(document.activeElement.tagName).toBe('A');
745+
expect($document).toHaveModalsOpen(0);
746+
747+
element.remove();
748+
});
698749
});
699750

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

0 commit comments

Comments
 (0)