<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>alert debugging &#187; HTML 5</title>
	<atom:link href="http://www.alertdebugging.com/category/html-5/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.alertdebugging.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 05 Nov 2009 11:50:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>On HTML 5 Drag and Drop</title>
		<link>http://www.alertdebugging.com/2009/08/16/on-html-5-drag-and-drop/</link>
		<comments>http://www.alertdebugging.com/2009/08/16/on-html-5-drag-and-drop/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 04:22:26 +0000</pubDate>
		<dc:creator>tolmasky</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[HTML 5]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.alertdebugging.com/?p=260</guid>
		<description><![CDATA[HTML 5 is shaping up to be quite an impressive step up from the capabilities web developers are currently constrained to. One of my favorite new features provided by the spec is support for native drag and drop. Cappuccino and many other JavaScript libraries have had drag and drop support for quite a while now, [...]]]></description>
			<content:encoded><![CDATA[<p>HTML 5 is shaping up to be quite an impressive step up from the capabilities web developers are currently constrained to. One of my favorite new features provided by the spec is support for native drag and drop. <a href = "http://cappuccino.org/learn/tutorials/scrapbook-tutorial-2/">Cappuccino</a> and many other JavaScript libraries have had drag and drop support for quite a while now, but with one important caveat: the drag operations were limited to <b>within</b> the browser window. This was not only visually displeasing, but prevented you from being able to share data in a user friendly way from one web app to another, or even to other desktop apps.  HTML 5 aims to change all this by giving us access to the computer&#8217;s native drag system and clipboard. I took the last week to really familiarize myself with this API and its various implementations on current browsers so I could start adding support for it in Cappuccino. I feel that this gave me a pretty unique perspective on the current state of this feature which I&#8217;d like to share, mainly because I&#8217;ve had to make it work in a number of real (sometimes shipping) applications, as opposed to simplying creating small demos. The good news is that last night I was able to land my first <a href = "http://github.com/280north/cappuccino/commit/e8dd56bda70eb43a3be191e561f15f7674cd57f9">commit</a> which adds full HTML 5 drag and drop support for Safari and other WebKit-based browsers. Here is a short movie that shows this feature in action in our internal <a href = "http://280slides.com">280 Slides</a> builds:</p>
<p><center><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/Tg6okHlWwv0&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Tg6okHlWwv0&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></center></p>
<p>As you can see, this feature enables you to easily share data, whether it be images and shapes or full slides, from one presentation to another. What&#8217;s particularly cool about this is that you won&#8217;t have to change your existing code at all since Cappuccino simply detects when you are on a compliant browser and magically &#8220;upgrades&#8221; to native drag and drop. On older browsers, you will still get the old in-browser implementation. Ah, the beauty of abstraction.</p>
<p>This isn&#8217;t to say that working with this feature was all peaches and cream though. For starters, this feature is far from complete in any browser. I experienced a tremendous amount of bugs, crashes, and inconsistencies in all the browsers I tried. On the one hand, I got to play with a very exciting new toy, and on the other I was given a glimpse into the future of the bugs I would be dealing with for years to come (just when we thought the whole cross-browser thing was starting to become managable). This isn&#8217;t surprising of course, it is a very new addition and the spec isn&#8217;t even 100% complete yet. For this reason, I&#8217;ve decided to split this post up into two pieces. In the following I will be discussing what I believe to be actual and serious design flaws in the current API, as well as a few suggestions I have for how they might be remedied. I will also <a href = "http://www.alertdebugging.com/drag-and-drop-bugs/">separately link</a> to a page that has all the bugs and inconsistencies I discovered (as well as the associated tickets I filed on them), and workarounds when I could find them.</p>
<p>I believe the main &#8220;theme&#8221; of the problems I encountered was due to the fact that I am trying to build full-blown applications as opposed to dynamic web pages. This however is no excuse, as one of HTML 5&#8217;s supposed goals is to usher in an era of more web apps that are more competitive with desktop apps. This is precisely why Google is supporting it so heavily.</p>
<h2>Lazy Data Loading</h2>
<p>One of the key facilities of drag and drop is the ability to provide, and get, multiple representations of the same data. Different web pages, web apps, and desktop apps support different kinds of data, so it is up to your application to give them something they can work with. Take 280 Slides for example: When a user drags the slides out of slides navigator, he may be planning to drop it to any number of locations. If he is dragging it from one instance of 280 Slides to another, then we want to provide a serialized version of these slides so that they can be added to the other presentation. If however, he drags these slides into a program like Photoshop, then we would want to provide image data. If he were to drag them to his desktop, then perhaps we could provide a PDF version. He could even drag them to his text editor and expect the text contents of his slides to be pasted.<br />
<div id="attachment_283" class="wp-caption aligncenter" style="width: 418px"><img src="http://www.alertdebugging.com/wp-content/uploads/2009/08/dragdata.png" alt="Multiple Data Types" title="Multiple Data Types" width="408" height="505" class="size-full wp-image-283" /><p class="wp-caption-text">Multiple Data Types</p></div></p>
<p> The way you do this currently is with the setData function, which allows you to specify different types of data:</p>
<pre class="textmate-source"><span class="source source_js source_js_objj"><span class="support support_class support_class_js">document</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>addEventListener<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>dragstart<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="storage storage_type storage_type_js">function</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="support support_class support_class_js">event</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
   <span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>dataTransfer<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>setData<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>image/png<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span>slides<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>imageRep<span class="meta meta_brace meta_brace_round meta_brace_round_js">())</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
   <span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>dataTransfer<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>setData<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>slides<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span>slides<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>serializedRep<span class="meta meta_brace meta_brace_round meta_brace_round_js">())</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
   <span class="comment comment_line comment_line_double-slash comment_line_double-slash_js"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_js">//</span> etc.
</span><span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="constant constant_language constant_language_boolean constant_language_boolean_false constant_language_boolean_false_js">false</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span></span></pre>
<p>This is incredibly common on the desktop, and you&#8217;ve probably never noticed it precisely because it works so well: things seem to just do the right thing when you drag and drop them. However, an unfortunate side effect of this feature is that you end up doing a lot of extra unecessary work. The user only ever drops the item to <b>one</b> location, and so all the other formats you&#8217;ve created were wasted processing time. This is not a big deal for simple cases of drag and drop, but it becomes quite noticable in large applications like 280 Slides. In the example above, creating serialized and image representations of these slides can become quite slow depending on how many elements are in the individual slides and how many slides you are moving. Because of this you may experience a lag when you first drag the slides out. The worst part is, if all you intended to do was reposition the slides in the same presentation, then you didn&#8217;t need any of these formats!</p>
<p>This problem was solved in a very simple and intelligent way on the desktop a long time ago: simply delay supplying the actual data until the drop occurs. At the point of the drop, you actually know which of the 5 supplied types the user is interested in, so create it then. Not only does this save you from doing uncessary work, but generally users notice time spent processing after a drop a lot less (because there is no expected user feedback to stutter). I&#8217;ve thought a lot about a good way to allow the user to do this with the existing setData method , and I think it could be done by simply  allowing developers to provide functions that could be called when the data is needed:</p>
<pre class="textmate-source"><span class="source source_js source_js_objj"><span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>dataTransfer<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>setData<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>slides<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="storage storage_type storage_type_js">function</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">()</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
   <span class="keyword keyword_control keyword_control_js">return</span> costlySerialization<span class="meta meta_brace meta_brace_round meta_brace_round_js">()</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span> <span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span></span></pre>
<p>Perhaps a more backwards compatible alternative would be:</p>
<pre class="textmate-source"><span class="source source_js source_js_objj"><span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>dataTransfer<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>setData<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>slides<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span> <span class="meta meta_function meta_function_json meta_function_json_js"><span class="entity entity_name entity_name_function entity_name_function_js">toString</span>: <span class="storage storage_type storage_type_function storage_type_function_js">function</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_begin punctuation_definition_parameters_begin_js">(</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_end punctuation_definition_parameters_end_js">)</span></span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
   <span class="keyword keyword_control keyword_control_js">return</span> costlySerialization<span class="meta meta_brace meta_brace_round meta_brace_round_js">()</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span> <span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span> <span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span></span></pre>
<p>Although I don&#8217;t really think this is necessary since this API is so new.  Either way, this allows us to use the existing setData method, while not actually needing to calculate the string value until getData is actually called by the drop target.</p>
<h2>Initiating Drags</h2>
<p>Another major hurdle I encountered was in controling the way drags are actually started. Currently this is a delicate dance of preventDefaults and interactions between mousedown, mousemove, and dragstart, in combination with the draggable HTML attribute. The basic problem with this is that it leaves the decision to create a drag entirely to the the browser. Again, this is just fine for simple cases, but it really starts to break down when you are building full on applications in the browser. On the other hand, frameworks like Cocoa allow the developer to initiate the actual drag sequence. Lets look at why this is important with a simple example. It is quite common to want to start a drag event on the initial mouse down, instead of waiting for additional mouse move events. In these cases, it would be more confusing if the initial mouse down did nothing. This is currently impossible to achieve with the HTML 5 drag and drop APIs. In Cocoa, this would be quite simple, requiring the developer simply start the process in mouseDown: instead of mouseDragged:</p>
<pre class="textmate-source"><span class="source source_objc">- (<span class="storage storage_type storage_type_c">void</span>)mouseDown:(<span class="support support_class support_class_cocoa">NSEvent</span> *)anEvent
<span class="meta meta_block meta_block_c">{
   <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSView</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dragImage<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>myImage <span class="comment comment_block comment_block_c"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">/*</span>...<span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">*/</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}</span></span></pre>
<p>This is just a simple example of course. More complex widgets provide even more cases where drag and drop in the browser really works against you. Take tables in Mac OS X, which provide different behaviors depending on what direction the users drags in:</p>
<p><center><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/KR0TdwObWPs&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/KR0TdwObWPs&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></center></p>
<p>As you can see, when a user drags upwards in a table on Mac OS X, the selection of the table changes (in other words, no drag takes place). On the other hand, if the user drags left, right, or diagonally in any way, then he is allowed to move these files. This is very intuitive experience when you use it, and is absolutely trivial to implement in Cocoa:</p>
<pre class="textmate-source"><span class="source source_objc">- (<span class="storage storage_type storage_type_c">void</span>)mouseDragged:(<span class="support support_class support_class_cocoa">NSEvent</span> *)anEvent
<span class="meta meta_block meta_block_c">{
   <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>deltaX &gt; <span class="constant constant_numeric constant_numeric_c">10</span>)
       <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="support support_class support_class_cocoa">NSView</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">dragIamge<span class="punctuation punctuation_separator punctuation_separator_arguments punctuation_separator_arguments_objc">:</span></span>myImage <span class="comment comment_block comment_block_c"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">/*</span>...<span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">*/</span></span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
   <span class="keyword keyword_control keyword_control_c">else</span>
       <span class="meta meta_bracketed meta_bracketed_objc"><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_begin punctuation_section_scope_begin_objc">[</span><span class="variable variable_language variable_language_objc">self</span> <span class="meta meta_function-call meta_function-call_objc"><span class="support support_function support_function_any-method support_function_any-method_objc">modifySelection</span></span><span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_end punctuation_section_scope_end_objc">]</span></span>;
}</span></span></pre>
<p>However, this is again basically impossible with the current HTML 5 API, as you can never be a part of the decision as to whether an object is dragged or not. Once you get the drag event, it&#8217;s too late. You can imagine that this would become even more cumbersome in applications like <a href = "https://bespin.mozilla.com/">Bespin</a> that revolve less around specific tags and more around content that is drawn to a canvas elements. When a user drag in Bespin, they have to decide between any number of actions. I think a good solution to this would be to simply allow the developer to manually kick off a dragging event loop from either a mousedown or mousemove callback. Something like this:</p>
<pre class="textmate-source"><span class="source source_js source_js_objj"><span class="support support_class support_class_js">document</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>addEventListener<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>mousedown<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="storage storage_type storage_type_js">function</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="support support_class support_class_js">event</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
   <span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>startDrag<span class="meta meta_brace meta_brace_round meta_brace_round_js">()</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="constant constant_language constant_language_boolean constant_language_boolean_false constant_language_boolean_false_js">false</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>

<span class="support support_class support_class_js">document</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>addEventListener<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="string string_quoted string_quoted_double string_quoted_double_js"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_js">"</span>mousemove<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_js">"</span></span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="storage storage_type storage_type_js">function</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span><span class="support support_class support_class_js">event</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">{</span>
   <span class="keyword keyword_control keyword_control_js">if</span> <span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span>someCondition<span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span>
       <span class="support support_class support_class_js">event</span><span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>startDrag<span class="meta meta_brace meta_brace_round meta_brace_round_js">()</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span>
<span class="meta meta_brace meta_brace_curly meta_brace_curly_js">}</span><span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span><span class="constant constant_language constant_language_boolean constant_language_boolean_false constant_language_boolean_false_js">false</span><span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span></span></pre>
<p>In both these cases, calling startDrag would result in no further mousemoves/mouseups being fired in this event loop, and instead would kick off the drag event loop with a &#8220;dragstart&#8221; event. A matching cancelDrag() could be provided as well. This would allow you to cancel a <b>drag</b>, but not any other specific behavior such as selection. Currently calling preventDefault cancels <b>both</b> drags and selection. This actually leads to a number of other confusing results. For example, if you place a textfield within a draggable element, it is essentially impossible for text selection to happen in that textfield, even if you set the textfield itself to not be draggable.</p>
<h2>Drag Images</h2>
<p>One of the nice parts about drag and drop is that you are allowed to set any arbitrary image or element as what is actually rendered during the drag process with the setDragImage method:</p>
<pre class="textmate-source"><span class="source source_js source_js_objj">dragEvent<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>dataTransfer<span class="meta meta_delimiter meta_delimiter_method meta_delimiter_method_period meta_delimiter_method_period_js">.</span>setDragImage<span class="meta meta_brace meta_brace_round meta_brace_round_js">(</span>aDOMElement<span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span>offsetX<span class="meta meta_delimiter meta_delimiter_object meta_delimiter_object_comma meta_delimiter_object_comma_js">, </span>offsetY<span class="meta meta_brace meta_brace_round meta_brace_round_js">)</span><span class="punctuation punctuation_terminator punctuation_terminator_statement punctuation_terminator_statement_js">;</span></span></pre>
<p>However, on Firefox it is required that this element already be visible. Now, I wasn&#8217;t sure whether to list this as simply a bug in Firefox or an actual design flaw, but I chose to list it as a flaw because <a href = "https://developer.mozilla.org/En/DragDrop/DataTransfer">the documentation at mozilla.org</a> would seem to suggest that they may consider this to be &#8220;correct behavior&#8221;. Safari does not have this restriction, and in fact Firefox even seems to make <a href = "https://developer.mozilla.org/En/DragDrop/Drag_Operations#dragfeedback">an exception for canvas elements</a>. Firefox seems particularly strict about this requirement too, as I tried positioning an element offscreen in a negative position, setting its visibility to hidden, setting the display to none, and even placing the element in an offscreen iframe, <b>anything</b> to prevent having to actually flash the element in some random portion of the screen before dragging it. It seems to me that this method exists for the purpose of showing something <b>different</b>, and thus it&#8217;s a bit unreasonable to expect it to already be not only in the document, but visible as well. My request here is simple: that it should simply work the way it does in Safari.</p>
<h2>Conclusion</h2>
<p>Drag and drop is an incredibly important part of the way we interact with computers, which is why it is so crucial that we get it right from the beginning. I really hope my concerns are heard and that we can come up with some good solutions to the initial problems I faced with this young API, so that we can avoid the windows of incompatibility that plagued the last updates to HTML. In the meanwhile, I&#8217;ve filed a bunch of bugs and documented my current experiences <a href = "http://www.alertdebugging.com/drag-and-drop-bugs/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.alertdebugging.com/2009/08/16/on-html-5-drag-and-drop/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
	</channel>
</rss>
