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 @@
-
+