diff --git a/src/js/dropdown_view.js b/src/js/dropdown_view.js index 8e2967bb..3024223d 100644 --- a/src/js/dropdown_view.js +++ b/src/js/dropdown_view.js @@ -33,13 +33,13 @@ var DropdownView = (function() { this.isMouseOverDropdown = false; }, - _handleMouseover: function(e) { + _handleMouseover: function($e) { this._getSuggestions().removeClass('tt-is-under-cursor'); - $(e.currentTarget).addClass('tt-is-under-cursor'); + $($e.currentTarget).addClass('tt-is-under-cursor'); }, - _handleSelection: function(e) { - this.trigger('select', formatDataForSuggestion($(e.currentTarget))); + _handleSelection: function($e) { + this.trigger('select', formatDataForSuggestion($($e.currentTarget))); }, _moveCursor: function(increment) { diff --git a/src/js/input_view.js b/src/js/input_view.js index beb2252d..bbfc7ae4 100644 --- a/src/js/input_view.js +++ b/src/js/input_view.js @@ -15,13 +15,13 @@ var InputView = (function() { utils.bindAll(this); this.specialKeyCodeMap = { - 9: { event: 'tab' }, - 27: { event: 'esc' }, - 37: { event: 'left' }, - 39: { event: 'right' }, - 13: { event: 'enter' }, - 38: { event: 'up', preventDefault: true }, - 40: { event: 'down', preventDefault: true } + 9: 'tab', + 27: 'esc', + 37: 'left', + 39: 'right', + 13: 'enter', + 38: 'up', + 40: 'down' }; this.query = ''; @@ -64,14 +64,11 @@ var InputView = (function() { this.trigger('blur'); }, - _handleSpecialKeyEvent: function(e) { + _handleSpecialKeyEvent: function($e) { // which is normalized and consistent (but not for IE) - var keyCode = this.specialKeyCodeMap[e.which || e.keyCode]; + var keyName = this.specialKeyCodeMap[$e.which || $e.keyCode]; - if (keyCode) { - this.trigger(keyCode.event, e); - keyCode.preventDefault && e.preventDefault(); - } + keyName && this.trigger(keyName, $e); }, _compareQueryToInputValue: function() { @@ -100,10 +97,6 @@ var InputView = (function() { this.$input.blur(); }, - setPreventDefaultValueForKey: function(key, value) { - this.specialKeyCodeMap[key].preventDefault = !!value; - }, - getQuery: function() { return this.query; }, @@ -138,7 +131,7 @@ var InputView = (function() { selectionStart = this.$input[0].selectionStart, range; - if (selectionStart) { + if (utils.isNumber(selectionStart)) { return selectionStart === valueLength; } diff --git a/src/js/typeahead_view.js b/src/js/typeahead_view.js index e4a28f4d..318dc72f 100644 --- a/src/js/typeahead_view.js +++ b/src/js/typeahead_view.js @@ -74,9 +74,9 @@ var TypeaheadView = (function() { .on('queryChange whitespaceChange', this._setLanguageDirection) .on('esc', this._hideDropdown) .on('esc', this._setInputValueToQuery) + .on('tab up down', this._managePreventDefault) .on('up down', this._moveDropdownCursor) .on('up down', this._showDropdown) - .on('tab', this._setPreventDefaultValueForTab) .on('tab left right', this._autocomplete); } @@ -84,14 +84,26 @@ var TypeaheadView = (function() { // private methods // --------------- - _setPreventDefaultValueForTab: function(e) { - var hint = this.inputView.getHintValue(), - inputValue = this.inputView.getInputValue(), + _managePreventDefault: function(e) { + var $e = e.data, + hint, + inputValue, + preventDefault = false; + + switch (e.type) { + case 'tab': + hint = this.inputView.getHintValue(); + inputValue = this.inputView.getInputValue(); preventDefault = hint && hint !== inputValue; + break; + + case 'up': + case 'down': + preventDefault = !$e.shiftKey && !$e.ctrlKey && !$e.metaKey; + break; + } - // if the user tabs to autocomplete while the menu is open - // this will prevent the focus from being lost from the query input - this.inputView.setPreventDefaultValueForKey('9', preventDefault); + preventDefault && $e.preventDefault(); }, _setLanguageDirection: function() { @@ -136,7 +148,9 @@ var TypeaheadView = (function() { }, _setInputValueToSuggestionUnderCursor: function(e) { - this.inputView.setInputValue(e.data.value, true); + var suggestion = e.data; + + this.inputView.setInputValue(suggestion.value, true); }, _showDropdown: function() { @@ -149,7 +163,12 @@ var TypeaheadView = (function() { }, _moveDropdownCursor: function(e) { - this.dropdownView[e.type === 'up' ? 'moveCursorUp' : 'moveCursorDown'](); + var $e = e.data; + + if (!$e.shiftKey && !$e.ctrlKey && !$e.metaKey) { + this.dropdownView[e.type === 'up' ? + 'moveCursorUp' : 'moveCursorDown'](); + } }, _handleSelection: function(e) { diff --git a/test/input_view_spec.js b/test/input_view_spec.js index ce6b1437..eb8400e8 100644 --- a/test/input_view_spec.js +++ b/test/input_view_spec.js @@ -162,18 +162,6 @@ describe('InputView', function() { }); }); - describe('#setPreventDefaultValueForKey', function() { - it('should act as a setter for keyCodeMap', function() { - var key = '9'; - - this.inputView.setPreventDefaultValueForKey(key, 'truthy value'); - expect(this.inputView.specialKeyCodeMap[key].preventDefault).toBe(true); - - this.inputView.setPreventDefaultValueForKey(key, false); - expect(this.inputView.specialKeyCodeMap[key].preventDefault).toBe(false); - }); - }); - describe('#getQuery', function() { it('should act as a getter for query', function() { this.inputView.query = 'i am the query value'; diff --git a/test/playground.html b/test/playground.html new file mode 100644 index 00000000..3fa83c0d --- /dev/null +++ b/test/playground.html @@ -0,0 +1,87 @@ + + +
+ + + + + + + + +