Drag and Drop в AngularJS¶
Шаблон:
<div class="row"
ng-mousemove="onMouseMove($event)"
ng-mouseup="onMouseUp($event)"
ng-touchmove="onMouseMove($event)"
ng-touchend="onMouseUp($event)">
<div class="col-md-2 col-sm-4 col-xs-6" ng-repeat="status in statuses">
<div class="panel panel-primary drag_item"
id="{{ status.id }}"
ng-style="nextStatus === status.id ? hover_style : {}">
<div class="panel-heading text-center">
<strong>{{status.id}}</strong>
</div>
<div class="panel-body">
<ul class="list-group">
<li
ng-mousedown="onMouseDown(item.id,status.id,$event)"
ng-touchstart="onMouseDown(item.id,status.id,$event)"
ng-style="item.id === dragging ? dragging_style : {}"
ng-repeat="item in status.items"
class="list-group-item"><span class="badge badge-primary">{{item.quantity}}</span> {{item.id}}</li>
</ul>
</div>
</div>
</div>
</div>
Контроллер:
// идентификатор элемента, который перетаскивается
$scope.dragging = null;
// идентификатор группы, которой пренадлежит переносимый элемент
$scope.currentStatus = null;
// стиль при наведении на блок, куда надо перетащить
$scope.hover_style = {'border': '2px solid #FF0000'};
// стиль при перетаскивании, не указан только TOP и LEFT
// TOP и LEFT присваиваются при переносе
$scope.dragging_style = {
'position': 'fixed',
'display' : 'block',
'z-index': '9999',
'opacity': .7,
'cursor': 'pointer',
'border': '1px dashed #ff5555',
'background-color': 'rgba(125,255,0,.5)'
}
// координаты внутри элемента
$scope.drag_offset = { x : 0, y : 0}
// примерные данные о блоках и элементах
$scope.statuses = [
{
id:"Литье",
items:[
{id:'Кольцо'},
{id:'Серьги'},
]
},
{
id:"Брак",
items:[
{id:'Браслет'}
]
},
];
$scope.onMouseMove = function(event){
// массив, список блоков для переноса
// Класс drag_item можно заменить, не забудьте заменить его в блоке
$scope.dragItemElements = angular.element(document.querySelectorAll('.drag_item'));
$scope.nextStatus = null;
event.preventDefault();
var touch = event;
if(!!event.originalEvent) {
if(!!event.originalEvent.changedTouches && event.originalEvent.changedTouches.length > 0){
touch = event.originalEvent.changedTouches[0];
} else if(!!event.originalEvent.touches && event.originalEvent.touches.length > 0) {
touch = event.originalEvent.touches[0];
}
} else if(!!event.touches && event.touches.length > 0) {
touch = event.touches[0];
} else if(!!event.changedTouches && event.changedTouches.length > 0) {
touch = event.changedTouches[0];
}
var target = event.currentTarget || event.target;
// условие, если элемент перетаскивается
if(!!$scope.dragging) {
// определение координат элемента через стиль
$scope.dragging_style.left = touch.pageX - $scope.drag_offset.x;
$scope.dragging_style.top = touch.pageY - $scope.drag_offset.y;
// цикл, перебираем все блоки для переноса, чтобы
// вычислить блок, на который наведен элемент при перетаскивании
angular.forEach($scope.dragItemElements,function(elem,num) {
// размеры блока
var bounds = elem.getBoundingClientRect();
// условие, если курсор направлен на этот блок
if(touch.pageX >= bounds.left
&& touch.pageX <= bounds.left + bounds.width
&& touch.pageY >= bounds.top
&& touch.pageY <= bounds.bottom + bounds.height){
// назначение следующего блока, куда перетащится
// элемент при завершении перетаскивания
$scope.nextStatus = elem.attributes.id.value;
}
});
/* ====================================================*/
// этот блок чтобы при перетаскивании не выделялся текст
if (event.stopPropagation) event.stopPropagation();
if (event.preventDefault) event.preventDefault();
event.cancelBubble = true;
event.returnValue = false;
return false;
/* ====================================================*/
}
}
$scope.onMouseDown = function(itemid,statusid,event){
// перетираем старые данные о местоположении элемента
delete $scope.dragging_style.left;
delete $scope.dragging_style.top;
// определение переменных координат внутри элемента
$scope.drag_offset.x = event.offsetX || 0;
$scope.drag_offset.y = event.offsetY || 0;
// маленькая задержка. timeuot НЕОБЯЗАТЕЛЬНО. Можно в принципе убрать.
$scope.timeoutMouseDown = setTimeout(function() {
// определение перетаскиваемого элемента
$scope.currentStatus = statusid
// определение блока, откуда перетаскиваемый элемент
$scope.dragging = itemid;
},100);
}
$scope.onMouseUp = function(event) {
// отключение задержки при нажатии НЕОБЯЗАТЕЛЬНО, ЕСЛИ ЕЕ НЕТ!
clearTimeout($scope.timeoutMouseDown);
if(!!$scope.nextStatus && !!$scope.currentStatus && !!$scope.dragging ) {
$scope.statuses.forEach(function(status,num1) {
// ЗДЕСЬ БУДЕТ ВЫЗОВ ЛОГИКИ
// ЛОГИКА ДЛЯ ТЕКУЩЕГО ПРИМЕРА
// условие на очистку фрейма откуда стащил элемент
if($scope.currentStatus == status.id) {
status.items = status.items.filter(function(item){ return item.id !== $scope.dragging });
}
// условие на добавление во фрейм куда перетащил элемент
if($scope.nextStatus == status.id) {
if(!("items" in status)) status.items = [];
status.items.push({'id' : $scope.dragging});
}
});
}
// обнуляем переменные
$scope.currentStatus = null;
$scope.dragging = null;
$scope.nextStatus = null;
}