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

Commit 988336c

Browse files
tompiwesleycho
authored andcommitted
fix(modal): focus on body if element disappears
- Change to focus on `document.body` instead if element is not present Closes #3653 Fixes #3639
1 parent 0d96221 commit 988336c

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

src/modal/modal.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ angular.module('ui.bootstrap.modal', [])
195195
}
196196
});
197197

198-
function removeModalWindow(modalInstance) {
198+
function removeModalWindow(modalInstance, elementToReceiveFocus) {
199199

200200
var body = $document.find('body').eq(0);
201201
var modalWindow = openedWindows.get(modalInstance).value;
@@ -208,6 +208,13 @@ angular.module('ui.bootstrap.modal', [])
208208
body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
209209
checkRemoveBackdrop();
210210
});
211+
212+
//move focus to specified element if available, or else to body
213+
if (elementToReceiveFocus && elementToReceiveFocus.focus) {
214+
elementToReceiveFocus.focus();
215+
} else {
216+
body.focus();
217+
}
211218
}
212219

213220
function checkRemoveBackdrop() {
@@ -318,8 +325,7 @@ angular.module('ui.bootstrap.modal', [])
318325
var modalWindow = openedWindows.get(modalInstance);
319326
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
320327
modalWindow.value.deferred.resolve(result);
321-
removeModalWindow(modalInstance);
322-
modalWindow.value.modalOpener.focus();
328+
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
323329
return true;
324330
}
325331
return !modalWindow;
@@ -329,8 +335,7 @@ angular.module('ui.bootstrap.modal', [])
329335
var modalWindow = openedWindows.get(modalInstance);
330336
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
331337
modalWindow.value.deferred.reject(reason);
332-
removeModalWindow(modalInstance);
333-
modalWindow.value.modalOpener.focus();
338+
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
334339
return true;
335340
}
336341
return !modalWindow;

src/modal/test/modal.spec.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ 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 () {
253+
it('should return to the element which had focus before the dialog was invoked', function () {
254254
var link = '<a href>Link</a>';
255255
var element = angular.element(link);
256256
angular.element(document.body).append(element);
@@ -272,6 +272,30 @@ describe('$modal', function () {
272272
element.remove();
273273
});
274274

275+
it('should return to document.body if element which had focus before the dialog was invoked is gone, or is missing focus function', function () {
276+
var link = '<a href>Link</a>';
277+
var element = angular.element(link);
278+
angular.element(document.body).append(element);
279+
element.focus();
280+
expect(document.activeElement.tagName).toBe('A');
281+
282+
var modal = open({template: '<div>Content</div>'});
283+
$timeout.flush();
284+
expect(document.activeElement.tagName).toBe('DIV');
285+
expect($document).toHaveModalsOpen(1);
286+
287+
// Fake undefined focus function, happening in IE in certain
288+
// iframe conditions. See issue 3639
289+
element[0].focus = undefined;
290+
triggerKeyDown($document, 27);
291+
$timeout.flush();
292+
$rootScope.$digest();
293+
294+
expect(document.activeElement.tagName).toBe('BODY');
295+
expect($document).toHaveModalsOpen(0);
296+
element.remove();
297+
});
298+
275299
it('should resolve returned promise on close', function () {
276300
var modal = open({template: '<div>Content</div>'});
277301
close(modal, 'closed ok');

0 commit comments

Comments
 (0)