Skip to content
This repository has been archived by the owner on Nov 22, 2021. It is now read-only.

Commit

Permalink
fix(autocomplete): Stop preventing keys from being propagated
Browse files Browse the repository at this point in the history
Stop preventing keys from being propagated when a modifier (shift, ctrl,
alt or meta) is on.

Closes #384
  • Loading branch information
mbenford committed Jul 13, 2015
1 parent 731ef9e commit b0db763
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 154 deletions.
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = function(config) {
'test/lib/angular-mocks.js',
'test/helpers.js',
'test/matchers.js',
'src/constants.js',
'test/*.spec.js',
'src/init.js',
'src/*.js',
Expand Down
3 changes: 2 additions & 1 deletion src/auto-complete.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,10 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, $q, tags
})
.on('input-keydown', function(event) {
var key = event.keyCode,
isModifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey,
handled = false;

if (hotkeys.indexOf(key) === -1) {
if (isModifier || hotkeys.indexOf(key) === -1) {
return;
}

Expand Down
300 changes: 147 additions & 153 deletions test/auto-complete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ describe('autoComplete directive', function() {
$scope.$digest();
}

function sendKeyDown(keyCode) {
var event = jQuery.Event('keydown', { keyCode: keyCode });
function sendKeyDown(keyCode, properties) {
var event = jQuery.Event('keydown', angular.extend({ keyCode: keyCode }, properties || {}));
eventHandlers.call('input-keydown', event);

return event;
Expand Down Expand Up @@ -615,157 +615,6 @@ describe('autoComplete directive', function() {
});
});

describe('keys propagation handling', function() {
describe('hotkeys - suggestion box is visible', function() {
beforeEach(function() {
suggestionList.show();
});

it('prevents the down arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.down);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('prevents the up arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.up);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('prevents the enter keydown event from being propagated if there is a suggestion selected', function() {
// Arrange
suggestionList.selected = 'suggestion';

// Act
var event = sendKeyDown(KEYS.enter);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('does not prevent the enter keydown event from begin propagated if there is no suggestion selected', function() {
// Arrange
suggestionList.selected = null;

// Act
var event = sendKeyDown(KEYS.enter);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('prevents the tab keydown event from being propagated if there is a suggestion selected', function() {
// Arrange
suggestionList.selected = 'suggestion';

// Act
var event = sendKeyDown(KEYS.tab);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('does not prevent the tab keydown event from being propagated if there is no suggestion selected', function() {
// Arrange
suggestionList.selected = null;

// Act
var event = sendKeyDown(KEYS.tab);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('prevents the escape keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.escape);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});
});

describe('hotkeys - suggestion box is hidden', function() {
beforeEach(function() {
suggestionList.reset();
});

it('does not prevent the down arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.down);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('does not prevent the up arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.up);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('does not prevent the enter keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.enter);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('does not prevent the tab keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.tab);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('does not prevent the escape keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.escape);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});
});

describe('non-hotkeys', function() {
it('does not prevent non-hotkeys keystrokes from being propagated', function() {
// Act
var events = [sendKeyDown(65), sendKeyDown(66), sendKeyDown(67)];

// Assert
expect(events[0].isDefaultPrevented()).toBe(false);
expect(events[0].isPropagationStopped()).toBe(false);

expect(events[1].isDefaultPrevented()).toBe(false);
expect(events[1].isPropagationStopped()).toBe(false);

expect(events[2].isDefaultPrevented()).toBe(false);
expect(events[2].isPropagationStopped()).toBe(false);
});
});
});

describe('load-on-down-arrow option', function() {
it('initializes the option to false', function() {
// Arrange
Expand Down Expand Up @@ -1308,4 +1157,149 @@ describe('autoComplete directive', function() {
expect(scope.$getDisplayText).not.toBeUndefined();
});
});

describe('keys propagation handling', function() {
describe('hotkeys', function() {
var hotkeys = [KEYS.enter, KEYS.tab, KEYS.escape, KEYS.up, KEYS.down];

describe('suggestion box is visible', function() {
beforeEach(function() {
suggestionList.show();
});

it('prevents the down arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.down);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('prevents the up arrow keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.up);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('prevents the enter keydown event from being propagated if there is a suggestion selected', function() {
// Arrange
suggestionList.selected = 'suggestion';

// Act
var event = sendKeyDown(KEYS.enter);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('does not prevent the enter keydown event from begin propagated if there is no suggestion selected', function() {
// Arrange
suggestionList.selected = null;

// Act
var event = sendKeyDown(KEYS.enter);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('prevents the tab keydown event from being propagated if there is a suggestion selected', function() {
// Arrange
suggestionList.selected = 'suggestion';

// Act
var event = sendKeyDown(KEYS.tab);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});

it('does not prevent the tab keydown event from being propagated if there is no suggestion selected', function() {
// Arrange
suggestionList.selected = null;

// Act
var event = sendKeyDown(KEYS.tab);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});

it('prevents the escape keydown event from being propagated', function() {
// Act
var event = sendKeyDown(KEYS.escape);

// Assert
expect(event.isDefaultPrevented()).toBe(true);
expect(event.isPropagationStopped()).toBe(true);
});
});

describe('suggestion box is hidden', function() {
beforeEach(function() {
suggestionList.reset();
});

hotkeys.forEach(function(hotkey) {
it('does not prevent the keydown event from being propagated (keycode ' + hotkey + ')', function() {
// Act
var event = sendKeyDown(hotkey);

// Assert
expect(event.isDefaultPrevented()).toBe(false);
expect(event.isPropagationStopped()).toBe(false);
});
});
});

describe('modifier key is on', function() {
beforeEach(function() {
suggestionList.show();
});

hotkeys.forEach(function(hotkey) {
it('does not prevent a hotkey from being propagated when the shift key is down (hotkey ' + hotkey + ')', function() {
expect(sendKeyDown(hotkey, { shiftKey: true }).isDefaultPrevented()).toBe(false);
});

it('does not prevent a hotkey from being propagated when the alt key is down (hotkey ' + hotkey + ')', function() {
expect(sendKeyDown(hotkey, { altKey: true }).isDefaultPrevented()).toBe(false);
});

it('does not prevent a hotkey from being propagated when the ctrl key is down (hotkey ' + hotkey + ')', function() {
expect(sendKeyDown(hotkey, { ctrlKey: true }).isDefaultPrevented()).toBe(false);
});

it('does not prevent a hotkey from being propagated when the meta key is down (hotkey ' + hotkey + ')', function() {
expect(sendKeyDown(hotkey, { metaKey: true }).isDefaultPrevented()).toBe(false);
});
});
});
});

describe('non-hotkeys', function() {
it('does not prevent non-hotkeys keystrokes from being propagated', function() {
// Act
var events = [sendKeyDown(65), sendKeyDown(66), sendKeyDown(67)];

// Assert
expect(events[0].isDefaultPrevented()).toBe(false);
expect(events[0].isPropagationStopped()).toBe(false);

expect(events[1].isDefaultPrevented()).toBe(false);
expect(events[1].isPropagationStopped()).toBe(false);

expect(events[2].isDefaultPrevented()).toBe(false);
expect(events[2].isPropagationStopped()).toBe(false);
});
});
});
});

0 comments on commit b0db763

Please sign in to comment.