Implemented custom JSX handler.

This commit is contained in:
flash 2019-06-05 16:56:37 +02:00
parent 502faf3cb4
commit 4a7b9c7f5e
3 changed files with 99 additions and 131 deletions

View file

@ -187,147 +187,70 @@ function commentInputEventHandler(ev: KeyboardEvent): void {
} }
function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElement { function commentConstruct(comment: CommentPostInfo, layer: number = 0): HTMLElement {
const commentElement: HTMLDivElement = document.createElement('div'); const commentDate = new Date(comment.comment_created + 'Z'),
commentElement.className = 'comment'; commentTime: HTMLElement = <time class="comment__date" title={commentDate.toLocaleString()} dateTime={commentDate.toISOString()}>{timeago.format(commentDate)}</time>;
commentElement.id = 'comment-' + comment.comment_id; let actions: HTMLElement[] = [];
// layer 2 if (checkUserPerm('comments', CommentPermission.Vote)) {
const commentContainer: HTMLDivElement = commentElement.appendChild(document.createElement('div')); actions.push(<a class="comment__action comment__action--link comment__action--vote comment__action--like"
commentContainer.className = 'comment__container'; data-comment-id={comment.comment_id} data-comment-vote={CommentVoteType.Like}
href="javascript:void(0);" onClick={commentVoteEventHandler}>Like</a>);
actions.push(<a class="comment__action comment__action--link comment__action--vote comment__action--dislike"
data-comment-id={comment.comment_id} data-comment-vote={CommentVoteType.Dislike}
href="javascript:void(0);" onClick={commentVoteEventHandler}>Dislike</a>);
}
const commentReplies: HTMLDivElement = commentElement.appendChild(document.createElement('div')); const commentText: HTMLDivElement = <div class="comment__text"></div>;
commentReplies.className = 'comment__replies comment__replies--indent-' + layer;
commentReplies.id = commentElement.id + '-replies';
// container
const commentAvatar: HTMLAnchorElement = commentContainer.appendChild(document.createElement('a'));
commentAvatar.className = 'avatar comment__avatar';
commentAvatar.href = urlFormat('user-profile', [{name:'user',value:comment.user_id}]);
commentAvatar.style.backgroundImage = "url('{0}')".replace('{0}', urlFormat('user-avatar', [
{ name: 'user', value: comment.user_id },
{ name: 'res', value: layer < 1 ? 100 : 80 }
]));
const commentContent: HTMLDivElement = commentContainer.appendChild(document.createElement('div'));
commentContent.className = 'comment__content';
// content
const commentInfo = commentContent.appendChild(document.createElement('div'));
commentInfo.className = 'comment__info';
const commentText = commentContent.appendChild(document.createElement('div'));
commentText.className = 'comment__text';
if (comment.comment_html) if (comment.comment_html)
commentText.innerHTML = comment.comment_html; commentText.innerHTML = comment.comment_html;
else else
commentText.textContent = comment.comment_text; commentText.textContent = comment.comment_text;
const commentActions = commentContent.appendChild(document.createElement('div')); const commentElement: HTMLDivElement = <div class="comment" id={"comment-" + comment.comment_id}>
commentActions.className = 'comment__actions'; <div class="comment__container">
<a class="avatar comment__avatar" href={urlFormat('user-profile', [{name:'user',value:comment.user_id}])}
style={"background-image: url('{0}')".replace('{0}', urlFormat('user-avatar', [
{ name: 'user', value: comment.user_id },
{ name: 'res', value: layer < 1 ? 100 : 80 }
]))}></a>
<div class="comment__content">
<div class="comment__info">
<a class="comment__user comment__user--link" href={urlFormat('user-profile', [{name:'user',value:comment.user_id}])}
style={"--user-colour: " + colourGetCSS(comment.user_colour)}>{comment.username}</a>
<a class="comment__link" href={"#comment-" + comment.comment_id}>{commentTime}</a>
</div>
{commentText}
<div class="comment__actions">
{actions}
<label class="comment__action comment__action--link" for={"comment-reply-toggle-" + comment.comment_id}>Reply</label>
</div>
</div>
</div>
<div class={"comment__replies comment__replies--indent-" + layer} id={"comment-" + comment.comment_id + "-replies"}>
<input type="checkbox" id={"comment-reply-toggle-" + comment.comment_id} class="comment__reply-toggle" />
<form id={"comment-reply-" + comment.comment_id} class="comment comment--input comment--reply" method="post"
action="javascript:void(0);" onSubmit={commentPostEventHandler}>
<input type="hidden" name="comment[category]" value={comment.category_id} />
<input type="hidden" name="csrf[comments]" value={getCSRFToken('comments')} />
<input type="hidden" name="comment[reply]" value={comment.comment_id} />
<div class="comment__container">
<div class="avatar comment__avatar"
style={"background-image: url('{0}')".replace('{0}', urlFormat('user-avatar', [{name:'user',value:comment.user_id},{name:'res',value:80}]))}></div>
<div class="comment__content">
<div class="comment__info"></div>
<textarea class="comment__text input__textarea comment__text--input" name="comment[text]" placeholder="Share your extensive insights..." onKeyDown={commentInputEventHandler}></textarea>
<div class="comment__actions">
<button class="input__button comment__action comment__action--button comment__action--post">Reply</button>
</div>
</div>
</div>
</form>
</div>
</div>;
// info
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.setProperty('--user-colour', colourGetCSS(comment.user_colour));
const commentLink: HTMLAnchorElement = commentInfo.appendChild(document.createElement('a'));
commentLink.className = 'comment__link';
commentLink.href = '#' + commentElement.id;
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);
timeago.render(commentTime); timeago.render(commentTime);
// actions
if (checkUserPerm('comments', CommentPermission.Vote)) {
const commentLike: HTMLAnchorElement = commentActions.appendChild(document.createElement('a'));
commentLike.dataset['commentId'] = comment.comment_id.toString();
commentLike.dataset['commentVote'] = CommentVoteType.Like.toString();
commentLike.className = 'comment__action comment__action--link comment__action--vote comment__action--like';
commentLike.href = 'javascript:void(0);';
commentLike.textContent = 'Like';
commentLike.addEventListener('click', commentVoteEventHandler);
const commentDislike: HTMLAnchorElement = commentActions.appendChild(document.createElement('a'));
commentDislike.dataset['commentId'] = comment.comment_id.toString();
commentDislike.dataset['commentVote'] = CommentVoteType.Dislike.toString();
commentDislike.className = 'comment__action comment__action--link comment__action--vote comment__action--dislike';
commentDislike.href = 'javascript:void(0);';
commentDislike.textContent = 'Dislike';
commentDislike.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
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';
// reply section
const commentReplyState: HTMLInputElement = commentReplies.appendChild(document.createElement('input'));
commentReplyState.id = commentReply.htmlFor;
commentReplyState.type = 'checkbox';
commentReplyState.className = 'comment__reply-toggle';
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.addEventListener('submit', commentPostEventHandler);
// reply attributes
const replyCategory: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
replyCategory.name = 'comment[category]';
replyCategory.value = comment.category_id.toString();
replyCategory.type = 'hidden';
const replyCsrf: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
replyCsrf.name = 'csrf[comments]';
replyCsrf.value = getCSRFToken('comments');
replyCsrf.type = 'hidden';
const replyId: HTMLInputElement = commentReplyInput.appendChild(document.createElement('input'));
replyId.name = 'comment[reply]';
replyId.value = comment.comment_id.toString();
replyId.type = 'hidden';
const replyContainer: HTMLDivElement = commentReplyInput.appendChild(document.createElement('div'));
replyContainer.className = 'comment__container';
// reply container
const replyAvatar: HTMLDivElement = replyContainer.appendChild(document.createElement('div'));
replyAvatar.className = 'avatar comment__avatar';
replyAvatar.style.backgroundImage = "url('{0}')".replace('{0}', urlFormat('user-avatar', [{name:'user',value:comment.user_id},{name:'res',value:80}]));
const replyContent: HTMLDivElement = replyContainer.appendChild(document.createElement('div'));
replyContent.className = 'comment__content';
// reply content
const replyInfo: HTMLDivElement = replyContent.appendChild(document.createElement('div'));
replyInfo.className = 'comment__info';
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...';
replyText.addEventListener('keydown', commentInputEventHandler);
const replyActions: HTMLDivElement = replyContent.appendChild(document.createElement('div'));
replyActions.className = 'comment__actions';
const replyButton: HTMLButtonElement = replyActions.appendChild(document.createElement('button'));
replyButton.className = 'input__button comment__action comment__action--button comment__action--post';
replyButton.textContent = 'Reply';
return commentElement; return commentElement;
} }

View file

@ -2,7 +2,7 @@
/// <reference path="Colour.ts" /> /// <reference path="Colour.ts" />
/// <reference path="Support.ts" /> /// <reference path="Support.ts" />
/// <reference path="Permissions.ts" /> /// <reference path="Permissions.ts" />
/// <reference path="Comments.ts" /> /// <reference path="Comments.tsx" />
/// <reference path="Common.ts" /> /// <reference path="Common.ts" />
/// <reference path="FormUtilities.ts" /> /// <reference path="FormUtilities.ts" />
/// <reference path="UserRelations.ts" /> /// <reference path="UserRelations.ts" />
@ -15,6 +15,49 @@ declare const hljs: any;
let loginFormAvatarTimeout: number = 0; let loginFormAvatarTimeout: number = 0;
function mszCreateElement(type: string, properties: {} = {}, children: any[] = []): HTMLElement {
const element: HTMLElement = document.createElement(type);
if(!Array.isArray(children))
children = [children];
if(arguments.length > 3)
for(let i = 3; i < arguments.length; i++)
children.push(arguments[i]);
if(properties)
for(let prop in properties) {
switch(typeof properties[prop]) {
case 'function':
element.addEventListener(
prop.substring(0, 2) === 'on'
? prop.substring(2).toLowerCase()
: prop,
properties[prop]
);
break;
default:
element.setAttribute(prop, properties[prop]);
break;
}
}
if(children)
for(let child in children as []) {
switch(typeof children[child]) {
case 'string':
element.appendChild(document.createTextNode(children[child]));
break;
default:
if(children[child] instanceof Element)
element.appendChild(children[child]);
break;
}
}
return element;
}
// Initialisation process. // Initialisation process.
window.addEventListener('load', () => { window.addEventListener('load', () => {
console.log("%c __ ____\n / |/ (_)______ ______ __ __\n / /|_/ / / ___/ / / /_ / / / / /\n / / / / (__ ) /_/ / / /_/ /_/ /\n/_/ /_/_/____/\\__,_/ /___/\\__,_/\nhttps://github.com/flashwave/misuzu", 'color: #8559a5'); console.log("%c __ ____\n / |/ (_)______ ______ __ __\n / /|_/ / / ___/ / / /_ / / / / /\n / / / / (__ ) /_/ / / /_/ /_/ /\n/_/ /_/_/____/\\__,_/ /___/\\__,_/\nhttps://github.com/flashwave/misuzu", 'color: #8559a5');

View file

@ -2,6 +2,8 @@
"compilerOptions": { "compilerOptions": {
"target": "es6", "target": "es6",
"module": "amd", "module": "amd",
"jsx": "react",
"jsxFactory": "mszCreateElement",
"removeComments": true, "removeComments": true,
"preserveConstEnums": true, "preserveConstEnums": true,
"out": "./public/js/misuzu.js", "out": "./public/js/misuzu.js",