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).

Drag'n'Drop Uploads: Difference between revisions

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...)
 
 
(5 intermediate revisions by 2 users not shown)
Line 19: Line 19:
=== The basic concept ===
=== The basic concept ===


A universal IDREF attribute that would connect particular element in document with a <code>&lt;input type=file></code> control.
A universal IDREF attribute that would connect particular element in document (''drop zone'') with a <code>&lt;input type=file></code> control.


  &lt;input type=file id=''uploader''>
  &lt;input type=file id=''uploader''>
  &lt;div dropped-files=''uploader''>drop your files here!&lt;/div>
  &lt;div dropped-files=''uploader''>drop your files here!&lt;/div>


In the above example, when file is dropped onto <div>, browser would "redirect" the file to <code>&lt;input></code> element. <code>&lt;input></code> can use <code>max</code> attribute to allow multiple files to be dropped at once.
In the above example, files is dropped into <code>&lt;div></code> would be "redirected" to the <code>&lt;input></code> element. <code>&lt;input></code> can use <code>max</code> 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 <code>&lt;input></code> 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 <code>&lt;input type=file></code> hardcoded.
Drop zone doesn't have to be &lt;div>:
 
&lt;textarea dropped-files=''uploader''>write post and drop images to have [img]url[/img] added automagically!&lt;/textarea>
 
Algorithm also allows dropping files directly into <code>&lt;input></code>, without requiring any additional code.
 
&lt;input type=file title="drop files here!">
 
Drop zones can be nested (deepest-nested takes precedence). For ease of implementation and compatibility with HTML4 documents, <code>&lt;form></code> can act as a drop zone (with least precedence).


=== 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>.
=== Security ===
Dropping is limited to one DOM tree (does not cross frames). Scripts still can't set value of &lt;input type=file>.
The only new risk is that script may know exactly when user has chosen a file and may start uploading it immediately (IIRC currently major browsers don't trigger <code>change</code> event on file controls).
Browsers which used to open files dropped into document area will probably have to ask user for confirmation when first file is dropped to prevent websites from stealing files from users unaware of the new feature.


=== Open Issues ===
=== 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 &lt;input>) enough?


Since the solution requires form and <code>&lt;input></code> 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.
==== Filesdropped Event ====
* It should reference relevant <code>&lt;input></code>
* Provide some information about dropped file(s) (file name, mime type, size?)
* If possible, provide information about exact place where event occurred (using <code>Range</code> object for WYSIWYG?)


Many elements could reference single <code>&lt;input></code>. Is this desirable? Disallowing that might help backwards compatibility (it would be more likely that there were separate &lt;form>s pre-filled with necessary data), OTOH it would be easier for authors to have single uploader for multiple items on the page.
==== Other issues ====
* 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 canceling <code>filesdropped</code> event enough?
* Since the solution requires form and <code>&lt;input></code> 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 <code>&lt;input></code>. Is this desirable? Disallowing that might help backwards compatibility (it would be more likely that authors prepare separate &lt;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 <code>&lt;canvas></code> 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 <code>&lt;from replace=values></code> and hidden input element or <code>&lt;from target=hidden_iframe></code> and cross-frame scripts.


Would it be possible to have previews of images and documents available prior upload? Import into <code>&lt;canvas></code> without upload?
== Related implementations ==


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).
IE supports [http://msdn2.microsoft.com/en-us/library/ms537658.aspx dataTransfer] object which can be used for handling drag'n'drop and clipboard copying of text and URLs. This interface could be reused+extended for files.


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 <code>&lt;from replace=values></code> and hidden input element or <code>&lt;from target=hidden_iframe></code> and cross-frame scripts.
[[Category:Proposals]]

Latest revision as of 12:09, 26 January 2011

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 (drop zone) with a <input type=file> control.

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

In the above example, files is dropped into <div> would be "redirected" to the <input> element. <input> can use max attribute to allow multiple files to be dropped at once.

Drop zone doesn't have to be <div>:

<textarea dropped-files=uploader>write post and drop images to have [img]url[/img] added automagically!</textarea> 

Algorithm also allows dropping files directly into <input>, without requiring any additional code.

<input type=file title="drop files here!">

Drop zones can be nested (deepest-nested takes precedence). For ease of implementation and compatibility with HTML4 documents, <form> can act as a drop zone (with least precedence).

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>.

Security

Dropping is limited to one DOM tree (does not cross frames). Scripts still can't set value of <input type=file>.

The only new risk is that script may know exactly when user has chosen a file and may start uploading it immediately (IIRC currently major browsers don't trigger change event on file controls).

Browsers which used to open files dropped into document area will probably have to ask user for confirmation when first file is dropped to prevent websites from stealing files from users unaware of the new feature.

Open Issues

Filesdropped Event

  • It should reference relevant <input>
  • Provide some information about dropped file(s) (file name, mime type, size?)
  • If possible, provide information about exact place where event occurred (using Range object for WYSIWYG?)

Other issues

  • 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 canceling filesdropped event 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 authors prepare 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.

Related implementations

IE supports dataTransfer object which can be used for handling drag'n'drop and clipboard copying of text and URLs. This interface could be reused+extended for files.