PDA

View Full Version : Nested List Index Issue/Question



existdissolve
11 Jan 2011, 5:03 AM
In a nested list, I'm trying to allow for jumping back to the root of the nested list from the DetailCard of a sublist. So, let's say I have the following:

Root

Level 1


Level 2



DetailCard

I'd like to be able to go back to the Root from the DetailCard.

I've tried each of the following:


nestedlist.setActiveItem(1);
nestedlist.setActivePath("root");
nestedlist.setActiveItem(nestedlist.items.items[0]);

They all *work* in the sense that they accomplish the desired end. However, one of the consequences of this approach is that the "back" button handling gets broken slightly.

What appears to be happening is that whatever mechanism is tracking the "index" of the nested list is not getting set correctly in my approach. If I output the card index value passed in "cardswitch" when drilling down to the DetailCard, it goes "0,1,2,3" as expected. However, once I "jump back" to root and drill back to DetailCard, the values go "0,4,5,6"; and if I "jump back" to root again and then re-drill, "0,7,8,9".

Somehow I need to reset the index on this nested list when jumping back to root, but cannot figure out how--any help would be appreciated/suggestions for doing this better.

Thanks

bhupesh
11 Jan 2011, 7:50 PM
I also want to do this. Any genius around here?

Your help much appreciated.

existdissolve
11 Jan 2011, 9:14 PM
Ok, this is pretty ugly, but seems to work:

First, I have a function to handle firing the "onBackTap()" function of the NestedList object:


function goBackwards() {
var nl = Ext.getCmp("nestedlist");
nl.onBackTap();
}

Next, I have a function that handles the "jump to front" action. I set an item on the NestedList object called "traverse"--this will be used in the last bit.


function loadURL() {
var nl = Ext.getCmp("nestedlist");
nl.traverse = true;
goBackwards();
}

Finally, for each "cardswitch" event, I fire a function called "checkMovement()". This checks if the "traverse" attribute is set and if the current index is greater than 0. If it is, it continues to call the goBackwards() function; otherwise, it sets "traverse" to false, effectively stopping the backward motion.


function checkMovement(container,newcard,oldcard,index,animated) {
var nl = Ext.getCmp("nestedlist");
if(nl.traverse && index > 0) {
goBackwards();
}
if(index==0) {
nl.traverse=false;
}
}

The drawback of this is that the movement animates through the each level in the tree. However, unlike the other methods I've tried, it doesn't break the "Back" button, which is more important to me than a straight jump from level X to 0.

Finally, I fully acknowledge that this bit of code is probably pretty laughable to the more knowledgeable, but it seems to be working, which is fine for my purposes at the time being. If there are more efficient/less stupid ways of accomplishing this, I hope someone else will jump in :)

bhupesh
12 Jan 2011, 2:17 PM
Thanks a lot. I will give it a try. :)

existdissolve
12 Jan 2011, 8:36 PM
An Update:

I've worked out a solution to programmatically browse around the NestedList. This expands a bit on what I had posted earlier.

First, I created a remote method in my server-side code to retrieve the full hierarchy for any passed node.

I return this back to my initial link-to-node click event:


function loadNode(target,title) {
Ext.Ajax.request({
url: "../com/parser.cfc",
method: "POST",
params: {method:"getnavcontext",identifier:title,target:target,returnformat:"json"},
success: navSearch
});
}

On success, I call navSearch(). This function sets the "traverse" attribute on my NestedList, and additionally set the result of my heirarchy retrieval to a global variable to be used later. Finally, it calls the "goBackwards()" function, which kicks off the node search.


function navSearch(req) {
hierarchy = Ext.decode(req.responseText);
var nl = Ext.getCmp("referencepanel");
nl.traverse = true;
goBackwards();
}

Go backwards simply fires the onBackTap() function of the NestedList nav button, in order to preserve the auto-navigation-button goodness.


function goBackwards() {
var nl = Ext.getCmp("referencepanel");
nl.onBackTap();
}

Finally, I have a listener for the "itemtap" event which always fires the "checkMovement()" function. I'll explain in-line what this is doing.


function checkMovement(container,newcard,oldcard,index,animated) {
var nl = Ext.getCmp("referencepanel");
// default value for matchrow
var matchrow= -1;
// if the "traverse" attribute of the NestedList is true, we're still in the middle of navigating
if(nl.traverse) {
// loop over the hierarchy array returned from remote context build-out
for(i=0;i<hierarchy.length;i++) {
// search the store to see if one of the items in the hierarchy matches
// one of the items in the current list's store (limited to current sublist)
var findrow = newcard.store.find("id",hierarchy[i].id);
// if a match is found, set "matchrow" to the position of the found store record
if(findrow != -1) {
matchrow = findrow;
break;
}
}
// if there's a match, we don't want to travel up the tree anymore;
// rather, we want to select the matched item
if(matchrow != -1) {
// do a check to see if the matched item is a leaf node
// if so, set NestedList traverse attribute to false so it doesn't blow up
if(newcard.recordNode.childNodes[matchrow].leaf) {
nl.traverse = false;
}
// fire the "itemtap" event for the matched element; pass the newcard and matchrow values
// because checkMovement() is fired onitemtap, we'll hit this method at least one more time
// until we hit a leaf node (see above)
newcard.fireEvent("itemtap",newcard,matchrow);
}
// if there wasn't a match from our hierarchy to the current level, we need to go up another level
// recall goBackwards() to kick off the whole process again
else {
goBackwards()
}
}
}

-------

Now, a couple notes. One of the things I DON'T like about this approach is that you see the whole procession from node to node while the hierarchy parsing is worked out to get to the next node. If the nodes are significantly separated in the tree, this can take a bit to parse out--it's speedy, but you get to watch a lot of card transitions :)

However, it does work, so that's something. I would love to see other suggestions about how to accomplish similar functionality in a more elegant way. Nonetheless, hope this is helpful to someone.

existdissolve
12 Jan 2011, 9:02 PM
That's what I originally tried (or an iteration of it, at least). While it certainly jumps the nested list back to root, it breaks the back button. If you try this, choose a nested list item *after* returning to root like this, and then click the back button. I'm getting an error every time ("Cannot call method 'getRecord' of undefined"), and it breaks the back nav permanently at that level.

*EDIT* - Sorry, didn't realize that my original post didn't have the "syncToolbar" bit in it. I did try several iterations with the syncToolbar() call, to no avail.

tomalex0
12 Jan 2011, 9:28 PM
This will hide the Back button, it seems the navigation still breaks ,



nestedList.setActiveItem(0,{type:'slide',reverse:true});
nestedList.syncToolbar();

tomalex0
12 Jan 2011, 10:07 PM
This is an override for Nested list to make Root node active. Hope this solves the issue with index.
Let me know if there is any bug?


Ext.override(Ext.NestedList, {
setRootActive:function(){
var navPnl = this;
var firstList = navPnl.items.getAt(0);
for(i=(navPnl.items.length-1);i >= 1;i--){
navPnl.remove(navPnl.items.getAt(i));
}
navPnl.setActiveItem(firstList, {
type: 'slide',
reverse: true,
scope: this
});
navPnl.syncToolbar(firstList);
}
});







nestedList.setRootActive();

existdissolve
13 Jan 2011, 5:27 AM
Ah, I see what you're doing with the remove()--that makes sense.

Thanks for this code--I'll give it a test out later this evening.

While we're on this subject, can you think of a better way to replicate what I hacked above (last long post of mine)--e.g., searching the tree and selecting a target item WITHOUT going through each intermediary list and level?

For example, let's say i have this structure:

Root

Colors


Green


Blue



Light Blue



Dark Blue

Shapes


Circle


Square



Rounded Corners

If I wanted to jump from Light Blue to Rounded Corners, my code above currently does this (more or less):

DetailCard -> Light Blue -> Blue -> Colors -> Shapes -> Square -> Rounded Corners -> DetailCard

In other words, an animation for each "->" above...that's alot.

The more complex the hierarchy, of course, the more steps it has to take, and it's a bit lengthy of a process. Is there a way to search the tree in the background, find the target (Rounded Corners), and then switch to that element WITHOUT breaking the way the NestedList index works?

Thanks again for your help!

akoimeexx
3 Jun 2011, 6:25 AM
I came up with this solution to navigate back to the root node after poking around the Sencha docs and looking at what happens in nestedList.onBackTap():


while (nestedList.items.indexOf(nestedList.getActiveItem()) > 0) {
nestedList.onBackTap();
}


Edit: I figure, why reinvent the wheel when they've already go the code written to navigate back up the tree?

Edit 2: I realize this is a fairly old topic, sorry about the necromancy. Just isn't a whole lot in the way of documentation on performing tasks like this, and if you're a googler, this is one of the top links that shows up for returning to the root of a nested list. :)

colworx
22 Jul 2011, 11:24 AM
Is there a way to search the tree in the background, find the target (Rounded Corners), and then switch to that element WITHOUT breaking the way the NestedList index works?


I would also love to find a solution...

cchiriac
7 Oct 2011, 8:08 AM
I would also love to find a solution...

Hi, I got it working to go to the root node with the following override:


_home: function() {
var items = this.items,
itemsArray = this.items.items,
i = items.length;

var rootNode = itemsArray[0].recordNode;

var path= '/' + rootNode.id;

// a forward leading slash indicates to go
// to root, otherwise its relative to current
// position
var gotoRoot = path.substr(0, 1) === "/",
ds = this.store,
tree = ds.tree,
lastCard,
pathArr, pathLn;

if (gotoRoot) {
path = path.substr(1);
}
pathArr = Ext.toArray(path.split('/'));
pathLn = pathArr.length;


if (gotoRoot) {
for (; i > 1; i--) {
this.remove(itemsArray[i - 1], true);
}

// verify last item left matches first item in pathArr
// <debug>

if (rootNode.id !== pathArr[0]) {
throw new Error("rootNode doesn't match!");
}
// </debug>
}

lastCard = this.items.getAt(0);
if (!lastCard) {
throw new Error("Card was not found when trying to add to NestedList.");
}

this.setActiveItem(lastCard, false);
this.fireEvent('listchange', this, lastCard);
this.syncToolbar();
}


It is based on setActivePath, and it changes 2 things:
- it doesn't add any card
- lastCard is item at index 0, which in my case is the root

I could be modified to take into account any existing node.

KPChow
27 Feb 2012, 8:36 AM
I came up with this solution to navigate back to the root node after poking around the Sencha docs and looking at what happens in nestedList.onBackTap():


while (nestedList.items.indexOf(nestedList.getActiveItem()) > 0) {
nestedList.onBackTap();
}


Edit: I figure, why reinvent the wheel when they've already go the code written to navigate back up the tree?

Edit 2: I realize this is a fairly old topic, sorry about the necromancy. Just isn't a whole lot in the way of documentation on performing tasks like this, and if you're a googler, this is one of the top links that shows up for returning to the root of a nested list. :)

Thanks for sharing this! However, there is an issue that I found from it. The leaf panel will show on top of the nested list when you go back. To fix this problem, you need to add the following code



nestedList.getActiveItem(1).hide();

a791446794
10 Jan 2014, 5:50 PM
I think it's just to tap backButton until it is hidden .
In jobview, set backButton to {itemId:'backButton'}
var j=Ext.ComponentQuery.query('jobview')[0],b=j.query('button#backButton')[0];
while( ! b.getHidden()){b.fireEvent('tap');}
You can understand!