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

Commit

Permalink
feat(autocomplete): Changed tag addition behavior
Browse files Browse the repository at this point in the history
Changed tag addition behavior so a new tag is added when a selection is
made, instead of just changing the input's value and requiring the user
to manually add the tag by pressing some hotkey.

Closes #30.
  • Loading branch information
mbenford committed Dec 2, 2013
1 parent 5625762 commit 4f868e0
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 67 deletions.
101 changes: 51 additions & 50 deletions src/auto-complete.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ angular.module('tags-input').directive('autoComplete', function($document, $time
maxResultsToShow: { type: Number, defaultValue: 10 }
});

suggestionList = new SuggestionList(scope.source, scope.options);
tagsInput = tagsInputCtrl.registerAutocomplete();
suggestionList = new SuggestionList(scope.source, scope.options);

if (scope.options.highlightMatchedText) {
highlight = function(item, text) {
Expand All @@ -134,7 +134,7 @@ angular.module('tags-input').directive('autoComplete', function($document, $time
var added = false;

if (suggestionList.selected) {
tagsInput.changeInputValue(suggestionList.selected);
tagsInput.tryAddTag(suggestionList.selected);
suggestionList.reset();
tagsInput.focusInput();

Expand All @@ -147,59 +147,60 @@ angular.module('tags-input').directive('autoComplete', function($document, $time
return $sce.trustAsHtml(highlight(item, suggestionList.query));
};

tagsInput.on('input-changed', function(value) {
if (value) {
suggestionList.load(value, tagsInput.getTags());
} else {
suggestionList.reset();
}
})
.on('input-keydown', function(e) {
var key, handled;

if (hotkeys.indexOf(e.keyCode) === -1) {
return;
}

// 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
var immediatePropagationStopped = false;
e.stopImmediatePropagation = function() {
immediatePropagationStopped = true;
e.stopPropagation();
};
e.isImmediatePropagationStopped = function() {
return immediatePropagationStopped;
};

if (suggestionList.visible) {
key = e.keyCode;
handled = false;

if (key === KEYS.down) {
suggestionList.selectNext();
handled = true;
}
else if (key === KEYS.up) {
suggestionList.selectPrior();
handled = true;
}
else if (key === KEYS.escape) {
tagsInput
.on('input-changed', function(value) {
if (value) {
suggestionList.load(value, tagsInput.getTags());
} else {
suggestionList.reset();
handled = true;
}
else if (key === KEYS.enter || key === KEYS.tab) {
handled = scope.addSuggestion();
})
.on('input-keydown', function(e) {
var key, handled;

if (hotkeys.indexOf(e.keyCode) === -1) {
return;
}

if (handled) {
e.preventDefault();
e.stopImmediatePropagation();
scope.$apply();
// 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
var immediatePropagationStopped = false;
e.stopImmediatePropagation = function() {
immediatePropagationStopped = true;
e.stopPropagation();
};
e.isImmediatePropagationStopped = function() {
return immediatePropagationStopped;
};

if (suggestionList.visible) {
key = e.keyCode;
handled = false;

if (key === KEYS.down) {
suggestionList.selectNext();
handled = true;
}
else if (key === KEYS.up) {
suggestionList.selectPrior();
handled = true;
}
else if (key === KEYS.escape) {
suggestionList.reset();
handled = true;
}
else if (key === KEYS.enter || key === KEYS.tab) {
handled = scope.addSuggestion();
}

if (handled) {
e.preventDefault();
e.stopImmediatePropagation();
scope.$apply();
}
}
}
});
});

$document.on('click', function() {
if (suggestionList.visible) {
Expand Down
11 changes: 6 additions & 5 deletions src/tags-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,19 @@ angular.module('tags-input').directive('tagsInput', function(configuration) {
};

return {
changeInputValue: function(value) {
$scope.newTag = value;
tryAddTag: function(tag) {
$scope.newTag = tag;
return $scope.tryAdd();
},
focusInput: function() {
input[0].focus();
},
getTags: function() {
return $scope.tags;
},
on: function(name, handler) {
events.on(name, handler);
return this;
},
getTags: function() {
return $scope.tags;
}
};
};
Expand Down
15 changes: 8 additions & 7 deletions test/auto-complete.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('autocomplete-directive', function() {

tagsInput = {
changeInputValue: jasmine.createSpy(),
tryAddTag: jasmine.createSpy(),
focusInput: jasmine.createSpy(),
on: jasmine.createSpy().andCallFake(function(name, handler) {
eventHandlers[name] = handler;
Expand Down Expand Up @@ -175,7 +176,7 @@ describe('autocomplete-directive', function() {
expect(isSuggestionsBoxVisible()).toBe(false);
});

it('adds the selected suggestion to the input field when the enter key is pressed and the suggestions box is visible', function() {
it('adds the selected suggestion when the enter key is pressed and the suggestions box is visible', function() {
// Arrange
loadSuggestions(['Item1', 'Item2']);
suggestionList.select(0);
Expand All @@ -184,10 +185,10 @@ describe('autocomplete-directive', function() {
sendKeyDown(KEYS.enter);

// Assert
expect(tagsInput.changeInputValue).toHaveBeenCalledWith('Item1');
expect(tagsInput.tryAddTag).toHaveBeenCalledWith('Item1');
});

it('adds the selected suggestion to the input field when the tab key is pressed and there is a suggestion selected', function() {
it('adds the selected suggestion when the tab key is pressed and there is a suggestion selected', function() {
// Arrange
loadSuggestions(['Item1', 'Item2']);
suggestionList.select(0);
Expand All @@ -196,7 +197,7 @@ describe('autocomplete-directive', function() {
sendKeyDown(KEYS.tab);

// Assert
expect(tagsInput.changeInputValue).toHaveBeenCalledWith('Item1');
expect(tagsInput.tryAddTag).toHaveBeenCalledWith('Item1');
});

it('does not change the input value when the enter key is pressed and there is nothing selected', function() {
Expand All @@ -207,7 +208,7 @@ describe('autocomplete-directive', function() {
sendKeyDown(KEYS.enter);

// Assert
expect(tagsInput.changeInputValue).not.toHaveBeenCalled();
expect(tagsInput.tryAddTag).not.toHaveBeenCalled();
});

it('sets the selected suggestion to null after adding it to the input field', function() {
Expand Down Expand Up @@ -322,7 +323,7 @@ describe('autocomplete-directive', function() {
expect(suggestionList.selected).toBe('Item2');
});

it('adds the selected suggestion to the input field when a mouse click is triggered', function() {
it('adds the selected suggestion when a mouse click is triggered', function() {
// Arrange
loadSuggestions(['Item1', 'Item2', 'Item3']);
getSuggestion(1).mouseenter();
Expand All @@ -331,7 +332,7 @@ describe('autocomplete-directive', function() {
getSuggestion(1).click();

// Assert
expect(tagsInput.changeInputValue).toHaveBeenCalledWith('Item2');
expect(tagsInput.tryAddTag).toHaveBeenCalledWith('Item2');
});

it('focuses the input field when a suggestion is added via a mouse click', function() {
Expand Down
13 changes: 8 additions & 5 deletions test/tags-input.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -764,20 +764,23 @@ describe('tags-input-directive', function() {

it('creates an object containing all the autocomplete directive needs to work', function() {
expect(autocompleteObj).toEqual({
changeInputValue: jasmine.any(Function),
tryAddTag: jasmine.any(Function),
focusInput: jasmine.any(Function),
on: jasmine.any(Function),
getTags: jasmine.any(Function)
});
});

it('changes the input value', function() {
// Act
autocompleteObj.changeInputValue('ABC');
it('tries to add a tag', function() {
// Arrange
$scope.tags = [];
$scope.$digest();

// Act
autocompleteObj.tryAddTag('tag');

// Assert
expect(getInput().val()).toBe('ABC');
expect($scope.tags).toEqual(['tag']);
});

it('focus the input box', function() {
Expand Down

0 comments on commit 4f868e0

Please sign in to comment.