szurubooru/client/js/controls/comment_control.js

261 lines
7.1 KiB
JavaScript
Raw Normal View History

'use strict';
const api = require('../api.js');
const misc = require('../util/misc.js');
const events = require('../events.js');
const views = require('../util/views.js');
const template = views.getTemplate('comment');
const scoreTemplate = views.getTemplate('score');
class CommentControl extends events.EventTarget {
constructor(hostNode, comment, onlyEditing) {
super();
this._hostNode = hostNode;
this._comment = comment;
this._onlyEditing = onlyEditing;
if (comment) {
comment.addEventListener(
'change', e => this._evtChange(e));
comment.addEventListener(
'changeScore', e => this._evtChangeScore(e));
}
const isLoggedIn = comment && api.isLoggedIn(comment.user);
const infix = isLoggedIn ? 'own' : 'any';
views.replaceContent(this._hostNode, template({
comment: comment,
user: comment ? comment.user : api.user,
canViewUsers: api.hasPrivilege('users:view'),
canEditComment: api.hasPrivilege(`comments:edit:${infix}`),
canDeleteComment: api.hasPrivilege(`comments:delete:${infix}`),
onlyEditing: onlyEditing,
}));
if (this._editButtonNodes) {
for (let node of this._editButtonNodes) {
node.addEventListener('click', e => this._evtEditClick(e));
}
}
if (this._deleteButtonNode) {
this._deleteButtonNode.addEventListener(
'click', e => this._evtDeleteClick(e));
}
if (this._previewEditingButtonNode) {
this._previewEditingButtonNode.addEventListener(
'click', e => this._evtPreviewEditingClick(e));
}
if (this._saveChangesButtonNode) {
this._saveChangesButtonNode.addEventListener(
'click', e => this._evtSaveChangesClick(e));
}
if (this._cancelEditingButtonNode) {
this._cancelEditingButtonNode.addEventListener(
'click', e => this._evtCancelEditingClick(e));
}
this._installScore();
if (onlyEditing) {
this._selectNav('edit');
this._selectTab('edit');
} else {
this._selectNav('readonly');
this._selectTab('preview');
}
}
get _formNode() {
return this._hostNode.querySelector('form');
}
get _scoreContainerNode() {
return this._hostNode.querySelector('.score-container');
}
get _editButtonNodes() {
return this._hostNode.querySelectorAll('li.edit>a, a.edit');
}
get _previewEditingButtonNode() {
return this._hostNode.querySelector('li.preview>a');
}
get _deleteButtonNode() {
return this._hostNode.querySelector('.delete');
}
get _upvoteButtonNode() {
return this._hostNode.querySelector('.upvote');
}
get _downvoteButtonNode() {
return this._hostNode.querySelector('.downvote');
}
get _saveChangesButtonNode() {
return this._hostNode.querySelector('.save-changes');
}
get _cancelEditingButtonNode() {
return this._hostNode.querySelector('.cancel-editing');
}
get _textareaNode() {
return this._hostNode.querySelector('.tab.edit textarea');
}
get _contentNode() {
return this._hostNode.querySelector('.tab.preview .comment-content');
}
get _heightKeeperNode() {
return this._hostNode.querySelector('.keep-height');
}
_installScore() {
views.replaceContent(
this._scoreContainerNode,
scoreTemplate({
score: this._comment ? this._comment.score : 0,
ownScore: this._comment ? this._comment.ownScore : 0,
canScore: api.hasPrivilege('comments:score'),
}));
if (this._upvoteButtonNode) {
this._upvoteButtonNode.addEventListener(
'click', e => this._evtScoreClick(e, 1));
}
if (this._downvoteButtonNode) {
this._downvoteButtonNode.addEventListener(
'click', e => this._evtScoreClick(e, -1));
}
}
enterEditMode() {
this._selectNav('edit');
this._selectTab('edit');
}
exitEditMode() {
if (this._onlyEditing) {
this._selectNav('edit');
this._selectTab('edit');
this._setText('');
} else {
this._selectNav('readonly');
this._selectTab('preview');
this._setText(this._comment.text);
}
this._forgetHeight();
views.clearMessages(this._hostNode);
}
enableForm() {
views.enableForm(this._formNode);
}
disableForm() {
views.disableForm(this._formNode);
}
showError(message) {
views.showError(this._hostNode, message);
}
2016-06-12 18:08:50 +02:00
_evtEditClick(e) {
e.preventDefault();
this.enterEditMode();
2016-06-12 18:08:50 +02:00
}
_evtScoreClick(e, score) {
e.preventDefault();
if (!api.hasPrivilege('comments:score')) {
return;
}
this.dispatchEvent(new CustomEvent('score', {
detail: {
comment: this._comment,
score: this._comment.ownScore === score ? 0 : score,
},
}));
}
_evtDeleteClick(e) {
e.preventDefault();
if (!window.confirm('Are you sure you want to delete this comment?')) {
return;
}
this.dispatchEvent(new CustomEvent('delete', {
detail: {
comment: this._comment,
},
}));
}
_evtChange(e) {
this.exitEditMode();
}
_evtChangeScore(e) {
this._installScore();
}
_evtPreviewEditingClick(e) {
e.preventDefault();
this._contentNode.innerHTML =
misc.formatMarkdown(this._textareaNode.value);
this._selectTab('edit');
this._selectTab('preview');
}
_evtSaveChangesClick(e) {
e.preventDefault();
this.dispatchEvent(new CustomEvent('submit', {
detail: {
target: this,
comment: this._comment,
text: this._textareaNode.value,
},
}));
}
_evtCancelEditingClick(e) {
e.preventDefault();
this.exitEditMode();
}
_setText(text) {
this._textareaNode.value = text;
this._contentNode.innerHTML = misc.formatMarkdown(text);
}
_selectNav(modeName) {
for (let node of this._hostNode.querySelectorAll('nav')) {
node.classList.toggle('active', node.classList.contains(modeName));
}
}
_selectTab(tabName) {
this._ensureHeight();
for (let node of this._hostNode.querySelectorAll('.tab, .tabs li')) {
node.classList.toggle('active', node.classList.contains(tabName));
}
}
_ensureHeight() {
this._heightKeeperNode.style.minHeight =
this._heightKeeperNode.getBoundingClientRect().height + 'px';
}
_forgetHeight() {
this._heightKeeperNode.style.minHeight = null;
}
2020-06-04 20:09:35 +02:00
}
module.exports = CommentControl;