(
function
() {
'use strict'
;
angular.module(
'ui.tree'
, [])
.constant(
'treeConfig'
, {
treeClass:
'angular-ui-tree'
,
emptyTreeClass:
'angular-ui-tree-empty'
,
dropzoneClass:
'angular-ui-tree-dropzone'
,
hiddenClass:
'angular-ui-tree-hidden'
,
nodesClass:
'angular-ui-tree-nodes'
,
nodeClass:
'angular-ui-tree-node'
,
handleClass:
'angular-ui-tree-handle'
,
placeholderClass:
'angular-ui-tree-placeholder'
,
dragClass:
'angular-ui-tree-drag'
,
dragThreshold: 3,
defaultCollapsed:
false
,
appendChildOnHover:
true
});
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.controller(
'TreeHandleController'
, [
'$scope'
,
'$element'
,
function
($scope, $element) {
this
.scope = $scope;
$scope.$element = $element;
$scope.$nodeScope =
null
;
$scope.$type =
'uiTreeHandle'
;
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.controller(
'TreeNodeController'
, [
'$scope'
,
'$element'
,
function
($scope, $element) {
this
.scope = $scope;
$scope.$element = $element;
$scope.$modelValue =
null
;
$scope.$parentNodeScope =
null
;
$scope.$childNodesScope =
null
;
$scope.$parentNodesScope =
null
;
$scope.$treeScope =
null
;
$scope.$handleScope =
null
;
$scope.$type = 'uiTreeNode
';
$scope.$$allowNodeDrop = false;
$scope.collapsed = false;
$scope.expandOnHover = false;
//Called by uiTreeNode Directive on load.
$scope.init = function (controllersArr) {
var treeNodesCtrl = controllersArr[0];
$scope.$treeScope = controllersArr[1] ? controllersArr[1].scope : null;
//Find the scope of it'
s parent node.
$scope.$parentNodeScope = treeNodesCtrl.scope.$nodeScope;
$scope.$modelValue = treeNodesCtrl.scope.$modelValue[$scope.$index];
$scope.$parentNodesScope = treeNodesCtrl.scope;
treeNodesCtrl.scope.initSubNode($scope);
$element.on(
'$destroy'
,
function
() {
treeNodesCtrl.scope.destroySubNode($scope);
});
};
$scope.index =
function
() {
return
$scope.$parentNodesScope.$modelValue.indexOf($scope.$modelValue);
};
$scope.dragEnabled =
function
() {
return
!($scope.$treeScope && !$scope.$treeScope.dragEnabled);
};
$scope.isSibling =
function
(targetNode) {
return
$scope.$parentNodesScope == targetNode.$parentNodesScope;
};
$scope.isChild =
function
(targetNode) {
var
nodes = $scope.childNodes();
return
nodes && nodes.indexOf(targetNode) > -1;
};
$scope.prev =
function
() {
var
index = $scope.index();
if
(index > 0) {
return
$scope.siblings()[index - 1];
}
return
null
;
};
$scope.siblings =
function
() {
return
$scope.$parentNodesScope.childNodes();
};
$scope.childNodesCount =
function
() {
return
$scope.childNodes() ? $scope.childNodes().length : 0;
};
$scope.hasChild =
function
() {
return
$scope.childNodesCount() > 0;
};
$scope.childNodes =
function
() {
return
$scope.$childNodesScope && $scope.$childNodesScope.$modelValue ?
$scope.$childNodesScope.childNodes() :
null
;
};
$scope.accept =
function
(sourceNode, destIndex) {
return
$scope.$childNodesScope &&
$scope.$childNodesScope.$modelValue &&
$scope.$childNodesScope.accept(sourceNode, destIndex);
};
$scope.remove =
function
() {
return
$scope.$parentNodesScope.removeNode($scope);
};
$scope.toggle =
function
() {
$scope.collapsed = !$scope.collapsed;
$scope.$treeScope.$callbacks.toggle($scope.collapsed, $scope);
};
$scope.collapse =
function
() {
$scope.collapsed =
true
;
};
$scope.expand =
function
() {
$scope.collapsed =
false
;
};
$scope.depth =
function
() {
var
parentNode = $scope.$parentNodeScope;
if
(parentNode) {
return
parentNode.depth() + 1;
}
return
1;
};
function
countSubTreeDepth(scope) {
if
(!scope) {
return
0;
}
var
thisLevelDepth = 0,
childNodes = scope.childNodes(),
childNode,
childDepth,
i;
if
(!childNodes || childNodes.length === 0) {
return
0;
}
for
(i = childNodes.length - 1; i >= 0 ; i--) {
childNode = childNodes[i],
childDepth = 1 + countSubTreeDepth(childNode);
thisLevelDepth = Math.max(thisLevelDepth, childDepth);
}
return
thisLevelDepth;
}
$scope.maxSubDepth =
function
() {
return
$scope.$childNodesScope ? countSubTreeDepth($scope.$childNodesScope) : 0;
};
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.controller(
'TreeNodesController'
, [
'$scope'
,
'$element'
,
'$timeout'
,
function
($scope, $element, $timeout) {
this
.scope = $scope;
$scope.$element = $element;
$scope.$modelValue =
null
;
$scope.$nodeScope =
null
;
$scope.$treeScope =
null
;
$scope.$type =
'uiTreeNodes'
;
$scope.$nodesMap = {};
$scope.nodropEnabled =
false
;
$scope.maxDepth = 0;
$scope.cloneEnabled =
false
;
$scope.initSubNode =
function
(subNode) {
if
(!subNode.$modelValue) {
return
null
;
}
$scope.$nodesMap[subNode.$modelValue.$$hashKey] = subNode;
};
$scope.destroySubNode =
function
(subNode) {
if
(!subNode.$modelValue) {
return
null
;
}
$scope.$nodesMap[subNode.$modelValue.$$hashKey] =
null
;
};
$scope.accept =
function
(sourceNode, destIndex) {
return
$scope.$treeScope.$callbacks.accept(sourceNode, $scope, destIndex);
};
$scope.beforeDrag =
function
(sourceNode) {
return
$scope.$treeScope.$callbacks.beforeDrag(sourceNode);
};
$scope.isParent =
function
(node) {
return
node.$parentNodesScope == $scope;
};
$scope.hasChild =
function
() {
return
$scope.$modelValue.length > 0;
};
$scope.removeNode =
function
(node) {
var
index = $scope.$modelValue.indexOf(node.$modelValue);
if
(index > -1) {
$timeout(
function
() {
$scope.$modelValue.splice(index, 1)[0];
});
return
$scope.$treeScope.$callbacks.removed(node);
}
return
null
;
};
$scope.insertNode =
function
(index, nodeData) {
$timeout(
function
() {
$scope.$modelValue.splice(index, 0, nodeData);
});
};
$scope.childNodes =
function
() {
var
i, nodes = [];
if
($scope.$modelValue) {
for
(i = 0; i < $scope.$modelValue.length; i++) {
nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]);
}
}
return
nodes;
};
$scope.depth =
function
() {
if
($scope.$nodeScope) {
return
$scope.$nodeScope.depth();
}
return
0;
};
$scope.outOfDepth =
function
(sourceNode) {
var
maxDepth = $scope.maxDepth || $scope.$treeScope.maxDepth;
if
(maxDepth > 0) {
return
$scope.depth() + sourceNode.maxSubDepth() + 1 > maxDepth;
}
return
false
;
};
}
]);
})();
(
function
() {
'use strict
';
angular.module('
ui.tree
')
.controller('
TreeController
', ['
$scope
', '
$element
',
function ($scope, $element) {
this.scope = $scope;
$scope.$element = $element;
$scope.$nodesScope = null; // root nodes
$scope.$type = '
uiTree
';
$scope.$emptyElm = null;
$scope.$dropzoneElm = null;
$scope.$callbacks = null;
$scope.dragEnabled = true;
$scope.emptyPlaceholderEnabled = true;
$scope.maxDepth = 0;
$scope.dragDelay = 0;
$scope.cloneEnabled = false;
$scope.nodropEnabled = false;
$scope.dropzoneEnabled = false;
// Check if it'
s a empty tree
$scope.isEmpty =
function
() {
return
($scope.$nodesScope && $scope.$nodesScope.$modelValue
&& $scope.$nodesScope.$modelValue.length === 0);
};
$scope.place =
function
(placeElm) {
$scope.$nodesScope.$element.append(placeElm);
$scope.$emptyElm.remove();
};
this
.resetEmptyElement =
function
() {
if
((!$scope.$nodesScope.$modelValue || $scope.$nodesScope.$modelValue.length === 0) &&
$scope.emptyPlaceholderEnabled) {
$element.append($scope.$emptyElm);
}
else
{
$scope.$emptyElm.remove();
}
};
this
.resetDropzoneElement =
function
() {
if
((!$scope.$nodesScope.$modelValue || $scope.$nodesScope.$modelValue.length !== 0) &&
$scope.dropzoneEnabled) {
$element.append($scope.$dropzoneElm);
}
else
{
$scope.$dropzoneElm.remove();
}
};
$scope.resetEmptyElement =
this
.resetEmptyElement;
$scope.resetDropzoneElement =
this
.resetDropzoneElement;
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.directive(
'uiTree'
, [
'treeConfig'
,
'$window'
,
function
(treeConfig, $window) {
return
{
restrict:
'A'
,
scope:
true
,
controller:
'TreeController'
,
link:
function
(scope, element, attrs, ctrl) {
var
callbacks = {
accept:
null
,
beforeDrag:
null
},
config = {},
tdElm,
$trElm,
emptyElmColspan;
angular.extend(config, treeConfig);
if
(config.treeClass) {
element.addClass(config.treeClass);
}
if
(element.prop(
'tagName'
).toLowerCase() ===
'table'
) {
scope.$emptyElm = angular.element($window.document.createElement(
'tr'
));
$trElm = element.find(
'tr'
);
if
($trElm.length > 0) {
emptyElmColspan = angular.element($trElm).children().length;
}
else
{
emptyElmColspan = 1000000;
}
tdElm = angular.element($window.document.createElement(
'td'
))
.attr(
'colspan'
, emptyElmColspan);
scope.$emptyElm.append(tdElm);
}
else
{
scope.$emptyElm = angular.element($window.document.createElement(
'div'
));
scope.$dropzoneElm = angular.element($window.document.createElement(
'div'
));
}
if
(config.emptyTreeClass) {
scope.$emptyElm.addClass(config.emptyTreeClass);
}
if
(config.dropzoneClass) {
scope.$dropzoneElm.addClass(config.dropzoneClass);
}
scope.$watch(
'$nodesScope.$modelValue.length'
,
function
(val) {
if
(!angular.isNumber(val)) {
return
;
}
ctrl.resetEmptyElement();
ctrl.resetDropzoneElement();
},
true
);
scope.$watch(attrs.dragEnabled,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.dragEnabled = val;
}
});
scope.$watch(attrs.emptyPlaceholderEnabled,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.emptyPlaceholderEnabled = val;
ctrl.resetEmptyElement();
}
});
scope.$watch(attrs.nodropEnabled,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.nodropEnabled = val;
}
});
scope.$watch(attrs.dropzoneEnabled,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.dropzoneEnabled = val;
ctrl.resetDropzoneElement();
}
});
scope.$watch(attrs.cloneEnabled,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.cloneEnabled = val;
}
});
scope.$watch(attrs.maxDepth,
function
(val) {
if
((
typeof
val) ==
'number'
) {
scope.maxDepth = val;
}
});
scope.$watch(attrs.dragDelay,
function
(val) {
if
((
typeof
val) ==
'number'
) {
scope.dragDelay = val;
}
});
callbacks.accept =
function
(sourceNodeScope, destNodesScope, destIndex) {
return
!(destNodesScope.nodropEnabled || destNodesScope.$treeScope.nodropEnabled || destNodesScope.outOfDepth(sourceNodeScope));
};
callbacks.beforeDrag =
function
(sourceNodeScope) {
return
true
;
};
callbacks.expandTimeoutStart =
function
()
{
};
callbacks.expandTimeoutCancel =
function
()
{
};
callbacks.expandTimeoutEnd =
function
()
{
};
callbacks.removed =
function
(node) {
};
callbacks.dropped =
function
(event) {
};
callbacks.dragStart =
function
(event) {
};
callbacks.dragMove =
function
(event) {
};
callbacks.dragStop =
function
(event) {
};
callbacks.beforeDrop =
function
(event) {
};
callbacks.toggle =
function
(collapsed, sourceNodeScope) {
};
scope.$watch(attrs.uiTree,
function
(newVal, oldVal) {
angular.forEach(newVal,
function
(value, key) {
if
(callbacks[key]) {
if
(
typeof
value ===
'function'
) {
callbacks[key] = value;
}
}
});
scope.$callbacks = callbacks;
},
true
);
}
};
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.directive(
'uiTreeHandle'
, [
'treeConfig'
,
function
(treeConfig) {
return
{
require:
'^uiTreeNode'
,
restrict:
'A'
,
scope:
true
,
controller:
'TreeHandleController'
,
link:
function
(scope, element, attrs, treeNodeCtrl) {
var
config = {};
angular.extend(config, treeConfig);
if
(config.handleClass) {
element.addClass(config.handleClass);
}
if
(scope != treeNodeCtrl.scope) {
scope.$nodeScope = treeNodeCtrl.scope;
treeNodeCtrl.scope.$handleScope = scope;
}
}
};
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.directive(
'uiTreeNode'
, [
'treeConfig'
,
'UiTreeHelper'
,
'$window'
,
'$document'
,
'$timeout'
,
'$q'
,
function
(treeConfig, UiTreeHelper, $window, $document, $timeout, $q) {
return
{
require: [
'^uiTreeNodes'
,
'^uiTree'
],
restrict:
'A'
,
controller:
'TreeNodeController'
,
link:
function
(scope, element, attrs, controllersArr) {
var
config = {},
hasTouch =
'ontouchstart'
in
window,
firstMoving,
dragInfo,
pos,
placeElm,
hiddenPlaceElm,
dragElm,
scrollContainerElm,
unhover,
treeScope =
null
,
elements,
dragDelaying =
true
,
dragStarted =
false
,
dragTimer =
null
,
body = document.body,
html = document.documentElement,
document_height,
document_width,
dragStart,
tagName,
dragMove,
dragEnd,
dragStartEvent,
dragMoveEvent,
dragEndEvent,
dragCancelEvent,
dragDelay,
bindDragStartEvents,
bindDragMoveEvents,
unbindDragMoveEvents,
keydownHandler,
isHandleChild,
el,
isUiTreeRoot,
treeOfOrigin;
angular.extend(config, treeConfig);
if
(config.nodeClass) {
element.addClass(config.nodeClass);
}
scope.init(controllersArr);
scope.collapsed = !!UiTreeHelper.getNodeAttribute(scope,
'collapsed'
) || treeConfig.defaultCollapsed;
scope.expandOnHover = !!UiTreeHelper.getNodeAttribute(scope,
'expandOnHover'
);
scope.scrollContainer = UiTreeHelper.getNodeAttribute(scope,
'scrollContainer'
) || attrs.scrollContainer ||
null
;
scope.sourceOnly = scope.nodropEnabled || scope.$treeScope.nodropEnabled;
scope.$watch(attrs.collapsed,
function
(val) {
if
((
typeof
val) ==
'boolean'
) {
scope.collapsed = val;
}
});
scope.$watch(
'collapsed'
,
function
(val) {
UiTreeHelper.setNodeAttribute(scope,
'collapsed'
, val);
attrs.$set(
'collapsed'
, val);
});
scope.$watch(attrs.expandOnHover,
function
(val) {
if
((
typeof
val) ===
'boolean'
|| (
typeof
val) ===
'number'
) {
scope.expandOnHover = val;
}
});
scope.$watch(
'expandOnHover'
,
function
(val) {
UiTreeHelper.setNodeAttribute(scope,
'expandOnHover'
, val);
attrs.$set(
'expandOnHover'
, val);
});
attrs.$observe(
'scrollContainer'
,
function
(val) {
if
((
typeof
val) ===
'string'
) {
scope.scrollContainer = val;
}
});
scope.$watch(
'scrollContainer'
,
function
(val) {
UiTreeHelper.setNodeAttribute(scope,
'scrollContainer'
, val);
attrs.$set(
'scrollContainer'
, val);
scrollContainerElm = document.querySelector(val);
});
scope.$on(
'angular-ui-tree:collapse-all'
,
function
() {
scope.collapsed =
true
;
});
scope.$on(
'angular-ui-tree:expand-all'
,
function
() {
scope.collapsed =
false
;
});
dragStart =
function
(e) {
if
(!hasTouch && (e.button === 2 || e.which === 3)) {
return
;
}
if
(e.uiTreeDragging || (e.originalEvent && e.originalEvent.uiTreeDragging)) {
return
;
}
var
eventElm = angular.element(e.target),
isHandleChild,
cloneElm,
eventElmTagName,
tagName,
eventObj,
tdElm,
hStyle,
isTreeNode,
isTreeNodeHandle;
isHandleChild = UiTreeHelper.treeNodeHandlerContainerOfElement(eventElm);
if
(isHandleChild) {
eventElm = angular.element(isHandleChild);
}
cloneElm = element.clone();
isTreeNode = UiTreeHelper.elementIsTreeNode(eventElm);
isTreeNodeHandle = UiTreeHelper.elementIsTreeNodeHandle(eventElm);
if
(!isTreeNode && !isTreeNodeHandle) {
return
;
}
if
(isTreeNode && UiTreeHelper.elementContainsTreeNodeHandler(eventElm)) {
return
;
}
eventElmTagName = eventElm.prop(
'tagName'
).toLowerCase();
if
(eventElmTagName ==
'input'
||
eventElmTagName ==
'textarea'
||
eventElmTagName ==
'button'
||
eventElmTagName ==
'select'
) {
return
;
}
el = angular.element(e.target);
isUiTreeRoot = el[0].attributes['ui-tree
'];
while (el && el[0] && el[0] !== element && !isUiTreeRoot) {
//Checking that I can access attributes.
if (el[0].attributes) {
isUiTreeRoot = el[0].attributes['
ui-tree
'];
}
//If the node mark as `nodrag`, DONOT drag it.
if (UiTreeHelper.nodrag(el)) {
return;
}
el = el.parent();
}
//If users beforeDrag calback returns falsey, do not initiate.
if (!scope.beforeDrag(scope)) {
return;
}
//Set property checked at start of function to prevent running logic again.
e.uiTreeDragging = true;
if (e.originalEvent) {
e.originalEvent.uiTreeDragging = true;
}
e.preventDefault();
//Get original event if TouchEvent.
eventObj = UiTreeHelper.eventObj(e);
//Set boolean used to specify beginning of move.
firstMoving = true;
//Setting drag info properties and methods in scope of node being moved.
dragInfo = UiTreeHelper.dragInfo(scope);
//Setting original tree to adjust horizontal behavior in drag move.
treeOfOrigin = dragInfo.source.$treeScope.$id;
//Determine tage name of element ui-tree-node is on.
tagName = element.prop('
tagName
');
if (tagName.toLowerCase() === '
tr
') {
//Create a new table column as placeholder.
placeElm = angular.element($window.document.createElement(tagName));
//Create a column placeholder and set colspan to whole row length.
tdElm = angular.element($window.document.createElement('
td
'))
.addClass(config.placeholderClass)
.attr('
colspan
', element[0].children.length);
placeElm.append(tdElm);
} else {
//If not a table just duplicate element and add placeholder class.
placeElm = angular.element($window.document.createElement(tagName))
.addClass(config.placeholderClass);
}
//Create a hidden placeholder and add class from config.
hiddenPlaceElm = angular.element($window.document.createElement(tagName));
if (config.hiddenClass) {
hiddenPlaceElm.addClass(config.hiddenClass);
}
//Getting starting position of element being moved.
pos = UiTreeHelper.positionStarted(eventObj, element);
placeElm.css('
height
', element.prop('
offsetHeight
') + '
px
');
//Creating drag element to represent node.
dragElm = angular.element($window.document.createElement(scope.$parentNodesScope.$element.prop('
tagName
')))
.addClass(scope.$parentNodesScope.$element.attr('
class
')).addClass(config.dragClass);
dragElm.css('
width
', UiTreeHelper.width(element) + '
px
');
dragElm.css('
z-index
', 9999);
//Prevents cursor to change rapidly in Opera 12.16 and IE when dragging an element.
hStyle = (element[0].querySelector('
.angular-ui-tree-handle
') || element[0]).currentStyle;
if (hStyle) {
document.body.setAttribute('
ui-tree-cursor
', $document.find('
body
').css('
cursor
') || '
');
$document.find('
body
').css({'
cursor
': hStyle.cursor + '
!important
'});
}
//If tree is sourceOnly (noDragDrop) don'
t show placeholder when moving about it.
if
(scope.sourceOnly) {
placeElm.css(
'display'
,
'none'
);
}
element.after(placeElm);
element.after(hiddenPlaceElm);
if
(dragInfo.isClone() && scope.sourceOnly) {
dragElm.append(cloneElm);
}
else
{
dragElm.append(element);
}
$document.find(
'body'
).append(dragElm);
dragElm.css({
'left'
: eventObj.pageX - pos.offsetX +
'px'
,
'top'
: eventObj.pageY - pos.offsetY +
'px'
});
elements = {
placeholder: placeElm,
dragging: dragElm
};
bindDragMoveEvents();
scope.$apply(
function
() {
scope.$treeScope.$callbacks.dragStart(dragInfo.eventArgs(elements, pos));
});
document_height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
document_width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
};
dragMove =
function
(e) {
var
eventObj = UiTreeHelper.eventObj(e),
prev,
next,
leftElmPos,
topElmPos,
top_scroll,
bottom_scroll,
scrollContainerElmRect,
target,
targetX,
targetY,
displayElm,
targetNode,
targetElm,
isEmpty,
scrollDownBy,
scrollUpBy,
targetOffset,
targetBefore,
moveWithinTree,
targetBeforeBuffer,
targetHeight,
targetChildElm,
targetChildHeight,
isDropzone;
if
(dragElm) {
e.preventDefault();
if
($window.getSelection) {
$window.getSelection().removeAllRanges();
}
else
if
($window.document.selection) {
$window.document.selection.empty();
}
leftElmPos = eventObj.pageX - pos.offsetX;
topElmPos = eventObj.pageY - pos.offsetY;
if
(leftElmPos < 0) {
leftElmPos = 0;
}
if
(topElmPos < 0) {
topElmPos = 0;
}
if
((topElmPos + 10) > document_height) {
topElmPos = document_height - 10;
}
if
((leftElmPos + 10) > document_width) {
leftElmPos = document_width - 10;
}
dragElm.css({
'left'
: leftElmPos +
'px'
,
'top'
: topElmPos +
'px'
});
if
(scrollContainerElm) {
scrollContainerElmRect = scrollContainerElm.getBoundingClientRect();
top_scroll = scrollContainerElm.scrollTop;
bottom_scroll = top_scroll + scrollContainerElm.clientHeight;
if
(scrollContainerElmRect.bottom < eventObj.clientY && bottom_scroll < scrollContainerElm.scrollHeight) {
scrollDownBy = Math.min(scrollContainerElm.scrollHeight - bottom_scroll, 10);
scrollContainerElm.scrollTop += scrollDownBy;
}
if
(scrollContainerElmRect.top > eventObj.clientY && top_scroll > 0) {
scrollUpBy = Math.min(top_scroll, 10);
scrollContainerElm.scrollTop -= scrollUpBy;
}
}
else
{
top_scroll = window.pageYOffset || $window.document.documentElement.scrollTop;
bottom_scroll = top_scroll + (window.innerHeight || $window.document.clientHeight || $window.document.clientHeight);
if
(bottom_scroll < eventObj.pageY && bottom_scroll < document_height) {
scrollDownBy = Math.min(document_height - bottom_scroll, 10);
window.scrollBy(0, scrollDownBy);
}
if
(top_scroll > eventObj.pageY) {
scrollUpBy = Math.min(top_scroll, 10);
window.scrollBy(0, -scrollUpBy);
}
}
UiTreeHelper.positionMoved(e, pos, firstMoving);
if
(firstMoving) {
firstMoving =
false
;
return
;
}
targetX = eventObj.pageX - ($window.pageXOffset ||
$window.document.body.scrollLeft ||
$window.document.documentElement.scrollLeft) -
($window.document.documentElement.clientLeft || 0);
targetY = eventObj.pageY - ($window.pageYOffset ||
$window.document.body.scrollTop ||
$window.document.documentElement.scrollTop) -
($window.document.documentElement.clientTop || 0);
if
(angular.isFunction(dragElm.hide)) {
dragElm.hide();
}
else
{
displayElm = dragElm[0].style.display;
dragElm[0].style.display =
'none'
;
}
$window.document.elementFromPoint(targetX, targetY);
targetElm = angular.element($window.document.elementFromPoint(targetX, targetY));
isHandleChild = UiTreeHelper.treeNodeHandlerContainerOfElement(targetElm);
if
(isHandleChild) {
targetElm = angular.element(isHandleChild);
}
if
(angular.isFunction(dragElm.show)) {
dragElm.show();
}
else
{
dragElm[0].style.display = displayElm;
}
if
(UiTreeHelper.elementIsTree(targetElm)) {
targetNode = targetElm.controller(
'uiTree'
).scope;
}
else
if
(UiTreeHelper.elementIsTreeNodeHandle(targetElm)) {
targetNode = targetElm.controller(
'uiTreeHandle'
).scope;
}
else
if
(UiTreeHelper.elementIsTreeNode(targetElm)) {
targetNode = targetElm.controller(
'uiTreeNode'
).scope;
}
else
if
(UiTreeHelper.elementIsTreeNodes(targetElm)) {
targetNode = targetElm.controller(
'uiTreeNodes'
).scope;
}
else
if
(UiTreeHelper.elementIsPlaceholder(targetElm)) {
targetNode = targetElm.controller(
'uiTreeNodes'
).scope;
}
else
if
(UiTreeHelper.elementIsDropzone(targetElm)) {
targetNode = targetElm.controller(
'uiTree'
).scope;
isDropzone =
true
;
}
else
if
(targetElm.controller(
'uiTreeNode'
)) {
targetNode = targetElm.controller(
'uiTreeNode'
).scope;
}
moveWithinTree = (targetNode && targetNode.$treeScope && targetNode.$treeScope.$id && targetNode.$treeScope.$id === treeOfOrigin);
if
(moveWithinTree && pos.dirAx) {
if
(pos.distX > 0) {
prev = dragInfo.prev();
if
(prev && !prev.collapsed
&& prev.accept(scope, prev.childNodesCount())) {
prev.$childNodesScope.$element.append(placeElm);
dragInfo.moveTo(prev.$childNodesScope, prev.childNodes(), prev.childNodesCount());
}
}
if
(pos.distX < 0) {
next = dragInfo.next();
if
(!next) {
target = dragInfo.parentNode();
if
(target
&& target.$parentNodesScope.accept(scope, target.index() + 1)) {
target.$element.after(placeElm);
dragInfo.moveTo(target.$parentNodesScope, target.siblings(), target.index() + 1);
}
}
}
}
else
{
isEmpty =
false
;
if
(!targetNode) {
return
;
}
if
(targetNode.$treeScope && !targetNode.$parent.nodropEnabled && !targetNode.$treeScope.nodropEnabled) {
placeElm.css('display
', '
');
}
//Set whether target tree is empty or not.
if (targetNode.$type === '
uiTree
' && targetNode.dragEnabled) {
isEmpty = targetNode.isEmpty();
}
//If target is a handle set new target to handle'
s node.
if
(targetNode.$type ===
'uiTreeHandle'
) {
targetNode = targetNode.$nodeScope;
}
if
(targetNode.$type !==
'uiTreeNode'
&& !isEmpty && !isDropzone) {
if
(config.appendChildOnHover) {
next = dragInfo.next();
if
(!next && unhover) {
target = dragInfo.parentNode();
target.$element.after(placeElm);
dragInfo.moveTo(target.$parentNodesScope, target.siblings(), target.index() + 1);
unhover =
false
;
}
}
return
;
}
if
(treeScope && placeElm.parent()[0] != treeScope.$element[0]) {
treeScope.resetEmptyElement();
treeScope.resetDropzoneElement();
treeScope =
null
;
}
if
(isEmpty) {
treeScope = targetNode;
if
(targetNode.$nodesScope.accept(scope, 0)) {
dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0);
}
}
else
if
(isDropzone) {
treeScope = targetNode;
if
(targetNode.$nodesScope.accept(scope, targetNode.$nodesScope.childNodes().length)) {
dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), targetNode.$nodesScope.childNodes().length);
}
}
else
if
(targetNode.dragEnabled()) {
if
(angular.isDefined(scope.expandTimeoutOn) && scope.expandTimeoutOn !== targetNode.id) {
$timeout.cancel(scope.expandTimeout);
delete
scope.expandTimeout;
delete
scope.expandTimeoutOn;
scope.$callbacks.expandTimeoutCancel();
}
if
(targetNode.collapsed) {
if
(scope.expandOnHover ===
true
|| (angular.isNumber(scope.expandOnHover) && scope.expandOnHover === 0)) {
targetNode.collapsed =
false
;
targetNode.$treeScope.$callbacks.toggle(
false
, targetNode);
}
else
if
(scope.expandOnHover !==
false
&& angular.isNumber(scope.expandOnHover) && scope.expandOnHover > 0) {
if
(angular.isUndefined(scope.expandTimeoutOn)) {
scope.expandTimeoutOn = targetNode.$id;
scope.$callbacks.expandTimeoutStart();
scope.expandTimeout = $timeout(
function
()
{
scope.$callbacks.expandTimeoutEnd();
targetNode.collapsed =
false
;
targetNode.$treeScope.$callbacks.toggle(
false
, targetNode);
}, scope.expandOnHover);
}
}
}
targetElm = targetNode.$element;
targetOffset = UiTreeHelper.offset(targetElm);
targetHeight = UiTreeHelper.height(targetElm);
targetChildElm = targetNode.$childNodesScope ? targetNode.$childNodesScope.$element :
null
;
targetChildHeight = targetChildElm ? UiTreeHelper.height(targetChildElm) : 0;
targetHeight -= targetChildHeight;
targetBeforeBuffer = config.appendChildOnHover ? targetHeight * 0.25 : UiTreeHelper.height(targetElm) / 2;
targetBefore = eventObj.pageY < (targetOffset.top + targetBeforeBuffer);
if
(targetNode.$parentNodesScope.accept(scope, targetNode.index())) {
if
(targetBefore) {
targetElm[0].parentNode.insertBefore(placeElm[0], targetElm[0]);
dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index());
}
else
{
if
(config.appendChildOnHover && targetNode.accept(scope, targetNode.childNodesCount())) {
targetNode.$childNodesScope.$element.prepend(placeElm);
dragInfo.moveTo(targetNode.$childNodesScope, targetNode.childNodes(), 0);
unhover =
true
;
}
else
{
targetElm.after(placeElm);
dragInfo.moveTo(targetNode.$parentNodesScope, targetNode.siblings(), targetNode.index() + 1);
}
}
}
else
if
(!targetBefore && targetNode.accept(scope, targetNode.childNodesCount())) {
targetNode.$childNodesScope.$element.append(placeElm);
dragInfo.moveTo(targetNode.$childNodesScope, targetNode.childNodes(), targetNode.childNodesCount());
}
}
}
scope.$apply(
function
() {
scope.$treeScope.$callbacks.dragMove(dragInfo.eventArgs(elements, pos));
});
}
};
dragEnd =
function
(e) {
var
dragEventArgs = dragInfo.eventArgs(elements, pos);
e.preventDefault();
unbindDragMoveEvents();
$timeout.cancel(scope.expandTimeout);
scope.$treeScope.$apply(
function
() {
$q.when(scope.$treeScope.$callbacks.beforeDrop(dragEventArgs))
.then(
function
(allowDrop) {
if
(allowDrop !==
false
&& scope.$$allowNodeDrop) {
dragInfo.apply();
scope.$treeScope.$callbacks.dropped(dragEventArgs);
}
else
{
bindDragStartEvents();
}
})
.
catch
(
function
() {
bindDragStartEvents();
})
.finally(
function
() {
hiddenPlaceElm.replaceWith(scope.$element);
placeElm.remove();
if
(dragElm) {
dragElm.remove();
dragElm =
null
;
}
scope.$treeScope.$callbacks.dragStop(dragEventArgs);
scope.$$allowNodeDrop =
false
;
dragInfo =
null
;
var
oldCur = document.body.getAttribute('ui-tree-cursor
');
if (oldCur !== null) {
$document.find('
body
').css({'
cursor
': oldCur});
document.body.removeAttribute('
ui-tree-cursor
');
}
});
});
};
dragStartEvent = function (e) {
if (scope.dragEnabled()) {
dragStart(e);
}
};
dragMoveEvent = function (e) {
dragMove(e);
};
dragEndEvent = function (e) {
scope.$$allowNodeDrop = true;
dragEnd(e);
};
dragCancelEvent = function (e) {
dragEnd(e);
};
dragDelay = (function () {
var to;
return {
exec: function (fn, ms) {
if (!ms) {
ms = 0;
}
this.cancel();
to = $timeout(fn, ms);
},
cancel: function () {
$timeout.cancel(to);
}
};
})();
keydownHandler = function (e) {
if (e.keyCode === 27) {
dragEndEvent(e);
}
};
/**
* Binds the mouse/touch events to enable drag start for this node.
*/
//This is outside of bindDragMoveEvents because of the potential for a delay setting.
bindDragStartEvents = function () {
element.bind('
touchstart mousedown
', function (e) {
//Don'
t call drag delay
if
no delay was specified.
if
(scope.dragDelay > 0) {
dragDelay.exec(
function
() {
dragStartEvent(e);
}, scope.dragDelay);
}
else
{
dragStartEvent(e);
}
});
element.bind(
'touchend touchcancel mouseup'
,
function
() {
if
(scope.dragDelay > 0) {
dragDelay.cancel();
}
});
};
bindDragStartEvents();
bindDragMoveEvents =
function
() {
angular.element($document).bind(
'touchend'
, dragEndEvent);
angular.element($document).bind(
'touchcancel'
, dragEndEvent);
angular.element($document).bind(
'touchmove'
, dragMoveEvent);
angular.element($document).bind(
'mouseup'
, dragEndEvent);
angular.element($document).bind(
'mousemove'
, dragMoveEvent);
angular.element($document).bind(
'mouseleave'
, dragCancelEvent);
angular.element($document).bind(
'keydown'
, keydownHandler);
};
unbindDragMoveEvents =
function
() {
angular.element($document).unbind(
'touchend'
, dragEndEvent);
angular.element($document).unbind(
'touchcancel'
, dragEndEvent);
angular.element($document).unbind(
'touchmove'
, dragMoveEvent);
angular.element($document).unbind(
'mouseup'
, dragEndEvent);
angular.element($document).unbind(
'mousemove'
, dragMoveEvent);
angular.element($document).unbind(
'mouseleave'
, dragCancelEvent);
angular.element($document).unbind(
'keydown'
, keydownHandler);
};
}
};
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.directive(
'uiTreeNodes'
, [
'treeConfig'
,
'$window'
,
function
(treeConfig) {
return
{
require: [
'ngModel'
,
'?^uiTreeNode'
,
'^uiTree'
],
restrict:
'A'
,
scope:
true
,
controller:
'TreeNodesController'
,
link:
function
(scope, element, attrs, controllersArr) {
var
config = {},
ngModel = controllersArr[0],
treeNodeCtrl = controllersArr[1],
treeCtrl = controllersArr[2];
angular.extend(config, treeConfig);
if
(config.nodesClass) {
element.addClass(config.nodesClass);
}
if
(treeNodeCtrl) {
treeNodeCtrl.scope.$childNodesScope = scope;
scope.$nodeScope = treeNodeCtrl.scope;
}
else
{
treeCtrl.scope.$nodesScope = scope;
}
scope.$treeScope = treeCtrl.scope;
if
(ngModel) {
ngModel.$render =
function
() {
scope.$modelValue = ngModel.$modelValue;
};
}
scope.$watch(
function
() {
return
attrs.maxDepth;
},
function
(val) {
if
((
typeof
val) ==
'number'
) {
scope.maxDepth = val;
}
});
scope.$watch(
function
() {
return
attrs.nodropEnabled;
},
function
(newVal) {
if
((
typeof
newVal) !=
'undefined'
) {
scope.nodropEnabled =
true
;
}
},
true
);
}
};
}
]);
})();
(
function
() {
'use strict'
;
angular.module(
'ui.tree'
)
.factory(
'UiTreeHelper'
, [
'$document'
,
'$window'
,
'treeConfig'
,
function
($document, $window, treeConfig) {
return
{
nodesData: {},
setNodeAttribute:
function
(scope, attrName, val) {
if
(!scope.$modelValue) {
return
null
;
}
var
data =
this
.nodesData[scope.$modelValue.$$hashKey];
if
(!data) {
data = {};
this
.nodesData[scope.$modelValue.$$hashKey] = data;
}
data[attrName] = val;
},
getNodeAttribute:
function
(scope, attrName) {
if
(!scope.$modelValue) {
return
null
;
}
var
data =
this
.nodesData[scope.$modelValue.$$hashKey];
if
(data) {
return
data[attrName];
}
return
null
;
},
nodrag:
function
(targetElm) {
if
(
typeof
targetElm.attr(
'data-nodrag'
) !=
'undefined'
) {
return
targetElm.attr(
'data-nodrag'
) !==
'false'
;
}
return
false
;
},
eventObj:
function
(e) {
var
obj = e;
if
(e.targetTouches !== undefined) {
obj = e.targetTouches.item(0);
}
else
if
(e.originalEvent !== undefined && e.originalEvent.targetTouches !== undefined) {
obj = e.originalEvent.targetTouches.item(0);
}
return
obj;
},
dragInfo:
function
(node) {
return
{
source: node,
sourceInfo: {
cloneModel: node.$treeScope.cloneEnabled ===
true
? angular.copy(node.$modelValue) : undefined,
nodeScope: node,
index: node.index(),
nodesScope: node.$parentNodesScope
},
index: node.index(),
siblings: node.siblings().slice(0),
parent: node.$parentNodesScope,
resetParent:
function
() {
this
.parent = node.$parentNodesScope;
},
moveTo:
function
(parent, siblings, index) {
this
.parent = parent;
this
.siblings = siblings.slice(0);
var
i =
this
.siblings.indexOf(
this
.source);
if
(i > -1) {
this
.siblings.splice(i, 1);
if
(
this
.source.index() < index) {
index--;
}
}
this
.siblings.splice(index, 0,
this
.source);
this
.index = index;
},
parentNode:
function
() {
return
this
.parent.$nodeScope;
},
prev:
function
() {
if
(
this
.index > 0) {
return
this
.siblings[
this
.index - 1];
}
return
null
;
},
next:
function
() {
if
(
this
.index <
this
.siblings.length - 1) {
return
this
.siblings[
this
.index + 1];
}
return
null
;
},
isClone:
function
() {
return
this
.source.$treeScope.cloneEnabled ===
true
;
},
clonedNode:
function
(node) {
return
angular.copy(node);
},
isDirty:
function
() {
return
this
.source.$parentNodesScope !=
this
.parent ||
this
.source.index() !=
this
.index;
},
isForeign:
function
() {
return
this
.source.$treeScope !==
this
.parent.$treeScope;
},
eventArgs:
function
(elements, pos) {
return
{
source:
this
.sourceInfo,
dest: {
index:
this
.index,
nodesScope:
this
.parent
},
elements: elements,
pos: pos
};
},
apply:
function
() {
var
nodeData =
this
.source.$modelValue;
if
(
this
.parent.nodropEnabled ||
this
.parent.$treeScope.nodropEnabled) {
return
;
}
if
(!
this
.isDirty()) {
return
;
}
if
(
this
.isClone() &&
this
.isForeign()) {
this
.parent.insertNode(
this
.index,
this
.sourceInfo.cloneModel);
}
else
{
this
.source.remove();
this
.parent.insertNode(
this
.index, nodeData);
}
}
};
},
height:
function
(element) {
return
element.prop(
'scrollHeight'
);
},
width:
function
(element) {
return
element.prop(
'scrollWidth'
);
},
offset:
function
(element) {
var
boundingClientRect = element[0].getBoundingClientRect();
return
{
width: element.prop(
'offsetWidth'
),
height: element.prop(
'offsetHeight'
),
top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
};
},
positionStarted:
function
(e, target) {
var
pos = {},
pageX = e.pageX,
pageY = e.pageY;
if
(e.originalEvent && e.originalEvent.touches && (e.originalEvent.touches.length > 0)) {
pageX = e.originalEvent.touches[0].pageX;
pageY = e.originalEvent.touches[0].pageY;
}
pos.offsetX = pageX -
this
.offset(target).left;
pos.offsetY = pageY -
this
.offset(target).top;
pos.startX = pos.lastX = pageX;
pos.startY = pos.lastY = pageY;
pos.nowX = pos.nowY = pos.distX = pos.distY = pos.dirAx = 0;
pos.dirX = pos.dirY = pos.lastDirX = pos.lastDirY = pos.distAxX = pos.distAxY = 0;
return
pos;
},
positionMoved:
function
(e, pos, firstMoving) {
var
pageX = e.pageX,
pageY = e.pageY,
newAx;
if
(e.originalEvent && e.originalEvent.touches && (e.originalEvent.touches.length > 0)) {
pageX = e.originalEvent.touches[0].pageX;
pageY = e.originalEvent.touches[0].pageY;
}
pos.lastX = pos.nowX;
pos.lastY = pos.nowY;
pos.nowX = pageX;
pos.nowY = pageY;
pos.distX = pos.nowX - pos.lastX;
pos.distY = pos.nowY - pos.lastY;
pos.lastDirX = pos.dirX;
pos.lastDirY = pos.dirY;
pos.dirX = pos.distX === 0 ? 0 : pos.distX > 0 ? 1 : -1;
pos.dirY = pos.distY === 0 ? 0 : pos.distY > 0 ? 1 : -1;
newAx = Math.abs(pos.distX) > Math.abs(pos.distY) ? 1 : 0;
if
(firstMoving) {
pos.dirAx = newAx;
pos.moving =
true
;
return
;
}
if
(pos.dirAx !== newAx) {
pos.distAxX = 0;
pos.distAxY = 0;
}
else
{
pos.distAxX += Math.abs(pos.distX);
if
(pos.dirX !== 0 && pos.dirX !== pos.lastDirX) {
pos.distAxX = 0;
}
pos.distAxY += Math.abs(pos.distY);
if
(pos.dirY !== 0 && pos.dirY !== pos.lastDirY) {
pos.distAxY = 0;
}
}
pos.dirAx = newAx;
},
elementIsTreeNode:
function
(element) {
return
typeof
element.attr(
'ui-tree-node'
) !==
'undefined'
;
},
elementIsTreeNodeHandle:
function
(element) {
return
typeof
element.attr(
'ui-tree-handle'
) !==
'undefined'
;
},
elementIsTree:
function
(element) {
return
typeof
element.attr(
'ui-tree'
) !==
'undefined'
;
},
elementIsTreeNodes:
function
(element) {
return
typeof
element.attr(
'ui-tree-nodes'
) !==
'undefined'
;
},
elementIsPlaceholder:
function
(element) {
return
element.hasClass(treeConfig.placeholderClass);
},
elementIsDropzone:
function
(element) {
return
element.hasClass(treeConfig.dropzoneClass);
},
elementContainsTreeNodeHandler:
function
(element) {
return
element[0].querySelectorAll(
'[ui-tree-handle]'
).length >= 1;
},
treeNodeHandlerContainerOfElement:
function
(element) {
return
findFirstParentElementWithAttribute(
'ui-tree-handle'
, element[0]);
}
};
}
]);
function
findFirstParentElementWithAttribute(attributeName, childObj) {
if
(childObj === undefined) {
return
null
;
}
var
testObj = childObj.parentNode,
count = 1,
res = (
typeof
testObj.setAttribute ===
'function'
&& testObj.hasAttribute(attributeName)) ? testObj :
null
;
while
(testObj &&
typeof
testObj.setAttribute ===
'function'
&& !testObj.hasAttribute(attributeName)) {
testObj = testObj.parentNode;
res = testObj;
if
(testObj === document.documentElement) {
res =
null
;
break
;
}
count++;
}
return
res;
}
})();