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:
parent
62410659d5
commit
07246e2b59
2 changed files with 67 additions and 63 deletions
|
@ -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 = [];
|
||||
|
|
16
internal/ui/static/js/bootstrap.js
vendored
16
internal/ui/static/js/bootstrap.js
vendored
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue