<!DOCTYPE html>
<html ng-app="listApp">
<head>
<meta charset="UTF-8">
<title>Simple Angular Draggable List</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<script src="script.js"></script>
</head>
	<body ng-controller="listCtrl">
		<ul class="list-group" ng-init="initList()">
		  <li class="list-group-item" id="item-{{item.Id}}" ng-repeat="item in listItems track by $index" ml-draggable-list="listItems">{{item.Name}}</li>
		</ul>
	</div>
	</body>
</html>
var app = angular.module("listApp", []);
app.controller("listCtrl", function($scope) {
// Example list for ng-repeat
    $scope.listItems = [];
	$scope.initList = function()
	{
		$scope.listItems.push({Id:0, Name:'one'});
		$scope.listItems.push({Id:1, Name:'two'});
		$scope.listItems.push({Id:2, Name:'three'});
	}
});
// Simple and reusable directive for making list elements draggable.
app.directive('mlDraggableList', function(){ 
   return {
      restrict: 'A', //attribute only
      link: function(scope, elem, attr, ctrl) {
			//Drag functions
				scope.swapItems = function(sourceElemId, targetElemId, collectionName)
				{
					var source = scope[collectionName][sourceElemId];
					scope[collectionName][sourceElemId] = scope[collectionName][targetElemId];
					scope[collectionName][targetElemId] = source;
					scope.$apply();
				}
				scope.listDragStart = function()
				{
				 var sourceElem = event.target.id;
				var startElemId = $(event.target).attr("dlid");
				event.dataTransfer.setData("dlid", startElemId);
				}
				
				scope.listDragOver = function () {
					event.preventDefault();
				}
				
				scope.listDrop = function (collectionName) {
					 event.preventDefault();
					var targetElem = $(event.target).closest('li')
					var targetElemId = targetElem.attr("dlid");
					var sourceElemId = event.dataTransfer.getData("dlid");

					if (sourceElemId != targetElemId)
					{
						scope.swapItems(sourceElemId, targetElemId, collectionName);
					}
				}
			// Wire elements on last ng-repeat
		   if (scope.$last){
				scope.dllistItems = scope.$eval("scope." + attr.mlDraggableList);
		     $("li[ml-draggable-list]").each(function(index, item){
				
				$(item).attr("dlid", index); // Id used for swapping elements
				$(item).attr("draggable", true);
				$(item).bind('dragstart', function(e) { // Capture source element
					scope.$eval("listDragStart()");
				});
				$(item).bind('dragover', function(e) { // overriding default behavior
					scope.$eval("listDragOver()");
				});
				$(item).bind('drop', function(e) {
					scope.$eval("listDrop('" + attr.mlDraggableList + "')"); // When element is dropped
				});
			 });
		   }
      }
   };
});
/* Styles go here */

## Synopsis

Simple and reusable directive for making list elements draggable.

## Code Example

To make elements draggable add "ml-draggable-list" custom attribute and pass in the collection name.

```
<ul class="list-group" ng-init="initList()">
	<li class="list-group-item" id="item-{{item.Id}}" ng-repeat="item in listItems track by $index" ml-draggable-list="listItems">{{item.Name}}</li>
</ul>
```

## Motivation

Needed a simple and reusable directive to make elements in ng-repeat draggable.

## Installation

```
Step 1 - Add directive e.g. [yourApp].directive('mlDraggableList', function(){ 
Step 2 - Add "ml-draggable-list" attribute to your ng-repeat and pass in the collection name e.g. ="ml-draggable-list='listItems'"
```

## Contributors

tarikub

## License

MIT: http://opensource.org/licenses/MIT