Added tag siblings to frontend
This commit is contained in:
parent
6015199559
commit
6ca08e5532
3 changed files with 120 additions and 36 deletions
1
TODO
1
TODO
|
@ -28,7 +28,6 @@ everything related to tags:
|
||||||
- tag editing
|
- tag editing
|
||||||
- category (from config.ini)
|
- category (from config.ini)
|
||||||
- description
|
- description
|
||||||
- related tags
|
|
||||||
- aliases
|
- aliases
|
||||||
- take care of recursion
|
- take care of recursion
|
||||||
- listing
|
- listing
|
||||||
|
|
|
@ -197,9 +197,31 @@ input[type=checkbox]:checked + label::before {
|
||||||
}
|
}
|
||||||
.tag-input li a {
|
.tag-input li a {
|
||||||
color: black;
|
color: black;
|
||||||
|
}
|
||||||
|
.tag-input li a.close {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-left: 0.5em;
|
margin-left: 0.75em;
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
|
.related-tags {
|
||||||
|
line-height: 200%;
|
||||||
|
font-size: 15px;
|
||||||
|
display: none;
|
||||||
|
margin: 0.5em 0.5em 1em 0.5em;
|
||||||
|
}
|
||||||
|
.related-tags span {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.related-tags ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.related-tags li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 0.5em;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.autocomplete {
|
.autocomplete {
|
||||||
|
|
|
@ -4,6 +4,8 @@ App.Controls = App.Controls || {};
|
||||||
App.Controls.TagInput = function($underlyingInput) {
|
App.Controls.TagInput = function($underlyingInput) {
|
||||||
var _ = App.DI.get('_');
|
var _ = App.DI.get('_');
|
||||||
var jQuery = App.DI.get('jQuery');
|
var jQuery = App.DI.get('jQuery');
|
||||||
|
var promise = App.DI.get('promise');
|
||||||
|
var api = App.DI.get('api');
|
||||||
|
|
||||||
var KEY_RETURN = 13;
|
var KEY_RETURN = 13;
|
||||||
var KEY_SPACE = 32;
|
var KEY_SPACE = 32;
|
||||||
|
@ -18,6 +20,15 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
inputConfirmed: null,
|
inputConfirmed: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var $wrapper = jQuery('<div class="tag-input">');
|
||||||
|
var $tagList = jQuery('<ul class="tags">');
|
||||||
|
var $input = jQuery('<input class="tag-real-input" type="text"/>');
|
||||||
|
var $related = jQuery('<div class="related-tags"><span>Related tags:</span><ul>');
|
||||||
|
init();
|
||||||
|
render();
|
||||||
|
initAutocomplete();
|
||||||
|
|
||||||
|
function init() {
|
||||||
if ($underlyingInput.length === 0) {
|
if ($underlyingInput.length === 0) {
|
||||||
throw new Error('Tag input element was not found');
|
throw new Error('Tag input element was not found');
|
||||||
}
|
}
|
||||||
|
@ -28,11 +39,10 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
throw new Error('Tag input was already initialized for this element');
|
throw new Error('Tag input was already initialized for this element');
|
||||||
}
|
}
|
||||||
$underlyingInput.attr('data-tagged', true);
|
$underlyingInput.attr('data-tagged', true);
|
||||||
$underlyingInput.hide();
|
}
|
||||||
|
|
||||||
var $wrapper = jQuery('<div class="tag-input">');
|
function render() {
|
||||||
var $tagList = jQuery('<ul class="tags">');
|
$underlyingInput.hide();
|
||||||
var $input = jQuery('<input class="tag-real-input" type="text"/>');
|
|
||||||
$wrapper.append($tagList);
|
$wrapper.append($tagList);
|
||||||
$wrapper.append($input);
|
$wrapper.append($input);
|
||||||
$wrapper.insertAfter($underlyingInput);
|
$wrapper.insertAfter($underlyingInput);
|
||||||
|
@ -44,11 +54,11 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
$input.focus();
|
$input.focus();
|
||||||
});
|
});
|
||||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||||
|
$related.insertAfter($wrapper);
|
||||||
|
|
||||||
addTagsFromText($underlyingInput.val());
|
addTagsFromText($underlyingInput.val());
|
||||||
$underlyingInput.val('');
|
$underlyingInput.val('');
|
||||||
|
}
|
||||||
initAutocomplete();
|
|
||||||
|
|
||||||
function initAutocomplete() {
|
function initAutocomplete() {
|
||||||
var autocomplete = new App.Controls.AutoCompleteInput($input);
|
var autocomplete = new App.Controls.AutoCompleteInput($input);
|
||||||
|
@ -131,14 +141,13 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldTags = getTags();
|
if (isTaggedWith(tag)) {
|
||||||
if (_.contains(_.map(oldTags, function(tag) { return tag.toLowerCase(); }), tag.toLowerCase())) {
|
|
||||||
flashTag(tag);
|
flashTag(tag);
|
||||||
} else {
|
} else {
|
||||||
if (typeof(options.beforeTagAdded) === 'function') {
|
if (typeof(options.beforeTagAdded) === 'function') {
|
||||||
options.beforeTagAdded(tag);
|
options.beforeTagAdded(tag);
|
||||||
}
|
}
|
||||||
var newTags = oldTags.slice();
|
var newTags = getTags().slice();
|
||||||
newTags.push(tag);
|
newTags.push(tag);
|
||||||
setTags(newTags);
|
setTags(newTags);
|
||||||
}
|
}
|
||||||
|
@ -155,6 +164,14 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTaggedWith(tag) {
|
||||||
|
var tags = getTags();
|
||||||
|
var tagNames = _.map(tags, function(tag) {
|
||||||
|
return tag.toLowerCase();
|
||||||
|
});
|
||||||
|
return _.contains(tagNames, tag.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
function removeLastTag() {
|
function removeLastTag() {
|
||||||
removeTag(_.last(getTags()));
|
removeTag(_.last(getTags()));
|
||||||
}
|
}
|
||||||
|
@ -170,11 +187,18 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
$underlyingInput.val(newTags.join(' '));
|
$underlyingInput.val(newTags.join(' '));
|
||||||
_.each(newTags, function(tag) {
|
_.each(newTags, function(tag) {
|
||||||
var $elem = jQuery('<li/>');
|
var $elem = jQuery('<li/>');
|
||||||
$elem.text(tag);
|
|
||||||
$elem.attr('data-tag', tag.toLowerCase());
|
$elem.attr('data-tag', tag.toLowerCase());
|
||||||
|
|
||||||
var $deleteButton = jQuery('<a><i class="fa fa-remove"></i></a>');
|
var $tagLink = jQuery('<a class="tag">');
|
||||||
$deleteButton.bind('click', function(e) {
|
$tagLink.text(tag);
|
||||||
|
$tagLink.click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
showRelatedTags(tag);
|
||||||
|
});
|
||||||
|
$elem.append($tagLink);
|
||||||
|
|
||||||
|
var $deleteButton = jQuery('<a class="close"><i class="fa fa-remove"></i></a>');
|
||||||
|
$deleteButton.click(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
removeTag(tag);
|
removeTag(tag);
|
||||||
$input.focus();
|
$input.focus();
|
||||||
|
@ -185,6 +209,45 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showRelatedTags(tag) {
|
||||||
|
if ($related.data('lastTag') === tag) {
|
||||||
|
$related.slideUp('fast');
|
||||||
|
$related.data('lastTag', null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$related.slideUp('fast', function() {
|
||||||
|
$related.data('lastTag', tag);
|
||||||
|
var $list = $related.find('ul');
|
||||||
|
promise.wait(api.get('/tags/' + tag + '/siblings'))
|
||||||
|
.then(function(response) {
|
||||||
|
$list.empty();
|
||||||
|
|
||||||
|
var relatedTags = response.json.data;
|
||||||
|
relatedTags = _.filter(relatedTags, function(tag) {
|
||||||
|
return !isTaggedWith(tag.name);
|
||||||
|
});
|
||||||
|
relatedTags = relatedTags.slice(0, 20);
|
||||||
|
_.each(relatedTags, function(tag) {
|
||||||
|
var $li = jQuery('<li>');
|
||||||
|
var $a = jQuery('<a href="#/posts/query=' + tag.name + '">');
|
||||||
|
$a.text(tag.name);
|
||||||
|
$a.click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
addTag(tag.name);
|
||||||
|
});
|
||||||
|
$li.append($a);
|
||||||
|
$list.append($li);
|
||||||
|
});
|
||||||
|
if (_.size(relatedTags)) {
|
||||||
|
$related.slideDown('fast');
|
||||||
|
}
|
||||||
|
}).fail(function() {
|
||||||
|
console.log(arguments);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getTags() {
|
function getTags() {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue