Right click contextual menu's are a great way to hide menu items that are less commonly used, and that you want to keep out of sight until a user decides that they need to use them. You might commonly find them implemented in text editors, drawing apps and typically anything that requires multiple options.
In this article, we are going to implement a custom vanilla JavaScript contextual menu that triggers when the user triggers a mouse click event.
The result will look something like the following:
There is no native contextual-menu support in HTML just yet, which means that you will have to build it from the ground-up yourself.
Lucky for us, JavaScript provides the 'contextmenu' event handler which will handle detecting when the user has performed a right-click.
So let's get started.
1. Creating the menu-items
Let's start off by creating a list of JSON object that will house all of the menu-items that are going to be rendered inside of the context menu.
This will make updating the list of contextual menu links a more streamlined process later on. And if you have multiple context menu's that you need to generate, you could then simply just create another collection and point your menu to that particular dataset.
var contextmenu = [{
Text: 'Link 1',
Url: 'http://www.google.com',
Action: function(){
alert('hello world');
}
},
{
Text: 'Link 2',
Url: 'http://www.google.com',
Action: function(){
alert('hello world');
}
},
{
Text: 'Link 3',
Url: 'http://www.google.com',
Action: function(){
alert('hello world');
}
}
];
For the sake of this article, I will only bind the 'contextmenu' event to a single element. You typically DO NOT want to hijack the right-click menu that the browser provides from the user. But you can bind it to individual elements, which is the approach that I will be showing.
Next up, let's load these menu-items to the context menu.
2. Creating the menu
For the sake of performance, we can create the new context menu on the page pre-loaded and then simply hide it by default. Once the user performs the right-click event, we can simply toggle the display of the menu to show it, and once again hide it on left-click.
Add the following element somewhere near the bottom of the page. Don't worry about placement, as it will be set to position: fixed in the CSS that follows.
<html lang="en"><
<body>
<div class='context-menu' id='context1'></div>
</body>
</html>
Notice that it's empty. And that's because we'll dynamically populate it with menu items when the user right-clicks anywhere within that element.
Here is the CSS needed to have it render fixed on the page.
.context-menu{
position: fixed;
display: none;
width: 140px;
box-shadow: 2px 2px 9px #aaa;
overflow: hidden;
border:solid 1px #aaa;
}
.context-menu > div{
padding: 10px;
background: #eee;
border-bottom: solid 1px #aaa;
font-size: 11pt;
cursor:pointer;
}
.context-menu > div:hover{
background:#fff;
}
.context-menu.show{
display:block;
}
The main CSS property to focus on here is the position of the menu, which I've set to 'fixed' meaning that it will stay stationary wherever the user decides to click. The X and Y position of the menu will be set in JavaScript once the click event occurs.
Next up, let's render the menu items from the contextmenu array defined in the beginning.
3. Rendering the menu items
While you can render the menu just one time during the beginning page loading phase, I will load the menu on each mouse click and I will explain why right after.
The renderContextMenu function will take 2 arguments, the first being the array of menu-items that we will use to bind the menu, and the second will be the DOM element that we are binding to.
Notice that the menu-item also binds the click event to whatever function property is assigned.
function renderContextMenu(menu, context){
context.innerHTML ='';
menu.forEach(function(item){
let menuitem = document.createElement('div');
menuitem.innerHTML = item.Title;
menuitem.addEventListener('click', item.Action);
context.appendChild(menuitem);
});
}
And as mentioned, we will call the renderContextMenu function each time that the user right-clicks.
window.addEventListener('load', function(){
document.getElementById('parent').addEventListener('contextmenu', function(e){
e.preventDefault();
renderContextMenu(menu, document.getElementById('context'));
// position menu at the right-click cursor
document.getElementById('context').style.left = e.clientX + 'px';
document.getElementById('context').style.top = e.clientY + 'px';
document.getElementById('context').classList.add('show');
});
document.getElementById('parent').addEventListener('click', function(e){
e.preventDefault();
document.getElementById('context').classList.remove('show');
});
});
So why load the items each time the user right-clicks? Well, the main point of a contextual menu is to be just that. Contextual. Which means that it should respond to wherever it is that you are clicking on.
If you are clicking on a text editor for example then you'll want menu items associated with editing. If you are right clicking on an image, then you might want "image" related actions It's all about the context. Which means that you'll want to render the menu in real-time.
4. Clearing the menu
And the last, but the simplest, is to simply get rid of the menu when a user is done with it. And we can do that by toggling off the 'show' class that was added during the render event.
Also note that to mimic the current logic of rendering a contextual menu, you'll more than likely want to clear it during a left-click event. For this, we can add another event-handler to the parent element to capture a standard mouse click.
document.getElementById('paragraph1').addEventListener('click', function(e){
document.getElementById('context').classList.remove('show');
}
And there you have it. A quick right-click contextual menu implementation that you can use as a base for your own projects.