Skip to content

Commit 3bb9659

Browse files
committed
refactor(js): create utility functions to manage buttons state
1 parent b505a63 commit 3bb9659

File tree

1 file changed

+78
-64
lines changed

1 file changed

+78
-64
lines changed

internal/ui/static/js/app.js

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,67 @@ function setIconAndLabelElement(parentElement, iconName, labelText) {
177177
}
178178
}
179179

180+
/**
181+
* Set the button to a loading state and return a clone of the original button element.
182+
*
183+
* @param {Element} buttonElement - The button element to set to loading state.
184+
* @return {Element} The original button element cloned before modification.
185+
*/
186+
function setButtonToLoadingState(buttonElement) {
187+
const originalButtonElement = buttonElement.cloneNode(true);
188+
189+
buttonElement.textContent = "";
190+
buttonElement.appendChild(createIconLabelElement(buttonElement.dataset.labelLoading));
191+
192+
return originalButtonElement;
193+
}
194+
195+
/**
196+
* Restore the button to its original state.
197+
*
198+
* @param {Element} buttonElement The button element to restore.
199+
* @param {Element} originalButtonElement The original button element to restore from.
200+
* @returns {void}
201+
*/
202+
function restoreButtonState(buttonElement, originalButtonElement) {
203+
buttonElement.textContent = "";
204+
buttonElement.appendChild(originalButtonElement);
205+
}
206+
207+
/**
208+
* Set the button to a saved state.
209+
*
210+
* @param {Element} buttonElement The button element to set to saved state.
211+
*/
212+
function setButtonToSavedState(buttonElement) {
213+
buttonElement.dataset.completed = "true";
214+
setIconAndLabelElement(buttonElement, "save", buttonElement.dataset.labelDone);
215+
}
216+
217+
/**
218+
* Set the bookmark button state.
219+
*
220+
* @param {Element} buttonElement - The button element to update.
221+
* @param {string} newState - The new state to set ("star" or "unstar").
222+
*/
223+
function setBookmarkButtonState(buttonElement, newState) {
224+
buttonElement.dataset.value = newState;
225+
const iconType = newState === "star" ? "unstar" : "star";
226+
setIconAndLabelElement(buttonElement, iconType, buttonElement.dataset[newState === "star" ? "labelUnstar" : "labelStar"]);
227+
}
228+
229+
/**
230+
* Set the read status button state.
231+
*
232+
* @param {Element} buttonElement - The button element to update.
233+
* @param {string} newState - The new state to set ("read" or "unread").
234+
*/
235+
function setReadStatusButtonState(buttonElement, newState) {
236+
buttonElement.dataset.value = newState;
237+
const iconType = newState === "read" ? "unread" : "read";
238+
setIconAndLabelElement(buttonElement, iconType, buttonElement.dataset[newState === "read" ? "labelUnread" : "labelRead"]);
239+
}
240+
180241
/**
181242
* Show a toast notification.
182243
*
@@ -202,29 +263,7 @@ function showToastNotification(iconType, notificationMessage) {
202263

203264
document.body.appendChild(toastElementWrapper);
204265

205-
setTimeout(() => {
206-
toastElementWrapper.classList.add("toast-animate");
207-
208-
}, 100);
209-
}
210-
211-
/**
212-
* Insert an icon label element into the parent element.
213-
*
214-
* @param {Element} parentElement The parent element to insert the icon label into.
215-
* @param {string} iconLabelText The text to display in the icon label.
216-
* @param {boolean} clearParentTextcontent If true, clear the parent's text content before appending the icon label.
217-
* @returns {void}
218-
*/
219-
function insertIconLabelElement(parentElement, iconLabelText, clearParentTextcontent = true) {
220-
const span = document.createElement('span');
221-
span.classList.add('icon-label');
222-
span.textContent = iconLabelText;
223-
224-
if (clearParentTextcontent) {
225-
parentElement.textContent = '';
226-
}
227-
parentElement.appendChild(span);
266+
setTimeout(() => toastElementWrapper.classList.add("toast-animate"), 100);
228267
}
229268

230269
/**
@@ -584,36 +623,21 @@ function handleEntryStatus(navigationDirection, element, setToRead) {
584623
*/
585624
function toggleEntryStatus(element, toasting) {
586625
const entryID = parseInt(element.dataset.id, 10);
587-
const link = element.querySelector(":is(a, button)[data-toggle-status]");
588-
if (!link) {
589-
return;
590-
}
626+
const buttonElement = element.querySelector(":is(a, button)[data-toggle-status]");
627+
if (!buttonElement) return;
591628

592-
const currentStatus = link.dataset.value;
629+
const currentStatus = buttonElement.dataset.value;
593630
const newStatus = currentStatus === "read" ? "unread" : "read";
594631

595-
link.querySelector("span").textContent = link.dataset.labelLoading;
632+
setButtonToLoadingState(buttonElement);
633+
596634
updateEntriesStatus([entryID], newStatus, () => {
597-
let iconElement, label;
635+
setReadStatusButtonState(buttonElement, newStatus);
598636

599-
if (currentStatus === "read") {
600-
iconElement = document.querySelector("template#icon-read");
601-
label = link.dataset.labelRead;
602-
if (toasting) {
603-
showToastNotification("read", link.dataset.toastUnread);
604-
}
605-
} else {
606-
iconElement = document.querySelector("template#icon-unread");
607-
label = link.dataset.labelUnread;
608-
if (toasting) {
609-
showToastNotification("unread", link.dataset.toastUnread);
610-
}
637+
if (toasting) {
638+
showToastNotification(currentStatus, currentStatus === "read" ? buttonElement.dataset.toastUnread : buttonElement.dataset.toastRead);
611639
}
612640

613-
link.replaceChildren(iconElement.content.cloneNode(true));
614-
insertIconLabelElement(link, label, false);
615-
link.dataset.value = newStatus;
616-
617641
if (element.classList.contains("item-status-" + currentStatus)) {
618642
element.classList.remove("item-status-" + currentStatus);
619643
element.classList.add("item-status-" + newStatus);
@@ -667,11 +691,10 @@ function handleSaveEntryAction(element = null) {
667691
const buttonElement = currentEntry.querySelector(":is(a, button)[data-save-entry]");
668692
if (!buttonElement || buttonElement.dataset.completed) return;
669693

670-
insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
694+
setButtonToLoadingState(buttonElement);
671695

672696
sendPOSTRequest(buttonElement.dataset.saveUrl).then(() => {
673-
insertIconLabelElement(buttonElement, buttonElement.dataset.labelDone);
674-
buttonElement.dataset.completed = "true";
697+
setButtonToSavedState(buttonElement);
675698
if (isEntryView()) {
676699
showToastNotification("save", buttonElement.dataset.toastDone);
677700
}
@@ -690,19 +713,13 @@ function handleBookmarkAction(element) {
690713
const buttonElement = currentEntry.querySelector(":is(a, button)[data-toggle-bookmark]");
691714
if (!buttonElement) return;
692715

693-
insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
716+
setButtonToLoadingState(buttonElement);
694717

695718
sendPOSTRequest(buttonElement.dataset.bookmarkUrl).then(() => {
696-
const currentStarStatus = buttonElement.dataset.value;
697-
const newStarStatus = currentStarStatus === "star" ? "unstar" : "star";
698-
const isStarred = currentStarStatus === "star";
719+
const isStarred = buttonElement.dataset.value === "star";
720+
const newStarStatus = isStarred ? "unstar" : "star";
699721

700-
const iconElement = document.querySelector(isStarred ? "template#icon-star" : "template#icon-unstar");
701-
const label = isStarred ? buttonElement.dataset.labelStar : buttonElement.dataset.labelUnstar;
702-
703-
buttonElement.replaceChildren(iconElement.content.cloneNode(true));
704-
insertIconLabelElement(buttonElement, label, false);
705-
buttonElement.dataset.value = newStarStatus;
722+
setBookmarkButtonState(buttonElement, newStarStatus);
706723

707724
if (isEntryView()) {
708725
showToastNotification(newStarStatus, buttonElement.dataset[isStarred ? "toastUnstar" : "toastStar"]);
@@ -721,13 +738,10 @@ function handleFetchOriginalContentAction() {
721738
const buttonElement = document.querySelector(":is(a, button)[data-fetch-content-entry]");
722739
if (!buttonElement) return;
723740

724-
const previousElement = buttonElement.cloneNode(true);
725-
726-
insertIconLabelElement(buttonElement, buttonElement.dataset.labelLoading);
741+
const originalButtonElement = setButtonToLoadingState(buttonElement);
727742

728743
sendPOSTRequest(buttonElement.dataset.fetchContentUrl).then((response) => {
729-
buttonElement.textContent = '';
730-
buttonElement.appendChild(previousElement);
744+
restoreButtonState(buttonElement, originalButtonElement);
731745

732746
response.json().then((data) => {
733747
if (data.content && data.reading_time) {

0 commit comments

Comments
 (0)