diff --git a/client/src/services/ContextMenu.js b/client/src/services/ContextMenu.js new file mode 100644 index 00000000..86335b8c --- /dev/null +++ b/client/src/services/ContextMenu.js @@ -0,0 +1,115 @@ +// You should hide the context menu when the element that has the +// event gets removed + +let margin = -3; + +let cursorX = 0; +let cursorY = 0; + +let arrowIcon = "icons/iconoir/regular/nav-arrow-right.svg"; + +function ShowContextMenu(){ + let contextMenu = document.getElementById('context-menu'); + contextMenu.style.display = "flex"; + contextMenu.style.top = (cursorY + margin) + "px"; + contextMenu.style.left = (cursorX + margin) + "px"; +} + +function HideContextMenu(){ + let contextMenu = document.getElementById('context-menu'); + contextMenu.style.display = "none"; +} + +function PopulateContext(val){ + let children = []; + val.forEach(element => { + let contextMenuElement = document.createElement('div'); + contextMenuElement.classList.add("context-menu-element"); + if(element.action) + contextMenuElement.addEventListener("click", element.action); + + let spanInfo = document.createElement('span'); + spanInfo.innerText = element.name; + contextMenuElement.appendChild(spanInfo); + + if(element.context){ + let iconContextElement = document.createElement('img'); + iconContextElement.src = arrowIcon; + contextMenuElement.appendChild(iconContextElement); + + let childContextMenuElement = document.createElement('div'); + childContextMenuElement.classList.add("context-menu"); + childContextMenuElement.style.left = "100%"; + childContextMenuElement.style.top = "0"; + childContextMenuElement.style.display = "none"; + + let childChildren = PopulateContext(element.context); + childChildren.forEach((child) => childContextMenuElement.appendChild(child)); + + contextMenuElement.addEventListener("mouseenter", () => { + childContextMenuElement.style.display = "flex"; + }); + + contextMenuElement.addEventListener("mouseleave", () => { + childContextMenuElement.style.display = "none"; + }) + + contextMenuElement.appendChild(childContextMenuElement); + } + + children.push(contextMenuElement); + }); + + return children; +} + +function PopulateContextMenu(val){ + let contextMenu = document.getElementById('context-menu'); + let children = PopulateContext(val); + + contextMenu.replaceChildren(); + children.forEach((el) => contextMenu.appendChild(el)); +} + +function AddContextMenu(element, val){ + element._dr_context = val; + element.addEventListener('contextmenu', (e) => { + e.preventDefault(); + PopulateContextMenu(val); + ShowContextMenu(); + }); + + +} + +function UpdateVisibility(){ + let contextMenu = document.getElementById('context-menu'); + let element = document.elementFromPoint(cursorX, cursorY); + let mustHide = true; + while(element){ + if(element == contextMenu){ + mustHide = false; + break; + } + element = element.parentElement; + } + if(mustHide) HideContextMenu(); +} + +function SetupContextMenu(){ + HideContextMenu(); + + document.addEventListener('mousemove', (e) => { + cursorX = e.clientX; + cursorY = e.clientY; + }); + + document.addEventListener('mousedown', UpdateVisibility); +} + +export { + SetupContextMenu, + AddContextMenu, + ShowContextMenu, + HideContextMenu +}; \ No newline at end of file diff --git a/client/src/services/Tooltip.js b/client/src/services/Tooltip.js index 4ce057a3..c0d9d598 100644 --- a/client/src/services/Tooltip.js +++ b/client/src/services/Tooltip.js @@ -16,20 +16,19 @@ function HideTooltip(){ tooltip.style.display = "none"; } -function AddTooltip(element, val){ - element._dr_tooltip = val; +function AddTooltip(element, val, data = {}){ + element._dr_tooltip = {value: val, ...data}; } function UpdateVisibilityThread(){ - let hiding = true; - document.elementsFromPoint(cursorX, cursorY).forEach(element => { - if(element._dr_tooltip){ - hiding = false; - content.value = element._dr_tooltip; - } - }); - if(hiding) HideTooltip(); - else ShowTooltip(); + let tooltip = document.getElementById('mouse-tooltip'); + let element = document.elementFromPoint(cursorX, cursorY); + if(element._dr_tooltip){ + ShowTooltip(); + content.value = element._dr_tooltip.value; + if(element._dr_tooltip.max_width) tooltip.style.maxWidth = element._dr_tooltip.max_width + "px"; + else tooltip.style.maxWidth = "none"; + } else HideTooltip(); setTimeout(UpdateVisibilityThread, 0); } diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index 4ade5a4f..d8ddf5cd 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -10,6 +10,7 @@ import Toast from './partials/Toast.vue'; import { DisplayToast, SetEmitter } from '../services/Dragonroll'; import GameManager from './managers/GameManager.vue'; import TooltipManager from './managers/TooltipManager.vue'; +import ContextMenuManager from './managers/ContextMenuManager.vue'; @@ -18,6 +19,7 @@ import TooltipManager from './managers/TooltipManager.vue'; + diff --git a/client/src/views/managers/ContextMenuManager.vue b/client/src/views/managers/ContextMenuManager.vue new file mode 100644 index 00000000..8507ac2f --- /dev/null +++ b/client/src/views/managers/ContextMenuManager.vue @@ -0,0 +1,70 @@ + + + + + \ No newline at end of file diff --git a/client/src/views/managers/TileMap.vue b/client/src/views/managers/TileMap.vue index 52903b9e..2e6219ab 100644 --- a/client/src/views/managers/TileMap.vue +++ b/client/src/views/managers/TileMap.vue @@ -1,11 +1,18 @@