<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html lang='en' class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/trymedo/pen/iqCcp?limit=all&page=65&q=draggable" />
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css'>
<style class="cp-pen-styles">
.draggable {
background-color: #9F9;
border: #222 solid 1px;
cursor:move;
height: 35px;
text-align: center;
width: 100px;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
user-select: none;
}
.draggable.dragging {
opacity: 0.4;
}
.droptarget {
float: left;
background-color: #EFEFEF;
border: 3px dashed gray;
height: 200px;
width: 200px;
}
.spawnpoint {
width: 500px;
height: 250px;
padding: 10px;
}
.droptarget.landscape {
height: 100px;
width: 200px;
}
.droptarget.portrait {
height: 200px;
width: 100px;
}
.droptarget.landscape .draggable {
background-color: #0F0;
height: 100px;
width: 198px;
}
.droptarget.portrait .draggable {
background-color: #F00;
height: 198px;
width: 100px;
}
.droptarget.used {
border-color: #0F0;
}
.droptarget.selected {
border-color: #FF0;
}
.droptarget.locked {
border-color: #F00;
}</style></head><body>
<div class="spawnpoint droptarget multidrop">
<div class="draggable">Drag Item 1</div>
<div class="draggable">Drag Item 2</div>
<div class="draggable">Drag Item 3</div>
<div class="draggable">Drag Item 4</div>
</div>
<div class="droptarget portrait"></div>
<div class="droptarget portrait"></div>
<div class="droptarget portrait"></div>
<div class="droptarget portrait"></div>
<div class="droptarget landscape"></div>
<div class="droptarget landscape"></div>
<div class="droptarget landscape"></div>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script >/**
* DD_Controller Class
* @param {[type]} initObj [description]
*/
function DD_Controller( initObj ) {
// Public vars
this.allowMultidrop = initObj.allowMultidrop ? true : false;
this.allowSwapping = initObj.allowSwapping ? !!initObj.allowSwapping : false;
// Set defaults via initObj
this.onStartDrag = initObj.onStartDrag ? initObj.onStartDrag : voidFunc;
this.onStopDrag = initObj.onStopDrag ? initObj.onStopDrag : voidFunc;
this.onTargetOver = initObj.onTargetOver ? initObj.onTargetOver : voidFunc;
this.onTargetOut = initObj.onTargetOut ? initObj.onTargetOut : voidFunc;
this.onTargetDrop = initObj.onTargetDrop ? initObj.onTargetDrop : voidFunc;
// Class names and RegExp's for adding/removing/checking classes...
var used_class = "used";
var locked_class = "locked";
var selected_class = "selected";
var regx_used = new RegExp("\\b "+used_class+"\\b", "g");
var regx_locked = new RegExp("\\b "+locked_class+"\\b", "g");
var regx_selected = new RegExp("\\b "+selected_class+"\\b", "g");
// Assign dd variable to 'this' so we can use the
// reference later within our class methods
var dd = this;
var oDropTargets = [];
var oDropTarget = null;
var oDragItem = null;
var iClickOffsetX = 0;
var iClickOffsetY = 0;
var _onTargetOverCalled = false;
var _prevParent = null;
// default function for public events
function voidFunc(i,t){return false;}
function EventObject( initObj ){
// private variable for preventDefault() method
var _prevented = false;
// Copy the initObjects stuff across
for(prop in initObj){if (window.CP.shouldStopExecution(1)){break;}
this[prop] = initObj[prop];
}
window.CP.exitedLoop(1);
// Public prevent default method
this.preventDefault = function(){
_prevented = true;
}
this.defaultPrevented = function(){
return _prevented;
}
}
var _construct = function(){
_setupDragDrop();
}();
function _setupDragDrop(){
oDropTargets = [];
var oList = document.getElementsByTagName("div");
for(var i=0; i<oList.length; i++){if (window.CP.shouldStopExecution(2)){break;}
var o = oList[i];
if (o.className.match(/\bdroptarget\b/)){
oDropTargets[oDropTargets.length] = _getObjPos(o);
} else if (o.className.match(/\bdraggable\b/)){
_makeDraggable(o);
}
}
window.CP.exitedLoop(2);
}
function _makeDraggable(oBox){
// disable selectable
oBox.setAttribute("selectable","no");
if (navigator.platform == "iPad"){
oBox.ontouchstart = function(e){_touchStart(e)};
oBox.ontouchmove = function(e){_touchMove(e)};
oBox.ontouchend = function(e){_touchEnd(e)};
} else {
oBox.onmousemove = function(e){_dragMove(oBox,e)};
oBox.onmouseup = function(e){_dragStop(oBox,e)};
oBox.onmousedown = function(e){_dragStart(oBox,e); return false};
}
}
function _touchStart(e){
var oPos = _getObjPos(e.target);
iClickOffsetX = e.targetTouches[0].pageX - oPos.x;
iClickOffsetY = e.targetTouches[0].pageY - oPos.y;
_onStartDrag();
}
function _dragStart(o,e){
if(!e) var e = window.event;
oDragItem = o;
if (e.offsetX){
iClickOffsetX = e.offsetX;
iClickOffsetY = e.offsetY;
} else {
var oPos = _getObjPos(o);
iClickOffsetX = e.clientX - oPos.x;
iClickOffsetY = e.clientY - oPos.y;
}
if (o.setCapture){
// Retarget all mouse events to this element until the mouse button
// is released or document.releaseCapture() is called.
o.setCapture();
} else {
window.addEventListener ("mousemove", _dragMoveListener, true);
window.addEventListener ("mouseup", _dragStopListener, true);
}
_onStartDrag();
}
function _dragMoveListener(e){
_dragMove(oDragItem,e);
}
function _dragStopListener(e){
_dragStop(oDragItem,e);
}
function _dragMove(o,e){
if (oDragItem==null) return;
if(!e) var e = window.event;
var x = e.clientX + document.body.scrollLeft - document.body.clientLeft - iClickOffsetX;
var y = e.clientY + document.body.scrollTop - document.body.clientTop - iClickOffsetY;
_handleDragMove(x,y);
}
function _handleDragMove(x,y){
with(oDragItem.style){
zIndex = 1000;
position="absolute";
left=x;
top=y;
}
for (var i=0; i< oDropTargets.length; i++){if (window.CP.shouldStopExecution(3)){break;}
var oTarget = oDropTargets[i];
if (oTarget.x < (x+iClickOffsetX) && oTarget.y < (y+iClickOffsetY) && (oTarget.x + oTarget.w) > (x+iClickOffsetX) && (oTarget.y + oTarget.h) > (y+iClickOffsetY)){
if (oDropTarget!=null && oDropTarget != oTarget.o) _onTargetOut();
oDropTarget = oTarget.o;
_onTargetOver();
return;
}
}
window.CP.exitedLoop(3);
// if we drag it out, just call onTargetOut once...
// without setting oDropTarget to null, we get this method called
// every time the mousemove event is triggered.
if (oDropTarget){
_onTargetOut();
oDropTarget = null;
}
}
function _touchMove(e){
e.preventDefault();
var x = e.targetTouches[0].pageX - iClickOffsetX;
var y = e.targetTouches[0].pageY - iClickOffsetY;
oDragItem = e.targetTouches[0].target;
_handleDragMove(x,y);
}
function _dragStop(o,e){
if (o.releaseCapture){
o.releaseCapture();
} else if (oDragItem){
window.removeEventListener ("mousemove", _dragMoveListener, true);
window.removeEventListener ("mouseup", _dragStopListener, true);
}
_handleDragStop();
}
function _handleDragStop(){
if(oDragItem==null) return;
if(dd.allowMultidrop){
// console.log("Drop in ANY case");
if(oDragItem){
dropInto(oDragItem, oDropTarget);
}
} else if(dd.allowSwapping){
// console.log("Drop if empty, swap if not.");
// if the target is used, swap
if(oDropTarget && oDropTarget.className.match(regx_used)){
// Move targets current child into dragged items previous parent
dropInto(oDropTarget.children[0], _prevParent);
// Move dragged item into target
dropInto(oDragItem, oDropTarget, ' '+used_class);
} else {
dropInto(oDragItem, oDropTarget);
}
} else {
// console.log("Drop if oDropTarget is empty");
if(oDropTarget && !oDropTarget.className.match(regx_used)){
// Move dragged item into target
dropInto(oDragItem, oDropTarget);
} else {
dropInto(oDragItem, _prevParent);
}
}
if (oDropTarget){
_onTargetOut();
_onTargetDrop();
}
_onStopDrag();
}
function _touchEnd(e){
e.target.innerHTML = "TouchEnd";
_handleDragStop();
}
function _getObjPos(obj){
var x = 0;
var y = 0;
var o = obj;
var w = obj.offsetWidth;
var h = obj.offsetHeight;
if (obj.offsetParent) {
x = obj.offsetLeft
y = obj.offsetTop
while (obj = obj.offsetParent){if (window.CP.shouldStopExecution(4)){break;}
x += obj.offsetLeft;
y += obj.offsetTop;
}
window.CP.exitedLoop(4);
}
return {x:x, y:y, w:w, h:h, o:o};
}
// Editable 'Events'
function _onStartDrag(){
var e = new EventObject( {name:'onStartDrag', target:oDragItem, droptarget:oDropTarget} );
dd.onStartDrag(e);
if(!e.defaultPrevented()){
// default actions...
//
if(oDragItem) _prevParent = oDragItem.parentNode;
}
}
function dropInto(item, target, replaceClass){
replaceClass = replaceClass ? replaceClass : '';
// Reset the positioning so that it sits within the container according to the document stylesheet
if((item && target) || (item && _prevParent)) item.style.position="";
// Work out what type of drop this is
if(item && target){
// If there are no more elements within the _prevParent, remove the used class.
if(_prevParent.children.length <= 1) {
_prevParent.className = _prevParent.className.replace(regx_used, replaceClass);
}
target.appendChild(item);
target.className += ' '+used_class;
} else if(_prevParent) {
console.log("Reverting");
_prevParent.appendChild(item);
} else {
console.log("Failing");
console.log("Failed.");
}
}
function _onStopDrag(){
// Testing out a e.preventDefault() style - will be better than returning false...
var e = new EventObject( {name:'onStopDrag', target:oDragItem, droptarget:oDropTarget} );
dd.onStopDrag(e);
if(!e.defaultPrevented()){
console.log("allowMultidrop:" + dd.allowMultidrop + ", allowSwapping: " + dd.allowSwapping);
// reset
oDragItem.style.zIndex = 1;
oDragItem = null;
oDropTarget = null;
}
}
function _onTargetOver(){
if(!_onTargetOverCalled) {
_onTargetOverCalled = true;
var e = new EventObject( {name:'onTargetOver', target:oDragItem, droptarget:oDropTarget} );
dd.onTargetOver(e);
if(!e.defaultPrevented()){
// default actions...
}
}
}
function _onTargetOut(){
_onTargetOverCalled = false;
var e = new EventObject( {name:'onTargetOut', target:oDragItem, droptarget:oDropTarget} );
dd.onTargetOut(e);
if(!e.defaultPrevented()){
// default actions...
}
}
function _onTargetDrop(){
// Test with and without...
if(navigator.platform=="iPad") _makeDraggable(oDragItem);
var e = new EventObject( {name:'onTargetDrop', target:oDragItem, droptarget:oDropTarget} );
dd.onTargetDrop(e);
if(!e.defaultPrevented()){
// default actions...
//dropInto(oDragItem, oDropTarget);
}
}
}
/* CREATE INTSTANCE OF CLASS */
function createDragController(){
var initObj = {};
// initObj.allowMultidrop = true;
// initObj.allowSwapping = true;
initObj.onStartDrag = function(e){
e.target.className += ' dragging';
}
initObj.onStopDrag = function(e){
e.target.className = e.target.className.replace(/\b dragging\b/g, '');
}
initObj.onTargetOver = function(e){
e.droptarget.className += ' selected';
};
initObj.onTargetOut = function(e){
e.droptarget.className = e.droptarget.className.replace(/\b selected\b/g, '');
};
var ddc = new DD_Controller( initObj );
}
createDragController();
//# sourceURL=pen.js
</script>
</body></html>