|
1
|
+/*
|
|
2
|
+ * Copyright © 2016-2019 The Thingsboard Authors
|
|
3
|
+ *
|
|
4
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+ * you may not use this file except in compliance with the License.
|
|
6
|
+ * You may obtain a copy of the License at
|
|
7
|
+ *
|
|
8
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+ *
|
|
10
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
11
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+ * See the License for the specific language governing permissions and
|
|
14
|
+ * limitations under the License.
|
|
15
|
+ */
|
|
16
|
+export default angular.module('thingsboard.directives.mdChipDraggable', [])
|
|
17
|
+ .directive('tbChipDraggable', function () {
|
|
18
|
+ return {
|
|
19
|
+ restrict: 'A',
|
|
20
|
+ scope: {},
|
|
21
|
+ bindToController: true,
|
|
22
|
+ controllerAs: 'vm',
|
|
23
|
+ controller: ['$document', '$scope', '$element', '$timeout',
|
|
24
|
+ function ($document, $scope, $element, $timeout) {
|
|
25
|
+ var options = {
|
|
26
|
+ axis: 'horizontal',
|
|
27
|
+ };
|
|
28
|
+ var handle = $element[0];
|
|
29
|
+ var draggingClassName = 'dragging';
|
|
30
|
+ var droppingClassName = 'dropping';
|
|
31
|
+ var droppingBeforeClassName = 'dropping--before';
|
|
32
|
+ var droppingAfterClassName = 'dropping--after';
|
|
33
|
+ var dragging = false;
|
|
34
|
+ var preventDrag = false;
|
|
35
|
+ var dropPosition;
|
|
36
|
+ var dropTimeout;
|
|
37
|
+
|
|
38
|
+ var move = function (from, to) {
|
|
39
|
+ this.splice(to, 0, this.splice(from, 1)[0]);
|
|
40
|
+ };
|
|
41
|
+
|
|
42
|
+ $element = angular.element($element[0].closest('md-chip'));
|
|
43
|
+
|
|
44
|
+ $element.attr('draggable', true);
|
|
45
|
+
|
|
46
|
+ $element.on('mousedown', function (event) {
|
|
47
|
+ if (event.target !== handle) {
|
|
48
|
+ preventDrag = true;
|
|
49
|
+ }
|
|
50
|
+ });
|
|
51
|
+
|
|
52
|
+ $document.on('mouseup', function () {
|
|
53
|
+ preventDrag = false;
|
|
54
|
+ });
|
|
55
|
+
|
|
56
|
+ $element.on('dragstart', function (event) {
|
|
57
|
+ if (preventDrag) {
|
|
58
|
+ event.preventDefault();
|
|
59
|
+
|
|
60
|
+ } else {
|
|
61
|
+ dragging = true;
|
|
62
|
+
|
|
63
|
+ $element.addClass(draggingClassName);
|
|
64
|
+
|
|
65
|
+ var dataTransfer = event.dataTransfer || event.originalEvent.dataTransfer;
|
|
66
|
+
|
|
67
|
+ dataTransfer.effectAllowed = 'copyMove';
|
|
68
|
+ dataTransfer.dropEffect = 'move';
|
|
69
|
+ dataTransfer.setData('text/plain', $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip));
|
|
70
|
+ }
|
|
71
|
+ });
|
|
72
|
+
|
|
73
|
+ $element.on('dragend', function () {
|
|
74
|
+ dragging = false;
|
|
75
|
+
|
|
76
|
+ $element.removeClass(draggingClassName);
|
|
77
|
+ });
|
|
78
|
+
|
|
79
|
+ var dragOverHandler = function (event) {
|
|
80
|
+ if (dragging) {
|
|
81
|
+ return;
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+ event.preventDefault();
|
|
85
|
+
|
|
86
|
+ var bounds = $element[0].getBoundingClientRect();
|
|
87
|
+
|
|
88
|
+ var props = {
|
|
89
|
+ width: bounds.right - bounds.left,
|
|
90
|
+ height: bounds.bottom - bounds.top,
|
|
91
|
+ x: (event.originalEvent || event).clientX - bounds.left,
|
|
92
|
+ y: (event.originalEvent || event).clientY - bounds.top,
|
|
93
|
+ };
|
|
94
|
+
|
|
95
|
+ var offset = options.axis === 'vertical' ? props.y : props.x;
|
|
96
|
+ var midPoint = (options.axis === 'vertical' ? props.height : props.width) / 2;
|
|
97
|
+
|
|
98
|
+ $element.addClass(droppingClassName);
|
|
99
|
+
|
|
100
|
+ if (offset < midPoint) {
|
|
101
|
+ dropPosition = 'before';
|
|
102
|
+ $element.removeClass(droppingAfterClassName);
|
|
103
|
+ $element.addClass(droppingBeforeClassName);
|
|
104
|
+
|
|
105
|
+ } else {
|
|
106
|
+ dropPosition = 'after';
|
|
107
|
+ $element.removeClass(droppingBeforeClassName);
|
|
108
|
+ $element.addClass(droppingAfterClassName);
|
|
109
|
+ }
|
|
110
|
+ };
|
|
111
|
+
|
|
112
|
+ var dropHandler = function (event) {
|
|
113
|
+ event.preventDefault();
|
|
114
|
+
|
|
115
|
+ var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text/plain'), 10);
|
|
116
|
+ var currentIndex = $scope.$parent.$mdChipsCtrl.items.indexOf($scope.$parent.$chip);
|
|
117
|
+ var newIndex = null;
|
|
118
|
+
|
|
119
|
+ if (dropPosition === 'before') {
|
|
120
|
+ if (droppedItemIndex < currentIndex) {
|
|
121
|
+ newIndex = currentIndex - 1;
|
|
122
|
+ } else {
|
|
123
|
+ newIndex = currentIndex;
|
|
124
|
+ }
|
|
125
|
+ } else {
|
|
126
|
+ if (droppedItemIndex < currentIndex) {
|
|
127
|
+ newIndex = currentIndex;
|
|
128
|
+ } else {
|
|
129
|
+ newIndex = currentIndex + 1;
|
|
130
|
+ }
|
|
131
|
+ }
|
|
132
|
+
|
|
133
|
+ // prevent event firing multiple times in firefox
|
|
134
|
+ $timeout.cancel(dropTimeout);
|
|
135
|
+ dropTimeout = $timeout(function () {
|
|
136
|
+ dropPosition = null;
|
|
137
|
+
|
|
138
|
+ move.apply($scope.$parent.$mdChipsCtrl.items, [droppedItemIndex, newIndex]);
|
|
139
|
+
|
|
140
|
+ $scope.$apply(function () {
|
|
141
|
+ $scope.$emit('mdChipDraggable:change', {
|
|
142
|
+ collection: $scope.$parent.$mdChipsCtrl.items,
|
|
143
|
+ item: $scope.$parent.$mdChipsCtrl.items[droppedItemIndex],
|
|
144
|
+ from: droppedItemIndex,
|
|
145
|
+ to: newIndex,
|
|
146
|
+ });
|
|
147
|
+ });
|
|
148
|
+
|
|
149
|
+ $element.removeClass(droppingClassName);
|
|
150
|
+ $element.removeClass(droppingBeforeClassName);
|
|
151
|
+ $element.removeClass(droppingAfterClassName);
|
|
152
|
+
|
|
153
|
+ $element.off('drop', dropHandler);
|
|
154
|
+ }, 1000 / 16);
|
|
155
|
+ };
|
|
156
|
+
|
|
157
|
+ $element.on('dragenter', function () {
|
|
158
|
+ if (dragging) {
|
|
159
|
+ return;
|
|
160
|
+ }
|
|
161
|
+
|
|
162
|
+ $element.off('dragover', dragOverHandler);
|
|
163
|
+ $element.off('drop', dropHandler);
|
|
164
|
+
|
|
165
|
+ $element.on('dragover', dragOverHandler);
|
|
166
|
+ $element.on('drop', dropHandler);
|
|
167
|
+ });
|
|
168
|
+
|
|
169
|
+ $element.on('dragleave', function () {
|
|
170
|
+ $element.removeClass(droppingClassName);
|
|
171
|
+ $element.removeClass(droppingBeforeClassName);
|
|
172
|
+ $element.removeClass(droppingAfterClassName);
|
|
173
|
+ });
|
|
174
|
+
|
|
175
|
+ }],
|
|
176
|
+ };
|
|
177
|
+ })
|
|
178
|
+ .name;
|
|
179
|
+
|
|
180
|
+/* eslint-enable angular/angularelement */ |
...
|
...
|
|