Link to home
Create AccountLog in
Avatar of GrrWolfie
GrrWolfieFlag for United States of America

asked on

Need help adding functionallity to simple Javascript expandable item tree

So I need to add the following,
1. A folder maximize and minimize link next to each folder. They'd operate by changing the "expand:" value in the array to true or false and redraw the array by calling createList(myArray). I just have no idea how to find all the parents beyond the first for this link. I'm also veeeeery new to this object passed "parenting" i'm struggling with the information available on the web on this when attempting to apply it to this code.
2. Each non-folder will have a <input type="text" value="?"> field, inside will be the full path (all parents) to that item + the item.
Example: "Ultra Purple" would show as Colors\Special\Purple\Ultra Purple
3. Instead of a list i'd like to use multiple &nbsp; tags for tabbing things over.

Many thanks, this would be a huge help i'm massively stuck.

Here's what I got so far! (credit to djon2003 for his awesome code :) )
- I get this error: "You may not start a |i] tag within a |i] tag" (replace "|" with "["), I had to change all instances of |i] to "|i]" to get it to post. To test it they'll need to be changed back. Anyone know how to get around that?

<div id="thecontainer"></div>

<script language="JavaScript">
var myArray= 
[
{name:"Colors",expand:true, children :
   [
      {name:"Blue",expand:true,children:[]},
      {name:"Yellow",expand:true,children:[]},
      {name:"Special",expand:true,children: 
         [
            {name:"Purple",expand:true,children:
               [
                  {name:"Ultra Purple",expand:true,children:[]},
               ]
            }
         ]
      }
   ]
},
{name:"Price range",expand:false,children: 
   [
      {name:"Low",expand:false,children:[]}
   ]
},
{name:"Distance",expand:false,children:[]}
];
var divContainer = document.getElementById('thecontainer');
divContainer.innerHTML = createList(myArray);
function createList(nodes, parent, level){
   if (level=="undefined"){
      level=1
   }
   var html="<ul>";
   if(parent!=undefined && parent.expand!=true){
      var html = "<ul style=\"display:none\">"
   }
   else{
      var html="<ul>"
   }
   for(var i = 0; i < nodes.length; i++) {
      //Do something  with nodes[i].name and other values
      html+="<li>";
      if (nodes[i].children.length!=0){

         //Here's where I'd add a folder expansion button, need an example! :X

      }
      html += nodes[i].name;
      if (nodes[i].children.length!=0){

         html+=createList(nodes[i].children, nodes[i], level + 1);
      }
      html+="</li>";
   }
   html+="</ul>";
   return html;
}
//myArray[Colors][]='false';createList(myArray);"
</script>

Open in new window

Avatar of Michel Plungjan
Michel Plungjan
Flag of Denmark image

[ i ] is italics

Just wrap in [ code ] or click Code and paste there.

I have fixed your post
Avatar of GrrWolfie

ASKER

* bump *

Accepting partial answers here, if I get a push in the right direction i'll go at it like a tiger! :)
SOLUTION
Avatar of Tom Beck
Tom Beck
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Good info tommyBoy, didn't even think of skipping the invisible stuff hah.

As for an expansion button, here's an example of one that'd be for the folder "Purple":
html+="<input type=\"button\" value=\"+\" onclick=\"myArray[0].children[2].children[0].expand=false; createList(myArray);\" />";

My only issue is figuring out how to dynamically generate that link :X

Or maybe i'm going about this all wrong lol.

Display before link is pressed:
+ Colors
    Blue
    Yellow
    + Special
        + Purple
            Ultra Purple
- Price range
Distance

Display after link is pressed:
+ Colors
    Blue
    Yellow
    + Special
        - Purple
- Price range
Distance

Thanks! :)
This is the way I am picturing the finished tree.

Display before Purple link is pressed:
- Colors
    Blue
    Yellow
    - Special
        + Purple
+ Price range
Distance


Display after Purple link is pressed:

- Colors
    Blue
    Yellow
    - Special
        - Purple
              Ultra Purple
+ Price range
Distance
Oh yes that's correct, got a little hasty with that visual. Still pounding on the code. :P
How's it going? I found some time last night to take a closer look at this. I believe I have another partial answer to offer. I have code that displays the array as depicted in the mock up in my last post. You may already be passed that point so I don't want to confuse the issue by posting it now. It was good practice, so I don't care if it's not needed. What I have not worked out yet is the click events that expand and collapse the tree nodes by changing the expand property in the array. Maybe later. Let me know where you are on this and if you need any help.
Thanks for checking in btw...

I've come a long long way and i've decided that it would be better to hide the branches than re-draw the whole thing.

At his point the branches are nested correctly in div's that belong to their parents. Their also distanced according to their level on the tree. I have some initial code for building the maximize/minimize buttons but it's in a pretty messy state so I didn't post it. I should be able to figure it out today but we'll see! :) I'll let you know if I get stuck on something.

<table><tr><td>
<div id="thecontainer"></div>
</table>

<script language="JavaScript">
var myArray= 
[
{name:"Colors",expand:true, children :
	[
		{name:"Blue",expand:true,children:[]},
		{name:"Special",expand:true,children: 
			[
				{name:"Purple",expand:true,children:
					[
						{name:"Ultra Purple",expand:true,children:[]},
					]
				}
			]
		},
		{name:"Yellow",expand:true,children:[]}
	]
},
{name:"Price range",expand:false,children: 
	[
		{name:"Low",expand:false,children:[]}
	]
},
{name:"Distance",expand:false,children:[]}
];

var lastlevel
var treeposition=new Array();
function createList(nodes, parent, level){
	if (level==undefined){level=0}
	var html=""
	for(var i=0;i<nodes.length;i++){
		html+="<img width=\""+(level*30)+"\" height=\"0\" src=\"img/all_bp.gif\">";
		if(nodes[i].children.length!=0){
			if(nodes[i].expand!=true){
				html+="<a href=\"javascript:togglebranch('')\">+</a>"+" "
				html+=nodes[i].name;
				html+="<div style=\"display:none\">";
				html+=createList(nodes[i].children,nodes[i],level+1);
				html+="</div><br>";
			}
			else{
				html+="<a href=\"javascript:togglebranch('')\">-</a>"+" "
				html+=nodes[i].name;
				html+="<div style=\"border-style:solid;border-width:1px;border-color:#aaaaaa;padding:3px\">";
				html+=createList(nodes[i].children,nodes[i],level+1);
				html+="</div>";
			}
		}
		else{ //It's a file
			html+=nodes[i].name;
			html+="<br>";
		}
	}
   return html;
}

document.getElementById("thecontainer").innerHTML=createList(myArray);

Open in new window

typo: "var lastlevel" i'm not using and won't be using.
ASKER CERTIFIED SOLUTION
Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
I completed the code and satisfied the goals of this thread with some minor alterations in direction.
That works nicely. Very efficient. More compact than what I came up with to display the tree.

I went a completely different direction. I kept the un-ordered lists and abandoned the html string. Instead, I accessed the HTML DOM directly and inserted the ULs and LIs where needed.

Thanks for the points.