Displaying how the HTML5 Drag and Drop API can be used to control what elements can be dragged and where they can be dropped.
For additional information, please see my corresponding article on SitePoint
A Pen by Simon Codrington
<article class="page"> | |
<article class="main"> | |
<h1>Native Drag and Drop - the effectAllowed and the DropEffect properties</h1> | |
<h3>Setting the correct effects will tell the API what is allowed to be dragged and to where</h3> | |
<p>Only draggable items that match the same effect as the drop zone will be allowed. This uses only the native HTML5 API to reject non applicable drags</p> | |
<article class="drop-effect cf"> | |
<div class="container"> | |
<p>Setting the effectAllowed tells the browser what is allowed with this draggable item. It also determines which cursor will be used when the draggable is hovered over a drop zone</p> | |
<div class="drag-zone cf"> | |
<div class="drag-item"> | |
<h4 class="clear">Copy</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="copy" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">Link</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="link" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">Move</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="move" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">All</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="all" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">None</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="none" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">copyLink</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="copyLink" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">linkMove</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="linkMove" /> | |
</div> | |
<div class="drag-item"> | |
<h4 class="clear">copyMove</h4> | |
<img draggable="true" src="http://tinyurl.com/pb4w3ew" class="drag" data-effect-allowed="copyMove" /> | |
</div> | |
</div> | |
</div> | |
<div class="container"> | |
<h3>Drag the image above in the various containers</h3> | |
<p>Depending on which item you drag, you may or may not be able to drop</p> | |
<div class="drop-zone cf"> | |
<div class="drop-item"> | |
<h4 class="clear">Copy</h4> | |
<p>I accept any element that specifies it will 'copy'</p> | |
<div class="drop" data-drop-effect="copy"></div> | |
</div> | |
<div class="drop-item"> | |
<h4 class="clear">Link</h4> | |
<p>I accept any element that specifies it will 'link'</p> | |
<div class="drop" data-drop-effect="link"></div> | |
</div> | |
<div class="drop-item"> | |
<h4 class="clear">Move</h4> | |
<p>I accept any element that specifies it will 'move'</p> | |
<div class="drop" data-drop-effect="move"></div> | |
</div> | |
<div class="drop-item"> | |
<h4 class="clear">None</h4> | |
<p>I wont accept anything at all. Nothing</p> | |
<div class="drop" data-drop-effect="none"></div> | |
</div> | |
</div> | |
<div class="reset-button">Reset drag and drop</div> | |
</div> | |
</article> | |
</article> | |
</article> |
Displaying how the HTML5 Drag and Drop API can be used to control what elements can be dragged and where they can be dropped.
For additional information, please see my corresponding article on SitePoint
A Pen by Simon Codrington
jQuery(document).ready(function($) { | |
var drag_items = $('.drop-effect .drag'); | |
var drop_items = $('.drop-effect').find('.drop'); | |
//sets up the drag and drop event listeners | |
function setUpEventListeners() { | |
drag_items.each(function() { | |
var thisDrag = $(this); | |
thisDrag[0].addEventListener('dragstart', dragStart); | |
thisDrag[0].addEventListener('drag', drag); | |
thisDrag[0].addEventListener('dragend', dragEnd); | |
}); | |
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(); | |
var dragItem; | |
//called as soon as the draggable starts being dragged | |
//used to set up data and options | |
function dragStart(event) { | |
drag = event.target; | |
dragItem = event.target; | |
//set the effectAllowed for the drag item | |
event.dataTransfer.effectAllowed = $(this).attr('data-effect-allowed'); | |
var imageSrc = $(dragItem).prop('src'); | |
var imageHTML = $(dragItem).prop('outerHTML'); | |
//check for IE (it supports only 'text' or 'URL') | |
try { | |
event.dataTransfer.setData('text/uri-list', imageSrc); | |
event.dataTransfer.setData('text/html', imageHTML); | |
} catch (e) { | |
event.dataTransfer.setData('text', imageSrc); | |
} | |
$(drag).addClass('drag-active'); | |
} | |
//called as the draggable enters a droppable | |
//needs to return false to make droppable area valid | |
function dragEnter(event) { | |
var drop = this; | |
//set the drop effect for this zone | |
event.dataTransfer.dropEffect = $(this).attr('data-drop-effect'); | |
$(drop).addClass('drop-active'); | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
//called continually while the draggable is over a droppable | |
//needs to return false to make droppable area valid | |
function dragOver(event) { | |
var drop = this; | |
//set the drop effect for this zone | |
event.dataTransfer.dropEffect = $(this).attr('data-drop-effect'); | |
$(drop).addClass('drop-active'); | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
//called when the draggable was inside a droppable but then left | |
function dragLeave(event) { | |
var drop = this; | |
$(drop).removeClass('drop-active'); | |
} | |
//called continually as the draggable is dragged | |
function drag(event) {} | |
//called when the draggable has been released (either on droppable or not) | |
//may be called on invalid or valid drop | |
function dragEnd(event) { | |
var drag = this; | |
$(drag).removeClass('drag-active'); | |
} | |
//called when draggable is dropped on droppable | |
//final process, used to copy data or update UI on successful drop | |
function drop(event) { | |
drop = this; | |
$(drop).removeClass('drop-active'); | |
$(drop).addClass('correct'); | |
var dataList, dataHTML, dataText; | |
//collect our data (based on what browser support we have) | |
try { | |
dataList = event.dataTransfer.getData('text/uri-list'); | |
dataHTML = event.dataTransfer.getData('text/html'); | |
} catch (e) {; | |
dataText = event.dataTransfer.getData('text'); | |
} | |
//we have access to the HTML | |
if (dataHTML) { | |
$(drop).empty(); | |
$(drop).prepend(dataHTML); | |
} | |
//only have access to text (old browsers + IE) | |
else { | |
$(drop).empty(); | |
$(drop).prepend($(dragItem).clone()); | |
} | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
//Reset the drop containers | |
$('.reset-button').on('click', function() { | |
$('.drop-zone').find('img').remove(); | |
$('.drop-zone').find('.drop').removeClass('correct'); | |
}); | |
}); |
<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; | |
} | |
.clear { | |
clear: both; | |
} | |
.page { | |
max-width: 960px; | |
margin: 0px auto; | |
} | |
.drop-effect .container { | |
width: 100%; | |
float: left; | |
margin: 0% 0% 5% 0%; | |
} | |
.reset-button { | |
background: #eee; | |
border: solid 1px #ccc; | |
padding: 12px 15px; | |
display: inline-block; | |
cursor: pointer; | |
margin-top: 25px; | |
} | |
/*universal*/ | |
.drop-effect .drag-zone, | |
.drop-effect .drop-zone { | |
width: 100%; | |
background: #eee; | |
border: solid 1px #ccc; | |
padding: 15px 0px 15px 15px; | |
} | |
.drop-effect .drag-item, | |
.drop-effect .drop-item { | |
width: 25%; | |
float: left; | |
text-align: center; | |
overflow: hidden; | |
} | |
.drop-effect .drag-item .drag, | |
.drop-effect .drop-item .drop { | |
border: solid 1px #ccc; | |
background: #DDD; | |
cursor: -webkit-grab; | |
cursor: -moz-grab; | |
border: solid 1px transparent; | |
height: 150px; | |
width: 150px; | |
display: inline-block; | |
-webkit-transition: all 300ms ease-in; | |
-moz-transition: all 300ms ease-in; | |
-o-transition: all 300ms ease-in; | |
transition: all 300ms ease-in; | |
} | |
/*drag related styles*/ | |
.drop-effect .drag-zone {} | |
.drop-effect .drag-zone .drag {} | |
.drop-effect .drag-zone .drag.drag-active { | |
border: solid 1px #333; | |
opacity: 0.7; | |
} | |
/*drop related styles*/ | |
.drop-effect .drop-zone {} | |
.drop-effect .drop-zone .drop {} | |
.drop-effect .drop-zone .drop.drop-active { | |
border: solid 1px #AAA; | |
} | |
.drop-effect .drop-zone .drop.correct { | |
border: solid 1px #32ce74; | |
} | |
.drop-effect .drop-zone .drop img { | |
max-width: 100%; | |
height: auto; | |
} |
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,300" rel="stylesheet" /> |