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

Commit 726ccc3

Browse files
Alex Knowleswesleycho
Alex Knowles
authored andcommitted
fix(modal): retain focus if child has focus
- If a child element in the modal has focus before animation completes, do not refocus Closes #4904 Fixes #4903
1 parent 6d5b1d9 commit 726ccc3

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

src/modal/modal.js

+19-13
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
105105
}
106106
}])
107107

108-
.directive('uibModalWindow', ['$uibModalStack', '$q', '$animate', '$animateCss',
109-
function($modalStack, $q, $animate, $animateCss) {
108+
.directive('uibModalWindow', ['$uibModalStack', '$q', '$animate', '$animateCss', '$document',
109+
function($modalStack, $q, $animate, $animateCss, $document) {
110110
return {
111111
scope: {
112112
index: '@'
@@ -172,19 +172,25 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])
172172

173173

174174
$q.when(animationPromise).then(function() {
175-
var inputWithAutofocus = element[0].querySelector('[autofocus]');
176175
/**
177-
* Auto-focusing of a freshly-opened modal element causes any child elements
178-
* with the autofocus attribute to lose focus. This is an issue on touch
179-
* based devices which will show and then hide the onscreen keyboard.
180-
* Attempts to refocus the autofocus element via JavaScript will not reopen
181-
* the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
182-
* the modal element if the modal does not contain an autofocus element.
176+
* If something within the freshly-opened modal already has focus (perhaps via a
177+
* directive that causes focus). then no need to try and focus anything.
183178
*/
184-
if (inputWithAutofocus) {
185-
inputWithAutofocus.focus();
186-
} else {
187-
element[0].focus();
179+
if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
180+
var inputWithAutofocus = element[0].querySelector('[autofocus]');
181+
/**
182+
* Auto-focusing of a freshly-opened modal element causes any child elements
183+
* with the autofocus attribute to lose focus. This is an issue on touch
184+
* based devices which will show and then hide the onscreen keyboard.
185+
* Attempts to refocus the autofocus element via JavaScript will not reopen
186+
* the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
187+
* the modal element if the modal does not contain an autofocus element.
188+
*/
189+
if (inputWithAutofocus) {
190+
inputWithAutofocus.focus();
191+
} else {
192+
element[0].focus();
193+
}
188194
}
189195
});
190196

src/modal/test/modal.spec.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ describe('$uibModal', function () {
2222
scope.text = ctrl.text;
2323
}
2424
};
25+
}).directive('focusMe', function() {
26+
return {
27+
link: function(scope, elem, attrs) {
28+
elem.focus();
29+
}
30+
};
2531
});
2632
}));
2733

@@ -413,6 +419,24 @@ describe('$uibModal', function () {
413419
openAndCloseModalWithAutofocusElement();
414420
});
415421

422+
it('should not focus on the element that has autofocus attribute when the modal is opened and something in the modal already has focus and the animations have finished', function() {
423+
function openAndCloseModalWithAutofocusElement() {
424+
425+
var modal = open({template: '<div><input type="text" id="auto-focus-element" autofocus><input type="text" id="pre-focus-element" focus-me></div>'});
426+
$animate.flush();
427+
$rootScope.$digest();
428+
expect(angular.element('#auto-focus-element')).not.toHaveFocus();
429+
expect(angular.element('#pre-focus-element')).toHaveFocus();
430+
431+
close(modal, 'closed ok');
432+
433+
expect(modal.result).toBeResolvedWith('closed ok');
434+
}
435+
436+
openAndCloseModalWithAutofocusElement();
437+
openAndCloseModalWithAutofocusElement();
438+
});
439+
416440
it('should wait until the in animation is finished before attempting to focus the modal or autofocus element', function() {
417441
function openAndCloseModalWithAutofocusElement() {
418442
var modal = open({template: '<div><input type="text" id="auto-focus-element" autofocus></div>'});
@@ -846,7 +870,7 @@ describe('$uibModal', function () {
846870
expect($document.find('.modal-backdrop')).not.toHaveClass('fade');
847871
});
848872
});
849-
873+
850874
describe('appendTo', function() {
851875
it('should be added to body by default', function() {
852876
var modal = open({template: '<div>Content</div>'});

0 commit comments

Comments
 (0)