diff --git a/ui/static/js/app.js b/ui/static/js/app.js index a8c0bce0..ab99a70d 100644 --- a/ui/static/js/app.js +++ b/ui/static/js/app.js @@ -127,9 +127,14 @@ function markPageAsRead() { } } -// Handle entry status changes from the list view and entry view. -// Focus the previous entry if it exists. -function handleEntryStatus(element, setToRead) { +/** + * Handle entry status changes from the list view and entry view. + * Focus the next or the previous entry if it exists. + * @param {string} item Item to focus: "previous" or "next". + * @param {Element} element + * @param {boolean} setToRead + */ +function handleEntryStatus(item, element, setToRead) { let toasting = !element; let currentEntry = findEntry(element); if (currentEntry) { @@ -137,22 +142,14 @@ function handleEntryStatus(element, setToRead) { toggleEntryStatus(currentEntry, toasting); } if (isListView() && currentEntry.classList.contains('current-item')) { - goToNextListItem(); - } - } -} - -// Handle entry status changes from the list view and entry view. -// Focus the next entry if it exists. -function handleEntryStatusNext(element, setToRead) { - let toasting = !element; - let currentEntry = findEntry(element); - if (currentEntry) { - if (!setToRead || currentEntry.querySelector("a[data-toggle-status]").dataset.value == "unread") { - toggleEntryStatus(currentEntry, toasting); - } - if (isListView() && currentEntry.classList.contains('current-item')) { - goToPrevListItem(); + switch (item) { + case "previous": + goToListItem(-1); + break; + case "next": + goToListItem(1); + break; + } } } } @@ -363,7 +360,7 @@ function openOriginalLink(openLinkInCurrentTab) { let currentItem = document.querySelector(".current-item"); // If we are not on the list of starred items, move to the next item if (document.location.href != document.querySelector('a[data-page=starred]').href) { - goToNextListItem(); + goToListItem(1); } markEntryAsRead(currentItem); } @@ -428,7 +425,7 @@ function goToPage(page, fallbackSelf) { function goToPrevious() { if (isListView()) { - goToPreviousListItem(); + goToListItem(-1); } else { goToPage("previous"); } @@ -436,7 +433,7 @@ function goToPrevious() { function goToNext() { if (isListView()) { - goToNextListItem(); + goToListItem(1); } else { goToPage("next"); } @@ -464,7 +461,10 @@ function goToFeed() { } } -function goToPreviousListItem() { +/** + * @param {number} offset How many items to jump for focus. + */ +function goToListItem(offset) { let items = DomHelper.getVisibleElements(".items .item"); if (items.length === 0) { return; @@ -480,80 +480,11 @@ function goToPreviousListItem() { if (items[i].classList.contains("current-item")) { items[i].classList.remove("current-item"); - let nextItem; - if (i - 1 >= 0) { - nextItem = items[i - 1]; - } else { - nextItem = items[items.length - 1]; - } + let item = items[(i + offset + items.length) % items.length]; - nextItem.classList.add("current-item"); - DomHelper.scrollPageTo(nextItem); - nextItem.querySelector('.item-header a').focus(); - - break; - } - } -} - -function goToNextListItem() { - let items = DomHelper.getVisibleElements(".items .item"); - if (items.length === 0) { - return; - } - - if (document.querySelector(".current-item") === null) { - items[0].classList.add("current-item"); - items[0].querySelector('.item-header a').focus(); - return; - } - - for (let i = 0; i < items.length; i++) { - if (items[i].classList.contains("current-item")) { - items[i].classList.remove("current-item"); - - let nextItem; - if (i + 1 < items.length) { - nextItem = items[i + 1]; - } else { - nextItem = items[0]; - } - - nextItem.classList.add("current-item"); - DomHelper.scrollPageTo(nextItem); - nextItem.querySelector('.item-header a').focus(); - - break; - } - } -} - -function goToPrevListItem() { - let items = DomHelper.getVisibleElements(".items .item"); - if (items.length === 0) { - return; - } - - if (document.querySelector(".current-item") === null) { - items[0].classList.add("current-item"); - items[0].querySelector('.item-header a').focus(); - return; - } - - for (let i = 0; i < items.length; i++) { - if (items[i].classList.contains("current-item")) { - items[i].classList.remove("current-item"); - - let prevItem; - if (i - 1 >= 0) { - prevItem = items[i - 1]; - } else { - prevItem = items[items.length - 1]; - } - - prevItem.classList.add("current-item"); - DomHelper.scrollPageTo(prevItem); - prevItem.querySelector('.item-header a').focus(); + item.classList.add("current-item"); + DomHelper.scrollPageTo(item); + item.querySelector('.item-header a').focus(); break; } diff --git a/ui/static/js/bootstrap.js b/ui/static/js/bootstrap.js index 6c41003d..6a1c9dbc 100644 --- a/ui/static/js/bootstrap.js +++ b/ui/static/js/bootstrap.js @@ -23,8 +23,8 @@ document.addEventListener("DOMContentLoaded", function () { keyboardHandler.on("V", () => openOriginalLink(true)); keyboardHandler.on("c", () => openCommentLink()); keyboardHandler.on("C", () => openCommentLink(true)); - keyboardHandler.on("m", () => handleEntryStatus()); - keyboardHandler.on("M", () => handleEntryStatusNext()); + keyboardHandler.on("m", () => handleEntryStatus("next")); + keyboardHandler.on("M", () => handleEntryStatus("previous")); keyboardHandler.on("A", () => markPageAsRead()); keyboardHandler.on("s", () => handleSaveEntry()); keyboardHandler.on("d", () => handleFetchOriginalContent()); @@ -46,7 +46,7 @@ document.addEventListener("DOMContentLoaded", function () { onClick("a[data-fetch-content-entry]", () => handleFetchOriginalContent()); onClick("a[data-action=search]", (event) => setFocusToSearchInput(event)); onClick("a[data-action=markPageAsRead]", (event) => handleConfirmationMessage(event.target, () => markPageAsRead())); - onClick("a[data-toggle-status]", (event) => handleEntryStatus(event.target)); + onClick("a[data-toggle-status]", (event) => handleEntryStatus("next", event.target)); onClick("a[data-confirm]", (event) => handleConfirmationMessage(event.target, (url, redirectURL) => { let request = new RequestBuilder(url); @@ -63,11 +63,11 @@ document.addEventListener("DOMContentLoaded", function () { })); onClick("a[data-original-link]", (event) => { - handleEntryStatus(event.target, true); + handleEntryStatus("next", event.target, true); }, true); onAuxClick("a[data-original-link]", (event) => { if (event.button == 1) { - handleEntryStatus(event.target, true); + handleEntryStatus("next", event.target, true); } }, true);