Search code examples
javascriptcontextmenupreventdefault

JavaScript preventDefault is delayed/not working when app is deployed on a network


I have an application with custom context menus that are displayed on right-click. When that happens, I don't want default windows menu to appear. I use the following code to accomplish that:

            // right click
if (e.which == 3) {
    let menuVisible = false;
    const toggleMenu = command => {
        menu.style.display = command === "show" ? "block" : "none";
        menuVisible = !menuVisible;
    };
    const setPosition = ({ top, left }) => {
        menu.style.left = `${left}px`;
        menu.style.top = `${top}px`;
        toggleMenu("show");
    };
    const origin = {
        left: e.pageX,
        top: e.pageY
    };
    setPosition(origin);
    // toggle right clicked menu visibility
    window.addEventListener("click", e => {
        if (menuVisible) toggleMenu("hide");
    });
    // Set up an event handler for the document right click
    document.addEventListener("contextmenu", function (event) {
        // Only do something when the element that was actually right-clicked
        if (event.target.classList.contains("menu")) {
            event.preventDefault();
        }
    });
}

When app is running on localhost everything works as expected. However, when application is deployed on a network server and then accessed from any clients on the network the default menu appears first and then custom menu displayed behind it. There are no any errors. Any advise on how to fix that will be greatly appreciated.

Update: It seems that if right mouse button is hold not just clicked the behavior is as expected.


Solution

  • I think you'll have to do something like this:

    let menuVisible = false;
    
    const toggleMenu = command => {
      menu.style.display = command === "show" ? "block" : "none";
      menuVisible = !menuVisible;
    };
    
    const setPosition = ({ top, left }) => {
      menu.style.left = `${left}px`;
      menu.style.top = `${top}px`;
    };
    
    // Set up an event handler for the document right click
    document.addEventListener("contextmenu", function (e) {
      if (e.target.classList.contains("menu")) {
        e.preventDefault();
        setPosition({
          left: e.pageX,
          top: e.pageY
        });
        toggleMenu("show");
      }
    });
    
    // Hide menu
    document.addEventListener("click", function(e) {
      if (e.target.classList.contains("menu-item")) {
        alert("menu item was clicked");
      }
      toggleMenu("hide"); 
    });
    #menu {
      position: absolute;
      padding: 10px;
      background: #eee;
      list-style-type: none;
    }
    <ul id="menu" style="display:none;">
      <li class="menu-item">Item 1</li>
      <li class="menu-item">Item 2</li>
      <li class="menu-item">Item 3</li>
    </ul>
    
    <button class="menu">toggle menu on right click</button>