From 6f78fa1cfb69cc3e222e8ac41eee9d52c12da79e Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 18 Feb 2025 15:29:37 +0100 Subject: [PATCH] FEAT: ContextMenu --- src/component.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/component.js b/src/component.js index 5283f9e..3a5d7e7 100644 --- a/src/component.js +++ b/src/component.js @@ -137,6 +137,95 @@ class Component extends StyleAndScriptStoringComponent { return this; } + /** + * + * @returns {Component} + */ + registerAsContextMenu() { + this._isContextMenu = true; + this.addStyleClass('contextmenu') + .hidden(); + + return this; + } + + /** + * @todo Positioning of the contextmenu element + * @todo extract into an extra function(allity) provider + * + * @param {Component} component + * @param {Function => Sides} getRefPos + * @param {null|ExtStorage} [extStore=null] + * @returns {Component} + */ + contextMenu(component, getRefPos = null, extStore = null) { + if (!component._isContextMenu) { + component.registerAsContextMenu(); + } + if (!getRefPos) { + getRefPos = function (cmEvent) { + return new Sides() + .left(cmEvent.pageX) + .top(cmEvent.pageY); + } + } + + let cMenuWenity = component.generate(); + + let identifier = cMenuWenity.html.getAttribute("data-autocompel"); + + function hideCMenu(el) { + el.setAttribute("hidden", "hidden"); + el.style.display = "none"; + } + + function hideOnEscape(event) { + if (event.key === "Escape") { + let menu = document.querySelector(`[data-autocompel="${identifier}"`); + hideCMenu(menu); + document.removeEventListener("keyup") + } + } + + + function hideOnClickOutsideOfBounds(event) { + let menu = document.querySelector(`[data-autocompel="${identifier}"`); + + let area = getEnclosingBounds(menu); + + if (!areXYInArea(area, event.clientX, event.clientY)) { + //if (event.target.offsetParent != menu) { + hideCMenu(menu); + document.removeEventListener("click") + } + } + + this.addEventListener( + "contextmenu", + function (event) { + event.preventDefault(); + + /** + * @type {Sides} + */ + const pos = getRefPos(event); + + let menu = document.querySelector(`[data-autocompel="${identifier}"`); + + menu.style.left = `${pos.getByIndex(SideDirections.LEFT)}px`; + menu.style.top = `${pos.getByIndex(SideDirections.TOP)}px`; + + menu.style["display"] = "block"; + menu.removeAttribute("hidden"); + document.addEventListener("click", hideOnClickOutsideOfBounds); + document.addEventListener("keyup", hideOnEscape); + } + ); + + return this; + } + + /** * Defines how a child Component is to be appended.