diff --git a/build/ng-tags-input.js b/build/ng-tags-input.js index b03e0da7..c0cb2ed4 100644 --- a/build/ng-tags-input.js +++ b/build/ng-tags-input.js @@ -189,8 +189,6 @@ tagsInput.directive('tagsInput', ["$timeout","$document","tagsInputConfig", func input .on('keydown', function(e) { - var key; - // This hack is needed because jqLite doesn't implement stopImmediatePropagation properly. // I've sent a PR to Angular addressing this issue and hopefully it'll be fixed soon. // https://github.com/angular/angular.js/pull/4833 @@ -198,12 +196,13 @@ tagsInput.directive('tagsInput', ["$timeout","$document","tagsInputConfig", func return; } - if (hotkeys.indexOf(e.keyCode) === -1) { + var key = e.keyCode, + isModifier = e.shiftKey || e.altKey || e.ctrlKey || e.metaKey; + + if (isModifier || hotkeys.indexOf(key) === -1) { return; } - key = e.keyCode; - if (key === KEYS.enter && scope.options.addOnEnter || key === KEYS.comma && scope.options.addOnComma || key === KEYS.space && scope.options.addOnSpace) { diff --git a/build/ng-tags-input.min.zip b/build/ng-tags-input.min.zip index 027ea93c..f8b5c04a 100644 Binary files a/build/ng-tags-input.min.zip and b/build/ng-tags-input.min.zip differ diff --git a/build/ng-tags-input.zip b/build/ng-tags-input.zip index d75aadbc..25fb0525 100644 Binary files a/build/ng-tags-input.zip and b/build/ng-tags-input.zip differ diff --git a/src/tags-input.js b/src/tags-input.js index e34242ca..a0bc904e 100644 --- a/src/tags-input.js +++ b/src/tags-input.js @@ -177,8 +177,6 @@ tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig) input .on('keydown', function(e) { - var key; - // This hack is needed because jqLite doesn't implement stopImmediatePropagation properly. // I've sent a PR to Angular addressing this issue and hopefully it'll be fixed soon. // https://github.com/angular/angular.js/pull/4833 @@ -186,12 +184,13 @@ tagsInput.directive('tagsInput', function($timeout, $document, tagsInputConfig) return; } - if (hotkeys.indexOf(e.keyCode) === -1) { + var key = e.keyCode, + isModifier = e.shiftKey || e.altKey || e.ctrlKey || e.metaKey; + + if (isModifier || hotkeys.indexOf(key) === -1) { return; } - key = e.keyCode; - if (key === KEYS.enter && scope.options.addOnEnter || key === KEYS.comma && scope.options.addOnComma || key === KEYS.space && scope.options.addOnSpace) { diff --git a/test/tags-input.spec.js b/test/tags-input.spec.js index 963a0f0c..25b77afd 100644 --- a/test/tags-input.spec.js +++ b/test/tags-input.spec.js @@ -60,8 +60,8 @@ describe('tags-input-directive', function() { } } - function sendKeyDown(keyCode) { - var event = jQuery.Event('keydown', { keyCode: keyCode }); + function sendKeyDown(keyCode, properties) { + var event = jQuery.Event('keydown', angular.extend({ keyCode: keyCode }, properties || {})); getInput().trigger(event); return event; @@ -964,4 +964,67 @@ describe('tags-input-directive', function() { expect(autocompleteObj.getTags()).toEqual(['a', 'b', 'c']); }); }); + + describe('hotkeys propagation handling', function() { + var hotkeys; + + beforeEach(function() { + compile('add-on-enter="true"', 'add-on-space="true"', 'add-on-comma="true"'); + }); + + describe('modifier key is on', function() { + beforeEach(function() { + hotkeys = [KEYS.enter, KEYS.comma, KEYS.space, KEYS.backspace]; + }); + + it('does not prevent any hotkey from being propagated when the shift key is down', function() { + angular.forEach(hotkeys, function(key) { + expect(sendKeyDown(key, { shiftKey: true }).isDefaultPrevented()).toBe(false); + }); + }); + + it('does not prevent any hotkey from being propagated when the alt key is down', function() { + angular.forEach(hotkeys, function(key) { + expect(sendKeyDown(key, { altKey: true }).isDefaultPrevented()).toBe(false); + }); + }); + + it('does not prevent any hotkey from being propagated when the ctrl key is down', function() { + angular.forEach(hotkeys, function(key) { + expect(sendKeyDown(key, { ctrlKey: true }).isDefaultPrevented()).toBe(false); + }); + }); + + it('does not prevent any hotkey from being propagated when the meta key is down', function() { + angular.forEach(hotkeys, function(key) { + expect(sendKeyDown(key, { metaKey: true }).isDefaultPrevented()).toBe(false); + }); + }); + + }); + + describe('modifier key is off', function() { + it('prevents enter, comma and space keys from being propagated when all modifiers are up', function() { + // Arrange + hotkeys = [KEYS.enter, KEYS.comma, KEYS.space]; + + // Act/Assert + angular.forEach(hotkeys, function(key) { + expect(sendKeyDown(key, { + shiftKey: false, + ctrlKey: false, + altKey: false, + metaKey: false}).isDefaultPrevented()).toBe(true); + }); + }); + + it('prevents the backspace key from being propagated when all modifiers are up', function() { + // Arrange + isolateScope.tryRemoveLast = function() { return true; }; + + // Act/Assert + expect(sendKeyDown(KEYS.backspace).isDefaultPrevented()).toBe(true); + }); + }); + }); }); \ No newline at end of file