I just wanted to improve letiagoalves excellent answer with a few more suggestions.
Here you will find a step-by-step guide on how to add a context menu to any html element.
Markup:
First, add the menu from the bootstrap drop-down list . Add it anywhere in your HTML, preferably at the root level of the body. The .dropdown-menu class sets display:none , so it is initially invisible.
It should look like this:
<ul id="contextMenu" class="dropdown-menu" role="menu"> <li><a tabindex="-1" href="#">Action</a></li> <li><a tabindex="-1" href="#">Another action</a></li> <li><a tabindex="-1" href="#">Something else here</a></li> <li class="divider"></li> <li><a tabindex="-1" href="#">Separated link</a></li> </ul>
Extension Settings:
To preserve the modular design, we will add our JavaScript code as a jQuery extension called contextMenu .
When we call $.contextMenu , we will pass a settings object with two properties:
menuSelector accepts the jQuery menu selector that we created earlier in HTML.menuSelected will be called when you click on the action of the context menu.
$("#myTable").contextMenu({ menuSelector: "#contextMenu", menuSelected: function (invokedOn, selectedMenu) {
Plugin Template:
Based on the jQuery template plugin template , we will use the Immediately-Invoked Function Expression so that we do not confuse the global namespace. Since we have jQuery dependencies and need access to the window, we will pass them as variables so that we can survive while minimizing. It will look like this:
(function($, window){ $.fn. contextMenu = function(settings) { return this.each(function() {
Well, no more plumbing. Here's the meat function:
Handle events with the right mouse button:
We will handle the mouse event of the contextMenu object, which is called an extension. When the event fires, we take the drop-down menu that we added at the beginning. We will find it using the selector string passed by the parameters when initializing this function. We will change the menu by following these steps:
- We
e.target property and save it as a data attribute called invokedOn , so we can later identify the item that raised the context menu. - We will switch the menu display to visible using
.show() - We will place the element using
.css() .- We need to make sure that this
position parameter is set to absolute . - Then we will set the left and top location using the
pageX and pageY event.
- Finally, to prevent right-clicking on the opening of our own menu, we
return false to stop javascript from working with anything else.
It will look like this:
$(this).on("contextmenu", function (e) { $(settings.menuSelector) .data("invokedOn", $(e.target)) .show() .css({ position: "absolute", left: e.pageX, top: e.pageY }); return false; });
Correction of the boundary conditions of the menu:
This will open the menu at the bottom right of the cursor that opened it. However, if the cursor is to the right of the screen , the menu should open to the left. Similarly, if the cursor is at the bottom, the menu should open at the top. It is also important to distinguish between the bottom of the window , which contains the physical frame, and the bottom of the document , which represents the entire html DOM, and can scroll far past the window.
To do this, we will set the location using the following functions:
We will call them as follows:
.css({ left: getMenuPosition(e.clientX, 'width', 'scrollLeft'), top: getMenuPosition(e.clientY, 'height', 'scrollTop') });
This function will call this function to return the corresponding position:
function getMenuPosition(mouse, direction, scrollDir) { var win = $(window)[direction](), scroll = $(window)[scrollDir](), menu = $(settings.menuSelector)[direction](), position = mouse + scroll;
Bind events to a menu item:
After displaying the context menu, we need to add an event handler to listen for click events on it. We will remove any other bindings that might be added so that we do not fire the same event twice. They can occur at any time when the menu was opened, but nothing was selected due to a click. Then we can add a new binding to the click event, where we look at the logic in the next section.
As valepu noted , we donβt want to register clicks on anything other than menu items, so we configure the delegated handler by passing a selector to the on function, which will "filter the descendants of the selected elements that trigger the event."
So far, the function should look like this:
$(settings.menuSelector) .off('click') .on( 'click', "a", function (e) {
Mouse click
As soon as we find out that a click has occurred in the menu, we will do the following: we will hide the menu from the .hide() screen. Then we want to save the item from which the menu was called, as well as the selection from the current menu. Finally, we run the option of the function that was passed to the extension using .call() on the property and pass it to the targets as arguments.
$menu.hide(); var $invokedOn = $menu.data("invokedOn"); var $selectedMenu = $(e.target); settings.menuSelected.call($(this), $invokedOn, $selectedMenu);
Hide on click:
Finally, as in most context menus, we want to close the menu when the user clicks on it. To do this, we will listen to any click events on the body and close the context menu if it is open as follows:
$('body').click(function () { $(settings.menuSelector).hide(); });
Note : Thanks to Sadhir's comment , Firefox linux fires the click event on document during a right-click, so you need to set the listener to body .
Example Syntax:
The extension will return with the original object that raised the context menu and the menu item that was clicked. You may have to cross dom with jQuery to find something meaningful from the targets, but this should provide a good level of basic functionality.
Here is an example of returning information for the selected item and action:
$("#myTable").contextMenu({ menuSelector: "#contextMenu", menuSelected: function (invokedOn, selectedMenu) { var msg = "You selected the menu item '" + selectedMenu.text() + "' on the value '" + invokedOn.text() + "'"; alert(msg); } });
Screenshot:

Update Note:
This answer has been substantially updated by porting it to the jQuery extension method. If you want to see my original, you can view the message history, but I believe that this final version uses much better coding methods.
Bonus Function :
If you want to add some useful functions for powerusers or on your own in the development of functions, you can bypass the context menu based on any key combinations that are held when you right-click. For example, if you want to allow the context menu of the source browser to be displayed while holding Ctrl , you can add this as the first line of the contextMenu handler: