Home > Software design >  How to hide a custom context menu when over a button or element
How to hide a custom context menu when over a button or element

Time:06-03

I am looking for a simple way to hide the custom context menu unless over a button or element. Here is a simple example I coded up containing a custom context menu and a button I wish to have it attached to. I am thinking maybe there could be an event listener that looks out for an on hover over the element, or maybe a function that toggles it on or off when needed? Also i was wondering if the button or element wasn't defined with a class or ID is there still a way to know when you are over it maybe via coordinates (Not necessary just curious if possible)? The idea is there will be multiple elements that will require the context menu but the general space around the elements in the body should not show the custom menu.

function view() {

    const contextMenu = document.getElementById('context-menu');
    const scope = document.querySelector("body");

    //body

    var listLength = contextMenu.children.length;
    for (i = 0; i < listLength; i  )
        contextMenu.removeChild(contextMenu.children[0]);

    contextMenuadd(contextMenu, "line 1 of context menu", 1);
    contextMenuadd(contextMenu, "line 2 of context menu", 2);
    contextMenuadd(contextMenu, "line 3 of context menu", 3);
    contextMenuadd(contextMenu, "line 4 of context menu", 4);

    scope.addEventListener("contextmenu", (event) => {
        event.preventDefault();

        const {
            clientX: mouseX,
            clientY: mouseY
        } = event;

        contextMenu.style.top = `${mouseY}px`;
        contextMenu.style.left = `${mouseX}px`;
        contextMenu.classList.add('visible');
        contextMenu.style.display = 'block';
        contextMenu.style.zIndex = 20000;
        contextMenu.style.position = 'fixed';
        contextMenu.style.width = "360px";
        contextMenu.style.borderRadius = "5px";


    });

    scope.addEventListener("click", (e) => {
        if (e.target.offsetParent != contextMenu) {
            contextMenu.style.display = 'none';
        }
    });

};

document.addEventListener('DOMContentLoaded', view);

function contextMenuadd(contextMenu, menustring, count) {
    var action = function(e) {
        //menuLink;
        let currentRow = $(event.target)[0].parentElement;
        var index = parseInt(currentRow.row);
        var value = currentRow.textContent;
        en(href, '_self');

    };


    var menuitem = document.createElement('LI');
    menuitem.addEventListener('click', action);
    menuitem.classList.add("hotspot__item");
    menuitem.innerHTML = '<a href="#">'   menustring   '</a>';
    menuitem.row = count;


    contextMenu.appendChild(menuitem);

};

document.addEventListener('click', function(e) {
    let inside = (e.target.closest('#container'));
    if (!inside) {
        let contextMenu = document.getElementById('contextMenuId');
        contextMenu.setAttribute('style', 'display:none');
    }
});
#context-menu {
    position: fixed;
    z-index: 10000;
    width: 180px;
    background: #ffaaaa;
    border-radius: 5px;
    display: none;
}

#context-menu.item {
    padding: 2px 4px;
    font-size: 12px;
    color: #eee;
    cursor: pointer;
    border-radius: inherit;
}
<body id="allofit">
    <header>
        <h2>Context Menu Example</h2>
    </header>

    <!-- <gm:figure-group> -->

    <div id='sdi_canvas1' style="width:400px; height:400px">

        <button id="container"> this is data in my DIV</button>

    </div>
    <div id="context-menu"  
        oncontextmenu="ShowMenu('contextMenu',event)" style="display:none">
        <div >Option 1</div>
        <div >Option 2</div>
    </div>

</body>

Here's a fiddle for reference JSFiddle

CodePudding user response:

Have you tried using a 'mouseover' and 'mouseout' events?

Let me know if this what you looking for:

const menu = document.querySelector('.menu')
const btn = document.getElementById('btn');

btn.addEventListener('mouseover', () => {
  menu.style.display = "block";
});
btn.addEventListener('mouseout', () => {
  menu.style.display = "none";
})
.menu {
  display: none;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <button id="btn">Hover me</button>
  <ul >
    <li>Test 1</li>
    <li>Test 1</li>
  </ul>
</body>
</html>

CodePudding user response:

  • You can add a class to all the elements that will show the custom context menu.
  • And oncontextmenu, you check if the element contains the class then toggle the context menu accordingly.

Try this

document.addEventListener('DOMContentLoaded', () => {
    const scope = document.querySelector("body");
    const contextMenu = document.getElementById('context-menu');

    scope.addEventListener("contextmenu", (event) => {
        event.preventDefault();

        if( event.target.classList.contains('has-content-menu') || 
            event.target.closest('.has-content-menu') !== null 
        ){
            contextMenu.style.top     = event.clientY   'px';
            contextMenu.style.left    = event.clientX   'px';
            contextMenu.style.display = 'block';
        }else{
            contextMenu.style.display = 'none';
        }
    });

    scope.addEventListener("click", (event) => {
        contextMenu.style.display = 'none';
    });
});
*, ::after, ::before {
    box-sizing: border-box;
}

body, html {
    height: 100%;
}

#context-menu {
    position: fixed;
    z-index: 10000;
    width: 180px;
    background: #ffaaaa;
    border-radius: 5px;
    display: none;
    z-index: 20000;
}

#context-menu.item {
    padding: 2px 4px;
    font-size: 12px;
    color: #eee;
    cursor: pointer;
    border-radius: inherit;
}
<button >  this is data in my DIV</button>
<div id="context-menu">
    <div >Option 1</div>
    <div >Option 2</div>
</div>

  • Related