// More comments system updates.
This commit is contained in:
parent
b4abea015a
commit
d3531fc2c1
5 changed files with 159 additions and 150 deletions
|
@ -21,6 +21,12 @@ function commentsFreeLock(): void
|
|||
globalCommentLock = false;
|
||||
}
|
||||
|
||||
enum CommentVoteType {
|
||||
Indifferent = 0,
|
||||
Like = 1,
|
||||
Dislike = -1,
|
||||
}
|
||||
|
||||
interface CommentNotice {
|
||||
error: string;
|
||||
message: string;
|
||||
|
@ -45,6 +51,12 @@ interface CommentPostInfo extends CommentNotice {
|
|||
user_colour: number;
|
||||
}
|
||||
|
||||
interface CommentVotesInfo extends CommentNotice {
|
||||
comment_id: number;
|
||||
likes: number;
|
||||
dislikes: number;
|
||||
}
|
||||
|
||||
function commentDelete(ev: Event): void
|
||||
{
|
||||
if (!checkUserPerm('comments', CommentPermission.Delete) || !commentsRequestLock())
|
||||
|
@ -77,19 +89,18 @@ function commentDelete(ev: Event): void
|
|||
|
||||
function commentPostEventHandler(ev: Event): void
|
||||
{
|
||||
const form: HTMLFormElement = ev.target as HTMLFormElement,
|
||||
formData: FormData = ExtractFormData(form, true);
|
||||
const form: HTMLFormElement = ev.target as HTMLFormElement;
|
||||
|
||||
commentPost(
|
||||
formData,
|
||||
ExtractFormData(form, true),
|
||||
info => commentPostSuccess(form, info),
|
||||
message => commentPostFail
|
||||
commentPostFail
|
||||
);
|
||||
}
|
||||
|
||||
function commentPost(formData: FormData, onSuccess: (comment: CommentPostInfo) => void = null, onFail: (message: string) => void = null): void
|
||||
{
|
||||
if (!commentsRequestLock())
|
||||
if (!checkUserPerm('comments', CommentPermission.Create) || !commentsRequestLock())
|
||||
return;
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
@ -100,6 +111,8 @@ function commentPost(formData: FormData, onSuccess: (comment: CommentPostInfo) =
|
|||
|
||||
commentsFreeLock();
|
||||
|
||||
console.log(xhr.getResponseHeader('X-Misuzu-CSRF'));
|
||||
|
||||
const json: CommentPostInfo = JSON.parse(xhr.responseText) as CommentPostInfo,
|
||||
message: string = json.error || json.message;
|
||||
|
||||
|
@ -118,7 +131,7 @@ function commentPostSuccess(form: HTMLFormElement, comment: CommentPostInfo): vo
|
|||
if (form.classList.contains('comment--reply'))
|
||||
(form.parentNode.parentNode.querySelector('label.comment__action') as HTMLLabelElement).click();
|
||||
|
||||
//commentInsert(info, form);
|
||||
commentInsert(comment, form);
|
||||
}
|
||||
|
||||
function commentPostFail(message: string): void {
|
||||
|
@ -137,6 +150,8 @@ function commentsInit(): void {
|
|||
const commentInputs: HTMLCollectionOf<HTMLTextAreaElement> = document.getElementsByClassName('comment__text--input') as HTMLCollectionOf<HTMLTextAreaElement>;
|
||||
|
||||
for (let i = 0; i < commentInputs.length; i++) {
|
||||
commentInputs[i].form.action = 'javascript:void(0);';
|
||||
commentInputs[i].form.addEventListener('submit', commentPostEventHandler);
|
||||
commentInputs[i].addEventListener('keydown', ev => {
|
||||
if (ev.keyCode === 13 && ev.ctrlKey && !ev.altKey && !ev.shiftKey) {
|
||||
let form = commentInputs[i].form;
|
||||
|
@ -151,8 +166,6 @@ function commentsInit(): void {
|
|||
}
|
||||
|
||||
function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElement {
|
||||
const isReply = comment.comment_reply_to > 0;
|
||||
|
||||
const commentElement: HTMLDivElement = document.createElement('div');
|
||||
commentElement.className = 'comment';
|
||||
commentElement.id = 'comment-' + comment.comment_id;
|
||||
|
@ -189,120 +202,94 @@ function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElem
|
|||
const commentActions = commentContent.appendChild(document.createElement('div'));
|
||||
commentActions.className = 'comment__actions';
|
||||
|
||||
}
|
||||
|
||||
function commentInsert(comment, form): void
|
||||
{
|
||||
var isReply = form.classList.contains('comment--reply'),
|
||||
parent = isReply
|
||||
? form.parentNode
|
||||
: form.parentNode.parentNode.getElementsByClassName('comments__listing')[0],
|
||||
repliesIndent = isReply
|
||||
? (parseInt(parent.classList[1].substr(25)) + 1)
|
||||
: 1;
|
||||
|
||||
// info
|
||||
var commentUser = document.createElement('a');
|
||||
const commentUser: HTMLAnchorElement = commentInfo.appendChild(document.createElement('a'));
|
||||
commentUser.className = 'comment__user comment__user--link';
|
||||
commentUser.textContent = comment.username;
|
||||
commentUser.href = '/profile?u=' + comment.user_id;
|
||||
commentUser.style.color = comment.user_colour == null || (comment.user_colour & 0x40000000) > 0
|
||||
? 'inherit'
|
||||
: '#' + (comment.user_colour & 0xFFFFFF).toString(16);
|
||||
commentInfo.appendChild(commentUser);
|
||||
|
||||
var commentLink = document.createElement('a');
|
||||
const commentLink: HTMLAnchorElement = commentInfo.appendChild(document.createElement('a'));
|
||||
commentLink.className = 'comment__link';
|
||||
commentLink.href = '#' + commentElement.id;
|
||||
commentInfo.appendChild(commentLink);
|
||||
|
||||
var commentTime = document.createElement('time'),
|
||||
const commentTime: HTMLTimeElement = commentLink.appendChild(document.createElement('time')),
|
||||
commentDate = new Date(comment.comment_created + 'Z');
|
||||
commentTime.className = 'comment__date';
|
||||
commentTime.title = commentDate.toLocaleString();
|
||||
commentTime.dateTime = commentDate.toISOString();
|
||||
commentTime.textContent = timeago().format(commentDate);
|
||||
commentLink.appendChild(commentTime);
|
||||
timeago().render(commentTime);
|
||||
|
||||
// actions
|
||||
if (typeof commentVote === 'function') {
|
||||
var commentLike = document.createElement('a');
|
||||
if (checkUserPerm('comments', CommentPermission.Vote)) {
|
||||
const commentLike: HTMLAnchorElement = commentActions.appendChild(document.createElement('a'));
|
||||
commentLike.className = 'comment__action comment__action--link comment__action--like';
|
||||
commentLike.href = 'javascript:void(0);';
|
||||
commentLike.textContent = 'Like';
|
||||
commentLike.onclick = commentVote;
|
||||
commentActions.appendChild(commentLike);
|
||||
commentLike.addEventListener('click', commentVoteEventHandler);
|
||||
|
||||
var commentDislike = document.createElement('a');
|
||||
const commentDislike: HTMLAnchorElement = commentActions.appendChild(document.createElement('a'));
|
||||
commentDislike.className = 'comment__action comment__action--link comment__action--dislike';
|
||||
commentDislike.href = 'javascript:void(0);';
|
||||
commentDislike.textContent = 'Dislike';
|
||||
commentDislike.onclick = commentVote;
|
||||
commentActions.appendChild(commentDislike);
|
||||
commentLike.addEventListener('click', commentVoteEventHandler);
|
||||
}
|
||||
|
||||
// if we're executing this it's fairly obvious that we can reply,
|
||||
// so no need to have a permission check on it here
|
||||
var commentReply = document.createElement('label');
|
||||
const commentReply: HTMLLabelElement = commentActions.appendChild(document.createElement('label'));
|
||||
commentReply.className = 'comment__action comment__action--link';
|
||||
commentReply.htmlFor = 'comment-reply-toggle-' + comment.comment_id;
|
||||
commentReply.textContent = 'Reply';
|
||||
commentActions.appendChild(commentReply);
|
||||
|
||||
// reply section
|
||||
var commentReplyState = document.createElement('input');
|
||||
const commentReplyState: HTMLInputElement = commentReplies.appendChild(document.createElement('input'));
|
||||
commentReplyState.id = commentReply.htmlFor;
|
||||
commentReplyState.type = 'checkbox';
|
||||
commentReplyState.className = 'comment__reply-toggle';
|
||||
commentReplies.appendChild(commentReplyState);
|
||||
|
||||
var commentReplyInput = document.createElement('form');
|
||||
const commentReplyInput: HTMLFormElement = commentReplies.appendChild(document.createElement('form'));
|
||||
commentReplyInput.id = 'comment-reply-' + comment.comment_id;
|
||||
commentReplyInput.className = 'comment comment--input comment--reply';
|
||||
commentReplyInput.method = 'post';
|
||||
commentReplyInput.action = 'javascript:void(0);';
|
||||
commentReplyInput.onsubmit = commentPostEventHandler;
|
||||
commentReplies.appendChild(commentReplyInput);
|
||||
commentReplyInput.addEventListener('submit', commentPostEventHandler);
|
||||
|
||||
// reply attributes
|
||||
var replyCategory = document.createElement('input');
|
||||
const replyCategory: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
|
||||
replyCategory.name = 'comment[category]';
|
||||
replyCategory.value = comment.category_id;
|
||||
replyCategory.value = comment.category_id.toString();
|
||||
replyCategory.type = 'hidden';
|
||||
commentReplyInput.appendChild(replyCategory);
|
||||
|
||||
var replyCsrf = document.createElement('input');
|
||||
const replyCsrf: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
|
||||
replyCsrf.name = 'csrf';
|
||||
replyCsrf.value = '{{ csrf_token("comments") }}';
|
||||
replyCsrf.type = 'hidden';
|
||||
commentReplyInput.appendChild(replyCsrf);
|
||||
|
||||
var replyId = document.createElement('input');
|
||||
const replyId: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
|
||||
replyId.name = 'comment[reply]';
|
||||
replyId.value = comment.comment_id;
|
||||
replyId.value = comment.comment_id.toString();
|
||||
replyId.type = 'hidden';
|
||||
commentReplyInput.appendChild(replyId);
|
||||
|
||||
var replyContainer = document.createElement('div');
|
||||
const replyContainer: HTMLDivElement = commentReplyInput.appendChild(document.createElement('div'));
|
||||
replyContainer.className = 'comment__container';
|
||||
commentReplyInput.appendChild(replyContainer);
|
||||
|
||||
// reply container
|
||||
var replyAvatar = document.createElement('div');
|
||||
const replyAvatar: HTMLDivElement = replyContainer.appendChild(document.createElement('div'));
|
||||
replyAvatar.className = 'avatar comment__avatar';
|
||||
replyAvatar.style.backgroundImage = 'url(\'/profile.php?m=avatar&u={0}\')'.replace('{0}', comment.user_id);
|
||||
replyContainer.appendChild(replyAvatar);
|
||||
replyAvatar.style.backgroundImage = `url('/profile.php?m=avatar&u=${comment.user_id}')`;
|
||||
|
||||
var replyContent = document.createElement('div');
|
||||
const replyContent: HTMLDivElement = replyContainer.appendChild(document.createElement('div'));
|
||||
replyContent.className = 'comment__content';
|
||||
replyContainer.appendChild(replyContent);
|
||||
|
||||
// reply content
|
||||
var replyInfo = document.createElement('div');
|
||||
const replyInfo: HTMLDivElement = replyContent.appendChild(document.createElement('div'));
|
||||
replyInfo.className = 'comment__info';
|
||||
replyContent.appendChild(replyInfo);
|
||||
|
||||
var replyUser = document.createElement('div');
|
||||
const replyUser: HTMLDivElement = document.createElement('div');
|
||||
replyUser.className = 'comment__user';
|
||||
replyUser.textContent = comment.username;
|
||||
replyUser.style.color = comment.user_colour == null || (comment.user_colour & 0x40000000) > 0
|
||||
|
@ -310,30 +297,72 @@ function commentInsert(comment, form): void
|
|||
: '#' + (comment.user_colour & 0xFFFFFF).toString(16);
|
||||
replyInfo.appendChild(replyUser);
|
||||
|
||||
var replyText = document.createElement('textarea');
|
||||
const replyText: HTMLTextAreaElement = replyContent.appendChild(document.createElement('textarea'));
|
||||
replyText.className = 'comment__text input__textarea comment__text--input';
|
||||
replyText.name = 'comment[text]';
|
||||
replyText.placeholder = 'Share your extensive insights...';
|
||||
replyContent.appendChild(replyText);
|
||||
|
||||
var replyActions = document.createElement('div');
|
||||
const replyActions: HTMLDivElement = replyContent.appendChild(document.createElement('div'));
|
||||
replyActions.className = 'comment__actions';
|
||||
replyContent.appendChild(replyActions);
|
||||
|
||||
var replyButton = document.createElement('button');
|
||||
const replyButton: HTMLButtonElement = replyActions.appendChild(document.createElement('button'));
|
||||
replyButton.className = 'input__button comment__action comment__action--button comment__action--post';
|
||||
replyButton.textContent = 'Reply';
|
||||
replyActions.appendChild(replyButton);
|
||||
|
||||
return commentElement;
|
||||
}
|
||||
|
||||
function commentInsert(comment: CommentPostInfo, form: HTMLFormElement): void
|
||||
{
|
||||
const isReply: boolean = form.classList.contains('comment--reply'),
|
||||
parent: Element = isReply
|
||||
? form.parentElement
|
||||
: form.parentElement.parentElement.getElementsByClassName('comments__listing')[0],
|
||||
repliesIndent: number = isReply
|
||||
? (parseInt(parent.classList[1].substr(25)) + 1)
|
||||
: 1,
|
||||
commentElement: HTMLElement = commentConstruct(comment, repliesIndent);
|
||||
|
||||
if (isReply)
|
||||
parent.appendChild(commentElement);
|
||||
else
|
||||
parent.insertBefore(commentElement, parent.firstElementChild);
|
||||
|
||||
timeago().render(commentTime);
|
||||
|
||||
var placeholder = document.getElementById('_no_comments_notice_' + comment.category_id);
|
||||
const placeholder: HTMLElement = document.getElementById('_no_comments_notice_' + comment.category_id);
|
||||
|
||||
if (placeholder)
|
||||
placeholder.parentNode.removeChild(placeholder);
|
||||
}
|
||||
|
||||
function commentVoteEventHandler(ev: Event): void {
|
||||
//
|
||||
}
|
||||
|
||||
function commentVoteV2(
|
||||
commentId: number,
|
||||
vote: CommentVoteType,
|
||||
onSuccess: (voteInfo: CommentVotesInfo, userVote: CommentVoteType) => void,
|
||||
onFail: (message: string) => void
|
||||
): void {
|
||||
if (!checkUserPerm('comments', CommentPermission.Vote) || !commentsRequestLock())
|
||||
return;
|
||||
|
||||
const xhr: XMLHttpRequest = new XMLHttpRequest;
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState !== 4)
|
||||
return;
|
||||
|
||||
commentsFreeLock();
|
||||
|
||||
const json: CommentVotesInfo = JSON.parse(xhr.responseText),
|
||||
message: string = json.error || json.message;
|
||||
|
||||
if (message && onFail)
|
||||
onFail(message);
|
||||
else if (!message && onSuccess)
|
||||
onSuccess(json, vote);
|
||||
};
|
||||
xhr.open('GET', `/comments.php?m=vote&c=${commentId}&v=${vote}&csrf={{ csrf_token("comments") }}`);
|
||||
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
|
||||
xhr.send();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ if (!user_session_active()) {
|
|||
return;
|
||||
}
|
||||
|
||||
header(csrf_http_header('comments'));
|
||||
$commentPerms = comments_get_perms(user_session_current('user_id', 0));
|
||||
|
||||
switch ($_GET['m'] ?? null) {
|
||||
|
|
|
@ -101,17 +101,17 @@ function comments_vote_add(int $comment, int $user, ?string $vote): bool
|
|||
function comments_votes_get(int $commentId): array
|
||||
{
|
||||
$getVotes = db_prepare('
|
||||
SELECT :id as `id`,
|
||||
SELECT :id as `comment_id`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_comments_votes`
|
||||
WHERE `comment_id` = `id`
|
||||
WHERE `comment_id` = `comment_id`
|
||||
AND `comment_vote` = \'Like\'
|
||||
) as `likes`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_comments_votes`
|
||||
WHERE `comment_id` = `id`
|
||||
WHERE `comment_id` = `comment_id`
|
||||
AND `comment_vote` = \'Dislike\'
|
||||
) as `dislikes`
|
||||
');
|
||||
|
|
|
@ -112,3 +112,8 @@ function csrf_html(string $realm, string $name = 'csrf'): string
|
|||
{
|
||||
return sprintf(MSZ_CSRF_HTML, $name, csrf_token($realm));
|
||||
}
|
||||
|
||||
function csrf_http_header(string $realm, string $name = 'X-Misuzu-CSRF'): string
|
||||
{
|
||||
return "{$name}: {$realm};" . csrf_token($realm);
|
||||
}
|
||||
|
|
|
@ -182,97 +182,75 @@
|
|||
|
||||
<script>
|
||||
window.addEventListener('load', function () {
|
||||
if (typeof commentVote === 'function') { // if this exists, the user is allowed to vote
|
||||
var likeButtons = document.getElementsByClassName('comment__action--like'),
|
||||
dislikeButtons = document.getElementsByClassName('comment__action--dislike');
|
||||
var likeButtons = document.getElementsByClassName('comment__action--like'),
|
||||
dislikeButtons = document.getElementsByClassName('comment__action--dislike');
|
||||
|
||||
for (var i = 0; i < likeButtons.length; i++) // there's gonna be an equal amount of like and dislike buttons
|
||||
{
|
||||
likeButtons[i].href = 'javascript:void(0);';
|
||||
likeButtons[i].onclick = commentVote;
|
||||
dislikeButtons[i].href = 'javascript:void(0);';
|
||||
dislikeButtons[i].onclick = commentVote;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof commentPostEventHandler === 'function') { // can comment
|
||||
var commentForms = document.getElementsByClassName('comment--input');
|
||||
|
||||
for (var i = 0; i < commentForms.length; i++) {
|
||||
commentForms[i].action = 'javascript:void(0);';
|
||||
commentForms[i].onsubmit = commentPostEventHandler;
|
||||
}
|
||||
for (var i = 0; i < likeButtons.length; i++) // there's gonna be an equal amount of like and dislike buttons
|
||||
{
|
||||
likeButtons[i].href = 'javascript:void(0);';
|
||||
likeButtons[i].onclick = commentVote;
|
||||
dislikeButtons[i].href = 'javascript:void(0);';
|
||||
dislikeButtons[i].onclick = commentVote;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{% if perms.can_vote %}
|
||||
<script>
|
||||
var commentVoteLock = false,
|
||||
commentLikeClass = 'comment__action--like',
|
||||
commentDislikeClass = 'comment__action--dislike',
|
||||
commentVotedClass = 'comment__action--voted',
|
||||
commentLikeText = 'Like',
|
||||
commentDislikeText = 'Dislike',
|
||||
commentVoteCountSuffix = ' ({0})';
|
||||
var commentVoteLock = false,
|
||||
commentLikeClass = 'comment__action--like',
|
||||
commentDislikeClass = 'comment__action--dislike',
|
||||
commentVotedClass = 'comment__action--voted',
|
||||
commentLikeText = 'Like',
|
||||
commentDislikeText = 'Dislike',
|
||||
commentVoteCountSuffix = ' ({0})';
|
||||
|
||||
// DEBUG THIS IF YOU MAKE MAJOR DOM CHANGES TO COMMENTS
|
||||
function commentVote(ev)
|
||||
{
|
||||
var elem = ev.target,
|
||||
id = elem.parentNode.parentNode.parentNode.parentNode.id.substr(8); // STACK UP
|
||||
// DEBUG THIS IF YOU MAKE MAJOR DOM CHANGES TO COMMENTS
|
||||
function commentVote(ev)
|
||||
{
|
||||
var elem = ev.target,
|
||||
id = elem.parentNode.parentNode.parentNode.parentNode.id.substr(8); // STACK UP
|
||||
|
||||
// the moment we find the id we engage vote lock
|
||||
if (id < 1 || commentVoteLock)
|
||||
return;
|
||||
commentVoteLock = true;
|
||||
elem.textContent = '.';
|
||||
// the moment we find the id we engage vote lock
|
||||
if (id < 1 || commentVoteLock)
|
||||
return;
|
||||
commentVoteLock = true;
|
||||
elem.textContent = '.';
|
||||
|
||||
var isLike = elem.classList.contains(commentLikeClass),
|
||||
isDislike = elem.classList.contains(commentDislikeClass),
|
||||
isIndifferent = elem.classList.contains(commentVotedClass),
|
||||
vote = isIndifferent ? 0 : (isLike ? 1 : -1);
|
||||
var isLike = elem.classList.contains(commentLikeClass),
|
||||
isDislike = elem.classList.contains(commentDislikeClass),
|
||||
isIndifferent = elem.classList.contains(commentVotedClass),
|
||||
vote = isIndifferent ? 0 : (isLike ? 1 : -1);
|
||||
|
||||
elem.textContent += '.';
|
||||
elem.textContent += '.';
|
||||
|
||||
// find friendo (the other vote button), this'll fuck up if the parent element is fucked with
|
||||
for (var i = 0; i < elem.parentNode.childNodes.length; i++) {
|
||||
var current = elem.parentNode.childNodes[i];
|
||||
if (current.nodeName.toLowerCase() === 'a' && current !== elem) {
|
||||
var friend = current;
|
||||
break;
|
||||
}
|
||||
// find friendo (the other vote button), this'll fuck up if the parent element is fucked with
|
||||
for (var i = 0; i < elem.parentNode.childNodes.length; i++) {
|
||||
var current = elem.parentNode.childNodes[i];
|
||||
if (current.nodeName.toLowerCase() === 'a' && current !== elem) {
|
||||
var friend = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof friend !== 'object') {
|
||||
console.error('something happened');
|
||||
return;
|
||||
}
|
||||
if (typeof friend !== 'object') {
|
||||
console.error('something happened');
|
||||
return;
|
||||
}
|
||||
|
||||
friend.classList.remove(commentVotedClass);
|
||||
friend.classList.remove(commentVotedClass);
|
||||
|
||||
friend.textContent = '';
|
||||
friend.textContent = '';
|
||||
|
||||
elem.textContent += '.';
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (this.readyState !== 4)
|
||||
return;
|
||||
elem.textContent += '.';
|
||||
|
||||
commentVoteV2(
|
||||
id, vote,
|
||||
(vInfo, uVote) => {
|
||||
if (vote)
|
||||
elem.classList.add(commentVotedClass);
|
||||
else
|
||||
elem.classList.remove(commentVotedClass);
|
||||
|
||||
var json = JSON.parse(this.responseText),
|
||||
message = json.error || json.message;
|
||||
|
||||
if (message)
|
||||
alert(message);
|
||||
|
||||
var likes = json.likes || 0,
|
||||
dislikes = json.dislikes || 0;
|
||||
var likes = vInfo.likes || 0,
|
||||
dislikes = vInfo.dislikes || 0;
|
||||
|
||||
if (isLike) { // somewhat implicitly defined, like will always come before dislike
|
||||
elem.textContent = commentLikeText + (likes > 0 ? commentVoteCountSuffix.replace('{0}', likes.toLocaleString()) : '');
|
||||
|
@ -281,13 +259,9 @@
|
|||
elem.textContent = commentDislikeText + (dislikes > 0 ? commentVoteCountSuffix.replace('{0}', dislikes.toLocaleString()) : '');
|
||||
friend.textContent = commentLikeText + (likes > 0 ? commentVoteCountSuffix.replace('{0}', likes.toLocaleString()) : '');
|
||||
}
|
||||
|
||||
commentVoteLock = false;
|
||||
};
|
||||
xhr.open('GET', '/comments.php?m=vote&c={0}&v={1}&csrf={{ csrf_token("comments") }}'.replace('{0}', id).replace('{1}', vote));
|
||||
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
|
||||
xhr.send();
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
},
|
||||
alert
|
||||
);
|
||||
}
|
||||
</script>
|
||||
{% endmacro %}
|
||||
|
|
Loading…
Add table
Reference in a new issue