diff --git a/src/modal/modal.js b/src/modal/modal.js index aed5855945..f6342cc84a 100644 --- a/src/modal/modal.js +++ b/src/modal/modal.js @@ -266,6 +266,8 @@ angular.module('ui.bootstrap.modal', []) $modalStack.open = function (modalInstance, modal) { + var modalOpener = $document[0].activeElement; + openedWindows.add(modalInstance, { deferred: modal.deferred, renderDeferred: modal.renderDeferred, @@ -303,6 +305,7 @@ angular.module('ui.bootstrap.modal', []) var modalDomEl = $compile(angularDomEl)(modal.scope); openedWindows.top().value.modalDomEl = modalDomEl; + openedWindows.top().value.modalOpener = modalOpener; body.append(modalDomEl); body.addClass(OPENED_MODAL_CLASS); }; @@ -316,6 +319,7 @@ angular.module('ui.bootstrap.modal', []) if (modalWindow && broadcastClosing(modalWindow, result, true)) { modalWindow.value.deferred.resolve(result); removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); return true; } return !modalWindow; @@ -326,6 +330,7 @@ angular.module('ui.bootstrap.modal', []) if (modalWindow && broadcastClosing(modalWindow, reason, false)) { modalWindow.value.deferred.reject(reason); removeModalWindow(modalInstance); + modalWindow.value.modalOpener.focus(); return true; } return !modalWindow; diff --git a/src/modal/test/modal.spec.js b/src/modal/test/modal.spec.js index 253e5ef737..c1d5fe4c29 100644 --- a/src/modal/test/modal.spec.js +++ b/src/modal/test/modal.spec.js @@ -250,6 +250,28 @@ describe('$modal', function () { expect($document).toHaveModalsOpen(0); }); + it('should return to the element which had focus before the dialog is invoked', function () { + 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: '
Content
'}); + $timeout.flush(); + expect(document.activeElement.tagName).toBe('DIV'); + expect($document).toHaveModalsOpen(1); + + triggerKeyDown($document, 27); + $timeout.flush(); + $rootScope.$digest(); + + expect(document.activeElement.tagName).toBe('A'); + expect($document).toHaveModalsOpen(0); + + element.remove(); + }); + it('should resolve returned promise on close', function () { var modal = open({template: '
Content
'}); close(modal, 'closed ok'); @@ -695,6 +717,35 @@ describe('$modal', function () { dismiss(modal2); expect(body).not.toHaveClass('modal-open'); }); + + it('should return to the element which had focus before the dialog is invoked', function () { + var link = 'Link'; + var element = angular.element(link); + angular.element(document.body).append(element); + element.focus(); + expect(document.activeElement.tagName).toBe('A'); + + var modal1 = open({template: '
Modal1
'}); + $timeout.flush(); + document.getElementById('focus').focus(); + expect(document.activeElement.tagName).toBe('BUTTON'); + expect($document).toHaveModalsOpen(1); + + var modal2 = open({template: '
Modal2
'}); + $timeout.flush(); + expect(document.activeElement.tagName).toBe('DIV'); + expect($document).toHaveModalsOpen(2); + + dismiss(modal2); + expect(document.activeElement.tagName).toBe('BUTTON'); + expect($document).toHaveModalsOpen(1); + + dismiss(modal1); + expect(document.activeElement.tagName).toBe('A'); + expect($document).toHaveModalsOpen(0); + + element.remove(); + }); }); describe('modal.closing event', function() {