mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-27 12:53:13 +03:00
Merge pull request #3005 from kevinansfield/ensure-incomplete-tags-arent-lost
Ensure incomplete tags aren't lost on save
This commit is contained in:
commit
67046f9cd6
201
core/client/controllers/post-tags-input.js
Normal file
201
core/client/controllers/post-tags-input.js
Normal file
@ -0,0 +1,201 @@
|
||||
var PostTagsInputController = Ember.Controller.extend({
|
||||
|
||||
tags: Ember.computed.alias('parentController.tags'),
|
||||
|
||||
suggestions: null,
|
||||
newTagText: null,
|
||||
|
||||
actions: {
|
||||
// triggered when the view is inserted so that later store.all('tag')
|
||||
// queries hit a full store cache and we don't see empty or out-of-date
|
||||
// suggestion lists
|
||||
loadAllTags: function () {
|
||||
this.store.find('tag');
|
||||
},
|
||||
|
||||
addNewTag: function () {
|
||||
var newTagText = this.get('newTagText'),
|
||||
searchTerm,
|
||||
existingTags,
|
||||
newTag;
|
||||
|
||||
if (Ember.isEmpty(newTagText) || this.hasTag(newTagText)) {
|
||||
this.send('reset');
|
||||
return;
|
||||
}
|
||||
|
||||
searchTerm = newTagText.toLowerCase();
|
||||
|
||||
// add existing tag if we have a match
|
||||
existingTags = this.store.all('tag').filter(function (tag) {
|
||||
return tag.get('name').toLowerCase() === searchTerm;
|
||||
});
|
||||
if (existingTags.get('length')) {
|
||||
this.send('addTag', existingTags.get('firstObject'));
|
||||
} else {
|
||||
// otherwise create a new one
|
||||
newTag = this.store.createRecord('tag');
|
||||
newTag.set('name', newTagText);
|
||||
this.get('tags').pushObject(newTag);
|
||||
}
|
||||
|
||||
this.send('reset');
|
||||
},
|
||||
|
||||
addTag: function (tag) {
|
||||
if (!Ember.isEmpty(tag) && !this.hasTag(tag.get('name'))) {
|
||||
this.get('tags').pushObject(tag);
|
||||
}
|
||||
this.send('reset');
|
||||
},
|
||||
|
||||
deleteTag: function (tag) {
|
||||
this.get('tags').removeObject(tag);
|
||||
},
|
||||
|
||||
deleteLastTag: function () {
|
||||
this.send('deleteTag', this.get('tags.lastObject'));
|
||||
},
|
||||
|
||||
selectSuggestion: function (suggestion) {
|
||||
if (!Ember.isEmpty(suggestion)) {
|
||||
this.get('suggestions').setEach('selected', false);
|
||||
suggestion.set('selected', true);
|
||||
}
|
||||
},
|
||||
|
||||
selectNextSuggestion: function () {
|
||||
var suggestions = this.get('suggestions'),
|
||||
selectedSuggestion = this.get('selectedSuggestion'),
|
||||
currentIndex,
|
||||
newSelection;
|
||||
|
||||
if (!Ember.isEmpty(suggestions)) {
|
||||
currentIndex = suggestions.indexOf(selectedSuggestion);
|
||||
if (currentIndex + 1 < suggestions.get('length')) {
|
||||
newSelection = suggestions[currentIndex + 1];
|
||||
this.send('selectSuggestion', newSelection);
|
||||
} else {
|
||||
suggestions.setEach('selected', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
selectPreviousSuggestion: function () {
|
||||
var suggestions = this.get('suggestions'),
|
||||
selectedSuggestion = this.get('selectedSuggestion'),
|
||||
currentIndex,
|
||||
lastIndex,
|
||||
newSelection;
|
||||
|
||||
if (!Ember.isEmpty(suggestions)) {
|
||||
currentIndex = suggestions.indexOf(selectedSuggestion);
|
||||
if (currentIndex === -1) {
|
||||
lastIndex = suggestions.get('length') - 1;
|
||||
this.send('selectSuggestion', suggestions[lastIndex]);
|
||||
} else if (currentIndex - 1 >= 0) {
|
||||
newSelection = suggestions[currentIndex - 1];
|
||||
this.send('selectSuggestion', newSelection);
|
||||
} else {
|
||||
suggestions.setEach('selected', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addSelectedSuggestion: function () {
|
||||
var suggestion = this.get('selectedSuggestion');
|
||||
if (Ember.isEmpty(suggestion)) { return; }
|
||||
|
||||
this.send('addTag', suggestion.get('tag'));
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
this.set('suggestions', null);
|
||||
this.set('newTagText', null);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
selectedSuggestion: function () {
|
||||
var suggestions = this.get('suggestions');
|
||||
if (suggestions && suggestions.get('length')) {
|
||||
return suggestions.filterBy('selected').get('firstObject');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}.property('suggestions.@each.selected'),
|
||||
|
||||
|
||||
updateSuggestionsList: function () {
|
||||
var searchTerm = this.get('newTagText'),
|
||||
matchingTags,
|
||||
// Limit the suggestions number
|
||||
maxSuggestions = 5,
|
||||
suggestions = new Ember.A();
|
||||
|
||||
if (!searchTerm || Ember.isEmpty(searchTerm.trim())) {
|
||||
this.set('suggestions', null);
|
||||
return;
|
||||
}
|
||||
|
||||
searchTerm = searchTerm.trim();
|
||||
|
||||
matchingTags = this.findMatchingTags(searchTerm);
|
||||
matchingTags = matchingTags.slice(0, maxSuggestions);
|
||||
matchingTags.forEach(function (matchingTag) {
|
||||
var suggestion = this.makeSuggestionObject(matchingTag, searchTerm);
|
||||
suggestions.pushObject(suggestion);
|
||||
}, this);
|
||||
|
||||
this.set('suggestions', suggestions);
|
||||
}.observes('newTagText'),
|
||||
|
||||
|
||||
findMatchingTags: function (searchTerm) {
|
||||
var matchingTags,
|
||||
self = this,
|
||||
allTags = this.store.all('tag');
|
||||
|
||||
if (allTags.get('length') === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
|
||||
matchingTags = allTags.filter(function (tag) {
|
||||
var tagNameMatches,
|
||||
hasAlreadyBeenAdded;
|
||||
|
||||
tagNameMatches = tag.get('name').toLowerCase().indexOf(searchTerm) !== -1;
|
||||
hasAlreadyBeenAdded = self.hasTag(tag.get('name'));
|
||||
|
||||
return tagNameMatches && !hasAlreadyBeenAdded;
|
||||
});
|
||||
|
||||
return matchingTags;
|
||||
},
|
||||
|
||||
hasTag: function (tagName) {
|
||||
return this.get('tags').mapBy('name').contains(tagName);
|
||||
},
|
||||
|
||||
makeSuggestionObject: function (matchingTag, _searchTerm) {
|
||||
var searchTerm = Ember.Handlebars.Utils.escapeExpression(_searchTerm),
|
||||
regexEscapedSearchTerm = searchTerm.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'),
|
||||
tagName = Ember.Handlebars.Utils.escapeExpression(matchingTag.get('name')),
|
||||
regex = new RegExp('(' + regexEscapedSearchTerm + ')', 'gi'),
|
||||
highlightedName,
|
||||
suggestion = new Ember.Object();
|
||||
|
||||
highlightedName = tagName.replace(regex, '<mark>$1</mark>');
|
||||
highlightedName = new Ember.Handlebars.SafeString(highlightedName);
|
||||
|
||||
suggestion.set('tag', matchingTag);
|
||||
suggestion.set('highlightedName', highlightedName);
|
||||
|
||||
return suggestion;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default PostTagsInputController;
|
@ -15,6 +15,9 @@ Ember.get(PostModel, 'attributes').forEach(function (name) {
|
||||
watchedProps.push('tags.[]');
|
||||
|
||||
var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||
|
||||
needs: ['post-tags-input'],
|
||||
|
||||
init: function () {
|
||||
var self = this;
|
||||
|
||||
@ -120,6 +123,9 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||
var status = this.get('willPublish') ? 'published' : 'draft',
|
||||
self = this;
|
||||
|
||||
// ensure an incomplete tag is finalised before save
|
||||
this.get('controllers.post-tags-input').send('addNewTag');
|
||||
|
||||
// set markdown equal to what's in the editor, minus the image markers.
|
||||
this.set('markdown', this.getMarkdown().withoutMarkers);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<footer id="publish-bar">
|
||||
<nav>
|
||||
{{view "editor-tags" tagName="section" id="entry-tags" class="left"}}
|
||||
{{render 'post-tags-input'}}
|
||||
|
||||
<div class="right">
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
<label class="tag-label" for="tags" title="Tags"><span class="hidden">Tags</span></label>
|
||||
<div class="tags">
|
||||
{{#each tags}}
|
||||
<span class="tag" {{action 'tagClick' this target="view"}}>{{name}}</span>
|
||||
{{view view.tagView tag=this}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<input type="hidden" class="tags-holder" id="tags-holder">
|
||||
{{input type="text" id="tags" class="tag-input" value=view.input}}
|
||||
<ul class="suggestions overlay" {{bind-attr style=view.overlayStyle}}></ul>
|
||||
{{view view.tagInputView class="tag-input" id="tags" value=newTagText}}
|
||||
<ul class="suggestions overlay" {{bind-attr style=view.overlayStyles}}>
|
||||
{{#each suggestions}}
|
||||
{{view view.suggestionView suggestion=this}}
|
||||
{{/each}}
|
||||
</ul>
|
@ -1,242 +0,0 @@
|
||||
var EditorTags = Ember.View.extend({
|
||||
templateName: 'editor-tags',
|
||||
|
||||
didInsertElement: function () {
|
||||
// Cache elements for later use
|
||||
this.$input = this.$('#tags');
|
||||
|
||||
this.$suggestions = this.$('ul.suggestions');
|
||||
},
|
||||
|
||||
willDestroyElement: function () {
|
||||
// Release ownership of the object for proper GC
|
||||
this.$input = null;
|
||||
|
||||
this.$suggestions = null;
|
||||
},
|
||||
|
||||
keys: {
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
ESC: 27,
|
||||
ENTER: 13,
|
||||
BACKSPACE: 8
|
||||
},
|
||||
|
||||
overlay: {
|
||||
visible: false,
|
||||
left: 0
|
||||
},
|
||||
|
||||
overlayStyle: function () {
|
||||
var styles = [];
|
||||
|
||||
styles.push(this.get('overlay.visible') ?
|
||||
'display: block' :
|
||||
'display: none'
|
||||
);
|
||||
|
||||
styles.push(this.get('overlay.left') ?
|
||||
'left: ' + this.get('overlay.left') + 'px' :
|
||||
'left: 0'
|
||||
);
|
||||
|
||||
return styles.join(';');
|
||||
}.property('overlay.visible'),
|
||||
|
||||
showSuggestions: function (_searchTerm) {
|
||||
var searchTerm = _searchTerm.toLowerCase(),
|
||||
matchingTags = this.findMatchingTags(searchTerm),
|
||||
// Limit the suggestions number
|
||||
maxSuggestions = 5,
|
||||
// Escape regex special characters
|
||||
escapedTerm = searchTerm.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&'),
|
||||
regexTerm = escapedTerm.replace(/(\s+)/g, '(<[^>]+>)*$1(<[^>]+>)*'),
|
||||
regexPattern = new RegExp('(' + regexTerm + ')', 'i'),
|
||||
highlightedNameRegex;
|
||||
|
||||
this.set('overlay.left', this.$input.position().left);
|
||||
this.$suggestions.html('');
|
||||
|
||||
matchingTags = matchingTags.slice(0, maxSuggestions);
|
||||
if (matchingTags.length > 0) {
|
||||
this.set('overlay.visible', true);
|
||||
}
|
||||
|
||||
highlightedNameRegex = /(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/;
|
||||
|
||||
matchingTags.forEach(function (matchingTag) {
|
||||
var highlightedName,
|
||||
suggestionHTML;
|
||||
|
||||
highlightedName = matchingTag.get('name').replace(regexPattern, function (match, p1) {
|
||||
return '<mark>' + encodeURIComponent(p1) + '</mark>';
|
||||
});
|
||||
/*jslint regexp: true */ // - would like to remove this
|
||||
highlightedName = highlightedName.replace(highlightedNameRegex, function (match, p1, p2, p3, p4) {
|
||||
return encodeURIComponent(p1) + '</mark>' + encodeURIComponent(p2) + '<mark>' + encodeURIComponent(p4);
|
||||
});
|
||||
|
||||
suggestionHTML = '<li data-tag-id="' + matchingTag.get('id') +
|
||||
'" data-tag-name="' + encodeURIComponent(matchingTag.get('name')) +
|
||||
'"><a href="#">' + highlightedName + '</a></li>';
|
||||
|
||||
this.$suggestions.append(suggestionHTML);
|
||||
}, this);
|
||||
},
|
||||
|
||||
findMatchingTags: function (searchTerm) {
|
||||
var matchingTagModels,
|
||||
self = this,
|
||||
allTags = this.get('controller.store').all('tag');
|
||||
|
||||
if (allTags.get('length') === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
searchTerm = searchTerm.toUpperCase();
|
||||
|
||||
matchingTagModels = allTags.filter(function (tag) {
|
||||
var tagNameMatches,
|
||||
hasAlreadyBeenAdded;
|
||||
|
||||
tagNameMatches = tag.get('name').toUpperCase().indexOf(searchTerm) !== -1;
|
||||
|
||||
hasAlreadyBeenAdded = self.hasTagBeenAdded(tag.name);
|
||||
|
||||
return tagNameMatches && !hasAlreadyBeenAdded;
|
||||
});
|
||||
|
||||
return matchingTagModels;
|
||||
},
|
||||
|
||||
keyDown: function (e) {
|
||||
var lastTagIndex;
|
||||
|
||||
// Delete character tiggers on Keydown, so needed to check on that event rather than Keyup.
|
||||
if (e.keyCode === this.keys.BACKSPACE && !this.get('input')) {
|
||||
lastTagIndex = this.get('controller.model.tags').get('length') - 1;
|
||||
|
||||
if (lastTagIndex > -1) {
|
||||
this.get('controller.model.tags').removeAt(lastTagIndex);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
keyUp: function (e) {
|
||||
var searchTerm = $.trim(this.get('input'));
|
||||
|
||||
if (e.keyCode === this.keys.UP) {
|
||||
e.preventDefault();
|
||||
if (this.get('overlay.visible')) {
|
||||
if (this.$suggestions.children('.selected').length === 0) {
|
||||
this.$suggestions.find('li:last-child').addClass('selected');
|
||||
} else {
|
||||
this.$suggestions.children('.selected').removeClass('selected').prev().addClass('selected');
|
||||
}
|
||||
}
|
||||
} else if (e.keyCode === this.keys.DOWN) {
|
||||
e.preventDefault();
|
||||
if (this.get('overlay.visible')) {
|
||||
if (this.$suggestions.children('.selected').length === 0) {
|
||||
this.$suggestions.find('li:first-child').addClass('selected');
|
||||
} else {
|
||||
this.$suggestions.children('.selected').removeClass('selected').next().addClass('selected');
|
||||
}
|
||||
}
|
||||
} else if (e.keyCode === this.keys.ESC) {
|
||||
this.set('overlay.visible', false);
|
||||
} else {
|
||||
if (searchTerm) {
|
||||
this.showSuggestions(searchTerm);
|
||||
} else {
|
||||
this.set('overlay.visible', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.keyCode === this.keys.UP || e.keyCode === this.keys.DOWN) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
keyPress: function (e) {
|
||||
var searchTerm = $.trim(this.get('input')),
|
||||
tag,
|
||||
$selectedSuggestion,
|
||||
isComma = ','.localeCompare(String.fromCharCode(e.keyCode || e.charCode)) === 0,
|
||||
hasAlreadyBeenAdded;
|
||||
|
||||
// use localeCompare in case of international keyboard layout
|
||||
if ((e.keyCode === this.keys.ENTER || isComma) && searchTerm) {
|
||||
// Submit tag using enter or comma key
|
||||
e.preventDefault();
|
||||
|
||||
$selectedSuggestion = this.$suggestions.children('.selected');
|
||||
if (this.get('overlay.visible') && $selectedSuggestion.length !== 0) {
|
||||
tag = {
|
||||
id: $selectedSuggestion.data('tag-id'),
|
||||
name: decodeURIComponent($selectedSuggestion.data('tag-name'))
|
||||
};
|
||||
hasAlreadyBeenAdded = this.hasTagBeenAdded(tag.name);
|
||||
if (!hasAlreadyBeenAdded) {
|
||||
this.addTag(tag);
|
||||
}
|
||||
} else {
|
||||
if (isComma) {
|
||||
// Remove comma from string if comma is used to submit.
|
||||
searchTerm = searchTerm.replace(/,/g, '');
|
||||
}
|
||||
|
||||
hasAlreadyBeenAdded = this.hasTagBeenAdded(searchTerm);
|
||||
if (!hasAlreadyBeenAdded) {
|
||||
this.addTag({id: null, name: searchTerm});
|
||||
}
|
||||
}
|
||||
this.set('input', '');
|
||||
this.$input.focus();
|
||||
this.set('overlay.visible', false);
|
||||
}
|
||||
},
|
||||
|
||||
addTag: function (tag) {
|
||||
var allTags = this.get('controller.store').all('tag'),
|
||||
newTag = allTags.findBy('name', tag.name);
|
||||
|
||||
if (!newTag) {
|
||||
newTag = this.get('controller.store').createRecord('tag', tag);
|
||||
}
|
||||
|
||||
this.get('controller.model.tags').addObject(newTag);
|
||||
|
||||
// Wait till Ember render's the new tag to access its dom element.
|
||||
Ember.run.schedule('afterRender', this, function () {
|
||||
this.$('.tag').last()[0].scrollIntoView(true);
|
||||
window.scrollTo(0, 1);
|
||||
|
||||
this.set('input', '');
|
||||
this.$input.focus();
|
||||
|
||||
this.set('overlay.visible', false);
|
||||
});
|
||||
},
|
||||
|
||||
hasTagBeenAdded: function (tagName) {
|
||||
if (!tagName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.get('controller.model.tags').filter(function (usedTag) {
|
||||
return usedTag.get('name').toUpperCase() === tagName.toUpperCase();
|
||||
}).length > 0;
|
||||
},
|
||||
|
||||
actions: {
|
||||
tagClick: function (tag) {
|
||||
this.get('controller.model.tags').removeObject(tag);
|
||||
window.scrollTo(0, 1);
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default EditorTags;
|
143
core/client/views/post-tags-input.js
Normal file
143
core/client/views/post-tags-input.js
Normal file
@ -0,0 +1,143 @@
|
||||
var PostTagsInputView = Ember.View.extend({
|
||||
tagName: 'section',
|
||||
elementId: 'entry-tags',
|
||||
classNames: 'left',
|
||||
|
||||
templateName: 'post-tags-input',
|
||||
|
||||
hasFocus: false,
|
||||
|
||||
keys: {
|
||||
BACKSPACE: 8,
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
ESCAPE: 27,
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
NUMPAD_ENTER: 108,
|
||||
COMMA: 188
|
||||
},
|
||||
|
||||
didInsertElement: function () {
|
||||
this.get('controller').send('loadAllTags');
|
||||
},
|
||||
|
||||
overlayStyles: function () {
|
||||
var styles = [],
|
||||
leftPos;
|
||||
|
||||
if (this.get('hasFocus') && this.get('controller.suggestions.length')) {
|
||||
leftPos = this.$().find('#tags').position().left;
|
||||
styles.push('display: block');
|
||||
styles.push('left: ' + leftPos + 'px');
|
||||
} else {
|
||||
styles.push('display: none');
|
||||
styles.push('left', 0);
|
||||
}
|
||||
|
||||
return styles.join(';');
|
||||
}.property('hasFocus', 'controller.suggestions.length'),
|
||||
|
||||
|
||||
tagInputView: Ember.TextField.extend({
|
||||
focusIn: function () {
|
||||
this.get('parentView').set('hasFocus', true);
|
||||
},
|
||||
|
||||
focusOut: function () {
|
||||
this.get('parentView').set('hasFocus', false);
|
||||
|
||||
// if (!Ember.isEmpty(this.get('value'))) {
|
||||
// this.get('parentView.controller').send('addNewTag');
|
||||
// }
|
||||
},
|
||||
|
||||
keyDown: function (event) {
|
||||
var controller = this.get('parentView.controller'),
|
||||
keys = this.get('parentView.keys'),
|
||||
hasValue;
|
||||
|
||||
switch (event.keyCode) {
|
||||
case keys.UP:
|
||||
event.preventDefault();
|
||||
controller.send('selectPreviousSuggestion');
|
||||
break;
|
||||
|
||||
case keys.DOWN:
|
||||
event.preventDefault();
|
||||
controller.send('selectNextSuggestion');
|
||||
break;
|
||||
|
||||
case keys.TAB:
|
||||
case keys.ENTER:
|
||||
case keys.NUMPAD_ENTER:
|
||||
case keys.COMMA:
|
||||
if (event.keyCode === keys.COMMA && event.shiftKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (controller.get('selectedSuggestion')) {
|
||||
event.preventDefault();
|
||||
controller.send('addSelectedSuggestion');
|
||||
} else {
|
||||
// allow user to tab out of field if input is empty
|
||||
hasValue = !Ember.isEmpty(this.get('value'));
|
||||
if (hasValue || event.keyCode !== keys.TAB) {
|
||||
event.preventDefault();
|
||||
controller.send('addNewTag');
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case keys.BACKSPACE:
|
||||
if (Ember.isEmpty(this.get('value'))) {
|
||||
event.preventDefault();
|
||||
controller.send('deleteLastTag');
|
||||
}
|
||||
break;
|
||||
|
||||
case keys.ESCAPE:
|
||||
event.preventDefault();
|
||||
controller.send('reset');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
tagView: Ember.View.extend({
|
||||
tagName: 'span',
|
||||
template: Ember.Handlebars.compile('{{view.tag.name}}'),
|
||||
classNames: 'tag',
|
||||
|
||||
tag: null,
|
||||
|
||||
click: function () {
|
||||
this.get('parentView.controller').send('deleteTag', this.get('tag'));
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
suggestionView: Ember.View.extend({
|
||||
tagName: 'li',
|
||||
template: Ember.Handlebars.compile('<a href="javascript:void(0);">{{view.suggestion.highlightedName}}</a>'),
|
||||
classNameBindings: 'suggestion.selected',
|
||||
|
||||
suggestion: null,
|
||||
|
||||
// we can't use the 'click' event here as the focusOut event on the
|
||||
// input will fire first
|
||||
|
||||
mouseDown: function (event) {
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
mouseUp: function (event) {
|
||||
event.preventDefault();
|
||||
this.get('parentView.controller').send('addTag',
|
||||
this.get('suggestion.tag'));
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export default PostTagsInputView;
|
Loading…
Reference in New Issue
Block a user