'use strict'; const api = require('../api.js'); const misc = require('../util/misc.js'); const views = require('../util/views.js'); class CommentControl { constructor(hostNode, comment) { this._hostNode = hostNode; this._comment = comment; this._template = views.getTemplate('comment'); this._scoreTemplate = views.getTemplate('score'); this.install(); } install() { const isLoggedIn = api.isLoggedIn(this._comment.user); const infix = isLoggedIn ? 'own' : 'any'; const sourceNode = this._template({ comment: this._comment, canViewUsers: api.hasPrivilege('users:view'), canEditComment: api.hasPrivilege(`comments:edit:${infix}`), canDeleteComment: api.hasPrivilege(`comments:delete:${infix}`), }); views.showView( sourceNode.querySelector('.score-container'), this._scoreTemplate({ score: this._comment.score, ownScore: this._comment.ownScore, canScore: api.hasPrivilege('comments:score'), })); const editButton = sourceNode.querySelector('.edit'); const deleteButton = sourceNode.querySelector('.delete'); const upvoteButton = sourceNode.querySelector('.upvote'); const downvoteButton = sourceNode.querySelector('.downvote'); const previewTabButton = sourceNode.querySelector('.buttons .preview'); const editTabButton = sourceNode.querySelector('.buttons .edit'); const formNode = sourceNode.querySelector('form'); const cancelButton = sourceNode.querySelector('.cancel'); const textareaNode = sourceNode.querySelector('form textarea'); if (editButton) { editButton.addEventListener( 'click', e => this._evtEditClick(e)); } if (deleteButton) { deleteButton.addEventListener( 'click', e => this._evtDeleteClick(e)); } if (upvoteButton) { upvoteButton.addEventListener( 'click', e => this._evtScoreClick( e, () => this._comment.ownScore === 1 ? 0 : 1)); } if (downvoteButton) { downvoteButton.addEventListener( 'click', e => this._evtScoreClick( e, () => this._comment.ownScore === -1 ? 0 : -1)); } previewTabButton.addEventListener( 'click', e => this._evtPreviewClick(e)); editTabButton.addEventListener( 'click', e => this._evtEditClick(e)); formNode.addEventListener('submit', e => this._evtSaveClick(e)); cancelButton.addEventListener('click', e => this._evtCancelClick(e)); for (let event of ['cut', 'paste', 'drop', 'keydown']) { textareaNode.addEventListener(event, e => { window.setTimeout(() => this._growTextArea(), 0); }); } textareaNode.addEventListener('change', e => { this._growTextArea(); }); views.showView(this._hostNode, sourceNode); } _evtScoreClick(e, scoreGetter) { e.preventDefault(); api.put( '/comment/' + this._comment.id + '/score', {score: scoreGetter()}) .then( response => { this._comment.score = parseInt(response.score); this._comment.ownScore = parseInt(response.ownScore); this.install(); }, response => { window.alert(response.description); }); } _evtDeleteClick(e) { e.preventDefault(); if (!window.confirm('Are you sure you want to delete this comment?')) { return; } api.delete('/comment/' + this._comment.id) .then(response => { this._hostNode.parentNode.removeChild(this._hostNode); }, response => { window.alert(response.description); }); } _evtSaveClick(e) { e.preventDefault(); api.put('/comment/' + this._comment.id, { text: this._hostNode.querySelector('.edit.tab textarea').value, }).then(response => { this._comment = response; this.install(); }, response => { this._showError(response.description); }); } _evtPreviewClick(e) { e.preventDefault(); this._hostNode.querySelector('.preview.tab .content').innerHTML = misc.formatMarkdown( this._hostNode.querySelector('.edit.tab textarea').value); this._freezeTabHeights(); this._selectTab('preview'); } _evtEditClick(e) { e.preventDefault(); this._freezeTabHeights(); this._enterEditMode(); this._selectTab('edit'); this._growTextArea(); } _evtCancelClick(e) { e.preventDefault(); this._exitEditMode(); this._hostNode.querySelector('.edit.tab textarea').value = this._comment.text; } _enterEditMode() { this._hostNode.querySelector('.comment').classList.add('editing'); misc.enableExitConfirmation(); } _exitEditMode() { this._hostNode.querySelector('.comment').classList.remove('editing'); this._hostNode.querySelector('.tabs-wrapper').style.minHeight = null; misc.disableExitConfirmation(); views.clearMessages(this._hostNode); } _selectTab(tabName) { this._freezeTabHeights(); for (let tab of this._hostNode.querySelectorAll('.tab, .buttons li')) { tab.classList.toggle('active', tab.classList.contains(tabName)); } } _freezeTabHeights() { const tabsNode = this._hostNode.querySelector('.tabs-wrapper'); const tabsHeight = tabsNode.getBoundingClientRect().height; tabsNode.style.minHeight = tabsHeight + 'px'; } _growTextArea() { const previewNode = this._hostNode.querySelector('.content'); const textareaNode = this._hostNode.querySelector('textarea'); textareaNode.style.height = textareaNode.scrollHeight + 'px'; } _showError(message) { views.showError(this._hostNode, message); } }; module.exports = CommentControl;