Link to home
Start Free TrialLog in
Avatar of GrrWolfie
GrrWolfieFlag for United States of America

asked on

Need to create a Javascript multi-dimensional tree from an array.

So 3 days in now and i'm totally at a loss for what to do... as far as my skills i'm an adept when it comes to messing with arrays but not so good with objects. Hoping to find an array based solution.

I need to create a multi-dimensional tree from an array or arrays...

Display Example: + is maximized, - is minimized, [ ] is a form check box
+ Colors I want
   [ ] Blue
   [ ] Yellow
   + Special
       [ ] Purple
- Price Range
- Distance

I can handle the easy stuff such as show/hide and dynamically creating the html through loops but I just have no idea how to set up the array so it's easy to loop through to produce this tree. Any ideas?
ASKER CERTIFIED SOLUTION
Avatar of djon2003
djon2003
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of GrrWolfie

ASKER

Thanks djon, i'm gonna go look into this tomorrow, long day :P
Avatar of Proculopsis
Proculopsis


//Try plugging this into the following tree control

                  children: [
                        {title: "Colours", isFolder: true, key: "colours", hideCheckbox: true, expand: true,
                              children: [
                                    {title: "Blue"},
                                    {title: "Yellow"},
                                    {title: "Special", isFolder: true, key: "special", hideCheckbox: true, expand: true,
                                          children: [
                                                {title: "Purple"}
                                          ]
                                    }
                              ]
                        },
                        {title: "Price Range", isFolder: true, key: "range", hideCheckbox: true, expand: false,
                              children: [{title: "Placeholder"}]
                        },
                        {title: "Distance", isFolder: true, key: "distance", hideCheckbox: true, expand: false,
                              children: [{title: "Placeholder"}]
                        }
                  ]


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
	<title>http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_27421997.html</title>
 
	<script src="http://wwwendt.de/tech/dynatree//jquery/jquery.js" type="text/javascript"></script>
	<script src="http://wwwendt.de/tech/dynatree//jquery/jquery-ui.custom.js" type="text/javascript"></script>
	<script src="http://wwwendt.de/tech/dynatree//jquery/jquery.cookie.js" type="text/javascript"></script>
 
	<link href="http://wwwendt.de/tech/dynatree//src/skin/ui.dynatree.css" rel="stylesheet" type="text/css">
	<script src="http://wwwendt.de/tech/dynatree//src/jquery.dynatree.js" type="text/javascript"></script>
 
 
	<!-- Add code to initialize the tree when the document is loaded: -->
	<script type="text/javascript">
	jQuery(document).ready( function(){
		// Attach the dynatree widget to an existing <div id="tree"> element
		// and pass the tree options as an argument to the dynatree() function:
		$("#tree").dynatree({
			checkbox: true,
			onActivate: function(node) {
				// A DynaTreeNode object is passed to the activation handler
				// Note: we also get this event, if persistence is on, and the page is reloaded.
				alert("Click checkbox to select: " + node.data.title);
			},

			children: [
				{title: "Colours", isFolder: true, key: "colours", hideCheckbox: true, expand: true,
					children: [
						{title: "Blue"},
						{title: "Yellow"},
						{title: "Special", isFolder: true, key: "special", hideCheckbox: true, expand: true,
							children: [
								{title: "Purple"}
							]
						}
					]
				},
				{title: "Price Range", isFolder: true, key: "range", hideCheckbox: true, expand: false,
					children: [{title: "Placeholder"}]
				},
				{title: "Distance", isFolder: true, key: "distance", hideCheckbox: true, expand: false,
					children: [{title: "Placeholder"}]
				}
			]

		});
	});
	</script>
</head>
<body class="example">

	<div id="tree"> </div>
 
</body>
</html>

Open in new window

Proculopsis, thanks for the input! Should have mentioned i'm definitely not looking for a jQuery option :)

(substituting [ with | because it won't let me post to the forum otherwise)

djon2003, now working on your script to make sure it's all I need (looks good so far), gotta brush on some learning so I can best make use of "//Do something  with nodes|i].name and other values" lol.

Right now i'm just doing document.write(nodes|i].name) or document.write(nodes|i].show), what would be the command to see how many "parents" the node has so I can indent it accordingly? If I have more complicated questions i'll create a new experts-exchange listing because it goes beyond the intended scope of this question into newbie learning territory. :P
Got a question, what'd be the best way to depict if an item is a folder or a file in your opinion?
Well, you could add an attribute for each of them ( as folder: true or false), though i think you can deduce it from the actual children attribute.

Using children.length == 0 would mean a folder.  
For the indentation problem, you can fix this out by adding a parameter to the function createList.

Let's change the show attribute in the data to expand. Though show could be used too to ensure creation. This could be used by filters to activate / desactivate data dynamically. So the new data would be :
 
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 : "Price range", expand : false, children : 
  [
    {name : "Low", expand : false, children : []}
  ]
},
{name : "Distance", expand : false, children : []}
];

Open in new window


Let's write something quick in JS.
 
var divContainer = document.getElementById('container');

divContainer.innerHTML = createList(myArray);

function createList(nodes, parent, level) {
   if (level == "undefined") level = 1;
   //Missing an id to be refereed by the expand button to change style.display
   var html = "<ul" + (parent != "undefined" && !parent.expand ? ' style="display:none"' : "" ) + ">";

   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) {//Add expand button}

      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;
}

Open in new window


This list is using the ul, li and embedded ul to create indentation. Though, I added a level param to show you that you could use something else. Example : Using the level as a multiplier to set the left padding of all your elements.

This could be done in multitude of ways. Analyse what's your needs are and try to figure out the way it should work and how data show be designed.

More, you can assign a function into value of an object's attribute. This can be used to get different functionality by object type. So, the main createList function can call this attribute's function to get the specific html needed for that object.

Example :
var obj= {name: 'Data1', getHtml: function() {return "<b>test</b>";}};
alert(obj.getHtml());

The function could be defined outside and using only its name as reference into the data.
djon2003, thanks again i'm lucky to have you help me out here. :)

I have some basic JavaScript knowledge questions but they're outside the scope of this thread. Will ask them tomorrow. Have a good one!