Updates tree item directive to have far less angular bindings and sets up much of the DOM manually, this improves perf in a big way when lots of nodes are rendered... still needs more of this though!

This commit is contained in:
Shannon
2014-10-13 14:27:07 +11:00
parent 3c7fb8aeff
commit 7a7f31b7a6

View File

@@ -31,20 +31,25 @@ angular.module("umbraco.directives")
tree: '='
},
template: '<li ng-class="{\'current\': (node == currentNode)}" on-right-click="altSelect(node, $event)"><div ng-style="setTreePadding(node)" ng-class="node.stateCssClass" ng-class="{\'loading\': node.loading}" ng-swipe-right="options(node, $event)" >' +
//TODO: Remove more of the binding from this template and move the DOM manipulation to be manually done in the link function,
// this will greatly improve performance since there's potentially a lot of nodes being rendered = a LOT of watches!
template: '<li ng-class="{\'current\': (node == currentNode)}" on-right-click="altSelect(node, $event)">' +
'<div ng-class="{\'loading\': node.loading}" ng-swipe-right="options(node, $event)" >' +
//NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog
'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
'<ins ng-if="node.hasChildren" style="width:18px;"></ins>' +
'<ins ng-show="node.hasChildren" ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"></ins>' +
//'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
'<ins style="width:18px;"></ins>' +
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"></ins>' +
//NOTE: If the tree supports check boxes, render different markup
'<i ng-if="tree.enablecheckboxes == \'true\'" title="#{{node.routePath}}" ng-class="selectEnabledNodeClass(node)"></i>' +
'<i ng-if="!tree.enablecheckboxes || tree.enablecheckboxes == \'false\'" title="#{{node.routePath}}" class="{{node.cssClass}}"></i>' +
'<a href ng-click="select(node, $event)" on-right-click="altSelect(node, $event)" ng-bind-html="node.name"></a>' +
'<a href class="umb-options" ng-hide="!node.menuUrl" ng-click="options(node, $event)"><i></i><i></i><i></i></a>' +
'<i ng-class="selectEnabledNodeClass(node)"></i>' +
'<i class="{{node.cssClass}}"></i>' +
'<a href ng-click="select(node, $event)" on-right-click="altSelect(node, $event)"></a>' +
//NOTE: These are the 'option' elipses
'<a href class="umb-options" ng-click="options(node, $event)"><i></i><i></i><i></i></a>' +
'<div ng-show="node.loading" class="l"><div></div></div>' +
'</div>' +
'</li>',
link: function (scope, element, attrs) {
localizationService.localize("general_search").then(function (value) {
@@ -61,12 +66,44 @@ angular.module("umbraco.directives")
}
}
/** updates the node's styles */
function styleNode(node) {
node.stateCssClass = (node.cssClasses || []).join(" ");
/** updates the node's DOM/styles */
function setupNodeDom(node, tree) {
//get the first div element
element.children(":first")
//set the padding
.css("padding-left", (node.level * 20) + "px")
//set the class
.addClass((node.cssClasses || []).join(" "));
//remove first 'ins' if there is no children
//show/hide last 'ins' depending on children
if (!node.hasChildren) {
element.find("ins:first").remove();
element.find("ins").last().hide();
}
else {
element.find("ins").last().show();
}
//add/remove 'i' depending on enablecheckboxes
if (tree.enablecheckboxes === "true") {
element.find("i").eq(1).remove();
element.find("i:first").attr("title", node.routePath);
}
else if (!tree.enablecheckboxes || tree.enablecheckboxes === 'false') {
element.find("i:first").remove();
element.find("i").eq(1).attr("title", node.routePath);
}
element.find("a:first").html(node.name);
if (!node.menuUrl) {
element.find("a:last").remove();
}
if (node.style) {
$(element).find("i:first").attr("style", node.style);
element.find("i:first").attr("style", node.style);
}
}
@@ -93,7 +130,7 @@ angular.module("umbraco.directives")
scope.node.updateNodeData = function (newNode) {
_.extend(scope.node, newNode);
//now update the styles
styleNode(scope.node);
setupNodeDom(scope.node, scope.tree);
};
/**
@@ -126,10 +163,6 @@ angular.module("umbraco.directives")
emitEvent("treeNodeAltSelect", { element: element, tree: scope.tree, node: n, event: ev });
};
scope.searchNode = function (n, ev) {
emitEvent("treeNodeSearch", { element: element, tree: scope.tree, node: n, event: ev });
};
/** method to set the current animation for the node.
* This changes dynamically based on if we are changing sections or just loading normal tree data.
* When changing sections we don't want all of the tree-ndoes to do their 'leave' animations.
@@ -178,20 +211,11 @@ angular.module("umbraco.directives")
node.expanded = true;
enableDeleteAnimations();
}
};
/**
Helper method for setting correct element padding on tree DOM elements
Since elements are not children of eachother, we need this indenting done
manually
*/
scope.setTreePadding = function (node) {
return { 'padding-left': (node.level * 20) + "px" };
};
};
//if the current path contains the node id, we will auto-expand the tree item children
styleNode(scope.node);
setupNodeDom(scope.node, scope.tree);
var template = '<ul ng-class="{collapsed: !node.expanded}"><umb-tree-item ng-repeat="child in node.children" eventhandler="eventhandler" tree="tree" current-node="currentNode" node="child" section="{{section}}" ng-animate="animation()"></umb-tree-item></ul>';
var newElement = angular.element(template);