[whatwg] Thoughts and feedback on HTML5 drag and drop API

Hi,

After having a bug while trying to implement a browser-based chess game
using the native Drag&Drop API, I have decided to investigate a bit on
this API, examples and opinions.
There is already a very good explanation of the current state of the API
and how to use it here : http://html5doctor.com/native-drag-and-drop/

And here is a quite "biased" opinion on the API :
http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
Even if I would use the same words, my reaction has roughly been the
same (for those who wouldn't have the time to read the article, its
author is furious about the API) while implementing an example. From my
experience as a web author writing the chess game, I have found
completely counter-intuitive to have to register a listener to the
dragover event only to ".preventDefault()" the event.
In my humble opinion, .preventDefault should be used really when the
default behavior (triggered either because of the spec imposes so or
because of the user agent implementation) goes against the web app needs.
I think a very good example of this is Wikidot (a wiki engine) on which,
if I remember well, you can save the page you're editing by doing
Ctrl+S. In most web browsers, Ctrl+S opens a menu to save the HTML page.
I have never looked at their code, but it's very likely that for Ctrl+S,
they have decided to prevent the default behavior, which makes sense.


To be slightly more structured, I am going to continue this e-mail
following this outline :
- From where to where ?
-- Same document
-- Document <---> Desktop
-- Different documents
- Influences of the drag&drop API
- Misc feedback


_From where to where ?_
In my opinion, a part of the confusion on the D&D API comes from the
fact that Drag & Drop can actually have different "meanings" depending
on the way the drag and drop is intended to be used. Even if clearly
stated by the spec that "this specification does not define exactly what
a drag-and-drop operation actually is.", I think that there are a lot of
things that should be said and distinguished. For instance, when I read
"drag-and-drop operations must have a starting point", I think it should
be explicitely mentionned that this starting point can be either from a
document (fully falling under the definition of this spec) or from
outside of it (like when you want to drop files in your web browser).
The same for the ending point. All the combinations can be listed (tell
me if I forget one) :
- FROM a document TO the same document
- FROM a document TO another document (there are a lot of different cases)
- FROM a document TO outside
- FROM outside TO a document


__Same document__
The "same document" use case is the one I fall into with my chess game.
I want to drag and drop pieces from one square to another and writing my
application with the conviniency of the all the drag* / drop events (and
not struggling with mouseup/down/move and changing the top and left
style attributes). In this use case like in other, one main concern of
the drag&drop operation is to transfer data from one point to another.
That is supposed to be the dataTransfer object purpose. However, for the
"same document use case" the dataTransfer object is pointless since you
can make communicate your handlers through an object. Accelerated example :
(function(){
    var drag = document.getElementById('drag'); // has the draggable
attribute to true, obviously
    var drop = document.getElementById('drop');
    var dragInfo = {};

    function dragStartHandler(e){ // This function is a closure using
the dragInfo object
        dragInfo.blabla = 'hello world !';
        // dragInfo is an ECMAScript object which is less restrictive
than the dataTransfer object
    }

    function dropHandler(e){ // This function is a closure using the
dragInfo object
        alert(dragInfo.blabla);
    }

    drag.addEventListener('dragstart', dragStartHandler, false);
    drop.addEventListener('drop', dropHandler, false);
    drop.addEventListener('dragover', function(e){e.preventDefault();},
false);
})();

In my opinion, a lot of early examples of usage of the API (including
but not limited to : http://ljouanneau.com/lab/html5/demodragdrop.html ,
http://decafbad.com/blog/2009/07/15/html5-drag-and-drop) advertise the
usage of dataTransfer even for the cases when this is (in my opinion)
useless and I hope that my example is a sufficient proof.
The provided example in the spec seems to be written in a way that make
think that drag and drop operations occur within the same document (it's
never written specifically). If it's the case, I think that a different
example should be provided without dataTransfer.


__Document <---> Desktop__
This use case is actually the one that really requires the dataTransfer
object espescially the recent "files" attribute. As opposed to the
previous use case, this one may have main security issues and
restrictions due to the terra incognita that "outside of the document"
can be.
A very good example of usage :
http://hacks.mozilla.org/2009/12/file-drag-and-drop-in-firefox-3-6/


__Different documents__
There are several cases that could be considered. I am not sure I will
think of all. Add other if you think they are relevant.

___Common "iframe tree" ancestor___
If two documents are "discussing" through a drag and drop operation and
if they are enclosed in iframes (either one contains the other or they
have a common ancestor), then, the dataTransfer could certainly allow
the transfer of "up to" DOM Elements since we stay in the same user
agent and there is a common document. (Web developers will have to be
careful of Node ownerDocument, but we don't really care about that now).

___Different documents within the same user agent___
I don't have enough knowledge to discuss this point. Maybe that
implementors will have ideas on this one. At least, user agent can have
user-agent-specific attributes for the dataTransfer object

___Different documents across different user agents___
Once again, this goes beyond my knowledge. There is certainly no way for
a user agent to know if the drop has been originated from another
(HTML5-compliant :-) ) user agent. Even if it was the case, it would
probably be a security issue since the dataTransfer could be crafted.


Let's stay within the same user for the moment.
___Different document, same origin___
___Different document, different origin___
Maybe it'd be convenient to know where a drop comes from. Restrictions
could be applied by the user agent if the dataTransfer comes from a
different-origin document. On the other hand, a lot could be allowed if
the document has the same origin. At least, some attribute could be
added for the origin as it is done with the cross-document communication.




- Influences of the Drag and Drop API
As far as I know, the current API is mostly influenced by the IE5+ API.
10 years later, a lot have been done on the web regarding drag and drop.
Most of the JavaScript libraries have a drag&drop feature. This is
actually how I have first developed a drag & drop feature for a web app,
hence my frustration when trying to use the native API for the "same
document" use case.
The librairies have different models, but a lot in common. I don't know
them by heart and them all neither, but it would probably be interesting
to have a look at the different features they offer and maybe review the
native drag and drop API to consider if these librairies can implement
their features through the native API .
Here is the documentation from four main libraries with a D&D feature :

script.aculo.us :
http://wiki.github.com/madrobby/scriptaculous/draggables-object
http://wiki.github.com/madrobby/scriptaculous/droppables
http://wiki.github.com/madrobby/scriptaculous/draggable

jQuery UI :
http://jqueryui.com/demos/draggable/
http://jqueryui.com/demos/droppable/

Mootools :
http://mootools.net/docs/more/Drag/Drag

YUI :
http://developer.yahoo.com/yui/3/api/Drag.html

Among the things in common, I think that there is the fact of explicitly
declaring which elements are drop targets. In jQueryUI, draggable
elements are distinguished by the ui-draggable class. Symetrically,
droppable elements have the ui-droppable class.
I think that it would make sense that "draggable" and "droppable"
elements have some common features. For instance, it's easy to refer to
draggable elements in CSS since there is an attribute with the selector
*[draggable="true"] (I'm not sure of how CSS work for boolean attribute.
Moving on...). On the other hand, to stylize specifically droppable
elements, you'd have to be very careful on which elements handle the
drop event (and .preventDefault() the dragover event !!) or not and
"manually" update a class on the element. For that matter, a droppable
attribute could be beneficial.


_Misc feedback_
* Regardless if the D&D spec example is changed (or another one added
for the "same document" use case without dataTransfer), please add a
comment next to the "event.preventDefault();" of the dragOverHandler
function to explain that the purpose of this is to define a drop target.
* I am worried about the effectAllowed attribute. Needless to say that
the number of value is exponencially proportional to the number of
possible values for the dropEffect attribute. Wouldn't it be better to
have a linear number of booleans ?
* About all the drag feedback generation, I am doubting that the current
API allows the rich effects that the JS librairies provide.
Do anyone have enough experience with these to tell if they see use
cases covered by the librairies that the native API wouldn't allow to
cover ?


I have seen in whatwg.org/issues that drag and drop is
"delayed-awaiting-more-implementation-experience". I haven't seen a wiki
page on http://wiki.whatwg.org/wiki/ though. Is there one ? Should one
be created to gather all the feedback and relevant resources regarding D&D?

Thanks for reading this quite long e-mail!
Comments, questions and input on places where I have lacking
skill/knowledge/experience are the most welcome !

David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20100815/70682132/attachment.htm>

Received on Sunday, 15 August 2010 13:11:54 UTC