The Menu plugin for the Dojo EnhancedGrid gives you the ability to add context menus to grid headers, rows, cells, and selected regions. In this post, I’ll show how to add the plugin and use it.
Dojo Data Grid Series
- Part 1: Concepts and Default Features
- Part 2: Creating a REST Service
- Part 3: Creating Your First Grid
- Part 4: Additional Grid Features
- Part 5: Grid Column Features
- Part 6: Reordering Columns
- Part 7: Sorting
- Part 8: Opening Documents
- Part 9: Multi-Row Entries
- Part 10: Full-Text Searching and Field-Specific Filtering
- Part 11: Editable Columns
- Part 12: Highlighting Edited Rows
- Part 13: Create a Dojo EnhancedGrid
- Part 14: Enhanced Filtering with No Coding
- Part 15: Enhanced Printing
- Part 16: Exporting Grid Data
- Part 17: EnhancedGrid Drag and Drop
This post assumes you already have a Dojo Data Grid control set up to use the Dojo EnhancedGrid, based on the instructions in this post.
Load the Menu Plugin (and more)
The dojox.grid.enhanced.plugins.Menu module must be included on the page, so add it to the page resources. Properties > Resources > Add > Dojo Module…
You also need to include the dijit menu and dijit menu item modules, since they’re required to build the context menus.
In this grid, I’m also including the Printer plugin, so I can trigger printing functions from the context menus.
Add the Plugin to the Grid
The first step made the plugin module available, but you also need to add it to the grid.
Go to the properties of the Dojo Data Grid > Dojo and click the Add button. Add two properties as shown here:
This is the first example of including more than one EnhancedGrid plugin.
contextMenus is the name of a JavaScript object I’ve created to build the context menus (shown below).
Note: The row selection property is necessary in order to select rows in the grid.
Creating the Menus
To create the context menus, you create an object that contains properties for all of the context menus to define. You then add menu items to those menus and provide onClick events to take action when a context menu option is selected. Example code is shown below.
Using the Context Menus
Right click on a selected region
Context Menu Code
This code builds all four types of context menus and provides several actions:
// Set up the context menu object dijit menus var contextMenus = { headerMenu: new dijit.Menu(), rowMenu: new dijit.Menu(), cellMenu: new dijit.Menu(), selectedRegionMenu: new dijit.Menu() }; // Header Context Menu contextMenus.headerMenu.addChild(new dijit.MenuItem({label: "Print All", onClick:printAll})); contextMenus.headerMenu.addChild(new dijit.MenuItem({label: "Print Selected", onClick:printSelected})); contextMenus.headerMenu.addChild(new dijit.MenuItem({label: "Print Custom", onClick:printCustomized})); contextMenus.headerMenu.startup(); // Row Context Menu contextMenus.rowMenu.addChild(new dijit.MenuItem({label: "Display Click Location", onClick: rowDisplayClickLocation})); contextMenus.rowMenu.addChild(new dijit.MenuItem({label: "Preview All", onClick:previewAll})); contextMenus.rowMenu.addChild(new dijit.MenuItem({label: "Preview Selected", onClick:previewSelected})); contextMenus.rowMenu.addChild(new dijit.MenuItem({label: "Preview Custom", onClick:previewCustomized})); contextMenus.rowMenu.startup(); // Cell Context Menu contextMenus.cellMenu.addChild(new dijit.MenuItem({label: "Display Click Location", onClick:cellDisplayClickLocation})); contextMenus.cellMenu.addChild(new dijit.MenuItem({label: "Cell Menu Item 1", iconClass:'dijitEditorIcon dijitEditorIconCopy',onClick:function(){alert('copy!')}})); contextMenus.cellMenu.addChild(new dijit.MenuItem({label: "Cell Menu Item 2", iconClass:'dijitEditorIcon dijitEditorIconPaste', onClick:function(){alert('paste!')}})); contextMenus.cellMenu.addChild(new dijit.MenuItem({label: "Cell Menu Item 3", iconClass:'dijitEditorIcon dijitEditorIconCut', onClick:function(){alert('cut!')}})); contextMenus.cellMenu.startup(); // Selected Region Context Menu contextMenus.selectedRegionMenu.addChild(new dijit.MenuItem({label: "Context Info", onClick:function(){alert('row: ' + rowIndex + '\ncell: ' + cellIndex);}})); contextMenus.selectedRegionMenu.addChild(new dijit.MenuItem({label: "Alert", onClick:function(){alert('selected region')}})); contextMenus.selectedRegionMenu.startup();
Note: There are references to print and print preview functions from the Printer plugin for the EnhancedGrid. The code for those functions can be found in this post.
Working with the Click Context
What we’ve seen so far is fine to trigger javascript events, but, commonly, you will want to know the context of the click so you can execute logic targeted to that context.
At least 1 of 4 events is fired on the grid when the user right clicks to bring up a context menu:
- onRowContextMenu(e)
- onCellContextMenu(e)
- onHeaderCellContextMenu(e)
- onSelectedRegionContextMenu(e)
These event handlers all automatically get a handle to an event object (e) that has context information.
To use them, you need to attach a function to the event. In that function, you can set global JavaScript variables with context information. Then, in your context menu item functions, you can access that context information.
To retrieve and use the location of a context menu click, follow these steps:
1. Define global variables and the event handler function(s) in an Output Script tag or client-side JavaScript library:
var rowIndex; var cellIndex; // onRowContextMenu Event Handler // Retrieves the rowIndex and cellIndex and stores them in a global variable for the menu click event handlers to reference // NOTE: This event fires when clicking on a row selector or any cell in the row function rowContextMenuEvent (e) { rowIndex = e.rowIndex; cellIndex = e.cellIndex; } // onCellContextMenu Event Handler // Retrieves the rowIndex and cellIndex and stores them in a global variable for the menu click event handlers to reference // NOTE: This event fires when clicking on any cell in the row. If an onRowContextMenu event handler is also defined, that will fire before this event handler fires. function cellContextMenuEvent (e) { rowIndex = e.rowIndex; cellIndex = e.cellIndex; }
2. Attach the event handler functions to the grid events on the onClientLoad event of your page. Here are examples of attaching to two of the events:
dojo.connect(dijit.byId("#{id:djxDataGrid1}"), "onRowContextMenu", rowContextMenuEvent); dojo.connect(dijit.byId("#{id:djxDataGrid1}"), "onCellContextMenu", cellContextMenuEvent);
3. Create one or more menu action functions that refer to the global variables and then work with the context.
// Row context menu function to display the index of the row function rowDisplayClickLocation () { alert('row index: ' + rowIndex + '\ncell index: ' + cellIndex); } // Cell context menu function to display the index of the row and cell function cellDisplayClickLocation () { alert('row index: ' + rowIndex + '\ncell index: ' + cellIndex); }
When the user right-clicks on a row selector to bring up the row context menu, the onRowContextMenu event function runs first, then the context menu is displayed, then the user selects an option from the context menu.
It is interesting to note that if you have event handlers defined for onRowContextMenu and onCellContextMenu, the onRowContextMenu event handler will run first, then the onCellContextMenu event handler will run second. If all you’re doing is getting the row and cell index where the click happend, you don’t even need the onCellContextMenu event handler.
Properties of the Event Object
Just for kicks, I ran a little script to tell me all of the properties available to that event object that’s provided to the context menu event handlers.
Here’s the list, in case you’d like to dig into any of them further:
rowNode, rowIndex, dispatch, grid, sourceView, cellNode, cellIndex, cell, type, target, currentTarget, eventPhase, bubbles, cancelable, timeStamp, defaultPrevented, stopPropagation, preventDefault, initEvent, stopImmediatePropagation, which, rangeParent, rangeOffset, pageX, pageY, isChar, screenX, screenY, mozMovementX, mozMovementY, clientX, clientY, ctrlKey, shiftKey, altKey, metaKey, button, buttons, relatedTarget, mozPressure, mozInputSource, initMouseEvent, initNSMouseEvent, getModifierState, originalTarget, explicitOriginalTarget, preventBubble, preventCapture, getPreventDefault, isTrusted, view, detail, initUIEvent, layerX, layerY, cancelBubble, NONE, CAPTURING_PHASE, AT_TARGET, BUBBLING_PHASE, MOUSEDOWN, MOUSEUP, MOUSEOVER, MOUSEOUT, MOUSEMOVE, MOUSEDRAG, CLICK, DBLCLICK, KEYDOWN, KEYUP, KEYPRESS, DRAGDROP, FOCUS, BLUR, SELECT, CHANGE, RESET, SUBMIT, SCROLL, LOAD, UNLOAD, XFER_DONE, ABORT, ERROR, LOCATE, MOVE, RESIZE, FORWARD, HELP, BACK, TEXT, ALT_MASK, CONTROL_MASK, SHIFT_MASK, META_MASK, SCROLL_PAGE_UP, SCROLL_PAGE_DOWN, MOZ_SOURCE_UNKNOWN, MOZ_SOURCE_MOUSE, MOZ_SOURCE_PEN, MOZ_SOURCE_ERASER, MOZ_SOURCE_CURSOR, MOZ_SOURCE_TOUCH, MOZ_SOURCE_KEYBOARD
