My Technical Notes

Wednesday, 3 November 2010

JQuery Context Menu

I have had a look at many JQuery context menu plugins and all of them are incredibly inflexible. For example jQuery.contextMenu can only be used for right clicks only, and can only show an unordered list as opposed to any html.

What I have found is that JQuery UI's Dialog is sufficient to create any arbitrary context menu as all we need to do is bind to the "contextmenu" event and show a dialog. JQuery UI Dialog handles all the sizing and positioning for us (although you need to provide it with the viewport x and y coordinates).

Below is a little plugin that I have devised which defines two JQuery functions; one called setUpContextMenu which creates a JQuery UI Dialog and keeps it closed (by using { autoOpen: false } option). The second function called openContextMenu opens (or displays) the context menu:


(function($) {
    $.fn.setUpContextMenu = function() {
        $(this).dialog({
            autoOpen: false,
            modal: true,
            resizable: false,
            width: 'auto',
            height: 'auto',
            minHeight: 'auto',
            minWidth: 'auto'
        });

        return $(this);
    };

    $.fn.openContextMenu = function(jsEvent) {
        var menu = $(this);
        menu.css('padding', 0);

        menu.dialog('option', 'position', [jsEvent.clientX, jsEvent.clientY]);
        menu.unbind('dialogopen');
        menu.bind('dialogopen', function(event, ui) {
            $('.ui-dialog-titlebar').hide();
            $('.ui-widget-overlay').unbind('click');
            $('.ui-widget-overlay').css('opacity', 0);
            $('.ui-widget-overlay').click(function() {
                menu.dialog('close');
            });
        });
        menu.dialog('open');

        return menu;
    };
})(jQuery); 

All in all, only 34 lines of code.

Let's go through an example. Let's say that you want a context menu with four different options to show up when the user right clicks a part of the screen. We start by defining this context menu as an HTML div:


<div id="context-menu">
  <a href="javascript:void(0)" id="option1">Option 1</a>
  <a href="javascript:void(0)" id="option2">Option 2</a>
  <a href="javascript:void(0)" id="option3">Option 3</a>
  <a href="javascript:void(0)" id="option4">Option 4</a>
</div>

Instead of styling them up, it is probably a lot easier to turn them into JQuery UI Buttons:


$('#context-menu a').css('display', 'block').button();
When the page loads, we want to turn the context-menu div into a context menu:

$('#context-menu').setUpContextMenu();
Lastly, we want the context menu to appear whenever we right click the page. For this, we use the contextmenu event:

$(document).bind('contextmenu', function(e) {
   $('#context-menu').openContextMenu(e);
   return false;
});
Thus when you right click you will see the following:

EDIT: Since we are in control of opening the context menu, we can open it whenever we want. For example, if we wanted to open the context menu when a user were to click on a link, all we need to do is open it in the click event:


// a#link is an anchor tag with an id of 'link'
$('a#link').click(function(e) {
   $('#context-menu').openContextMenu(e);
   return false;
});

5 comments:

Fernando said...

It works great. Thanks

Zain Akhtar said...

Not working for me... kindy upload sample file... thenks

Vignesh said...

wow works...

how do i change the look of the thing...

right now it looks big and ugly..

Scriptonaut said...

I got it working, however how do I figure out which item I'm right clicking on. What if I want a different menu depending on what object I click?

theBrettman said...

u freakin rock, dude!