diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index f9db3ed7ef..fadbee2f1e 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -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) { @@ -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); } }; @@ -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) { @@ -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) { @@ -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; } diff --git a/src/dropdown/test/dropdown.spec.js b/src/dropdown/test/dropdown.spec.js index cdef7512c2..825c42fbfe 100644 --- a/src/dropdown/test/dropdown.spec.js +++ b/src/dropdown/test/dropdown.spec.js @@ -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() { @@ -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); }); @@ -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(); }); @@ -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); @@ -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); @@ -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); @@ -556,7 +560,7 @@ 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(); }); @@ -564,7 +568,7 @@ describe('uib-dropdown', function() { 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); @@ -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'); @@ -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); @@ -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(); }); @@ -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); }); @@ -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'); @@ -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');