Update guestbook control with new features

This commit is contained in:
Helen Chong 2024-05-27 13:00:11 +08:00
parent 42aa1f10aa
commit b13c859038
2 changed files with 84 additions and 17 deletions

View File

@ -53,6 +53,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 0.5em; gap: 0.5em;
background-color: var(--clr-quote-bg);
} }
.form-footer { .form-footer {
@ -63,7 +64,8 @@
} }
.form-footer input, .form-footer input,
.comment-article > button { .comment-footer button,
.show-comment {
cursor: pointer; cursor: pointer;
border: none; border: none;
background: var(--clr-link-btn-bg); background: var(--clr-link-btn-bg);
@ -72,6 +74,20 @@
border-radius: 0.2em; border-radius: 0.2em;
} }
gw-comment-card:not(.collapsed) .show-comment {
display: none;
}
gw-comment-card.collapsed .comment-article > *:not(.comment-header) {
display: none !important;
}
gw-comment-card.collapsed .show-comment {
display: block;
}
gw-comment-card.collapsed .comment-header-right time {
display: none;
}
.comments-container { .comments-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -81,7 +97,7 @@
} }
.comment-article { .comment-article {
padding: 0.5em 0; padding: 0.3em 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@ -109,14 +125,16 @@
padding-right: 0; padding-right: 0;
} }
.comment-id, .comment-timestamp { .comment-id, .comment-header-right > time {
font-size: 0.85em; font-size: 0.85em;
font-style: italic; font-style: italic;
word-break: keep-all; word-break: keep-all;
} }
.comment-timestamp { .comment-header-right {
text-align: end; display: flex;
flex-direction: row;
justify-content: flex-end;
} }
.commenter-name { .commenter-name {

View File

@ -6,6 +6,25 @@
* File Description: Comments Control * File Description: Comments Control
*/ */
/**
* By default, any JavaScript code written is defined in the global namespace, which means it's accessible directly under the "window" element.
* If you have a lot of scripts, this can lead to clutter and naming collisions (what if two different scripts use a variable called "i"? They can inadvertently mess each other up).
* To get around this, we define the registerNamespace function in the global namespace, which just confines all the code in the function passed to it to a property under window.
* That property is represented as the "path" parameter. It is passed to the function for ease of access.
*/
function registerNamespace(path, nsFunc)
{
var ancestors = path.split(".");
var ns = window;
for(var i = 0; i < ancestors.length; i++)
{
ns[ancestors[i]] = ns[ancestors[i]] || {};
ns = ns[ancestors[i]];
}
nsFunc(ns);
}
registerNamespace("GW.Controls", function (ns) registerNamespace("GW.Controls", function (ns)
{ {
ns.CommentForm = class CommentForm extends HTMLElement ns.CommentForm = class CommentForm extends HTMLElement
@ -312,6 +331,7 @@ registerNamespace("GW.Controls", function (ns)
<gw-comment-card id="${this.idKey}-cmt-${comment.ID}" <gw-comment-card id="${this.idKey}-cmt-${comment.ID}"
commentId="${comment.ID || ""}" commentId="${comment.ID || ""}"
replyToId="${parentId || ""}" replyToId="${parentId || ""}"
numChildren="${(comment.childrenIdxs || []).length}"
commenterName="${comment["Display Name"] || ""}" commenterName="${comment["Display Name"] || ""}"
isoTimestamp="${comment.Timestamp.toISOString()}" isoTimestamp="${comment.Timestamp.toISOString()}"
websiteURL="${comment.Website || ""}" websiteURL="${comment.Website || ""}"
@ -364,6 +384,7 @@ registerNamespace("GW.Controls", function (ns)
isInitialized; isInitialized;
commentId; commentId;
replyToId; replyToId;
numChildren;
commenterName; commenterName;
isoTimestamp; isoTimestamp;
datetime; datetime;
@ -396,6 +417,7 @@ registerNamespace("GW.Controls", function (ns)
this.commentId = this.getAttribute("commentId"); this.commentId = this.getAttribute("commentId");
this.replyToId = this.getAttribute("replyToId"); this.replyToId = this.getAttribute("replyToId");
this.numChildren = this.getAttribute("numChildren");
this.commenterName = this.getAttribute("commenterName"); this.commenterName = this.getAttribute("commenterName");
this.isoTimestamp = this.getAttribute("isoTimestamp"); this.isoTimestamp = this.getAttribute("isoTimestamp");
this.datetime = new Date(this.isoTimestamp); this.datetime = new Date(this.isoTimestamp);
@ -412,10 +434,12 @@ registerNamespace("GW.Controls", function (ns)
renderContent() renderContent()
{ {
const headerText = this.replyToId let headerText = this.replyToId
? `Comment #${this.commentId} replying to #${this.replyToId}` ? `Comment #${this.commentId} replying to #${this.replyToId}`
: `Top level comment #${this.commentId}`; : `Top level comment #${this.commentId}`;
headerText += ` with ${this.numChildren} direct ${this.numChildren == 1 ? "reply" : "replies"}`;
const displayTimestamp = this.datetime.toLocaleString( const displayTimestamp = this.datetime.toLocaleString(
undefined, undefined,
{ dateStyle: "short", timeStyle: "short" } { dateStyle: "short", timeStyle: "short" }
@ -432,27 +456,40 @@ registerNamespace("GW.Controls", function (ns)
class="comment-article" class="comment-article"
> >
<div id="${this.idKey}-header" class="comment-header"> <div id="${this.idKey}-header" class="comment-header">
<div> <div class="comment-id" role="img" aria-label="${headerText}">
<span aria-hidden="true" class="comment-id">#${this.commentId}</span> <span aria-hidden="true" class="comment-id">#${this.commentId}</span>
<span class="visually-hidden">${headerText}</span>
</div> </div>
${commenterNameEl} ${commenterNameEl}
<time datetime="${this.isoTimestamp}" class="comment-timestamp">${displayTimestamp}</time> <div class="comment-header-right">
<time id="${this.idKey}-timestamp"
datetime="${this.isoTimestamp}"
tabindex="-1"
>${displayTimestamp}</time>
<button id="${this.idKey}-show" class="show-comment">Show #${this.commentId}</button>
</div>
</div> </div>
<blockquote>${this.commentText}</blockquote> <blockquote>${this.commentText}</blockquote>
<div class="comment-footer">
<button id="${this.idKey}-reply">Reply to #${this.commentId}</button> <button id="${this.idKey}-reply">Reply to #${this.commentId}</button>
<button id="${this.idKey}-hide">Hide #${this.commentId}</button>
</div>
</article> </article>
`; `;
//element properties //element properties
this.articleEl = document.getElementById(`${this.idKey}-article`); this.articleEl = document.getElementById(`${this.idKey}-article`);
this.timestamp = document.getElementById(`${this.idKey}-timestamp`);
this.replyBtn = document.getElementById(`${this.idKey}-reply`); this.replyBtn = document.getElementById(`${this.idKey}-reply`);
this.hideBtn = document.getElementById(`${this.idKey}-hide`);
this.showBtn = document.getElementById(`${this.idKey}-show`);
} }
//#region Handlers //#region Handlers
registerHandlers() registerHandlers()
{ {
this.replyBtn.onclick = this.onReply; this.replyBtn.onclick = this.onReply;
this.hideBtn.onclick = this.onHide;
this.showBtn.onclick = this.onShow;
} }
onReply = () => onReply = () =>
@ -468,6 +505,18 @@ registerNamespace("GW.Controls", function (ns)
respToInpt.value = this.commentId; respToInpt.value = this.commentId;
respToInpt.focus(); respToInpt.focus();
}; };
onHide = () =>
{
this.classList.add("collapsed");
this.showBtn.focus();
};
onShow = () =>
{
this.classList.remove("collapsed");
this.timestamp.focus();
};
//#endregion //#endregion
}; };
customElements.define("gw-comment-card", ns.CommentCard); customElements.define("gw-comment-card", ns.CommentCard);