"use strict"; const $ = require("jquery"); const Mousetrap = require("mousetrap"); const contextMenuContainer = $("#context-menu-container"); module.exports = class ContextMenu { constructor(contextMenuItems, contextMenuActions, selectedElement, event) { this.previousActiveElement = document.activeElement; this.contextMenuItems = contextMenuItems; this.contextMenuActions = contextMenuActions; this.selectedElement = selectedElement; this.event = event; } show() { const contextMenu = showContextMenu( this.contextMenuItems, this.selectedElement, this.event ); this.bindEvents(contextMenu); return false; } hide() { contextMenuContainer .hide() .empty() .off(".contextMenu"); Mousetrap.unbind("escape"); } bindEvents(contextMenu) { const contextMenuActions = this.contextMenuActions; contextMenuActions.execute = (id, ...args) => contextMenuActions[id] && contextMenuActions[id](...args); const clickItem = (item) => { const itemData = item.attr("data-data"); const contextAction = item.attr("data-action"); this.hide(); contextMenuActions.execute(contextAction, itemData); }; contextMenu.on("click", ".context-menu-item", function() { clickItem($(this)); }); const trap = Mousetrap(contextMenu.get(0)); trap.bind(["up", "down"], (e, key) => { const items = contextMenu.find(".context-menu-item"); let index = items.toArray().findIndex((item) => $(item).is(":focus")); if (key === "down") { index = (index + 1) % items.length; } else { index = Math.max(index, 0) - 1; } items.eq(index).trigger("focus"); }); trap.bind("enter", () => { const item = contextMenu.find(".context-menu-item:focus"); if (item.length) { clickItem(item); } return false; }); // Hide context menu when clicking or right clicking outside of it contextMenuContainer.on("click.contextMenu contextmenu.contextMenu", (e) => { // Do not close the menu when clicking inside of the context menu (e.g. on a divider) if ($(e.target).prop("id") === "context-menu") { return; } this.hide(); return false; }); // Hide the context menu when pressing escape within the context menu container Mousetrap.bind("escape", () => { this.hide(); // Return focus to the previously focused element $(this.previousActiveElement).trigger("focus"); return false; }); } }; function showContextMenu(contextMenuItems, selectedElement, event) { const target = $(event.currentTarget); const contextMenu = $("