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")) {
|
if (items[i].classList.contains("current-item")) {
|
||||||
items[i].classList.remove("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;
|
let itemOffset = (i + offset + items.length) % items.length;
|
||||||
// Allow jumping to top or bottom
|
// Allow jumping to top or bottom
|
||||||
if (offset === TOP) {
|
if (offset === TOP) {
|
||||||
|
@ -338,73 +338,85 @@ async function triggerWebShare(title, url) {
|
||||||
window.location.reload();
|
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");
|
const logoElement = document.querySelector(".logo");
|
||||||
if (!logoElement) return;
|
|
||||||
|
|
||||||
const homePageLinkElement = document.querySelector(".logo > a");
|
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 navMenuElement = document.getElementById("header-menu");
|
||||||
const navMenuElementIsExpanded = navMenuElement.classList.contains("js-menu-show");
|
const isExpanded = navMenuElement?.classList.contains("js-menu-show") ?? false;
|
||||||
const logoToggleButtonLabel = logoElement.getAttribute("data-toggle-button-label");
|
const toggleButtonLabel = logoElement.getAttribute("data-toggle-button-label");
|
||||||
logoElement.setAttribute("role", "button");
|
|
||||||
logoElement.setAttribute("tabindex", "0");
|
// Set mobile menu button attributes
|
||||||
logoElement.setAttribute("aria-label", logoToggleButtonLabel);
|
Object.assign(logoElement, {
|
||||||
logoElement.setAttribute("aria-expanded", navMenuElementIsExpanded?"true":"false");
|
role: "button",
|
||||||
homePageLinkElement.setAttribute("tabindex", "-1");
|
tabIndex: 0,
|
||||||
|
ariaLabel: toggleButtonLabel,
|
||||||
|
ariaExpanded: isExpanded.toString()
|
||||||
|
});
|
||||||
|
homePageLinkElement.tabIndex = -1;
|
||||||
} else {
|
} else {
|
||||||
logoElement.removeAttribute("role");
|
// Remove mobile menu button attributes
|
||||||
logoElement.removeAttribute("tabindex");
|
["role", "tabindex", "aria-expanded", "aria-label"].forEach(attr =>
|
||||||
logoElement.removeAttribute("aria-expanded");
|
logoElement.removeAttribute(attr)
|
||||||
logoElement.removeAttribute("aria-label");
|
);
|
||||||
homePageLinkElement.removeAttribute("tabindex");
|
homePageLinkElement.removeAttribute("tabindex");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixVoiceOverDetailsSummaryBug() {
|
/**
|
||||||
document.querySelectorAll("details").forEach((details) => {
|
* Toggle the main menu dropdown.
|
||||||
const summaryElement = details.querySelector("summary");
|
*
|
||||||
summaryElement.setAttribute("role", "button");
|
* @param {Event} event - The event object.
|
||||||
summaryElement.setAttribute("aria-expanded", details.open? "true": "false");
|
*/
|
||||||
|
function toggleMainMenuDropdown(event) {
|
||||||
details.addEventListener("toggle", () => {
|
// Only handle Enter, Space, or click events
|
||||||
summaryElement.setAttribute("aria-expanded", details.open? "true": "false");
|
if (event.type === "keydown" && !["Enter", " "].includes(event.key)) {
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show and hide the main menu on mobile devices.
|
|
||||||
function toggleMainMenu(event) {
|
|
||||||
if (event.type === "keydown" && !(event.key === "Enter" || event.key === " ")) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent default only if element has role attribute (mobile menu button)
|
||||||
if (event.currentTarget.getAttribute("role")) {
|
if (event.currentTarget.getAttribute("role")) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = document.querySelector(".header nav ul");
|
const navigationMenu = document.querySelector(".header nav ul");
|
||||||
const menuToggleButton = document.querySelector(".logo");
|
const menuToggleButton = document.querySelector(".logo");
|
||||||
if (menu.classList.contains("js-menu-show")) {
|
|
||||||
menuToggleButton.setAttribute("aria-expanded", "false");
|
if (!navigationMenu || !menuToggleButton) {
|
||||||
} else {
|
return;
|
||||||
menuToggleButton.setAttribute("aria-expanded", "true");
|
|
||||||
}
|
}
|
||||||
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) {
|
* Initialize the main menu handlers.
|
||||||
const element = event.target;
|
*/
|
||||||
|
function initializeMainMenuHandlers() {
|
||||||
|
toggleAriaAttributesOnMainMenu();
|
||||||
|
window.addEventListener("resize", toggleAriaAttributesOnMainMenu, { passive: true });
|
||||||
|
|
||||||
if (element.tagName === "A") {
|
const logoElement = document.querySelector(".logo");
|
||||||
window.location.href = element.getAttribute("href");
|
if (logoElement) {
|
||||||
} else {
|
logoElement.addEventListener("click", toggleMainMenuDropdown);
|
||||||
const linkElement = element.querySelector("a") || element.closest("a");
|
logoElement.addEventListener("keydown", toggleMainMenuDropdown);
|
||||||
window.location.href = linkElement.getAttribute("href");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function disableSubmitButtonsOnFormSubmit() {
|
function initializeFormHandlers() {
|
||||||
document.querySelectorAll("form").forEach((element) => {
|
document.querySelectorAll("form").forEach((element) => {
|
||||||
element.onsubmit = () => {
|
element.onsubmit = () => {
|
||||||
const buttons = element.querySelectorAll("button[type=submit]");
|
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() {
|
function showKeyboardShortcuts() {
|
||||||
const template = document.getElementById("keyboard-shortcuts");
|
const template = document.getElementById("keyboard-shortcuts");
|
||||||
ModalHandler.open(template.content, "dialog-title");
|
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() {
|
function markPageAsRead() {
|
||||||
const items = getVisibleEntries();
|
const items = getVisibleEntries();
|
||||||
const entryIDs = [];
|
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();
|
initializeMediaPlayerHandlers();
|
||||||
|
|
||||||
// Initialize the keyboard shortcuts if enabled.
|
// Initialize the keyboard shortcuts if enabled.
|
||||||
|
@ -85,19 +86,6 @@ onAuxClick("a[data-original-link='true']", (event) => {
|
||||||
}
|
}
|
||||||
}, true);
|
}, 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.
|
// Register the service worker if supported.
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
const serviceWorkerURL = document.body.dataset.serviceWorkerUrl;
|
const serviceWorkerURL = document.body.dataset.serviceWorkerUrl;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue