angular.module('demo', []).controller("listController", function ($scope) {
$scope.list = [];
var max = 10;
for(var i = 0; i < max; i++){
$scope.list.push({id: i, text: "Element " + i});
}
}).directive('draggable', function(){
return {
restrict: 'A',
// scope: {
// dragData: '='
// },
link: function (scope, element, attributes) {
var el = element[0];
el.draggable = true;
el.addEventListener('dragstart', handleDragStart, false);
el.addEventListener('dragend', handleDragEnd, false);
function handleDragStart(e){
this.classList.add('dragging');
e.dataTransfer.effectAllowed = 'move';
console.log(attributes.dragData);
e.dataTransfer.setData('data', attributes.dragData);
}
function handleDragEnd(e) {
// this/e.target is the source node.
this.classList.remove('dragging');
}
}
}
}).directive('droppable', function(){
return {
restrict:"A",
// scope: {
// ondrop: '&',
// dropData: '='
// },
link: function(scope, element, attributes) {
var el = element[0];
//el.draggable = true;
el.addEventListener('dragenter', handleDragEnter, false);
el.addEventListener('dragover', handleDragOver, false);
el.addEventListener('dragleave', handleDragLeave, false);
el.addEventListener('drop', handleDrop, false);
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
return false;
}
function handleDragEnter(e) {
// this / e.target is the current hover target.
this.classList.add('dragover');
//e.dataTransfer.dropEffect = 'move';
}
function handleDrop(e){
// Stops some browsers from redirecting.
if (e.stopPropagation) e.stopPropagation();
var data =e.dataTransfer.getData('data');
// this / e.target is previous target element.
if ('function' == typeof scope.ondrop) {
scope.ondrop(data, attributes.dropData , e);
}
this.classList.remove('dragover');
}
function handleDragLeave(e) {
if (e.preventDefault) e.preventDefault();
this.classList.remove('dragover');
}
}
};
}).directive('reorder', function () {
return {
restrict: 'E',
transclude: true,
scope: {
list: '='
},
template: "<li drop-data='{{$index}}' drag-data='{{$index}}' ng-repeat='element in list' draggable droppable ng-transclude ></li>",
link: function (scope, element) {
scope.ondrop = function resort(dragIndex, dropIndex, event){
if (dragIndex == dropIndex){
return;
}
// console.log("HERE");
scope.$apply(function(){
dragIndex = Number(dragIndex);
// grab element to move
var elementToMove = scope.list[dragIndex];
// remove the element
scope.list.splice(dragIndex, 1);
// insert the element
scope.list.splice(Number(dropIndex), 0, elementToMove);
});
};
}
};
});
<div id='container' ng-controller="listController">
<ul class='list' >
<reorder list='list'>
<div >{{element.text}}</div>
</reorder>
</ul>
</div>
.dragging{
opacity:.4;
}
.dragover{
border: 2px dashed #000;
}
.dragover *{
//pointer-events: none;
}
li{
}