Document Information

Last modified:
2007/06/06 15:42 by aback

Drag & Drop

qooxdoo comes with an advanced Drag&Drop implementation. In qooxdoo Drag&Drop is implemented similarly to typical native environments. This also means that we haven’t implemented something which simply drags some nodes around.

qooxdoo supports Drag&Drop with event-based widget interaction. Drag&Drop can handle data for multiple mime-types where the drop target could choose which one to use. It also supports different actions, which can be controlled by the keyboard while dragging around like copy, move or alias.

Setting up the drag source

qooxdoo’s Drag&Drop operates on a typical qooxdoo widget. Each widget in qooxdoo could be a drag source or a drop target or even both. To setup a widget as drag source do the following:

yourSourceWidget.addEventListener("dragstart", handleDragStart);

The function handleDragStart must be defined before adding this event. This function could look like this for example:

function handleDragStart(e) {
  e.addData("text/plain", "Plain text");
  e.addData("text/html", "Some <strong>HTML</strong>");
      
  e.addAction("copy");
  e.addAction("move");
  e.addAction("alias");
      
  e.startDrag();
}

The first parameter of the method e is the event object, in this case an instance of qx.event.type.DragEvent. Let’s take a more detailed look at the content:

  • The first two lines define the data which should be available to the drop candidates. You have to add at least one data type to get the drop mechanism to work. Otherwise the supportsDrop method will prohibit any drop action (showing the forbidden cursor sign). The first parameter is the name of the mimetype. You can choose your own. Generally you should try to keep it mimetype typical with the slash between the two words. The second parameter is the content. This could also be of any type: strings, numbers, objects, arrays, ...
  • The next 3 lines define the available actions. Currently the three listed actions (copy, move, alias) are supported. You don’t need to enable all of them. It’s enough to add one action. Each action is represented with an own feedback cursor. One can switch to each action by pressing the Alt, Control or Shift key during a drag and drop session. The action move is activated by pressing the Shift key, alias by pressing the Alt key and copy by pressing the Control key. The latter action is also the default action when no key is pressed during the drag and drop operation.
  • With the last line you finally enable the Drag&Drop handling. If you don’t add this line then Drag&Drop will be cancelled.

Setting up the drop candidates

Now the basic dragging should work, but as you haven’t configured a drop target yet, the cursor shows you a not-allowed state while dragging around.

First you need to setup the allowed drop data types. These are mimetypes like above configured for the drag source. There must be one identical mime type to let the Drag&Drop mechanism accept the drop target. Here’s how you configure the drop data types:

yourDestinationWidget.setDropDataTypes(["text/html", "text/plain"]);

As you can see you can define an array here, which contains all the accepted data types.

If you need to make a more fine-grained decision on which drops are accepted and which are not, each widget has a supportDrop method which you can override. You can use this to reject drops which have the correct data type, but are not valid for other reasons. An example for this is to allow a folder in a folder tree to be moved to another folder by dropping it there. It is invalid to drop a folder onto one of its children, although the data type is correct.

supportsDrop : function(vDragCache) {
  var acceptDrop = vDragCache.sourceWidget != xyz;
  return acceptDrop;
}

Finally you must add some handler which implements the real code which is needed to really copy/move/alias something around. This should be done using an event listener for the event “dragdrop” on the drop candidate:

yourDestinationWidget.addEventListener("dragdrop", handleDragDrop);

The function handleDragDrop should have been defined before.

function handleDragDrop(e) {
  var type = e.getDropDataTypes()[0];
  var data = e.getData(type);
 
  switch(type)
  {
    case "text/plain":
    case "text/html":
      this.setLabel(data);  
      break;
  }
}
  • e.getDropDataTypes() gives you an array of data types which were added by the drag source.
  • With the e.getData(mimeType) statement you can get the corresponding data for a specific mimetype which was attached previously to the drag event.
  • The next lines are just some example code. Generally I think you need to implement more than this for a real-world case.

Drag over, move and out effects

If you want to add some effects or highlighting while dragging some widget around, you can add the dragover, dragmove and dragout events to your drop targets. You can for example change the background color.

function handleDragOver(e) {
  e.getTarget().setBackgroundColor("#f2f2f2");
}
 
function handleDragMove(e) {
  // show other visual effects, e.g. relative mouse position
}
 
function handleDragOut(e) {
  e.getTarget().setBackgroundColor("#ffffff");
}
 
yourDestinationWidget.addEventListener("dragover", handleDragOver);
yourDestinationWidget.addEventListener("dragmove", handleDragMove);
yourDestinationWidget.addEventListener("dragout", handleDragOut);

Detailed event order

To get a better understanding of the Drag and Drop mechanism it is essential to take a closer look at the order in which the events are fired. The described order relies on the correct initialization of source and target widgets (setting up the event listeners, DropDataTypes, etc.) and describes a Drag and Drop operation from the source widget directly to its target.

If the user hovers accross multiple targets without dropping the data the steps 2 - 4 and 7 are called repeatedly.

  1. Source widget fires a DragStart event
  2. On every mouse movement the DragAndDropHandler executes the supportsDrop method.
  3. Destination widget fires a DragOver event if mouse cursor hovers accross
  4. Every mouse movement accross the destination widget fires a DragMove event and additionally the supportsDrop method is executed by every mouse movement
  5. Destination widget fires a DragDrop event when data is dropped
  6. Source widget fires a DragEnd event
  7. Destination widget fires a DragOut event

Troubleshooting

Sometimes it can occur that Drag and Drop works fine in the source version of your application but the build version it doesn’t. Is this the case the loader failed to add the DragAndDropHandler class automatically. To fix this probem just add following line to your application class

#require(qx.event.handler.DragAndDropHandler)

to ensure the DragAndDropHandler class is really added to the build version of your application.

Information

Last modified:
2007/06/06 15:42 by aback

Account

Not logged in

 
 

Job Offers

To further improve qooxdoo we are seeking javascript developers. Read more...

Rich Ajax Platform (RAP)

RAP uses qooxdoo, Java and the Eclipse development model to build rich web applications. Read more...

qooxdoo Web Toolkit (QWT)

Similar to GWT this framework allows to create impressive qooxdoo applications just using Java. Read more...

Pustefix

Pustefix is a MVC-based web application framework using Java and XML/XSLT. Read more...

 
SourceForge.net Logo

Bad Behavior has blocked 0 potential spam attempts in the last 7 days.