HTML context menu without framework
Without any frameworks, add context menus in JavaScript and CSS to application or web page elements.
This script is compatible with IE9, Firefox, Chrome, Safari.
The default menu can be replaced by right-clicking on the menu selected for this interface element. If you just want to show a window or list when the mouse goes to an item, you will use a hint.
It is known that the onClick attribute detects the click of any button, but the onSpecttMenu attribute is used to respond to the right button.
The first step is to delete the default context menu. To do this, it is enough to return false.
<div oncontextmenu="return false"></div>
Since we are going to call the function in response to the event, the function will have to return false and return the result of the function as follows:
<div oncontextmenu="return mafonction()"></div>
To build a context menu, the function generates a layer that is dynamically populated with a list of menu items. For example, the Rename and Edit commands are added. The stylesheet is statically included in the page containing the script.
Here's a demonstration of the script followed by the full source code .
The HTML code is simple:
<div oncontextmenu="return monmenu(this)"> Démonstration : Cliquez le bouton droit </div>
JavaScript code first captures the current mouse position to place the created context menu above the corresponding item.
A certain feature works on all modern browsers. Since the script is for an application, you can stall the navigation tools of the past.
var xMousePosition = 0; var yMousePosition = 0; document.onmousemove = function(e) { xMousePosition = e.clientX + window.pageXOffset; yMousePosition = e.clientY + window.pageYOffset; };
The pageXOfset and pageYOfset attributes allow you to take into account the page progress (which is actually useless if the interface does not work in the browser window ).
You can dispense with this function by placing the context menu as a child of the corresponding element, rather than its container, and giving it a fixed position next to that element .
The menu is then created and placed according to the mouse position.
Full JavaScript code from the context menu
var xMousePosition = 0; var yMousePosition = 0; document.onmousemove = function(e) { xMousePosition = e.clientX + window.pageXOffset; yMousePosition = e.clientY + window.pageYOffset; }; function rename(element) { alert("Renommer"); } function edit(element) { alert("Editer"); } function monmenu(element) { var x = document.getElementById('ctxmenu1'); if(x) x.parentNode.removeChild(x); var d = document.createElement('div'); d.setAttribute('class', 'ctxmenu'); d.setAttribute('id', 'ctxmenu1'); element.parentNode.appendChild(d); d.style.left = xMousePosition + "px"; d.style.top = yMousePosition + "px"; d.onmouseover = function(e) { this.style.cursor = 'pointer'; } d.onclick = function(e) { element.parentNode.removeChild(d); } document.body.onclick = function(e) { element.parentNode.removeChild(d); } var p = document.createElement('p'); d.appendChild(p); p.onclick=function() { rename(element) }; p.setAttribute('class', 'ctxline'); p.innerHTML = "Renommer"; var p2 = document.createElement('p'); d.appendChild(p2); p2.onclick=function() { edit(element) }; p2.setAttribute('class', 'ctxline'); p2.innerHTML = "Editer"; return false; }
The remame () and edit () elements are for demonstration purposes only and will be replaced by their own functions.
This code reflects two design options:
- The menu is created dynamically by inserting new tags in the DOM.
- There is no add strings function, a specific code is created for each command. This is enough if there are few context menus in the application, but we will have to develop it if we have a lot. In fact, you just need to add a line by copying/pasting and changing the data .
The menu created in this way is equivalent to the following static code, where you can see that it would be more difficult to associate events with tags:
<body onclick="document.getElementById('ctxmenu1').parentNode.removeChild(d);"> <div class="ctxmenu" id="ctxmenu1" onmouseover="this.style.cursor = 'pointer'" onclick="this.parentNode.parentNode.removeChild(this)"> <p class="ctxline" onclick="rename(element)">Renommer</p> <p class="ctxline" onclick="edit(element)">Editer</p> </div>
The item variable represents the object with which the context menu is associated. In our example, the name of the file in the list.
Full CSS code
.ctxmenu { position:absolute; min-width: 128px; height:auto; padding: 8px; margin:0; margin-left:32px; margin-top:-16px; border: 1px solid #999; background: #F8F8F8; box-shadow: 2px 2px 2px #AAA; z-index:11; overflow: visible; } .ctxline { display:block; margin:0px; padding:2px 2px 2px 8px; border:1px solid #F8F8F8; border-radius:3px; font-size:13px; font-family:Arial, Helvetica, sans-serif; overflow:visible; } .ctxline:hover { border:1px solid #BBB; background-color: #F0F0F0; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); }
Some properties are important:
- Absolute position for the menu (.ctxmenu). This allows you to specify left and top values that are ignored in other modes.
- overflow: visible so that: the menu is always visible, even if it extends beyond the container.
- screen: block for lines (.ctxline). This allows you to customize the <p> .
The rest is a matter of appearance.
An attempt was made to look quite similar to the appearance of the standard Windows environment. Because the appearance of Windows items depends on the theme you choose, the appearance of context menus on your system may not be the same. But it's hard to do better in this regard...
Restriction
When I use this context menu in production, sometimes the browser incrementally assigns the left and top properties by adding predefined values to the container values. This is actually due to <! doctype html> HTML 5 and does not occur with previous doctypes.
To work around this problem, you can add a menu as a child of the object it is associated with, and statically position the menu with a negative top value. But we can also change the doctor.
In fact, the best solution is to make the container position static (this is the default):
#content
{
position:absolute;
left: 218px;
top: 92px;
}
Replace:
#content
{
position:static;
margin-left: 218px;
margin-top: 92px;
}
This is what was done for the current page. Thus, the top and left properties are correctly assigned to the menu.