Here is the complete AS3 code for the Flash side of things. Note that you also need Javascript in your embedding HTML to make it work.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
minWidth="1024" minHeight="768"
creationComplete="onAppCreationComplete()"
click="onRightClick()"
>
<mx:DataGrid
id="dgTest"
dataProvider="{['aaa','bbbbbbbbbbbbbbb']}"
>
<mx:columns>
<mx:DataGridColumn />
</mx:columns>
</mx:DataGrid>
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import mx.controls.Alert;
import mx.controls.Menu;
import mx.effects.Fade;
import mx.events.MenuEvent;
[Bindable]
public var customContextMenuItem : Object;
public var customContextMenu : Menu;
protected function onAppCreationComplete () : void
{
ExternalInterface.addCallback("rightClick", onRightClick);
this.customContextMenu = this.createCustomContextMenu();
}
protected function onRightClick () : void
{
// find datagrid at mouse click coords
var dg : DataGrid = this.getDataGridFromObjectsUnderPoint(this.mouseX, this.mouseY);
if (dg) {
// if any, find clicked item
this.customContextMenuItem = this.findClickedItem(this.mouseX, this.mouseY, dg);
if (this.customContextMenuItem) {
// right clicking an item with the menu already showing does not show a new menu
// unless the previous one is hidden first
this.customContextMenu.hide();
this.customContextMenu.show(this.mouseX+3, this.mouseY+2);
}
}
}
protected function getDataGridFromObjectsUnderPoint (x:Number, y:Number) : DataGrid
{
var objectsHere : Array = this.getObjectsUnderPoint(new Point(this.mouseX, this.mouseY));
for each (var dispObj:DisplayObject in objectsHere) {
while (dispObj) {
if (dispObj is DataGrid)
return dispObj as DataGrid;
dispObj = dispObj.parent;
}
}
return null;
}
/**
* Returns a dataProvider item that displays at the given coords for the given dataGrid.
* Code provided by Stackoverflow user http://stackoverflow.com/users/165297/amarghosh,
* thanks a lot!
*/
protected function findClickedItem (x:Number, y:Number, dg:DataGrid) : Object
{
var p1 : Point;
var p2 : Point;
var renderer : DisplayObject;
for(var i:int=0; i<dg.dataProvider.length; i++) {
renderer = DisplayObject(dg.indexToItemRenderer(i));
if (!renderer) //item is not displayed (scroll to view it)
continue;
p1 = new Point(renderer.x, renderer.y);
p2 = new Point(renderer.width, renderer.height);
p1 = renderer.parent.localToGlobal(p1);
p2 = renderer.localToGlobal(p2);
if(x >= p1.x && x <= p2.x && y >= p1.y && y <= p2.y)
return dg.dataProvider.getItemAt(i);
}
return null;
}
protected function createCustomContextMenu () : Menu
{
// create a dynamic-object as our first menu item entry, and use data binding
// to dynamically populate the 'title' value whenever our right-clicked item
// has changed
var menuItem : Object = new Object();
menuItem.title = "default";
BindingUtils.bindSetter(function (item:Object) : void {
trace(item);
menuItem.title = "Edit '" + item + "'";
}, this, ["customContextMenuItem"]);
var dataProvider : Array = [ menuItem, {title:"Exit"} ];
// create a nicely styled menu that looks very different to the standard Flash menu
var menu : Menu = Menu.createMenu(this, dataProvider, false);
menu.setStyle("fontWeight", "bold");
menu.setStyle("backgroundColor", 0x000000); // standard back/foreground
menu.setStyle("color", 0xf0f0f0);
menu.setStyle("rollOverColor", 0x444444); // mouse hover back/foreground
menu.setStyle("textRollOverColor", 0xffffff);
menu.setStyle("selectionColor", 0x444444); // mouse click back/foreground
menu.setStyle("textSelectedColor", 0xe18c31);
menu.setStyle("openDuration", 0);
menu.labelField = "title";
// we want to react to clicks in the menu
menu.addEventListener(MenuEvent.ITEM_CLICK, function (event:MenuEvent) : void {
Alert.show("Menu item clicked - clicked item title '" + event.item.title + "'");
});
// done
return menu;
}
]]>
</mx:Script>
</mx:Application>