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
    Create a CSS Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

  • By
    Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() - this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

Incredible Demos

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!