Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

fix(dialog): only restore focus with keyboard interaction #9923

Merged
merged 1 commit into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/components/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ function MdDialogProvider($$interimElementProvider) {

/* @ngInject */
function dialogDefaultOptions($mdDialog, $mdAria, $mdUtil, $mdConstant, $animate, $document, $window, $rootElement,
$log, $injector, $mdTheming, $interpolate) {
$log, $injector, $mdTheming, $interpolate, $mdInteraction) {

return {
hasBackdrop: true,
Expand Down Expand Up @@ -798,7 +798,10 @@ function MdDialogProvider($$interimElementProvider) {
// Exposed cleanup function from the $mdCompiler.
options.cleanupElement();

if (!options.$destroy) options.origin.focus();
// Restores the focus to the origin element if the last interaction upon opening was a keyboard.
if (!options.$destroy && options.originInteraction === 'keyboard') {
options.origin.focus();
}
}
}

Expand Down Expand Up @@ -850,7 +853,8 @@ function MdDialogProvider($$interimElementProvider) {
options.openFrom = getBoundingClientRect(getDomElement(options.openFrom));

if ( options.targetEvent ) {
options.origin = getBoundingClientRect(options.targetEvent.target, options.origin);
options.origin = getBoundingClientRect(options.targetEvent.target, options.origin);
options.originInteraction = $mdInteraction.getLastInteractionType();
}


Expand Down
76 changes: 76 additions & 0 deletions src/components/dialog/dialog.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,82 @@ describe('$mdDialog', function() {
expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
}));

it('should restore the focus to the origin upon close', inject(function($mdDialog, $compile, $rootScope) {
var scope = $rootScope.$new();
var body = angular.element(document.body);
var parent = angular.element('<div>');
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);

// Append the button to the body, because otherwise the dialog is not able to determine
// the origin rectangle.
document.body.appendChild(button[0]);

scope.openDialog = function($event) {
$mdDialog.show({
parent: parent,
template: '<md-dialog>Test</md-dialog>',
targetEvent: $event,
scope: scope.$new()
});
};

// Emit a keyboard event to fake a keyboard interaction.
body.triggerHandler('keydown');
button.triggerHandler('click');

runAnimation();

expect(parent.find('md-dialog').length).toBe(1);
expect(document.activeElement).not.toBe(button[0]);


$mdDialog.hide();
runAnimation();

expect(parent.find('md-dialog').length).toBe(0);
expect(document.activeElement).toBe(button[0]);

button.remove();
}));

it('should not restore the focus without keyboard interaction', inject(function($mdDialog, $compile, $rootScope) {
var scope = $rootScope.$new();
var body = angular.element(document.body);
var parent = angular.element('<div>');
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);

// Append the button to the body, because otherwise the dialog is not able to determine
// the origin rectangle.
document.body.appendChild(button[0]);

scope.openDialog = function($event) {
$mdDialog.show({
parent: parent,
template: '<md-dialog>Test</md-dialog>',
targetEvent: $event,
scope: scope.$new()
});
};

// Emit a keyboard event to fake a mouse interaction.
body.triggerHandler('mousedown');
button.triggerHandler('click');

runAnimation();

expect(parent.find('md-dialog').length).toBe(1);
expect(document.activeElement).not.toBe(button[0]);


$mdDialog.hide();
runAnimation();

expect(parent.find('md-dialog').length).toBe(0);
expect(document.activeElement).not.toBe(button[0]);

button.remove();
}));

it('should focus the dialog element if no actions are set', inject(function($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);

Expand Down