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 Namespaced Classes with MooTools

    MooTools has always gotten a bit of grief for not inherently using and standardizing namespaced-based JavaScript classes like the Dojo Toolkit does.  Many developers create their classes as globals which is generally frowned up.  I mostly disagree with that stance, but each to their own.  In any event...

  • 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...

Incredible Demos

  • By
    Digg-Style Dynamic Share Widget Using MooTools

    I've always seen Digg as a very progressive website. Digg uses experimental, ajaxified methods for comments and mission-critical functions. One nice touch Digg has added to their website is their hover share widget. Here's how to implement that functionality on your site...

  • By
    Introducing MooTools ScrollSide

    This post is a proof of concept post -- the functionality is yet to be perfected. Picture this: you've found yourself on a website that uses horizontal scrolling instead of vertical scrolling. It's an artistic site so you accept that the site scrolls left to right.

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!