YUI recommends YUI3.
YUI 2 has been deprecated since 2011. This site acts as an archive for files and documentation.
This documentation is no longer maintained.
The Drag & Drop Utility allows you to create a draggable interface efficiently, buffering you from browser-level abnormalities and enabling you to focus on the interesting logic surrounding your particular implementation. This component enables you to create a variety of standard draggable objects with just a few lines of code and then, using its extensive API, add your own specific implementation logic.
For more information about drag and drop as a design pattern, see the Yahoo! Design Pattern Libary.
To use Drag and Drop, include the following source files in your web page with the script tag:
<!-- Dependencies --> <script src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js" ></script> <!-- Drag and Drop source file --> <script src="http://yui.yahooapis.com/2.9.0/build/dragdrop/dragdrop-min.js" ></script>
<!-- Dependencies --> <script src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js" ></script> <!-- Drag and Drop source file --> <script src="http://yui.yahooapis.com/2.9.0/build/dragdrop/dragdrop-min.js" ></script>
Instead of copying and pasting the filepaths above, try letting the YUI dependency Configurator determine the optimal file list for your desired components; the Configurator uses YUI Loader to write out the full HTML for including the precise files you need for your implementation.
Note: If you wish to include this component via the YUI Loader, its module name is dragdrop
. (Click here for the full list of module names for YUI Loader.)
Where these files come from: The files included using the text above will be served from Yahoo! servers. JavaScript files are minified, meaning that comments and white space have been removed to make them more efficient to download. To use the full, commented versions or the -debug
versions of YUI JavaScript files, please download the library distribution and host the files on your own server.
Order matters: As is the case generally with JavaScript and CSS, order matters; these files should be included in the order specified above. If you include files in the wrong order, errors may result.
To enable a simple drag and drop of any DOM element, create a new instance of YAHOO.util.DD
, providing the constructor with the HTML id of the element you want to make draggable. Optionally, you can provide an element reference instead of an id
var dd1 = new YAHOO.util.DD("element1"); // alternatively, use an element reference // var el=YAHOO.util.Dom.get("element1"); // var dd1 = new YAHOO.util.DD(el);
var dd1 = new YAHOO.util.DD("element1"); // alternatively, use an element reference // var el=YAHOO.util.Dom.get("element1"); // var dd1 = new YAHOO.util.DD(el);
In this example, a new instance of YAHOO.util.DD
is created for an element whose HTML id is "element1"; this enables "element1" to be dragged and dropped. Note that while the element can now be moved visually on the page, this visual motion is accomplished by changing the element's style properties. Its actual location in the DOM itself remains unchanged.
In many Drag and Drop implementations, the dragged element does not track with the mouse while being moved — often because it is large and tends to obscure information beneath it during the drag. One solution to this problem is to use a proxy element, usually a smaller visual representation of the original, that tracks with the mouse during a drag event. The Drag and Drop Utility makes it extremely easy to accomplish this effect; simply instantiate YAHOO.util.DDProxy
instead of YAHOO.util.DD
:
var dd2 = new YAHOO.util.DDProxy("element2");
var dd2 = new YAHOO.util.DDProxy("element2");
In this case, "element2" is made draggable, but during the drag event it will be represented visually by a proxy element created automatically by the Drag and Drop Utility. See the API documentation for YAHOO.util.DDProxy
for more information about how to access and stylize this proxy element. When the drag interaction is completed, "element2" will move to the drop position and the proxy element will be hidden.
In addition to YAHOO.util.DD
and YAHOO.util.DDProxy
, a third type of Drag and Drop object is available with the utility: the target object (YAHOO.util.DDTarget
). Targets are elements that participate in the drag interaction (that is, you are made aware that they are being dragged over or dropped upon) but that are not themselves draggable.
var dd3 = new YAHOO.util.DDTarget("element3");
var dd3 = new YAHOO.util.DDTarget("element3");
In the example above, the HTML element whose ID is "element3" serves as a target for Drag and Drop interactions, but the user cannot drag "element3" itself.
See the examples below in Using Drag and Drop or the API Documentation for more details.
This section describes several common features and uses and of Drag and Drop. See the Examples for additional code and implementation samples.
Drag and Drop operations within a page are managed by the Drag and Drop Manager, a singleton object accessible as YAHOO.util.DragDropMgr
(this object can also be referenced via its shorter alias, YAHOO.util.DDM
). The Drag and Drop Manager controls a variety of key settings that may be of interest to you in configuring Drag and Drop interactions — for example, the time delay that defines when a mousedown event becomes a drag event is configured via YAHOO.util.DragDropMgr
:
//sets the time delay between a mousedown and a //drag event to 1200 milliseconds: YAHOO.util.DragDropMgr.clickTimeThresh = 1200;
//sets the time delay between a mousedown and a //drag event to 1200 milliseconds: YAHOO.util.DragDropMgr.clickTimeThresh = 1200;
A variety of other useful settings are configured via YAHOO.util.DragDropMgr
; see the API documentation for this object to read more about its capabilities.
Each Drag and Drop object belongs to one or more interaction groups. Drag and Drop events fire only when the dragged element interacts with other objects that with which it shares a group membership. If no group is specified in the constructor, an object belongs to the "default" group.
// No group specified so dd0 is assigned to the "default" group var dd0 = new YAHOO.util.DD("elementid0"); // dd1 is a member of group1 var dd1 = new YAHOO.util.DD("elementid1", "group1"); // dd2 is a member of group2 var dd2 = new YAHOO.util.DD("elementid2", "group2"); // dd3 is a member of both group1 and group2 var dd3 = new YAHOO.util.DD("elementid3", "group1"); dd3.addToGroup("group2"); //groups can be removed via script as well: dd1.removeFromGroup("group1");
// No group specified so dd0 is assigned to the "default" group var dd0 = new YAHOO.util.DD("elementid0"); // dd1 is a member of group1 var dd1 = new YAHOO.util.DD("elementid1", "group1"); // dd2 is a member of group2 var dd2 = new YAHOO.util.DD("elementid2", "group2"); // dd3 is a member of both group1 and group2 var dd3 = new YAHOO.util.DD("elementid3", "group1"); dd3.addToGroup("group2"); //groups can be removed via script as well: dd1.removeFromGroup("group1");
An optional third argument in drag-and-drop object constructors is an object literal containing configuration info for well-known properties. The following example uses this configuration object to specify an existing HTML element as the drag proxy for this instance instead of the default:
var dd = new YAHOO.example.DDProxy("dragDiv1", "proxytest", { dragElId: "existingProxyDiv" });
var dd = new YAHOO.example.DDProxy("dragDiv1", "proxytest", { dragElId: "existingProxyDiv" });
The following configuration properties are currently supported via the contructor's configuration object:
YAHOO.util.DragDrop
: padding, isTarget, maintainOffset, primaryButtonOnlyYAHOO.util.DD
(in addition to those in YAHOO.util.DragDrop
): scrollYAHOO.util.DDProxy
(in addition to those in YAHOO.util.DD
): resizeFrame, centerFrame, dragElIdAll of these properties are public fields in the respective classes. See the API documentation for information about the fields.
Simply making an object draggable rarely suffices to achieve the desired interaction behavior for a drag-and-drop implementation. In most cases, Drag and Drop requires that you write code to respond to the interesting moments in the interaction: when the drag event starts, when the dragged object enters another object, and so on. The Drag and Drop Utility provides methods that fire during each of the interesting moments of the interaction. You customize your implementation by supplying the code for these methods (all of which are members of the YAHOO.util.DD
, YAHOO.util.DDProxy
, and YAHOO.util.DDTarget
).
Moment | Description |
---|---|
onMouseDown | Provides access to the mousedown event. The mousedown does not always result in a drag operation. |
startDrag | Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. |
onDrag | Occurs every mousemove event while dragging. |
onDragEnter | Occurs when the dragged object first interacts with another targettable drag and drop object. |
onDragOver | Fires every mousemove event while over a drag and drop object. |
onDragOut | Fires when a dragged object is no longer over an object that had the onDragEnter fire. |
onDragDrop | Fires when the dragged objects is dropped on another. |
onInvalidDrop | Fires when the dragged objects is dropped in a location that contains no drop targets. |
endDrag | Fires on the mouseup event after a drag has been initiated (startDrag fired). |
onMouseUp | Fires on the mouseup event whether or not a drag was initiated. |
In version 2.5.0, Custom Events were added to all DragDrop instances. See the API documentation for information about the events.
Event | Description |
---|---|
mouseDownEvent | Provides access to the mousedown event. The mousedown does not always result in a drag operation. |
mouseUpEvent | Fired from inside DragDropMgr when the drag operation is finished. |
startDragEvent | Occurs after a mouse down and the drag threshold has been met. The drag threshold default is either 3 pixels of mouse movement or 1 full second of holding the mousedown. |
endDragEvent | Fires on the mouseup event after a drag has been initiated (startDrag fired). |
dragEvent | Occurs every mousemove event while dragging. |
invalidDropEvent | Fires when the dragged objects is dropped in a location that contains no drop targets. |
dragOutEvent | Fires when a dragged object is no longer over an object that had the onDragEnter fire. |
dragEnterEvent | Occurs when the dragged object first interacts with another targettable drag and drop object. |
dragOverEvent | Fires every mousemove event while over a drag and drop object. |
dragDropEvent | Fires when the dragged objects is dropped on another. |
You can subscribe to these events using the on
method for the DragDrop instance.
var dd = new YAHOO.util.DD('demo'); dd.on('dragEvent', function(ev) { YAHOO.log('Element is being dragged.'); }, dd, true);
var dd = new YAHOO.util.DD('demo'); dd.on('dragEvent', function(ev) { YAHOO.log('Element is being dragged.'); }, dd, true);
By default, the drag and drop interaction is defined by the location of the mouse cursor during the drag operation (Point mode). Intersect mode takes into account the dragged element's dimensions, reporting when that element intersects with any other drag and drop element in its group or groups.
You can switch from point mode to intersect mode at any time by setting
the property YAHOO.util.DDM.mode
to the constant YAHOO.util.DDM.INTERSECT
.
//set Drag and Drop to Intersect mode: YAHOO.util.DDM.mode = YAHOO.util.DDM.INTERSECT; //set Drag and Drop to Point mode (default): YAHOO.util.DDM.mode = YAHOO.util.DDM.POINT;
//set Drag and Drop to Intersect mode: YAHOO.util.DDM.mode = YAHOO.util.DDM.INTERSECT; //set Drag and Drop to Point mode (default): YAHOO.util.DDM.mode = YAHOO.util.DDM.POINT;
A major side effect of switching to intersect mode is that it becomes far more
likely that multiple Drag and Drop objects will be overlapping during a drag event — which means that events like onDragEnter
and especially onDragOver
will be firing much more often.
Because of this, the API's interesting moments are handled somewhat differently in each mode. The following table describes the core differences between API events in Point mode and Intersect mode:
Moment | Point Mode | Intersect Mode | Notes |
---|---|---|---|
onMouseDown | e | e | e is the mousedown event |
startDrag | x, y | x, y | x,y is the location of the mousedown |
onDrag | e | e | e is the mousemove event |
onDragEnter | e, id | e, DDArray | e is the mousemove event; id is the drag and drop object involved; DDarray is an array of drag and drop objects |
onDragOver | e, id | e, DDArray | e is the mousemove event; id is the drag and drop object involved; DDarray is an array of drag and drop objects |
onDragOut | e, id | e, DDArray | e is the mousemove event; id is the drag and drop object involved; DDarray is an array of drag and drop objects |
onDragDrop | e, id | e, DDArray | e is the mouseup event; id is the drag and drop object involved; DDarray is an array of drag and drop objects |
onInvalidDrop | e | e | e is the mouseup event; |
endDrag | e | e | e is the mouseup event; |
onMouseUp | e | e | e is the mouseup event; |
Point mode returns the id of the target Drag and Drop object (e.g., the object over which you are dragging in onDragDrop
), while
Intersect mode returns an array of Drag and Drop objects instead.Note: it
is possible to have stacked Drag and Drop objects — objects
which overlap each other spatially. In Point mode, a drop on two stacked
items would result in two onDragDrop
events being fired; in Intersect mode,
only one event is triggered, but an array of targeted objects is passed to
that single event handler.
The reason the Drag and Drop objects are passed to the event handler in Intersect mode is that they contain properties about the interaction that can help determine the most appropriate response in your implementation:
cursorIsOver
property is true if the mouse cursor was over the Drag and Drop element
when the interaction happened. Often this will be an important factor as you calculate the intent of the user. YAHOO.util.Region
object that specifies the location
and dimensions of the overlap of the two Drag and Drop objects. The size of this region can be used to determine
which element had more overlap (YAHOO.util.Region.getArea
). getBestMatch
method uses the two strategies above to deduce
which among the multiple matches is the most significant. The getBestMatch
method returns either the first match it finds for which cursorIsOver
is true, or (if the cursor is not over a target) the one with the largest
overlap. 2.6.0 introduces the use of the Drag Shim to help with dragging over troublesome nodes. The Drag Shim is used to track the mousemove
at a higher level instead of at the document
level.
You can use this setting to allow dragging a node over an iframe or other such element that traps mouse events.
You can either use the Drag Shim on a per instance basis or on all draggable nodes.
//Instance based at creation var dd = new YAHOO.util.DDProxy('demo', { useShim: true }); //Instance based at runtime //Must be called before startDrag to take effect. dd.useShim = true; //All DD objects on the page YAHOO.util.DDM.useShim = true;
//Instance based at creation var dd = new YAHOO.util.DDProxy('demo', { useShim: true }); //Instance based at runtime //Must be called before startDrag to take effect. dd.useShim = true; //All DD objects on the page YAHOO.util.DDM.useShim = true;
The complexity of the application logic in the interesting moments
of Drag and Drop can have significant performance implications. This is particularly
true of the onDrag event; onDragOver
fires with every mouseMove event reported by the browser during a drag interaction.
Optimize your onDrag
(and, similarly, your onDragOver
) code as much as possible; try to avoid iterative code, opting for object hashtables in the event that you need to perform basic data lookups each time the event fires.
Getting and setting the position of elements, an intrinsic aspect of drag interactions, gets progressively more expensive
the deeper the element is in the DOM. If you encounter performance issues
using Drag and Drop, consider using YAHOO.util.DDProxy
instead of YAHOO.util.DD
; the proxy element is absolutely positioned
in the document body and therefore requires fewer cycles for repositioning.
Storyboarding can be a powerful strategy for thinking through a rich interaction during the design phase. We have created a storyboard matrix for Drag and Drop (ZIPed XLS file) that helps you track the actors and the events that are important when a Drag and Drop interaction is taking place. Interesting moments (which correspond to API events for which you can write handlers) are listed across the top; each row in the matrix represents an element.
The YUI Library and related topics are discussed on the on the YUILibrary.com forums.
Also be sure to check out YUIBlog for updates and articles about the YUI Library written by the library's developers.
The YUI Library's public bug tracking and feature request repositories are located on the YUILibrary.com site. Before filing new feature requests or bug reports, please review our reporting guidelines.
All YUI 2.x users should review the YUI 2.8.2 security bulletin, which discusses a vulnerability present in YUI 2.4.0-2.8.1.
Copyright © 2013 Yahoo! Inc. All rights reserved.