Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
143023864X_HT5.pdf
Скачиваний:
8
Добавлен:
21.02.2016
Размер:
7.98 Mб
Скачать

CHAPTER 9 WORKING WITH DRAG-AND-DROP

Although modeling a crude drag-and-drop system using low-level events is possible, it suffers from some notable drawbacks. First, the logic necessary to handle the mouse events is more complex than you might imagine, as each of the listed events has many edge cases that must be accounted for. Although some were in the previous list, the reality is that there are enough of them to warrant their own chapter. During these events, CSS must be carefully updated to provide feedback to the user about the possibility of dragging or dropping at any particular location.

However, an even more serious drawback is that this type of ad hoc drag-and-drop implementation relies on total control of the system. If you try mixing your app content with other content in the same page, things quickly spiral out of control when different developers start using events for their own means. Similarly, if you try to drag-and-drop content from someone else’s code, you may have trouble unless the two codebases are carefully coordinated beforehand. Also, ad hoc drag-and-drop does not interact with the user’s desktop or work across windows.

The new HTML5 drag-and-drop API has been designed to address these limitations, borrowing from the way drag-and-drop has been provided in other user interface frameworks.

Note Even when properly implemented, beware of the limitations of drag-and-drop in any application. Mobile devices that use drag gestures to navigate might not function correctly if drag behavior is overridden. Also, drag- and-drop can interfere with drag selection. Take care to use it sparingly and appropriately.

Overview of HTML5 Drag-and-Drop

If you have used the drag-and-drop APIs in programming technologies such as Java or Microsoft MFC, then you’re in luck. The new HTML5 drag-and-drop API is closely modeled on the concepts of these environments. Getting started is easy, but mastering the new functionality means that you will need to become acquainted with a new set of DOM events, though this time at a higher level of abstraction.

The Big Picture

The easiest way to learn the new API is to map it to the concepts with which you are already familiar. If you are reading a book on pro HTML5 programming, we’ll make a bold assumption that you are experienced with using drag-and-drop in your day-to-day computing. Nonetheless, we can start by putting some standard terms on the major concepts.

As shown in Figure 9-1, when you (as a user) start a drag-and-drop operation, you start by clicking and dragging the pointer. The item or region where you began the drag is known as the drag source. When you release the pointer and complete the operation, the region or item you are targeting at the end is known as the drop target. As the mouse moves across the page, you may traverse a series of drop targets before you actually release the mouse.

218

CHAPTER 9 WORKING WITH DRAG-AND-DROP

Figure 9-1. Drag sources and drop targets

So far, so good. But simply holding down the mouse and moving it to another part of an application is not what constitutes a drag-and-drop. Rather, it is the feedback during the operation that makes for a successful interaction. Consider your own uses of drag-and-drop in past experiences; the ones that are the most intuitive are those where the system is giving constant updates to let you know what will happen if you release at this point in time:

Does the cursor indicate that the current position is a valid drop target, or does it imply a rejection with a “forbidden” cursor indicator?

Does the cursor imply to the user that the operation will be a move, link, or a copy, such as with a “plus” sign indicator on the cursor?

Does the area or target you are hovering over change its appearance in any way to indicate that it is currently selected as a drop if you release right now?

In order to give similar feedback to users over the course of an HTML drag-and-drop operation, the browsers will emit a whole slew of events over the course of a single drag. This proves quite handy, as during these events we will have full power to change the DOM and style of the page elements to give just the type of feedback that users will be expecting.

Beyond the drag source and drop target, there is one more key concept to learn in the new API: the data transfer. The specification describes the data transfer as the set of objects used to expose the drag data store that underlies a drag-and-drop operation. However, it may be easier just to think of the data transfer as being the central control of drag-and-drop. The operation type (e.g., move, copy, or link), the image to use as feedback during the drag, and the retrieval of the data itself are all managed here.

Regarding the data itself, the dataTransfer mechanism for completing the drop directly addresses one of the limitations of the old ad hoc drag-and-drop techniques described previously. Instead of forcing all drag sources and drop targets to be aware of each other, the data transfer mechanism works similar to a network protocol negotiation. In this case, the negotiation is performed via Multipurpose Internet Mail Exchange (MIME) types.

Note MIME types are the same types used to attach files to e-mail. They are an Internet standard that is used pervasively in all types of Web traffic, and they are very common in HTML5. In short, MIME types are standardized

219

CHAPTER 9 WORKING WITH DRAG-AND-DROP

text strings used to classify the type of unknown content, such as “text/plain” for plain text and “image/png” for PNG images.

The purpose of using MIME types is to allow the source and target to negotiate on which format best suits the needs of the drop target. As shown in Figure 9-2, during a drag start, the dataTransfer object is loaded up with data representing all reasonable types, or “flavors,” by which the data can be transferred. Then, when the drop completes, the drop handler code can scan the available types of data and decide which MIME type format best suits its needs.

For example, imagine a list item in a web page representing a person. There are many different ways to represent the data for a person; some are standard, some are not. When a drag starts on a particular person’s list item, the drag start handler can declare that the person’s data is available in a few formats, as shown in Table 9-1.

Table 9-1.Examples of MIME Types in Data Transfer of a Person

MIME Type

Result

 

 

text/plain

A standard MIME type for unformatted text. We can use it as the

 

most common representation, such as the person’s name.

image/png

A standard MIME type for PNG images. Here, it could represent the

 

person’s picture in PNG format.

image/jpeg

text/x-age

The standard MIME type for JPEG images. It could be used to transfer the person’s picture in that format.

A non-standard MIME type (as indicated by the x- prefix). We could use this format to transfer our own types of information, such as the person’s age.

When the drop completes, the drop handler can query for a list of available data types. From the provided list, the handler can choose which type is most appropriate. A text list drop target may choose to grab the text/plain “flavor” of data to retrieve the person’s name, while a more advanced control might choose to retrieve and display the person’s PNG image as a result of the drop. And, if the source and target have coordinated on non-standard types, the target could also retrieve the person’s age at the time of the drop.

220

CHAPTER 9 WORKING WITH DRAG-AND-DROP

Figure 9-2. Drag and drop negotiation of data “flavors”

It is this negotiation process that allows for drag sources and drop targets to be decoupled. As long as the drag sources provide data in a choice of MIME types, the drop target can choose which format suits its operation the best, even if the two came from different developers. In later sections of this chapter, we’ll explore how even more unusual MIME types, such as files, can be used.

Events to Remember

Now that we’ve explored the key concepts of the drag-and-drop API, let’s focus on the events that can be used throughout the process. As you’ll see, the events operate at a higher level than the mouse events previously utilized to mock up a drag-and-drop system. However, drag-and-drop events extend the DOM mouse event. Therefore, you still have access to the low-level mouse information, such as coordinates, if you need it.

Propagation and Prevention

But before we focus on drag and-drop-itself, let’s refresh on two DOM event functions that have been around since the browsers standardized on DOM Level 3 events: the stopPropagation and preventDefault functions.

Consider the case where one element in a page is nested inside another element. We will refer to them as the child and parent elements, respectively. The child takes up some, but not all, of the visible space of the parent. Although we are only referring to two elements in our example, in practice a web page often has many levels of nesting.

When a user clicks a mouse on the child, which element should actually receive the event: the child, the parent, or both? And if both, in which order? The answer to this question was settled by the World Wide Web Consortium (W3C) in the DOM events specification. Events flow from a parent, through intermediaries, and down to the most specific child first in a process known as “event capture.” Once the child has had access to the event, the event flows back up the element hierarchy via a process known as “event bubbling.” Together, these two flows allow developers to catch and process the event in the way that is most suitable to their page architecture. Only elements with handlers actually registered will process the event, which keeps the system lightweight. The overall approach is a compromise among

221

CHAPTER 9 WORKING WITH DRAG-AND-DROP

different behaviors from multiple browser vendors, and it is consistent with other native development frameworks, some of which capture and some of which bubble.

However, at any time a handler can call the stopPropagation function on the event, which will stop it from further traversing down the event capture chain or up through the bubbling phase.

Note Microsoft has provided a great interactive demo of event models at http://ie.microsoft.com/testdrive/HTML5/ComparingEventModels

Browsers also have default implementations for how some events will be handled. For example, when a user clicks on a page link, the default behavior is to navigate the browser to the destination specified by the link. Developers can prevent this by intercepting the event in a handler and calling preventDefault on it. This allows code to override the default behaviors of some built-in events. It is also how a developer can cancel a drag-and-drop operation in an event handler.

Both stopPropagation and preventDefault will be handy in our examples of the drag-and-drop API.

Drag-and-Drop Event Flow

When a user initiates a drag-and-drop operation in an HTML5-ready browser, a series of events trigger at the start and continue throughout the course of the whole operation. We will examine them in turn here.

dragstart

The dragstart event is fired on an element in the page when the user begins to drag on it. In other words, once the mouse is down and the user moves the mouse, the dragstart is initiated. The dragstart event is of key importance, as it is the only event where the dataTransfer can have data set on it using the setData call. This means that in a dragStart handler, the possible data types need to be set up so that they can be queried at the end of the drop, as described previously.

Interception!

Brian says: “If you are wondering why the data types can only be set during the dragStart event, there’s actually a very good reason for that.

Because drag-and-drop has been designed to work across windows and across content from various sources, it would be a security risk if drag event listeners were able to insert or replace data when the drag passed over them. Imagine a malicious section of code with event listeners inserted that queried and replaced drag data of any drag travelling by. This would misrepresent the intentions of the drag source, and as such any data replacements after the start are forbidden.”

222

CHAPTER 9 WORKING WITH DRAG-AND-DROP

drag

The drag event can be thought of as the continuous event of a drag operation. As the user moves the mouse cursor around the page, the drag event is called repeatedly on the drag source. The drag event will fire a few times each second during the operation. Although the visuals of the drag feedback can be modified during a drag event, the data on the dataTransfer is off-limits.

dragenter

When the drag crosses into a new element on the page, a dragenter event fires on that element. This event is a good time to set drop feedback on the element based on whether or not it can receive the drop.

dragleave

Conversely, the browser will fire a dragleave event whenever the user moves the drag out of the element where dragenter was previously called. Drop feedback can be restored at this time, as the mouse is no longer over this target.

dragover

The dragover event is called at frequent intervals as the mouse moves over an element during a drag operation. Unlike its counterpart drag event, which is called on the drag source, this event is called on the current target of the mouse.

drop

The drop event is called on the current mouse target when the user releases the mouse. Based on the result of the dataTransfer object, this is where the code to handle the drop should be executed.

dragend

The final event in the chain, dragend fires on the drag source, indicating that the drag completed. It is particularly suitable for cleaning up the state used during the drag, as it is called regardless of whether or not the drop completes.

Altogether, there are plenty of ways for you to intercept the drag-and-drop operations and take action. The drag-and-drop event chain is summarized in Figure 9-3.

223