/** * AniWorld - Context Menu Component * * Right-click context menu for anime series cards. * Provides quick access to edit metadata. * * Dependencies: ui-utils.js, edit-modal.js */ var AniWorld = window.AniWorld || {}; AniWorld.ContextMenu = (function() { 'use strict'; let menuElement = null; let currentSeriesKey = null; /** * Initialize the context menu system. * Attaches global dismissal listeners. */ function init() { // Dismiss on click outside document.addEventListener('click', function(e) { if (menuElement && !menuElement.contains(e.target)) { hide(); } }); // Dismiss on Escape document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { hide(); } }); // Dismiss on scroll or resize window.addEventListener('scroll', hide, true); window.addEventListener('resize', hide); // Attach context menu via event delegation on the series grid const grid = document.getElementById('series-grid'); if (grid) { grid.addEventListener('contextmenu', function(e) { const card = e.target.closest('.series-card'); if (card) { e.preventDefault(); const key = card.getAttribute('data-key'); if (key) { show(e, key); } } }); } } /** * Show context menu at cursor position. * @param {MouseEvent} event - The contextmenu event * @param {string} seriesKey - The series key to operate on */ function show(event, seriesKey) { hide(); // Remove any existing menu first currentSeriesKey = seriesKey; menuElement = document.createElement('div'); menuElement.className = 'context-menu'; menuElement.innerHTML = `
`; document.body.appendChild(menuElement); // Position within viewport bounds const x = event.clientX; const y = event.clientY; const menuRect = menuElement.getBoundingClientRect(); const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; let posX = x; let posY = y; if (x + menuRect.width > viewportWidth) { posX = viewportWidth - menuRect.width - 8; } if (y + menuRect.height > viewportHeight) { posY = viewportHeight - menuRect.height - 8; } menuElement.style.left = posX + 'px'; menuElement.style.top = posY + 'px'; // Attach action handlers menuElement.querySelector('[data-action="edit"]').addEventListener('click', function() { hide(); if (AniWorld.EditModal) { AniWorld.EditModal.open(currentSeriesKey); } }); } /** * Hide and remove the context menu from DOM. */ function hide() { if (menuElement) { menuElement.remove(); menuElement = null; currentSeriesKey = null; } } return { init: init, show: show, hide: hide }; })();