From fe711f56eaa3fe4293527955e653b3f6bbd235a0 Mon Sep 17 00:00:00 2001 From: Michael Benford Date: Sun, 27 Jul 2014 01:06:13 -0300 Subject: [PATCH] feat(autocomplete): Add loadOnFocus option Add a new option, loadOnFocus, to enable the loading of suggestions when the input element gains focus. This option has lower precedence than minLength and loadOnEmpty options. --- src/auto-complete.js | 22 ++++++++++++++++------ test/auto-complete.spec.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/auto-complete.js b/src/auto-complete.js index 6de473fb..2dd81a83 100644 --- a/src/auto-complete.js +++ b/src/auto-complete.js @@ -23,6 +23,8 @@ * is available as $query. * @param {boolean=} {loadOnEmpty=false} Flag indicating that the source option will be evaluated when the input content * becomes empty. The $query variable will be passed to the expression as an empty string. + * @param {boolean=} {loadOnFocus=false} Flag indicating that the source option will be evaluated when the input element + * gains focus. The current input value is available as $query. */ tagsInput.directive('autoComplete', function($document, $timeout, $sce, tagsInputConfig) { function SuggestionList(loadFn, options) { @@ -104,7 +106,7 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, tagsInpu templateUrl: 'ngTagsInput/auto-complete.html', link: function(scope, element, attrs, tagsInputCtrl) { var hotkeys = [KEYS.enter, KEYS.tab, KEYS.escape, KEYS.up, KEYS.down], - suggestionList, tagsInput, options, getItem, getDisplayText, documentClick; + suggestionList, tagsInput, options, getItem, getDisplayText, shouldLoadSuggestions; tagsInputConfig.load('autoComplete', scope, attrs, { debounceDelay: [Number, 100], @@ -112,7 +114,8 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, tagsInpu highlightMatchedText: [Boolean, true], maxResultsToShow: [Number, 10], loadOnDownArrow: [Boolean, false], - loadOnEmpty: [Boolean, false] + loadOnEmpty: [Boolean, false], + loadOnFocus: [Boolean, false] }); options = scope.options; @@ -130,6 +133,10 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, tagsInpu return safeToString(getItem(item)); }; + shouldLoadSuggestions = function(value) { + return value && value.length >= options.minLength || !value && options.loadOnEmpty; + }; + scope.suggestionList = suggestionList; scope.addSuggestionByIndex = function(index) { @@ -168,16 +175,19 @@ tagsInput.directive('autoComplete', function($document, $timeout, $sce, tagsInpu suggestionList.reset(); }) .on('input-change', function(value) { - var shouldLoadSuggestions = value && value.length >= options.minLength || - !value && options.loadOnEmpty; - - if (shouldLoadSuggestions) { + if (shouldLoadSuggestions(value)) { suggestionList.load(value, tagsInput.getTags()); } else { suggestionList.reset(); } }) + .on('input-focus', function() { + var value = tagsInput.getCurrentTagText(); + if (options.loadOnFocus && shouldLoadSuggestions(value)) { + suggestionList.load(value, tagsInput.getTags()); + } + }) .on('input-keydown', function(e) { // 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. diff --git a/test/auto-complete.spec.js b/test/auto-complete.spec.js index 10f685b7..2c98c2c9 100644 --- a/test/auto-complete.spec.js +++ b/test/auto-complete.spec.js @@ -736,6 +736,42 @@ describe('autoComplete directive', function() { }); }); + describe('load-on-focus option', function() { + it('initializes the option to false', function() { + // Arrange/Act + compile(); + + // Assert + expect(isolateScope.options.loadOnFocus).toBe(false); + }); + + it('calls the load function when the input element gains focus and the option is true', function() { + // Arrange + compile('load-on-focus="true"'); + tagsInput.getCurrentTagText.and.returnValue('ABC'); + + // Act + eventHandlers['input-focus'](); + $timeout.flush(); + + // Assert + expect($scope.loadItems).toHaveBeenCalledWith('ABC'); + }); + + it('doesn\' call the load function when the input element gains focus and the option is false', function() { + // Arrange + compile('load-on-focus="false"'); + tagsInput.getCurrentTagText.and.returnValue('ABC'); + + // Act + eventHandlers['input-focus'](); + $timeout.flush(); + + // Assert + expect($scope.loadItems).not.toHaveBeenCalled(); + }); + }); + describe('debounce-delay option', function() { it('initializes the option to 100 milliseconds', function() { // Arrange/Act