angular_ui_tree_rails 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/angular_ui_tree_rails/version.rb +1 -1
- data/lib/vendor/assets/javascripts/angular-ui-tree.js +1247 -0
- data/lib/vendor/assets/javascripts/angular-ui-tree.min.js +6 -0
- data/lib/vendor/assets/stylesheets/angular-ui-tree.css +63 -0
- data/lib/vendor/assets/stylesheets/angular-ui-tree.min.css +2 -0
- data/lib/vendor/assets/stylesheets/angular-ui-tree.scss +63 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e977635ef5a14d7181a0663865914513d0400483
|
4
|
+
data.tar.gz: 7c966188eb155837a470c236c34160b7a24e9ff8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c99575754ddb92ae812c3d1e03c86c5a3c505bff8c43747a22333d7ec8fb2c7da976f3e842de282e25dc906eb6517104f43aad89612c9d392828db60d5efe790
|
7
|
+
data.tar.gz: 0ad0b5c3141b45c9c3cdb01045e9752b64e000894ef8ca1827dcd88db6d65551447d30da9788ded7a4c391ffc8aa0065c1a1b8d7632fe7d04d545f4620f34f51
|
@@ -0,0 +1,1247 @@
|
|
1
|
+
/**
|
2
|
+
* @license Angular UI Tree v2.1.5
|
3
|
+
* (c) 2010-2014. https://github.com/JimLiu/angular-ui-tree
|
4
|
+
* License: MIT
|
5
|
+
*/
|
6
|
+
(function () {
|
7
|
+
'use strict';
|
8
|
+
|
9
|
+
angular.module('ui.tree', [])
|
10
|
+
.constant('treeConfig', {
|
11
|
+
treeClass: 'angular-ui-tree',
|
12
|
+
emptyTreeClass: 'angular-ui-tree-empty',
|
13
|
+
hiddenClass: 'angular-ui-tree-hidden',
|
14
|
+
nodesClass: 'angular-ui-tree-nodes',
|
15
|
+
nodeClass: 'angular-ui-tree-node',
|
16
|
+
handleClass: 'angular-ui-tree-handle',
|
17
|
+
placeHolderClass: 'angular-ui-tree-placeholder',
|
18
|
+
dragClass: 'angular-ui-tree-drag',
|
19
|
+
dragThreshold: 3,
|
20
|
+
levelThreshold: 30
|
21
|
+
});
|
22
|
+
|
23
|
+
})();
|
24
|
+
|
25
|
+
(function () {
|
26
|
+
'use strict';
|
27
|
+
|
28
|
+
angular.module('ui.tree')
|
29
|
+
|
30
|
+
/**
|
31
|
+
* @ngdoc service
|
32
|
+
* @name ui.tree.service:$helper
|
33
|
+
* @requires ng.$document
|
34
|
+
* @requires ng.$window
|
35
|
+
*
|
36
|
+
* @description
|
37
|
+
* angular-ui-tree.
|
38
|
+
*/
|
39
|
+
.factory('$uiTreeHelper', ['$document', '$window',
|
40
|
+
function ($document, $window) {
|
41
|
+
return {
|
42
|
+
|
43
|
+
/**
|
44
|
+
* A hashtable used to storage data of nodes
|
45
|
+
* @type {Object}
|
46
|
+
*/
|
47
|
+
nodesData: {
|
48
|
+
},
|
49
|
+
|
50
|
+
setNodeAttribute: function(scope, attrName, val) {
|
51
|
+
if (!scope.$modelValue) return null;
|
52
|
+
var data = this.nodesData[scope.$modelValue.$$hashKey];
|
53
|
+
if (!data) {
|
54
|
+
data = {};
|
55
|
+
this.nodesData[scope.$modelValue.$$hashKey] = data;
|
56
|
+
}
|
57
|
+
data[attrName] = val;
|
58
|
+
},
|
59
|
+
|
60
|
+
getNodeAttribute: function(scope, attrName) {
|
61
|
+
if (!scope.$modelValue) return null;
|
62
|
+
var data = this.nodesData[scope.$modelValue.$$hashKey];
|
63
|
+
if (data) {
|
64
|
+
return data[attrName];
|
65
|
+
}
|
66
|
+
return null;
|
67
|
+
},
|
68
|
+
|
69
|
+
/**
|
70
|
+
* @ngdoc method
|
71
|
+
* @methodOf ui.tree.service:$nodrag
|
72
|
+
* @param {Object} targetElm angular element
|
73
|
+
* @return {Bool} check if the node can be dragged.
|
74
|
+
*/
|
75
|
+
nodrag: function (targetElm) {
|
76
|
+
return (typeof targetElm.attr('data-nodrag')) != "undefined";
|
77
|
+
},
|
78
|
+
|
79
|
+
/**
|
80
|
+
* get the event object for touchs
|
81
|
+
* @param {[type]} e [description]
|
82
|
+
* @return {[type]} [description]
|
83
|
+
*/
|
84
|
+
eventObj: function(e) {
|
85
|
+
var obj = e;
|
86
|
+
if (e.targetTouches !== undefined) {
|
87
|
+
obj = e.targetTouches.item(0);
|
88
|
+
} else if (e.originalEvent !== undefined && e.originalEvent.targetTouches !== undefined) {
|
89
|
+
obj = e.originalEvent.targetTouches.item(0);
|
90
|
+
}
|
91
|
+
return obj;
|
92
|
+
},
|
93
|
+
|
94
|
+
dragInfo: function(node) {
|
95
|
+
return {
|
96
|
+
source: node,
|
97
|
+
sourceInfo: {
|
98
|
+
nodeScope: node,
|
99
|
+
index: node.index(),
|
100
|
+
nodesScope: node.$parentNodesScope
|
101
|
+
},
|
102
|
+
index: node.index(),
|
103
|
+
siblings: node.siblings().slice(0),
|
104
|
+
parent: node.$parentNodesScope,
|
105
|
+
|
106
|
+
moveTo: function(parent, siblings, index) { // Move the node to a new position
|
107
|
+
this.parent = parent;
|
108
|
+
this.siblings = siblings.slice(0);
|
109
|
+
var i = this.siblings.indexOf(this.source); // If source node is in the target nodes
|
110
|
+
if (i > -1) {
|
111
|
+
this.siblings.splice(i, 1);
|
112
|
+
if (this.source.index() < index) {
|
113
|
+
index--;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
this.siblings.splice(index, 0, this.source);
|
117
|
+
this.index = index;
|
118
|
+
},
|
119
|
+
|
120
|
+
parentNode: function() {
|
121
|
+
return this.parent.$nodeScope;
|
122
|
+
},
|
123
|
+
|
124
|
+
prev: function() {
|
125
|
+
if (this.index > 0) {
|
126
|
+
return this.siblings[this.index - 1];
|
127
|
+
}
|
128
|
+
return null;
|
129
|
+
},
|
130
|
+
|
131
|
+
next: function() {
|
132
|
+
if (this.index < this.siblings.length - 1) {
|
133
|
+
return this.siblings[this.index + 1];
|
134
|
+
}
|
135
|
+
return null;
|
136
|
+
},
|
137
|
+
|
138
|
+
isDirty: function() {
|
139
|
+
return this.source.$parentNodesScope != this.parent ||
|
140
|
+
this.source.index() != this.index;
|
141
|
+
},
|
142
|
+
|
143
|
+
eventArgs: function(elements, pos) {
|
144
|
+
return {
|
145
|
+
source: this.sourceInfo,
|
146
|
+
dest: {
|
147
|
+
index: this.index,
|
148
|
+
nodesScope: this.parent
|
149
|
+
},
|
150
|
+
elements: elements,
|
151
|
+
pos: pos
|
152
|
+
};
|
153
|
+
},
|
154
|
+
|
155
|
+
apply: function() {
|
156
|
+
var nodeData = this.source.$modelValue;
|
157
|
+
this.source.remove();
|
158
|
+
this.parent.insertNode(this.index, nodeData);
|
159
|
+
}
|
160
|
+
};
|
161
|
+
},
|
162
|
+
|
163
|
+
/**
|
164
|
+
* @ngdoc method
|
165
|
+
* @name hippo.theme#height
|
166
|
+
* @methodOf ui.tree.service:$helper
|
167
|
+
*
|
168
|
+
* @description
|
169
|
+
* Get the height of an element.
|
170
|
+
*
|
171
|
+
* @param {Object} element Angular element.
|
172
|
+
* @returns {String} Height
|
173
|
+
*/
|
174
|
+
height: function (element) {
|
175
|
+
return element.prop('scrollHeight');
|
176
|
+
},
|
177
|
+
|
178
|
+
/**
|
179
|
+
* @ngdoc method
|
180
|
+
* @name hippo.theme#width
|
181
|
+
* @methodOf ui.tree.service:$helper
|
182
|
+
*
|
183
|
+
* @description
|
184
|
+
* Get the width of an element.
|
185
|
+
*
|
186
|
+
* @param {Object} element Angular element.
|
187
|
+
* @returns {String} Width
|
188
|
+
*/
|
189
|
+
width: function (element) {
|
190
|
+
return element.prop('scrollWidth');
|
191
|
+
},
|
192
|
+
|
193
|
+
/**
|
194
|
+
* @ngdoc method
|
195
|
+
* @name hippo.theme#offset
|
196
|
+
* @methodOf ui.nestedSortable.service:$helper
|
197
|
+
*
|
198
|
+
* @description
|
199
|
+
* Get the offset values of an element.
|
200
|
+
*
|
201
|
+
* @param {Object} element Angular element.
|
202
|
+
* @returns {Object} Object with properties width, height, top and left
|
203
|
+
*/
|
204
|
+
offset: function (element) {
|
205
|
+
var boundingClientRect = element[0].getBoundingClientRect();
|
206
|
+
|
207
|
+
return {
|
208
|
+
width: element.prop('offsetWidth'),
|
209
|
+
height: element.prop('offsetHeight'),
|
210
|
+
top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
|
211
|
+
left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
|
212
|
+
};
|
213
|
+
},
|
214
|
+
|
215
|
+
/**
|
216
|
+
* @ngdoc method
|
217
|
+
* @name hippo.theme#positionStarted
|
218
|
+
* @methodOf ui.tree.service:$helper
|
219
|
+
*
|
220
|
+
* @description
|
221
|
+
* Get the start position of the target element according to the provided event properties.
|
222
|
+
*
|
223
|
+
* @param {Object} e Event
|
224
|
+
* @param {Object} target Target element
|
225
|
+
* @returns {Object} Object with properties offsetX, offsetY, startX, startY, nowX and dirX.
|
226
|
+
*/
|
227
|
+
positionStarted: function (e, target) {
|
228
|
+
var pos = {};
|
229
|
+
pos.offsetX = e.pageX - this.offset(target).left;
|
230
|
+
pos.offsetY = e.pageY - this.offset(target).top;
|
231
|
+
pos.startX = pos.lastX = e.pageX;
|
232
|
+
pos.startY = pos.lastY = e.pageY;
|
233
|
+
pos.nowX = pos.nowY = pos.distX = pos.distY = pos.dirAx = 0;
|
234
|
+
pos.dirX = pos.dirY = pos.lastDirX = pos.lastDirY = pos.distAxX = pos.distAxY = 0;
|
235
|
+
return pos;
|
236
|
+
},
|
237
|
+
|
238
|
+
positionMoved: function (e, pos, firstMoving) {
|
239
|
+
// mouse position last events
|
240
|
+
pos.lastX = pos.nowX;
|
241
|
+
pos.lastY = pos.nowY;
|
242
|
+
|
243
|
+
// mouse position this events
|
244
|
+
pos.nowX = e.pageX;
|
245
|
+
pos.nowY = e.pageY;
|
246
|
+
|
247
|
+
// distance mouse moved between events
|
248
|
+
pos.distX = pos.nowX - pos.lastX;
|
249
|
+
pos.distY = pos.nowY - pos.lastY;
|
250
|
+
|
251
|
+
// direction mouse was moving
|
252
|
+
pos.lastDirX = pos.dirX;
|
253
|
+
pos.lastDirY = pos.dirY;
|
254
|
+
|
255
|
+
// direction mouse is now moving (on both axis)
|
256
|
+
pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1;
|
257
|
+
pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1;
|
258
|
+
|
259
|
+
// axis mouse is now moving on
|
260
|
+
var newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0;
|
261
|
+
|
262
|
+
// do nothing on first move
|
263
|
+
if (firstMoving) {
|
264
|
+
pos.dirAx = newAx;
|
265
|
+
pos.moving = true;
|
266
|
+
return;
|
267
|
+
}
|
268
|
+
|
269
|
+
// calc distance moved on this axis (and direction)
|
270
|
+
if (pos.dirAx !== newAx) {
|
271
|
+
pos.distAxX = 0;
|
272
|
+
pos.distAxY = 0;
|
273
|
+
} else {
|
274
|
+
pos.distAxX += Math.abs(pos.distX);
|
275
|
+
if (pos.dirX !== 0 && pos.dirX !== pos.lastDirX) {
|
276
|
+
pos.distAxX = 0;
|
277
|
+
}
|
278
|
+
|
279
|
+
pos.distAxY += Math.abs(pos.distY);
|
280
|
+
if (pos.dirY !== 0 && pos.dirY !== pos.lastDirY) {
|
281
|
+
pos.distAxY = 0;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
pos.dirAx = newAx;
|
286
|
+
}
|
287
|
+
};
|
288
|
+
}
|
289
|
+
]);
|
290
|
+
|
291
|
+
})();
|
292
|
+
(function () {
|
293
|
+
'use strict';
|
294
|
+
|
295
|
+
angular.module('ui.tree')
|
296
|
+
|
297
|
+
.controller('TreeController', ['$scope', '$element', '$attrs', 'treeConfig',
|
298
|
+
function ($scope, $element, $attrs, treeConfig) {
|
299
|
+
this.scope = $scope;
|
300
|
+
|
301
|
+
$scope.$element = $element;
|
302
|
+
$scope.$nodesScope = null; // root nodes
|
303
|
+
$scope.$type = 'uiTree';
|
304
|
+
$scope.$emptyElm = null;
|
305
|
+
$scope.$callbacks = null;
|
306
|
+
|
307
|
+
$scope.dragEnabled = true;
|
308
|
+
$scope.emptyPlaceHolderEnabled = true;
|
309
|
+
$scope.maxDepth = 0;
|
310
|
+
$scope.dragDelay = 0;
|
311
|
+
|
312
|
+
// Check if it's a empty tree
|
313
|
+
$scope.isEmpty = function() {
|
314
|
+
return ($scope.$nodesScope && $scope.$nodesScope.$modelValue
|
315
|
+
&& $scope.$nodesScope.$modelValue.length === 0);
|
316
|
+
};
|
317
|
+
|
318
|
+
// add placeholder to empty tree
|
319
|
+
$scope.place = function(placeElm) {
|
320
|
+
$scope.$nodesScope.$element.append(placeElm);
|
321
|
+
$scope.$emptyElm.remove();
|
322
|
+
};
|
323
|
+
|
324
|
+
$scope.resetEmptyElement = function() {
|
325
|
+
if ($scope.$nodesScope.$modelValue.length === 0 &&
|
326
|
+
$scope.emptyPlaceHolderEnabled) {
|
327
|
+
$element.append($scope.$emptyElm);
|
328
|
+
} else {
|
329
|
+
$scope.$emptyElm.remove();
|
330
|
+
}
|
331
|
+
};
|
332
|
+
|
333
|
+
var collapseOrExpand = function(scope, collapsed) {
|
334
|
+
var nodes = scope.childNodes();
|
335
|
+
for (var i = 0; i < nodes.length; i++) {
|
336
|
+
collapsed ? nodes[i].collapse() : nodes[i].expand();
|
337
|
+
var subScope = nodes[i].$childNodesScope;
|
338
|
+
if (subScope) {
|
339
|
+
collapseOrExpand(subScope, collapsed);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
};
|
343
|
+
|
344
|
+
$scope.collapseAll = function() {
|
345
|
+
collapseOrExpand($scope.$nodesScope, true);
|
346
|
+
};
|
347
|
+
|
348
|
+
$scope.expandAll = function() {
|
349
|
+
collapseOrExpand($scope.$nodesScope, false);
|
350
|
+
};
|
351
|
+
|
352
|
+
}
|
353
|
+
]);
|
354
|
+
})();
|
355
|
+
|
356
|
+
(function () {
|
357
|
+
'use strict';
|
358
|
+
|
359
|
+
angular.module('ui.tree')
|
360
|
+
|
361
|
+
.controller('TreeNodesController', ['$scope', '$element', 'treeConfig',
|
362
|
+
function ($scope, $element, treeConfig) {
|
363
|
+
this.scope = $scope;
|
364
|
+
|
365
|
+
$scope.$element = $element;
|
366
|
+
$scope.$modelValue = null;
|
367
|
+
$scope.$nodeScope = null; // the scope of node which the nodes belongs to
|
368
|
+
$scope.$treeScope = null;
|
369
|
+
$scope.$type = 'uiTreeNodes';
|
370
|
+
$scope.$nodesMap = {};
|
371
|
+
|
372
|
+
$scope.nodrop = false;
|
373
|
+
$scope.maxDepth = 0;
|
374
|
+
|
375
|
+
$scope.initSubNode = function(subNode) {
|
376
|
+
if(!subNode.$modelValue) return null;
|
377
|
+
$scope.$nodesMap[subNode.$modelValue.$$hashKey] = subNode;
|
378
|
+
};
|
379
|
+
|
380
|
+
$scope.destroySubNode = function(subNode) {
|
381
|
+
if(!subNode.$modelValue) return null;
|
382
|
+
$scope.$nodesMap[subNode.$modelValue.$$hashKey] = null;
|
383
|
+
};
|
384
|
+
|
385
|
+
$scope.accept = function(sourceNode, destIndex) {
|
386
|
+
return $scope.$treeScope.$callbacks.accept(sourceNode, $scope, destIndex);
|
387
|
+
};
|
388
|
+
|
389
|
+
$scope.beforeDrag = function(sourceNode) {
|
390
|
+
return $scope.$treeScope.$callbacks.beforeDrag(sourceNode);
|
391
|
+
};
|
392
|
+
|
393
|
+
$scope.isParent = function(node) {
|
394
|
+
return node.$parentNodesScope == $scope;
|
395
|
+
};
|
396
|
+
|
397
|
+
$scope.hasChild = function() {
|
398
|
+
return $scope.$modelValue.length > 0;
|
399
|
+
};
|
400
|
+
|
401
|
+
$scope.safeApply = function(fn) {
|
402
|
+
var phase = this.$root.$$phase;
|
403
|
+
if(phase == '$apply' || phase == '$digest') {
|
404
|
+
if(fn && (typeof(fn) === 'function')) {
|
405
|
+
fn();
|
406
|
+
}
|
407
|
+
} else {
|
408
|
+
this.$apply(fn);
|
409
|
+
}
|
410
|
+
};
|
411
|
+
|
412
|
+
$scope.removeNode = function(node) {
|
413
|
+
var index = $scope.$modelValue.indexOf(node.$modelValue);
|
414
|
+
if (index > -1) {
|
415
|
+
$scope.safeApply(function() {
|
416
|
+
$scope.$modelValue.splice(index, 1)[0];
|
417
|
+
});
|
418
|
+
return node;
|
419
|
+
}
|
420
|
+
return null;
|
421
|
+
};
|
422
|
+
|
423
|
+
$scope.insertNode = function(index, nodeData) {
|
424
|
+
$scope.safeApply(function() {
|
425
|
+
$scope.$modelValue.splice(index, 0, nodeData);
|
426
|
+
});
|
427
|
+
};
|
428
|
+
|
429
|
+
$scope.childNodes = function() {
|
430
|
+
var nodes = [];
|
431
|
+
if ($scope.$modelValue) {
|
432
|
+
for (var i = 0; i < $scope.$modelValue.length; i++) {
|
433
|
+
nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
return nodes;
|
437
|
+
};
|
438
|
+
|
439
|
+
$scope.depth = function() {
|
440
|
+
if ($scope.$nodeScope) {
|
441
|
+
return $scope.$nodeScope.depth();
|
442
|
+
}
|
443
|
+
return 0; // if it has no $nodeScope, it's root
|
444
|
+
};
|
445
|
+
|
446
|
+
// check if depth limit has reached
|
447
|
+
$scope.outOfDepth = function(sourceNode) {
|
448
|
+
var maxDepth = $scope.maxDepth || $scope.$treeScope.maxDepth;
|
449
|
+
if (maxDepth > 0) {
|
450
|
+
return $scope.depth() + sourceNode.maxSubDepth() + 1 > maxDepth;
|
451
|
+
}
|
452
|
+
return false;
|
453
|
+
};
|
454
|
+
|
455
|
+
}
|
456
|
+
]);
|
457
|
+
})();
|
458
|
+
(function () {
|
459
|
+
'use strict';
|
460
|
+
|
461
|
+
angular.module('ui.tree')
|
462
|
+
|
463
|
+
.controller('TreeNodeController', ['$scope', '$element', '$attrs', 'treeConfig',
|
464
|
+
function ($scope, $element, $attrs, treeConfig) {
|
465
|
+
this.scope = $scope;
|
466
|
+
|
467
|
+
$scope.$element = $element;
|
468
|
+
$scope.$modelValue = null; // Model value for node;
|
469
|
+
$scope.$parentNodeScope = null; // uiTreeNode Scope of parent node;
|
470
|
+
$scope.$childNodesScope = null; // uiTreeNodes Scope of child nodes.
|
471
|
+
$scope.$parentNodesScope = null; // uiTreeNodes Scope of parent nodes.
|
472
|
+
$scope.$treeScope = null; // uiTree scope
|
473
|
+
$scope.$handleScope = null; // it's handle scope
|
474
|
+
$scope.$type = 'uiTreeNode';
|
475
|
+
$scope.$$apply = false; //
|
476
|
+
|
477
|
+
$scope.collapsed = false;
|
478
|
+
|
479
|
+
$scope.init = function(controllersArr) {
|
480
|
+
var treeNodesCtrl = controllersArr[0];
|
481
|
+
$scope.$treeScope = controllersArr[1] ? controllersArr[1].scope : null;
|
482
|
+
|
483
|
+
// find the scope of it's parent node
|
484
|
+
$scope.$parentNodeScope = treeNodesCtrl.scope.$nodeScope;
|
485
|
+
// modelValue for current node
|
486
|
+
$scope.$modelValue = treeNodesCtrl.scope.$modelValue[$scope.$index];
|
487
|
+
$scope.$parentNodesScope = treeNodesCtrl.scope;
|
488
|
+
treeNodesCtrl.scope.initSubNode($scope); // init sub nodes
|
489
|
+
|
490
|
+
$element.on('$destroy', function() {
|
491
|
+
treeNodesCtrl.scope.destroySubNode($scope); // destroy sub nodes
|
492
|
+
});
|
493
|
+
};
|
494
|
+
|
495
|
+
$scope.index = function() {
|
496
|
+
return $scope.$parentNodesScope.$modelValue.indexOf($scope.$modelValue);
|
497
|
+
};
|
498
|
+
|
499
|
+
$scope.dragEnabled = function() {
|
500
|
+
return !($scope.$treeScope && !$scope.$treeScope.dragEnabled);
|
501
|
+
};
|
502
|
+
|
503
|
+
$scope.isSibling = function(targetNode) {
|
504
|
+
return $scope.$parentNodesScope == targetNode.$parentNodesScope;
|
505
|
+
};
|
506
|
+
|
507
|
+
$scope.isChild = function(targetNode) {
|
508
|
+
var nodes = $scope.childNodes();
|
509
|
+
return nodes && nodes.indexOf(targetNode) > -1;
|
510
|
+
};
|
511
|
+
|
512
|
+
$scope.prev = function() {
|
513
|
+
var index = $scope.index();
|
514
|
+
if (index > 0) {
|
515
|
+
return $scope.siblings()[index - 1];
|
516
|
+
}
|
517
|
+
return null;
|
518
|
+
};
|
519
|
+
|
520
|
+
$scope.siblings = function() {
|
521
|
+
return $scope.$parentNodesScope.childNodes();
|
522
|
+
};
|
523
|
+
|
524
|
+
$scope.childNodesCount = function() {
|
525
|
+
return $scope.childNodes() ? $scope.childNodes().length : 0;
|
526
|
+
};
|
527
|
+
|
528
|
+
$scope.hasChild = function() {
|
529
|
+
return $scope.childNodesCount() > 0;
|
530
|
+
};
|
531
|
+
|
532
|
+
$scope.childNodes = function() {
|
533
|
+
return $scope.$childNodesScope && $scope.$childNodesScope.$modelValue ?
|
534
|
+
$scope.$childNodesScope.childNodes() :
|
535
|
+
null;
|
536
|
+
};
|
537
|
+
|
538
|
+
$scope.accept = function(sourceNode, destIndex) {
|
539
|
+
return $scope.$childNodesScope &&
|
540
|
+
$scope.$childNodesScope.$modelValue &&
|
541
|
+
$scope.$childNodesScope.accept(sourceNode, destIndex);
|
542
|
+
};
|
543
|
+
|
544
|
+
$scope.removeNode = function(){
|
545
|
+
var node = $scope.remove();
|
546
|
+
$scope.$callbacks.removed(node);
|
547
|
+
return node;
|
548
|
+
};
|
549
|
+
|
550
|
+
$scope.remove = function() {
|
551
|
+
return $scope.$parentNodesScope.removeNode($scope);
|
552
|
+
};
|
553
|
+
|
554
|
+
$scope.toggle = function() {
|
555
|
+
$scope.collapsed = !$scope.collapsed;
|
556
|
+
};
|
557
|
+
|
558
|
+
$scope.collapse = function() {
|
559
|
+
$scope.collapsed = true;
|
560
|
+
};
|
561
|
+
|
562
|
+
$scope.expand = function() {
|
563
|
+
$scope.collapsed = false;
|
564
|
+
};
|
565
|
+
|
566
|
+
$scope.depth = function() {
|
567
|
+
var parentNode = $scope.$parentNodeScope;
|
568
|
+
if (parentNode) {
|
569
|
+
return parentNode.depth() + 1;
|
570
|
+
}
|
571
|
+
return 1;
|
572
|
+
};
|
573
|
+
|
574
|
+
var subDepth = 0;
|
575
|
+
var countSubDepth = function(scope) {
|
576
|
+
var count = 0;
|
577
|
+
var nodes = scope.childNodes();
|
578
|
+
for (var i = 0; i < nodes.length; i++) {
|
579
|
+
var childNodes = nodes[i].$childNodesScope;
|
580
|
+
if (childNodes) {
|
581
|
+
count = 1;
|
582
|
+
countSubDepth(childNodes);
|
583
|
+
}
|
584
|
+
}
|
585
|
+
subDepth += count;
|
586
|
+
};
|
587
|
+
|
588
|
+
$scope.maxSubDepth = function() {
|
589
|
+
subDepth = 0;
|
590
|
+
if ($scope.$childNodesScope) {
|
591
|
+
countSubDepth($scope.$childNodesScope);
|
592
|
+
}
|
593
|
+
return subDepth;
|
594
|
+
};
|
595
|
+
|
596
|
+
}
|
597
|
+
]);
|
598
|
+
})();
|
599
|
+
|
600
|
+
(function () {
|
601
|
+
'use strict';
|
602
|
+
|
603
|
+
angular.module('ui.tree')
|
604
|
+
|
605
|
+
.controller('TreeHandleController', ['$scope', '$element', '$attrs', 'treeConfig',
|
606
|
+
function ($scope, $element, $attrs, treeConfig) {
|
607
|
+
this.scope = $scope;
|
608
|
+
|
609
|
+
$scope.$element = $element;
|
610
|
+
$scope.$nodeScope = null;
|
611
|
+
$scope.$type = 'uiTreeHandle';
|
612
|
+
|
613
|
+
}
|
614
|
+
]);
|
615
|
+
})();
|
616
|
+
|
617
|
+
(function () {
|
618
|
+
'use strict';
|
619
|
+
|
620
|
+
angular.module('ui.tree')
|
621
|
+
.directive('uiTree', [ 'treeConfig', '$window',
|
622
|
+
function(treeConfig, $window) {
|
623
|
+
return {
|
624
|
+
restrict: 'A',
|
625
|
+
scope: true,
|
626
|
+
controller: 'TreeController',
|
627
|
+
link: function(scope, element, attrs) {
|
628
|
+
var callbacks = {
|
629
|
+
accept: null,
|
630
|
+
beforeDrag: null
|
631
|
+
};
|
632
|
+
|
633
|
+
var config = {};
|
634
|
+
angular.extend(config, treeConfig);
|
635
|
+
if (config.treeClass) {
|
636
|
+
element.addClass(config.treeClass);
|
637
|
+
}
|
638
|
+
|
639
|
+
scope.$emptyElm = angular.element($window.document.createElement('div'));
|
640
|
+
if (config.emptyTreeClass) {
|
641
|
+
scope.$emptyElm.addClass(config.emptyTreeClass);
|
642
|
+
}
|
643
|
+
|
644
|
+
scope.$watch('$nodesScope.$modelValue.length', function() {
|
645
|
+
if (scope.$nodesScope.$modelValue) {
|
646
|
+
scope.resetEmptyElement();
|
647
|
+
}
|
648
|
+
}, true);
|
649
|
+
|
650
|
+
scope.$watch(attrs.dragEnabled, function(val) {
|
651
|
+
if((typeof val) == "boolean") {
|
652
|
+
scope.dragEnabled = val;
|
653
|
+
}
|
654
|
+
});
|
655
|
+
|
656
|
+
scope.$watch(attrs.emptyPlaceHolderEnabled, function(val) {
|
657
|
+
if((typeof val) == "boolean") {
|
658
|
+
scope.emptyPlaceHolderEnabled = val;
|
659
|
+
}
|
660
|
+
});
|
661
|
+
|
662
|
+
scope.$watch(attrs.maxDepth, function(val) {
|
663
|
+
if((typeof val) == "number") {
|
664
|
+
scope.maxDepth = val;
|
665
|
+
}
|
666
|
+
});
|
667
|
+
|
668
|
+
scope.$watch(attrs.dragDelay, function(val) {
|
669
|
+
if((typeof val) == "number") {
|
670
|
+
scope.dragDelay = val;
|
671
|
+
}
|
672
|
+
});
|
673
|
+
|
674
|
+
// check if the dest node can accept the dragging node
|
675
|
+
// by default, we check the 'data-nodrop' attribute in `ui-tree-nodes`
|
676
|
+
// and the 'max-depth' attribute in `ui-tree` or `ui-tree-nodes`.
|
677
|
+
// the method can be overrided
|
678
|
+
callbacks.accept = function(sourceNodeScope, destNodesScope, destIndex) {
|
679
|
+
if (destNodesScope.nodrop || destNodesScope.outOfDepth(sourceNodeScope)) {
|
680
|
+
return false;
|
681
|
+
}
|
682
|
+
return true;
|
683
|
+
};
|
684
|
+
|
685
|
+
callbacks.beforeDrag = function(sourceNodeScope) {
|
686
|
+
return true;
|
687
|
+
};
|
688
|
+
|
689
|
+
callbacks.removed = function(node){
|
690
|
+
|
691
|
+
};
|
692
|
+
|
693
|
+
callbacks.dropped = function(event) {
|
694
|
+
|
695
|
+
};
|
696
|
+
|
697
|
+
//
|
698
|
+
callbacks.dragStart = function(event) {
|
699
|
+
|
700
|
+
};
|
701
|
+
|
702
|
+
callbacks.dragMove = function(event) {
|
703
|
+
|
704
|
+
};
|
705
|
+
|
706
|
+
callbacks.dragStop = function(event) {
|
707
|
+
|
708
|
+
};
|
709
|
+
|
710
|
+
callbacks.beforeDrop = function(event) {
|
711
|
+
|
712
|
+
};
|
713
|
+
|
714
|
+
scope.$watch(attrs.uiTree, function(newVal, oldVal){
|
715
|
+
angular.forEach(newVal, function(value, key){
|
716
|
+
if (callbacks[key]) {
|
717
|
+
if (typeof value === "function") {
|
718
|
+
callbacks[key] = value;
|
719
|
+
}
|
720
|
+
}
|
721
|
+
});
|
722
|
+
|
723
|
+
scope.$callbacks = callbacks;
|
724
|
+
}, true);
|
725
|
+
|
726
|
+
|
727
|
+
}
|
728
|
+
};
|
729
|
+
}
|
730
|
+
]);
|
731
|
+
})();
|
732
|
+
|
733
|
+
(function () {
|
734
|
+
'use strict';
|
735
|
+
|
736
|
+
angular.module('ui.tree')
|
737
|
+
.directive('uiTreeNodes', [ 'treeConfig', '$window',
|
738
|
+
function(treeConfig) {
|
739
|
+
return {
|
740
|
+
require: ['ngModel', '?^uiTreeNode', '^uiTree'],
|
741
|
+
restrict: 'A',
|
742
|
+
scope: true,
|
743
|
+
controller: 'TreeNodesController',
|
744
|
+
link: function(scope, element, attrs, controllersArr) {
|
745
|
+
|
746
|
+
var config = {};
|
747
|
+
angular.extend(config, treeConfig);
|
748
|
+
if (config.nodesClass) {
|
749
|
+
element.addClass(config.nodesClass);
|
750
|
+
}
|
751
|
+
|
752
|
+
var ngModel = controllersArr[0];
|
753
|
+
var treeNodeCtrl = controllersArr[1];
|
754
|
+
var treeCtrl = controllersArr[2];
|
755
|
+
if (treeNodeCtrl) {
|
756
|
+
treeNodeCtrl.scope.$childNodesScope = scope;
|
757
|
+
scope.$nodeScope = treeNodeCtrl.scope;
|
758
|
+
}
|
759
|
+
else { // find the root nodes if there is no parent node and have a parent ui-tree
|
760
|
+
treeCtrl.scope.$nodesScope = scope;
|
761
|
+
}
|
762
|
+
scope.$treeScope = treeCtrl.scope;
|
763
|
+
|
764
|
+
if (ngModel) {
|
765
|
+
ngModel.$render = function() {
|
766
|
+
if (!ngModel.$modelValue || !angular.isArray(ngModel.$modelValue)) {
|
767
|
+
scope.$modelValue = [];
|
768
|
+
}
|
769
|
+
scope.$modelValue = ngModel.$modelValue;
|
770
|
+
};
|
771
|
+
}
|
772
|
+
|
773
|
+
scope.$watch(attrs.maxDepth, function(val) {
|
774
|
+
if((typeof val) == "number") {
|
775
|
+
scope.maxDepth = val;
|
776
|
+
}
|
777
|
+
});
|
778
|
+
|
779
|
+
attrs.$observe('nodrop', function(val) {
|
780
|
+
scope.nodrop = ((typeof val) != "undefined");
|
781
|
+
});
|
782
|
+
|
783
|
+
attrs.$observe('horizontal', function(val) {
|
784
|
+
scope.horizontal = ((typeof val) != "undefined");
|
785
|
+
});
|
786
|
+
|
787
|
+
}
|
788
|
+
};
|
789
|
+
}
|
790
|
+
]);
|
791
|
+
})();
|
792
|
+
|
793
|
+
(function () {
|
794
|
+
'use strict';
|
795
|
+
|
796
|
+
angular.module('ui.tree')
|
797
|
+
|
798
|
+
.directive('uiTreeNode', ['treeConfig', '$uiTreeHelper', '$window', '$document','$timeout',
|
799
|
+
function (treeConfig, $uiTreeHelper, $window, $document, $timeout) {
|
800
|
+
return {
|
801
|
+
require: ['^uiTreeNodes', '^uiTree'],
|
802
|
+
restrict: 'A',
|
803
|
+
controller: 'TreeNodeController',
|
804
|
+
link: function(scope, element, attrs, controllersArr) {
|
805
|
+
var config = {};
|
806
|
+
angular.extend(config, treeConfig);
|
807
|
+
if (config.nodeClass) {
|
808
|
+
element.addClass(config.nodeClass);
|
809
|
+
}
|
810
|
+
scope.init(controllersArr);
|
811
|
+
|
812
|
+
scope.collapsed = !!$uiTreeHelper.getNodeAttribute(scope, 'collapsed');
|
813
|
+
|
814
|
+
scope.$watch(attrs.collapsed, function(val) {
|
815
|
+
if((typeof val) == "boolean") {
|
816
|
+
scope.collapsed = val;
|
817
|
+
}
|
818
|
+
});
|
819
|
+
|
820
|
+
scope.$watch('collapsed', function(val) {
|
821
|
+
$uiTreeHelper.setNodeAttribute(scope, 'collapsed', val);
|
822
|
+
attrs.$set('collapsed', val);
|
823
|
+
});
|
824
|
+
|
825
|
+
var hasTouch = 'ontouchstart' in window;
|
826
|
+
// todo startPos is unused
|
827
|
+
var startPos, firstMoving, dragInfo, pos;
|
828
|
+
var placeElm, hiddenPlaceElm, dragElm;
|
829
|
+
var treeScope = null;
|
830
|
+
var elements; // As a parameter for callbacks
|
831
|
+
var dragDelaying = true;
|
832
|
+
var dragStarted = false;
|
833
|
+
var dragTimer = null;
|
834
|
+
var body = document.body,
|
835
|
+
html = document.documentElement,
|
836
|
+
document_height,
|
837
|
+
document_width;
|
838
|
+
|
839
|
+
var dragStart = function(e) {
|
840
|
+
if (!hasTouch && (e.button == 2 || e.which == 3)) {
|
841
|
+
// disable right click
|
842
|
+
return;
|
843
|
+
}
|
844
|
+
if (e.uiTreeDragging || (e.originalEvent && e.originalEvent.uiTreeDragging)) { // event has already fired in other scope.
|
845
|
+
return;
|
846
|
+
}
|
847
|
+
|
848
|
+
// the element which is clicked.
|
849
|
+
var eventElm = angular.element(e.target);
|
850
|
+
var eventScope = eventElm.scope();
|
851
|
+
if (!eventScope || !eventScope.$type) {
|
852
|
+
return;
|
853
|
+
}
|
854
|
+
if (eventScope.$type != 'uiTreeNode'
|
855
|
+
&& eventScope.$type != 'uiTreeHandle') { // Check if it is a node or a handle
|
856
|
+
return;
|
857
|
+
}
|
858
|
+
if (eventScope.$type == 'uiTreeNode'
|
859
|
+
&& eventScope.$handleScope) { // If the node has a handle, then it should be clicked by the handle
|
860
|
+
return;
|
861
|
+
}
|
862
|
+
|
863
|
+
var eventElmTagName = eventElm.prop('tagName').toLowerCase();
|
864
|
+
if (eventElmTagName == 'input' ||
|
865
|
+
eventElmTagName == 'textarea' ||
|
866
|
+
eventElmTagName == 'button' ||
|
867
|
+
eventElmTagName == 'select') { // if it's a input or button, ignore it
|
868
|
+
return;
|
869
|
+
}
|
870
|
+
|
871
|
+
// check if it or it's parents has a 'data-nodrag' attribute
|
872
|
+
while (eventElm && eventElm[0] && eventElm[0] != element) {
|
873
|
+
if ($uiTreeHelper.nodrag(eventElm)) { // if the node mark as `nodrag`, DONOT drag it.
|
874
|
+
return;
|
875
|
+
}
|
876
|
+
eventElm = eventElm.parent();
|
877
|
+
}
|
878
|
+
|
879
|
+
if (!scope.beforeDrag(scope)){
|
880
|
+
return;
|
881
|
+
}
|
882
|
+
|
883
|
+
e.uiTreeDragging = true; // stop event bubbling
|
884
|
+
if (e.originalEvent) {
|
885
|
+
e.originalEvent.uiTreeDragging = true;
|
886
|
+
}
|
887
|
+
e.preventDefault();
|
888
|
+
var eventObj = $uiTreeHelper.eventObj(e);
|
889
|
+
|
890
|
+
firstMoving = true;
|
891
|
+
dragInfo = $uiTreeHelper.dragInfo(scope);
|
892
|
+
|
893
|
+
var tagName = scope.$element.prop('tagName');
|
894
|
+
if (tagName.toLowerCase() === 'tr') {
|
895
|
+
placeElm = angular.element($window.document.createElement(tagName));
|
896
|
+
var tdElm = angular.element($window.document.createElement('td'))
|
897
|
+
.addClass(config.placeHolderClass);
|
898
|
+
placeElm.append(tdElm);
|
899
|
+
} else {
|
900
|
+
placeElm = angular.element($window.document.createElement(tagName))
|
901
|
+
.addClass(config.placeHolderClass);
|
902
|
+
}
|
903
|
+
hiddenPlaceElm = angular.element($window.document.createElement(tagName));
|
904
|
+
if (config.hiddenClass) {
|
905
|
+
hiddenPlaceElm.addClass(config.hiddenClass);
|
906
|
+
}
|
907
|
+
pos = $uiTreeHelper.positionStarted(eventObj, scope.$element);
|
908
|
+
placeElm.css('height', $uiTreeHelper.height(scope.$element) + 'px');
|
909
|
+
placeElm.css('width', $uiTreeHelper.width(scope.$element) + 'px');
|
910
|
+
dragElm = angular.element($window.document.createElement(scope.$parentNodesScope.$element.prop('tagName')))
|
911
|
+
.addClass(scope.$parentNodesScope.$element.attr('class')).addClass(config.dragClass);
|
912
|
+
dragElm.css('width', $uiTreeHelper.width(scope.$element) + 'px');
|
913
|
+
dragElm.css('z-index', 9999);
|
914
|
+
|
915
|
+
// Prevents cursor to change rapidly in Opera 12.16 and IE when dragging an element
|
916
|
+
var hStyle = (scope.$element[0].querySelector('.angular-ui-tree-handle') || scope.$element[0]).currentStyle;
|
917
|
+
if (hStyle) {
|
918
|
+
document.body.setAttribute('ui-tree-cursor', $document.find('body').css('cursor') || '');
|
919
|
+
$document.find('body').css({'cursor': hStyle.cursor + '!important'});
|
920
|
+
}
|
921
|
+
|
922
|
+
scope.$element.after(placeElm);
|
923
|
+
scope.$element.after(hiddenPlaceElm);
|
924
|
+
dragElm.append(scope.$element);
|
925
|
+
$document.find('body').append(dragElm);
|
926
|
+
dragElm.css({
|
927
|
+
'left' : eventObj.pageX - pos.offsetX + 'px',
|
928
|
+
'top' : eventObj.pageY - pos.offsetY + 'px'
|
929
|
+
});
|
930
|
+
elements = {
|
931
|
+
placeholder: placeElm,
|
932
|
+
dragging: dragElm
|
933
|
+
};
|
934
|
+
|
935
|
+
angular.element($document).bind('touchend', dragEndEvent);
|
936
|
+
angular.element($document).bind('touchcancel', dragEndEvent);
|
937
|
+
angular.element($document).bind('touchmove', dragMoveEvent);
|
938
|
+
angular.element($document).bind('mouseup', dragEndEvent);
|
939
|
+
angular.element($document).bind('mousemove', dragMoveEvent);
|
940
|
+
angular.element($document).bind('mouseleave', dragCancelEvent);
|
941
|
+
|
942
|
+
document_height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
|
943
|
+
document_width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
|
944
|
+
};
|
945
|
+
|
946
|
+
var dragMove = function(e) {
|
947
|
+
if (!dragStarted) {
|
948
|
+
if (!dragDelaying) {
|
949
|
+
dragStarted = true;
|
950
|
+
scope.$apply(function() {
|
951
|
+
scope.$callbacks.dragStart(dragInfo.eventArgs(elements, pos));
|
952
|
+
});
|
953
|
+
}
|
954
|
+
return;
|
955
|
+
}
|
956
|
+
|
957
|
+
var eventObj = $uiTreeHelper.eventObj(e);
|
958
|
+
var prev, leftElmPos, topElmPos;
|
959
|
+
|
960
|
+
if (dragElm) {
|
961
|
+
e.preventDefault();
|
962
|
+
|
963
|
+
if ($window.getSelection) {
|
964
|
+
$window.getSelection().removeAllRanges();
|
965
|
+
} else if ($window.document.selection) {
|
966
|
+
$window.document.selection.empty();
|
967
|
+
}
|
968
|
+
|
969
|
+
leftElmPos = eventObj.pageX - pos.offsetX;
|
970
|
+
topElmPos = eventObj.pageY - pos.offsetY;
|
971
|
+
|
972
|
+
//dragElm can't leave the screen on the left
|
973
|
+
if(leftElmPos < 0){
|
974
|
+
leftElmPos = 0;
|
975
|
+
}
|
976
|
+
|
977
|
+
//dragElm can't leave the screen on the top
|
978
|
+
if(topElmPos < 0){
|
979
|
+
topElmPos = 0;
|
980
|
+
}
|
981
|
+
|
982
|
+
//dragElm can't leave the screen on the bottom
|
983
|
+
if ((topElmPos + 10) > document_height){
|
984
|
+
topElmPos = document_height - 10;
|
985
|
+
}
|
986
|
+
|
987
|
+
//dragElm can't leave the screen on the right
|
988
|
+
if((leftElmPos + 10) > document_width) {
|
989
|
+
leftElmPos = document_width - 10;
|
990
|
+
}
|
991
|
+
|
992
|
+
dragElm.css({
|
993
|
+
'left': leftElmPos + 'px',
|
994
|
+
'top': topElmPos + 'px'
|
995
|
+
});
|
996
|
+
|
997
|
+
var top_scroll = window.pageYOffset || $window.document.documentElement.scrollTop;
|
998
|
+
var bottom_scroll = top_scroll + (window.innerHeight || $window.document.clientHeight || $window.document.clientHeight);
|
999
|
+
|
1000
|
+
// to scroll down if cursor y-position is greater than the bottom position the vertical scroll
|
1001
|
+
if (bottom_scroll < eventObj.pageY && bottom_scroll <= document_height) {
|
1002
|
+
window.scrollBy(0, 10);
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
// to scroll top if cursor y-position is less than the top position the vertical scroll
|
1006
|
+
if (top_scroll > eventObj.pageY) {
|
1007
|
+
window.scrollBy(0, -10);
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
$uiTreeHelper.positionMoved(e, pos, firstMoving);
|
1011
|
+
if (firstMoving) {
|
1012
|
+
firstMoving = false;
|
1013
|
+
return;
|
1014
|
+
}
|
1015
|
+
|
1016
|
+
// move horizontal
|
1017
|
+
if (pos.dirAx && pos.distAxX >= config.levelThreshold) {
|
1018
|
+
pos.distAxX = 0;
|
1019
|
+
|
1020
|
+
// increase horizontal level if previous sibling exists and is not collapsed
|
1021
|
+
if (pos.distX > 0) {
|
1022
|
+
prev = dragInfo.prev();
|
1023
|
+
if (prev && !prev.collapsed
|
1024
|
+
&& prev.accept(scope, prev.childNodesCount())) {
|
1025
|
+
prev.$childNodesScope.$element.append(placeElm);
|
1026
|
+
dragInfo.moveTo(prev.$childNodesScope, prev.childNodes(), prev.childNodesCount());
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
// decrease horizontal level
|
1031
|
+
if (pos.distX < 0) {
|
1032
|
+
// we can't decrease a level if an item preceeds the current one
|
1033
|
+
var next = dragInfo.next();
|
1034
|
+
if (!next) {
|
1035
|
+
var target = dragInfo.parentNode(); // As a sibling of it's parent node
|
1036
|
+
if (target
|
1037
|
+
&& target.$parentNodesScope.accept(scope, target.index() + 1)) {
|
1038
|
+
target.$element.after(placeElm);
|
1039
|
+
dragInfo.moveTo(target.$parentNodesScope, target.siblings(), target.index() + 1);
|
1040
|
+
}
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
// check if add it as a child node first
|
1046
|
+
// todo decrease is unused
|
1047
|
+
var decrease = ($uiTreeHelper.offset(dragElm).left - $uiTreeHelper.offset(placeElm).left) >= config.threshold;
|
1048
|
+
var targetX = eventObj.pageX - $window.document.body.scrollLeft;
|
1049
|
+
var targetY = eventObj.pageY - (window.pageYOffset || $window.document.documentElement.scrollTop);
|
1050
|
+
|
1051
|
+
// Select the drag target. Because IE does not support CSS 'pointer-events: none', it will always
|
1052
|
+
// pick the drag element itself as the target. To prevent this, we hide the drag element while
|
1053
|
+
// selecting the target.
|
1054
|
+
var displayElm;
|
1055
|
+
if (angular.isFunction(dragElm.hide)) {
|
1056
|
+
dragElm.hide();
|
1057
|
+
}else{
|
1058
|
+
displayElm = dragElm[0].style.display;
|
1059
|
+
dragElm[0].style.display = "none";
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
// when using elementFromPoint() inside an iframe, you have to call
|
1063
|
+
// elementFromPoint() twice to make sure IE8 returns the correct value
|
1064
|
+
$window.document.elementFromPoint(targetX, targetY);
|
1065
|
+
|
1066
|
+
var targetElm = angular.element($window.document.elementFromPoint(targetX, targetY));
|
1067
|
+
if (angular.isFunction(dragElm.show)) {
|
1068
|
+
dragElm.show();
|
1069
|
+
}else{
|
1070
|
+
dragElm[0].style.display = displayElm;
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
// move vertical
|
1074
|
+
if (!pos.dirAx) {
|
1075
|
+
var targetBefore, targetNode;
|
1076
|
+
// check it's new position
|
1077
|
+
targetNode = targetElm.scope();
|
1078
|
+
var isEmpty = false;
|
1079
|
+
if (!targetNode) {
|
1080
|
+
return;
|
1081
|
+
}
|
1082
|
+
if (targetNode.$type == 'uiTree' && targetNode.dragEnabled) {
|
1083
|
+
isEmpty = targetNode.isEmpty(); // Check if it's empty tree
|
1084
|
+
}
|
1085
|
+
if (targetNode.$type == 'uiTreeHandle') {
|
1086
|
+
targetNode = targetNode.$nodeScope;
|
1087
|
+
}
|
1088
|
+
if (targetNode.$type != 'uiTreeNode'
|
1089
|
+
&& !isEmpty) { // Check if it is a uiTreeNode or it's an empty tree
|
1090
|
+
return;
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
// if placeholder move from empty tree, reset it.
|
1094
|
+
if (treeScope && placeElm.parent()[0] != treeScope.$element[0]) {
|
1095
|
+
treeScope.resetEmptyElement();
|
1096
|
+
treeScope = null;
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
if (isEmpty) { // it's an empty tree
|
1100
|
+
treeScope = targetNode;
|
1101
|
+
if (targetNode.$nodesScope.accept(scope, 0)) {
|
1102
|
+
targetNode.place(placeElm);
|
1103
|
+
dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0);
|
1104
|
+
}
|
1105
|
+
} else if (targetNode.dragEnabled()){ // drag enabled
|
1106
|
+
targetElm = targetNode.$element; // Get the element of ui-tree-node
|
1107
|
+
var targetOffset = $uiTreeHelper.offset(targetElm);
|
1108
|
+
targetBefore = targetNode.horizontal ? eventObj.pageX < (targetOffset.left + $uiTreeHelper.width(targetElm) / 2)
|
1109
|
+
: eventObj.pageY < (targetOffset.top + $uiTreeHelper.height(targetElm) / 2);
|
1110
|
+
|
1111
|
+
if (targetNode.$parentNodesScope.accept(scope, targetNode.index())) {
|
1112
|
+
if (targetBefore) {
|
1113
|
+
targetElm[0].parentNode.insertBefore(placeElm[0], targetElm[0]);
|
1114
|
+
dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index());
|
1115
|
+
} else {
|
1116
|
+
targetElm.after(placeElm);
|
1117
|
+
dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index() + 1);
|
1118
|
+
}
|
1119
|
+
}
|
1120
|
+
else if (!targetBefore && targetNode.accept(scope, targetNode.childNodesCount())) { // we have to check if it can add the dragging node as a child
|
1121
|
+
targetNode.$childNodesScope.$element.append(placeElm);
|
1122
|
+
dragInfo.moveTo(targetNode.$childNodesScope, targetNode.childNodes(), targetNode.childNodesCount());
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
scope.$apply(function() {
|
1129
|
+
scope.$callbacks.dragMove(dragInfo.eventArgs(elements, pos));
|
1130
|
+
});
|
1131
|
+
}
|
1132
|
+
};
|
1133
|
+
|
1134
|
+
var dragEnd = function(e) {
|
1135
|
+
e.preventDefault();
|
1136
|
+
|
1137
|
+
if (dragElm) {
|
1138
|
+
scope.$treeScope.$apply(function() {
|
1139
|
+
scope.$callbacks.beforeDrop(dragInfo.eventArgs(elements, pos));
|
1140
|
+
});
|
1141
|
+
// roll back elements changed
|
1142
|
+
hiddenPlaceElm.replaceWith(scope.$element);
|
1143
|
+
placeElm.remove();
|
1144
|
+
|
1145
|
+
dragElm.remove();
|
1146
|
+
dragElm = null;
|
1147
|
+
if (scope.$$apply) {
|
1148
|
+
dragInfo.apply();
|
1149
|
+
scope.$treeScope.$apply(function() {
|
1150
|
+
scope.$callbacks.dropped(dragInfo.eventArgs(elements, pos));
|
1151
|
+
});
|
1152
|
+
} else {
|
1153
|
+
bindDrag();
|
1154
|
+
}
|
1155
|
+
scope.$treeScope.$apply(function() {
|
1156
|
+
scope.$callbacks.dragStop(dragInfo.eventArgs(elements, pos));
|
1157
|
+
});
|
1158
|
+
scope.$$apply = false;
|
1159
|
+
dragInfo = null;
|
1160
|
+
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
// Restore cursor in Opera 12.16 and IE
|
1164
|
+
var oldCur = document.body.getAttribute('ui-tree-cursor');
|
1165
|
+
if (oldCur !== null) {
|
1166
|
+
$document.find('body').css({'cursor': oldCur});
|
1167
|
+
document.body.removeAttribute('ui-tree-cursor');
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
angular.element($document).unbind('touchend', dragEndEvent); // Mobile
|
1171
|
+
angular.element($document).unbind('touchcancel', dragEndEvent); // Mobile
|
1172
|
+
angular.element($document).unbind('touchmove', dragMoveEvent); // Mobile
|
1173
|
+
angular.element($document).unbind('mouseup', dragEndEvent);
|
1174
|
+
angular.element($document).unbind('mousemove', dragMoveEvent);
|
1175
|
+
angular.element($window.document.body).unbind('mouseleave', dragCancelEvent);
|
1176
|
+
};
|
1177
|
+
|
1178
|
+
var dragStartEvent = function(e) {
|
1179
|
+
if (scope.dragEnabled()) {
|
1180
|
+
dragStart(e);
|
1181
|
+
}
|
1182
|
+
};
|
1183
|
+
|
1184
|
+
var dragMoveEvent = function(e) {
|
1185
|
+
dragMove(e);
|
1186
|
+
};
|
1187
|
+
|
1188
|
+
var dragEndEvent = function(e) {
|
1189
|
+
scope.$$apply = true;
|
1190
|
+
dragEnd(e);
|
1191
|
+
};
|
1192
|
+
|
1193
|
+
var dragCancelEvent = function(e) {
|
1194
|
+
dragEnd(e);
|
1195
|
+
};
|
1196
|
+
|
1197
|
+
var bindDrag = function() {
|
1198
|
+
element.bind('touchstart mousedown', function (e) {
|
1199
|
+
dragDelaying = true;
|
1200
|
+
dragStarted = false;
|
1201
|
+
dragStartEvent(e);
|
1202
|
+
dragTimer = $timeout(function(){dragDelaying = false;}, scope.dragDelay);
|
1203
|
+
});
|
1204
|
+
element.bind('touchend touchcancel mouseup',function(){$timeout.cancel(dragTimer);});
|
1205
|
+
};
|
1206
|
+
bindDrag();
|
1207
|
+
|
1208
|
+
angular.element($window.document.body).bind("keydown", function(e) {
|
1209
|
+
if (e.keyCode == 27) {
|
1210
|
+
scope.$$apply = false;
|
1211
|
+
dragEnd(e);
|
1212
|
+
}
|
1213
|
+
});
|
1214
|
+
}
|
1215
|
+
};
|
1216
|
+
}
|
1217
|
+
]);
|
1218
|
+
|
1219
|
+
})();
|
1220
|
+
|
1221
|
+
(function () {
|
1222
|
+
'use strict';
|
1223
|
+
|
1224
|
+
angular.module('ui.tree')
|
1225
|
+
.directive('uiTreeHandle', [ 'treeConfig', '$window',
|
1226
|
+
function(treeConfig) {
|
1227
|
+
return {
|
1228
|
+
require: '^uiTreeNode',
|
1229
|
+
restrict: 'A',
|
1230
|
+
scope: true,
|
1231
|
+
controller: 'TreeHandleController',
|
1232
|
+
link: function(scope, element, attrs, treeNodeCtrl) {
|
1233
|
+
var config = {};
|
1234
|
+
angular.extend(config, treeConfig);
|
1235
|
+
if (config.handleClass) {
|
1236
|
+
element.addClass(config.handleClass);
|
1237
|
+
}
|
1238
|
+
// connect with the tree node.
|
1239
|
+
if (scope != treeNodeCtrl.scope) {
|
1240
|
+
scope.$nodeScope = treeNodeCtrl.scope;
|
1241
|
+
treeNodeCtrl.scope.$handleScope = scope;
|
1242
|
+
}
|
1243
|
+
}
|
1244
|
+
};
|
1245
|
+
}
|
1246
|
+
]);
|
1247
|
+
})();
|