7 changed files with 270 additions and 117 deletions
@ -0,0 +1,180 @@ |
|||||
|
/* |
||||
|
* Copyright © 2016-2019 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
export default angular.module('thingsboard.directives.mdChipDraggable', []) |
||||
|
.directive('tbChipDraggable', function () { |
||||
|
return { |
||||
|
restrict: 'A', |
||||
|
scope: {}, |
||||
|
bindToController: true, |
||||
|
controllerAs: 'vm', |
||||
|
controller: ['$document', '$scope', '$element', '$timeout', |
||||
|
function ($document, $scope, $element, $timeout) { |
||||
|
var options = { |
||||
|
axis: 'horizontal', |
||||
|
}; |
||||
|
var handle = $element[0]; |
||||
|
var draggingClassName = 'dragging'; |
||||
|
var droppingClassName = 'dropping'; |
||||
|
var droppingBeforeClassName = 'dropping--before'; |
||||
|
var droppingAfterClassName = 'dropping--after'; |
||||
|
var dragging = false; |
||||
|
var preventDrag = false; |
||||
|
var dropPosition; |
||||
|
var dropTimeout; |
||||
|
|
||||
|
var move = function (from, to) { |
||||
|
this.splice(to, 0, this.splice(from, 1)[0]); |
||||
|
}; |
||||
|
|
||||
|
$element = angular.element($element[0].closest('md-chip')); |
||||
|
|
||||
|
$element.attr('draggable', true); |
||||
|
|
||||
|
$element.on('mousedown', function (event) { |
||||
|
if (event.target !== handle) { |
||||
|
preventDrag = true; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$document.on('mouseup', function () { |
||||
|
preventDrag = false; |
||||
|
}); |
||||
|
|
||||
|
$element.on('dragstart', function (event) { |
||||
|
if (preventDrag) { |
||||
|
event.preventDefault(); |
||||
|
|
||||
|
} else { |
||||
|
dragging = true; |
||||
|
|
||||
|
$element.addClass(draggingClassName); |
||||
|
|
||||
|
var dataTransfer = event.dataTransfer || event.originalEvent.dataTransfer; |
||||
|
|
||||
|
dataTransfer.effectAllowed = 'copyMove'; |
||||
|
dataTransfer.dropEffect = 'move'; |
||||
|
dataTransfer.setData('text/plain', $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip)); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$element.on('dragend', function () { |
||||
|
dragging = false; |
||||
|
|
||||
|
$element.removeClass(draggingClassName); |
||||
|
}); |
||||
|
|
||||
|
var dragOverHandler = function (event) { |
||||
|
if (dragging) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
event.preventDefault(); |
||||
|
|
||||
|
var bounds = $element[0].getBoundingClientRect(); |
||||
|
|
||||
|
var props = { |
||||
|
width: bounds.right - bounds.left, |
||||
|
height: bounds.bottom - bounds.top, |
||||
|
x: (event.originalEvent || event).clientX - bounds.left, |
||||
|
y: (event.originalEvent || event).clientY - bounds.top, |
||||
|
}; |
||||
|
|
||||
|
var offset = options.axis === 'vertical' ? props.y : props.x; |
||||
|
var midPoint = (options.axis === 'vertical' ? props.height : props.width) / 2; |
||||
|
|
||||
|
$element.addClass(droppingClassName); |
||||
|
|
||||
|
if (offset < midPoint) { |
||||
|
dropPosition = 'before'; |
||||
|
$element.removeClass(droppingAfterClassName); |
||||
|
$element.addClass(droppingBeforeClassName); |
||||
|
|
||||
|
} else { |
||||
|
dropPosition = 'after'; |
||||
|
$element.removeClass(droppingBeforeClassName); |
||||
|
$element.addClass(droppingAfterClassName); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
var dropHandler = function (event) { |
||||
|
event.preventDefault(); |
||||
|
|
||||
|
var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text/plain'), 10); |
||||
|
var currentIndex = $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip); |
||||
|
var newIndex = null; |
||||
|
|
||||
|
if (dropPosition === 'before') { |
||||
|
if (droppedItemIndex < currentIndex) { |
||||
|
newIndex = currentIndex - 1; |
||||
|
} else { |
||||
|
newIndex = currentIndex; |
||||
|
} |
||||
|
} else { |
||||
|
if (droppedItemIndex < currentIndex) { |
||||
|
newIndex = currentIndex; |
||||
|
} else { |
||||
|
newIndex = currentIndex + 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// prevent event firing multiple times in firefox
|
||||
|
$timeout.cancel(dropTimeout); |
||||
|
dropTimeout = $timeout(function () { |
||||
|
dropPosition = null; |
||||
|
|
||||
|
move.apply($scope.$parent.$mdChipsCtrl.items, [droppedItemIndex, newIndex]); |
||||
|
|
||||
|
$scope.$apply(function () { |
||||
|
$scope.$emit('mdChipDraggable:change', { |
||||
|
collection: $scope.$parent.$mdChipsCtrl.items, |
||||
|
item: $scope.$parent.$mdChipsCtrl.items[droppedItemIndex], |
||||
|
from: droppedItemIndex, |
||||
|
to: newIndex, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
$element.removeClass(droppingClassName); |
||||
|
$element.removeClass(droppingBeforeClassName); |
||||
|
$element.removeClass(droppingAfterClassName); |
||||
|
|
||||
|
$element.off('drop', dropHandler); |
||||
|
}, 1000 / 16); |
||||
|
}; |
||||
|
|
||||
|
$element.on('dragenter', function () { |
||||
|
if (dragging) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
$element.off('dragover', dragOverHandler); |
||||
|
$element.off('drop', dropHandler); |
||||
|
|
||||
|
$element.on('dragover', dragOverHandler); |
||||
|
$element.on('drop', dropHandler); |
||||
|
}); |
||||
|
|
||||
|
$element.on('dragleave', function () { |
||||
|
$element.removeClass(droppingClassName); |
||||
|
$element.removeClass(droppingBeforeClassName); |
||||
|
$element.removeClass(droppingAfterClassName); |
||||
|
}); |
||||
|
|
||||
|
}], |
||||
|
}; |
||||
|
}) |
||||
|
.name; |
||||
|
|
||||
|
/* eslint-enable angular/angularelement */ |
||||
Loading…
Reference in new issue