<!doctype html>
<html ng-app="demo">
<head>
<meta charset="utf-8">
<title>AngularJS Drag Drop directive demo by Ajain Vivek</title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular-sanitize.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container" ng-controller="mainCtrl">
<h1 class="text-muted">Drag Drop Demo - https://github.com/ajainvivek/ngDragDrop</h1>
<div class="usage row">
<h4>Simple usage</h4>
<p>This is a simple usage of the drag drop directive</p>
<pre><ng-drag-drop dropTo="#drop-zone"></ng-drag-drop></pre>
<h4>Results</h4>
<div class="drag_container">
<h4>Draggables</h4>
<div ng-drag-drop dropTo="#drop-zone" styles="{{styles}}" on-drag="dragCallback(event)" on-drop="dropCallback(event)" on-over="overCallback(event)">
<div class="draggable-item" dragIt="true">Drag Item A</div>
<div class="draggable-item" dragIt="true">Drag Item B</div>
<div class="draggable-item" dragIt="false">Fixed Item C</div>
</div>
</div>
<div class="drop_container">
<h4>Drop Zone</h4>
<div id="drop-zone">
</div>
</div>
</div>
</div>
<script src="ngDragDrop.js"></script>
<script src="script.js"></script>
</body>
</html>
var app = angular.module('demo', ['ngSanitize', 'ngDragDrop']);
app.controller("mainCtrl", function ($scope, ngDragDrop) {
$scope.styles = {
draggables : {
onDragging : {border: "1px dashed #000", cursor : "move"},
onStart : {opacity: 0.5}
},
droppables : {
onEnter: {background: "red"},
onLeave: {background: "yellow"}
}
};
$scope.dragCallback = function (event) {
console.log("Dragging", event);
};
$scope.dropCallback = function (event) {
var currDragElem = ngDragDrop.getCurrentDragElement();
var dropElem = angular.element(event.target);
currDragElem.css({
"pointer-events": "none"
});
dropElem.append(currDragElem);
};
$scope.overCallback = function (event) {
console.log("Drag Over", event);
};
});
.usage {
padding: 10px;
border: 1px solid rgba(0,0,0,0.09);
border-radius: 5px;
}
#draggables {
float: left;
height: 100%;
}
.draggable-item {
height: 100px;
width: 100px;
background: #ccc;
margin: 10px auto;
text-align: center;
line-height: 100px;
}
.drag_container {
float: left;
width: 300px;
margin: 10px;
background: #ffe;
text-align: center;
}
.drop_container {
float: left;
width: 300px;
height: 100%;
margin: 10px;
background: #efe;
text-align: center;
}
#drop-zone {
height: 100%;
min-height: 200px;
width: 100%;
padding: 20px;
}
/*
* ngDragDrop - HTML5 Drag & Drop
* http://github.com/ajainvivek/ngDragDrop
* (c) 2015 MIT License, https://chaicode.com
*/
(function(window, angular, undefined) {
'use strict';
var module = angular.module('ngDragDrop', []);
var $el = angular.element;
var isDef = angular.isDefined;
var style = (document.body || document.documentElement).style;
var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
module.provider('ngDragDrop', function() {
var defaults = this.defaults = {
styles : {
draggables : {
onDragging : {},
onStart : {}
},
droppables : {
onEnter: {},
onLeave: {}
}
}
};
this.setDefaults = function (newDefaults) {
angular.extend(defaults, newDefaults);
};
this.$get = ['$document', '$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
function($document, $templateCache, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
var privateMethods = {
currentDragElement: {},
currentDropElement: {},
resetStyles: function () {
var defaults = publicMethods.getDefaults();
var i;
var onDraggingKeys = Object.keys(defaults.styles.draggables.onDragging);
var onStartKeys = Object.keys(defaults.styles.draggables.onStart);
var onEnterKeys = Object.keys(defaults.styles.droppables.onEnter);
var onLeaveKeys = Object.keys(defaults.styles.droppables.onLeave);
if (!angular.equals({}, this.currentDragElement)) {
//Reset Draggables
for (i = 0; i < onDraggingKeys.length; i++) {
this.currentDragElement.css(onDraggingKeys[i], "");
}
for (i = 0; i < onStartKeys.length; i++) {
this.currentDragElement.css(onStartKeys[i], "");
}
}
if (!angular.equals({}, this.currentDropElement)) {
//Reset Droppables
for (i = 0; i < onEnterKeys.length; i++) {
this.currentDropElement.css(onEnterKeys[i], "");
}
for (i = 0; i < onLeaveKeys.length; i++) {
this.currentDropElement.css(onLeaveKeys[i], "");
}
}
},
bindDragEvents: function (scope, dragElems, listeners) {
var self = this;
var defaults = publicMethods.getDefaults();
var onDragStart = function (event) {
self.currentDragElement = angular.element(event.target);
angular.element(event.target).css(defaults.styles.draggables.onStart);
};
var onDrag = function (event) {
angular.element(event.target).css(defaults.styles.draggables.onDragging);
listeners.onDrag({
event : event
});
return true;
};
var onDragEnd = function (event) {
self.resetStyles();
};
for (var i = 0; i < dragElems.length; i++) {
dragElems[i].addEventListener('dragstart', onDragStart);
dragElems[i].addEventListener('drag', onDrag);
dragElems[i].addEventListener('dragend', onDragEnd);
}
},
bindDropEvents: function (scope, dropZone, listeners) {
var self = this;
var defaults = publicMethods.getDefaults();
var onDragEnter = function (event) {
self.currentDropElement = angular.element(event.target);
angular.element(event.target).css(defaults.styles.droppables.onEnter);
event.preventDefault();
};
var onDragOver = function (event) {
listeners.onOver({event: event});
//Allow moves
event.dataTransfer.dropEffect = "move";
event.preventDefault();
return false;
};
var onDragLeave = function (event) {
angular.element(event.target).css(defaults.styles.droppables.onLeave);
};
var onDrop = function (event) {
event.preventDefault();
listeners.onDrop({event: event});
$timeout(function() { //Reset Drag/Drop Element
self.currentDropElement = {};
self.currentDragElement = {};
}, 10);
};
dropZone.addEventListener('drop', onDrop);
dropZone.addEventListener('dragenter', onDragEnter);
dropZone.addEventListener('dragleave', onDragLeave);
dropZone.addEventListener('dragover', onDragOver);
},
setDraggable: function(scope, elem, listeners) {
var dragItems = angular.element(elem.querySelectorAll("[dragIt='true']"));
dragItems.attr("draggable", true);
this.bindDragEvents(scope, dragItems, listeners);
return dragItems;
},
setDroppable: function (scope, elem, listeners) {
var style = elem.attr("dropTo");
this.bindDropEvents(scope, document.querySelectorAll(style)[0], listeners);
}
};
var publicMethods = {
setup: function(opts) {
angular.extend(defaults, opts);
var options = this.getDefaults();
privateMethods.setDraggable(options.scope, options.elem[0], options.listeners);
privateMethods.setDroppable(options.scope, options.elem, options.listeners);
},
getDefaults: function () {
return defaults;
},
getCurrentDragElement : function () {
return privateMethods.currentDragElement;
}
};
return publicMethods;
}
];
});
module.directive('ngDragDrop', ['ngDragDrop', '$parse', function(ngDragDrop, $parse) {
return {
restrict: 'EA',
scope: {
onDrag: '&',
onDrop: '&',
onOver: '&'
},
link: function(scope, elem, attrs) {
var ngDragDropScope = angular.isDefined(scope.ngDragDropScope) ? scope.ngDragDropScope : 'noScope';
var defaults = ngDragDrop.getDefaults();
ngDragDrop.setup({
elem : elem,
attrs : attrs,
scope: scope,
listeners : {
onDrag : scope.onDrag || function () {},
onDrop : scope.onDrop || function () {},
onOver : scope.onOver || function () {}
},
styles : JSON.parse(attrs.styles) || defaults.styles
});
}
};
}]);
})(window, window.angular);