Why Dont I Have an Upload Option in Dropbox Preview and Remove Html Css
I work on an RSS reader app called Readerrr (editor's note: link removed as site seems dead). I wanted to enrich the feed import experience by making allowing for drag and driblet file upload alongside the traditional file input. Sometimes elevate and drop is a more than comfortable style to select a file, isn't information technology?
View Demo
Markup
This markup doesn't have annihilation specifically to do with drag and driblet. It'southward just a normal, functional<form>
, albeit with some extra HTML elements for potential states.
<form course="box" method="mail" action="" enctype="multipart/course-information"> <div class="box__input"> <input class="box__file" blazon="file" proper noun="files[]" id="file" information-multiple-caption="{count} files selected" multiple /> <characterization for="file"><strong>Choose a file</strong><span class="box__dragndrop"> or elevate information technology hither</span>.</label> <push class="box__button" type="submit">Upload</push> </div> <div course="box__uploading">Uploading…</div> <div grade="box__success">Done!</div> <div class="box__error">Error! <span></bridge>.</div> </form>
We'll hide those states until we need them:
.box__dragndrop, .box__uploading, .box__success, .box__error { display: none; }
A footling caption:
- Regarding states:
.box__uploading
element will be visible during the Ajax process of file upload (and the others will however be hidden). And so.box__success
or.box__error
will exist shown depending on what happens. -
input[type="file"]
andlabel
are the functional parts of the form. I wrote about styling these together in my mail about customizing file inputs. In that post I likewise described the purpose of[information-multiple-caption]
attribute. The input and label also serve as an alternative for selecting files in the standard way (or the only way if drag and drib isn't supported). -
.box__dragndrop
will be shown if a browser supports elevate and drop file upload functionality.
Characteristic detection
We can't 100% rely on browsers supporting drag and drop. We should provide a fallback solution. And then: feature detection. Elevate & drop file upload relies on a number of different JavaScript API's, so we'll demand to cheque on all of them.
First, drag & drop events themselves. Modernizr is a library you tin can trust all about characteristic detection. This examination is from there:
var div = document.createElement('div'); return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)
Side by side we demand to check the FormData interface, which is for forming a programmatic object of the selected file(s) so they can be sent to the server via Ajax:
return 'FormData' in window;
Last, we need the DataTransfer object. This i is a bit tricky considering there is no bullet-proof style to detect the availability of the object before user'due south first interaction with the drag & driblet interface. Not all browsers expose the object.
Ideally we'd similar to avoid UX like…
- "Drag and drop files here!"
- [User drags and drops files]
- "Oops just kidding drag and drop isn't supported."
The trick here is to check the availability of FileReader API correct when the document loads. The thought behind this is that browsers that support FileReader
back up DataTransfer
too:
'FileReader' in window
Combining the code in a higher place into self-invoking bearding function…
var isAdvancedUpload = function() { var div = certificate.createElement('div'); return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window; }();
… will enable us to brand an effective feature back up detection:
if (isAdvancedUpload) { // ... }
With this working feature detection, at present nosotros can let the users know they can elevate & drop their files into our form (or not). We can mode the form by adding a course to it in the case of support:
var $form = $('.box'); if (isAdvancedUpload) { $form.addClass('has-advanced-upload'); }
.box.has-advanced-upload { groundwork-colour: white; outline: 2px dashed black; outline-offset: -10px; } .box.has-advanced-upload .box__dragndrop { display: inline; }
No problems at all if drag & drop file upload is not supported. Wsers volition be able to upload files via adept ol' input[blazon="file"]
!
Note on browser support: Microsoft Edge has a bug which stops drag and drop from working. Information technology sounds similar they are enlightened of it and hope to set up it. (Update: link to bug removed as the link stopped working. Now that Border is Chromium, presumably, it'due south not a trouble anymore.)
Drag 'due north' Drib
Here we go, here'due south the expert stuff.
This part deals with calculation and removing classes to the grade on the different states like when the user is dragging a file over the form. Then, catching those files when they are dropped.
if (isAdvancedUpload) { var droppedFiles = false; $class.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) { due east.preventDefault(); due east.stopPropagation(); }) .on('dragover dragenter', office() { $form.addClass('is-dragover'); }) .on('dragleave dragend driblet', function() { $course.removeClass('is-dragover'); }) .on('drop', function(e) { droppedFiles = eastward.originalEvent.dataTransfer.files; }); }
-
e.preventDefault()
anddue east.stopPropagation()
prevent any unwanted behaviors for the assigned events across browsers. -
e.originalEvent.dataTransfer.files
returns the listing of files that were dropped. Soon you will run into how to employ the information for sending these files to the server.
Adding and removing .is-dragover
when necessary enables united states of america to visually betoken when it is safe for a user to drib the files:
.box.is-dragover { groundwork-color: greyness; }
Selecting Files In a Traditional Mode
Sometimes dragging & dropping files is not very comfortable manner for selecting files for upload. Especially when a user is in front of a small screen size computer. Therefore it would exist nice to let users choose the method they prefer. The file input and label are here to allow this. Styling them both in the style I've described allows us to keep the UI consistant:
Ajax Upload
There is no cross-browser mode to upload dragged & dropped files without Ajax. Some browsers (IE and Firefox) do non allow setting the value of a file input, which and so could be submitted to server in a usual way.
This won't piece of work:
$form.detect('input[type="file"]').prop('files', droppedFiles);
Instead, we'll use Ajax when the form is submitted:
$form.on('submit', function(e) { if ($form.hasClass('is-uploading')) return imitation; $grade.addClass('is-uploading').removeClass('is-error'); if (isAdvancedUpload) { // ajax for modern browsers } else { // ajax for legacy browsers } });
The .is-uploading
grade does double duty: it prevents the form from beingness submitted repeatedly (return fake
) and helps to indicate to a user that the submission is in progress:
.box.is-uploading .box__input { visibility: none; } .box.is-uploading .box__uploading { display: block; }
Ajax for modern browsers
If this was a form without a file upload, we wouldn't need to have two different Ajax techniques. Unfortunately, file uploading via XMLHttpRequest
on IE ix and beneath is not supported.
To distinguish which Ajax method volition work, we tin can use our existing isAdvancedUpload
examination, because the browsers which back up the stuff I wrote before, also support file uploading via XMLHttpRequest. Here's lawmaking that works on IE x+:
if (isAdvancedUpload) { eastward.preventDefault(); var ajaxData = new FormData($class.get(0)); if (droppedFiles) { $.each( droppedFiles, function(i, file) { ajaxData.append( $input.attr('name'), file ); }); } $.ajax({ url: $form.attr('activity'), type: $form.attr('method'), information: ajaxData, dataType: 'json', cache: fake, contentType: false, processData: false, complete: function() { $form.removeClass('is-uploading'); }, success: role(information) { $grade.addClass( data.success == truthful ? 'is-success' : 'is-error' ); if (!information.success) $errorMsg.text(information.error); }, error: role() { // Log the error, testify an alert, whatever works for y'all } }); }
-
FormData($form.get(0))
collects data from all the form inputs - The
$.each()
loop runs through the dragged & dropped files.ajaxData.append()
adds them to the data stack which volition be submitted via Ajax -
data.success
anddata.fault
are a JSON format reply which will be returned from the server. Here's what that would be like in PHP:
<?php // ... dice(json_encode([ 'success'=> $is_success, 'fault'=> $error_msg])); ?>
Ajax for legacy browsers
This is essentially for IE 9-. Nosotros do not demand to collect the dragged & dropped files because in this case (isAdvancedUpload = simulated
), the browser does non support elevate & drop file upload and the class relies only on the input[type="file"]
.
Strangely enough, targeting the form on a dynamically inserted iframe does the trick:
if (isAdvancedUpload) { // ... } else { var iframeName = 'uploadiframe' + new Date().getTime(); $iframe = $('<iframe name="' + iframeName + '" mode="display: none;"></iframe>'); $('trunk').append($iframe); $form.attr('target', iframeName); $iframe.one('load', function() { var data = JSON.parse($iframe.contents().observe('body' ).text()); $form .removeClass('is-uploading') .addClass(data.success == true ? 'is-success' : 'is-fault') .removeAttr('target'); if (!information.success) $errorMsg.text(information.error); $form.removeAttr('target'); $iframe.remove(); }); }
Automatic Submission
If yous have a simple form with just a drag & drib area or file input, it may exist a user convenience to avert requiring them to press the button. Instead, yous can automatically submit the course on file drop/select by triggering the submit
event:
// ... .on('drib', role(east) { // when drag & drop is supported droppedFiles = east.originalEvent.dataTransfer.files; $class.trigger('submit'); }); // ... $input.on('change', part(east) { // when drag & drib is NOT supported $form.trigger('submit'); });
If drag & driblet area is visually well-designed (it's obvious to the user what to do), you might consider hiding the submit push button (less UI can exist skillful). Simply be careful when hiding a control like that. The button should be visible and functional if for some reason JavaScript is not available (progressive enhancement!). Calculation a .no-js
grade proper name to and removing it with JavaScript will practice the play a joke on:
<html class="no-js"> <head> <!-- remove this if you apply Modernizr --> <script>(office(e,t,n){var r=e.querySelectorAll("html")[0];r.className=r.className.replace(/(^|\south)no-js(\southward|$)/,"$1js$2")})(certificate,window,0);</script> </head> </html>
.box__button { display: none; } .no-js .box__button { brandish: block; }
Displaying the Selected Files
If you lot're non going to do auto-submission there should exist an indication to the user if they have selected files successfully:
var $input = $form.find('input[type="file"]'), $label = $form.observe('label'), showFiles = function(files) { $label.text(files.length > ane ? ($input.attr('data-multiple-explanation') || '').replace( '{count}', files.length ) : files[ 0 ].name); }; // ... .on('drop', part(east) { droppedFiles = e.originalEvent.dataTransfer.files; // the files that were dropped showFiles( droppedFiles ); }); //... $input.on('modify', function(e) { showFiles(e.target.files); });
When JavaScript Is Not Available
Progressive enhancement is about the thought that a user should be able to complete the principal tasks on a website no affair what. File uploading is no exception. If for some reason JavaScript is non available, the interface volition wait similar this:
The folio volition refresh on form submission. Our JavaScript for indicating the result of submission is useless. That means we have to rely on server-side solution. Hither's how it looks and works in the demo page:
<?php $upload_success = cypher; $upload_error = ''; if (!empty($_FILES['files'])) { /* the code for file upload; $upload_success – becomes "true" or "fake" if upload was unsuccessful; $upload_error – an error message of if upload was unsuccessful; */ } ?>
And some adjustments for the markup:
<form grade="box" method="post" action="" enctype="multipart/form-data"> <?php if ($upload_success === zippo): ?> <div grade="box__input"> <!-- ... --> </div> <?php endif; ?> <!-- ... --> <div class="box__success"<?php if( $upload_success === true ): ?> fashion="display: cake;"<?php endif; ?>>Done!</div> <div class="box__error"<?php if( $upload_success === false ): ?> style="display: cake;"<?php endif; ?>>Error! <span><?=$upload_error?></span>.</div> </form>
That's information technology! This already-long article could have been even longer, merely I think this volition get you going with a responsible drag and driblet file upload feature on your ain projects.
Cheque out the demo for more (view source to come across the no-jQuery-dependency JavaScript):
View Demo
Source: https://css-tricks.com/drag-and-drop-file-uploading/
0 Response to "Why Dont I Have an Upload Option in Dropbox Preview and Remove Html Css"
ارسال یک نظر