diff --git a/src/modal/modal.js b/src/modal/modal.js
index b1f339dd84..4843490fad 100644
--- a/src/modal/modal.js
+++ b/src/modal/modal.js
@@ -203,13 +203,15 @@ angular.module('ui.bootstrap.modal', [])
});
modalRenderDeferObj.promise.then(function() {
+ var animationPromise = null;
+
if (attrs.modalInClass) {
if ($animateCss) {
- $animateCss(element, {
+ animationPromise = $animateCss(element, {
addClass: attrs.modalInClass
}).start();
} else {
- $animate.addClass(element, attrs.modalInClass);
+ animationPromise = $animate.addClass(element, attrs.modalInClass);
}
scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {
@@ -224,20 +226,23 @@ angular.module('ui.bootstrap.modal', [])
});
}
- var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]');
- /**
- * Auto-focusing of a freshly-opened modal element causes any child elements
- * with the autofocus attribute to lose focus. This is an issue on touch
- * based devices which will show and then hide the onscreen keyboard.
- * Attempts to refocus the autofocus element via JavaScript will not reopen
- * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
- * the modal element if the modal does not contain an autofocus element.
- */
- if (inputsWithAutofocus.length) {
- inputsWithAutofocus[0].focus();
- } else {
- element[0].focus();
- }
+
+ $q.when(animationPromise).then(function() {
+ var inputsWithAutofocus = element[0].querySelectorAll('[autofocus]');
+ /**
+ * Auto-focusing of a freshly-opened modal element causes any child elements
+ * with the autofocus attribute to lose focus. This is an issue on touch
+ * based devices which will show and then hide the onscreen keyboard.
+ * Attempts to refocus the autofocus element via JavaScript will not reopen
+ * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
+ * the modal element if the modal does not contain an autofocus element.
+ */
+ if (inputsWithAutofocus.length) {
+ inputsWithAutofocus[0].focus();
+ } else {
+ element[0].focus();
+ }
+ });
// Notify {@link $modalStack} that modal is rendered.
var modal = $modalStack.getTop();
diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js
index bfe78eada0..66ae1a91fe 100644
--- a/src/modal/test/modal.spec.js
+++ b/src/modal/test/modal.spec.js
@@ -292,6 +292,8 @@ describe('$modal', function () {
expect(document.activeElement.tagName).toBe('A');
var modal = open({template: '
'});
+ $animate.flush();
+ $rootScope.$digest();
expect(document.activeElement.tagName).toBe('DIV');
expect($document).toHaveModalsOpen(1);
@@ -377,10 +381,11 @@ describe('$modal', function () {
expect(modal.opened).toBeRejectedWith('ko');
});
- it('should focus on the element that has autofocus attribute when the modal is open/reopen', function() {
+ it('should focus on the element that has autofocus attribute when the modal is open/reopen and the animations have finished', function() {
function openAndCloseModalWithAutofocusElement() {
var modal = open({template: ''});
-
+ $animate.flush();
+ $rootScope.$digest();
expect(angular.element('#auto-focus-element')).toHaveFocus();
close(modal, 'closed ok');
@@ -392,6 +397,45 @@ describe('$modal', function () {
openAndCloseModalWithAutofocusElement();
});
+ it('should wait until the in animation is finished before attempting to focus the modal or autofocus element', function() {
+ function openAndCloseModalWithAutofocusElement() {
+ var modal = open({template: ''});
+ expect(angular.element('#auto-focus-element')).not.toHaveFocus();
+
+ $animate.flush();
+ $rootScope.$digest();
+
+ expect(angular.element('#auto-focus-element')).toHaveFocus();
+
+ close(modal, 'closed ok');
+
+ expect(modal.result).toBeResolvedWith('closed ok');
+ }
+
+ function openAndCloseModalWithOutAutofocusElement() {
+ var link = 'Link';
+ var element = angular.element(link);
+ angular.element(document.body).append(element);
+ element.focus();
+ expect(document.activeElement.tagName).toBe('A');
+
+ var modal = open({template: ''});
+ expect(document.activeElement.tagName).toBe('A');
+
+ $animate.flush();
+ $rootScope.$digest();
+
+ expect(document.activeElement.tagName).toBe('DIV');
+
+ close(modal, 'closed ok');
+
+ expect(modal.result).toBeResolvedWith('closed ok');
+ }
+
+ openAndCloseModalWithAutofocusElement();
+ openAndCloseModalWithOutAutofocusElement();
+ });
+
it('should change focus to first element when tab key was pressed', function() {
var initialPage = angular.element('Outland link');
angular.element(document.body).append(initialPage);
@@ -918,11 +962,15 @@ describe('$modal', function () {
expect(document.activeElement.tagName).toBe('A');
var modal1 = open({template: '