1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-11 17:51:01 +00:00

refactor(js): improve menu handlers

This commit is contained in:
Frédéric Guillot 2025-08-02 13:05:20 -07:00
parent 62410659d5
commit 07246e2b59
2 changed files with 67 additions and 63 deletions

View file

@ -270,7 +270,7 @@ function goToListItem(offset) {
if (items[i].classList.contains("current-item")) {
items[i].classList.remove("current-item");
// By default adjust selection by offset
// By default adjust selection to the next item
let itemOffset = (i + offset + items.length) % items.length;
// Allow jumping to top or bottom
if (offset === TOP) {
@ -338,73 +338,85 @@ async function triggerWebShare(title, url) {
window.location.reload();
}
// make logo element as button on mobile layout
function checkMenuToggleModeByLayout() {
/**
* Toggle the ARIA attributes on the main menu based on the viewport width.
*/
function toggleAriaAttributesOnMainMenu() {
const logoElement = document.querySelector(".logo");
if (!logoElement) return;
const homePageLinkElement = document.querySelector(".logo > a");
if (document.documentElement.clientWidth < 620) {
if (!logoElement || !homePageLinkElement) return;
const isMobile = document.documentElement.clientWidth < 650;
if (isMobile) {
const navMenuElement = document.getElementById("header-menu");
const navMenuElementIsExpanded = navMenuElement.classList.contains("js-menu-show");
const logoToggleButtonLabel = logoElement.getAttribute("data-toggle-button-label");
logoElement.setAttribute("role", "button");
logoElement.setAttribute("tabindex", "0");
logoElement.setAttribute("aria-label", logoToggleButtonLabel);
logoElement.setAttribute("aria-expanded", navMenuElementIsExpanded?"true":"false");
homePageLinkElement.setAttribute("tabindex", "-1");
const isExpanded = navMenuElement?.classList.contains("js-menu-show") ?? false;
const toggleButtonLabel = logoElement.getAttribute("data-toggle-button-label");
// Set mobile menu button attributes
Object.assign(logoElement, {
role: "button",
tabIndex: 0,
ariaLabel: toggleButtonLabel,
ariaExpanded: isExpanded.toString()
});
homePageLinkElement.tabIndex = -1;
} else {
logoElement.removeAttribute("role");
logoElement.removeAttribute("tabindex");
logoElement.removeAttribute("aria-expanded");
logoElement.removeAttribute("aria-label");
// Remove mobile menu button attributes
["role", "tabindex", "aria-expanded", "aria-label"].forEach(attr =>
logoElement.removeAttribute(attr)
);
homePageLinkElement.removeAttribute("tabindex");
}
}
function fixVoiceOverDetailsSummaryBug() {
document.querySelectorAll("details").forEach((details) => {
const summaryElement = details.querySelector("summary");
summaryElement.setAttribute("role", "button");
summaryElement.setAttribute("aria-expanded", details.open? "true": "false");
details.addEventListener("toggle", () => {
summaryElement.setAttribute("aria-expanded", details.open? "true": "false");
});
});
}
// Show and hide the main menu on mobile devices.
function toggleMainMenu(event) {
if (event.type === "keydown" && !(event.key === "Enter" || event.key === " ")) {
/**
* Toggle the main menu dropdown.
*
* @param {Event} event - The event object.
*/
function toggleMainMenuDropdown(event) {
// Only handle Enter, Space, or click events
if (event.type === "keydown" && !["Enter", " "].includes(event.key)) {
return;
}
// Prevent default only if element has role attribute (mobile menu button)
if (event.currentTarget.getAttribute("role")) {
event.preventDefault();
}
const menu = document.querySelector(".header nav ul");
const navigationMenu = document.querySelector(".header nav ul");
const menuToggleButton = document.querySelector(".logo");
if (menu.classList.contains("js-menu-show")) {
menuToggleButton.setAttribute("aria-expanded", "false");
} else {
menuToggleButton.setAttribute("aria-expanded", "true");
if (!navigationMenu || !menuToggleButton) {
return;
}
menu.classList.toggle("js-menu-show");
const isShowing = navigationMenu.classList.toggle("js-menu-show");
menuToggleButton.setAttribute("aria-expanded", isShowing.toString());
}
// Handle click events for the main menu (<li> and <a>).
function onClickMainMenuListItem(event) {
const element = event.target;
/**
* Initialize the main menu handlers.
*/
function initializeMainMenuHandlers() {
toggleAriaAttributesOnMainMenu();
window.addEventListener("resize", toggleAriaAttributesOnMainMenu, { passive: true });
if (element.tagName === "A") {
window.location.href = element.getAttribute("href");
} else {
const linkElement = element.querySelector("a") || element.closest("a");
window.location.href = linkElement.getAttribute("href");
const logoElement = document.querySelector(".logo");
if (logoElement) {
logoElement.addEventListener("click", toggleMainMenuDropdown);
logoElement.addEventListener("keydown", toggleMainMenuDropdown);
}
onClick(".header nav li", (event) => {
const linkElement = event.target.closest("a") || event.target.querySelector("a");
if (linkElement) {
window.location.href = linkElement.getAttribute("href");
}
});
}
/**
@ -412,7 +424,7 @@ function onClickMainMenuListItem(event) {
*
* @returns {void}
*/
function disableSubmitButtonsOnFormSubmit() {
function initializeFormHandlers() {
document.querySelectorAll("form").forEach((element) => {
element.onsubmit = () => {
const buttons = element.querySelectorAll("button[type=submit]");
@ -426,13 +438,17 @@ function disableSubmitButtonsOnFormSubmit() {
});
}
// Show modal dialog with the list of keyboard shortcuts.
/**
* Show the keyboard shortcuts modal.
*/
function showKeyboardShortcuts() {
const template = document.getElementById("keyboard-shortcuts");
ModalHandler.open(template.content, "dialog-title");
}
// Mark as read visible items of the current page.
/**
* Mark all visible entries on the current page as read.
*/
function markPageAsRead() {
const items = getVisibleEntries();
const entryIDs = [];

View file

@ -1,4 +1,5 @@
disableSubmitButtonsOnFormSubmit();
initializeMainMenuHandlers();
initializeFormHandlers();
initializeMediaPlayerHandlers();
// Initialize the keyboard shortcuts if enabled.
@ -85,19 +86,6 @@ onAuxClick("a[data-original-link='true']", (event) => {
}
}, true);
checkMenuToggleModeByLayout();
window.addEventListener("resize", checkMenuToggleModeByLayout, { passive: true });
fixVoiceOverDetailsSummaryBug();
const logoElement = document.querySelector(".logo");
if (logoElement) {
logoElement.addEventListener("click", toggleMainMenu);
logoElement.addEventListener("keydown", toggleMainMenu);
}
onClick(".header nav li", (event) => onClickMainMenuListItem(event));
// Register the service worker if supported.
if ("serviceWorker" in navigator) {
const serviceWorkerURL = document.body.dataset.serviceWorkerUrl;