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
(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><input type=file></code> control. | A universal IDREF attribute that would connect particular element in document (''drop zone'') with a <code><input type=file></code> control. | ||
<input type=file id=''uploader''> | <input type=file id=''uploader''> | ||
<div dropped-files=''uploader''>drop your files here!</div> | <div dropped-files=''uploader''>drop your files here!</div> | ||
In the above example, | In the above example, files is dropped into <code><div></code> would be "redirected" to the <code><input></code> element. <code><input></code> can use <code>max</code> 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 <code><input></code>, 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, <code><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><input></code>, or into a designated drop zone. As a fallback a <code><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 ( | # 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><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 | # If element with <code>dropped-files</code> attribute was found: | ||
# Find element referenced by <code>dropped-files</code> attribute | ## Find element referenced by <code>dropped-files</code> attribute | ||
# | ## Verify that referenced element it's an <code><input type=file></code> | ||
# | ## If above conditions are met '''proceed to the next section.''' | ||
# | ## 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><form></code>, check its parent. Continue checking ancestors until <code><form></code> is found or there are no more parent elements. | |||
# If <code><form></code> is found: | |||
## Find first <code><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><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><input></code>. | |||
=== 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 <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 === | ||
==== Filesdropped Event ==== | |||
* It should reference relevant <code><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><input></code>. Is this desirable? Disallowing that might help backwards compatibility (it would be more likely that | ==== 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><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><input></code>. 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 <code><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><from replace=values></code> and hidden input element or <code><from target=hidden_iframe></code> and cross-frame scripts. | |||
== Related implementations == | |||
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. | |||
[[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
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:
- Take element on which file(s) were dropped (drop target) - usually it will be target of
mouseup
event. - If the element is
<input type=file>
proceed to the next section. - 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. - If element with
dropped-files
attribute was found:- Find element referenced by
dropped-files
attribute - Verify that referenced element it's an
<input type=file>
- If above conditions are met proceed to the next section.
- Otherwise ignore dropped files or perform browser's default action and abort these steps.
- Find element referenced by
- Start again from the drop target
- If the element is not
<form>
, check its parent. Continue checking ancestors until<form>
is found or there are no more parent elements. - If
<form>
is found:- Find first
<input type=file>
that belongs to that form - If element can be found, proceed to the next section.
- Find first
- 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
filesdropped
event on drop target - If
filesdropped
event was cancelled, ignore dropped files and abort these steps. - Set value of
<input>
just as if files were chosen using regular method (including setting multiple files ifmax
attribute permits) and firechange
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.