mirror of
https://github.com/TryGhost/Ghost-Admin.git
synced 2023-12-14 02:33:04 +01:00
Replace the current tag input with a selectize based input
issue #3800, closes #5648 - uses ember-cli-selectize addon for the tag editing functionality in the PSM
This commit is contained in:
parent
f983a4537e
commit
ad83bca937
8 changed files with 65 additions and 693 deletions
|
@ -1,281 +0,0 @@
|
||||||
/* global Bloodhound, key */
|
|
||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ghost Tag Input Component
|
|
||||||
*
|
|
||||||
* Creates an input field that is used to input tags for a post.
|
|
||||||
* @param {Boolean} hasFocus Whether or not the input is focused
|
|
||||||
* @param {DS.Model} post The current post object to input tags for
|
|
||||||
*/
|
|
||||||
export default Ember.Component.extend({
|
|
||||||
classNames: ['gh-input'],
|
|
||||||
classNameBindings: ['hasFocus:focus'],
|
|
||||||
|
|
||||||
// Uses the Ember-Data store directly, as it needs to create and get tag records
|
|
||||||
store: Ember.inject.service(),
|
|
||||||
|
|
||||||
hasFocus: false,
|
|
||||||
post: null,
|
|
||||||
highlightIndex: null,
|
|
||||||
|
|
||||||
isDirty: false,
|
|
||||||
isReloading: false,
|
|
||||||
|
|
||||||
unassignedTags: Ember.A(), // tags that AREN'T assigned to this post
|
|
||||||
currentTags: Ember.A(), // tags that ARE assigned to this post
|
|
||||||
|
|
||||||
// Input field events
|
|
||||||
click: function () {
|
|
||||||
this.$('#tag-input').focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
focusIn: function () {
|
|
||||||
this.set('hasFocus', true);
|
|
||||||
key.setScope('tags');
|
|
||||||
},
|
|
||||||
|
|
||||||
focusOut: function () {
|
|
||||||
this.set('hasFocus', false);
|
|
||||||
key.setScope('default');
|
|
||||||
this.set('highlightIndex', null);
|
|
||||||
// if there is text in the input field, create a tag with it
|
|
||||||
if (this.$('#tag-input').val() !== '') {
|
|
||||||
this.send('addTag', this.$('#tag-input').val());
|
|
||||||
}
|
|
||||||
this.saveTags();
|
|
||||||
},
|
|
||||||
|
|
||||||
keyPress: function (event) {
|
|
||||||
var val = this.$('#tag-input').val(),
|
|
||||||
isComma = ','.localeCompare(String.fromCharCode(event.keyCode || event.charCode)) === 0;
|
|
||||||
|
|
||||||
if (isComma && val !== '') {
|
|
||||||
event.preventDefault();
|
|
||||||
this.send('addTag', val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Tag Loading functions
|
|
||||||
loadTagsOnInit: Ember.on('init', function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (this.get('post')) {
|
|
||||||
this.loadTags().then(function () {
|
|
||||||
Ember.run.schedule('afterRender', self, 'initTypeahead');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
reloadTags: Ember.observer('post', function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.loadTags().then(function () {
|
|
||||||
self.reloadTypeahead(false);
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
|
|
||||||
loadTags: function () {
|
|
||||||
var self = this,
|
|
||||||
post = this.get('post');
|
|
||||||
|
|
||||||
this.get('currentTags').clear();
|
|
||||||
this.get('unassignedTags').clear();
|
|
||||||
|
|
||||||
return this.get('store').find('tag', {limit: 'all'}).then(function (tags) {
|
|
||||||
if (post.get('id')) { // if it's a new post, it won't have an id
|
|
||||||
self.get('currentTags').pushObjects(post.get('tags').toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
tags.forEach(function (tag) {
|
|
||||||
if (Ember.isEmpty(post.get('id')) || Ember.isEmpty(self.get('currentTags').findBy('id', tag.get('id')))) {
|
|
||||||
self.get('unassignedTags').pushObject(tag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Ember.RSVP.resolve();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Key Binding functions
|
|
||||||
bindKeys: function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
key('enter, tab', 'tags', function (event) {
|
|
||||||
var val = self.$('#tag-input').val();
|
|
||||||
|
|
||||||
if (val !== '') {
|
|
||||||
event.preventDefault();
|
|
||||||
self.send('addTag', val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
key('backspace', 'tags', function (event) {
|
|
||||||
if (self.$('#tag-input').val() === '') {
|
|
||||||
event.preventDefault();
|
|
||||||
self.send('deleteTag');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
key('left', 'tags', function (event) {
|
|
||||||
self.updateHighlightIndex(-1, event);
|
|
||||||
});
|
|
||||||
|
|
||||||
key('right', 'tags', function (event) {
|
|
||||||
self.updateHighlightIndex(1, event);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
unbindKeys: function () {
|
|
||||||
key.unbind('enter, tab', 'tags');
|
|
||||||
key.unbind('backspace', 'tags');
|
|
||||||
key.unbind('left', 'tags');
|
|
||||||
key.unbind('right', 'tags');
|
|
||||||
},
|
|
||||||
|
|
||||||
didInsertElement: function () {
|
|
||||||
this.bindKeys();
|
|
||||||
},
|
|
||||||
|
|
||||||
willDestroyElement: function () {
|
|
||||||
this.unbindKeys();
|
|
||||||
this.destroyTypeahead();
|
|
||||||
},
|
|
||||||
|
|
||||||
updateHighlightIndex: function (modifier, event) {
|
|
||||||
if (this.$('#tag-input').val() === '') {
|
|
||||||
var highlightIndex = this.get('highlightIndex'),
|
|
||||||
length = this.get('currentTags.length'),
|
|
||||||
newIndex;
|
|
||||||
|
|
||||||
if (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (highlightIndex === null) {
|
|
||||||
newIndex = (modifier > 0) ? 0 : length - 1;
|
|
||||||
} else {
|
|
||||||
newIndex = highlightIndex + modifier;
|
|
||||||
if (newIndex < 0 || newIndex >= length) {
|
|
||||||
newIndex = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.set('highlightIndex', newIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Typeahead functions
|
|
||||||
initTypeahead: function () {
|
|
||||||
var tags = new Bloodhound({
|
|
||||||
datumTokenizer: Bloodhound.tokenizers.whitespace,
|
|
||||||
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
|
||||||
local: this.get('unassignedTags').map(function (tag) {
|
|
||||||
return tag.get('name');
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$('#tag-input').typeahead({
|
|
||||||
minLength: 1,
|
|
||||||
classNames: {
|
|
||||||
// TODO: Fix CSS for these
|
|
||||||
input: 'tag-input',
|
|
||||||
hint: 'tag-input',
|
|
||||||
menu: 'dropdown-menu',
|
|
||||||
suggestion: 'dropdown-item',
|
|
||||||
open: 'open'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'tags',
|
|
||||||
source: tags
|
|
||||||
}).bind('typeahead:select', Ember.run.bind(this, 'typeaheadAdd'));
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyTypeahead: function () {
|
|
||||||
this.$('#tag-input').typeahead('destroy');
|
|
||||||
},
|
|
||||||
|
|
||||||
reloadTypeahead: function (refocus) {
|
|
||||||
refocus = (typeof refocus !== 'undefined') ? refocus : true; // set default refocus value
|
|
||||||
this.set('isReloading', true);
|
|
||||||
this.destroyTypeahead();
|
|
||||||
this.initTypeahead();
|
|
||||||
if (refocus) {
|
|
||||||
this.click();
|
|
||||||
}
|
|
||||||
this.set('isReloading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Tag Saving / Tag Add/Delete Actions
|
|
||||||
saveTags: function () {
|
|
||||||
var post = this.get('post');
|
|
||||||
|
|
||||||
if (post && this.get('isDirty') && !this.get('isReloading')) {
|
|
||||||
post.get('tags').clear();
|
|
||||||
post.get('tags').pushObjects(this.get('currentTags').toArray());
|
|
||||||
this.set('isDirty', false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Used for typeahead selection
|
|
||||||
typeaheadAdd: function (event, datum) {
|
|
||||||
if (datum) {
|
|
||||||
// this is needed so two tags with the same name aren't added
|
|
||||||
this.$('#tag-input').typeahead('val', '');
|
|
||||||
this.send('addTag', datum);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
addTag: function (tagName) {
|
|
||||||
var tagToAdd, checkTag;
|
|
||||||
|
|
||||||
this.$('#tag-input').typeahead('val', '');
|
|
||||||
|
|
||||||
// Prevent multiple tags with the same name occuring
|
|
||||||
if (this.get('currentTags').findBy('name', tagName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkTag = this.get('unassignedTags').findBy('name', tagName);
|
|
||||||
|
|
||||||
if (checkTag) {
|
|
||||||
tagToAdd = checkTag;
|
|
||||||
this.get('unassignedTags').removeObject(checkTag);
|
|
||||||
this.reloadTypeahead();
|
|
||||||
} else {
|
|
||||||
tagToAdd = this.get('store').createRecord('tag', {name: tagName});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set('isDirty', true);
|
|
||||||
this.set('highlightIndex', null);
|
|
||||||
this.get('currentTags').pushObject(tagToAdd);
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteTag: function (tag) {
|
|
||||||
var removedTag;
|
|
||||||
|
|
||||||
if (tag) {
|
|
||||||
removedTag = this.get('currentTags').findBy('name', tag);
|
|
||||||
this.get('currentTags').removeObject(removedTag);
|
|
||||||
} else {
|
|
||||||
if (this.get('highlightIndex') !== null) {
|
|
||||||
removedTag = this.get('currentTags').objectAt(this.get('highlightIndex'));
|
|
||||||
this.get('currentTags').removeObject(removedTag);
|
|
||||||
this.set('highlightIndex', null);
|
|
||||||
} else {
|
|
||||||
this.set('highlightIndex', this.get('currentTags.length') - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removedTag) {
|
|
||||||
if (removedTag.get('isNew')) { // if tag is new, don't change isDirty,
|
|
||||||
removedTag.deleteRecord(); // and delete the new record
|
|
||||||
} else {
|
|
||||||
this.set('isDirty', true);
|
|
||||||
this.get('unassignedTags').pushObject(removedTag);
|
|
||||||
this.reloadTypeahead();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -188,6 +188,13 @@ export default Ember.Controller.extend(SettingsMenuMixin, {
|
||||||
this.set('debounceId', debounceId);
|
this.set('debounceId', debounceId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// live-query of all tags for tag input autocomplete
|
||||||
|
availableTags: Ember.computed(function () {
|
||||||
|
return this.get('store').filter('tag', {limit: 'all'}, function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
showErrors: function (errors) {
|
showErrors: function (errors) {
|
||||||
errors = Ember.isArray(errors) ? errors : [errors];
|
errors = Ember.isArray(errors) ? errors : [errors];
|
||||||
this.get('notifications').showErrors(errors);
|
this.get('notifications').showErrors(errors);
|
||||||
|
@ -460,6 +467,45 @@ export default Ember.Controller.extend(SettingsMenuMixin, {
|
||||||
self.set('selectedAuthor', author);
|
self.set('selectedAuthor', author);
|
||||||
model.rollback();
|
model.rollback();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addTag: function (tagName) {
|
||||||
|
var self = this,
|
||||||
|
currentTags = this.get('model.tags'),
|
||||||
|
currentTagNames = currentTags.map(function (tag) { return tag.get('name').toLowerCase(); }),
|
||||||
|
availableTagNames = null,
|
||||||
|
tagToAdd = null;
|
||||||
|
|
||||||
|
// abort if tag is already selected
|
||||||
|
if (currentTagNames.contains(tagName.toLowerCase())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get('availableTags').then(function (availableTags) {
|
||||||
|
availableTagNames = availableTags.map(function (tag) { return tag.get('name').toLowerCase(); });
|
||||||
|
|
||||||
|
// find existing tag or create new
|
||||||
|
if (availableTagNames.contains(tagName.toLowerCase())) {
|
||||||
|
tagToAdd = availableTags.find(function (tag) {
|
||||||
|
return tag.get('name').toLowerCase() === tagName.toLowerCase();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tagToAdd = self.get('store').createRecord('tag', {
|
||||||
|
name: tagName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// push tag onto post relationship
|
||||||
|
if (tagToAdd) { self.get('model.tags').pushObject(tagToAdd); }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeTag: function (tag) {
|
||||||
|
this.get('model.tags').removeObject(tag);
|
||||||
|
|
||||||
|
if (tag.get('isNew')) {
|
||||||
|
tag.destroyRecord();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -128,3 +128,11 @@
|
||||||
.closed > .dropdown-menu {
|
.closed > .dropdown-menu {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Selectize
|
||||||
|
/* ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
.selectize-dropdown {
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
<ul class="tags-input-list">
|
|
||||||
{{#each currentTags as |tag index|}}
|
|
||||||
<li class="label-tag {{if (is-equal highlightIndex index) 'highlight'}}" {{action "deleteTag" tag.name}}>{{tag.name}}</li>
|
|
||||||
{{/each}}
|
|
||||||
<li><input type="text" id="tag-input"></li>
|
|
||||||
</ul>
|
|
|
@ -35,7 +35,15 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tag-input">Tags</label>
|
<label for="tag-input">Tags</label>
|
||||||
{{gh-tags-input post=model}}
|
{{ember-selectize
|
||||||
|
id="tag-input"
|
||||||
|
multiple=true
|
||||||
|
selection=model.tags
|
||||||
|
content=availableTags
|
||||||
|
optionValuePath="content.name"
|
||||||
|
optionLabelPath="content.name"
|
||||||
|
create-item="addTag"
|
||||||
|
remove-item="removeTag"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#unless session.user.isAuthor}}
|
{{#unless session.user.isAuthor}}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"normalize.css": "3.0.3",
|
"normalize.css": "3.0.3",
|
||||||
"password-generator": "git://github.com/bermi/password-generator#49accd7",
|
"password-generator": "git://github.com/bermi/password-generator#49accd7",
|
||||||
"rangyinputs": "1.2.0",
|
"rangyinputs": "1.2.0",
|
||||||
|
"selectize": "~0.12.1",
|
||||||
"showdown-ghost": "0.3.6",
|
"showdown-ghost": "0.3.6",
|
||||||
"sinonjs": "1.14.1",
|
"sinonjs": "1.14.1",
|
||||||
"typeahead.js": "0.11.1",
|
"typeahead.js": "0.11.1",
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
"ember-cli-ic-ajax": "0.1.1",
|
"ember-cli-ic-ajax": "0.1.1",
|
||||||
"ember-cli-inject-live-reload": "^1.3.0",
|
"ember-cli-inject-live-reload": "^1.3.0",
|
||||||
"ember-cli-mocha": "^0.7.0",
|
"ember-cli-mocha": "^0.7.0",
|
||||||
|
"ember-cli-selectize": "0.4.0",
|
||||||
"ember-cli-simple-auth": "0.8.0",
|
"ember-cli-simple-auth": "0.8.0",
|
||||||
"ember-cli-simple-auth-oauth2": "0.8.0",
|
"ember-cli-simple-auth-oauth2": "0.8.0",
|
||||||
"ember-cli-uglify": "^1.0.1",
|
"ember-cli-uglify": "^1.0.1",
|
||||||
|
|
|
@ -1,405 +0,0 @@
|
||||||
/* jshint expr:true */
|
|
||||||
import Ember from 'ember';
|
|
||||||
import { expect } from 'chai';
|
|
||||||
import {
|
|
||||||
describeComponent,
|
|
||||||
it
|
|
||||||
} from 'ember-mocha';
|
|
||||||
|
|
||||||
describeComponent(
|
|
||||||
'gh-tags-input',
|
|
||||||
'GhTagsInputComponent',
|
|
||||||
{
|
|
||||||
needs: ['helper:is-equal']
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
var post = Ember.Object.create({
|
|
||||||
id: 1,
|
|
||||||
tags: Ember.A()
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
var store = Ember.Object.create({
|
|
||||||
tags: Ember.A(),
|
|
||||||
|
|
||||||
find: function () {
|
|
||||||
return Ember.RSVP.resolve(this.get('tags'));
|
|
||||||
},
|
|
||||||
|
|
||||||
createRecord: function (name, opts) {
|
|
||||||
return Ember.Object.create({
|
|
||||||
isNew: true,
|
|
||||||
isDeleted: false,
|
|
||||||
|
|
||||||
name: opts.name,
|
|
||||||
|
|
||||||
deleteRecord: function () {
|
|
||||||
this.set('isDeleted', true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
store.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 1,
|
|
||||||
name: 'Test1'
|
|
||||||
}));
|
|
||||||
store.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 2,
|
|
||||||
name: 'Test2'
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.subject().set('store', store);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
post.get('tags').clear(); // reset tags
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders with null post', function () {
|
|
||||||
// creates the component instance
|
|
||||||
var component = this.subject();
|
|
||||||
expect(component._state).to.equal('preRender');
|
|
||||||
|
|
||||||
// renders the component on the page
|
|
||||||
this.render();
|
|
||||||
expect(component._state).to.equal('inDOM');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly loads all tags', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly loads & filters tags when post has tags', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 1,
|
|
||||||
name: 'Test1'
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(1);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
expect(component.get('unassignedTags').findBy('id', 1)).to.not.exist;
|
|
||||||
expect(component.get('unassignedTags').findBy('id', 2)).to.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly adds new tag to currentTags', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('addTag', 'Test3');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
expect(component.get('isDirty')).to.be.true;
|
|
||||||
expect(component.get('currentTags').findBy('name', 'Test3')).to.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly adds existing tag to currentTags', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('addTag', 'Test2');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(1);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
expect(component.get('isDirty')).to.be.true;
|
|
||||||
expect(component.get('currentTags').findBy('name', 'Test2')).to.exist;
|
|
||||||
expect(component.get('unassignedTags').findBy('name', 'Test2')).to.not.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('doesn\'t allow duplicate tags to be added', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 1,
|
|
||||||
name: 'Test1'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(1);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('addTag', 'Test1');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(1);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('deletes new tag correctly', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('addTag', 'Test3');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('deleteTag', 'Test3');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
expect(component.get('currentTags').findBy('name', 'Test3')).to.not.exist;
|
|
||||||
expect(component.get('unassignedTags').findBy('name', 'Test3')).to.not.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('deletes existing tag correctly', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 1,
|
|
||||||
name: 'Test1'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(1);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
expect(component.get('unassignedTags').findBy('name', 'Test1')).to.not.exist;
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.send('deleteTag', 'Test1');
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
expect(component.get('unassignedTags').findBy('name', 'Test1')).to.exist;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates tag with leftover text when component is de-focused', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(0);
|
|
||||||
|
|
||||||
component.$('#tag-input').typeahead('val', 'Test3');
|
|
||||||
component.focusOut(); // simluate de-focus
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets highlight index to length-1 if it is null and modifier is negative', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 3,
|
|
||||||
name: 'Test3'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 4,
|
|
||||||
name: 'Test4'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 5,
|
|
||||||
name: 'Test5'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(3);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets highlight index to 0 if it is null and modifier is positive', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 3,
|
|
||||||
name: 'Test3'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 4,
|
|
||||||
name: 'Test4'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 5,
|
|
||||||
name: 'Test5'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(3);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('increments highlight index correctly (no reset)', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 3,
|
|
||||||
name: 'Test3'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 4,
|
|
||||||
name: 'Test4'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 5,
|
|
||||||
name: 'Test5'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
component.set('highlightIndex', 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(1);
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(3);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(2);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('increments highlight index correctly (with reset)', function () {
|
|
||||||
var component = this.subject();
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 3,
|
|
||||||
name: 'Test3'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 4,
|
|
||||||
name: 'Test4'
|
|
||||||
}));
|
|
||||||
|
|
||||||
post.get('tags').pushObject(Ember.Object.create({
|
|
||||||
id: 5,
|
|
||||||
name: 'Test5'
|
|
||||||
}));
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('post', post);
|
|
||||||
component.set('highlightIndex', 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(2);
|
|
||||||
expect(component.get('unassignedTags.length')).to.equal(2);
|
|
||||||
expect(component.get('currentTags.length')).to.equal(3);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.be.null;
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.set('highlightIndex', 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.equal(0);
|
|
||||||
|
|
||||||
Ember.run(function () {
|
|
||||||
component.updateHighlightIndex(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.get('highlightIndex')).to.be.null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
Loading…
Reference in a new issue