client/posts: tweak upload appearance and UX
This commit is contained in:
parent
4cb613a5c9
commit
d1bb33ecf0
|
@ -1,5 +1,6 @@
|
||||||
@import colors
|
@import colors
|
||||||
|
$upload-header-background-color = $top-navigation-color
|
||||||
|
$upload-border-color = #DDD
|
||||||
$cancel-button-color = tomato
|
$cancel-button-color = tomato
|
||||||
|
|
||||||
#post-upload
|
#post-upload
|
||||||
|
@ -35,7 +36,7 @@ $cancel-button-color = tomato
|
||||||
.skip-duplicates
|
.skip-duplicates
|
||||||
margin-left: 1em
|
margin-left: 1em
|
||||||
|
|
||||||
.messages
|
form>.messages
|
||||||
margin-top: 1em
|
margin-top: 1em
|
||||||
|
|
||||||
.uploadables-container
|
.uploadables-container
|
||||||
|
@ -43,48 +44,78 @@ $cancel-button-color = tomato
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
li
|
.uploadable-container
|
||||||
|
clear: both
|
||||||
margin: 0 0 1.2em 0
|
margin: 0 0 1.2em 0
|
||||||
|
padding-left: 13em
|
||||||
.uploadable
|
|
||||||
.file
|
|
||||||
margin: 0.3em 0
|
|
||||||
overflow: hidden
|
|
||||||
white-space: nowrap
|
|
||||||
text-align: left
|
|
||||||
text-overflow: ellipsis
|
|
||||||
|
|
||||||
.anonymous
|
|
||||||
margin: 0.3em 0
|
|
||||||
|
|
||||||
.safety
|
|
||||||
margin: 0.3em 0
|
|
||||||
label
|
|
||||||
display: inline-block
|
|
||||||
margin-right: 1em
|
|
||||||
|
|
||||||
.options div
|
|
||||||
display: inline-block
|
|
||||||
margin: 0 1em 0 0
|
|
||||||
|
|
||||||
.thumbnail-wrapper
|
.thumbnail-wrapper
|
||||||
float: left
|
float: left
|
||||||
width: 12.5em
|
width: 12em
|
||||||
height: 7em
|
height: 8em
|
||||||
margin: 0.2em 1em 0 0
|
margin: 0 0 0 -13em
|
||||||
|
|
||||||
.thumbnail
|
.thumbnail
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
||||||
.controls
|
.uploadable
|
||||||
float: right
|
border: 1px solid $upload-border-color
|
||||||
a
|
min-height: 8em
|
||||||
color: $inactive-link-color
|
box-sizing: border-box
|
||||||
margin-left: 0.5em
|
|
||||||
|
|
||||||
div:last-child:after
|
header
|
||||||
display: block
|
line-height: 1.5em
|
||||||
content: ' '
|
padding: 0.25em 1em
|
||||||
height: 1px
|
text-align: left
|
||||||
clear: both
|
background: $upload-header-background-color
|
||||||
|
border-bottom: 1px solid $upload-border-color
|
||||||
|
|
||||||
|
nav
|
||||||
|
&:first-of-type
|
||||||
|
float: left
|
||||||
|
a
|
||||||
|
margin: 0 0.5em 0 0
|
||||||
|
&:last-of-type
|
||||||
|
float: right
|
||||||
|
a
|
||||||
|
margin: 0 0 0 0.5em
|
||||||
|
|
||||||
|
ul
|
||||||
|
list-style-type: none
|
||||||
|
ul, li
|
||||||
|
display: inline-block
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
span.filename
|
||||||
|
padding: 0 0.5em
|
||||||
|
display: block
|
||||||
|
overflow: hidden
|
||||||
|
white-space: nowrap
|
||||||
|
text-overflow: ellipsis
|
||||||
|
|
||||||
|
.body
|
||||||
|
margin: 1em
|
||||||
|
|
||||||
|
.anonymous
|
||||||
|
margin: 0.3em 0
|
||||||
|
|
||||||
|
.safety
|
||||||
|
margin: 0.3em 0
|
||||||
|
label
|
||||||
|
display: inline-block
|
||||||
|
margin-right: 1em
|
||||||
|
|
||||||
|
.options div
|
||||||
|
display: inline-block
|
||||||
|
margin: 0 1em 0 0
|
||||||
|
|
||||||
|
.messages
|
||||||
|
margin-top: 1em
|
||||||
|
.message:last-child
|
||||||
|
margin-bottom: 0
|
||||||
|
|
||||||
|
&:first-child .move-up
|
||||||
|
color: $inactive-link-color
|
||||||
|
&:last-child .move-down
|
||||||
|
color: $inactive-link-color
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
<li class='uploadable'>
|
<li class='uploadable-container'>
|
||||||
<div class='controls'>
|
|
||||||
<a href class='move-up'><i class='fa fa-chevron-up'></i></a>
|
|
||||||
<a href class='move-down'><i class='fa fa-chevron-down'></i></a>
|
|
||||||
<a href class='remove'><i class='fa fa-remove'></i></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class='thumbnail-wrapper'>
|
<div class='thumbnail-wrapper'>
|
||||||
<% if (['image'].includes(ctx.uploadable.type)) { %>
|
<% if (['image'].includes(ctx.uploadable.type)) { %>
|
||||||
|
|
||||||
|
@ -29,40 +23,58 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='file'>
|
<div class='uploadable'>
|
||||||
<strong><%= ctx.uploadable.name %></strong>
|
<header>
|
||||||
</div>
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li><a href class='move-up'><i class='fa fa-chevron-up'></i></a></li>
|
||||||
|
<li><a href class='move-down'><i class='fa fa-chevron-down'></i></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li><a href class='remove'><i class='fa fa-remove'></i></a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<div class='safety'>
|
<span class='filename'><%= ctx.uploadable.name %></span>
|
||||||
<% for (let safety of ['safe', 'sketchy', 'unsafe']) { %>
|
</header>
|
||||||
<%= ctx.makeRadio({
|
|
||||||
name: 'safety-' + ctx.uploadable.key,
|
|
||||||
value: safety,
|
|
||||||
text: safety[0].toUpperCase() + safety.substr(1),
|
|
||||||
selectedValue: ctx.uploadable.safety,
|
|
||||||
}) %>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class='options'>
|
<div class='body'>
|
||||||
<% if (ctx.canUploadAnonymously) { %>
|
<div class='safety'>
|
||||||
<div class='anonymous'>
|
<% for (let safety of ['safe', 'sketchy', 'unsafe']) { %>
|
||||||
<%= ctx.makeCheckbox({
|
<%= ctx.makeRadio({
|
||||||
text: 'Upload anonymously',
|
name: 'safety-' + ctx.uploadable.key,
|
||||||
name: 'anonymous',
|
value: safety,
|
||||||
checked: ctx.uploadable.anonymous,
|
text: safety[0].toUpperCase() + safety.substr(1),
|
||||||
}) %>
|
selectedValue: ctx.uploadable.safety,
|
||||||
|
}) %>
|
||||||
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
|
||||||
|
|
||||||
<% if (['video'].includes(ctx.uploadable.type)) { %>
|
<div class='options'>
|
||||||
<div class='loop-video'>
|
<% if (ctx.canUploadAnonymously) { %>
|
||||||
<%= ctx.makeCheckbox({
|
<div class='anonymous'>
|
||||||
text: 'Loop video',
|
<%= ctx.makeCheckbox({
|
||||||
name: 'loop-video',
|
text: 'Upload anonymously',
|
||||||
checked: ctx.uploadable.flags.includes('loop'),
|
name: 'anonymous',
|
||||||
}) %>
|
checked: ctx.uploadable.anonymous,
|
||||||
|
}) %>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (['video'].includes(ctx.uploadable.type)) { %>
|
||||||
|
<div class='loop-video'>
|
||||||
|
<%= ctx.makeCheckbox({
|
||||||
|
text: 'Loop video',
|
||||||
|
name: 'loop-video',
|
||||||
|
checked: ctx.uploadable.flags.includes('loop'),
|
||||||
|
}) %>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
|
||||||
|
<div class='messages'></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -8,9 +8,13 @@ const Post = require('../models/post.js');
|
||||||
const PostUploadView = require('../views/post_upload_view.js');
|
const PostUploadView = require('../views/post_upload_view.js');
|
||||||
const EmptyView = require('../views/empty_view.js');
|
const EmptyView = require('../views/empty_view.js');
|
||||||
|
|
||||||
|
const genericErrorMessage =
|
||||||
|
'One of the posts needs your attention; ' +
|
||||||
|
'click "resume upload" when you\'re ready.';
|
||||||
|
|
||||||
class PostUploadController {
|
class PostUploadController {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._lastPromise = null;
|
this._lastCancellablePromise = null;
|
||||||
|
|
||||||
if (!api.hasPrivilege('posts:create')) {
|
if (!api.hasPrivilege('posts:create')) {
|
||||||
this._view = new EmptyView();
|
this._view = new EmptyView();
|
||||||
|
@ -22,6 +26,7 @@ class PostUploadController {
|
||||||
topNavigation.setTitle('Upload');
|
topNavigation.setTitle('Upload');
|
||||||
this._view = new PostUploadView({
|
this._view = new PostUploadView({
|
||||||
canUploadAnonymously: api.hasPrivilege('posts:create:anonymous'),
|
canUploadAnonymously: api.hasPrivilege('posts:create:anonymous'),
|
||||||
|
canViewPosts: api.hasPrivilege('posts:view'),
|
||||||
});
|
});
|
||||||
this._view.addEventListener('change', e => this._evtChange(e));
|
this._view.addEventListener('change', e => this._evtChange(e));
|
||||||
this._view.addEventListener('submit', e => this._evtSubmit(e));
|
this._view.addEventListener('submit', e => this._evtSubmit(e));
|
||||||
|
@ -33,13 +38,13 @@ class PostUploadController {
|
||||||
misc.enableExitConfirmation();
|
misc.enableExitConfirmation();
|
||||||
} else {
|
} else {
|
||||||
misc.disableExitConfirmation();
|
misc.disableExitConfirmation();
|
||||||
|
this._view.clearMessages();
|
||||||
}
|
}
|
||||||
this._view.clearMessages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_evtCancel(e) {
|
_evtCancel(e) {
|
||||||
if (this._lastPromise) {
|
if (this._lastCancellablePromise) {
|
||||||
this._lastPromise.abort();
|
this._lastCancellablePromise.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,46 +52,57 @@ class PostUploadController {
|
||||||
this._view.disableForm();
|
this._view.disableForm();
|
||||||
this._view.clearMessages();
|
this._view.clearMessages();
|
||||||
|
|
||||||
e.detail.uploadables.reduce((promise, uploadable) => {
|
e.detail.uploadables.reduce(
|
||||||
return promise.then(() => {
|
(promise, uploadable) =>
|
||||||
let post = new Post();
|
promise.then(() =>
|
||||||
post.safety = uploadable.safety;
|
this._uploadSinglePost(
|
||||||
post.flags = uploadable.flags;
|
uploadable, e.detail.skipDuplicates)),
|
||||||
if (uploadable.url) {
|
Promise.resolve())
|
||||||
post.newContentUrl = uploadable.url;
|
.then(() => {
|
||||||
} else {
|
this._view.clearMessages();
|
||||||
post.newContent = uploadable.file;
|
misc.disableExitConfirmation();
|
||||||
}
|
const ctx = router.show('/posts');
|
||||||
|
ctx.controller.showSuccess('Posts uploaded.');
|
||||||
|
}, errorContext => {
|
||||||
|
if (errorContext.constructor === Array) {
|
||||||
|
const [errorMessage, uploadable] = errorContext;
|
||||||
|
this._view.showError(genericErrorMessage);
|
||||||
|
this._view.showError(errorMessage, uploadable);
|
||||||
|
} else {
|
||||||
|
this._view.showError(errorContext);
|
||||||
|
}
|
||||||
|
this._view.enableForm();
|
||||||
|
return Promise.reject();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let modelPromise = post.save(uploadable.anonymous);
|
_uploadSinglePost(uploadable, skipDuplicates) {
|
||||||
this._lastPromise = modelPromise;
|
let post = new Post();
|
||||||
|
post.safety = uploadable.safety;
|
||||||
|
post.flags = uploadable.flags;
|
||||||
|
|
||||||
return modelPromise
|
if (uploadable.url) {
|
||||||
.then(() => {
|
post.newContentUrl = uploadable.url;
|
||||||
this._view.removeUploadable(uploadable);
|
} else {
|
||||||
return Promise.resolve();
|
post.newContent = uploadable.file;
|
||||||
}).catch(errorMessage => {
|
}
|
||||||
// XXX:
|
|
||||||
// lame, API eats error codes so we need to match
|
|
||||||
// messages instead
|
|
||||||
if (e.detail.skipDuplicates &&
|
|
||||||
errorMessage.match(/already uploaded/)) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
return Promise.reject(errorMessage);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, Promise.resolve())
|
|
||||||
|
|
||||||
|
let savePromise = post.save(uploadable.anonymous)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
misc.disableExitConfirmation();
|
this._view.removeUploadable(uploadable);
|
||||||
const ctx = router.show('/posts');
|
return Promise.resolve();
|
||||||
ctx.controller.showSuccess('Posts uploaded.');
|
|
||||||
}, errorMessage => {
|
}, errorMessage => {
|
||||||
this._view.showError(errorMessage);
|
// XXX:
|
||||||
this._view.enableForm();
|
// lame, API eats error codes so we need to match
|
||||||
return Promise.reject();
|
// messages instead
|
||||||
|
if (skipDuplicates &&
|
||||||
|
errorMessage.match(/already uploaded/)) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject([errorMessage, uploadable, null]);
|
||||||
});
|
});
|
||||||
|
this._lastCancellablePromise = savePromise;
|
||||||
|
return savePromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,25 +267,26 @@ function showMessage(target, message, className) {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
message = 'Unknown message';
|
message = 'Unknown message';
|
||||||
}
|
}
|
||||||
const messagesHolder = target.querySelector('.messages');
|
const messagesHolderNode = target.querySelector('.messages');
|
||||||
if (!messagesHolder) {
|
if (!messagesHolderNode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* TODO: animate this */
|
const textNode = document.createElement('div');
|
||||||
const node = document.createElement('div');
|
textNode.innerHTML = message.replace(/\n/g, '<br/>');
|
||||||
node.innerHTML = message.replace(/\n/g, '<br/>');
|
textNode.classList.add('message');
|
||||||
node.classList.add('message');
|
textNode.classList.add(className);
|
||||||
node.classList.add(className);
|
const wrapperNode = document.createElement('div');
|
||||||
const wrapper = document.createElement('div');
|
wrapperNode.classList.add('message-wrapper');
|
||||||
wrapper.classList.add('message-wrapper');
|
wrapperNode.appendChild(textNode);
|
||||||
wrapper.appendChild(node);
|
messagesHolderNode.appendChild(wrapperNode);
|
||||||
messagesHolder.appendChild(wrapper);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(target, message) {
|
function showError(target, message) {
|
||||||
document.oldTitle = document.title;
|
if (!document.title.startsWith('!')) {
|
||||||
document.title = `! ${document.title}`;
|
document.oldTitle = document.title;
|
||||||
|
document.title = `! ${document.title}`;
|
||||||
|
}
|
||||||
return showMessage(target, misc.formatInlineMarkdown(message), 'error');
|
return showMessage(target, misc.formatInlineMarkdown(message), 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,9 +303,9 @@ function clearMessages(target) {
|
||||||
document.title = document.oldTitle;
|
document.title = document.oldTitle;
|
||||||
document.oldTitle = null;
|
document.oldTitle = null;
|
||||||
}
|
}
|
||||||
const messagesHolder = target.querySelector('.messages');
|
for (let messagesHolderNode of target.querySelectorAll('.messages')) {
|
||||||
/* TODO: animate that */
|
emptyContent(messagesHolderNode);
|
||||||
emptyContent(messagesHolder);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function htmlToDom(html) {
|
function htmlToDom(html) {
|
||||||
|
|
|
@ -20,12 +20,6 @@ function _mimeTypeToPostType(mimeType) {
|
||||||
}[mimeType] || 'unknown';
|
}[mimeType] || 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
function _listen(rootNode, selector, eventType, handler) {
|
|
||||||
for (let node of rootNode.querySelectorAll(selector)) {
|
|
||||||
node.addEventListener(eventType, e => handler(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Uploadable extends events.EventTarget {
|
class Uploadable extends events.EventTarget {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
@ -193,8 +187,16 @@ class PostUploadView extends events.EventTarget {
|
||||||
views.showSuccess(this._hostNode, message);
|
views.showSuccess(this._hostNode, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
showError(message) {
|
showError(message, uploadable) {
|
||||||
views.showError(this._hostNode, message);
|
this._showMessage(views.showError, message, uploadable);
|
||||||
|
}
|
||||||
|
|
||||||
|
showInfo(message, uploadable) {
|
||||||
|
this._showMessage(views.showInfo, message, uploadable);
|
||||||
|
}
|
||||||
|
|
||||||
|
_showMessage(functor, message, uploadable) {
|
||||||
|
functor(uploadable ? uploadable.rowNode : this._hostNode, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
addUploadables(uploadables) {
|
addUploadables(uploadables) {
|
||||||
|
@ -207,9 +209,9 @@ class PostUploadView extends events.EventTarget {
|
||||||
}
|
}
|
||||||
this._uploadables.set(uploadable.key, uploadable);
|
this._uploadables.set(uploadable.key, uploadable);
|
||||||
this._emit('change');
|
this._emit('change');
|
||||||
this._createRowNode(uploadable);
|
this._renderRowNode(uploadable);
|
||||||
uploadable.addEventListener(
|
uploadable.addEventListener(
|
||||||
'finish', e => this._updateRowNode(e.detail.uploadable));
|
'finish', e => this._updateThumbnailNode(e.detail.uploadable));
|
||||||
}
|
}
|
||||||
if (duplicatesFound) {
|
if (duplicatesFound) {
|
||||||
let message = null;
|
let message = null;
|
||||||
|
@ -236,6 +238,7 @@ class PostUploadView extends events.EventTarget {
|
||||||
this._emit('change');
|
this._emit('change');
|
||||||
if (!this._uploadables.size) {
|
if (!this._uploadables.size) {
|
||||||
this._formNode.classList.add('inactive');
|
this._formNode.classList.add('inactive');
|
||||||
|
this._submitButtonNode.value = 'Upload all';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,9 +257,24 @@ class PostUploadView extends events.EventTarget {
|
||||||
|
|
||||||
_evtFormSubmit(e) {
|
_evtFormSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
for (let uploadable of this._uploadables.values()) {
|
||||||
|
this._updateUploadableFromDom(uploadable);
|
||||||
|
}
|
||||||
|
this._submitButtonNode.value = 'Resume upload';
|
||||||
this._emit('submit');
|
this._emit('submit');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateUploadableFromDom(uploadable) {
|
||||||
|
const rowNode = uploadable.rowNode;
|
||||||
|
uploadable.safety =
|
||||||
|
rowNode.querySelector('.safety input:checked').value;
|
||||||
|
uploadable.anonymous =
|
||||||
|
rowNode.querySelector('.anonymous input').checked;
|
||||||
|
if (rowNode.querySelector('.loop-video input:checked')) {
|
||||||
|
uploadable.flags.push('loop');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_evtRemoveClick(e, uploadable) {
|
_evtRemoveClick(e, uploadable) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this._uploading) {
|
if (this._uploading) {
|
||||||
|
@ -265,48 +283,23 @@ class PostUploadView extends events.EventTarget {
|
||||||
this.removeUploadable(uploadable);
|
this.removeUploadable(uploadable);
|
||||||
}
|
}
|
||||||
|
|
||||||
_evtMoveUpClick(e, uploadable) {
|
_evtMoveClick(e, uploadable, delta) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this._uploading) {
|
if (this._uploading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let sortedUploadables = this._getSortedUploadables();
|
let sortedUploadables = this._getSortedUploadables();
|
||||||
if (uploadable.order > 0) {
|
if ((uploadable.order + delta).between(-1, sortedUploadables.length)) {
|
||||||
uploadable.order--;
|
uploadable.order += delta;
|
||||||
const prevUploadable = sortedUploadables[uploadable.order];
|
const otherUploadable = sortedUploadables[uploadable.order];
|
||||||
prevUploadable.order++;
|
otherUploadable.order -= delta;
|
||||||
uploadable.rowNode.parentNode.insertBefore(
|
if (delta === 1) {
|
||||||
uploadable.rowNode, prevUploadable.rowNode);
|
uploadable.rowNode.parentNode.insertBefore(
|
||||||
}
|
otherUploadable.rowNode, uploadable.rowNode);
|
||||||
}
|
} else {
|
||||||
|
uploadable.rowNode.parentNode.insertBefore(
|
||||||
_evtMoveDownClick(e, uploadable) {
|
uploadable.rowNode, otherUploadable.rowNode);
|
||||||
e.preventDefault();
|
}
|
||||||
if (this._uploading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let sortedUploadables = this._getSortedUploadables();
|
|
||||||
if (uploadable.order + 1 < sortedUploadables.length) {
|
|
||||||
uploadable.order++;
|
|
||||||
const nextUploadable = sortedUploadables[uploadable.order];
|
|
||||||
nextUploadable.order--;
|
|
||||||
uploadable.rowNode.parentNode.insertBefore(
|
|
||||||
nextUploadable.rowNode, uploadable.rowNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_evtSafetyRadioboxChange(e, uploadable) {
|
|
||||||
uploadable.safety = e.target.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_evtAnonymityCheckboxChange(e, uploadable) {
|
|
||||||
uploadable.anonymous = e.target.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
_evtLoopVideoCheckboxChange(e, uploadable) {
|
|
||||||
uploadable.flags = uploadable.flags.filter(f => f !== 'loop');
|
|
||||||
if (e.target.checked) {
|
|
||||||
uploadable.flags.push('loop');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,28 +326,27 @@ class PostUploadView extends events.EventTarget {
|
||||||
}}));
|
}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_createRowNode(uploadable) {
|
_renderRowNode(uploadable) {
|
||||||
const rowNode = rowTemplate(Object.assign(
|
const rowNode = rowTemplate(Object.assign(
|
||||||
{}, this._ctx, {uploadable: uploadable}));
|
{}, this._ctx, {uploadable: uploadable}));
|
||||||
this._listNode.appendChild(rowNode);
|
if (uploadable.rowNode) {
|
||||||
|
uploadable.rowNode.parentNode.replaceChild(
|
||||||
|
rowNode, uploadable.rowNode);
|
||||||
|
} else {
|
||||||
|
this._listNode.appendChild(rowNode);
|
||||||
|
}
|
||||||
|
|
||||||
_listen(rowNode, '.safety input', 'change',
|
|
||||||
e => this._evtSafetyRadioboxChange(e, uploadable));
|
|
||||||
_listen(rowNode, '.anonymous input', 'change',
|
|
||||||
e => this._evtAnonymityCheckboxChange(e, uploadable));
|
|
||||||
_listen(rowNode, '.loop-video input', 'change',
|
|
||||||
e => this._evtLoopVideoCheckboxChange(e, uploadable));
|
|
||||||
|
|
||||||
_listen(rowNode, 'a.remove', 'click',
|
|
||||||
e => this._evtRemoveClick(e, uploadable));
|
|
||||||
_listen(rowNode, 'a.move-up', 'click',
|
|
||||||
e => this._evtMoveUpClick(e, uploadable));
|
|
||||||
_listen(rowNode, 'a.move-down', 'click',
|
|
||||||
e => this._evtMoveDownClick(e, uploadable));
|
|
||||||
uploadable.rowNode = rowNode;
|
uploadable.rowNode = rowNode;
|
||||||
|
|
||||||
|
rowNode.querySelector('a.remove').addEventListener('click',
|
||||||
|
e => this._evtRemoveClick(e, uploadable));
|
||||||
|
rowNode.querySelector('a.move-up').addEventListener('click',
|
||||||
|
e => this._evtMoveClick(e, uploadable, -1));
|
||||||
|
rowNode.querySelector('a.move-down').addEventListener('click',
|
||||||
|
e => this._evtMoveClick(e, uploadable, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateRowNode(uploadable) {
|
_updateThumbnailNode(uploadable) {
|
||||||
const rowNode = rowTemplate(Object.assign(
|
const rowNode = rowTemplate(Object.assign(
|
||||||
{}, this._ctx, {uploadable: uploadable}));
|
{}, this._ctx, {uploadable: uploadable}));
|
||||||
views.replaceContent(
|
views.replaceContent(
|
||||||
|
|
Loading…
Reference in New Issue