Previous Page Next Page

4.8. Drag-and-Drop

4.8.1. Use Drag—and-Drop from HTML

4.8.1.1. Problem

You want to allow users to drag files, images, text, and other data types into and out of HTML-based AIR applications.

4.8.1.2. Solution

By using Adobe AIR's Drag and Drop implementation in JavaScript, developers can react to drag-and-drop operations that occur on HTML DOM objects.

NOTE

Adobe AIR's support for drag-and-drop within HTML content is based on the WebKit implementation. You can find more information on this at http://developer.apple.com/documentation/AppleApplications/Conceptual/SafariJSProgTopics/Tasks/DragAndDrop.html.

4.8.1.3. Discussion

One of the benefits of developing for the desktop is providing users with a more integrated experience when interacting with multiple applications. One of the most frequently used user gestures is to drag-and-drop files, data, and other elements between applications and the desktop and between the applications themselves.

This example will demonstrate how you can accept text being dragged items into your application as well as support dragging elements out. It will also show you how to modify the drag effect to demonstrate for the user what type of drag operations he can perform with the element he is dragging as well as the ability to modify the drag image.

Two flows are important to consider when using drag-and-drop operations in HTML. First, we will examine the flow for HTML elements that are drag-enabled:

  1. The element specifies that it is available for drag operations.

  2. The user selects the element and starts to drag it.

  3. The element receives an ondragstart event and sets the data which will be transferred, as well as specifies which drag operations are supported. It can also specify a custom drag image at this time.

  4. The element receives ondrag events while it is being dragged.

  5. The user drops the element being dragged and receives an ondragend event.

The typical flow for HTML elements that want to receive drop operations is as follows:

  1. The user drags an item over the element listening for drop events.

  2. The element receives an ondragenter event and specifies which drop operations are allowed.

  3. The element receives ondragover operations continuously as the item is being dragged over.

  4. The user drops the item and the receiving element receives an ondrop event.

  5. Alternatively, if the user moves the dragged item outside the boundaries of the listening element, it will receive an ondragleave event.

Linked text and highlighted text elements are drag-enabled by default. To disable this functionality, use the -khtml-user-drag:none style. Conversely, to enable other HTML elements to be drag-enabled, use the -khtml-user-drag:element style.

To manipulate the data that is being transferred as part of the drag operation, listen for the ondragstar operation and use the dataTransfer object that is attached to the event object. The dataTransfer object has two data modification methods: getData and setData. The setData method takes two parameters: the MIME type and the string of data that conforms to that type. You can call the setData method multiple times, and it allows you to store multiple data types. For example, if you wanted to specify a text/plain type and a text/uri- list type, you would do the following:

function dropStartListener( event )
{
    event.dataTransfer.setData( "text/plain", "Adobe" );
    event.dataTransfer.setData( "text/uri-list",
                                 "http://www.adobe.com" );
}

If setData is called for a MIME type that already exists on the element being dragged, that data will be overwritten. Retrieving data from an element that is being dragged can occur only within an ondrop event handler. The getData method takes a MIME type as its only parameter and returns the value of the MIME type if it exists on the element being dragged. For example:

function dropListener( event )
{
    alert( event.dataTransfer.getData( "text/plain" ) );
// Adobe
}

AIR supports the following MIME types:

Text "text/plain"

HTML "text/html"

URL "text/uri-list"

Bitmap "image/x-vnd.adobe.air.bitmap"

File list "application/x-vnd.adobe.air.file-list"

When a user is dragging data from one application to another, or from one location in your application to another, you may want to indicate to the user which operations (copy, link, or move) are available. By using the effectAllowed and dropEffect properties of the dataTransfer object, you can specify which operations are allowed. You can see the list of available values for these properties by reading the WebKit documentation referenced earlier.

The effectAllowed property tells the system what operations the source element supports. The dropEffect property specifies the single operation that the current target receiving the drag event supports. The operating system then uses this information regarding which effects the source and destination targets support, and allows the user to make that choice. Generally, the user chooses by using the system's standard keyboard modifiers.

To modify the drag image that is displayed to the user as she is dragging the item, use the setDragImage method of the dataTransfer object. This method takes three arguments. The first argument is a JavaScript Image object which references the image that will appear to the user. The second and third arguments are the respective X and Y offsets that will modify the position of that image relative to the cursor's X and Y positions on-screen.

Assume that we had the following HTML element in our document. Notice that we explicitly specify that this element is draggable using the -khtml-user-drag:element style:

<div id="box" style="-khtml-user-drag:element"
      ondragstart="onBoxDragStart
(event)"></div>

We can then change the image by listening for the ondragstart event and modify the image using the setDragImage method:

    // First create a reference to our drag image in the 
    // main document scope.
    var dragImage = new Image();
    dragImage.src = "app:/images/dragimage.png";

    // This method gets called when a drag starts
    // on our 'box' element.
    function onBoxDragStart( event )
    {
        // Set the data we would like to be transferred.
        event.dataTransfer.setData("text/plain", 
        "This is a red box!");

        // Modify the drag image to use the reference
        // we created above.
        event.dataTransfer.setDragImage( dragImage, 0, 0 );
    }

Here is the full example:

<html>
<head>
    <title>HTML Drag Test</title>
    <script src="airaliases.js" />
    <script>

    // DROP EVENTS

    function onDragEnter(event)
    {
        air.trace("onDragEnter");
        event.dataTransfer.dropEffect = "copy";
        event.preventDefault();
    }

    function onDrop(event)
    {
      air.trace("onDrop");
      air.trace( event.dataTransfer.getData("text/plain") );
      air.trace( event.dataTransfer.getData("text/uri-list") );
    }

    function onDragOver(event)
    {
        event.preventDefault();
    }

    // DRAG EVENTS

    function onDragStart(event)
    {
        air.trace("onDragStart");
        event.dataTransfer.setData("text/plain",
           "This is the URL I am dragging" );
        // We overwrite the default URL specified in the
        // anchor tag with a different URL. When the data
        // is dropped, this is the URL that will be
        //  transferred.
        event.dataTransfer.setData("text/uri-list",
                                   "http://www.foo.com" );
        event.dataTransfer.effectAllowed = "all";
    }

    function onDragEnd( event )
    {
        air.trace("onDragEnd");
    }


    var dragImage = new Image();
    dragImage.src = "app:/images/dragimage.png";

    function onBoxDragStart( event )
    {
         event.dataTransfer.setData("text/plain", "This is a 
red box!");
         event.dataTransfer.setDragImage( dragImage, 0, 0 );
    }

    </script>
</head>
<body>
    <div style="margin: 0px auto; width: 80%;
    background-color: white; border: solid black;">
        <div style="background-color: lightblue;
        border-bottom: solid black; padding: 3px;
        font-family: sans-serif; font-weight: bold;"
             ondragenter="onDragEnter(event)"
             ondragover="onDragOver(event)"
             ondrop="onDrop(event)">
            Drop Here
        </div>
        <p>
            <span id="content" ondragstart="onDragStart(event)"
                               ondragend="onDragEnd(event)">
           <a href="http://www.adobe.com">drag Me
           (text/uri-list)</a>
            </span>
        </p>
        <p>
         <div id="box" style="-khtml-user-drag:element"
      ondragstart="
onBoxDragStart(event)"></div>
        </p>
    </div>
</body>
</html>


					  

Previous Page Next Page