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

Commit 68200bb

Browse files
committed
fix(dropdown): stop esc keydown event
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.
1 parent 68ed7ab commit 68200bb

File tree

2 files changed

+33
-27
lines changed

2 files changed

+33
-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

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

2727
var triggerKeyDown = function (element, keyCode) {
2828
var e = $.Event('keydown');
29+
spyOn(e, 'stopPropagation');
30+
e.stopPropagation.and.callThrough();
2931
e.which = keyCode;
3032
element.trigger(e);
33+
return e;
3134
};
3235

3336
describe('basic', function() {
@@ -68,14 +71,15 @@ describe('uib-dropdown', function() {
6871
it('should close on escape key & focus toggle element', function() {
6972
$document.find('body').append(element);
7073
clickDropdownToggle();
71-
triggerKeyDown($document, 27);
74+
var event = triggerKeyDown(element, 27);
7275
expect(element).not.toHaveClass(dropdownConfig.openClass);
7376
expect(element.find('a')).toHaveFocus();
77+
expect(event.stopPropagation).toHaveBeenCalled();
7478
});
7579

7680
it('should not close on backspace key', function() {
7781
clickDropdownToggle();
78-
triggerKeyDown($document, 8);
82+
triggerKeyDown(element, 8);
7983
expect(element).toHaveClass(dropdownConfig.openClass);
8084
});
8185

@@ -470,7 +474,7 @@ describe('uib-dropdown', function() {
470474
element = dropdown('disabled');
471475
$document.find('body').append(element);
472476
clickDropdownToggle();
473-
triggerKeyDown($document, 27);
477+
triggerKeyDown(element, 27);
474478
expect(element).not.toHaveClass(dropdownConfig.openClass);
475479
expect(element.find('a')).toHaveFocus();
476480
});
@@ -524,7 +528,7 @@ describe('uib-dropdown', function() {
524528
it('should focus first list element when down arrow pressed', function() {
525529
$document.find('body').append(element);
526530
clickDropdownToggle();
527-
triggerKeyDown($document, 40);
531+
triggerKeyDown(element, 40);
528532

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

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

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

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

559-
triggerKeyDown($document, 38);
563+
triggerKeyDown(element, 38);
560564
var focusEl = element.find('ul').eq(0).find('a').eq(0);
561565
expect(focusEl).not.toHaveFocus();
562566
});
563567

564568
it('should focus last list element when up arrow pressed after dropdown toggled', function() {
565569
$document.find('body').append(element);
566570
clickDropdownToggle();
567-
triggerKeyDown($document, 38);
571+
triggerKeyDown(element, 38);
568572

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

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

591-
triggerKeyDown($document, 38);
595+
triggerKeyDown(element, 38);
592596

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

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

608-
triggerKeyDown($document, 40);
612+
triggerKeyDown(element, 40);
609613
expect(focusEl).toHaveFocus();
610614
});
611615

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

617-
triggerKeyDown($document, 40);
621+
triggerKeyDown(element, 40);
618622

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

623-
triggerKeyDown($document, 27);
627+
triggerKeyDown(element, 27);
624628
expect(element).not.toHaveClass(dropdownConfig.openClass);
625629
});
626630

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

639-
triggerKeyDown($document, 40);
643+
triggerKeyDown(element, 40);
640644

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

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

648652
it('should focus second list element when down arrow pressed twice', function() {
649653
clickDropdownToggle();
650-
triggerKeyDown($document, 40);
651-
triggerKeyDown($document, 40);
654+
triggerKeyDown(element, 40);
655+
triggerKeyDown(element, 40);
656+
triggerKeyDown(element, 40);
652657

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

0 commit comments

Comments
 (0)