Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Only sorting certain levels in tree

    I am trying to perform some custom sorting on a Tree/TreeGrid (see attachment for a screenshot of grid sample). What I am trying to accomplish is when sorting to only sort the data under a certain level of the tree (i.e. levels 0-2 should always remain constant & any sorting should only be applied at levels 3+).

    In the example in the screenshot, only the items who are children of the INVESTMENTS & CASH nodes should be sorted. The Account, INVESTMENTS, & CASH nodes should always remain exactly where they are.

    Anyone have any ideas/help?
    Attached Files

    #2
    To customize sort, use a SortNormalizer.

    Comment


      #3
      sortNormalizer does not do what I want to do - sortNormalizer only allows me to return a value to sort by for a paricular row. I need more than that. I need to be able to say "Only apply sorting for certain levels of the tree - otherwise don't perform any sort".

      Comment


        #4
        Right.. so use a SortNormalizer that returns values such that rows that you don't want reordered are not reordered.

        Comment


          #5
          How would you do that not knowing what all of the other values that are being sorted are? My Tree/TreeGrid could have 1,000 rows in it and I would have to figure out values for these "frozen" rows which would fit inside all of the other rows?

          Comment


            #6
            This is becoming advice about algorithms and not about our product as such, but realize you can run code before you trigger the sort, so you can pre-calculate the desired sort by sorting the rows who's order should change in advance, then assigning an index to every row that the sort normalizer could return.

            Comment


              #7
              Wouldn't a better solution be one where a user can supply whatever comparator they would like and have the sort routine call that? Right now the implementation of the sort is in isc.Array in the sortByProperties function. The Tree/TreeGrid is passed into this as a context. Seems kind of backwards to me.

              Comment


                #8
                No, because some browsers are terrible about only calling your comparator a reasonable number of times (IE), making it tricky to write a performant comparator (on IE), whereas your normalizer is called once per record.

                Comment


                  #9
                  Ok so I took your advice & came up with a sort value & customized the sortNormalizer to return this pre-determined sort value. I am echo'ing it out to the console and my sort values are correct, however the tree does not respect my ordering. Am I missing something?

                  See the screenshot - it shows the result. Here is the log from my console:

                  Code:
                  ["Account 3CH", "CASH", "US Dollar (Trade Date Cash)", "INVESTMENTS", "Equity", "Oracle Corp.", "GOOGLE INC-CL A", "Debt", "GNMA 30 YR SINGLE FAMILY 6.5%", "FNMA 30 YR Conv. 7%", "FNMA 30 YR Conv. 7%", "FNMA 30 YR Conv. 7%"]
                  sortNormalizer(Account 3CH, sec_name) = 0
                  sortNormalizer(CASH, sec_name) = 1
                  sortNormalizer(INVESTMENTS, sec_name) = 3
                  sortNormalizer(Debt, sec_name) = 7
                  sortNormalizer(Equity, sec_name) = 4
                  sortNormalizer(FNMA 30 YR Conv. 7%, sec_name) = 9
                  sortNormalizer(FNMA 30 YR Conv. 7%, sec_name) = 10
                  sortNormalizer(FNMA 30 YR Conv. 7%, sec_name) = 11
                  sortNormalizer(GNMA 30 YR SINGLE FAMILY 6.5%, sec_name) = 8
                  sortNormalizer(GOOGLE INC-CL A, sec_name) = 6
                  sortNormalizer(Oracle Corp., sec_name) = 5
                  sortNormalizer(US Dollar (Trade Date Cash), sec_name) = 2
                  Attached Files

                  Comment


                    #10
                    We can't really help based on a screenshot and some log output - the problem is in code which you haven't shared.

                    Comment


                      #11
                      I can't share my entire codebase with you because it is proprietary and a subclass of TreeGrid. I can share with you the functions pertaining to this issue that I am over-writing.

                      The field this.useSortIndexesInNormalizer is set to true by default and is only toggled in the setSort function.

                      sortNormalizer:
                      Code:
                      sortNormalizer: function(record, fieldName) {	
                        console.log("sortNormalizer(" + record['name'] + ", " + fieldName + ") = " + this.sortIndexes[record.key]);
                        return this.useSortIndexesInNormalizer ? this.sortIndexes[record.key] : record[fieldName];
                      }
                      setSort:
                      Code:
                      setSort: function(sortSpecifiers) {
                      	if (this.displayMode == crd.PositionGrid.ViewMode.Account) {			
                      		if ((this.data) && isc.isA.Tree(this.data)) {
                      			// 1st re-initialize the sort indexes
                      			this.sortIndexes = [];
                      			this.sortIndexesByName = [];
                      				
                      			// Now process the tree
                      			var currentIndexObj = { currentIndex: 0 };
                      			this.useSortIndexesInNormalizer = false;
                      			this.computeSortIndexes(this.data.getRoot(), currentIndexObj, sortSpecifiers);
                      			this.useSortIndexesInNormalizer = true;
                      				this.sortIndexes.setLength(currentIndexObj.currentIndex);
                      		}
                      	}
                      		
                      	console.log(this.sortIndexesByName.valueOf());
                      		
                      	return this.Super("setSort", arguments);
                      }
                      computeSortIndexes:
                      Code:
                      computeSortIndexes: function(node, currentIndexObj, sortSpecifiers) {
                            // Node is an instance of TreeNode, which also is an instance of ListGridRecord
                      	if (node && (node != null)) {			
                      		if (this.data.getLevel(node) <= 2) {
                      			// 	This is a level above what we want sorted, so just add it as-is (if its not the tree's root),
                      			// then go onto any children, if any
                      				
                      			if (!this.data.isRoot(node)) {
                      				// This isn't the root of the tree. The actual root node of the tree we don't show. It's just a dummy row
                      				this.sortIndexes[node.key] = currentIndexObj.currentIndex++;
                      				this.sortIndexesByName.push(node.name);
                      			}
                      				
                      			if (!this.data.isLeaf(node)) {
                      				// This node is not a leaf, so get the children & call ourselves for each child
                      				var children = this.data.getChildren(node);
                      					
                      				if ((children != null) && isc.isA.Array(children)) {
                      					for (var i = 0; i < children.length; i++) {
                      						this.computeSortIndexes(children[i], currentIndexObj, sortSpecifiers);
                      					}
                      				}
                      			}
                      		}
                      		else if ((typeof this.sortIndexes[node.key] == "undefined") || (this.sortIndexes[node.key] == null)) {
                      			// We're at a level where we want to sort & the node has not already been added to the sortIndexes
                      			// So get our parent and then perform the sort on the paren't direct children
                      			// Then map the results to the sort indexes
                      			var parent = this.data.getParent(node);
                      				
                      			if (parent != null) {
                      				var parentsChildren = this.data.getChildren(parent);
                      					
                      				if ((parentsChildren != null) && isc.isA.Array(parentsChildren)) {
                      					var arrayToSort = [];
                      					arrayToSort.addList(parentsChildren); // Don't want to modify the actual array
                      					arrayToSort.setSort(sortSpecifiers);
                      						
                      					// Now that its sorted, we'll walk it and add them to the sort indexes
                      					for (var i = 0; i < arrayToSort.length; i++) {
                      						this.sortIndexes[arrayToSort[i].key] = currentIndexObj.currentIndex++;
                      							this.sortIndexesByName.push(arrayToSort[i].name);
                      							
                      						if (!this.data.isLeaf(arrayToSort[i])) {
                      							var children = this.data.getChildren(arrayToSort[i]);
                      								
                      							if ((children != null) && isc.isA.Array(children)) {
                      								for (var j = 0; j < children.length; j++) {
                      										this.computeSortIndexes(children[j], currentIndexObj, sortSpecifiers);
                      								}
                      							}
                      						}
                      					}					
                      				}
                      			}
                      		}
                      	}
                      }

                      Comment


                        #12
                        Let me ask this question about sortNormalizer in relation to a Tree/TreeGrid - should I only be concerned about generating pre-sorted values on nodes that are expanded (i.e. not generating anything on nodes that are not visible because the parent is collapsed?

                        Comment


                          #13
                          The way your code is organized, it looks like it will run your sort, then run the default sort afterwards.

                          Comment


                            #14
                            I run my routine, which creates a map of node keys to the sort order. Then I call the superclass's sort routine. I also override sortNormalizer which for the given record returns the sort order from the map I created earlier. The orderings of things in this map seems to be correct for the screenshot I posted earlier.

                            If I just do the sorting and then never call the superclass's setSort method then the sorting never happens or gets shown either.

                            Comment


                              #15
                              We can't really tell what's wrong from what's been posted. Try taking this out of the context of the grid with a direct call to Tree.sortByProperty() (note: documentation is under List because a Tree can also be viewed as a List). If you seem to be getting misbehavior there, please show a test case we can run, and we'll check it out.

                              Comment

                              Working...
                              X