|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
|
|
<meta name='description' content='AngularJS + jQuery UI Drag-n-Drop'/> |
|
|
|
<title>JS Bin</title> |
|
|
|
<link href='//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css' rel='stylesheet'/> |
|
<link href='//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css' rel='stylesheet'> |
|
|
|
<style> |
|
#dnd-container { |
|
margin-left: auto; |
|
margin-right: auto; |
|
margin-top: 20px; |
|
width: 568px |
|
} |
|
|
|
#dnd-container .ui-droppable { |
|
float: left; |
|
border: 2px solid fuchsia; |
|
width: 250px; |
|
padding: 10px; |
|
height: 208px; |
|
border-radius: 10px; |
|
margin-top: 20px; |
|
} |
|
|
|
</style> |
|
|
|
</head> |
|
<body> |
|
|
|
<div ng-app='App' id='dnd-container' ng-controller='dndCtrl' ng-cloak> |
|
|
|
<div ui-drop-listener='dropListener' data-model='someArrays.list0'> |
|
<div ui-draggable ng-repeat='item in someArrays.list0' data-index='{{$index}}' class='btn btn-info btn-block'> |
|
{{item.name}} |
|
</div> |
|
</div> |
|
|
|
<div ui-drop-listener='dropListener' data-model='someArrays.list1' style='margin-left: 20px'> |
|
<div ui-draggable ng-repeat='item in someArrays.list1' data-index='{{$index}}' class='btn btn-info btn-block'> |
|
{{item.name}} |
|
</div> |
|
</div> |
|
|
|
<div ui-drop-listener='dropListener' data-model='someArrays.list2'> |
|
<div ui-draggable ng-repeat='item in someArrays.list2' data-index='{{$index}}' class='btn btn-info btn-block'> |
|
{{item.name}} |
|
</div> |
|
</div> |
|
|
|
<div ui-drop-listener='dropListener' data-model='someArrays.list3' style='margin-left: 20px'> |
|
<div ui-draggable ng-repeat='item in someArrays.list3' data-index='{{$index}}' class='btn btn-info btn-block'> |
|
{{item.name}} |
|
</div> |
|
</div> |
|
|
|
</div> |
|
|
|
<script src='//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js'></script> |
|
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'></script> |
|
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js'></script> |
|
<script src='//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js'></script> |
|
|
|
<script> |
|
(function () { |
|
|
|
var app = angular.module('App', []); |
|
|
|
app.controller('dndCtrl', ['$scope', 'someArrays', function ($scope, someArrays) { |
|
|
|
$scope.someArrays = someArrays; |
|
|
|
$scope.dropListener = function (eDraggable, eDroppable) { |
|
|
|
var isDropForbidden = function (aTarget, item) { |
|
if (aTarget.some(function (i) { |
|
return i.name == item.name; |
|
})) { |
|
return {reason:'target already contains "' + item.name + '"'}; |
|
} else { |
|
return false; |
|
} |
|
}; |
|
|
|
var onDropRejected = function (error) { |
|
alert('Operation not permitted: ' + error.reason); |
|
}; |
|
|
|
var onDropComplete = function (eSrc, item, index) { |
|
console.log('moved "' + item.name + ' from ' + eSrc.data('model') + '[' + index + ']' + ' to ' + eDroppable.data('model')); |
|
}; |
|
|
|
var eSrc = eDraggable.parent(); |
|
var sSrc = eSrc.data('model'); |
|
var sTarget = eDroppable.data('model'); |
|
|
|
if (sSrc != sTarget) { |
|
$scope.$apply(function () { |
|
var index = eDraggable.data('index'); |
|
var aSrc = $scope.$eval(sSrc); |
|
var aTarget = $scope.$eval(sTarget); |
|
var item = aSrc[index]; |
|
var error = isDropForbidden(aTarget, item); |
|
if (error) { |
|
onDropRejected(error); |
|
} else { |
|
aTarget.push(item); |
|
aSrc.splice(index, 1); |
|
onDropComplete(eSrc, item, index); |
|
} |
|
}); |
|
} |
|
|
|
}; |
|
}]); |
|
|
|
app.factory('someArrays', ['$q', '$timeout', function ($q, $timeout) { |
|
var deferred = $q.defer(); |
|
$timeout(function () { |
|
deferred.resolve({ |
|
someArrays:{ |
|
list0:[ |
|
{name:'AngularJS'}, |
|
{name:'Is'}, |
|
{name:'teh'}, |
|
{name:'@wesome'} |
|
], |
|
list1:[ |
|
{name:'AngularJS'} |
|
], |
|
list2:[ |
|
{name:'Is'}, |
|
{name:'rather good'} |
|
], |
|
list3:[ |
|
{name:'@wesome'}, |
|
{name:'MooTools'} |
|
]} |
|
}); |
|
}, 50); |
|
return deferred.promise.then(function (result) { |
|
return result.someArrays; |
|
}); |
|
}]); |
|
|
|
app.directive('uiDraggable', function () { |
|
return { |
|
restrict:'A', |
|
link:function (scope, element, attrs) { |
|
element.draggable({ |
|
revert:true |
|
}); |
|
} |
|
}; |
|
}); |
|
|
|
app.directive('uiDropListener', function () { |
|
return { |
|
restrict:'A', |
|
link:function (scope, eDroppable, attrs) { |
|
eDroppable.droppable({ |
|
drop:function (event, ui) { |
|
var fnDropListener = scope.$eval(attrs.uiDropListener); |
|
if (fnDropListener && angular.isFunction(fnDropListener)) { |
|
var eDraggable = angular.element(ui.draggable); |
|
fnDropListener(eDraggable, eDroppable, event, ui); |
|
} |
|
} |
|
}); |
|
} |
|
}; |
|
}); |
|
|
|
})(); |
|
</script> |
|
|
|
</body> |
|
</html> |