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

fix(dropdown): bind event listener on dropdown menu #5982

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/dropdown/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
this.open = function(dropdownScope, element) {
if (!openScope) {
$document.on('click', closeDropdown);
element.on('keydown', keybindFilter);
}

if (openScope && openScope !== dropdownScope) {
Expand All @@ -25,7 +24,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
if (openScope === dropdownScope) {
openScope = null;
$document.off('click', closeDropdown);
element.off('keydown', keybindFilter);
dropdownScope.getDropdownElement().off('keydown', this.keybindFilter);
}
};

Expand Down Expand Up @@ -57,7 +56,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
}
};

var keybindFilter = function(evt) {
this.keybindFilter = function(evt) {
if (evt.which === 27) {
evt.stopPropagation();
openScope.focusToggleElement();
Expand Down Expand Up @@ -248,13 +247,17 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
var newEl = dropdownElement;
self.dropdownMenu.replaceWith(newEl);
self.dropdownMenu = newEl;
self.dropdownMenu.on('keydown', uibDropdownService.keybindFilter);
});
});
} else {
scope.getDropdownElement().on('keydown', uibDropdownService.keybindFilter);
}

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

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

Expand Down
78 changes: 44 additions & 34 deletions src/dropdown/test/dropdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('uib-dropdown', function() {

describe('basic', function() {
function dropdown() {
return $compile('<li uib-dropdown><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li></ul></li>')($rootScope);
return $compile('<li uib-dropdown><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li></ul></li>')($rootScope);
}

beforeEach(function() {
Expand Down Expand Up @@ -69,9 +69,10 @@ describe('uib-dropdown', function() {
});

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

it('should not toggle if the element has `disabled` class', function() {
var elm = $compile('<li uib-dropdown><a class="disabled" uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
var elm = $compile('<li uib-dropdown><a class="disabled" uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
clickDropdownToggle( elm );
expect(elm).not.toHaveClass(dropdownConfig.openClass);
});
Expand All @@ -121,7 +122,7 @@ describe('uib-dropdown', function() {

it('should not toggle if the element has `ng-disabled` as true', function() {
$rootScope.isdisabled = true;
var elm = $compile('<li uib-dropdown><div ng-disabled="isdisabled" uib-dropdown-toggle></div><ul><li>Hello</li></ul></li>')($rootScope);
var elm = $compile('<li uib-dropdown><div ng-disabled="isdisabled" uib-dropdown-toggle></div><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
elm.find('div').click();
expect(elm).not.toHaveClass(dropdownConfig.openClass);
Expand All @@ -134,7 +135,7 @@ describe('uib-dropdown', function() {

it('should unbind events on scope destroy', function() {
var $scope = $rootScope.$new();
var elm = $compile('<li uib-dropdown><button ng-disabled="isdisabled" uib-dropdown-toggle></button><ul><li>Hello</li></ul></li>')($scope);
var elm = $compile('<li uib-dropdown><button ng-disabled="isdisabled" uib-dropdown-toggle></button><ul uib-dropdown-menu><li>Hello</li></ul></li>')($scope);
$scope.$digest();

var buttonEl = elm.find('button');
Expand Down Expand Up @@ -306,7 +307,7 @@ describe('uib-dropdown', function() {
describe('with uib-dropdown-toggle', function() {
beforeEach(function() {
$rootScope.isopen = true;
element = $compile('<li uib-dropdown is-open="isopen"><a href uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown is-open="isopen"><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
});

Expand Down Expand Up @@ -340,7 +341,7 @@ describe('uib-dropdown', function() {
describe('without uib-dropdown-toggle', function() {
beforeEach(function() {
$rootScope.isopen = true;
element = $compile('<li uib-dropdown is-open="isopen"><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown is-open="isopen"><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
});

Expand All @@ -361,7 +362,7 @@ describe('uib-dropdown', function() {
beforeEach(function() {
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
$rootScope.isopen = false;
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
});

Expand All @@ -388,7 +389,7 @@ describe('uib-dropdown', function() {
beforeEach(function() {
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
$rootScope.isopen = true;
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
});

Expand Down Expand Up @@ -416,7 +417,7 @@ describe('uib-dropdown', function() {
describe('without is-open', function() {
beforeEach(function() {
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();
});

Expand Down Expand Up @@ -444,7 +445,7 @@ describe('uib-dropdown', function() {
function dropdown(autoClose) {
return $compile('<li uib-dropdown ' +
(autoClose === undefined ? '' : 'auto-close="' + autoClose + '"') +
'><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li></ul></li>')($rootScope);
'><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li></ul></li>')($rootScope);
}

describe('always', function() {
Expand Down Expand Up @@ -476,7 +477,7 @@ describe('uib-dropdown', function() {

it('control with is-open', function() {
$rootScope.isopen = true;
element = $compile('<li uib-dropdown is-open="isopen" auto-close="disabled"><a href uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
element = $compile('<li uib-dropdown is-open="isopen" auto-close="disabled"><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
$rootScope.$digest();

expect(element).toHaveClass(dropdownConfig.openClass);
Expand All @@ -499,9 +500,10 @@ describe('uib-dropdown', function() {

it('should close anyway if esc is pressed', function() {
element = dropdown('disabled');
var dropdownMenu = element.find('[uib-dropdown-menu]');
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown(element, 27);
triggerKeyDown(dropdownMenu, 27);
expect(element).not.toHaveClass(dropdownConfig.openClass);
expect(element.find('a')).toHaveFocus();
});
Expand Down Expand Up @@ -546,66 +548,72 @@ describe('uib-dropdown', function() {

describe('using keyboard-nav', function() {
function dropdown() {
return $compile('<li uib-dropdown keyboard-nav><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
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);
}
beforeEach(function() {
element = dropdown();
});

it('should focus first list element when down arrow pressed', function() {
var dropdownMenu = element.find('[uib-dropdown-menu]');
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown(element, 40);
triggerKeyDown(dropdownMenu, 40);

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

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

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

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

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

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

triggerKeyDown(element, 38);
triggerKeyDown(dropdownMenu, 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() {
var dropdownMenu = element.find('[uib-dropdown-menu]');
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown(element, 38);
triggerKeyDown(dropdownMenu, 38);

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

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

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a');
Expand All @@ -614,23 +622,25 @@ describe('uib-dropdown', function() {
});

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

triggerKeyDown(element, 38);
triggerKeyDown(dropdownMenu, 38);

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

it('should stay focused on final list element if down pressed at list end', function() {
var dropdownMenu = element.find('[uib-dropdown-menu]');
$document.find('body').append(element);
clickDropdownToggle();
triggerKeyDown(element, 40);
triggerKeyDown(element, 40);
triggerKeyDown(dropdownMenu, 40);
triggerKeyDown(dropdownMenu, 40);

expect(element).toHaveClass(dropdownConfig.openClass);
var focusEl = element.find('ul').eq(0).find('a').eq(1);
Expand All @@ -642,16 +652,17 @@ describe('uib-dropdown', function() {

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

triggerKeyDown(element, 40);
triggerKeyDown(dropdownMenu, 40);

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

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

Expand All @@ -667,22 +678,21 @@ describe('uib-dropdown', function() {
it('should focus first list element when down arrow pressed', function() {
clickDropdownToggle();

triggerKeyDown(element, 40);

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

triggerKeyDown(dropdownMenu, 40);

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

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

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

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