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

Commit

Permalink
fix(dropdown): stop esc keydown event
Browse files Browse the repository at this point in the history
Fixes #5778
Closes #5787

BREAKING CHANGE: Stops propagation of keydown event when escape key is pressed. Removes keydown event from the document and moves it to the dropdown element.
  • Loading branch information
deeg committed Apr 13, 2016
1 parent 68ed7ab commit 68200bb
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 27 deletions.
13 changes: 7 additions & 6 deletions src/dropdown/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
.service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) {
var openScope = null;

this.open = function(dropdownScope) {
this.open = function(dropdownScope, element) {
if (!openScope) {
$document.on('click', closeDropdown);
$document.on('keydown', keybindFilter);
element.on('keydown', keybindFilter);
}

if (openScope && openScope !== dropdownScope) {
Expand All @@ -21,11 +21,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
openScope = dropdownScope;
};

this.close = function(dropdownScope) {
this.close = function(dropdownScope, element) {
if (openScope === dropdownScope) {
openScope = null;
$document.off('click', closeDropdown);
$document.off('keydown', keybindFilter);
element.off('keydown', keybindFilter);
}
};

Expand Down Expand Up @@ -58,6 +58,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])

var keybindFilter = function(evt) {
if (evt.which === 27) {
evt.stopPropagation();
openScope.focusToggleElement();
closeDropdown();
} else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen) {
Expand Down Expand Up @@ -249,7 +250,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
}

scope.focusToggleElement();
uibDropdownService.open(scope);
uibDropdownService.open(scope, $element);
} else {
if (self.dropdownMenuTemplateUrl) {
if (templateScope) {
Expand All @@ -260,7 +261,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
self.dropdownMenu = newEl;
}

uibDropdownService.close(scope);
uibDropdownService.close(scope, $element);
self.selectedOption = null;
}

Expand Down
47 changes: 26 additions & 21 deletions src/dropdown/test/dropdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ describe('uib-dropdown', function() {

var triggerKeyDown = function (element, keyCode) {
var e = $.Event('keydown');
spyOn(e, 'stopPropagation');
e.stopPropagation.and.callThrough();
e.which = keyCode;
element.trigger(e);
return e;
};

describe('basic', function() {
Expand Down Expand Up @@ -68,14 +71,15 @@ describe('uib-dropdown', function() {
it('should close on escape key & focus toggle element', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 27);
var event = triggerKeyDown(element, 27);
expect(element).not.toHaveClass(dropdownConfig.openClass);
expect(element.find('a')).toHaveFocus();
expect(event.stopPropagation).toHaveBeenCalled();
});

it('should not close on backspace key', function() {
clickDropdownToggle();
triggerKeyDown($document, 8);
triggerKeyDown(element, 8);
expect(element).toHaveClass(dropdownConfig.openClass);
});

Expand Down Expand Up @@ -470,7 +474,7 @@ describe('uib-dropdown', function() {
element = dropdown('disabled');
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 27);
triggerKeyDown(element, 27);
expect(element).not.toHaveClass(dropdownConfig.openClass);
expect(element.find('a')).toHaveFocus();
});
Expand Down Expand Up @@ -524,7 +528,7 @@ describe('uib-dropdown', function() {
it('should focus first list element when down arrow pressed', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);

expect(element).toHaveClass(dropdownConfig.openClass);
var optionEl = element.find('ul').eq(0).find('a').eq(0);
Expand All @@ -533,7 +537,7 @@ describe('uib-dropdown', function() {

it('should not focus first list element when down arrow pressed if closed', function() {
$document.find('body').append(element);
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);

expect(element).not.toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(0);
Expand All @@ -543,8 +547,8 @@ describe('uib-dropdown', function() {
it('should focus second list element when down arrow pressed twice', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 40);
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(1);
Expand All @@ -556,15 +560,15 @@ describe('uib-dropdown', function() {
clickDropdownToggle();
expect(element).toHaveClass(dropdownConfig.openClass);

triggerKeyDown($document, 38);
triggerKeyDown(element, 38);
var focusEl = element.find('ul').eq(0).find('a').eq(0);
expect(focusEl).not.toHaveFocus();
});

it('should focus last list element when up arrow pressed after dropdown toggled', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 38);
triggerKeyDown(element, 38);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(1);
Expand All @@ -574,7 +578,7 @@ describe('uib-dropdown', function() {
it('should not change focus when other keys are pressed', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 37);
triggerKeyDown(element, 37);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a');
Expand All @@ -585,10 +589,10 @@ describe('uib-dropdown', function() {
it('should focus first list element when down arrow pressed 2x and up pressed 1x', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 40);
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);

triggerKeyDown($document, 38);
triggerKeyDown(element, 38);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(0);
Expand All @@ -598,14 +602,14 @@ describe('uib-dropdown', function() {
it('should stay focused on final list element if down pressed at list end', function() {
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown($document, 40);
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(1);
expect(focusEl).toHaveFocus();

triggerKeyDown($document, 40);
triggerKeyDown(element, 40);
expect(focusEl).toHaveFocus();
});

Expand All @@ -614,13 +618,13 @@ describe('uib-dropdown', function() {
$document.find('body').append(element);
clickDropdownToggle();

triggerKeyDown($document, 40);
triggerKeyDown(element, 40);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(0);
expect(focusEl).toHaveFocus();

triggerKeyDown($document, 27);
triggerKeyDown(element, 27);
expect(element).not.toHaveClass(dropdownConfig.openClass);
});

Expand All @@ -636,7 +640,7 @@ describe('uib-dropdown', function() {
it('should focus first list element when down arrow pressed', function() {
clickDropdownToggle();

triggerKeyDown($document, 40);
triggerKeyDown(element, 40);

var dropdownMenu = $document.find('#dropdown-menu');

Expand All @@ -647,8 +651,9 @@ describe('uib-dropdown', function() {

it('should focus second list element when down arrow pressed twice', function() {
clickDropdownToggle();
triggerKeyDown($document, 40);
triggerKeyDown($document, 40);
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);

var dropdownMenu = $document.find('#dropdown-menu');

Expand Down

0 comments on commit 68200bb

Please sign in to comment.