Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonrcodrington/8f24bcdbcec655f815cb to your computer and use it in GitHub Desktop.
Save simonrcodrington/8f24bcdbcec655f815cb to your computer and use it in GitHub Desktop.
Native Drag & Drop - Dragging files directly onto the website
<article class="page">
<article class="main">
<h1>Native Drag and Drop - Dragging files directly onto the website</h1>
<p>Using the native HTML5 D&D API we can build drop zones that take in dragged elements. These elements can be <strong>files directly from your computer </strong>or <strong>from another tab or window where an item is draggable (image etc)</strong></p>
<article class="dnd-onto-website cf">
<h3>Drag your images into the container below</h3>
<p>Any draggable elements (images, link tags, selected text) can be dropped here, but <strong>only dragged images from external sites / uploaded images will be displayed</strong></p>
<p>Some images are wrapped around an anchor tag, these won't work as the API will consider the drop to be a 'link' and not an 'image'</p>
<h4>Notes</h4>
<ul>
<li>Most images online will be wrapped around a &lt;a&GT; tag. When you drag and drop these it looks like you're dragging the image but actually you're dragging the link (which won't work below). This is a limitation of the API </li>
<li>There is no concept of what an "image" is to the API. As such we need to check to see if the URI supplied has a filetype in it. We check the URL to see if it contains the '.jpg', '.jpeg', '.png' ,'.bmp', or '.gif' extension</li>
<li>Some CND's use strange URL patterns that don't end in a specific file type. These won't work as the API won't be able to tell what it is.</li>
</ul>
<h4 class="ie-message">You are using Internet Explorer. IE only supports the 'text' and 'URL' transfer types so your experience may be limited. Also IE9 and below have no support for dragging images from your desktop to the page</h4>
<div class="container-drop drop"></div>
<div class="message-container"></div>
</article>
</article>
</article>

Native Drag & Drop - Dragging files directly onto the website

Showcases how to use the native API to handle drag and drop elements from external sources (other tabs, other windows, other browsers) and also locally from your machine (via the uploading / writing functionality)

A Pen by Simon Codrington on CodePen.

License.

jQuery(document).ready(function($) {
var drop_items = $('.dnd-onto-website').find('.drop');
//get user agent, test for IE, if show display warning
var userAgent = window.navigator.userAgent;
if (userAgent.indexOf('MSIE') != -1) {
$('.ie-message').show();
}
//set up event listeners for the drop item
function setUpEventListeners() {
drop_items.each(function() {
var thisDrop = $(this);
thisDrop[0].addEventListener('dragenter', dragEnter);
thisDrop[0].addEventListener('dragover', dragOver);
thisDrop[0].addEventListener('dragleave', dragLeave);
thisDrop[0].addEventListener('drop', drop);
});
}
setUpEventListeners();
//called as the draggable enters a droppable
//needs to return false to make droppable area valid
function dragEnter(event) {
var drop = this;
$(drop).addClass('drop-active');
event.preventDefault();
}
//called continually while the draggable is over a droppable
//needs to return false to make droppable area valid
function dragOver(event) {
var drop = this;
$(drop).addClass('drop-active');
event.preventDefault();
}
//called when the draggable was inside a droppable but then left
function dragLeave(event) {
var drop = this;
$(drop).removeClass('drop-active');
}
//called when draggable is dropped on droppable
//final process, used to copy data or update UI on successful drop
function drop(event) {
event.stopPropagation();
event.preventDefault();
//main drop container
drop = $(this);
//remove class from drop zone
drop.removeClass('drop-active');
var dataList, dataText, dataType;
//get the URL of elements being dragged here
try {
dataValue = event.dataTransfer.getData('text/uri-list');
dataType = 'text/uri-list';
} catch (e) {
dataValue = event.dataTransfer.getData('URL');
dataType = 'URL';
}
//if we have a URL passed
if (dataValue) {
var messageContainer = $('.message-container');
messageContainer.empty();
messageContainer.addClass('active');
messageContainer.append('<p>Your dropped element from an external window. It has this data<p>');
drop.empty();
//if we have access to the URI list
if (dataType == 'text/uri-list') {
messageContainer.append('<ul><li><strong>Text/URI-List: </strong>' + dataValue + '</li></ul>');
}
//only have access to the older URL value (IE)
if (dataType == 'URL') {
messageContainer.append('You must be on Internet Explorer, it only supports \'\text\'\ or \'\URL\'\ types');
messageContainer.append('<ul><li><strong>URL: </strong>' + dataValue + '</li></ul>');
}
//determine if our URL is an image
imageDropped = false;
var imageExtensions = ['.jpg', '.jpeg', '.png', '.bmp', '.gif'];
for (i = 0; i < imageExtensions.length; i++) {
if (dataValue.indexOf(imageExtensions[i]) !== -1) {
//create our image from the URL of the drop
var image = '<img src="' + dataValue + '">';
drop.append(image);
imageDropped = true;
break;
}
}
//if we dropped an image, notify user
if (imageDropped == true) {
messageContainer.append('<p><strong>Successfully dropped from an online source</strong></p>');
} else {
messageContainer.append('<p><strong>Couldn\'\t determine what was dropped, it didn\'\t match expected image formats</strong></p>');
}
}
//if we have a list of files
else {
//check if any files were dropped (from the desktop etc)
var dataFiles = event.dataTransfer.files;
var dataOutput = [];
if (dataFiles) {
var messageContainer = $('.message-container');
messageContainer.empty();
messageContainer.addClass('active');
messageContainer.append('<p>You dropped an item / items from your desktop. Here is its data<p>');
drop.empty();
for (i = 0; i < dataFiles.length; i++) {
var dataItem = dataFiles[i];
var dataType = dataFiles[i].type;
//check if this is an image
if (dataType.match('image.*')) {
var dataLastModified = dataFiles[i].lastModified;
var dataLastModifiedDate = dataFiles[i].lastModifiedDate;
var dataName = dataFiles[i].name;
var dataSize = dataFiles[i].size;
var dataType = dataFiles[i].type;
messageContainer.append('<ul>');
messageContainer.append('<li><strong>Name</strong>:' + dataName + '</li>');
messageContainer.append('<li><strong>Data Size</strong>:' + dataSize + '</li>');
messageContainer.append('<li><strong>Data Type</strong>:' + dataType + '</li>');
messageContainer.append('</ul>');
//read into memory
var reader = new FileReader();
//when our image is loaded
reader.onload = (function(theFile) {
return function(e) {
var url = e.target.result;
drop.append('<img src="' + url + '" title="' + dataName + '"/>');
messageContainer.append('<p><strong>Successfully dropped an image from your desktop</strong></p>');
};
})(dataItem);
//load element
reader.readAsDataURL(dataItem);
} else {
messageContainer.append('<p><strong>It looks like you have not dropped an image. Only images are allowed </strong></p>');
}
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
/*universal styling*/
html{
font-size: 62.5%;
}
body{
font-family: 'Open Sans', sans-serif;
font-weight: 400;
font-style: normal;
font-size: 1.5rem;
line-height: 1.5rem;
}
h1,h2,h3,h4,h5,h6{
font-weight: 600;
line-height: 150%;
margin: 1.5rem 0rem;
}
h1{
font-size: 3.8rem;
margin: 2.85rem 0rem;
}
h2{
font-size: 2.8rem;
margin: 2.1rem 0rem;
}
h3{
font-size: 2.1rem;
margin: 1.57rem 0rem;
}
h4{
font-size: 1.8rem;
}
h5{
font-size: 1.3rem;
}
h6{
font-size: 1.0rem;
}
p{
margin: 0rem 0rem 2.4rem 0rem;
line-height: 150%;
}
ul,
ol{
margin-left: 25px;
margin-bottom: 15px;
line-height: 150%;
}
/*clearfixes*/
.cf:before,
.cf:after {
content: " ";
display: table;
}
.cf:after {
clear: both;
}
*,*:before,*:after{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, div{
margin: 1.5rem 0rem;
}
div {
margin: 0rem;
}
.page{
max-width: 1200px;
margin: 0px auto;
}
/*drag onto website specific styles*/
.dnd-onto-website .container{
width: 48%;
float: left;
margin: 0% 1% 2% 1%;
}
.dnd-onto-website .container-drop{
min-height: 300px;
width: 50%;
background: #eee;
border: solid 2px #ddd;
padding: 15px;
-webkit-transition: all 300ms ease-in;
-moz-transition: all 300ms ease-in;
-o-transition: all 300ms ease-in;
transition: all 300ms ease-in;
position: relative;
float: left;
}
.dnd-onto-website .container-drop.drop-active{
border: dashed 2px #ccc;
background: #efefef;
}
.dnd-onto-website .container-drop:before{
content: '\f019';
position: absolute;
top: 50%;
left: 50%;
top: calc(50% - 40px);
left: calc(50% - 40px);
font-family: fontawesome;
width: 80px;
height: 80px;
font-size: 80px;
line-height: 80px;
color: #ccc;
-webkit-transition: all 300ms ease-in;
-moz-transition: all 300ms ease-in;
-o-transition: all 300ms ease-in;
transition: all 300ms ease-in;
z-index: 1;
}
.dnd-onto-website .container-drop.drop-active:before{
color: #aaa;
}
.dnd-onto-website .container-drop img{
max-width: 100%;
height: auto;
position: relative;
z-index: 2;
}
.dnd-onto-website .message-container{
width: 47.5%;
margin-left: 2.5%;
float: left;
word-break: break-all;
}
.dnd-onto-website .message-container.active{
border: solid 1px #ccc;
padding: 15px;
}
.ie-message{
display: none;
padding: 15px;
background: #e74c3c;
color: #fff;
border: dashed 2px #c0392b;
margin-bottom: 15px;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,300" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment