Fixes issue with tree picker and search where the already selected nodes would be cleared when searching and not selecting anything. Adds transition to go to search.

This commit is contained in:
Shannon
2014-10-15 15:57:04 +10:00
parent 4121e3a427
commit bd0a1e66f2
6 changed files with 129 additions and 56 deletions

View File

@@ -35,14 +35,12 @@ angular.module("umbraco.directives")
// 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)" >' +
'<div ng-class="getNodeCssClass(node)" 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 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-class="selectEnabledNodeClass(node)"></i>' +
'<i></i>' +
'<i class="icon umb-tree-icon sprTree"></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>' +
@@ -56,25 +54,23 @@ angular.module("umbraco.directives")
scope.searchAltText = value;
});
//flag to enable/disable delete animations, default for an item is tru
//flag to enable/disable delete animations, default for an item is true
var deleteAnimations = true;
/** Helper function to emit tree events */
// Helper function to emit tree events
function emitEvent(eventName, args) {
if (scope.eventhandler) {
$(scope.eventhandler).trigger(eventName, args);
}
}
/** updates the node's DOM/styles */
// 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(" "));
.css("padding-left", (node.level * 20) + "px");
//remove first 'ins' if there is no children
//show/hide last 'ins' depending on children
@@ -85,17 +81,10 @@ angular.module("umbraco.directives")
else {
element.find("ins").last().show();
}
//add/remove 'i' depending on enablecheckboxes
if (tree.enablecheckboxes === "true") {
element.find("i").eq(1).remove();
}
else if (!tree.enablecheckboxes || tree.enablecheckboxes === 'false') {
element.find("i:first").remove();
element.find("i:first").addClass(node.cssClass);
}
//now set the title on the remaining icon
element.find("i:first").attr("title", node.routePath);
var icon = element.find("i:first");
icon.addClass(node.cssClass);
icon.attr("title", node.routePath);
element.find("a:first").html(node.name);
@@ -108,7 +97,7 @@ angular.module("umbraco.directives")
}
}
/** This will deleteAnimations to true after the current digest */
//This will deleteAnimations to true after the current digest
function enableDeleteAnimations() {
//do timeout so that it re-enables them after this digest
$timeout(function () {
@@ -117,12 +106,21 @@ angular.module("umbraco.directives")
}, 0, false);
}
scope.selectEnabledNodeClass = function (node) {
return node ?
node.selected ?
'icon umb-tree-icon sprTree icon-check blue temporary' :
node.cssClass :
'';
/** Returns the css classses assigned to the node (div element) */
scope.getNodeCssClass = function (node) {
if (!node) {
return '';
}
var css = [];
if (node.cssClasses) {
_.each(node.cssClasses, function(c) {
css.push(c);
});
}
if (node.selected) {
css.push("umb-tree-node-checked");
}
return css.join(" ");
};
//add a method to the node which we can use to call to update the node data if we need to ,
@@ -169,6 +167,9 @@ angular.module("umbraco.directives")
* When changing sections we don't want all of the tree-ndoes to do their 'leave' animations.
*/
scope.animation = function () {
if (scope.node.showHideAnimation) {
return scope.node.showHideAnimation;
}
if (deleteAnimations && scope.node.expanded) {
return { leave: 'tree-node-delete-leave' };
}

View File

@@ -145,3 +145,47 @@
.tree-node-delete-leave * {
color:@red !important;
}
.tree-node-slide-up
{
opacity:1;
top: 0px;
-webkit-transition: 700ms cubic-bezier(0.000, 0.000, 0.580, 1.000) all;
-moz-transition: 700ms cubic-bezier(0.000, 0.000, 0.580, 1.000) all;
-ms-transition: 700ms cubic-bezier(0.000, 0.000, 0.580, 1.000) all;
-o-transition: 700ms cubic-bezier(0.000, 0.000, 0.580, 1.000) all;
transition: 700ms cubic-bezier(0.000, 0.000, 0.580, 1.000) all;
}
.tree-node-slide-up * {
font-size:100%;
-webkit-transition:font-size 700ms;
-moz-transition:font-size 700ms;
-ms-transition:font-size 700ms;
-o-transition:font-size 700ms;
transition:font-size 700ms;
}
.tree-node-slide-up.tree-node-slide-up-hide-active {
opacity: 0;
top: -100px;
}
.tree-node-slide-up.tree-node-slide-up-hide-active * {
font-size:120%;
}
.tree-fade-out-hide ,
.tree-fade-out-show,
.tree-fade-out-hide div:not(.tree-node-slide-up-hide-active),
.tree-fade-out-show div:not(.tree-node-slide-up-hide-active) {
-webkit-transition: 700ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
-moz-transition: 700ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
-ms-transition: 700ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
-o-transition: 700ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
transition: 700ms cubic-bezier(0.075, 0.820, 0.165, 1.000) all;
}
.tree-fade-out-show.tree-fade-out-show-active div:not(.tree-node-slide-up-hide-active){
opacity: 1;
}
.tree-fade-out-hide.tree-fade-out-hide-active div:not(.tree-node-slide-up-hide-active){
opacity: 0;
}

View File

@@ -70,13 +70,13 @@
@import "modals.less";
@import "panel.less";
@import "sections.less";
@import "helveticons.less";
@import "main.less";
@import "tree.less";
@import "listview.less";
@import "gridview.less";
@import "footer.less";
@import "animations.less";
@import "helveticons.less";
@import "dragdrop.less";
//used for property editors

View File

@@ -150,6 +150,18 @@
/*color:@turquoise;*/
}
.icon-check:before {
content: "\e165";
}
.umb-tree .umb-tree-node-checked i {
color:@blue !important;
}
.umb-tree .umb-tree-node-checked i:before {
/*check box*/
content: "\e165" !important;
}
a.umb-options {
visibility: hidden;
cursor: pointer;
@@ -224,6 +236,7 @@ li.root > div > a.umb-options {
}
// Tree item states
// -------------------------
div.not-published > i.icon,div.not-published > a{

View File

@@ -1,6 +1,6 @@
//used for the media picker dialog
angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService) {
function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService) {
var tree = null;
var dialogOptions = $scope.dialogOptions;
@@ -75,20 +75,25 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
child.children = [
{
level: child.level + 1,
hasChildren: false,
hasChildren: false,
parent: function () {
return child;
},
name: searchText,
metaData: {
listViewNode: child,
},
cssClass: "icon umb-tree-icon sprTree icon-search",
cssClass: "icon-search",
cssClasses: ["not-published"]
}
];
//add base transition classes to this node
child.cssClasses.push("tree-node-slide-up");
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function(i) {
return i.parentId == child.id;
});
_.each(listViewResults, function(item) {
var parent = child;
child.children.unshift({
id: item.id,
name: item.name,
@@ -99,7 +104,7 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
},
hasChildren: false,
parent: function () {
return parent;
return child;
}
});
});
@@ -138,6 +143,10 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
$scope.searchInfo.showSearch = true;
$scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id;
$scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name;
//add transition classes
var listViewNode = args.node.parent();
listViewNode.cssClasses.push('tree-node-slide-up-hide-active');
}
else if (args.node.metaData.isSearchResult) {
//check if the item selected was a search result from a list view
@@ -258,14 +267,20 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
return i.id == result.id;
});
}
//ensure the tree node in the tree is checked/unchecked if it already exists there
if (tree) {
var found = treeService.getDescendantNode(tree.root, result.id);
if (found) {
found.selected = result.selected;
}
}
};
$scope.hideSearch = function () {
//TODO: Move this to the treeService, we don't need a reference to the 'tree' the way this is working
// because if we have a single node, that is all we need since we can traverse to the tree root in the treeService.
// this logic needs to be centralized so it can be used in other tree + search areas.
//Traverse the entire displayed tree and update each node to sync with the selected search results
if (tree) {
//we need to ensure that any currently displayed nodes that get selected
@@ -290,14 +305,15 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController",
return c.id == child.id;
});
}
else {
//it's not part of any search result, uncheck it
child.selected = false;
}
//check if the current node is a list view and if so, check if there's any new results
// that need to be added as child nodes to it based on search results selected
if (child.metaData.isContainer) {
child.cssClasses = _.reject(child.cssClasses, function(c) {
return c === 'tree-node-slide-up-hide-active';
});
var listViewResults = _.filter($scope.searchInfo.selectedSearchResults, function (i) {
return i.parentId == child.id;
});

View File

@@ -17,22 +17,21 @@
<div class="tab-content umb-control-group">
<umb-tree-search-results
ng-if="searchInfo.showSearch"
ng-if="searchInfo.showSearch"
results="searchInfo.results"
select-result-callback="selectResult">
</umb-tree-search-results>
<div ng-hide="searchInfo.showSearch">
<umb-tree
section="{{section}}"
treealias="{{treeAlias}}"
hideheader="{{hideHeader}}"
hideoptions="true"
isdialog="true"
customtreeparams="{{customTreeParams}}"
eventhandler="dialogTreeEventHandler"
enablelistviewsearch="true"
enablecheckboxes="{{multiPicker}}">
<div ng-hide="searchInfo.showSearch" ng-animate="'tree-fade-out'">
<umb-tree section="{{section}}"
treealias="{{treeAlias}}"
hideheader="{{hideHeader}}"
hideoptions="true"
isdialog="true"
customtreeparams="{{customTreeParams}}"
eventhandler="dialogTreeEventHandler"
enablelistviewsearch="true"
enablecheckboxes="{{multiPicker}}">
</umb-tree>
</div>
</div>