Added tag siblings to frontend

This commit is contained in:
Marcin Kurczewski 2014-10-11 22:00:22 +02:00
parent 6015199559
commit 6ca08e5532
3 changed files with 120 additions and 36 deletions

1
TODO
View file

@ -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

View file

@ -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 {

View file

@ -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;
} }