"Drag and drop" is the term applied to the action of dragging an object from one place to another. A "drag" begins by pressing down on an eligible object and moving while applying pressure (either by keeping a finger in touch with the screen or pressing down on a mouse button). The "drop" happens when the pressure is released (e.g., letting go of the mouse button). If the drop happens over a suitable place (the "drop target"), then item being dragging is incorporated into the drop target somehow. A drag and drop can either cause the initial object to move to the new location or a copy of the initial object added to the new location.
Drag and Drop in FlexJS is accomplished using beads. When you add the beads to components, you enable them to have some part of them to be dragged and/or act as a drop target. This document will show you how to add the code necessary to make it all work.
The DragMouseController is the bead you add to a component strand to activate dragging. This will not, by itself, cause anything to be dragged. What it will do is enable special events to be dispatched from the strand which you can catch and use.
<js:Group id="bucketGroup">
<js:beads>
<js:DragMouseController />
</js:beads>
<!-- components in the group -->
</js:Group>
In this example, a Group has the DragMouseController in its bead list. When the Group is instantiated, set up a listener for the "dragStart" event:
bucketGroup.addEventListener("dragStart", handleDragStart);The event handler needs to do three things:
DragEvent.dataSource = (event.target as MyObject).data;
var dragImage:Label = new Label();
dragImage.text = (event.target as MyObject).toString();
DragMouseController.dragImage = dragImage;
In this example the event.target is cast to a class called "MyObject" which has a data property and that becomes the dragSource. Then a dragImage is created as a simple Label with the Label text being a string representation of the object selected. You can make any UI component or component composite a dragImage.
Once that has been set up in the "dragStart" event handler, the DragMouseController bead takes over and displays the dragImage as you move around the screen.
Use DropMouseController with the component strand that will accept the drop from the drag source strand. This can be the same component if you want to use drag and drop to re-arrange a strand's children. The DropMouseController emits its own events, such as "dragEvent" and "dragDrop". You can use these events to provide feedback to the user (such as adding a border when the dragImage enters the drop target space).
The "dragDrop" event is the event to handle when the user releases the mouse over the strand with the DropMouseController bead. You use this event to incorporate the data being dragged into the target component.
<js:Group id="dropZone">
<js:beads>
<js:VerticalLayout />
<js:DropMouseController dragDrop="handleDrop(event)" />
</js:beads>
</js:Group>
The event listener for the DropMouseController's "dragDrop" event can do whatever it needs to do it incorporate the data.
private function handleDrop(event:DragEvent):void
{
var data:Object = DragEvent.dataSource;
var newItem:OtherObject = new OtherObject(data);
dropZone.addElement(newItem);
dropZone.dispatchEvent(new Event("layoutNeeded"));
}
In this example the dropped data is used to create a new instance of "OtherObject" and it is added as an element to the dropZone Group. Notice that the dropZone group is told to update its layout after the new item is added. FlexJS will not automatically run layouts.
Once the drop has completed, its often useful to the source component is know that the drop was accepted. Perhaps you will want to delete the original component or change it somehow to reflect the drag and drop action. You do this by implementing the IDragInitiator interface and setting the object into the DragMouseController:
// code from DragMouseController example, including...
DragMouseController.dragImage = dragImage; // see above
DragMouseController.dragInitiator = this;
Whatever the component class is that has these two Groups becomes the drag initiator, implementing IDragIntiator interface. This means the class will need to implement two functions:
public function acceptingDrop(dropTarget:Object, type:String):void
{
// maybe highlight the component that was dragged.
}
public function acceptedDrop(dropTarget:Object, type:String):void
{
// maybe delete the component that was dragged.
}
The dropTarget parameter in each function just lets you know what object accepted the drop - maybe you will have different drop targets and will react differently depending on where the drop happens. The type is an indicator of what was dropped. You should save some way to identify the drag source in the "dragStart" event.
Very often a List is used with drag and drop; either to move or copy items from one list to another or to re-arrange items in one list. FlexJS provides specialty beads for Lists.
SingleSelectionDragSourceBead can be used with Lists whose items are to be dragged around. This takes the place of DragMouseController.
SingleSelectionDragImageBead can be used with Lists as quick way to display a drag image from the list's itemRenderer that is being dragged about.
SingleSelectionDropTargetBead can be used with Lists that are accepting drops. This can be the same list that uses SingleSelectionDragSourceBead to allow for items to be re-arranged.
<js:List>
<js:beads>
<js:SingleSelectionDragSourceBead />
<js:SingleSelectionDragImageBead />
<js:SingleSelectionDropTargetBead />
<!-- beads for the data provider -->
</js:beads>
</js:List>
By having these three beads present, the user will now be able to drag one item from the list to a new location within the same list.
To Do