Skip to content

Commit 79eea88

Browse files
committed
fix(dropdown): stop esc keydown event
Fixes angular-ui#5778 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.
1 parent bba3f27 commit 79eea88

File tree

2 files changed

+32
-27
lines changed

2 files changed

+32
-27
lines changed

src/dropdown/dropdown.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
88
.service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) {
99
var openScope = null;
1010

11-
this.open = function(dropdownScope) {
11+
this.open = function(dropdownScope, element) {
1212
if (!openScope) {
1313
$document.on('click', closeDropdown);
14-
$document.on('keydown', keybindFilter);
14+
element.on('keydown', keybindFilter);
1515
}
1616

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

24-
this.close = function(dropdownScope) {
24+
this.close = function(dropdownScope, element) {
2525
if (openScope === dropdownScope) {
2626
openScope = null;
2727
$document.off('click', closeDropdown);
28-
$document.off('keydown', keybindFilter);
28+
element.off('keydown', keybindFilter);
2929
}
3030
};
3131

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

5959
var keybindFilter = function(evt) {
6060
if (evt.which === 27) {
61+
evt.stopPropagation();
6162
openScope.focusToggleElement();
6263
closeDropdown();
6364
} else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen) {
@@ -249,7 +250,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
249250
}
250251

251252
scope.focusToggleElement();
252-
uibDropdownService.open(scope);
253+
uibDropdownService.open(scope, $element);
253254
} else {
254255
if (self.dropdownMenuTemplateUrl) {
255256
if (templateScope) {
@@ -260,7 +261,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
260261
self.dropdownMenu = newEl;
261262
}
262263

263-
uibDropdownService.close(scope);
264+
uibDropdownService.close(scope, $element);
264265
self.selectedOption = null;
265266
}
266267

src/dropdown/test/dropdown.spec.js

+25-21
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ describe('uib-dropdown', function() {
2626

2727
var triggerKeyDown = function (element, keyCode) {
2828
var e = $.Event('keydown');
29+
spyOn(e, "stopPropagation");
2930
e.which = keyCode;
3031
element.trigger(e);
32+
return e;
3133
};
3234

3335
describe('basic', function() {
@@ -68,14 +70,15 @@ describe('uib-dropdown', function() {
6870
it('should close on escape key & focus toggle element', function() {
6971
$document.find('body').append(element);
7072
clickDropdownToggle();
71-
triggerKeyDown($document, 27);
73+
var event = triggerKeyDown(element, 27);
7274
expect(element).not.toHaveClass(dropdownConfig.openClass);
7375
expect(element.find('a')).toHaveFocus();
76+
expect(event.stopPropagation).toHaveBeenCalled();
7477
});
7578

7679
it('should not close on backspace key', function() {
7780
clickDropdownToggle();
78-
triggerKeyDown($document, 8);
81+
triggerKeyDown(element, 8);
7982
expect(element).toHaveClass(dropdownConfig.openClass);
8083
});
8184

@@ -470,7 +473,7 @@ describe('uib-dropdown', function() {
470473
element = dropdown('disabled');
471474
$document.find('body').append(element);
472475
clickDropdownToggle();
473-
triggerKeyDown($document, 27);
476+
triggerKeyDown(element, 27);
474477
expect(element).not.toHaveClass(dropdownConfig.openClass);
475478
expect(element.find('a')).toHaveFocus();
476479
});
@@ -524,7 +527,7 @@ describe('uib-dropdown', function() {
524527
it('should focus first list element when down arrow pressed', function() {
525528
$document.find('body').append(element);
526529
clickDropdownToggle();
527-
triggerKeyDown($document, 40);
530+
triggerKeyDown(element, 40);
528531

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

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

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

549552
expect(element).toHaveClass(dropdownConfig.openClass);
550553
var focusEl = element.find('ul').eq(0).find('a').eq(1);
@@ -556,15 +559,15 @@ describe('uib-dropdown', function() {
556559
clickDropdownToggle();
557560
expect(element).toHaveClass(dropdownConfig.openClass);
558561

559-
triggerKeyDown($document, 38);
562+
triggerKeyDown(element, 38);
560563
var focusEl = element.find('ul').eq(0).find('a').eq(0);
561564
expect(focusEl).not.toHaveFocus();
562565
});
563566

564567
it('should focus last list element when up arrow pressed after dropdown toggled', function() {
565568
$document.find('body').append(element);
566569
clickDropdownToggle();
567-
triggerKeyDown($document, 38);
570+
triggerKeyDown(element, 38);
568571

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

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

591-
triggerKeyDown($document, 38);
594+
triggerKeyDown(element, 38);
592595

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

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

608-
triggerKeyDown($document, 40);
611+
triggerKeyDown(element, 40);
609612
expect(focusEl).toHaveFocus();
610613
});
611614

@@ -614,13 +617,13 @@ describe('uib-dropdown', function() {
614617
$document.find('body').append(element);
615618
clickDropdownToggle();
616619

617-
triggerKeyDown($document, 40);
620+
triggerKeyDown(element, 40);
618621

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

623-
triggerKeyDown($document, 27);
626+
triggerKeyDown(element, 27);
624627
expect(element).not.toHaveClass(dropdownConfig.openClass);
625628
});
626629

@@ -636,7 +639,7 @@ describe('uib-dropdown', function() {
636639
it('should focus first list element when down arrow pressed', function() {
637640
clickDropdownToggle();
638641

639-
triggerKeyDown($document, 40);
642+
triggerKeyDown(element, 40);
640643

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

@@ -647,8 +650,9 @@ describe('uib-dropdown', function() {
647650

648651
it('should focus second list element when down arrow pressed twice', function() {
649652
clickDropdownToggle();
650-
triggerKeyDown($document, 40);
651-
triggerKeyDown($document, 40);
653+
triggerKeyDown(element, 40);
654+
triggerKeyDown(element, 40);
655+
triggerKeyDown(element, 40);
652656

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

0 commit comments

Comments
 (0)