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...) |
|||
Line 29: | Line 29: | ||
=== 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>. | |||
=== 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
<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
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>
.
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.