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

Commit 6bad759

Browse files
Matt Lewiswesleycho
Matt Lewis
authored andcommitted
fix(dropdown): fix keyboard-nav
- Fix keyboard-nav for when not using append-to or append-to-body Fixes #6102 Closes #6154
1 parent 0023d1b commit 6bad759

File tree

2 files changed

+32
-37
lines changed

2 files changed

+32
-37
lines changed

src/dropdown/dropdown.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
2424
if (openScope === dropdownScope) {
2525
openScope = null;
2626
$document.off('click', closeDropdown);
27-
var dropdownMenu = dropdownScope.getDropdownElement();
28-
if (dropdownMenu) {
29-
dropdownMenu.off('keydown', this.keybindFilter);
30-
}
27+
$document.off('keydown', this.keybindFilter);
3128
}
3229
};
3330

@@ -60,11 +57,15 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
6057
};
6158

6259
this.keybindFilter = function(evt) {
60+
var dropdownElement = openScope.getDropdownElement();
61+
var toggleElement = openScope.getToggleElement();
62+
var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
63+
var toggleElementTargeted = toggleElement && toggleElement[0].contains(evt.target);
6364
if (evt.which === 27) {
6465
evt.stopPropagation();
6566
openScope.focusToggleElement();
6667
closeDropdown();
67-
} else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen) {
68+
} else if (openScope.isKeynavEnabled() && [38, 40].indexOf(evt.which) !== -1 && openScope.isOpen && (dropdownElementTargeted || toggleElementTargeted)) {
6869
evt.preventDefault();
6970
evt.stopPropagation();
7071
openScope.focusDropdownEntry(evt.which);
@@ -256,13 +257,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
256257
var newEl = dropdownElement;
257258
self.dropdownMenu.replaceWith(newEl);
258259
self.dropdownMenu = newEl;
259-
self.dropdownMenu.on('keydown', uibDropdownService.keybindFilter);
260+
$document.on('keydown', uibDropdownService.keybindFilter);
260261
});
261262
});
262263
} else {
263-
if (self.dropdownMenu) {
264-
self.dropdownMenu.on('keydown', uibDropdownService.keybindFilter);
265-
}
264+
$document.on('keydown', uibDropdownService.keybindFilter);
266265
}
267266

268267
scope.focusToggleElement();

src/dropdown/test/dropdown.spec.js

+24-28
Original file line numberDiff line numberDiff line change
@@ -550,70 +550,67 @@ describe('uib-dropdown', function() {
550550
function dropdown() {
551551
return $compile('<li uib-dropdown keyboard-nav><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
552552
}
553+
function getFocusedElement() {
554+
return angular.element(document.activeElement);
555+
}
553556
beforeEach(function() {
554557
element = dropdown();
555558
});
556559

557560
it('should focus first list element when down arrow pressed', function() {
558-
var dropdownMenu = element.find('[uib-dropdown-menu]');
559561
$document.find('body').append(element);
560562
clickDropdownToggle();
561-
triggerKeyDown(dropdownMenu, 40);
563+
triggerKeyDown(getFocusedElement(), 40);
562564

563565
expect(element).toHaveClass(dropdownConfig.openClass);
564566
var optionEl = element.find('ul').eq(0).find('a').eq(0);
565567
expect(optionEl).toHaveFocus();
566568
});
567569

568570
it('should not focus first list element when down arrow pressed if closed', function() {
569-
var dropdownMenu = element.find('[uib-dropdown-menu]');
570571
$document.find('body').append(element);
571-
triggerKeyDown(dropdownMenu, 40);
572+
triggerKeyDown(getFocusedElement(), 40);
572573

573574
expect(element).not.toHaveClass(dropdownConfig.openClass);
574575
var focusEl = element.find('ul').eq(0).find('a').eq(0);
575576
expect(focusEl).not.toHaveFocus();
576577
});
577578

578579
it('should focus second list element when down arrow pressed twice', function() {
579-
var dropdownMenu = element.find('[uib-dropdown-menu]');
580580
$document.find('body').append(element);
581581
clickDropdownToggle();
582-
triggerKeyDown(dropdownMenu, 40);
583-
triggerKeyDown(dropdownMenu, 40);
582+
triggerKeyDown(getFocusedElement(), 40);
583+
triggerKeyDown(getFocusedElement(), 40);
584584

585585
expect(element).toHaveClass(dropdownConfig.openClass);
586586
var focusEl = element.find('ul').eq(0).find('a').eq(1);
587587
expect(focusEl).toHaveFocus();
588588
});
589589

590590
it('should not focus first list element when up arrow pressed after dropdown toggled', function() {
591-
var dropdownMenu = element.find('[uib-dropdown-menu]');
592591
$document.find('body').append(element);
593592
clickDropdownToggle();
594593
expect(element).toHaveClass(dropdownConfig.openClass);
595594

596-
triggerKeyDown(dropdownMenu, 38);
595+
triggerKeyDown(getFocusedElement(), 38);
597596
var focusEl = element.find('ul').eq(0).find('a').eq(0);
598597
expect(focusEl).not.toHaveFocus();
599598
});
600599

601600
it('should focus last list element when up arrow pressed after dropdown toggled', function() {
602-
var dropdownMenu = element.find('[uib-dropdown-menu]');
603601
$document.find('body').append(element);
604602
clickDropdownToggle();
605-
triggerKeyDown(dropdownMenu, 38);
603+
triggerKeyDown(getFocusedElement(), 38);
606604

607605
expect(element).toHaveClass(dropdownConfig.openClass);
608606
var focusEl = element.find('ul').eq(0).find('a').eq(1);
609607
expect(focusEl).toHaveFocus();
610608
});
611609

612610
it('should not change focus when other keys are pressed', function() {
613-
var dropdownMenu = element.find('[uib-dropdown-menu]');
614611
$document.find('body').append(element);
615612
clickDropdownToggle();
616-
triggerKeyDown(dropdownMenu, 37);
613+
triggerKeyDown(getFocusedElement(), 37);
617614

618615
expect(element).toHaveClass(dropdownConfig.openClass);
619616
var focusEl = element.find('ul').eq(0).find('a');
@@ -622,25 +619,23 @@ describe('uib-dropdown', function() {
622619
});
623620

624621
it('should focus first list element when down arrow pressed 2x and up pressed 1x', function() {
625-
var dropdownMenu = element.find('[uib-dropdown-menu]');
626622
$document.find('body').append(element);
627623
clickDropdownToggle();
628-
triggerKeyDown(dropdownMenu, 40);
629-
triggerKeyDown(dropdownMenu, 40);
624+
triggerKeyDown(getFocusedElement(), 40);
625+
triggerKeyDown(getFocusedElement(), 40);
630626

631-
triggerKeyDown(dropdownMenu, 38);
627+
triggerKeyDown(getFocusedElement(), 38);
632628

633629
expect(element).toHaveClass(dropdownConfig.openClass);
634630
var focusEl = element.find('ul').eq(0).find('a').eq(0);
635631
expect(focusEl).toHaveFocus();
636632
});
637633

638634
it('should stay focused on final list element if down pressed at list end', function() {
639-
var dropdownMenu = element.find('[uib-dropdown-menu]');
640635
$document.find('body').append(element);
641636
clickDropdownToggle();
642-
triggerKeyDown(dropdownMenu, 40);
643-
triggerKeyDown(dropdownMenu, 40);
637+
triggerKeyDown(getFocusedElement(), 40);
638+
triggerKeyDown(getFocusedElement(), 40);
644639

645640
expect(element).toHaveClass(dropdownConfig.openClass);
646641
var focusEl = element.find('ul').eq(0).find('a').eq(1);
@@ -652,47 +647,48 @@ describe('uib-dropdown', function() {
652647

653648
it('should close if esc is pressed while focused', function() {
654649
element = dropdown('disabled');
655-
var dropdownMenu = element.find('[uib-dropdown-menu]');
656650
$document.find('body').append(element);
657651
clickDropdownToggle();
658652

659-
triggerKeyDown(dropdownMenu, 40);
653+
triggerKeyDown(getFocusedElement(), 40);
660654

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

665-
triggerKeyDown(dropdownMenu, 27);
659+
triggerKeyDown(getFocusedElement(), 27);
666660
expect(element).not.toHaveClass(dropdownConfig.openClass);
667661
});
668662

669663
describe('with dropdown-append-to-body', function() {
670664
function dropdown() {
671-
return $compile('<li uib-dropdown dropdown-append-to-body keyboard-nav><a href uib-dropdown-toggle></a><ul uib-dropdown-menu id="dropdown-menu"><li><a href>Hello On Body</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
665+
return $compile('<li uib-dropdown dropdown-append-to-body keyboard-nav><a href uib-dropdown-toggle>foo</a><ul uib-dropdown-menu id="dropdown-menu"><li><a href>Hello On Body</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
672666
}
673667

674668
beforeEach(function() {
675669
element = dropdown();
676670
});
677671

678672
it('should focus first list element when down arrow pressed', function() {
673+
$document.find('body').append(element);
679674
clickDropdownToggle();
680675

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

683-
triggerKeyDown(dropdownMenu, 40);
678+
triggerKeyDown(getFocusedElement(), 40);
684679

685680
expect(dropdownMenu.parent()).toHaveClass(dropdownConfig.appendToOpenClass);
686681
var focusEl = $document.find('ul').eq(0).find('a');
687682
expect(focusEl).toHaveFocus();
688683
});
689684

690685
it('should focus second list element when down arrow pressed twice', function() {
686+
$document.find('body').append(element);
691687
clickDropdownToggle();
692688
var dropdownMenu = $document.find('#dropdown-menu');
693-
triggerKeyDown(dropdownMenu, 40);
694-
triggerKeyDown(dropdownMenu, 40);
695-
triggerKeyDown(dropdownMenu, 40);
689+
triggerKeyDown(getFocusedElement(), 40);
690+
triggerKeyDown(getFocusedElement(), 40);
691+
triggerKeyDown(getFocusedElement(), 40);
696692

697693
expect(dropdownMenu.parent()).toHaveClass(dropdownConfig.appendToOpenClass);
698694
var elem1 = $document.find('ul');

0 commit comments

Comments
 (0)