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

Commit c851204

Browse files
devversionkara
authored andcommitted
fix(dialog): only restore focus with keyboard interaction (#9923)
Fixes #7963.
1 parent a6f0de7 commit c851204

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

src/components/dialog/dialog.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ function MdDialogProvider($$interimElementProvider) {
657657

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

662662
return {
663663
hasBackdrop: true,
@@ -817,7 +817,10 @@ function MdDialogProvider($$interimElementProvider) {
817817
// Exposed cleanup function from the $mdCompiler.
818818
options.cleanupElement();
819819

820-
if (!options.$destroy) options.origin.focus();
820+
// Restores the focus to the origin element if the last interaction upon opening was a keyboard.
821+
if (!options.$destroy && options.originInteraction === 'keyboard') {
822+
options.origin.focus();
823+
}
821824
}
822825
}
823826

@@ -869,7 +872,8 @@ function MdDialogProvider($$interimElementProvider) {
869872
options.openFrom = getBoundingClientRect(getDomElement(options.openFrom));
870873

871874
if ( options.targetEvent ) {
872-
options.origin = getBoundingClientRect(options.targetEvent.target, options.origin);
875+
options.origin = getBoundingClientRect(options.targetEvent.target, options.origin);
876+
options.originInteraction = $mdInteraction.getLastInteractionType();
873877
}
874878

875879

src/components/dialog/dialog.spec.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,82 @@ describe('$mdDialog', function() {
11341134
expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
11351135
}));
11361136

1137+
it('should restore the focus to the origin upon close', inject(function($mdDialog, $compile, $rootScope) {
1138+
var scope = $rootScope.$new();
1139+
var body = angular.element(document.body);
1140+
var parent = angular.element('<div>');
1141+
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);
1142+
1143+
// Append the button to the body, because otherwise the dialog is not able to determine
1144+
// the origin rectangle.
1145+
document.body.appendChild(button[0]);
1146+
1147+
scope.openDialog = function($event) {
1148+
$mdDialog.show({
1149+
parent: parent,
1150+
template: '<md-dialog>Test</md-dialog>',
1151+
targetEvent: $event,
1152+
scope: scope.$new()
1153+
});
1154+
};
1155+
1156+
// Emit a keyboard event to fake a keyboard interaction.
1157+
body.triggerHandler('keydown');
1158+
button.triggerHandler('click');
1159+
1160+
runAnimation();
1161+
1162+
expect(parent.find('md-dialog').length).toBe(1);
1163+
expect(document.activeElement).not.toBe(button[0]);
1164+
1165+
1166+
$mdDialog.hide();
1167+
runAnimation();
1168+
1169+
expect(parent.find('md-dialog').length).toBe(0);
1170+
expect(document.activeElement).toBe(button[0]);
1171+
1172+
button.remove();
1173+
}));
1174+
1175+
it('should not restore the focus without keyboard interaction', inject(function($mdDialog, $compile, $rootScope) {
1176+
var scope = $rootScope.$new();
1177+
var body = angular.element(document.body);
1178+
var parent = angular.element('<div>');
1179+
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);
1180+
1181+
// Append the button to the body, because otherwise the dialog is not able to determine
1182+
// the origin rectangle.
1183+
document.body.appendChild(button[0]);
1184+
1185+
scope.openDialog = function($event) {
1186+
$mdDialog.show({
1187+
parent: parent,
1188+
template: '<md-dialog>Test</md-dialog>',
1189+
targetEvent: $event,
1190+
scope: scope.$new()
1191+
});
1192+
};
1193+
1194+
// Emit a keyboard event to fake a mouse interaction.
1195+
body.triggerHandler('mousedown');
1196+
button.triggerHandler('click');
1197+
1198+
runAnimation();
1199+
1200+
expect(parent.find('md-dialog').length).toBe(1);
1201+
expect(document.activeElement).not.toBe(button[0]);
1202+
1203+
1204+
$mdDialog.hide();
1205+
runAnimation();
1206+
1207+
expect(parent.find('md-dialog').length).toBe(0);
1208+
expect(document.activeElement).not.toBe(button[0]);
1209+
1210+
button.remove();
1211+
}));
1212+
11371213
it('should focus the dialog element if no actions are set', inject(function($mdDialog, $rootScope, $document) {
11381214
jasmine.mockElementFocus(this);
11391215

0 commit comments

Comments
 (0)