diff --git a/bower.json b/bower.json index cb1b1f29..479763c2 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-tree", - "version": "2.0.8", + "version": "2.0.9", "homepage": "https://github.com/JimLiu/angular-ui-tree", "authors": [ "Jim Liu ", diff --git a/demo/dist/angular-ui-tree.js b/demo/dist/angular-ui-tree.js index e68ec674..d589e5ac 100644 --- a/demo/dist/angular-ui-tree.js +++ b/demo/dist/angular-ui-tree.js @@ -1,5 +1,5 @@ /** - * @license Angular UI Tree v2.0.8 + * @license Angular UI Tree v2.0.9 * (c) 2010-2014. https://github.com/JimLiu/angular-ui-tree * License: MIT */ @@ -74,7 +74,7 @@ nodesScope: node.$parentNodesScope, }, index: node.index(), - siblings: node.$parentNodesScope.$nodes.slice(0), + siblings: node.siblings().slice(0), parent: node.$parentNodesScope, moveTo: function(parent, siblings, index) { // Move the node to a new position @@ -302,9 +302,10 @@ }; var collapseOrExpand = function(scope, collapsed) { - for (var i = 0; i < scope.$nodes.length; i++) { - collapsed ? scope.$nodes[i].collapse() : scope.$nodes[i].expand(); - var subScope = scope.$nodes[i].$childNodesScope; + var nodes = scope.childNodes(); + for (var i = 0; i < nodes.length; i++) { + collapsed ? nodes[i].collapse() : nodes[i].expand(); + var subScope = nodes[i].$childNodesScope; if (subScope) { collapseOrExpand(subScope, collapsed); } @@ -328,31 +329,28 @@ angular.module('ui.tree') - .controller('TreeNodesController', ['$scope', '$element', 'treeConfig', - function ($scope, $element, treeConfig) { + .controller('TreeNodesController', ['$scope', '$element', '$timeout', 'treeConfig', + function ($scope, $element, $timeout, treeConfig) { this.scope = $scope; $scope.$element = $element; $scope.$modelValue = null; - $scope.$nodes = []; // sub nodes $scope.$nodeScope = null; // the scope of node which the nodes belongs to $scope.$treeScope = null; $scope.$type = 'uiTreeNodes'; + $scope.$nodesMap = {}; $scope.nodrop = false; $scope.maxDepth = 0; $scope.initSubNode = function(subNode) { - $scope.$nodes.splice(subNode.index(), 0, subNode); + $timeout(function() { + $scope.$nodesMap[subNode.$modelValue.$$hashKey] = subNode; + }); }; - $scope.reinitNodes = function() { - var nodes = $scope.$nodes.splice(0); - $scope.$nodes = []; - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - $scope.$nodes.splice(node.index(), 0, node); - } + $scope.destroySubNode = function(subNode) { + $scope.$nodesMap[subNode.$modelValue.$$hashKey] = null; }; $scope.accept = function(sourceNode, destIndex) { @@ -364,7 +362,7 @@ }; $scope.hasChild = function() { - return $scope.$nodes.length > 0; + return $scope.$modelValue.length > 0; }; $scope.safeApply = function(fn) { @@ -379,11 +377,10 @@ }; $scope.removeNode = function(node) { - var index = $scope.$nodes.indexOf(node); + var index = $scope.$modelValue.indexOf(node.$modelValue); if (index > -1) { $scope.safeApply(function() { $scope.$modelValue.splice(index, 1)[0]; - $scope.$nodes.splice(index, 1)[0]; }); return node; } @@ -396,6 +393,13 @@ }); }; + $scope.childNodes = function() { + var nodes = []; + for (var i = 0; i < $scope.$modelValue.length; i++) { + nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]); + } + return nodes; + }; $scope.depth = function() { if ($scope.$nodeScope) { @@ -433,7 +437,7 @@ $scope.$treeScope = null; // uiTree scope $scope.$handleScope = null; // it's handle scope $scope.$type = 'uiTreeNode'; - $scope.$$apply = false; // + $scope.$$apply = false; // $scope.collapsed = false; @@ -449,6 +453,7 @@ treeNodesCtrl.scope.initSubNode($scope); // init sub nodes $element.on('$destroy', function() { + treeNodesCtrl.scope.destroySubNode($scope); // destroy sub nodes }); }; @@ -478,7 +483,7 @@ }; $scope.siblings = function() { - return $scope.$parentNodesScope.$nodes; + return $scope.$parentNodesScope.childNodes(); }; $scope.childNodesCount = function() { @@ -490,7 +495,7 @@ }; $scope.childNodes = function() { - return $scope.$childNodesScope ? $scope.$childNodesScope.$nodes : null; + return $scope.$childNodesScope ? $scope.$childNodesScope.childNodes() : null; }; $scope.accept = function(sourceNode, destIndex) { @@ -524,8 +529,9 @@ var subDepth = 0; var countSubDepth = function(scope) { var count = 0; - for (var i = 0; i < scope.$nodes.length; i++) { - var childNodes = scope.$nodes[i].$childNodesScope; + var nodes = scope.childNodes(); + for (var i = 0; i < nodes.length; i++) { + var childNodes = nodes[i].$childNodesScope; if (childNodes) { count = 1; countSubDepth(childNodes); @@ -690,11 +696,15 @@ scope.$treeScope = treeCtrl.scope; if (ngModel) { - scope.$watch(attrs.ngModel, function() { + ngModel.$render = function() { scope.$modelValue = ngModel.$modelValue; - scope.reinitNodes(); // we have to keep syncing with $nodes array - }, true); + }; } + /* + scope.$watch(attrs.ngModel, function() { + scope.$modelValue = ngModel.$modelValue; + }, true); + */ scope.$watch(function() { return scope.$eval(attrs.maxDepth); @@ -923,7 +933,7 @@ treeScope = targetNode; if (targetNode.$nodesScope.accept(scope, 0)) { targetNode.place(placeElm); - dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.$nodes, 0); + dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0); } } else if (targetNode.dragEnabled()){ // drag enabled targetElm = targetNode.$element; // Get the element of ui-tree-node diff --git a/demo/dist/angular-ui-tree.min.js b/demo/dist/angular-ui-tree.min.js index 10f07547..da208855 100644 --- a/demo/dist/angular-ui-tree.min.js +++ b/demo/dist/angular-ui-tree.min.js @@ -1,6 +1,6 @@ /** - * @license Angular UI Tree v2.0.8 + * @license Angular UI Tree v2.0.9 * (c) 2010-2014. https://github.com/JimLiu/angular-ui-tree * License: MIT */ -!function(){"use strict";angular.module("ui.tree",[]).constant("treeConfig",{treeClass:"angular-ui-tree",emptyTreeClass:"angular-ui-tree-empty",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,levelThreshold:30})}(),function(){"use strict";angular.module("ui.tree").factory("$uiTreeHelper",["$document","$window",function($document,$window){return{nodrag:function(targetElm){return"undefined"!=typeof targetElm.attr("data-nodrag")},eventObj:function(e){var obj=e;return void 0!==e.targetTouches?obj=e.targetTouches.item(0):void 0!==e.originalEvent&&void 0!==e.originalEvent.targetTouches&&(obj=e.originalEvent.targetTouches.item(0)),obj},dragInfo:function(node){return{source:node,sourceInfo:{nodeScope:node,index:node.index(),nodesScope:node.$parentNodesScope},index:node.index(),siblings:node.$parentNodesScope.$nodes.slice(0),parent:node.$parentNodesScope,moveTo:function(parent,siblings,index){this.parent=parent,this.siblings=siblings.slice(0);var i=this.siblings.indexOf(this.source);i>-1&&(this.siblings.splice(i,1),this.source.index()0?this.siblings[this.index-1]:null},next:function(){return this.index0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;return firstMoving?(pos.dirAx=newAx,void(pos.moving=!0)):(pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),void(pos.dirAx=newAx))}}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeController",["$scope","$element","$attrs","treeConfig",function($scope,$element){this.scope=$scope,$scope.$element=$element,$scope.$nodesScope=null,$scope.$type="uiTree",$scope.$emptyElm=null,$scope.$callbacks=null,$scope.dragEnabled=!0,$scope.maxDepth=0,$scope.isEmpty=function(){return $scope.$nodesScope&&$scope.$nodesScope.$modelValue&&0===$scope.$nodesScope.$modelValue.length},$scope.place=function(placeElm){$scope.$nodesScope.$element.append(placeElm),$scope.$emptyElm.remove()},$scope.resetEmptyElement=function(){0===$scope.$nodesScope.$modelValue.length?$element.append($scope.$emptyElm):$scope.$emptyElm.remove()};var collapseOrExpand=function(scope,collapsed){for(var i=0;i0},$scope.safeApply=function(fn){var phase=this.$root.$$phase;"$apply"==phase||"$digest"==phase?fn&&"function"==typeof fn&&fn():this.$apply(fn)},$scope.removeNode=function(node){var index=$scope.$nodes.indexOf(node);return index>-1?($scope.safeApply(function(){$scope.$modelValue.splice(index,1)[0],$scope.$nodes.splice(index,1)[0]}),node):null},$scope.insertNode=function(index,nodeData){$scope.safeApply(function(){$scope.$modelValue.splice(index,0,nodeData)})},$scope.depth=function(){return $scope.$nodeScope?$scope.$nodeScope.depth():0},$scope.outOfDepth=function(sourceNode){var maxDepth=$scope.maxDepth||$scope.$treeScope.maxDepth;return maxDepth>0?$scope.depth()+sourceNode.maxSubDepth()+1>maxDepth:!1}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeNodeController",["$scope","$element","$attrs","treeConfig",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.$$apply=!1,$scope.collapsed=!1,$scope.init=function(controllersArr){var treeNodesCtrl=controllersArr[0];$scope.$treeScope=controllersArr[1]?controllersArr[1].scope:null,$scope.$parentNodeScope=treeNodesCtrl.scope.$nodeScope,$scope.$modelValue=treeNodesCtrl.scope.$modelValue[$scope.$index],$scope.$parentNodesScope=treeNodesCtrl.scope,treeNodesCtrl.scope.initSubNode($scope),$element.on("$destroy",function(){})},$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();return index>0?$scope.siblings()[index-1]:null},$scope.siblings=function(){return $scope.$parentNodesScope.$nodes},$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.$nodes:null},$scope.accept=function(sourceNode,destIndex){return $scope.$childNodesScope&&$scope.$childNodesScope.accept(sourceNode,destIndex)},$scope.remove=function(){return $scope.$parentNodesScope.removeNode($scope)},$scope.toggle=function(){$scope.collapsed=!$scope.collapsed},$scope.collapse=function(){$scope.collapsed=!0},$scope.expand=function(){$scope.collapsed=!1},$scope.depth=function(){var parentNode=$scope.$parentNodeScope;return parentNode?parentNode.depth()+1:1};var subDepth=0,countSubDepth=function(scope){for(var count=0,i=0;i=config.levelThreshold&&(pos.distAxX=0,pos.distX>0&&(prev=dragInfo.prev(),prev&&!prev.collapsed&&prev.accept(scope,prev.childNodesCount())&&(prev.$childNodesScope.$element.append(placeElm),dragInfo.moveTo(prev.$childNodesScope,prev.childNodes(),prev.childNodesCount()))),pos.distX<0)){var next=dragInfo.next();if(!next){var target=dragInfo.parentNode();target&&target.$parentNodesScope.accept(scope,target.index()+1)&&(target.$element.after(placeElm),dragInfo.moveTo(target.$parentNodesScope,target.siblings(),target.index()+1))}}var targetX=($uiTreeHelper.offset(dragElm).left-$uiTreeHelper.offset(placeElm).left>=config.threshold,eventObj.pageX-$window.document.body.scrollLeft),targetY=eventObj.pageY-(window.pageYOffset||$window.document.documentElement.scrollTop);angular.isFunction(dragElm.hide)&&dragElm.hide(),$window.document.elementFromPoint(targetX,targetY);var targetElm=angular.element($window.document.elementFromPoint(targetX,targetY));if(angular.isFunction(dragElm.show)&&dragElm.show(),!pos.dirAx){var targetBefore,targetNode;targetNode=targetElm.scope();var isEmpty=!1;if("uiTree"==targetNode.$type&&targetNode.dragEnabled&&(isEmpty=targetNode.isEmpty()),"uiTreeHandle"==targetNode.$type&&(targetNode=targetNode.$nodeScope),"uiTreeNode"!=targetNode.$type&&!isEmpty)return;if(treeScope&&placeElm.parent()[0]!=treeScope.$element[0]&&(treeScope.resetEmptyElement(),treeScope=null),isEmpty)treeScope=targetNode,targetNode.$nodesScope.accept(scope,0)&&(targetNode.place(placeElm),dragInfo.moveTo(targetNode.$nodesScope,targetNode.$nodesScope.$nodes,0));else if(targetNode.dragEnabled()){targetElm=targetNode.$element;var targetOffset=$uiTreeHelper.offset(targetElm);targetBefore=eventObj.pageY-1&&(this.siblings.splice(i,1),this.source.index()0?this.siblings[this.index-1]:null},next:function(){return this.index0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;return firstMoving?(pos.dirAx=newAx,void(pos.moving=!0)):(pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),void(pos.dirAx=newAx))}}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeController",["$scope","$element","$attrs","treeConfig",function($scope,$element){this.scope=$scope,$scope.$element=$element,$scope.$nodesScope=null,$scope.$type="uiTree",$scope.$emptyElm=null,$scope.$callbacks=null,$scope.dragEnabled=!0,$scope.maxDepth=0,$scope.isEmpty=function(){return $scope.$nodesScope&&$scope.$nodesScope.$modelValue&&0===$scope.$nodesScope.$modelValue.length},$scope.place=function(placeElm){$scope.$nodesScope.$element.append(placeElm),$scope.$emptyElm.remove()},$scope.resetEmptyElement=function(){0===$scope.$nodesScope.$modelValue.length?$element.append($scope.$emptyElm):$scope.$emptyElm.remove()};var collapseOrExpand=function(scope,collapsed){for(var nodes=scope.childNodes(),i=0;i0},$scope.safeApply=function(fn){var phase=this.$root.$$phase;"$apply"==phase||"$digest"==phase?fn&&"function"==typeof fn&&fn():this.$apply(fn)},$scope.removeNode=function(node){var index=$scope.$modelValue.indexOf(node.$modelValue);return index>-1?($scope.safeApply(function(){$scope.$modelValue.splice(index,1)[0]}),node):null},$scope.insertNode=function(index,nodeData){$scope.safeApply(function(){$scope.$modelValue.splice(index,0,nodeData)})},$scope.childNodes=function(){for(var nodes=[],i=0;i<$scope.$modelValue.length;i++)nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]);return nodes},$scope.depth=function(){return $scope.$nodeScope?$scope.$nodeScope.depth():0},$scope.outOfDepth=function(sourceNode){var maxDepth=$scope.maxDepth||$scope.$treeScope.maxDepth;return maxDepth>0?$scope.depth()+sourceNode.maxSubDepth()+1>maxDepth:!1}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeNodeController",["$scope","$element","$attrs","treeConfig",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.$$apply=!1,$scope.collapsed=!1,$scope.init=function(controllersArr){var treeNodesCtrl=controllersArr[0];$scope.$treeScope=controllersArr[1]?controllersArr[1].scope:null,$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();return index>0?$scope.siblings()[index-1]: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.childNodes():null},$scope.accept=function(sourceNode,destIndex){return $scope.$childNodesScope&&$scope.$childNodesScope.accept(sourceNode,destIndex)},$scope.remove=function(){return $scope.$parentNodesScope.removeNode($scope)},$scope.toggle=function(){$scope.collapsed=!$scope.collapsed},$scope.collapse=function(){$scope.collapsed=!0},$scope.expand=function(){$scope.collapsed=!1},$scope.depth=function(){var parentNode=$scope.$parentNodeScope;return parentNode?parentNode.depth()+1:1};var subDepth=0,countSubDepth=function(scope){for(var count=0,nodes=scope.childNodes(),i=0;i=config.levelThreshold&&(pos.distAxX=0,pos.distX>0&&(prev=dragInfo.prev(),prev&&!prev.collapsed&&prev.accept(scope,prev.childNodesCount())&&(prev.$childNodesScope.$element.append(placeElm),dragInfo.moveTo(prev.$childNodesScope,prev.childNodes(),prev.childNodesCount()))),pos.distX<0)){var next=dragInfo.next();if(!next){var target=dragInfo.parentNode();target&&target.$parentNodesScope.accept(scope,target.index()+1)&&(target.$element.after(placeElm),dragInfo.moveTo(target.$parentNodesScope,target.siblings(),target.index()+1))}}var targetX=($uiTreeHelper.offset(dragElm).left-$uiTreeHelper.offset(placeElm).left>=config.threshold,eventObj.pageX-$window.document.body.scrollLeft),targetY=eventObj.pageY-(window.pageYOffset||$window.document.documentElement.scrollTop);angular.isFunction(dragElm.hide)&&dragElm.hide(),$window.document.elementFromPoint(targetX,targetY);var targetElm=angular.element($window.document.elementFromPoint(targetX,targetY));if(angular.isFunction(dragElm.show)&&dragElm.show(),!pos.dirAx){var targetBefore,targetNode;targetNode=targetElm.scope();var isEmpty=!1;if("uiTree"==targetNode.$type&&targetNode.dragEnabled&&(isEmpty=targetNode.isEmpty()),"uiTreeHandle"==targetNode.$type&&(targetNode=targetNode.$nodeScope),"uiTreeNode"!=targetNode.$type&&!isEmpty)return;if(treeScope&&placeElm.parent()[0]!=treeScope.$element[0]&&(treeScope.resetEmptyElement(),treeScope=null),isEmpty)treeScope=targetNode,targetNode.$nodesScope.accept(scope,0)&&(targetNode.place(placeElm),dragInfo.moveTo(targetNode.$nodesScope,targetNode.$nodesScope.childNodes(),0));else if(targetNode.dragEnabled()){targetElm=targetNode.$element;var targetOffset=$uiTreeHelper.offset(targetElm);targetBefore=eventObj.pageY 0; + return $scope.$modelValue.length > 0; }; $scope.safeApply = function(fn) { @@ -379,11 +377,10 @@ }; $scope.removeNode = function(node) { - var index = $scope.$nodes.indexOf(node); + var index = $scope.$modelValue.indexOf(node.$modelValue); if (index > -1) { $scope.safeApply(function() { $scope.$modelValue.splice(index, 1)[0]; - $scope.$nodes.splice(index, 1)[0]; }); return node; } @@ -396,6 +393,13 @@ }); }; + $scope.childNodes = function() { + var nodes = []; + for (var i = 0; i < $scope.$modelValue.length; i++) { + nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]); + } + return nodes; + }; $scope.depth = function() { if ($scope.$nodeScope) { @@ -433,7 +437,7 @@ $scope.$treeScope = null; // uiTree scope $scope.$handleScope = null; // it's handle scope $scope.$type = 'uiTreeNode'; - $scope.$$apply = false; // + $scope.$$apply = false; // $scope.collapsed = false; @@ -449,6 +453,7 @@ treeNodesCtrl.scope.initSubNode($scope); // init sub nodes $element.on('$destroy', function() { + treeNodesCtrl.scope.destroySubNode($scope); // destroy sub nodes }); }; @@ -478,7 +483,7 @@ }; $scope.siblings = function() { - return $scope.$parentNodesScope.$nodes; + return $scope.$parentNodesScope.childNodes(); }; $scope.childNodesCount = function() { @@ -490,7 +495,7 @@ }; $scope.childNodes = function() { - return $scope.$childNodesScope ? $scope.$childNodesScope.$nodes : null; + return $scope.$childNodesScope ? $scope.$childNodesScope.childNodes() : null; }; $scope.accept = function(sourceNode, destIndex) { @@ -524,8 +529,9 @@ var subDepth = 0; var countSubDepth = function(scope) { var count = 0; - for (var i = 0; i < scope.$nodes.length; i++) { - var childNodes = scope.$nodes[i].$childNodesScope; + var nodes = scope.childNodes(); + for (var i = 0; i < nodes.length; i++) { + var childNodes = nodes[i].$childNodesScope; if (childNodes) { count = 1; countSubDepth(childNodes); @@ -690,11 +696,15 @@ scope.$treeScope = treeCtrl.scope; if (ngModel) { - scope.$watch(attrs.ngModel, function() { + ngModel.$render = function() { scope.$modelValue = ngModel.$modelValue; - scope.reinitNodes(); // we have to keep syncing with $nodes array - }, true); + }; } + /* + scope.$watch(attrs.ngModel, function() { + scope.$modelValue = ngModel.$modelValue; + }, true); + */ scope.$watch(function() { return scope.$eval(attrs.maxDepth); @@ -923,7 +933,7 @@ treeScope = targetNode; if (targetNode.$nodesScope.accept(scope, 0)) { targetNode.place(placeElm); - dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.$nodes, 0); + dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0); } } else if (targetNode.dragEnabled()){ // drag enabled targetElm = targetNode.$element; // Get the element of ui-tree-node diff --git a/dist/angular-ui-tree.min.js b/dist/angular-ui-tree.min.js index 10f07547..da208855 100644 --- a/dist/angular-ui-tree.min.js +++ b/dist/angular-ui-tree.min.js @@ -1,6 +1,6 @@ /** - * @license Angular UI Tree v2.0.8 + * @license Angular UI Tree v2.0.9 * (c) 2010-2014. https://github.com/JimLiu/angular-ui-tree * License: MIT */ -!function(){"use strict";angular.module("ui.tree",[]).constant("treeConfig",{treeClass:"angular-ui-tree",emptyTreeClass:"angular-ui-tree-empty",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,levelThreshold:30})}(),function(){"use strict";angular.module("ui.tree").factory("$uiTreeHelper",["$document","$window",function($document,$window){return{nodrag:function(targetElm){return"undefined"!=typeof targetElm.attr("data-nodrag")},eventObj:function(e){var obj=e;return void 0!==e.targetTouches?obj=e.targetTouches.item(0):void 0!==e.originalEvent&&void 0!==e.originalEvent.targetTouches&&(obj=e.originalEvent.targetTouches.item(0)),obj},dragInfo:function(node){return{source:node,sourceInfo:{nodeScope:node,index:node.index(),nodesScope:node.$parentNodesScope},index:node.index(),siblings:node.$parentNodesScope.$nodes.slice(0),parent:node.$parentNodesScope,moveTo:function(parent,siblings,index){this.parent=parent,this.siblings=siblings.slice(0);var i=this.siblings.indexOf(this.source);i>-1&&(this.siblings.splice(i,1),this.source.index()0?this.siblings[this.index-1]:null},next:function(){return this.index0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;return firstMoving?(pos.dirAx=newAx,void(pos.moving=!0)):(pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),void(pos.dirAx=newAx))}}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeController",["$scope","$element","$attrs","treeConfig",function($scope,$element){this.scope=$scope,$scope.$element=$element,$scope.$nodesScope=null,$scope.$type="uiTree",$scope.$emptyElm=null,$scope.$callbacks=null,$scope.dragEnabled=!0,$scope.maxDepth=0,$scope.isEmpty=function(){return $scope.$nodesScope&&$scope.$nodesScope.$modelValue&&0===$scope.$nodesScope.$modelValue.length},$scope.place=function(placeElm){$scope.$nodesScope.$element.append(placeElm),$scope.$emptyElm.remove()},$scope.resetEmptyElement=function(){0===$scope.$nodesScope.$modelValue.length?$element.append($scope.$emptyElm):$scope.$emptyElm.remove()};var collapseOrExpand=function(scope,collapsed){for(var i=0;i0},$scope.safeApply=function(fn){var phase=this.$root.$$phase;"$apply"==phase||"$digest"==phase?fn&&"function"==typeof fn&&fn():this.$apply(fn)},$scope.removeNode=function(node){var index=$scope.$nodes.indexOf(node);return index>-1?($scope.safeApply(function(){$scope.$modelValue.splice(index,1)[0],$scope.$nodes.splice(index,1)[0]}),node):null},$scope.insertNode=function(index,nodeData){$scope.safeApply(function(){$scope.$modelValue.splice(index,0,nodeData)})},$scope.depth=function(){return $scope.$nodeScope?$scope.$nodeScope.depth():0},$scope.outOfDepth=function(sourceNode){var maxDepth=$scope.maxDepth||$scope.$treeScope.maxDepth;return maxDepth>0?$scope.depth()+sourceNode.maxSubDepth()+1>maxDepth:!1}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeNodeController",["$scope","$element","$attrs","treeConfig",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.$$apply=!1,$scope.collapsed=!1,$scope.init=function(controllersArr){var treeNodesCtrl=controllersArr[0];$scope.$treeScope=controllersArr[1]?controllersArr[1].scope:null,$scope.$parentNodeScope=treeNodesCtrl.scope.$nodeScope,$scope.$modelValue=treeNodesCtrl.scope.$modelValue[$scope.$index],$scope.$parentNodesScope=treeNodesCtrl.scope,treeNodesCtrl.scope.initSubNode($scope),$element.on("$destroy",function(){})},$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();return index>0?$scope.siblings()[index-1]:null},$scope.siblings=function(){return $scope.$parentNodesScope.$nodes},$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.$nodes:null},$scope.accept=function(sourceNode,destIndex){return $scope.$childNodesScope&&$scope.$childNodesScope.accept(sourceNode,destIndex)},$scope.remove=function(){return $scope.$parentNodesScope.removeNode($scope)},$scope.toggle=function(){$scope.collapsed=!$scope.collapsed},$scope.collapse=function(){$scope.collapsed=!0},$scope.expand=function(){$scope.collapsed=!1},$scope.depth=function(){var parentNode=$scope.$parentNodeScope;return parentNode?parentNode.depth()+1:1};var subDepth=0,countSubDepth=function(scope){for(var count=0,i=0;i=config.levelThreshold&&(pos.distAxX=0,pos.distX>0&&(prev=dragInfo.prev(),prev&&!prev.collapsed&&prev.accept(scope,prev.childNodesCount())&&(prev.$childNodesScope.$element.append(placeElm),dragInfo.moveTo(prev.$childNodesScope,prev.childNodes(),prev.childNodesCount()))),pos.distX<0)){var next=dragInfo.next();if(!next){var target=dragInfo.parentNode();target&&target.$parentNodesScope.accept(scope,target.index()+1)&&(target.$element.after(placeElm),dragInfo.moveTo(target.$parentNodesScope,target.siblings(),target.index()+1))}}var targetX=($uiTreeHelper.offset(dragElm).left-$uiTreeHelper.offset(placeElm).left>=config.threshold,eventObj.pageX-$window.document.body.scrollLeft),targetY=eventObj.pageY-(window.pageYOffset||$window.document.documentElement.scrollTop);angular.isFunction(dragElm.hide)&&dragElm.hide(),$window.document.elementFromPoint(targetX,targetY);var targetElm=angular.element($window.document.elementFromPoint(targetX,targetY));if(angular.isFunction(dragElm.show)&&dragElm.show(),!pos.dirAx){var targetBefore,targetNode;targetNode=targetElm.scope();var isEmpty=!1;if("uiTree"==targetNode.$type&&targetNode.dragEnabled&&(isEmpty=targetNode.isEmpty()),"uiTreeHandle"==targetNode.$type&&(targetNode=targetNode.$nodeScope),"uiTreeNode"!=targetNode.$type&&!isEmpty)return;if(treeScope&&placeElm.parent()[0]!=treeScope.$element[0]&&(treeScope.resetEmptyElement(),treeScope=null),isEmpty)treeScope=targetNode,targetNode.$nodesScope.accept(scope,0)&&(targetNode.place(placeElm),dragInfo.moveTo(targetNode.$nodesScope,targetNode.$nodesScope.$nodes,0));else if(targetNode.dragEnabled()){targetElm=targetNode.$element;var targetOffset=$uiTreeHelper.offset(targetElm);targetBefore=eventObj.pageY-1&&(this.siblings.splice(i,1),this.source.index()0?this.siblings[this.index-1]:null},next:function(){return this.index0?1:-1,pos.dirY=0===pos.distY?0:pos.distY>0?1:-1;var newAx=Math.abs(pos.distX)>Math.abs(pos.distY)?1:0;return firstMoving?(pos.dirAx=newAx,void(pos.moving=!0)):(pos.dirAx!==newAx?(pos.distAxX=0,pos.distAxY=0):(pos.distAxX+=Math.abs(pos.distX),0!==pos.dirX&&pos.dirX!==pos.lastDirX&&(pos.distAxX=0),pos.distAxY+=Math.abs(pos.distY),0!==pos.dirY&&pos.dirY!==pos.lastDirY&&(pos.distAxY=0)),void(pos.dirAx=newAx))}}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeController",["$scope","$element","$attrs","treeConfig",function($scope,$element){this.scope=$scope,$scope.$element=$element,$scope.$nodesScope=null,$scope.$type="uiTree",$scope.$emptyElm=null,$scope.$callbacks=null,$scope.dragEnabled=!0,$scope.maxDepth=0,$scope.isEmpty=function(){return $scope.$nodesScope&&$scope.$nodesScope.$modelValue&&0===$scope.$nodesScope.$modelValue.length},$scope.place=function(placeElm){$scope.$nodesScope.$element.append(placeElm),$scope.$emptyElm.remove()},$scope.resetEmptyElement=function(){0===$scope.$nodesScope.$modelValue.length?$element.append($scope.$emptyElm):$scope.$emptyElm.remove()};var collapseOrExpand=function(scope,collapsed){for(var nodes=scope.childNodes(),i=0;i0},$scope.safeApply=function(fn){var phase=this.$root.$$phase;"$apply"==phase||"$digest"==phase?fn&&"function"==typeof fn&&fn():this.$apply(fn)},$scope.removeNode=function(node){var index=$scope.$modelValue.indexOf(node.$modelValue);return index>-1?($scope.safeApply(function(){$scope.$modelValue.splice(index,1)[0]}),node):null},$scope.insertNode=function(index,nodeData){$scope.safeApply(function(){$scope.$modelValue.splice(index,0,nodeData)})},$scope.childNodes=function(){for(var nodes=[],i=0;i<$scope.$modelValue.length;i++)nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]);return nodes},$scope.depth=function(){return $scope.$nodeScope?$scope.$nodeScope.depth():0},$scope.outOfDepth=function(sourceNode){var maxDepth=$scope.maxDepth||$scope.$treeScope.maxDepth;return maxDepth>0?$scope.depth()+sourceNode.maxSubDepth()+1>maxDepth:!1}}])}(),function(){"use strict";angular.module("ui.tree").controller("TreeNodeController",["$scope","$element","$attrs","treeConfig",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.$$apply=!1,$scope.collapsed=!1,$scope.init=function(controllersArr){var treeNodesCtrl=controllersArr[0];$scope.$treeScope=controllersArr[1]?controllersArr[1].scope:null,$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();return index>0?$scope.siblings()[index-1]: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.childNodes():null},$scope.accept=function(sourceNode,destIndex){return $scope.$childNodesScope&&$scope.$childNodesScope.accept(sourceNode,destIndex)},$scope.remove=function(){return $scope.$parentNodesScope.removeNode($scope)},$scope.toggle=function(){$scope.collapsed=!$scope.collapsed},$scope.collapse=function(){$scope.collapsed=!0},$scope.expand=function(){$scope.collapsed=!1},$scope.depth=function(){var parentNode=$scope.$parentNodeScope;return parentNode?parentNode.depth()+1:1};var subDepth=0,countSubDepth=function(scope){for(var count=0,nodes=scope.childNodes(),i=0;i=config.levelThreshold&&(pos.distAxX=0,pos.distX>0&&(prev=dragInfo.prev(),prev&&!prev.collapsed&&prev.accept(scope,prev.childNodesCount())&&(prev.$childNodesScope.$element.append(placeElm),dragInfo.moveTo(prev.$childNodesScope,prev.childNodes(),prev.childNodesCount()))),pos.distX<0)){var next=dragInfo.next();if(!next){var target=dragInfo.parentNode();target&&target.$parentNodesScope.accept(scope,target.index()+1)&&(target.$element.after(placeElm),dragInfo.moveTo(target.$parentNodesScope,target.siblings(),target.index()+1))}}var targetX=($uiTreeHelper.offset(dragElm).left-$uiTreeHelper.offset(placeElm).left>=config.threshold,eventObj.pageX-$window.document.body.scrollLeft),targetY=eventObj.pageY-(window.pageYOffset||$window.document.documentElement.scrollTop);angular.isFunction(dragElm.hide)&&dragElm.hide(),$window.document.elementFromPoint(targetX,targetY);var targetElm=angular.element($window.document.elementFromPoint(targetX,targetY));if(angular.isFunction(dragElm.show)&&dragElm.show(),!pos.dirAx){var targetBefore,targetNode;targetNode=targetElm.scope();var isEmpty=!1;if("uiTree"==targetNode.$type&&targetNode.dragEnabled&&(isEmpty=targetNode.isEmpty()),"uiTreeHandle"==targetNode.$type&&(targetNode=targetNode.$nodeScope),"uiTreeNode"!=targetNode.$type&&!isEmpty)return;if(treeScope&&placeElm.parent()[0]!=treeScope.$element[0]&&(treeScope.resetEmptyElement(),treeScope=null),isEmpty)treeScope=targetNode,targetNode.$nodesScope.accept(scope,0)&&(targetNode.place(placeElm),dragInfo.moveTo(targetNode.$nodesScope,targetNode.$nodesScope.childNodes(),0));else if(targetNode.dragEnabled()){targetElm=targetNode.$element;var targetOffset=$uiTreeHelper.offset(targetElm);targetBefore=eventObj.pageY 0; + return $scope.$modelValue.length > 0; }; $scope.safeApply = function(fn) { @@ -54,11 +51,10 @@ }; $scope.removeNode = function(node) { - var index = $scope.$nodes.indexOf(node); + var index = $scope.$modelValue.indexOf(node.$modelValue); if (index > -1) { $scope.safeApply(function() { $scope.$modelValue.splice(index, 1)[0]; - $scope.$nodes.splice(index, 1)[0]; }); return node; } @@ -71,6 +67,13 @@ }); }; + $scope.childNodes = function() { + var nodes = []; + for (var i = 0; i < $scope.$modelValue.length; i++) { + nodes.push($scope.$nodesMap[$scope.$modelValue[i].$$hashKey]); + } + return nodes; + }; $scope.depth = function() { if ($scope.$nodeScope) { diff --git a/source/controllers/treeCtrl.js b/source/controllers/treeCtrl.js index 625cb350..518b55ef 100644 --- a/source/controllers/treeCtrl.js +++ b/source/controllers/treeCtrl.js @@ -37,9 +37,10 @@ }; var collapseOrExpand = function(scope, collapsed) { - for (var i = 0; i < scope.$nodes.length; i++) { - collapsed ? scope.$nodes[i].collapse() : scope.$nodes[i].expand(); - var subScope = scope.$nodes[i].$childNodesScope; + var nodes = scope.childNodes(); + for (var i = 0; i < nodes.length; i++) { + collapsed ? nodes[i].collapse() : nodes[i].expand(); + var subScope = nodes[i].$childNodesScope; if (subScope) { collapseOrExpand(subScope, collapsed); } diff --git a/source/directives/uiTreeNode.js b/source/directives/uiTreeNode.js index c976d3a3..f74eb921 100644 --- a/source/directives/uiTreeNode.js +++ b/source/directives/uiTreeNode.js @@ -204,7 +204,7 @@ treeScope = targetNode; if (targetNode.$nodesScope.accept(scope, 0)) { targetNode.place(placeElm); - dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.$nodes, 0); + dragInfo.moveTo(targetNode.$nodesScope, targetNode.$nodesScope.childNodes(), 0); } } else if (targetNode.dragEnabled()){ // drag enabled targetElm = targetNode.$element; // Get the element of ui-tree-node diff --git a/source/directives/uiTreeNodes.js b/source/directives/uiTreeNodes.js index 68ef6913..5fde15ed 100644 --- a/source/directives/uiTreeNodes.js +++ b/source/directives/uiTreeNodes.js @@ -30,11 +30,15 @@ scope.$treeScope = treeCtrl.scope; if (ngModel) { - scope.$watch(attrs.ngModel, function() { + ngModel.$render = function() { scope.$modelValue = ngModel.$modelValue; - scope.reinitNodes(); // we have to keep syncing with $nodes array - }, true); + }; } + /* + scope.$watch(attrs.ngModel, function() { + scope.$modelValue = ngModel.$modelValue; + }, true); + */ scope.$watch(function() { return scope.$eval(attrs.maxDepth); diff --git a/source/main.js b/source/main.js index 9ed73505..f022b7d5 100644 --- a/source/main.js +++ b/source/main.js @@ -1,5 +1,5 @@ /** - * @license Angular UI Tree v2.0.8 + * @license Angular UI Tree v2.0.9 * (c) 2010-2014. https://github.com/JimLiu/angular-ui-tree * License: MIT */ diff --git a/source/services/helper.js b/source/services/helper.js index 0743228d..e0f6031d 100644 --- a/source/services/helper.js +++ b/source/services/helper.js @@ -50,7 +50,7 @@ nodesScope: node.$parentNodesScope, }, index: node.index(), - siblings: node.$parentNodesScope.$nodes.slice(0), + siblings: node.siblings().slice(0), parent: node.$parentNodesScope, moveTo: function(parent, siblings, index) { // Move the node to a new position