Create a Context Menu with Dojo and Dijit

By  on  
Dojo Context Menu

Context menus, used in the right type of web application, can be invaluable.  They provide shortcut methods to different functionality within the application and, with just a right click, they are readily available.  Dojo's Dijit frameworks provides an easy way to create stylish, flexible context menus in just minutes.

The Dojo JavaScript

/* require necessary classes */
dojo.require('dijit.Menu');
dojo.require('dijit.MenuSeparator');
dojo.require('dijit.MenuItem');
dojo.require('dijit.PopupMenuItem');

The above requires the necessary widget classes that will be used in the context menu.

The Context Menu HTML

<-- menu container -->
<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display:none;">

	<-- enabled menu item -->
	<div dojoType="dijit.MenuItem" id="enabledItem" onClick="Clicked enabled item!">Enabled Item</div>
	
	<-- disabled menu item -->
	<div dojoType="dijit.MenuItem" disabled="true">Disabled Item</div>
	
	<-- separator -->
	<div dojoType="dijit.MenuSeparator"></div>
	
	<-- menu items with icons -->
	<div dojoType="dijit.MenuItem" iconClass="dijitIconCut"
		onClick="alert('Cutting!')">Cut</div>
	<div dojoType="dijit.MenuItem" iconClass="dijitIconCopy"
		onClick="alert('not actually copying anything, just a test!')">Copy</div>
	
	<div dojoType="dijit.MenuSeparator"></div>
	
	<-- nested popup menus with items -->
	<div dojoType="dijit.PopupMenuItem">
		<span>Enabled Submenu</span>
		<div dojoType="dijit.Menu" id="submenu2">
			<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
			<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
			<div dojoType="dijit.PopupMenuItem">
				<span>Deeper Submenu</span>
				<div dojoType="dijit.Menu" id="submenu4">
					<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 1!')">Sub-sub-menu Item One</div>
					<div dojoType="dijit.MenuItem" onClick="alert('Sub-submenu 2!')">Sub-sub-menu Item Two</div>
				</div>
			</div>
		</div>
	</div>
	
	<-- popup menu with disabled item -->
	<div dojoType="dijit.PopupMenuItem" disabled="true">
		<span>Disabled Submenu</span>
		<div dojoType="dijit.Menu" id="submenu3" style="display: none;">
			<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')">Submenu Item One</div>
			<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')">Submenu Item Two</div>
		</div>
	</div>
</div>

The menu is based on a system of nested DIV elements.  The top element is a dijit.Menu widget with child dijit.MenuItem widgets.  You may also add a dijit.MenuSeparator widget or a dijit.PopupMenuItem widget with child dijit.MenuItem widgets to create a popup menu.  You may disable menu items with "disabled='true'" declaratively or by using JavaScript:

dijit.byId('enabledItem').attr('disabled','true');

So simple! Context menus may also be created programmatically, but the declarative method of widget creation speeds up development.

This is just another way that Dojo's Dijit framework allows you to quickly create a functional UI widget in minutes!

Recent Features

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

  • By
    7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

Incredible Demos

  • By
    jQuery Wookmark

    The first thing that hits you when you visit Pinterest is "Whoa, the columns are the same width and the photos are cut to fit just the way they should."  Basic web users probably think nothing of it but as a developer, I can appreciate the...

  • By
    Basic AJAX Requests Using MooTools 1.2

    AJAX has become a huge part of the modern web and that wont change in the foreseeable future. MooTools has made AJAX so simple that a rookie developer can get their dynamic pages working in no time. Step 1: The XHTML Here we define two links...

Discussion

  1. Tim

    Looks smooth! Can’t wait for mootools Art to do this kind of stuff.

  2. Hi David, thanks for the look at dojo’s context menu capability. The problem I’m having is I can’t seem to find any hooks to make the menu actually contextual.

    If I create a table with 100 records in it, and then want a context menu that will contain links specific to the record I right click on, I would have to create a div based menu for each and every record on the page. That’s a lot of overhead for something that should be relatively simple.

    I would say that this should be accomplished by only nesting certain parameters/attributes in each row, only creating a single div menu structure and then passing those attributes to the menu each time it’s invoked.

    From what I’ve seen this is not possible with Dojo, but I would REALLY like to be proven wrong!

    • Michael Holly

      Kevin

      I worked out some of the context menu stuff. In the oncontextmenu I call a doEvt(event) function. In that function I set a var equal to the e.target value. This is the object that got clicked on. My problem is that I have set my context menus up with following line…

      pMenu = new dijit.Menu({ targetNodeIds: [“reportpage”] });

      Unfortunately this only seems to work with the initial reportpage and none after that. Not sure what I am going to do. I would like to use this Menu but I may have to roll my own.

    • Michael Holly

      After further examination it appears that the use of the domNodeId as the driver for where the context menu pops up is difficult. Does this scale for a page with 4000 records? I would think doing a dojo query and passing the result should power the dijit.Menu constructor. That way all the records could have a particular styling and also the same context menu behavior tied by just a css name. Having to pass an array of unique DOM ids makes this constructor difficult to use.

    • You could set up a system of event delegation and connect the node that’s clicked when as its clicked. That saves the need to connect to multiple or create many menus.

  3. Miguel

    How can you use the functionality of another dijit in a right click? For example selecting a row right a right click within an Enhanced grid? How do I find the method within enchancedgrid that does the selecting? Does that go in the declaration of the new Menu object?

  4. lemon

    April 5 2016, chrome 49.0.2623.110 (64-bit), mac osx 10.11;
    Does not work.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!