2016-06-11 15:41:28 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const api = require('../api.js');
|
2016-12-24 20:49:39 +00:00
|
|
|
const misc = require('../util/misc.js');
|
2016-06-17 18:25:44 +00:00
|
|
|
const events = require('../events.js');
|
2016-06-11 15:41:28 +00:00
|
|
|
const views = require('../util/views.js');
|
|
|
|
|
2016-06-17 18:25:44 +00:00
|
|
|
const template = views.getTemplate('comment');
|
|
|
|
const scoreTemplate = views.getTemplate('score');
|
|
|
|
|
|
|
|
class CommentControl extends events.EventTarget {
|
2016-12-24 20:49:39 +00:00
|
|
|
constructor(hostNode, comment, onlyEditing) {
|
2016-06-17 18:25:44 +00:00
|
|
|
super();
|
2016-06-11 15:41:28 +00:00
|
|
|
this._hostNode = hostNode;
|
|
|
|
this._comment = comment;
|
2016-12-24 20:49:39 +00:00
|
|
|
this._onlyEditing = onlyEditing;
|
2016-06-11 15:41:28 +00:00
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
if (comment) {
|
|
|
|
comment.addEventListener(
|
|
|
|
'change', e => this._evtChange(e));
|
|
|
|
comment.addEventListener(
|
|
|
|
'changeScore', e => this._evtChangeScore(e));
|
|
|
|
}
|
2016-06-11 15:41:28 +00:00
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
const isLoggedIn = comment && api.isLoggedIn(comment.user);
|
2016-06-11 15:41:28 +00:00
|
|
|
const infix = isLoggedIn ? 'own' : 'any';
|
2016-06-17 18:25:44 +00:00
|
|
|
views.replaceContent(this._hostNode, template({
|
2016-12-24 20:49:39 +00:00
|
|
|
comment: comment,
|
|
|
|
user: comment ? comment.user : api.user,
|
2016-06-11 15:41:28 +00:00
|
|
|
canViewUsers: api.hasPrivilege('users:view'),
|
|
|
|
canEditComment: api.hasPrivilege(`comments:edit:${infix}`),
|
|
|
|
canDeleteComment: api.hasPrivilege(`comments:delete:${infix}`),
|
2016-12-24 20:49:39 +00:00
|
|
|
onlyEditing: onlyEditing,
|
2016-06-17 18:25:44 +00:00
|
|
|
}));
|
2016-06-11 15:41:28 +00:00
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
if (this._editButtonNodes) {
|
|
|
|
for (let node of this._editButtonNodes) {
|
|
|
|
node.addEventListener('click', e => this._evtEditClick(e));
|
|
|
|
}
|
2016-06-11 15:41:28 +00:00
|
|
|
}
|
2016-06-17 18:25:44 +00:00
|
|
|
if (this._deleteButtonNode) {
|
|
|
|
this._deleteButtonNode.addEventListener(
|
2016-06-11 15:41:28 +00:00
|
|
|
'click', e => this._evtDeleteClick(e));
|
|
|
|
}
|
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
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));
|
|
|
|
}
|
2016-06-17 18:25:44 +00:00
|
|
|
|
|
|
|
this._installScore();
|
2016-12-24 20:49:39 +00:00
|
|
|
if (onlyEditing) {
|
|
|
|
this._selectNav('edit');
|
|
|
|
this._selectTab('edit');
|
|
|
|
} else {
|
|
|
|
this._selectNav('readonly');
|
|
|
|
this._selectTab('preview');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get _formNode() {
|
|
|
|
return this._hostNode.querySelector('form');
|
2016-06-11 15:41:28 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 18:25:44 +00:00
|
|
|
get _scoreContainerNode() {
|
|
|
|
return this._hostNode.querySelector('.score-container');
|
|
|
|
}
|
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
get _editButtonNodes() {
|
|
|
|
return this._hostNode.querySelectorAll('li.edit>a, a.edit');
|
|
|
|
}
|
|
|
|
|
|
|
|
get _previewEditingButtonNode() {
|
|
|
|
return this._hostNode.querySelector('li.preview>a');
|
2016-06-17 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get _deleteButtonNode() {
|
|
|
|
return this._hostNode.querySelector('.delete');
|
|
|
|
}
|
|
|
|
|
|
|
|
get _upvoteButtonNode() {
|
|
|
|
return this._hostNode.querySelector('.upvote');
|
|
|
|
}
|
|
|
|
|
|
|
|
get _downvoteButtonNode() {
|
|
|
|
return this._hostNode.querySelector('.downvote');
|
|
|
|
}
|
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
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');
|
|
|
|
}
|
|
|
|
|
2016-06-17 18:25:44 +00:00
|
|
|
_installScore() {
|
|
|
|
views.replaceContent(
|
|
|
|
this._scoreContainerNode,
|
|
|
|
scoreTemplate({
|
2016-12-24 20:49:39 +00:00
|
|
|
score: this._comment ? this._comment.score : 0,
|
|
|
|
ownScore: this._comment ? this._comment.ownScore : 0,
|
2016-06-17 18:25:44 +00:00
|
|
|
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));
|
|
|
|
}
|
2016-06-11 15:41:28 +00:00
|
|
|
}
|
|
|
|
|
2016-12-24 20:49:39 +00:00
|
|
|
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 16:08:50 +00:00
|
|
|
_evtEditClick(e) {
|
|
|
|
e.preventDefault();
|
2016-12-24 20:49:39 +00:00
|
|
|
this.enterEditMode();
|
2016-06-12 16:08:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 18:25:44 +00:00
|
|
|
_evtScoreClick(e, score) {
|
|
|
|
e.preventDefault();
|
2016-08-23 19:30:53 +00:00
|
|
|
if (!api.hasPrivilege('comments:score')) {
|
|
|
|
return;
|
|
|
|
}
|
2016-06-17 18:25:44 +00:00
|
|
|
this.dispatchEvent(new CustomEvent('score', {
|
|
|
|
detail: {
|
|
|
|
comment: this._comment,
|
|
|
|
score: this._comment.ownScore === score ? 0 : score,
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2016-06-11 15:41:28 +00:00
|
|
|
_evtDeleteClick(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
|
|
|
return;
|
|
|
|
}
|
2016-06-17 18:25:44 +00:00
|
|
|
this.dispatchEvent(new CustomEvent('delete', {
|
|
|
|
detail: {
|
|
|
|
comment: this._comment,
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
_evtChange(e) {
|
2016-12-24 20:49:39 +00:00
|
|
|
this.exitEditMode();
|
2016-06-17 18:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_evtChangeScore(e) {
|
|
|
|
this._installScore();
|
2016-06-11 15:41:28 +00:00
|
|
|
}
|
2016-12-24 20:49:39 +00:00
|
|
|
|
|
|
|
_evtPreviewEditingClick(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
this._contentNode.innerHTML =
|
|
|
|
misc.formatMarkdown(this._textareaNode.value);
|
|
|
|
this._selectTab('edit');
|
|
|
|
this._selectTab('preview');
|
|
|
|
}
|
|
|
|
|
|
|
|
_evtEditClick(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.enterEditMode();
|
|
|
|
}
|
|
|
|
|
|
|
|
_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;
|
|
|
|
}
|
2016-06-11 15:41:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = CommentControl;
|