A right mouse click on a web page will bring up the default browser menu, but many times you need to customize the right click menu (for example, online document editor, custom video player, etc.). Today we’re going to quickly implement a custom right-click menu.

Preview:

contextmenuEvent listeners

First, we need to disable the default menu pop-up behavior of the browser by blocking the default behavior of the contextMenu event and triggering the display of the custom menu:

document.addEventListener("contextmenu", (e) => {
  e.preventDefault();
  showMenu(e);
});
Copy the code

To construct the menu

1. Implement singletons

There should only be one instance of a menu on a page, so we use the singleton pattern to create a menu. A typical singleton constructor can be implemented as follows:

const ContextMenu = function (options) {
  // Unique instance
  let instance;

  // Create the instance method
  function createMenu() {
    // todo
  }

  return {
    // The only way to get an instance
    getInstance: function () {
      if(! instance) { instance = createMenu(); }returninstance; }}; };Copy the code

2. Create a menu instance

That is to implement the above createMenu method.

The specific configuration of the menu is passed in through options. The structure of options is defined as:

Options: {menus: [{name: string, onClick: Function}]}Copy the code

We iterate over options.menus to generate a list of menus, mount them into the body, and finally return an instance of the menu:

function createMenu() {
  const ul = document.createElement("ul");
  ul.classList.add("custom-context-menu");
  const { menus } = options;
  if (menus && menus.length > 0) {
    for (let menu of menus) {
      const li = document.createElement("li"); li.textContent = menu.name; li.onclick = menu.onClick; ul.appendChild(li); }}const body = document.querySelector("body");
  body.appendChild(ul);
  return ul;
}
Copy the code

The main logic for creating the menu is now complete.

3. Initialize the menu

Next, pass options to ContextMenu to initialize the singleton constructor:

const menuSinglton = ContextMenu({
  menus: [{name: "custom menu 1".onClick: function (e) {
        console.log("menu1 clicked"); }, {},name: "custom menu 2".onClick: function (e) {
        console.log("menu2 clicked"); }, {},name: "custom menu 3".onClick: function (e) {
        console.log("menu3 clicked"); }},]});Copy the code

Once initialized, you can get the menu instance via menusinglton.getInstance ().

According to the menu

When we right-click the page, we can get the coordinates of the mouse, set the menu as Position: Fixed, and set the upper left corner of the menu as the mouse coordinates, so as to realize the popup of the menu at the mouse click position:

function showMenu(e) {
  const menus = menuSinglton.getInstance();
  menus.style.top = `${e.clientY}px`;
  menus.style.left = `${e.clientX}px`;
  menus.style.display = "block";
}
Copy the code

The hidden menu

Finally, we need to hide the menu when we click on other areas of the page:

function hideMenu(e) {
  const menus = menuSinglton.getInstance();
  menus.style.display = "none";
}

document.addEventListener("click", hideMenu);
Copy the code

And we’re done!!

Codepen Trick by Day (2020-07-05) Custom Context Menus

Tricks by Day. Quantitative change causes qualitative change. I hope you can learn more every Day with me and make technology more interesting.

All the examples will be put together in my tricks-by-day Github project. You are welcome to visit 😊