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

View File

@ -1,10 +1,29 @@
/**
* Author: Vera Konigin
* Site: https://groundedwren.neocities.org
* Contact: vera@groundedwren.com
*
* File Description: Comments Control
*/
* Author: Vera Konigin
* Site: https://groundedwren.neocities.org
* Contact: vera@groundedwren.com
*
* 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)
{
@ -312,6 +331,7 @@ registerNamespace("GW.Controls", function (ns)
<gw-comment-card id="${this.idKey}-cmt-${comment.ID}"
commentId="${comment.ID || ""}"
replyToId="${parentId || ""}"
numChildren="${(comment.childrenIdxs || []).length}"
commenterName="${comment["Display Name"] || ""}"
isoTimestamp="${comment.Timestamp.toISOString()}"
websiteURL="${comment.Website || ""}"
@ -364,6 +384,7 @@ registerNamespace("GW.Controls", function (ns)
isInitialized;
commentId;
replyToId;
numChildren;
commenterName;
isoTimestamp;
datetime;
@ -396,6 +417,7 @@ registerNamespace("GW.Controls", function (ns)
this.commentId = this.getAttribute("commentId");
this.replyToId = this.getAttribute("replyToId");
this.numChildren = this.getAttribute("numChildren");
this.commenterName = this.getAttribute("commenterName");
this.isoTimestamp = this.getAttribute("isoTimestamp");
this.datetime = new Date(this.isoTimestamp);
@ -412,10 +434,12 @@ registerNamespace("GW.Controls", function (ns)
renderContent()
{
const headerText = this.replyToId
let headerText = this.replyToId
? `Comment #${this.commentId} replying to #${this.replyToId}`
: `Top level comment #${this.commentId}`;
headerText += ` with ${this.numChildren} direct ${this.numChildren == 1 ? "reply" : "replies"}`;
const displayTimestamp = this.datetime.toLocaleString(
undefined,
{ dateStyle: "short", timeStyle: "short" }
@ -432,27 +456,40 @@ registerNamespace("GW.Controls", function (ns)
class="comment-article"
>
<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 class="visually-hidden">${headerText}</span>
</div>
${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>
<blockquote>${this.commentText}</blockquote>
<div class="comment-footer">
<button id="${this.idKey}-reply">Reply to #${this.commentId}</button>
<button id="${this.idKey}-hide">Hide #${this.commentId}</button>
</div>
</article>
`;
//element properties
this.articleEl = document.getElementById(`${this.idKey}-article`);
this.timestamp = document.getElementById(`${this.idKey}-timestamp`);
this.replyBtn = document.getElementById(`${this.idKey}-reply`);
this.hideBtn = document.getElementById(`${this.idKey}-hide`);
this.showBtn = document.getElementById(`${this.idKey}-show`);
}
//#region Handlers
registerHandlers()
{
this.replyBtn.onclick = this.onReply;
this.hideBtn.onclick = this.onHide;
this.showBtn.onclick = this.onShow;
}
onReply = () =>
@ -468,6 +505,18 @@ registerNamespace("GW.Controls", function (ns)
respToInpt.value = this.commentId;
respToInpt.focus();
};
onHide = () =>
{
this.classList.add("collapsed");
this.showBtn.focus();
};
onShow = () =>
{
this.classList.remove("collapsed");
this.timestamp.focus();
};
//#endregion
};
customElements.define("gw-comment-card", ns.CommentCard);