Dynamic Drag-and-Drop without the Hassle
Like most of the other library components, when creating your own drag-and-drop elements, there are a range of different options available to you that allow you to tailor those objects to your requirements. These properties, like those of most other library components, can be set using an object literal supplied with the constructor, but in most cases even this is not required.
The most challenging aspects of any drag-and-drop scenario in your web applications are going to center around the design of your specific implementation rather than in getting drag-and-drop to work in the first place. This utility is yet another example of the huge benefits the YUI can provide in reducing the amount of coding and troubleshooting that you need to concern yourself with.
The Different Components of Drag-and-Drop
In addition to the configurable properties used in your object literal, you also have several constructors that can be used to enable drag-and-drop. The first constructor YAHOO.util.DD allows for drag-and-drop at its most basic level. The supplied element will be transformed into an object that can be dragged around the page.
The mechanics of drag-and-drop result in a burden of fairly high processing. The library has to keep track of the mouse pointer whilst it is moving, the draggable object needs to be repositioned, and different events are almost continually firing while the drag is taking place.
In order to minimize the amount of information that needs to be processed, especially when the draggable object is fairly large, you can make use of a proxy element that will track across the page with the mouse pointer. When the proxy element reaches its final destination, it disappears and is replaced by the actual element.
If a proxy element is required, we can use the YAHOO.util.DDProxy constructor instead of the basic constructor. As the proxy element is just an empty <div>, it’s much easier to track and can even be shared between different drag objects on the page, reducing the overall processing that’s required.
Personally I think the default appearance of the proxy element is perfectly adequate, however you can also create your own custom elements to use as a proxy. The figure below shows the default proxy-element appearance:
When working with DragDrop implementations, it is useful to consider the following aspects of the design:
- Can any part of the drag object be clicked on to initiate the drag, or should a drag handle be defined?
- Can the object be dropped on to any part of the page or should a specific drop target be defined?
- Should anything occur whilst the object is being dragged?
- Should anything occur when the item is dropped on a non-valid target?
- Should anything occur when the object is dropped on to a valid target?
Events are an integral aspect of many DragDrop situations. Sometimes, however, being able to move something around the screen is the only behavior that’s required, but generally you’ll want something to happen either while the object is being dragged, or when it is dropped.
The YAHOO.util.DragDrop utility provides a series of custom events which allow you to hook into and respond to events such as startDrag, endDrag, onDrag, onDragDrop, and onInvalidDrop. Valid targets also expose events of their own including onDragEnter, onDragOut, and onDragOver. We will be looking at a number of these events during the example that follows.
Allowing Your Visitors to Drag-and-Drop
The Drag-and-Drop utility uses tried and tested DHTML techniques, as well as some innovative new features, to allow you to easily create objects that can be dragged and then dropped. All that you need to do to make an element on your page dragable is to create a new instance of the YAHOO.util.DD class and feed in the id or element reference of the element that drag is to be enabled for.
The base class of the Drag-and-Drop utility is YAHOO.util. DragDrop, but you’ll use one of its extending subclasses, like YAHOO.util.DD, most of the time. This subclass inherits all of the properties and methods of the base class and even adds a few of its own, so it’s more than capable of handling most of your drag-and-drop requirements.
The YAHOO.util.DD class also has its own subclasses to deal with additional drag-and-drop requirements for different situations. The subclasses are YAHOO.util.DDProxy and YAHOO.widget.SliderThumb. As you can see, the Drag-and-Drop utility provides some of the basic functionality of another of the controls found in the YUI, the Slider Control (which we will look at in more detail towards the end of this article). Let’s examine the DDProxy class, as that is relevant specifically to the Drag-and-Drop utility.
Creating a proxy object that tracks with the cursor when a drag object is being dragged instead of allowing the actual drag object to track can prevent problems that arise with large drag objects not tracking properly or obscuring other content on the page. The proxy object is a small, empty object that represents the drag object and shows only its borders.
The proxy object is created on the mouseDown event of the drag object and the actual drag object does not move to its new position until the mouseUp event is fired. Using a proxy object is both visually appealing and better overall for all but the simplest of implementations performance wise.
The constructor for an instance of the DragDrop object can also take a second or third argument when you are instantiating objects for dragging. The second argument, which is optional, specifies the group to which the element being dragged belongs.
This refers to interaction groups—the object being dragged can only interact with and fire events with other elements in its interaction group. The third argument, which is also optional, can be used to supply a configuration object, the members of which hold additional optional configuration properties that can easily be accessed and set.
Every object instantiated with the drag-and-drop constructor is a member of one or more interaction group(s), even if the second argument is not passed. When the argument is not supplied, the object will simply belong to the ‘default’ group instead. There is no limit as to how many groups an object can belong to.
The API provides just two methods that relate to group access. .addToGroup() is used to add the object to more than one group, so the first group membership is defined with the constructor and subsequent groups with the .addToGroup() method. To remove an object from a group, just call the .removeFromGroup() method.
There is no doubt that drag-and-drop adds a hands-on, fun element to surfing the net that is way more engaging than simple point-and-click scenarios, and there are many serious applications of this behavior too.
But dragging is only half of the action; without assigned drop targets, the usefulness of being able to drag elements on the page around at leisure is almost wasted.
Drop targets have a class of their own in the Drag-and-Drop utility. Which extends the YAHOO.util.DragDrop base class to cater for the creation of drag elements that aren’t actually dragable and this is the defining attribute of a drop target.
The constructor is exactly the same as for the DD and Proxy classes with regard to the arguments passed, but YAHOO.util.DDTarget is used instead. The Target class has no methods or properties of its own, but it inherits all of the same methods and properties as the other two classes, including all of the events.