Flex Packed Bubble Chart - apache-flex
Is it possible to create a packed bubble chart in Flex like the following example?
Source: http://blog.tiger.com.pl/wp-content/uploads/2013/06/bubble2.jpg
I googled it and didn't find anything. If there is not a native way to do it, can someone suggest how I could draw it myself?
Well, after searching and searching I found a library called flare here you can see an example of what I was looking for demo at Layout/Bubbles. But everything was done in Actionscript 3. Then I started to create my own class to be used in Flex and I got it. Here is the code of the class I wrote.
package classes
{
import flare.animate.FunctionSequence;
import flare.animate.Transition;
import flare.animate.TransitionEvent;
import flare.animate.Transitioner;
import flare.display.TextSprite;
import flare.query.methods.add;
import flare.query.methods.div;
import flare.query.methods.mul;
import flare.util.Shapes;
import flare.util.Strings;
import flare.vis.Visualization;
import flare.vis.controls.DragControl;
import flare.vis.controls.ExpandControl;
import flare.vis.controls.HoverControl;
import flare.vis.controls.IControl;
import flare.vis.controls.TooltipControl;
import flare.vis.data.Data;
import flare.vis.data.DataList;
import flare.vis.data.DataSprite;
import flare.vis.data.NodeSprite;
import flare.vis.events.SelectionEvent;
import flare.vis.events.TooltipEvent;
import flare.vis.operator.OperatorSwitch;
import flare.vis.operator.encoder.PropertyEncoder;
import flare.vis.operator.label.Labeler;
import flare.vis.operator.layout.CircleLayout;
import flare.vis.operator.layout.CirclePackingLayout;
import flare.vis.operator.layout.DendrogramLayout;
import flare.vis.operator.layout.ForceDirectedLayout;
import flare.vis.operator.layout.IcicleTreeLayout;
import flare.vis.operator.layout.IndentedTreeLayout;
import flare.vis.operator.layout.Layout;
import flare.vis.operator.layout.NodeLinkTreeLayout;
import flare.vis.operator.layout.RadialTreeLayout;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import mx.core.Container;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.ResizeEvent;
public class PackedBubblesChart extends UIComponent {
public static const DEFAULT_FLEX_SERIES_COLORS:Array = [
0xe48701, 0xa5bc4e, 0x1b95d9, 0xcaca9e,
0x6693b0, 0xf05e27, 0x86d1e4, 0xe4f9a0,
0xffd512, 0x75b000, 0x0662b0, 0xede8c6,
0xcc3300, 0xd1dfe7, 0x52d4ca, 0xc5e05d,
0xe7c174, 0xfff797, 0xc5f68f, 0xbdf1e6,
0x9e987d, 0xeb988d, 0x91c9e5, 0x93dc4a,
0xffb900, 0x9ebbcd, 0x009797, 0x0db2c2
];
// Constructor
public function PackedBubblesChart() {
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
}
protected function addedToStage(event: Event) : void {
(this.parent as Container).addEventListener(ResizeEvent.RESIZE, resizeBubbleChart);
tryRender();
}
protected function removedFromStage(event: Event) : void {
clearNodes();
(this.parent as Container).removeEventListener(ResizeEvent.RESIZE, resizeBubbleChart);
}
protected function clearNodes() : void {
if(vis) {
for each(var sprite : DataSprite in _nodesInformation.nodes) {
sprite.parent.removeChild(sprite);
}
vis = null;
}
}
protected function resizeBubbleChart(event:ResizeEvent) : void {
_bounds = new Rectangle(0, 0, parent.width, parent.height);
tryRender();
}
private var _init:Boolean = false;
private var _bounds:Rectangle;
public var labelField : String = "label";
public var valueField : String = "value";
public function get bounds():Rectangle { return _bounds; }
public function set bounds(b:Rectangle):void {
_bounds = b;
resize();
}
private var _dataProvider : Array = [];
private var _nodesInformation : Data = new Data();
private var _nodeDefaultFormat : Object =
{
name: "Bubbles",
op: new CirclePackingLayout(8, false, "depth"),
nodes:{
shape: Shapes.CIRCLE,
fillColor: 0x11aaaaaa,
lineColor: 0xdddddddd,
lineWidth: 4,
alpha: 1,
visible: true
},
edges: {alpha:0, visible:false},
ctrl: new DragControl(NodeSprite),
canStraighten: true
}
public function get dataProvider() : Array {
return _dataProvider;
}
public function set dataProvider(info : Array) : void {
/*
if(vis && _dataProvider && _dataProvider.length > 0) {
for each(var sprite : DataSprite in _nodesInformation.nodes) {
sprite.parent.removeChild(sprite);
}
vis = null;
}
*/
_dataProvider = info;
tryRender();
}
protected function tryRender() : void {
if(parent) _bounds = new Rectangle(0,0,parent.width, parent.height);
if(_dataProvider && _dataProvider.length > 0 && _bounds) {
clearNodes();
_nodesInformation = createNodes(_dataProvider.length);
_nodesInformation.nodes.setProperties(_nodeDefaultFormat.nodes);
var index : uint = 0;
for each(var item : Object in _dataProvider) {
var labelText : String = item[labelField];
var valueNumber : Number = item[valueField];
_nodesInformation.nodes[index].data.label = labelText;
_nodesInformation.nodes[index].buttonMode = true;
_nodesInformation.nodes[index].size = item[valueField];
_nodesInformation.nodes[index].props.value = valueNumber;
_nodesInformation.nodes[index].props.name =labelText;
_nodesInformation.nodes[index].props.name_value = labelText+"\n("+valueNumber+")";
_nodesInformation.nodes[index].fillColor = 0xff000000 + DEFAULT_FLEX_SERIES_COLORS[index % 28];
index++;
}
_nodesInformation.nodes.sortBy("props.value");
// create the visualization
vis = new Visualization(_nodesInformation);
vis.bounds = bounds;
vis.operators.add(_nodeDefaultFormat.op);
vis.setOperator("nodes", new PropertyEncoder(_nodeDefaultFormat.nodes, "nodes"));
vis.operators.add(new Labeler("props.name_value", Data.NODES,new TextFormat("Arial",12,0,true,null,null,null,null, TextFormatAlign.CENTER),null));
vis.controls.add(new TooltipControl(DataSprite, null,
function(evt:TooltipEvent):void {
var d:DataSprite = evt.node;
TextSprite(evt.tooltip).htmlText = Strings.format(_tipText, d.props.name, d.props.value);
}
));
init();
}
}
public static function createNodes(n:uint):Data {
var g:Data = new Data();
for (var i:uint=0; i < n; i++) {
var node:NodeSprite = g.addNode();
node.data.label = String(i);
}
return g;
}
public function set toolTipFormat(value : String) : void {
_tipText = value;
}
private var _tipText:String = "<b>Label</b>: {0}<br/><b>Value</b>: {1}";
private var vis:Visualization;
private var os:OperatorSwitch;
private var shape:String = null;
public function init():void {
vis.controls.add(new HoverControl(NodeSprite,
// by default, move highlighted items to front
HoverControl.MOVE_AND_RETURN,
// highlight node border on mouse over
function(e:SelectionEvent):void {
e.node.lineWidth = 10;
e.node.lineColor = 0x88ff0000;
},
// remove highlight on mouse out
function(e:SelectionEvent):void {
e.node.lineWidth = 4;
e.node.lineColor = _nodeDefaultFormat.nodes.lineColor;
}));
vis.controls.add(_nodeDefaultFormat.ctrl);
vis.update();
addChild(vis);
}
public function resize():void
{
if (vis) {
vis.bounds = bounds;
vis.update();
}
}
}
}
And here is an application example of what to use it in flex
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
minWidth="955" minHeight="600" creationComplete="init(event)" layout="vertical"
verticalAlign="middle">
<mx:Script>
<![CDATA[
import classes.PackedBubblesChart;
import mx.events.FlexEvent;
import mx.events.ResizeEvent;
protected var companies : Array = [];
protected var otherCompanies : Array = [];
protected var bubbleChart : PackedBubblesChart = new PackedBubblesChart();
protected function init(event:FlexEvent):void {
companies.push({company_name:"Sunray Management Group", count:92});
companies.push({company_name:"Chevron", count:145});
companies.push({company_name:"Nabors", count:35});
companies.push({company_name:"Milicom", count:23});
companies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Cisco", count:43});
otherCompanies.push({company_name:"Chevron", count:145});
otherCompanies.push({company_name:"Nabors", count:35});
otherCompanies.push({company_name:"Milicom", count:23});
otherCompanies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Sunray Management Group", count:92});
companies.push({company_name:"Chevron", count:145});
companies.push({company_name:"Nabors", count:35});
companies.push({company_name:"Milicom", count:23});
companies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Cisco", count:43});
otherCompanies.push({company_name:"Chevron", count:145});
otherCompanies.push({company_name:"Nabors", count:35});
otherCompanies.push({company_name:"Milicom", count:23});
otherCompanies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Sunray Management Group", count:92});
companies.push({company_name:"Chevron", count:145});
companies.push({company_name:"Nabors", count:35});
companies.push({company_name:"Milicom", count:23});
companies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Cisco", count:43});
otherCompanies.push({company_name:"Chevron", count:145});
otherCompanies.push({company_name:"Nabors", count:35});
otherCompanies.push({company_name:"Milicom", count:23});
otherCompanies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Sunray Management Group", count:92});
companies.push({company_name:"Chevron", count:145});
companies.push({company_name:"Nabors", count:35});
companies.push({company_name:"Milicom", count:23});
companies.push({company_name:"gNostos", count:200});
companies.push({company_name:"Cisco", count:43});
otherCompanies.push({company_name:"Chevron", count:145});
otherCompanies.push({company_name:"Nabors", count:35});
otherCompanies.push({company_name:"Milicom", count:23});
otherCompanies.push({company_name:"gNostos", count:200});
bubbleChart.labelField = "company_name";
bubbleChart.valueField = "count";
bubbleChart.toolTipFormat = "<b>Company</b>: {0}<br/><b>Count</b>: {1}";
bubbleChart.dataProvider = companies;
canvas.addChild(bubbleChart);
}
protected function button_clickHandler(event:MouseEvent):void {
if(bubbleChart.dataProvider == companies) bubbleChart.dataProvider = otherCompanies;
else bubbleChart.dataProvider = companies;
}
]]>
</mx:Script>
<mx:Canvas id="canvas" width="100%" height="100%">
</mx:Canvas>
<mx:Button label="New data provider" click="button_clickHandler(event)"/>
</mx:Application>
Well, I answer my own question because I think it could be useful for other people.
Sorry for my english.
this was the result... Ah, Beautyful. Thanks to Flare people.
Related
Flex popup manager, mousedown outside of the popup removes the popup
If you create a popup via: PopUpManager.addPopUp( popup, this, false ); PopUpManager.bringToFront( popup ); It will create a popup and bring it on top of any other visual piece. I have one problem though. This 'popup' needs to stay up even when the user interacts with the background. I would use modal, but I need the ability to interact with the back. Any way to tell the popup manager not to remove the popup when the user clicks off of it? Thanks!
here's a helper class which would help you (tested only in Flex 4, but probably could be changed for Flex 3 too): import flash.display.DisplayObject; import flash.events.Event; import flash.events.MouseEvent; import mx.core.mx_internal; import mx.managers.ISystemManager; import mx.managers.systemClasses.ActiveWindowManager; use namespace mx_internal; public class PopupHelper { private var popup : DisplayObject; private var systemManager : ISystemManager; public function PopupHelper(popup : DisplayObject, systemManager : ISystemManager) : void { this.popup = popup; this.systemManager = systemManager; } public function forceToFront() : void { systemManager.addEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown); popup.addEventListener(Event.REMOVED_FROM_STAGE, onPopupRemoved) } private function onSystemMouseDown(e : MouseEvent) : void { bringToFront(popup); } private function onPopupRemoved(e : Event) : void { popup.removeEventListener(Event.REMOVED, onPopupRemoved); systemManager.removeEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown); } private function bringToFront(popup : DisplayObject) : void { var windowManager : ActiveWindowManager = systemManager.getImplementation("mx.managers::IActiveWindowManager") as ActiveWindowManager; var index : int = systemManager.getChildIndex(popup); var newIndex : int = index; var n : int = windowManager.forms.length; for (var j : int = 0; j < n; j++) { var f : DisplayObject = windowManager.forms[j]; if (systemManager.contains(f)) if (systemManager.getChildIndex(f) > index) newIndex = Math.max(systemManager.getChildIndex(f), newIndex); } if (newIndex > index) { systemManager.setChildIndex(popup, newIndex); } } } Here's a test example: import helperClasses.PopupHelper; import mx.managers.PopUpManager; import spark.components.TitleWindow; public function showPopup() : void { var popup1 : TitleWindow = new TitleWindow(); popup1.title = "Popup 1"; new PopupHelper(popup1, systemManager).forceToFront(); var popup2 : TitleWindow = new TitleWindow(); popup2.title = "Popup 2"; PopUpManager.addPopUp(popup1, this, false); PopUpManager.addPopUp(popup2, this, false); PopUpManager.bringToFront(popup1); popup1.x = 20; popup1.y = 20; }
addchild not displaying content
In the following code i dont have any error but why is that the addchild(video); i.e, the the video captured by webcam is not displayed <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import org.com.figurew; import mx.controls.Button; import mx.controls.Alert; import flash.display.InteractiveObject; import flash.display.Sprite; import flash.media.*; import flash.net.*; public function addBody():void { var ret:Number = figurew.getInstance().getparam(); if( ret == 1) { Alert.show("Camera detected"); } if(ret == 0) { Alert.show("No camera detected"); } var cam:Camera = Camera.getCamera(); if(cam != null) { cam.setMode(640, 480, 30); var video:Video = new Video(30, 40); video.attachCamera(cam); addChild(video); } else { trace("No Camera Detected"); } } ]]> </mx:Script> <mx:Button label="Test camera" click="addBody();" x="99" y="116"/> </mx:Application > figurew.as package org.com { import flash.display.InteractiveObject; import flash.display.Sprite; import flash.media.*; import flash.net.*; public class figurew extends Sprite { public function figurew() { //getparam(); var cam:Camera = Camera.getCamera(); if(cam != null) { cam.setMode(640, 480, 30); var video:Video = new Video(300, 450); video.attachCamera(cam); addChild(video); } else { trace("No Camera Detected"); } } public function getparam():Number { var cam:Camera = Camera.getCamera(); if(cam != null) { cam.setMode(640, 480, 30); var video:Video = new Video(300, 450); video.attachCamera(cam); addChild(video); return 1; } else { return 0; trace("No Camera Detected"); } } private static var _instance:figurew = null; public static function getInstance():cldAS { if(_instance == null) { trace("No instance found"); _instance = new cldAS(); } return _instance; } } }
I see no place where you set a height or width of the video child of your main application. That may be an issue. You have an MX Button tag inside the script tag. I suspect this will cause a compilation error. So it is possible that you're viewing an "old" Version of your code. Fix the errors and recompile and relaunch.
Flex actionscript extending DateChooser, events in calendar
ExtendedDateChooser class is great solution for simple event calendar used in my flex project. You can find it if google for "Adding-Calendar-Event-Entries-to-the-Flex-DateChooser-Component" with a link of updated solution in comments of the post. I posted files below. Problem in that calendar is text events are missing when month is changed. Is there updateCompleted event in Actionscript just like in dateChooser flex component? Like in: <mx:DateChooser id="dc" updateCompleted="goThroughDateChooserCalendarLayoutAndSetEventsInCalendarAgain()"</mx> When scroll event is added, which is available in Actionscript, it gets dispatched but after updateDisplayList() is fired, so didn't manage to answer, why are calendar events erased? Any suggestions, what to add in code, maybe override some function? ExtendedDateChooserClass.mxml <?xml version='1.0' encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:mycomp="cyberslingers.controls.*" layout="absolute" creationComplete="init()"> <mx:Script> <![CDATA[ import cyberslingers.controls.ExtendedDateChooser; import mx.rpc.events.ResultEvent; import mx.rpc.events.FaultEvent; import mx.controls.Alert; public var mycal:ExtendedDateChooser = new ExtendedDateChooser(); // collection to hold date, data and label [Bindable] public var dateCollection:XMLList = new XMLList(); private function init():void { eventList.send(); } private function readCollection(event:ResultEvent):void { dateCollection = event.result.calendarevent; //Position and size the calendar mycal.width = 400; mycal.height = 400; //Add the data from the XML file to the calendar mycal.dateCollection = dateCollection; //Add the calendar to the canvas this.addChild(mycal); } private function readFaultHandler(event:FaultEvent):void { Alert.show(event.fault.message, "Could not load data"); } ]]> </mx:Script> <mx:HTTPService id="eventList" url="data.xml" resultFormat="e4x" result="readCollection(event);" fault="readFaultHandler(event);"/> </mx:Application> ExtendedDateChooser.as package cyberslingers.controls { import flash.events.Event; import flash.events.TextEvent; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.controls.CalendarLayout; import mx.controls.DateChooser; import mx.core.UITextField; import mx.events.FlexEvent; public class ExtendedDateChooser extends DateChooser { public function ExtendedDateChooser() { super(); this.addEventListener(TextEvent.LINK, linkHandler); this.addEventListener(FlexEvent.CREATION_COMPLETE, addEvents); } //datasource public var dateCollection:XMLList = new XMLList(); //-------------------------------------- // Add events //-------------------------------------- /** * Loop through calendar control and add event links * #param e */ private function addEvents(e:Event):void { // loop through all the calendar children for(var i:uint = 0; i < this.numChildren; i++) { var calendarObj:Object = this.getChildAt(i); // find the CalendarLayout object if(calendarObj.hasOwnProperty("className")) { if(calendarObj.className == "CalendarLayout") { var cal:CalendarLayout = CalendarLayout(calendarObj); // loop through all the CalendarLayout children for(var j:uint = 0; j < cal.numChildren; j++) { var dateLabel:Object = cal.getChildAt(j); // find all UITextFields if(dateLabel.hasOwnProperty("text")) { var day:UITextField = UITextField(dateLabel); var dayHTML:String = day.text; day.selectable = true; day.wordWrap = true; day.multiline = true; day.styleName = "EventLabel"; //TODO: passing date as string is not ideal, tough to validate //Make sure to add one to month since it is zero based var eventArray:Array = dateHelper((this.displayedMonth+1) + "/" + dateLabel.text + "/" + this.displayedYear); if(eventArray.length > 0) { for(var k:uint = 0; k < eventArray.length; k++) { dayHTML += "<br><A HREF='event:" + eventArray[k].data + "' TARGET=''>" + eventArray[k].label + "</A>"; } day.htmlText = dayHTML; } } } } } } } //-------------------------------------- // Events //-------------------------------------- /** * Handle clicking text link * #param e */ private function linkHandler(event:TextEvent):void { // What do we want to do when user clicks an entry? Alert.show("selected: " + event.text); } //-------------------------------------- // Helpers //-------------------------------------- /** * Build array of events for current date * #param string - current date * */ private function dateHelper(renderedDate:String):Array { var result:Array = new Array(); for(var i:uint = 0; i < dateCollection.length(); i++) { if(dateCollection[i].date == renderedDate) { result.push(dateCollection[i]); } } return result; } } } data.xml <?xml version="1.0" encoding="utf-8"?> <rss> <calendarevent> <date>8/22/2009</date> <data>This is a test 1</data> <label>Stephens Test 1</label> </calendarevent> <calendarevent> <date>8/23/2009</date> <data>This is a test 2</data> <label>Stephens Test 2</label> </calendarevent> </rss>
Just Change the FlexEvent.CREATION_COMPLETE in the ExtendedDateChooser.as to FlexEvent.UPDATE_COMPLETE That should do.
( Flex ) How can we get an imagesnapshot of the entire component without scrollbars?
I can take snapshot of a component. But the problem is the component is lil bigger with scroll bars. The saved image has scrollbars (only the visible area is getting saved). What i need is I want the entire component to be saved as an image. This exact functionality is available while we print the component using FlexPrintJob, where by setting the FlexPrintJobScaleType.NONE. But here in my case i want it to be saved using ImageSnapShot ( not thru FlexPrintJob ). Thanks Advance, Sriss
I thought I knew how to do this, but there seem to be lots of awkward issues. I got it working but it's not nice. :-( Maybe you can improve on it. Here's the code for an example application. And below is the code for the MyCanvas class. When you click the button an image of the Canvas container but without scrollbars should be drawn. <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:my="*"> <mx:Script><![CDATA[ import flash.display.BitmapData; import flash.events.Event; import mx.containers.Canvas; import mx.graphics.ImageSnapshot; import flash.geom.Matrix; import mx.core.ScrollPolicy; public function onclick():void { var bitmapData:BitmapData = ImageSnapshot.captureBitmapData(canvas); canvas.addEventListener("BitMapReady", onBitMapReady); canvas.horizontalScrollPolicy = ScrollPolicy.OFF; canvas.CreateBitMapData(); } private function onBitMapReady(e:Event):void { DrawBitmapDataAt(canvas.bitMapData, 100, 100); canvas.removeEventListener("BitMapReady", onBitMapReady); canvas.horizontalScrollPolicy = ScrollPolicy.AUTO; } private function DrawBitmapDataAt(bitmapData:BitmapData,x:int,y:int):void { var matrix:Matrix = new Matrix(); matrix.tx = x; matrix.ty = y; box.graphics.lineStyle(0,0,0); box.graphics.beginBitmapFill(bitmapData, matrix, false); box.graphics.drawRect(x,y,bitmapData.width,bitmapData.height); } ]]></mx:Script> <mx:Box id="box"> <my:MyCanvas width="50" height="50" backgroundColor="white" id="canvas"> <mx:Button label="Hello" click="onclick()" /> </my:MyCanvas> </mx:Box> </mx:Application> MyCanvas class: package { import flash.events.Event; import flash.events.TimerEvent; import mx.containers.Canvas; import flash.display.BitmapData; import mx.core.ScrollPolicy; import mx.graphics.ImageSnapshot; import flash.utils.Timer; public class MyCanvas extends Canvas { public var bitMapData:BitmapData; private var creatingBitMap:Boolean = false; private var timer:Timer; public function CreateBitMapData():void { this.horizontalScrollPolicy = ScrollPolicy.OFF; creatingBitMap = true; } override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); if (creatingBitMap == true && this.horizontalScrollBar == null) { bitMapData = ImageSnapshot.captureBitmapData(this); this.dispatchEvent(new Event("BitMapReady")); creatingBitMap = false; timer = new Timer(10); timer.addEventListener(TimerEvent.TIMER, onTimer); this.width += 1; timer.start(); } } private function onTimer(e:TimerEvent):void { this.width -= 1; trace("timer"); timer.removeEventListener(TimerEvent.TIMER, onTimer); timer.stop(); } } }
Flex + Image + Disable Drag
How do I diable the drag-drop of an image. I've tried to stopPropagation, but that didn't help. Here is the snippet of the code that I've written <mx:Image width="24" height="24" complete="init()" dragStart="disableMove(event)" source="{(data.id==null)?'': (data.id.search('\\.') > 0) ? 'assets/icons/teacher.png' : 'assets/icons/student.png'}" toolTip="{data.data}" doubleClick="itemDoubleClick(event, data.id)" doubleClickEnabled="true"> <mx:Script> <![CDATA[ import mx.controls.Alert; import flash.events.MouseEvent; import flash.ui.ContextMenu; import flash.ui.ContextMenuItem; private var allCurrentItems: Array = new Array(); private function itemDoubleClick(event: Event, id: String): void { Alert.show("Clicked = "+id); } private function init(): void { var menuLabel:String = "About School\u00A0"; var cm:ContextMenu = new ContextMenu(); cm.hideBuiltInItems(); var item:ContextMenuItem = new ContextMenuItem(menuLabel); this.addEventListener(MouseEvent.MOUSE_DOWN, showClick); //add eventlisteners to the menu item and provide functions cm.customItems.push(item); //cm.customItems = [item]; this.contextMenu = cm; } private function showClick(event:MouseEvent): void { if (event.buttonDown) { Alert.show(String(event.buttonDown)); } } private function disableMove(event: MouseEvent): void { event.stopImmediatePropagation(); } ]]> </mx:Script> </mx:Image>
I got it, instead of calling disableMove(event) on dragStart(), I called it on mouseDown() it worked.