Compare commits
No commits in common. "e051095ce32c3a3ed04ffed5690f9fc875c78420" and "cab5981aaeb6ecbeb8acf6525bcfb964d6db976d" have entirely different histories.
e051095ce3
...
cab5981aae
|
@ -110,7 +110,7 @@ gw-comment-card.collapsed .comment-header-right time { display: none; }
|
||||||
|
|
||||||
.comment-header {
|
.comment-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 0fr auto 1fr;
|
grid-template-columns: 0fr max-content 1fr;
|
||||||
gap: 0.4em;
|
gap: 0.4em;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
@ -136,5 +136,4 @@ gw-comment-card.collapsed .comment-header-right time { display: none; }
|
||||||
.commenter-name {
|
.commenter-name {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
overflow-wrap: break-word;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,36 @@
|
||||||
/**
|
/**
|
||||||
* @file Comments control
|
* Author: Vera Konigin
|
||||||
* @author Vera Konigin vera@groundedwren.com
|
* Site: https://groundedwren.neocities.org
|
||||||
* https://groundedwren.neocities.org
|
* Contact: vera@groundedwren.com
|
||||||
|
*
|
||||||
|
* File Description: Comments Control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.GW = window.GW || {};
|
/**
|
||||||
(function Controls(ns) {
|
* By default, any JavaScript code written is defined in the global namespace, which means it's accessible directly under the "window" element.
|
||||||
ns.CommentForm = class CommentForm extends HTMLElement {
|
* 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)
|
||||||
|
{
|
||||||
|
ns.CommentForm = class CommentForm extends HTMLElement
|
||||||
|
{
|
||||||
//#region staticProperties
|
//#region staticProperties
|
||||||
|
static observedAttributes = [];
|
||||||
static instanceCount = 0;
|
static instanceCount = 0;
|
||||||
static instanceMap = {};
|
static instanceMap = {};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
@ -36,17 +59,21 @@ window.GW = window.GW || {};
|
||||||
//#endregion
|
//#endregion
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
constructor() {
|
constructor()
|
||||||
|
{
|
||||||
super();
|
super();
|
||||||
this.instanceId = CommentForm.instanceCount++;
|
this.instanceId = CommentForm.instanceCount++;
|
||||||
CommentForm.instanceMap[this.instanceId] = this;
|
CommentForm.instanceMap[this.instanceId] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
get idKey() {
|
get idKey()
|
||||||
|
{
|
||||||
return `gw-comment-form-${this.instanceId}`;
|
return `gw-comment-form-${this.instanceId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
//#region HTMLElement implementation
|
||||||
|
connectedCallback()
|
||||||
|
{
|
||||||
if (this.isInitialized) { return; }
|
if (this.isInitialized) { return; }
|
||||||
|
|
||||||
this.titleText = this.getAttribute("titleText") || "Add a Comment";
|
this.titleText = this.getAttribute("titleText") || "Add a Comment";
|
||||||
|
@ -59,8 +86,10 @@ window.GW = window.GW || {};
|
||||||
|
|
||||||
this.isInitialized = true;
|
this.isInitialized = true;
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
renderContent() {
|
renderContent()
|
||||||
|
{
|
||||||
//Markup
|
//Markup
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<form id="${this.idKey}-form"
|
<form id="${this.idKey}-form"
|
||||||
|
@ -91,21 +120,19 @@ window.GW = window.GW || {};
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="comment-box-container">
|
<div class="comment-box-container">
|
||||||
<div class="input-vertical">
|
|
||||||
<label for="${this.idKey}-comment">
|
<label for="${this.idKey}-comment">
|
||||||
Comment<span aria-hidden="true">*</span>
|
Comment<span aria-hidden="true">*</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea id="${this.idKey}-comment"
|
<textarea id="${this.idKey}-comment"
|
||||||
minlength="1"
|
minlength="1"
|
||||||
maxlength="1000"
|
maxlength="4000"
|
||||||
required="true"
|
required="true"
|
||||||
rows="5"
|
rows="5"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="${this.idKey}-banner" class="inline-banner" aria-live="polite">
|
<div id="${this.idKey}-banner" class="inline-banner" aria-live="polite">
|
||||||
<gw-icon iconKey="circle-info" title="info"></gw-icon>
|
<gw-icon iconKey="circle-info"></gw-icon>
|
||||||
<span>Comments are manually approved</span>
|
<p>Comments are manually approved</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-footer">
|
<div class="form-footer">
|
||||||
<input id="${this.idKey}-reset" type="reset" value="Reset">
|
<input id="${this.idKey}-reset" type="reset" value="Reset">
|
||||||
|
@ -135,11 +162,13 @@ window.GW = window.GW || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Handlers
|
//#region Handlers
|
||||||
registerHandlers() {
|
registerHandlers()
|
||||||
|
{
|
||||||
this.formEl.onsubmit = this.onSubmit;
|
this.formEl.onsubmit = this.onSubmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit = (event) => {
|
onSubmit = (event) =>
|
||||||
|
{
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const contentObj = {
|
const contentObj = {
|
||||||
|
@ -147,13 +176,12 @@ window.GW = window.GW || {};
|
||||||
email: this.emailInpt.value,
|
email: this.emailInpt.value,
|
||||||
website: this.websiteInpt.value,
|
website: this.websiteInpt.value,
|
||||||
responseTo: this.respToInpt.value,
|
responseTo: this.respToInpt.value,
|
||||||
comment: (
|
comment: this.commentInpt.value,
|
||||||
this.commentInpt.value || ""
|
|
||||||
).replaceAll("\n", "<br>").replaceAll("(", "\\("),
|
|
||||||
timestamp: new Date().toUTCString(),
|
timestamp: new Date().toUTCString(),
|
||||||
};
|
};
|
||||||
const contentAry = [];
|
const contentAry = [];
|
||||||
for (let contentKey in contentObj) {
|
for (let contentKey in contentObj)
|
||||||
|
{
|
||||||
contentAry.push(`${contentKey}=${contentObj[contentKey]}`);
|
contentAry.push(`${contentKey}=${contentObj[contentKey]}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,33 +193,33 @@ window.GW = window.GW || {};
|
||||||
);
|
);
|
||||||
request.setRequestHeader("Content-Type", "application/json");
|
request.setRequestHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
request.onreadystatechange = () => {
|
request.onreadystatechange = () =>
|
||||||
|
{
|
||||||
if (request.readyState !== XMLHttpRequest.DONE) { return; }
|
if (request.readyState !== XMLHttpRequest.DONE) { return; }
|
||||||
if (Math.floor(request.status / 100) !== 2) {
|
if (Math.floor(request.status / 100) !== 2)
|
||||||
|
{
|
||||||
console.log(request.responseText);
|
console.log(request.responseText);
|
||||||
|
|
||||||
this.bannerEl.classList.add("warning");
|
this.bannerEl.classList.add("warning");
|
||||||
this.bannerEl.innerHTML =
|
this.bannerEl.innerHTML =
|
||||||
`
|
`
|
||||||
<gw-icon iconKey="triangle-exclamation" title="warning"></gw-icon>
|
<gw-icon iconKey="triangle-exclamation"></gw-icon>
|
||||||
<span>
|
<span>
|
||||||
That didn't work.
|
That didn't work.
|
||||||
${this.fallbackEmail
|
${this.fallbackEmail
|
||||||
? `<a class="full" href="mailto:${this.fallbackEmail}?subject=Comment on ${document.title}&body=${contentAry.join("; ")}">Click here to send as an email instead</a>.`
|
? `<a class="full" href="mailto:${this.fallbackEmail}?subject=Comment on ${document.title}&body=${contentAry.join("; ")}">Send your comment as an email instead</a>.`
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
alert("Your comment has been submitted!");
|
alert("Your comment has been submitted!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
request.send(JSON.stringify({
|
request.send(JSON.stringify({ content: contentAry.join("; ") }));
|
||||||
embeds: [{
|
|
||||||
fields: Object.keys(contentObj).map(key => { return { name: key, value: contentObj[key] }})
|
|
||||||
}]
|
|
||||||
}));
|
|
||||||
|
|
||||||
localStorage.setItem("comment-name", contentObj.name);
|
localStorage.setItem("comment-name", contentObj.name);
|
||||||
localStorage.setItem("comment-email", contentObj.email);
|
localStorage.setItem("comment-email", contentObj.email);
|
||||||
|
@ -206,11 +234,12 @@ window.GW = window.GW || {};
|
||||||
};
|
};
|
||||||
customElements.define("gw-comment-form", ns.CommentForm);
|
customElements.define("gw-comment-form", ns.CommentForm);
|
||||||
|
|
||||||
ns.CommentList = class CommentList extends HTMLElement {
|
ns.CommentList = class CommentList extends HTMLElement
|
||||||
|
{
|
||||||
//#region staticProperties
|
//#region staticProperties
|
||||||
|
static observedAttributes = [];
|
||||||
static instanceCount = 0;
|
static instanceCount = 0;
|
||||||
static instanceMap = {};
|
static instanceMap = {};
|
||||||
static Data = [];
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region instance properties
|
//#region instance properties
|
||||||
|
@ -225,18 +254,21 @@ window.GW = window.GW || {};
|
||||||
//#endregion
|
//#endregion
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
constructor() {
|
constructor()
|
||||||
|
{
|
||||||
super();
|
super();
|
||||||
this.instanceId = CommentList.instanceCount++;
|
this.instanceId = CommentList.instanceCount++;
|
||||||
CommentList.instanceMap[this.instanceId] = this;
|
CommentList.instanceMap[this.instanceId] = this;
|
||||||
CommentList.Data[this.instanceId] = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get idKey() {
|
get idKey()
|
||||||
|
{
|
||||||
return `gw-comment-list-${this.instanceId}`;
|
return `gw-comment-list-${this.instanceId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
//#region HTMLElement implementation
|
||||||
|
connectedCallback()
|
||||||
|
{
|
||||||
if (this.isInitialized) { return; }
|
if (this.isInitialized) { return; }
|
||||||
|
|
||||||
this.gSpreadsheetId = this.getAttribute("gSpreadsheetId");
|
this.gSpreadsheetId = this.getAttribute("gSpreadsheetId");
|
||||||
|
@ -248,8 +280,10 @@ window.GW = window.GW || {};
|
||||||
|
|
||||||
this.isInitialized = true;
|
this.isInitialized = true;
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
async loadAndRender() {
|
async loadAndRender()
|
||||||
|
{
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<div class="inline-banner">
|
<div class="inline-banner">
|
||||||
<gw-icon iconkey="circle-info" title="info"></gw-icon>
|
<gw-icon iconkey="circle-info" title="info"></gw-icon>
|
||||||
|
@ -258,11 +292,12 @@ window.GW = window.GW || {};
|
||||||
`
|
`
|
||||||
|
|
||||||
const sheetReader = new GW.Gizmos.GoogleSheetsReader(this.gSpreadsheetId, this.gSheetId);
|
const sheetReader = new GW.Gizmos.GoogleSheetsReader(this.gSpreadsheetId, this.gSheetId);
|
||||||
await sheetReader.loadData();
|
const sheetData = await sheetReader.loadData();
|
||||||
this.innerHTML = "";
|
this.innerHTML = "";
|
||||||
|
|
||||||
const allComments = sheetReader.rowData;
|
const allComments = sheetReader.rowData;
|
||||||
if (this.isNewestFirst) {
|
if (this.isNewestFirst)
|
||||||
|
{
|
||||||
allComments.reverse();
|
allComments.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,59 +307,72 @@ window.GW = window.GW || {};
|
||||||
const allCommentsIndex = {};
|
const allCommentsIndex = {};
|
||||||
const topLevelCommentIdxs = [];
|
const topLevelCommentIdxs = [];
|
||||||
const childCommentIdxs = [];
|
const childCommentIdxs = [];
|
||||||
for (let i = 0; i < allComments.length; i++) {
|
for (let i = 0; i < allComments.length; i++)
|
||||||
|
{
|
||||||
const comment = allComments[i];
|
const comment = allComments[i];
|
||||||
allCommentsIndex[comment.ID] = i;
|
allCommentsIndex[comment.ID] = i;
|
||||||
if (!comment.ResponseTo) {
|
if (!comment.ResponseTo)
|
||||||
|
{
|
||||||
topLevelCommentIdxs.push(i);
|
topLevelCommentIdxs.push(i);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
childCommentIdxs.push(i);
|
childCommentIdxs.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
childCommentIdxs.forEach(childIdx => {
|
childCommentIdxs.forEach(childIdx =>
|
||||||
|
{
|
||||||
const replyId = allComments[childIdx].ResponseTo;
|
const replyId = allComments[childIdx].ResponseTo;
|
||||||
const respondeeComment = allComments[allCommentsIndex[replyId]];
|
const respondeeComment = allComments[allCommentsIndex[replyId]];
|
||||||
|
|
||||||
respondeeComment.ChildIdxs = respondeeComment.ChildIdxs || [];
|
respondeeComment.childrenIdxs = respondeeComment.childrenIdxs || [];
|
||||||
respondeeComment.ChildIdxs.push(childIdx);
|
respondeeComment.childrenIdxs.push(childIdx);
|
||||||
});
|
});
|
||||||
|
|
||||||
let commentsToBuild = [];
|
let commentsToBuild = [];
|
||||||
topLevelCommentIdxs.forEach(
|
topLevelCommentIdxs.forEach(
|
||||||
topCommentIdx => commentsToBuild.push({
|
topCommentIdx => commentsToBuild.push(
|
||||||
|
{
|
||||||
parent: this.containerEl,
|
parent: this.containerEl,
|
||||||
|
parentId: null,
|
||||||
comment: allComments[topCommentIdx]
|
comment: allComments[topCommentIdx]
|
||||||
})
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
while (commentsToBuild.length > 0) {
|
while (commentsToBuild.length > 0)
|
||||||
let { parent, comment } = commentsToBuild.shift();
|
{
|
||||||
if (!comment.Timestamp) {
|
let { parent, parentId, comment } = commentsToBuild.shift();
|
||||||
|
if (!comment.Timestamp)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentList.Data[this.instanceId][comment.ID] = comment;
|
|
||||||
|
|
||||||
parent.insertAdjacentHTML("beforeend", `
|
parent.insertAdjacentHTML("beforeend", `
|
||||||
<gw-comment-card id="${this.idKey}-cmt-${comment.ID}"
|
<gw-comment-card id="${this.idKey}-cmt-${comment.ID}"
|
||||||
listInstance=${this.instanceId}
|
commentId="${comment.ID || ""}"
|
||||||
commentId=${comment.ID}
|
replyToId="${parentId || ""}"
|
||||||
gwCommentFormId=${this.gwCommentFormId || ""}
|
numChildren="${(comment.childrenIdxs || []).length}"
|
||||||
|
commenterName="${comment["Display Name"] || ""}"
|
||||||
|
isoTimestamp="${comment.Timestamp.toISOString()}"
|
||||||
|
websiteURL="${comment.Website || ""}"
|
||||||
|
commentText="${comment.Comment || ""}"
|
||||||
|
gwCommentFormId="${this.gwCommentFormId || ""}"
|
||||||
></gw-comment-card>
|
></gw-comment-card>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const commentEl = document.getElementById(`${this.idKey}-cmt-${comment.ID}`);
|
const commentEl = document.getElementById(`${this.idKey}-cmt-${comment.ID}`);
|
||||||
(comment.ChildIdxs || []).forEach(
|
(comment.childrenIdxs || []).forEach(
|
||||||
childIdx => commentsToBuild.push({
|
childIdx => commentsToBuild.push({
|
||||||
parent: commentEl.articleEl,
|
parent: commentEl.articleEl,
|
||||||
|
parentId: comment.ID,
|
||||||
comment: allComments[childIdx]
|
comment: allComments[childIdx]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContent() {
|
renderContent()
|
||||||
|
{
|
||||||
//Markup
|
//Markup
|
||||||
this.innerHTML = `
|
this.innerHTML = `
|
||||||
<div id="${this.idKey}-container" class="comments-container"">
|
<div id="${this.idKey}-container" class="comments-container"">
|
||||||
|
@ -336,14 +384,17 @@ window.GW = window.GW || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Handlers
|
//#region Handlers
|
||||||
registerHandlers() {
|
registerHandlers()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
};
|
};
|
||||||
customElements.define("gw-comment-list", ns.CommentList);
|
customElements.define("gw-comment-list", ns.CommentList);
|
||||||
|
|
||||||
ns.CommentCard = class CommentCard extends HTMLElement {
|
ns.CommentCard = class CommentCard extends HTMLElement
|
||||||
|
{
|
||||||
//#region staticProperties
|
//#region staticProperties
|
||||||
|
static observedAttributes = [];
|
||||||
static instanceCount = 0;
|
static instanceCount = 0;
|
||||||
static instanceMap = {};
|
static instanceMap = {};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
@ -351,16 +402,15 @@ window.GW = window.GW || {};
|
||||||
//#region instance properties
|
//#region instance properties
|
||||||
instanceId;
|
instanceId;
|
||||||
isInitialized;
|
isInitialized;
|
||||||
|
|
||||||
commentId;
|
commentId;
|
||||||
gwCommentFormId;
|
|
||||||
|
|
||||||
replyToId;
|
replyToId;
|
||||||
numChildren;
|
numChildren;
|
||||||
commenterName;
|
commenterName;
|
||||||
|
isoTimestamp;
|
||||||
datetime;
|
datetime;
|
||||||
websiteURL;
|
websiteURL;
|
||||||
commentText;
|
commentText;
|
||||||
|
gwCommentFormId;
|
||||||
|
|
||||||
//#region element properties
|
//#region element properties
|
||||||
articleEl;
|
articleEl;
|
||||||
|
@ -368,32 +418,33 @@ window.GW = window.GW || {};
|
||||||
//#endregion
|
//#endregion
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
constructor() {
|
constructor()
|
||||||
|
{
|
||||||
super();
|
super();
|
||||||
this.instanceId = CommentCard.instanceCount++;
|
this.instanceId = CommentCard.instanceCount++;
|
||||||
CommentCard.instanceMap[this.instanceId] = this;
|
CommentCard.instanceMap[this.instanceId] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
get idKey() {
|
get idKey()
|
||||||
|
{
|
||||||
return `gw-comment-card-${this.instanceId}`;
|
return `gw-comment-card-${this.instanceId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region HTMLElement implementation
|
//#region HTMLElement implementation
|
||||||
connectedCallback() {
|
connectedCallback()
|
||||||
|
{
|
||||||
if (this.isInitialized) { return; }
|
if (this.isInitialized) { return; }
|
||||||
|
|
||||||
this.commentId = this.getAttribute("commentId");
|
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);
|
||||||
|
this.websiteURL = this.getAttribute("websiteURL");
|
||||||
|
this.commentText = this.getAttribute("commentText");
|
||||||
this.gwCommentFormId = this.getAttribute("gwCommentFormId");
|
this.gwCommentFormId = this.getAttribute("gwCommentFormId");
|
||||||
|
|
||||||
const commentData = ns.CommentList.Data[this.getAttribute("listInstance")][this.commentId];
|
|
||||||
|
|
||||||
this.replyToId = commentData.ResponseTo;
|
|
||||||
this.numChildren = (commentData.ChildIdxs || []).length;
|
|
||||||
this.commenterName = commentData["Display Name"];
|
|
||||||
this.datetime = commentData.Timestamp;
|
|
||||||
this.websiteURL = commentData.Website;
|
|
||||||
this.commentText = this.parseCommentText(commentData.Comment);
|
|
||||||
|
|
||||||
this.renderContent();
|
this.renderContent();
|
||||||
this.registerHandlers();
|
this.registerHandlers();
|
||||||
|
|
||||||
|
@ -401,10 +452,12 @@ window.GW = window.GW || {};
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
renderContent() {
|
renderContent()
|
||||||
|
{
|
||||||
let 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"}`;
|
headerText += ` with ${this.numChildren} direct ${this.numChildren == 1 ? "reply" : "replies"}`;
|
||||||
|
|
||||||
const displayTimestamp = this.datetime.toLocaleString(
|
const displayTimestamp = this.datetime.toLocaleString(
|
||||||
|
@ -429,7 +482,7 @@ window.GW = window.GW || {};
|
||||||
${commenterNameEl}
|
${commenterNameEl}
|
||||||
<div class="comment-header-right">
|
<div class="comment-header-right">
|
||||||
<time id="${this.idKey}-timestamp"
|
<time id="${this.idKey}-timestamp"
|
||||||
datetime="${this.datetime.toISOString()}"
|
datetime="${this.isoTimestamp}"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
>${displayTimestamp}</time>
|
>${displayTimestamp}</time>
|
||||||
<button id="${this.idKey}-show" class="show-comment">Show #${this.commentId}</button>
|
<button id="${this.idKey}-show" class="show-comment">Show #${this.commentId}</button>
|
||||||
|
@ -452,16 +505,19 @@ window.GW = window.GW || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Handlers
|
//#region Handlers
|
||||||
registerHandlers() {
|
registerHandlers()
|
||||||
|
{
|
||||||
this.replyBtn.onclick = this.onReply;
|
this.replyBtn.onclick = this.onReply;
|
||||||
this.hideBtn.onclick = this.onHide;
|
this.hideBtn.onclick = this.onHide;
|
||||||
this.showBtn.onclick = this.onShow;
|
this.showBtn.onclick = this.onShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
onReply = () => {
|
onReply = () =>
|
||||||
|
{
|
||||||
const gwCommentForm = document.getElementById(this.gwCommentFormId);
|
const gwCommentForm = document.getElementById(this.gwCommentFormId);
|
||||||
const respToInpt = gwCommentForm.respToInpt;
|
const respToInpt = gwCommentForm.respToInpt;
|
||||||
if (!respToInpt) {
|
if (!respToInpt)
|
||||||
|
{
|
||||||
alert("Comment form not found");
|
alert("Comment form not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -470,59 +526,18 @@ window.GW = window.GW || {};
|
||||||
respToInpt.focus();
|
respToInpt.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
onHide = () => {
|
onHide = () =>
|
||||||
|
{
|
||||||
this.classList.add("collapsed");
|
this.classList.add("collapsed");
|
||||||
this.showBtn.focus();
|
this.showBtn.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
onShow = () => {
|
onShow = () =>
|
||||||
|
{
|
||||||
this.classList.remove("collapsed");
|
this.classList.remove("collapsed");
|
||||||
this.timestamp.focus();
|
this.timestamp.focus();
|
||||||
};
|
};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
parseCommentText(commentString) {
|
|
||||||
let commentText = "";
|
|
||||||
let linkObj = {};
|
|
||||||
|
|
||||||
for(let i = 0; i < commentString.length; i++){
|
|
||||||
let char = commentString.charAt(i);
|
|
||||||
switch (char) {
|
|
||||||
case '[':
|
|
||||||
linkObj = {tStart: i};
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
if(linkObj.tStart !== undefined && linkObj.tStart !== i-1) {
|
|
||||||
linkObj.tEnd = i;
|
|
||||||
}
|
|
||||||
else { linkObj = {}; }
|
|
||||||
break;
|
|
||||||
case '(':
|
|
||||||
if(linkObj.tEnd !== undefined && linkObj.tEnd === i-1) {
|
|
||||||
linkObj.lStart = i;
|
|
||||||
}
|
|
||||||
else { linkObj = {}; }
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
if(linkObj.lStart !== undefined && linkObj.lStart !== i-1) {
|
|
||||||
linkObj.lEnd = i;
|
|
||||||
}
|
|
||||||
else { linkObj = {}; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(linkObj.lEnd !== undefined) {
|
|
||||||
const linkText = commentString.substring(linkObj.tStart + 1, linkObj.tEnd);
|
|
||||||
const linkURL = commentString.substring(linkObj.lStart + 1, linkObj.lEnd);
|
|
||||||
commentText = commentText.substring(0, commentText.length - (i - linkObj.tStart));
|
|
||||||
commentText += `<a href="${linkURL}" target="_blank">${linkText}</a>`;
|
|
||||||
linkObj = {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
commentText += char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return commentText;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
customElements.define("gw-comment-card", ns.CommentCard);
|
customElements.define("gw-comment-card", ns.CommentCard);
|
||||||
}) (window.GW.Controls = window.GW.Controls || {});
|
});
|
|
@ -12,7 +12,7 @@ eleventyComputed:
|
||||||
|
|
||||||
<p class="center-text">Guestbook Archive: <a href="https://web.archive.org/web/20240528231121/https%3A%2F%2Fleilukin.123guestbook.com%2F">123Guestbook</a></p>
|
<p class="center-text">Guestbook Archive: <a href="https://web.archive.org/web/20240528231121/https%3A%2F%2Fleilukin.123guestbook.com%2F">123Guestbook</a></p>
|
||||||
|
|
||||||
<p>Feel free to say hi and connect with me! The comment field supports <a href="https://www.markdownguide.org/basic-syntax/#links">Markdown links</a> and and HTML.</p>
|
<p>Feel free to say hi and connect with me!</p>
|
||||||
|
|
||||||
<p>JavaScript is required for this guestbook to function. Special thanks to <a href="https://groundedwren.neocities.org/pages/controls/guestbookDemo">Vera Konigin</a> for this guestbook widget!</p>
|
<p>JavaScript is required for this guestbook to function. Special thanks to <a href="https://groundedwren.neocities.org/pages/controls/guestbookDemo">Vera Konigin</a> for this guestbook widget!</p>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue