mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
43334b33e1 | |||
839e97b1e2 | |||
8a33b9581d | |||
7067d8e13d | |||
5769034223 | |||
c0a5c800e0 | |||
b70231bd7e | |||
bc757dd883 | |||
924592675c | |||
a3aea27a13 | |||
3c54671aeb | |||
d8df51f0c0 | |||
b693a5f4b3 | |||
303f91e15c | |||
c350c47195 | |||
24ce67b4ff |
@ -24,6 +24,10 @@ h3 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#middle {
|
||||
padding: 0 2em;
|
||||
position: relative;
|
||||
|
@ -18,10 +18,12 @@
|
||||
#home .post .left {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
#home .post .right {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
#home .post-footer,
|
||||
@ -35,5 +37,7 @@
|
||||
|
||||
#home .version {
|
||||
opacity: .4;
|
||||
font-size: 12px;
|
||||
}
|
||||
#home .subheader, #home .post-footer {
|
||||
font-size: 85%;
|
||||
}
|
||||
|
@ -157,12 +157,17 @@
|
||||
|
||||
#post-view #post-edit-target {
|
||||
padding: 1em;
|
||||
width: 50%;
|
||||
min-width: 30em;
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0 0 1em 0.5em rgba(255, 255, 255, 0.8);
|
||||
z-index: 2;
|
||||
display: none;
|
||||
}
|
||||
#post-edit-target .form-wrapper {
|
||||
min-width: 100%;
|
||||
}
|
||||
#post-view>* {
|
||||
z-index: -1;
|
||||
}
|
||||
@ -224,6 +229,7 @@
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
font-size: 12pt;
|
||||
}
|
||||
.post-note .text-wrapper {
|
||||
position: absolute;
|
||||
|
@ -17,12 +17,14 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
maxResults: 15,
|
||||
minLengthToArbitrarySearch: 3,
|
||||
onApply: null,
|
||||
onRender: null,
|
||||
additionalFilter: null,
|
||||
};
|
||||
var showTimeout = null;
|
||||
var cachedSource = null;
|
||||
var results = [];
|
||||
var activeResult = -1;
|
||||
var monitorInputHidingInterval = null;
|
||||
|
||||
if ($input.length === 0) {
|
||||
throw new Error('Input element was not found');
|
||||
@ -133,6 +135,7 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
|
||||
function hide() {
|
||||
$div.hide();
|
||||
window.clearInterval(monitorInputHidingInterval);
|
||||
}
|
||||
|
||||
function selectPrevious() {
|
||||
@ -222,12 +225,16 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
});
|
||||
$list.append($listItem);
|
||||
});
|
||||
if (options.onRender) {
|
||||
options.onRender($list);
|
||||
}
|
||||
refreshActiveResult();
|
||||
$div.css({
|
||||
left: ($input.offset().left) + 'px',
|
||||
top: ($input.offset().top + $input.outerHeight() - 2) + 'px',
|
||||
});
|
||||
$div.show();
|
||||
monitorInputHiding();
|
||||
}
|
||||
|
||||
function refreshActiveResult() {
|
||||
@ -237,5 +244,13 @@ App.Controls.AutoCompleteInput = function($input) {
|
||||
}
|
||||
}
|
||||
|
||||
function monitorInputHiding() {
|
||||
monitorInputHidingInterval = window.setInterval(function() {
|
||||
if (!$input.is(':visible')) {
|
||||
hide();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
@ -14,6 +14,14 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var tagConfirmKeys = [KEY_RETURN, KEY_SPACE];
|
||||
var inputConfirmKeys = [KEY_RETURN];
|
||||
|
||||
var SOURCE_INITIAL_TEXT = 1;
|
||||
var SOURCE_AUTOCOMPLETION = 2;
|
||||
var SOURCE_PASTE = 3;
|
||||
var SOURCE_IMPLICATIONS = 4;
|
||||
var SOURCE_INPUT_BLUR = 5;
|
||||
var SOURCE_INPUT_ENTER = 6;
|
||||
var SOURCE_SUGGESTIONS = 7;
|
||||
|
||||
var tags = [];
|
||||
var options = {
|
||||
beforeTagAdded: null,
|
||||
@ -56,10 +64,10 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$input.focus();
|
||||
});
|
||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||
$suggestions.insertAfter($wrapper);
|
||||
$siblings.insertAfter($wrapper);
|
||||
$suggestions.insertAfter($wrapper);
|
||||
|
||||
processText($underlyingInput.val(), addTagDirectly);
|
||||
processText($underlyingInput.val(), SOURCE_INITIAL_TEXT);
|
||||
|
||||
$underlyingInput.val('');
|
||||
}
|
||||
@ -67,7 +75,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
function initAutoComplete() {
|
||||
var autoComplete = new App.Controls.AutoCompleteInput($input);
|
||||
autoComplete.onApply = function(text) {
|
||||
processText(text, addTag);
|
||||
processText(text, SOURCE_AUTOCOMPLETION);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.additionalFilter = function(results) {
|
||||
@ -75,6 +83,14 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return !_.contains(getTags(), resultItem[0]);
|
||||
});
|
||||
};
|
||||
autoComplete.onRender = function($list) {
|
||||
$list.find('li').each(function() {
|
||||
var $li = jQuery(this);
|
||||
if (isTaggedWith($li.attr('data-key'))) {
|
||||
$li.css('opacity', '0.5');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$input.bind('focus', function(e) {
|
||||
@ -83,7 +99,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$input.bind('blur', function(e) {
|
||||
$wrapper.removeClass('focused');
|
||||
var tagName = $input.val();
|
||||
addTag(tagName);
|
||||
addTag(tagName, SOURCE_INPUT_BLUR);
|
||||
$input.val('');
|
||||
});
|
||||
|
||||
@ -101,7 +117,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
processTextWithoutLast(pastedText, addTag);
|
||||
processTextWithoutLast(pastedText, SOURCE_PASTE);
|
||||
});
|
||||
|
||||
$input.bind('keydown', function(e) {
|
||||
@ -114,7 +130,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var tagName = $input.val();
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
addTag(tagName);
|
||||
addTag(tagName, SOURCE_INPUT_ENTER);
|
||||
} else if (e.which === KEY_BACKSPACE && jQuery(this).val().length === 0) {
|
||||
e.preventDefault();
|
||||
removeLastTag();
|
||||
@ -127,19 +143,19 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
});
|
||||
}
|
||||
|
||||
function processText(text, callback) {
|
||||
function processText(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
_.map(tagNamesToAdd, function(tagName) { callback(tagName); });
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
}
|
||||
|
||||
function processTextWithoutLast(text, callback) {
|
||||
function processTextWithoutLast(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
var lastTagName = tagNamesToAdd.pop();
|
||||
_.map(tagNamesToAdd, function(tagName) { callback(tagName); });
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
$input.val(lastTagName);
|
||||
}
|
||||
|
||||
function addTag(tagName) {
|
||||
function addTag(tagName, source) {
|
||||
tagName = tagName.trim();
|
||||
if (tagName.length === 0) {
|
||||
return;
|
||||
@ -157,41 +173,55 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
if (isTaggedWith(tagName)) {
|
||||
flashTagRed(tagName);
|
||||
} else {
|
||||
beforeTagAdded(tagName);
|
||||
beforeTagAdded(tagName, source);
|
||||
|
||||
var exportedTag = getExportedTag(tagName);
|
||||
if (!exportedTag || !exportedTag.banned) {
|
||||
addTagDirectly(tagName);
|
||||
}
|
||||
|
||||
afterTagAdded(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function addTagDirectly(tagName) {
|
||||
tags.push(tagName);
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
}
|
||||
|
||||
function beforeTagAdded(tagName) {
|
||||
afterTagAdded(tagName, source);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeTagRemoved(tagName) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function afterTagRemoved(tagName) {
|
||||
refreshShownSiblings();
|
||||
}
|
||||
|
||||
function beforeTagAdded(tagName, source) {
|
||||
if (typeof(options.beforeTagAdded) === 'function') {
|
||||
options.beforeTagAdded(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function afterTagAdded(tagName) {
|
||||
function afterTagAdded(tagName, source) {
|
||||
if (source === SOURCE_IMPLICATIONS) {
|
||||
flashTagYellow(tagName);
|
||||
} else if (source !== SOURCE_INITIAL_TEXT) {
|
||||
var tag = getExportedTag(tagName);
|
||||
if (tag) {
|
||||
_.each(tag.implications, function(impliedTagName) {
|
||||
addTag(impliedTagName);
|
||||
flashTagYellow(impliedTagName);
|
||||
if (!isTaggedWith(impliedTagName)) {
|
||||
addTag(impliedTagName, SOURCE_IMPLICATIONS);
|
||||
}
|
||||
});
|
||||
showOrHideSuggestions(tag.suggestions);
|
||||
if (source !== SOURCE_IMPLICATIONS && source !== SOURCE_SUGGESTIONS) {
|
||||
showOrHideSuggestions(tagName);
|
||||
refreshShownSiblings();
|
||||
}
|
||||
} else {
|
||||
flashTagGreen(tagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getExportedTag(tagName) {
|
||||
return _.first(_.filter(
|
||||
@ -205,10 +235,9 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
var oldTagNames = getTags();
|
||||
var newTagNames = _.without(oldTagNames, tagName);
|
||||
if (newTagNames.length !== oldTagNames.length) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
beforeTagRemoved(tagName);
|
||||
setTags(newTagNames);
|
||||
afterTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +291,8 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$tagLink.text(tagName);
|
||||
$tagLink.click(function(e) {
|
||||
e.preventDefault();
|
||||
showOrHideTagSiblings(tagName);
|
||||
showOrHideSiblings(tagName);
|
||||
showOrHideSuggestions(tagName);
|
||||
});
|
||||
$elem.append($tagLink);
|
||||
|
||||
@ -276,19 +306,13 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
return $elem;
|
||||
}
|
||||
|
||||
function showOrHideSuggestions(suggestedTagNames) {
|
||||
if (_.size(suggestedTagNames) === 0) {
|
||||
return;
|
||||
function showOrHideSuggestions(tagName) {
|
||||
var tag = getExportedTag(tagName);
|
||||
var suggestions = tag ? tag.suggestions : [];
|
||||
updateSuggestions($suggestions, suggestions);
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($suggestions.find('ul'), suggestions);
|
||||
$suggestions.slideDown('fast');
|
||||
}
|
||||
}
|
||||
|
||||
function showOrHideTagSiblings(tagName) {
|
||||
function showOrHideSiblings(tagName) {
|
||||
if ($siblings.data('lastTag') === tagName && $siblings.is(':visible')) {
|
||||
$siblings.slideUp('fast');
|
||||
$siblings.data('lastTag', null);
|
||||
@ -298,22 +322,23 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
promise.wait(getSiblings(tagName), promise.make(function(resolve, reject) {
|
||||
$siblings.slideUp('fast', resolve);
|
||||
})).then(function(siblings) {
|
||||
siblings = _.pluck(siblings, 'name');
|
||||
$siblings.data('lastTag', tagName);
|
||||
|
||||
if (!_.size(siblings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(_.pluck(siblings, 'name'));
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($siblings.find('ul'), suggestions);
|
||||
$siblings.slideDown('fast');
|
||||
}
|
||||
$siblings.data('siblings', siblings);
|
||||
updateSuggestions($siblings, siblings);
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function refreshShownSiblings() {
|
||||
updateSuggestions($siblings, $siblings.data('siblings'));
|
||||
}
|
||||
|
||||
function updateSuggestions($target, suggestedTagNames) {
|
||||
function filterSuggestions(sourceTagNames) {
|
||||
if (!sourceTagNames) {
|
||||
return [];
|
||||
}
|
||||
var tagNames = _.filter(sourceTagNames.slice(), function(tagName) {
|
||||
return !isTaggedWith(tagName);
|
||||
});
|
||||
@ -329,7 +354,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
$a.text(tagName);
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
addTag(tagName);
|
||||
addTag(tagName, SOURCE_SUGGESTIONS);
|
||||
$li.fadeOut('fast', function() {
|
||||
$li.remove();
|
||||
if ($list.children().length === 0) {
|
||||
@ -342,6 +367,15 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
});
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($target.find('ul'), suggestions);
|
||||
$target.slideDown('fast');
|
||||
} else {
|
||||
$target.slideUp('fast');
|
||||
}
|
||||
}
|
||||
|
||||
function getSiblings(tagName) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get('/tags/' + tagName + '/siblings'))
|
||||
@ -364,6 +398,7 @@ App.Controls.TagInput = function($underlyingInput) {
|
||||
function hideSuggestions() {
|
||||
$siblings.hide();
|
||||
$suggestions.hide();
|
||||
$siblings.data('siblings', []);
|
||||
}
|
||||
|
||||
_.extend(options, {
|
||||
|
@ -10,8 +10,6 @@ App.Presenters.TagListPresenter = function(
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var KEY_RETURN = 13;
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var templates = {};
|
||||
@ -78,8 +76,8 @@ App.Presenters.TagListPresenter = function(
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
$searchInput.keydown(searchInputKeyPressed);
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
softRender();
|
||||
}
|
||||
|
||||
@ -88,13 +86,6 @@ App.Presenters.TagListPresenter = function(
|
||||
}
|
||||
|
||||
|
||||
function searchInputKeyPressed(e) {
|
||||
if (e.which !== KEY_RETURN) {
|
||||
return;
|
||||
}
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
|
@ -128,6 +128,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.put('/tags/' + tag.name, formData))
|
||||
.then(function(response) {
|
||||
router.navigateInplace('#/tag/' + response.json.name);
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -140,6 +141,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.delete('/tags/' + tag.name))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -151,6 +153,7 @@ App.Presenters.TagPresenter = function(
|
||||
promise.wait(api.put('/tags/' + tag.name + '/merge', {targetTag: targetTag}))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
@ -183,4 +186,16 @@ App.Presenters.TagPresenter = function(
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('tagPresenter', ['_', 'jQuery', 'util', 'promise', 'auth', 'api', 'tagList', 'router', 'keyboard', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.TagPresenter);
|
||||
App.DI.register('tagPresenter', [
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'auth',
|
||||
'api',
|
||||
'tagList',
|
||||
'router',
|
||||
'keyboard',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.TagPresenter);
|
||||
|
@ -210,6 +210,8 @@ App.Util.Misc = function(_, jQuery, marked, promise) {
|
||||
text = text.replace(/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, '<a href="#/posts/query=$1"><code>$1</code></a>');
|
||||
//spoilers
|
||||
text = text.replace(/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, '<span class="spoiler">$1</span>');
|
||||
//[small]
|
||||
text = text.replace(/\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig, '<small>$1</small>');
|
||||
//strike-through
|
||||
text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1<del>$3</del>');
|
||||
text = text.replace(/\\~/g, '~');
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div id="home">
|
||||
<h1><%= title %></h1>
|
||||
<p>
|
||||
<small>Serving <%= globals.postCount || 0 %> posts (<%= formatFileSize(globals.postSize || 0) %>)</small>
|
||||
<p class="subheader">
|
||||
Serving <%= globals.postCount || 0 %> posts (<%= formatFileSize(globals.postSize || 0) %>)
|
||||
</p>
|
||||
|
||||
<% if (post && post.id) { %>
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
<div class="post-footer">
|
||||
|
||||
<small class="left">
|
||||
<span class="left">
|
||||
<% var showLink = canViewPosts %>
|
||||
|
||||
<% if (showLink) { %>
|
||||
@ -26,9 +26,9 @@
|
||||
|
||||
uploaded
|
||||
<%= formatRelativeTime(post.uploadTime) %>
|
||||
</small>
|
||||
</span>
|
||||
|
||||
<small class="right">
|
||||
<span class="right">
|
||||
featured
|
||||
<%= formatRelativeTime(post.lastFeatureTime) %>
|
||||
by
|
||||
@ -48,7 +48,7 @@
|
||||
<% if (showLink) { %>
|
||||
</a>
|
||||
<% } %>
|
||||
</small>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -109,10 +109,13 @@ class PostService
|
||||
{
|
||||
$formData->validate($this->validator);
|
||||
|
||||
if ($formData->anonymous)
|
||||
$this->authService->loginAnonymous();
|
||||
|
||||
$post = new Post();
|
||||
$post->setUploadTime($this->timeService->getCurrentTime());
|
||||
$post->setLastEditTime($this->timeService->getCurrentTime());
|
||||
$post->setUser($formData->anonymous ? null : $this->authService->getLoggedInUser());
|
||||
$post->setUser($this->authService->getLoggedInUser());
|
||||
$post->setOriginalFileName($formData->contentFileName);
|
||||
$post->setName($this->getUniqueRandomPostName());
|
||||
|
||||
|
Reference in New Issue
Block a user