A user account is required in order to edit this wiki, but we've had to disable public user registrations due to spam.

To request an account, ask an autoconfirmed user on Chat (such as one of these permanent autoconfirmed members).

Difference between revisions of "Drag'n'Drop Uploads"

From WHATWG Wiki
Jump to navigation Jump to search
(New page: === The problem === Web applications cannot accept files from user's machine as easily and intuitively as native OS applications - users can't drop images from desktop right into documents...)
 
Line 29: Line 29:


=== The process ===
=== The process ===
==== Finding related <input type=file> ====
These steps are supposed to allow dropping files directly into <code>&lt;input></code>, or into a designated drop zone. As a fallback a <code>&lt;form></code> can be assumed to be a drop zone.


When user drops file(s) into the document:
When user drops file(s) into the document:


# Take element on which file(s) were dropped (that's target of <code>mouseup</code> event)
# Take element on which file(s) were dropped (''drop target'') - usually it will be target of <code>mouseup</code> event.
# If the element is <code>&lt;input type=file></code> '''proceed to the next section.'''
# If the element does not have <code>dropped-files</code> attribute, check its parent. Continue checking ancestors until the attribute is found or there are no more parent elements.
# If the element does not have <code>dropped-files</code> attribute, check its parent. Continue checking ancestors until the attribute is found or there are no more parent elements.
# If no ancestor with <code>dropped-files</code> was found, ignore dropped files or perform browser's default action and abort these steps.
# If element with <code>dropped-files</code> attribute was found:
# Find element referenced by <code>dropped-files</code> attribute and verify it's <code>&lt;input type=file></code>. If this element can't be found or is not a file input, ignore dropped files or perform browser's default action and abort these steps.
## Find element referenced by <code>dropped-files</code> attribute  
# Set value of <input> just as if files were chosen using regular method (including setting multiple files if <code>max</code> attribute permits)
## Verify that referenced element it's an <code>&lt;input type=file></code>
# ?? Fire <code>change</code> event (<code>formchange</code>? <code>filesdropped</code>?) [ on which element? <code>&lt;input></code> or drop target? how would one find where files were dropped? (Range object with position within related textarea/contentEditable would be useful) ]
## If above conditions are met '''proceed to the next section.'''
# ?? Should the form be submitted automatically? For example form could be submitted asynchronously unless script objects to it using <code>preventDefault/stopPropagation</code> of <code>filesdropped</code> event
## Otherwise ignore dropped files or perform browser's default action and abort these steps.
# Start again from the ''drop target''
# If the element is not <code>&lt;form></code>, check its parent. Continue checking ancestors until <code>&lt;form></code> is found or there are no more parent elements.
# If <code>&lt;form></code> is found:
## Find first <code>&lt;input type=file></code> that belongs to that form
## If element can be found, '''proceed to the next section.'''
# Otherwise ignore dropped files or perform browser's default action.
 
(this algorithm can be optimized to walk up the DOM tree only once)
 
==== The next section ====


# Synchronously fire <code>filesdropped</code> event on ''drop target''
# If <code>filesdropped</code> event was cancelled, ignore dropped files and abort these steps.
# Set value of <code>&lt;input></code> just as if files were chosen using regular method (including setting multiple files if <code>max</code> attribute permits) and fire <code>change</code> event on <code>&lt;input></code>.


=== Open Issues ===
=== Open Issues ===

Revision as of 20:04, 26 April 2007

The problem

Web applications cannot accept files from user's machine as easily and intuitively as native OS applications - users can't drop images from desktop right into documents edited in WYSIWYG editors, on-line file browsers, asset management interfaces of CMSes.

Although browsers could allow <input type=file> controls to accept dropped files, drop zone would have to be limited to small area occupied by the control. This is not how applications usually work - they don't have area exclusively for dropping files, but entire window or regular UI controls react to dropped files.

There's nothing inherently wrong with having <input type=file> with file browser, some users may even prefer this type of UI, but depending on type of application/user preference such UI may feel inefficient and unintuitive.


Use cases

  • Dropping image from local machine (desktop, file explorer/finder window, another application) into WYSIWYG (contentEditable) editor to have image uploaded to server and inserted into edited document right under cursor - just like you can with office suites.
  • Dropping image into textarea that uses BBcode or Wiki syntax to have image uploaded and appropriate image embedding syntax automatically inserted.
  • Adding attachments in a webmail
  • Web-based file browser/asset management interface
  • Drag'n'drop customization of images in page templates, forum avatars, etc.


Proposed solution

The basic concept

A universal IDREF attribute that would connect particular element in document with a <input type=file> control.

<input type=file id=uploader>
<div dropped-files=uploader>drop your files here!</div>

In the above example, when file is dropped onto

, browser would "redirect" the file to <input> element. <input> can use max attribute to allow multiple files to be dropped at once.

Note: alternative approach would be to use DOM event triggered when a file is dropped. That could be much more flexible, but probably would require giving JS method for passing file information from event object to chosen <input> element - with complexity of DOM events and inherent insecurity of JS prototypes it could be too difficult to implement securely. With IDREF browser can keep full control and have process of setting <input type=file> hardcoded.

The process

Finding related <input type=file>

These steps are supposed to allow dropping files directly into <input>, or into a designated drop zone. As a fallback a <form> can be assumed to be a drop zone.

When user drops file(s) into the document:

  1. Take element on which file(s) were dropped (drop target) - usually it will be target of mouseup event.
  2. If the element is <input type=file> proceed to the next section.
  3. If the element does not have dropped-files attribute, check its parent. Continue checking ancestors until the attribute is found or there are no more parent elements.
  4. If element with dropped-files attribute was found:
    1. Find element referenced by dropped-files attribute
    2. Verify that referenced element it's an <input type=file>
    3. If above conditions are met proceed to the next section.
    4. Otherwise ignore dropped files or perform browser's default action and abort these steps.
  5. Start again from the drop target
  6. If the element is not <form>, check its parent. Continue checking ancestors until <form> is found or there are no more parent elements.
  7. If <form> is found:
    1. Find first <input type=file> that belongs to that form
    2. If element can be found, proceed to the next section.
  8. Otherwise ignore dropped files or perform browser's default action.

(this algorithm can be optimized to walk up the DOM tree only once)

The next section

  1. Synchronously fire filesdropped event on drop target
  2. If filesdropped event was cancelled, ignore dropped files and abort these steps.
  3. Set value of <input> just as if files were chosen using regular method (including setting multiple files if max attribute permits) and fire change event on <input>.

Open Issues

What's the best way to get information about dropped files and where event has occurred? It will be needed for inserting markup into WYSIWYG/textarea.

How would script mark areas where files can't be dropped (temporarily/conditionally) allowing browser to dynamically change cursor? Is script fiddling with CSS cursor property (and clearing value of <input>) enough?

Since the solution requires form and <input> element, backwards compatibility can be maintained. The problem is script may rely on files being set via drag'n'drop and may not act properly when user uses file control directly.

Many elements could reference single <input>. Is this desirable? Disallowing that might help backwards compatibility (it would be more likely that there were separate <form>s pre-filled with necessary data), OTOH it would be easier for authors to have single uploader for multiple items on the page.

Would it be possible to have previews of images and documents available prior upload? Import into <canvas> without upload?

Should the form be submitted asynchronously and automatically? It would allow browser to save user's time by uploading immediately and in the background. There would be possibility of uploading multiple files at the same time (alternatively they could be queued/batched).

If upload is async, script would have to receive information from the server once upload finishes (WYSIWYG editors would need to put placeholder in the document while file uploads and replace it with the real thing afterwards). Currently it can be hacked via <from replace=values> and hidden input element or <from target=hidden_iframe> and cross-frame scripts.