Author Archive for adminPage 2 of 2

Further work on JIT

I’m very happy with this first JavaScript Infovis Toolkit release, and I’m already working on fixing some known bugs and adding features for the next release of this library.
For the next step I’ll be focusing on fixing bugs, refactoring code, adding some features and improving the documentation.
Some of the things you’ll find in my TODO list are:

  • For RGraphs:
    • Add polar interpolation in animations.
    • Mantain Child ordering during transitions.
    • Change node diameters based on the first dataset object value.
    • Graph support (trees with cycles…)
  • For the ST:
    • Code refactoring.
    • Performance improvements (bind with the Animation object).
    • Support for IE.
  • For Hypertrees:
    • Bug fix (node diameters, multilevel display).
    • Graph support, (although it might be supporting Graph structures already).
  • Treemaps
    • Bug fix (mostly on computing rectangles dimensions).

Before adding some radical features (binding visualizations with real time mutable data, etc.) I really want to have a strong API, and in order to do that, I must do some research on my own.
Don’t forget you have some quick tutorials on the visualizations. Also, the Hypertree, ST, RGraph and Treemap have some object references. Finally, there’s a Google Group about the JIT here.

RGraph quick tutorial

This tutorial requires you to have read Feeding JSON tree structures to the JIT and on controllers first.

Hi, this is going to be a quick tutorial on how to set the RGraph up and running.

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":8},
    {"key":"key2",
     "value":-88}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":8},
        {"key":"key2",
         "value":74}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":55}],
         "children":[]},
        {"id":"node25",
         "name":"2.5",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":67}],
         "children":[]},
        {"id":"node26",
         "name":"2.6",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-50}],
         "children":[]},
        {"id":"node27",
         "name":"2.7",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":10}],
         "children":[]},
        {"id":"node28",
         "name":"2.8",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-69}],
         "children":[]},
        {"id":"node29",
         "name":"2.9",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":98}],
         "children":[]},
        {"id":"node210",
         "name":"2.10",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":12}],
         "children":[]},
        {"id":"node211",
         "name":"2.11",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-95}],
         "children":[]}]},
    {"id":"node112",
     "name":"1.12",
     "data":[
        {"key":"key1",
         "value":1},
        {"key":"key2",
         "value":96}],
     "children":[
        {"id":"node213",
         "name":"2.13",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-58}],
         "children":[]},
        {"id":"node214",
         "name":"2.14",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-42}],
         "children":[]},
        {"id":"node215",
         "name":"2.15",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":92}],
         "children":[]},
        {"id":"node216",
         "name":"2.16",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-15}],
         "children":[]},
        {"id":"node217",
         "name":"2.17",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":29}],
         "children":[]},
        {"id":"node218",
         "name":"2.18",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-59}],
         "children":[]},
        {"id":"node219",
         "name":"2.19",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":21}],
         "children":[]},
        {"id":"node220",
         "name":"2.20",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":78}],
         "children":[]}]},
    {"id":"node121",
     "name":"1.21",
     "data":[
        {"key":"key1",
         "value":3},
        {"key":"key2",
         "value":53}],
     "children":[
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":10}],
         "children":[]},
        {"id":"node223",
         "name":"2.23",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":21}],
         "children":[]},
        {"id":"node224",
         "name":"2.24",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-32}],
         "children":[]},
        {"id":"node225",
         "name":"2.25",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-42}],
         "children":[]},
        {"id":"node226",
         "name":"2.26",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":75}],
         "children":[]},
        {"id":"node227",
         "name":"2.27",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-74}],
         "children":[]},
        {"id":"node228",
         "name":"2.28",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":52}],
         "children":[]},
        {"id":"node229",
         "name":"2.29",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-49}],
         "children":[]}]},
    {"id":"node130",
     "name":"1.30",
     "data":[
        {"key":"key1",
         "value":9},
        {"key":"key2",
         "value":-29}],
     "children":[
        {"id":"node231",
         "name":"2.31",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-23}],
         "children":[]},
        {"id":"node232",
         "name":"2.32",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":19}],
         "children":[]},
        {"id":"node233",
         "name":"2.33",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":92}],
         "children":[]}]},
    {"id":"node134",
     "name":"1.34",
     "data":[
        {"key":"key1",
         "value":9},
        {"key":"key2",
         "value":71}],
     "children":[
        {"id":"node235",
         "name":"2.35",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":-65}],
         "children":[]}]},
    {"id":"node136",
     "name":"1.36",
     "data":[
        {"key":"key1",
         "value":3},
        {"key":"key2",
         "value":-11}],
     "children":[
        {"id":"node237",
         "name":"2.37",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-85}],
         "children":[]},
        {"id":"node238",
         "name":"2.38",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-13}],
         "children":[]},
        {"id":"node239",
         "name":"2.39",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":80}],
         "children":[]},
        {"id":"node240",
         "name":"2.40",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-69}],
         "children":[]}]},
    {"id":"node141",
     "name":"1.41",
     "data":[
        {"key":"key1",
         "value":10},
        {"key":"key2",
         "value":-4}],
     "children":[
        {"id":"node242",
         "name":"2.42",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-27}],
         "children":[]},
        {"id":"node243",
         "name":"2.43",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-44}],
         "children":[]},
        {"id":"node244",
         "name":"2.44",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":24}],
         "children":[]},
        {"id":"node245",
         "name":"2.45",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-66}],
         "children":[]}]}]};

Put this HTML in your page:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-rgraph.css" />

	<!--[if IE]>
		<script type="text/javascript" src="/static/js/excanvas.js"></script>
	<![endif]-->

	<script type="text/javascript" src="/static/js/rgraph/RGraph.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-rgraph.js" ></script>

	</head>
	<body onload="init();">

         <canvas id="infovis" width="900" height="500"></canvas>
         <div id="label_container"></div>

	</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.

Now, create a rgraph-example.css and put this code in it:

html,body {
	width:100%;
	height:100%;
	overflow:hidden;
	margin:0;padding:0;
	background-color:#333;
	text-align:center;
}

#infovis {
	width:900px;
	height:500px;
	background-color:#222;
}

.node {
	color: white;
	background-color:transparent;
	cursor:pointer;
	font-weight:bold;
	opacity:0.9;
	border:1px solid red;
}

.node:hover {
	cursor:pointer;
	color: #222;
	background-color:white;
	font-weight:bold;
	opacity:1;
}

Finally, create an example-rgraph.js file and put this code in it:
Note: I’ll be using the Mootools library to do this tutorial, just because I don’t want to spend time writing low level code that would make the code uglier. You can use any library you want (or none at all) though. You are provided with a Mootools library and excanvas library in the extras folder of the library. You can also download the mootools library here.

function init() {
	//Set node interpolation to linear (can also be 'polar')
	Config.interpolation = "linear";
	//Set distance for concentric circles
	Config.levelDistance = 100;
	//Set number of concentric circles, default's to six.
	Config.drawConcentricCircles = 4;

	var json= //data defined previously

	var canvas= new Canvas('infovis', '#ccddee', '#772277');

	var rgraph= new RGraph(canvas,  {
	  //Add a controller to make the tree move on click.
		onCreateLabel: function(domElement, node) {
			var d = $(domElement);
			d.addEvents({
				'click': function() {
					rgraph.onClick(d.id);
				}
			});
		}
	 });

	  //load tree from tree data.
	  rgraph.loadTreeFromJSON(json);
	  //compute positions
	  rgraph.compute();
	  //make first plot
	  rgraph.plot();
}

You should see a RGraph up and running. Click on the labels and the tree should move.

Some notes:

  • It’s mandatory to put the width and height properties on the canvas html tag.
    You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough.
  • You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
  • The Canvas constructor takes 3 parameters: the canvas id, the fillStyle property and the strokeStyle property. If you don’t know what those properties are, take a look at this section from the canvas tutorial.
  • You can take off the concentric circles by setting Config.drawConcentricCircles to false. Just be sure you do that before making a canvas or RGraph instance.

Customizing the Graph

Let’s add some labels!

First, strip off the border: 1px solid red; line from the .node class in your CSS file.
It should look like this:

.node {
	color: white;
	background-color:transparent;
	cursor:pointer;
	font-weight:bold;
	opacity:0.9;
}

Now we are going to add a javascript controller in order to put the name of the nodes into the labels. Since we only need to do this once, we’ll use the onCreateLabel method. If you don’t know what I’m talking about you should probably read the on controllers post first.

So the JavaScript file should look like this now:

function init() {
	//Set node interpolation to linear (can also be 'polar')
	Config.interpolation = "linear";
	//Set distance for concentric circles
	Config.levelDistance = 100;
	//Set number of concentric circles, default's to six.
	Config.drawConcentricCircles = 4;

	var json= //json data defined previously

	var canvas= new Canvas('infovis', '#ccddee', '#772277');

	var rgraph= new RGraph(canvas,  {
	  //Add a controller to assign a name to the created label.
		onCreateLabel: function(domElement, node) {
			var d = $(domElement);
			d.set('html', node.name).addEvents({
				'click': function() {
					rgraph.onClick(d.id);
				}
			});
		}
	 });

	  //load tree from tree data.
	  rgraph.loadTreeFromJSON(json);
	  //compute positions
	  rgraph.compute();
	  //make first plot
	  rgraph.plot();
}

You should see some labels now.
The thing is that… well, they are not centered. So we’ll just add an onPlaceLabel method to the controller in order to do that, since the onPlaceLabel method is called after labels have been placed.

So the js code should now look like:

function init() {
	//Set node interpolation to linear (can also be 'polar')
	Config.interpolation = "linear";
	//Set distance for concentric circles
	Config.levelDistance = 100;
	//Set number of concentric circles, default's to six.
	Config.drawConcentricCircles = 4;

	var json= //json data defined previously

	var canvas= new Canvas('infovis', '#ccddee', '#772277');

	var rgraph= new RGraph(canvas,  {
	  //Add a controller to assign a name to the label.
		onCreateLabel: function(domElement, node) {
			var d = $(domElement);
			d.set('html', node.name).addEvents({
				'click': function() {
					rgraph.onClick(d.id);
				}
			});
		},

	//Take off previous width and height styles and
	//add half of the *actual* label width to the left position
	// That will center your label (do the math man).
		onPlaceLabel: function(domElement, node) {
			domElement.innerHTML = '';
			domElement.innerHTML = node.name;
			var left = parseInt(domElement.style.left);
			domElement.style.width = '';
			domElement.style.height = '';
			var w = domElement.offsetWidth;
			domElement.style.left = (left - w /2) + 'px';
		}
	});

	  //load tree from tree data.
	  rgraph.loadTreeFromJSON(json);
	  //compute positions
	  rgraph.compute();
	  //make first plot
	  rgraph.plot();
}

You should see some centered labels now!

Labels already have the onclick event handler to move the graph. You set that onCreateLabel.

Remember there are lots of other controller methods!

Remember also that you can change the animation time and the frames per second in the animation with Config.animationTime and Config.fps.
Hope it was helpful.

ST quick tutorial

This tutorial requires you to have read Feeding JSON tree structures to the JIT and on controllers first.

Hi, this is going to be a quick tutorial on how to set the ST up and running.

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":2},
    {"key":"key2",
     "value":-86}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":7},
        {"key":"key2",
         "value":73}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":2},
            {"key":"key2",
             "value":-49}],
         "children":[
            {"id":"node35",
             "name":"3.5",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":-10}],
             "children":[
                {"id":"node46",
                 "name":"4.6",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":74}],
                 "children":[]},
                {"id":"node47",
                 "name":"4.7",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-37}],
                 "children":[]}]},
            {"id":"node38",
             "name":"3.8",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":88}],
             "children":[
                {"id":"node49",
                 "name":"4.9",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-67}],
                 "children":[]},
                {"id":"node410",
                 "name":"4.10",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":38}],
                 "children":[]},
                {"id":"node411",
                 "name":"4.11",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":-77}],
                 "children":[]}]}]},
        {"id":"node212",
         "name":"2.12",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-99}],
         "children":[
            {"id":"node313",
             "name":"3.13",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":48}],
             "children":[
                {"id":"node414",
                 "name":"4.14",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":-19}],
                 "children":[]},
                {"id":"node415",
                 "name":"4.15",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":61}],
                 "children":[]},
                {"id":"node416",
                 "name":"4.16",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":83}],
                 "children":[]}]},
            {"id":"node317",
             "name":"3.17",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":-18}],
             "children":[
                {"id":"node418",
                 "name":"4.18",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":-58}],
                 "children":[]},
                {"id":"node419",
                 "name":"4.19",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-35}],
                 "children":[]},
                {"id":"node420",
                 "name":"4.20",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":84}],
                 "children":[]},
                {"id":"node421",
                 "name":"4.21",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":19}],
                 "children":[]}]}]},
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-3}],
         "children":[
            {"id":"node323",
             "name":"3.23",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":-53}],
             "children":[
                {"id":"node424",
                 "name":"4.24",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":63}],
                 "children":[]},
                {"id":"node425",
                 "name":"4.25",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":38}],
                 "children":[]},
                {"id":"node426",
                 "name":"4.26",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":84}],
                 "children":[]}]}]}]},
    {"id":"node127",
     "name":"1.27",
     "data":[
        {"key":"key1",
         "value":4},
        {"key":"key2",
         "value":34}],
     "children":[
        {"id":"node228",
         "name":"2.28",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-8}],
         "children":[
            {"id":"node329",
             "name":"3.29",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":-48}],
             "children":[
                {"id":"node430",
                 "name":"4.30",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-64}],
                 "children":[]},
                {"id":"node431",
                 "name":"4.31",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-79}],
                 "children":[]},
                {"id":"node432",
                 "name":"4.32",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":18}],
                 "children":[]}]},
            {"id":"node333",
             "name":"3.33",
             "data":[
                {"key":"key1",
                 "value":1},
                {"key":"key2",
                 "value":96}],
             "children":[
                {"id":"node434",
                 "name":"4.34",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":32}],
                 "children":[]},
                {"id":"node435",
                 "name":"4.35",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":-52}],
                 "children":[]}]},
            {"id":"node336",
             "name":"3.36",
             "data":[
                {"key":"key1",
                 "value":6},
                {"key":"key2",
                 "value":81}],
             "children":[
                {"id":"node437",
                 "name":"4.37",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":-51}],
                 "children":[]},
                {"id":"node438",
                 "name":"4.38",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":14}],
                 "children":[]},
                {"id":"node439",
                 "name":"4.39",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":18}],
                 "children":[]},
                {"id":"node440",
                 "name":"4.40",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-3}],
                 "children":[]}]},
            {"id":"node341",
             "name":"3.41",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":-56}],
             "children":[
                {"id":"node442",
                 "name":"4.42",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":56}],
                 "children":[]},
                {"id":"node443",
                 "name":"4.43",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-90}],
                 "children":[]},
                {"id":"node444",
                 "name":"4.44",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-64}],
                 "children":[]},
                {"id":"node445",
                 "name":"4.45",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-82}],
                 "children":[]}]}]},
        {"id":"node246",
         "name":"2.46",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-16}],
         "children":[
            {"id":"node347",
             "name":"3.47",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":-41}],
             "children":[
                {"id":"node448",
                 "name":"4.48",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":17}],
                 "children":[]},
                {"id":"node449",
                 "name":"4.49",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":24}],
                 "children":[]},
                {"id":"node450",
                 "name":"4.50",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":-11}],
                 "children":[]},
                {"id":"node451",
                 "name":"4.51",
                 "data":[
                    {"key":"key1",
                     "value":1},
                    {"key":"key2",
                     "value":-77}],
                 "children":[]}]},
            {"id":"node352",
             "name":"3.52",
             "data":[
                {"key":"key1",
                 "value":8},
                {"key":"key2",
                 "value":20}],
             "children":[
                {"id":"node453",
                 "name":"4.53",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":20}],
                 "children":[]},
                {"id":"node454",
                 "name":"4.54",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":77}],
                 "children":[]},
                {"id":"node455",
                 "name":"4.55",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":52}],
                 "children":[]},
                {"id":"node456",
                 "name":"4.56",
                 "data":[
                    {"key":"key1",
                     "value":3},
                    {"key":"key2",
                     "value":41}],
                 "children":[]}]},
            {"id":"node357",
             "name":"3.57",
             "data":[
                {"key":"key1",
                 "value":2},
                {"key":"key2",
                 "value":-17}],
             "children":[
                {"id":"node458",
                 "name":"4.58",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":4}],
                 "children":[]}]},
            {"id":"node359",
             "name":"3.59",
             "data":[
                {"key":"key1",
                 "value":10},
                {"key":"key2",
                 "value":-79}],
             "children":[
                {"id":"node460",
                 "name":"4.60",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-55}],
                 "children":[]},
                {"id":"node461",
                 "name":"4.61",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":92}],
                 "children":[]},
                {"id":"node462",
                 "name":"4.62",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-40}],
                 "children":[]},
                {"id":"node463",
                 "name":"4.63",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":57}],
                 "children":[]}]}]},
        {"id":"node264",
         "name":"2.64",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":91}],
         "children":[
            {"id":"node365",
             "name":"3.65",
             "data":[
                {"key":"key1",
                 "value":5},
                {"key":"key2",
                 "value":-51}],
             "children":[
                {"id":"node466",
                 "name":"4.66",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":50}],
                 "children":[]},
                {"id":"node467",
                 "name":"4.67",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":16}],
                 "children":[]}]},
            {"id":"node368",
             "name":"3.68",
             "data":[
                {"key":"key1",
                 "value":9},
                {"key":"key2",
                 "value":50}],
             "children":[
                {"id":"node469",
                 "name":"4.69",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":-22}],
                 "children":[]},
                {"id":"node470",
                 "name":"4.70",
                 "data":[
                    {"key":"key1",
                     "value":5},
                    {"key":"key2",
                     "value":-71}],
                 "children":[]}]}]},
        {"id":"node271",
         "name":"2.71",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-40}],
         "children":[
            {"id":"node372",
             "name":"3.72",
             "data":[
                {"key":"key1",
                 "value":7},
                {"key":"key2",
                 "value":-7}],
             "children":[
                {"id":"node473",
                 "name":"4.73",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":-35}],
                 "children":[]},
                {"id":"node474",
                 "name":"4.74",
                 "data":[
                    {"key":"key1",
                     "value":8},
                    {"key":"key2",
                     "value":92}],
                 "children":[]},
                {"id":"node475",
                 "name":"4.75",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":64}],
                 "children":[]},
                {"id":"node476",
                 "name":"4.76",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-95}],
                 "children":[]}]},
            {"id":"node377",
             "name":"3.77",
             "data":[
                {"key":"key1",
                 "value":3},
                {"key":"key2",
                 "value":-46}],
             "children":[
                {"id":"node478",
                 "name":"4.78",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":56}],
                 "children":[]},
                {"id":"node479",
                 "name":"4.79",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-40}],
                 "children":[]},
                {"id":"node480",
                 "name":"4.80",
                 "data":[
                    {"key":"key1",
                     "value":2},
                    {"key":"key2",
                     "value":-88}],
                 "children":[]}]},
            {"id":"node381",
             "name":"3.81",
             "data":[
                {"key":"key1",
                 "value":6},
                {"key":"key2",
                 "value":-81}],
             "children":[
                {"id":"node482",
                 "name":"4.82",
                 "data":[
                    {"key":"key1",
                     "value":7},
                    {"key":"key2",
                     "value":-14}],
                 "children":[]}]},
            {"id":"node383",
             "name":"3.83",
             "data":[
                {"key":"key1",
                 "value":4},
                {"key":"key2",
                 "value":32}],
             "children":[
                {"id":"node484",
                 "name":"4.84",
                 "data":[
                    {"key":"key1",
                     "value":6},
                    {"key":"key2",
                     "value":36}],
                 "children":[]},
                {"id":"node485",
                 "name":"4.85",
                 "data":[
                    {"key":"key1",
                     "value":9},
                    {"key":"key2",
                     "value":96}],
                 "children":[]},
                {"id":"node486",
                 "name":"4.86",
                 "data":[
                    {"key":"key1",
                     "value":10},
                    {"key":"key2",
                     "value":13}],
                 "children":[]},
                {"id":"node487",
                 "name":"4.87",
                 "data":[
                    {"key":"key1",
                     "value":4},
                    {"key":"key2",
                     "value":96}],
                 "children":[]}]}]}]}]};

Put this HTML in your page:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-spacetree.css" />

	<script type="text/javascript" src="/static/js/spacetree/Spacetree.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-spacetree.js" ></script>

	</head>
	<body onload="init();">

<canvas id="infovis" width="900" height="500"></canvas>
<div id="label_container" />

	</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.

Now, create a spacetree-example.css and put this code in it:

html, body {
	width:100%;
	height:100%;
	background-color:#444;
	text-align:center;
	overflow:hidden;
	font-size:9px;
	font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;
	margin:0;padding:0;
}

#infovis {
	background-color:#222;
	position:relative;
	width:900px;
	height:500px;
}

a, a:link, a:visited {
	color:#343439;
}

.node {
	background-color:transparent;
	font-weight:bold;
	overflow:hidden;
	text-decoration:none;
	position:absolute;
	text-align:center;
	padding:4px 1px 1px 1px;
}

.node:hover {
	color:#393434;
}

.hidden{
	display:none;
}

Note: the margin:0;padding:0; on html,body is pretty important to place well the ST labels.

Finally, create an example-spacetree.js file and put this code in it:

function init() {
	  var json= //data defined previously
	  //Create a new canvas instance.
	  var canvas= new Canvas('infovis');
	  //Create a new ST instance
	  st= new ST(canvas);
	  //load json data
	  st.loadFromJSON(json);
	  //compute node positions and layout
	  st.compute();
	  //optional: make a translation of the tree
	  Tree.Geometry.translate(st.tree, new Complex(-200, 0), "startPos");
	  //Emulate a click on the root node.
	  st.onClick(st.tree.id);
}

You should see a spacetree up and running (it may take a few seconds to load).

Some notes:

  • It’s mandatory to put the width and height properties on the canvas html tag.
    You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough.
  • You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
  • The Canvas constructor takes 1 parameter: the canvas id. To set the fillStyle and strokeStyle properties for nodes which are in path to root or nodes which aren’t you should refer to Config.Node.(strokeStyle|fillStyle|strokeStyleInPath|fillStyleInPath).
  • You can define how many levels to expand by setting Config.levelsToShow. However, if the expanded subtree height is greater than the canvas height, the spacetree might not show all levels. Unfortunately, this doesn’t happen when the width of the subtree expanded is greater than the canvas width (divided by two).

Customizing the Spacetree

The default layout for the spacetree is “left”. That means that the root node always lies at the left of the visualization. You can set the tree layout to “top” though.
So, put a checkbox in your HTML. Your HTML should look like this:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-spacetree.css" />

	<script type="text/javascript" src="/static/js/spacetree/Spacetree.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-spacetree.js" ></script>

	</head>
	<body onload="init();">

<input type="checkbox" id="switch"/>
<canvas id="infovis" width="900" height="500"></canvas>
<div id="label_container" />

	</body>
</html>

Note: You can add some style to the checkbox to put it somewhere else.

Now change the JS file to put a handler on the onchange event. It should look like this:

function init() {
	  var json= //data defined previously
	  //Create a new canvas instance.
	  var canvas= new Canvas('infovis');
	  //Create a new ST instance
	  st= new ST(canvas);
	  //load json data
	  st.loadFromJSON(json);
	  //compute node positions and layout
	  st.compute();
	  //optional: make a translation of the tree
	  Tree.Geometry.translate(st.tree, new Complex(-200, 0), "startPos");
	  //Emulate a click on the root node.
	  st.onClick(st.tree.id);

	//Add input handler to switch spacetree orientation.
  var checkbox = document.getElementById('switch');
  	checkbox.onchange = function () {
    	checkbox.disabled = true;
    	st.switchPosition({onComplete: function() {
        checkbox.disabled = false;
    }});
  };
}

Now if you click on the checkbox you should be able to switch the Spacetree orientation. Hows that!

Remember that you can also add controlers to the spacetree!. Take a look at the on controllers section and some examples with the hypertree.

Hope it was helpful!

Treemap quick tutorial

This tutorial requires you to have read Feeding JSON tree structures to the JIT and on controllers first.

Hi, this is going to be a quick tutorial on how to set the treemap up and running.

Note: You could change all calls to TM.Squarified to TM.SliceAndDice and it should also work.

We are going to work with this tree JSON structure:

var json = {"id":"node02",
 "name":"0.2",
 "data":[
    {"key":"key1",
     "value":195},
    {"key":"key2",
     "value":5}],
 "children":[
    {"id":"node13",
     "name":"1.3",
     "data":[
        {"key":"key1",
         "value":23},
        {"key":"key2",
         "value":8}],
     "children":[
        {"id":"node24",
         "name":"2.4",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":-75}],
         "children":[]},
        {"id":"node25",
         "name":"2.5",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-48}],
         "children":[]},
        {"id":"node26",
         "name":"2.6",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-1}],
         "children":[]},
        {"id":"node27",
         "name":"2.7",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":25}],
         "children":[]}]},
    {"id":"node18",
     "name":"1.8",
     "data":[
        {"key":"key1",
         "value":17},
        {"key":"key2",
         "value":28}],
     "children":[
        {"id":"node29",
         "name":"2.9",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-28}],
         "children":[]},
        {"id":"node210",
         "name":"2.10",
         "data":[
            {"key":"key1",
             "value":9},
            {"key":"key2",
             "value":-83}],
         "children":[]}]},
    {"id":"node111",
     "name":"1.11",
     "data":[
        {"key":"key1",
         "value":25},
        {"key":"key2",
         "value":-82}],
     "children":[
        {"id":"node212",
         "name":"2.12",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-27}],
         "children":[]},
        {"id":"node213",
         "name":"2.13",
         "data":[
            {"key":"key1",
             "value":3},
            {"key":"key2",
             "value":-80}],
         "children":[]},
        {"id":"node214",
         "name":"2.14",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":-73}],
         "children":[]},
        {"id":"node215",
         "name":"2.15",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":26}],
         "children":[]}]},
    {"id":"node116",
     "name":"1.16",
     "data":[
        {"key":"key1",
         "value":17},
        {"key":"key2",
         "value":91}],
     "children":[
        {"id":"node217",
         "name":"2.17",
         "data":[
            {"key":"key1",
             "value":7},
            {"key":"key2",
             "value":48}],
         "children":[]},
        {"id":"node218",
         "name":"2.18",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-86}],
         "children":[]}]},
    {"id":"node119",
     "name":"1.19",
     "data":[
        {"key":"key1",
         "value":52},
        {"key":"key2",
         "value":-77}],
     "children":[
        {"id":"node220",
         "name":"2.20",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":64}],
         "children":[]},
        {"id":"node221",
         "name":"2.21",
         "data":[
            {"key":"key1",
             "value":5},
            {"key":"key2",
             "value":84}],
         "children":[]},
        {"id":"node222",
         "name":"2.22",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":81}],
         "children":[]},
        {"id":"node223",
         "name":"2.23",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":25}],
         "children":[]},
        {"id":"node224",
         "name":"2.24",
         "data":[
            {"key":"key1",
             "value":4},
            {"key":"key2",
             "value":18}],
         "children":[]},
        {"id":"node225",
         "name":"2.25",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":37}],
         "children":[]},
        {"id":"node226",
         "name":"2.26",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":83}],
         "children":[]},
        {"id":"node227",
         "name":"2.27",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":-62}],
         "children":[]}]},
    {"id":"node128",
     "name":"1.28",
     "data":[
        {"key":"key1",
         "value":37},
        {"key":"key2",
         "value":-40}],
     "children":[
        {"id":"node229",
         "name":"2.29",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-67}],
         "children":[]},
        {"id":"node230",
         "name":"2.30",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":46}],
         "children":[]},
        {"id":"node231",
         "name":"2.31",
         "data":[
            {"key":"key1",
             "value":4},
            {"key":"key2",
             "value":-99}],
         "children":[]},
        {"id":"node232",
         "name":"2.32",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":-38}],
         "children":[]},
        {"id":"node233",
         "name":"2.33",
         "data":[
            {"key":"key1",
             "value":1},
            {"key":"key2",
             "value":-3}],
         "children":[]},
        {"id":"node234",
         "name":"2.34",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":82}],
         "children":[]}]},
    {"id":"node135",
     "name":"1.35",
     "data":[
        {"key":"key1",
         "value":24},
        {"key":"key2",
         "value":63}],
     "children":[
        {"id":"node236",
         "name":"2.36",
         "data":[
            {"key":"key1",
             "value":10},
            {"key":"key2",
             "value":8}],
         "children":[]},
        {"id":"node237",
         "name":"2.37",
         "data":[
            {"key":"key1",
             "value":8},
            {"key":"key2",
             "value":63}],
         "children":[]},
        {"id":"node238",
         "name":"2.38",
         "data":[
            {"key":"key1",
             "value":6},
            {"key":"key2",
             "value":46}],
         "children":[]}]}]};

Note: remember that the Treemap takes the first dataset object value to calculate the rectangles dimensions. That means that the values you setted on the first dataset object for all nodes must be coherent. Coherent means that, for example, if node A has nodes B and C as children, B having 3 as its first dataset object value and C having 2 as its first dataset value, then A must have 5 as its first dataset object value.

Put this HTML in your page:

<html>
	<head>

	<link type="text/css" rel="stylesheet" href="/static/css/example-treemap.css" />

	<script type="text/javascript" src="/static/js/mootools-1.2.js"></script>
	<script type="text/javascript" src="/static/js/treemap/Treemap.js" ></script>
	<script type="text/javascript" src="/static/js/example/example-treemap.js" ></script>

	</head>

	<body onload="init();">

<div id="infovis" />

	</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.
Note2: This is the only visualization that requires Mootools 1.2+ to run. I use version 1.2 which comes packaged with the library (in the extras folder). You can also download it from here.

Now, create a treemap-example.css and put this code in it:

html, body {
	width:100%;
	height:100%;
	background-color:#222;
	text-align:center;
	overflow:hidden;
	font-size:10px;
	font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;
}

#infovis {
	position:relative;
	width:900px;
	height:500px;
	margin:auto;
	background-color:#1D1D20;
}

#infovis div {
	position:absolute;
	overflow:hidden;
}

#infovis .content {
	background-color:#333;
	border:0px solid #111;
}

#infovis .head {
	height:12px;
	color:white;
	background-color:#444;
}

#infovis .head.in-path {
	background-color:#655;
}

#infovis .body {
	background-color:black;
}

#infovis .leaf {
	color:white;
	background-color:#111;
	display:table-cell;
	vertical-align:middle;
}

#infovis .over-leaf {
	border:1px solid #9FD4FF;
}

#infovis .over-content {
	background-color: #9FD4FF;
}

#infovis .over-head { /* ...boy i'm funny */
	background-color:#A4D9FF;
	color:black;
}

/*TOOLTIPS*/
.tool-tip {
	color: #fff;
	width: 139px;
	z-index: 13000;
	background-color: black;
}

.tip-title {
	font-weight: bold;
	font-size: 11px;
	margin: 0;
	color: #9FD4FF;
	padding: 8px 8px 4px;
	background-color: black;
}

.tip-text {
	font-size: 11px;
	padding: 4px 8px 8px;
	background-color: black;
}

Note: I won’t explain all CSS classes, they are pretty much self explainable. However, you must put a position:relative; in the infovis container (the visualization container), just as specified on the CSS stylesheet.

Finally, create an example-treemap.js file and put this code in it:

function init() {
	var json = //json data specified above...
	var tm = new TM.Squarified();
	tm.loadFromJSON(json);

}

You should see a treemap up and running.

Some notes:

  • It’s mandatory to put the width and height style properties on the main div container, just as specified on the CSS stylesheet.
  • You could change the main container id by setting the Config.rootId property to whatever id you like. Be sure to set that property before making a TM instance.

Customizing the Treemap

Let’s add some colors!
In order to add colors you must know three things:

  • Colors are calculated by taking the second dataset object value. You must also know the range of this value. In this example the second value ranges between [-100, 100]. You can change these values by setting the Config.Color.minValue and Config.Color.maxValue parameters. Remember to do this before instanciating the TM.
  • You can also choose the color range for your visualization, this is done by setting the Config.Color.minColorValue and Config.Color.maxColorValue parameters. These properties take an array of 3 integers each describing an RGB value. Remember to do this before instanciating the TM.
  • Finally, to enable treemap coloring you must set the property Config.Color.allow to true.

So the init javascript function would now look like:

function init() {
	var json = //..json data
	//Allow coloring
	Config.Color.allow = true;
//Set min value and max value for the second *dataset* object values.
//Default's to -100 and 100.
	Config.Color.minValue = -100;
	Config.Color.maxValue = 100;
//Set color range. Default's to reddish and greenish. It takes an array of three
//integers as R, G and B values.
	Config.Color.minColorValue = [255, 0, 50];
	Config.Color.maxColorValue = [0, 255, 50];

	var tm = new TM.Squarified();
	tm.loadFromJSON(json);
}

You should see a colored treemap now.

This part of the tutorial has been updated for the new 1.0.7a library spec. If you have any questions please feel free to post them at the google group

Finally, let’s put nice tooltips! We’ll do this by using the Tip Mootools class.
First, we’ll define an onAfterCompute controller method to query for all nodes that will be displaying information (like .head and .leaf nodes) and assign the information to be displayed. To know more about this please check the docs for the Tips Mootools plug in
I also define some extra methods that convert the dataset to HTML.
I also allow tooltips by setting Config.tips to true.

So the JavaScript file should now look like this:

function init() {
	var json = //...same json data as before...
	//Allow coloring
	Config.Color.allow = true;
//Set min value and max value for the second *dataset* object values.
//Default's to -100 and 100.
	Config.Color.minValue = -100;
	Config.Color.maxValue = 100;
//Set color range. Default's to reddish and greenish. It takes an array of three
//integers as R, G and B values.
	Config.Color.minColorValue = [255, 0, 50];
	Config.Color.maxColorValue = [0, 255, 50];

	//Allow tips for treemap
	Config.tips = true;

	var tm = new TM.Squarified({
		onAfterCompute: function() {
			var that = this, parent;
			$$('#infovis .leaf', '#infovis .head').each(function(elem, i) {
				//get the JSON tree node element having the same id
				//as the dom element queried and makeTip.
				if(p = elem.getParent()) {
					var sTree = TreeUtil.getSubtree(tm.tree, p.id);
					if(sTree) that.makeTip(elem, sTree);
				}
			});
		},
//Tooltip content is setted by setting the *title* of the element to be *tooltiped*.
//Read the mootools docs for further understanding.
		makeTip: function(elem, json) {
			var title = json.name;
			var html = this.makeHTMLFromData(json.data);
			elem.store('tip:title', title).store('tip:text', html);
		},
//Take each dataset object key and value and make an HTML from it.
		makeHTMLFromData: function(data) {
			var html = '';
			for(var i=0; i<data.length; i++) {
				html += data[i].key + ': ' + data[i].value + '<br />';
			}
			return html;
		}

	});

	tm.loadFromJSON(json);
}

You should see some tooltips now!

Remember that you have more controller methods to customize your visualization just as you want! Hope it was helpful.

Hypertree quick tutorial

This tutorial requires you to have read Feeding JSON tree structures to the JIT and on controllers first.

Hi, this is going to be a quick tutorial on how to set the hyperbolic tree up and running.

We are going to work with this tree JSON structure:

var json = {"id":"node02",
"name":"0.2",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":71}],
"children":[
{"id":"node13",
"name":"1.3",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":-9}],
"children":[
{"id":"node24",
"name":"2.4",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-42}],
"children":[]},
{"id":"node25",
"name":"2.5",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":59}],
"children":[]},
{"id":"node26",
"name":"2.6",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-50}],
"children":[]},
{"id":"node27",
"name":"2.7",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-78}],
"children":[]}]},
{"id":"node18",
"name":"1.8",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":79}],
"children":[
{"id":"node29",
"name":"2.9",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":77}],
"children":[]},
{"id":"node210",
"name":"2.10",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":30}],
"children":[]},
{"id":"node211",
"name":"2.11",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-44}],
"children":[]}]},
{"id":"node112",
"name":"1.12",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":94}],
"children":[
{"id":"node213",
"name":"2.13",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":99}],
"children":[]},
{"id":"node214",
"name":"2.14",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-72}],
"children":[]},
{"id":"node215",
"name":"2.15",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node216",
"name":"2.16",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":53}],
"children":[]},
{"id":"node217",
"name":"2.17",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-96}],
"children":[]},
{"id":"node218",
"name":"2.18",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-84}],
"children":[]},
{"id":"node219",
"name":"2.19",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-4}],
"children":[]},
{"id":"node220",
"name":"2.20",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":66}],
"children":[]}]},
{"id":"node121",
"name":"1.21",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":0}],
"children":[
{"id":"node222",
"name":"2.22",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":66}],
"children":[]},
{"id":"node223",
"name":"2.23",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-78}],
"children":[]},
{"id":"node224",
"name":"2.24",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-91}],
"children":[]},
{"id":"node225",
"name":"2.25",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-51}],
"children":[]},
{"id":"node226",
"name":"2.26",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":25}],
"children":[]},
{"id":"node227",
"name":"2.27",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":30}],
"children":[]},
{"id":"node228",
"name":"2.28",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-43}],
"children":[]}]},
{"id":"node129",
"name":"1.29",
"data":[
{"key":"key1",
"value":3},
{"key":"key2",
"value":-89}],
"children":[
{"id":"node230",
"name":"2.30",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":96}],
"children":[]},
{"id":"node231",
"name":"2.31",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":-21}],
"children":[]},
{"id":"node232",
"name":"2.32",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node233",
"name":"2.33",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":42}],
"children":[]}]},
{"id":"node134",
"name":"1.34",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":84}],
"children":[
{"id":"node235",
"name":"2.35",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-14}],
"children":[]},
{"id":"node236",
"name":"2.36",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":60}],
"children":[]},
{"id":"node237",
"name":"2.37",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":-71}],
"children":[]}]},
{"id":"node138",
"name":"1.38",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":-70}],
"children":[
{"id":"node239",
"name":"2.39",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-69}],
"children":[]},
{"id":"node240",
"name":"2.40",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-31}],
"children":[]},
{"id":"node241",
"name":"2.41",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-5}],
"children":[]},
{"id":"node242",
"name":"2.42",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":62}],
"children":[]},
{"id":"node243",
"name":"2.43",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":91}],
"children":[]}]},
{"id":"node144",
"name":"1.44",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":10}],
"children":[
{"id":"node245",
"name":"2.45",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-2}],
"children":[]},
{"id":"node246",
"name":"2.46",
"data":[
{"key":"key1",
"value":1},
{"key":"key2",
"value":93}],
"children":[]},
{"id":"node247",
"name":"2.47",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":70}],
"children":[]},
{"id":"node248",
"name":"2.48",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-40}],
"children":[]}]},
{"id":"node149",
"name":"1.49",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":-58}],
"children":[
{"id":"node250",
"name":"2.50",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":-41}],
"children":[]},
{"id":"node251",
"name":"2.51",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-91}],
"children":[]},
{"id":"node252",
"name":"2.52",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-21}],
"children":[]},
{"id":"node253",
"name":"2.53",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-69}],
"children":[]},
{"id":"node254",
"name":"2.54",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":5}],
"children":[]},
{"id":"node255",
"name":"2.55",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-43}],
"children":[]},
{"id":"node256",
"name":"2.56",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":64}],
"children":[]},
{"id":"node257",
"name":"2.57",
"data":[
{"key":"key1",
"value":10},
{"key":"key2",
"value":-60}],
"children":[]}]},
{"id":"node158",
"name":"1.58",
"data":[
{"key":"key1",
"value":7},
{"key":"key2",
"value":-63}],
"children":[
{"id":"node259",
"name":"2.59",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":86}],
"children":[]},
{"id":"node260",
"name":"2.60",
"data":[
{"key":"key1",
"value":4},
{"key":"key2",
"value":13}],
"children":[]},
{"id":"node261",
"name":"2.61",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-70}],
"children":[]},
{"id":"node262",
"name":"2.62",
"data":[
{"key":"key1",
"value":5},
{"key":"key2",
"value":-83}],
"children":[]},
{"id":"node263",
"name":"2.63",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-98}],
"children":[]},
{"id":"node264",
"name":"2.64",
"data":[
{"key":"key1",
"value":2},
{"key":"key2",
"value":-79}],
"children":[]},
{"id":"node265",
"name":"2.65",
"data":[
{"key":"key1",
"value":9},
{"key":"key2",
"value":10}],
"children":[]},
{"id":"node266",
"name":"2.66",
"data":[
{"key":"key1",
"value":6},
{"key":"key2",
"value":17}],
"children":[]},
{"id":"node267",
"name":"2.67",
"data":[
{"key":"key1",
"value":8},
{"key":"key2",
"value":26}],
"children":[]}]}]};

Put this HTML in your page:

<html>
<head>

<link type="text/css" rel="stylesheet" href="/static/css/example-hypertree.css" />

<!--[if IE]>
<script type="text/javascript" src="/static/js/excanvas.js"></script>
<![endif]-->

<script type="text/javascript" src="/static/js/hypertree/Hypertree.js" ></script>
<script type="text/javascript" src="/static/js/example/example-hypertree.js" ></script>

</head>
<body onload="init();">

<canvas id="infovis" width="900" height="500"></canvas>
<div id="label_container"></div>

</body>
</html>

Note: You’ll probably have to change the paths to the css and javascript files.

Now, create a hypertree-example.css and put this code in it:

html, body {
width:100%;
height:100%;
background-color:#444;
text-align:center;
overflow:hidden;
font-size:10px;
font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;

}

#infovis {
background-color:#222;
width:900px;
height:500px;
}

.node {
border: 1px solid #555;
background-color: #ccc;
color:#222;
cursor:pointer;
padding:2px;
display:none;
}

.hidden {
display:none;
}

Note: I like the canvas black, just like my coffee.

Finally, create an example-hypertree.js file and put this code in it:

function init() {

var json = //the json structure mentioned above...
//Create a new canvas instance.
var canvas= new Canvas('infovis', '#fff', '#fff');
//create a new hypertree instance.
var ht= new Hypertree(canvas);
//feed the hypertree with a JSON structure.
ht.loadTreeFromJSON(json);
//compute node positions
ht.compute();
//plot the hypertree on canvas
ht.plot();
//add event handlers to the canvas in order to move the hypertree when I click con the canvas -optional-
ht.prepareCanvasEvents();
}

You should see a hypertree up and running (it may take a few seconds to load).

Some notes:

  • It’s mandatory to put the width and height properties on the canvas html tag.
    You could set those properties dynamically, of course, but what I mean is that setting only width and height style properties (as with CSS) isn’t enough.
  • You could change the label container id by setting the Config.labelContainer property to whatever id you like. Be sure to set that property before making a Canvas instance.
  • The Canvas constructor takes 3 parameters: the canvas id, the fillStyle property and the strokeStyle property. If you don’t know what those properties are, take a look at this section from the canvas tutorial.
  • It’s not mandatory to add the ht.prepareCanvasEvents(); method. This method just adds some event handlers to the canvas tag in order to move the tree when you click on the canvas.
  • You can take off the main circle by setting Config.drawMainCircle to false. Just be sure you do that before making a canvas or Hypertree instance.

Customizing the Hypertree

Let’s add some labels!
Note: I’ll be using the Mootools library to do this, just because I don’t want to spend time writing low level code that would make the code uglier. You can use any library you want (or none at all) though.

First, strip off the display:none; line from the .node class in your CSS file.
It should look like this:

.node {
border: 1px solid #555;
background-color: #ccc;
color:#222;
cursor:pointer;
padding:2px;
}

Now we are going to add a javascript controller in order to put the name of the nodes into the labels. Since we only need to do this once, we’ll use the onCreateLabel method. If you don’t know what I’m talking about you should probably read the on controllers post first.

So the JavaScript file should look like this now:

function init() {
	var json = //json data mentioned above...
	var canvas= new Canvas('infovis', '#fff', '#fff');
	var ht= new Hypertree(canvas, {

		onCreateLabel: function(domElement, node) {
		$(domElement).set('html', node.name + " and text");
		}
	});

	ht.loadTreeFromJSON(json);
	ht.compute();
	ht.plot();
	ht.prepareCanvasEvents();
}

You should see some labels now.
The thing is that… well, they are not centered. So we’ll just add an onPlaceLabel method to the controller in order to do that, since the onPlaceLabel method is called after labels have been placed.

So the js code should now look like:

function init() {
	var json = //json data...
	var canvas= new Canvas('infovis', '#fff', '#fff');
	var ht= new Hypertree(canvas, {
		onCreateLabel: function(domElement, node) {
		$(domElement).set('html', node.name + " and text");
		},

		//Take the left style property and
		// substract half of the label actual width.
		onPlaceLabel: function(tag, node) {
		var width = tag.offsetWidth;
		var intX = tag.style.left.toInt();
		intX -= width/2;
		tag.style.left = intX + 'px';
		}

	});

	ht.loadTreeFromJSON(json);
	ht.compute();
	ht.plot();
	ht.prepareCanvasEvents();
}

You should see some centered labels now!

Finally, we’ll add an onclick event handler in order to move the tree when clicking on a label, hows that!

We’ll add this method on the onCreateLabel method, just because we only want to add label event handlers once.
So the code should look like:

function init() {
	var json = //some json data
	var canvas= new Canvas('infovis', '#fff', '#fff');
	var ht= new Hypertree(canvas, {
		onCreateLabel: function(domElement, node) {
			$(domElement).set('html', node.name + " and text").addEvents({
					//Call the "onclick" method from
					//the hypertree to move the hypertree
					//correspondingly.
					//This method takes the native event object.
					//Since Mootools uses a wrapper for this
					//event, I have to put e.event to get the
					//native event object.
					'click': function(e) {
					ht.onClick(e.event);
					}
				});

		},

		//Take the left style property and
		//substract half of the label actual width.
		onPlaceLabel: function(tag, node) {
			var width = tag.offsetWidth;
			var intX = tag.style.left.toInt();
			intX -= width/2;
			tag.style.left = intX + 'px';
		}

	});

	ht.loadTreeFromJSON(json);
	ht.compute();
	ht.plot();
	ht.prepareCanvasEvents();
}

If you want to see more advanced examples please check the “examples” folder in the library.

Remember that you have more controller methods!

Remember also that you can change the animation time and the frames per second in the animation with Config.animationTime and Config.fps.
Hope it was helpful.

On controllers

Controllers are a straightforward way to customize the JavaScript infovis toolkit (JIT) visualizations.
A controller is a JavaScript object that “implements” an interface. The interface methods will then be called at different stages of the visualization, allowing you to, for example, place labels and add event handlers to them, performing actions before and after the animation, making ajax - calls to load data dynamically to the tree, etc.

The controller interface is defined as:

 var ControllerInterface = {

       onCreateLabel: function (domElement, node) {},

       onPlaceLabel: function (domElement, node) {},

       onBeforePlotLine: function(adj) {},

       onAfterPlotLine: function(adj) {},

       onBeforeCompute: function (node) {},

       onAfterCompute: function () {}

       request: function(nodeId, level, onComplete) {},

 };
 

where:

  • onCreateLabel(domElement, node) is a method that receives the label dom element as first parameter, and the homologue JSON tree node as second parameter. This method will only be called on label creation. Note that a JSON tree node is a node from the input tree you provided to the visualization. If you don’t know what kind of JSON tree format is used to feed the visualizations, you should take a look at my other post first, feeding JSON tree structures to the JIT.
    This method proves useful when adding events to the labels used by the JIT.
  • onPlaceLabel(domElement, node) is a method that receives the label dom element as first parameter and the homologue JSON tree node as second parameter. This method is called each time a label has been placed on the visualization, and thus it allows you to update the labels properties, such as size or position. Note that onPlaceLabel will be triggered after updating positions to the labels. That means that, for example, the left and top css properties are allready updated to match the nodes positions.
  • onBeforePlotLine(adj) is called right before plotting an edge. It provides an adjacence object adj. This object contains two important properties, adj.nodeFrom and adj.nodeTo which contain the graph nodes connected by this edge. You can also assign extra information in an adjacency object, by using the data property. This can be done when assigning weighted graph JSON structures to the visualizations. To know more about weighted nodes and edges please check this post.
  • onAfterPlotLine(adj) behaves exactly like onBeforePlotLine except that this method is called right after plotting the adj edge. This method can be useful to restore a lineWidth state you’ve previously changed onBeforePlotLine.
  • onBeforeCompute(node) is a method called right before performing all computation and animations to the JIT visualization. In the case of treemaps this method will be called after entering or exiting a tree level. In the case of Hyperbolic trees, RGraphs and Spacetrees, this method will be triggered right before perfoming an animation.
    For Treemap visualizations, the node parameter corresponds to the root node of the subtree which will be laid out.
    For the Spacetree, Hypertree and RGraph visualizations, the node parameter corresponds to the actual node being clicked or centered on the canvas.
  • onAfterCompute() is a method triggered right after all animations or computations for the JIT visualizations ended.
  • request(nodeId, level, onComplete) is a method only used by the Treemap and Spacetree visualizations. You can use this method to “bufferize” information, so that not all the JSON tree structure is loaded at once. The nodeId parameter is the node actually being requested, the level parameter is the level of the subtree being requested, and the onComplete handler is a function you must call after performing your request. A common structure for the request method could be
    	request: function(nodeId, level, onComplete) {
    		var data;
                    //make a request call to fill the data object and on complete do:
    		onComplete(nodeId, data);
    	},
    

Note that you should not declare any of these methods on your controller object if you are not going to use them.
Note also that is not mandatory to provide a controller object to the main classes.
You can find some example uses for the controller object at the spacetree, hypertree, treemap and rgraph tutorials.
Be sure to know what JSON structure feeds the JIT visualizations before you read the tutorials.
Hope it was helpful.

Feeding JSON tree structures to the JIT

The tree structure that feeds the spacetree, hypertree, treemap and rgraph visualizations is always the same.
Roughly speaking, the JSON tree structure consists of tree nodes, each having as properties:

  • id a unique identifier for the node.
  • name a node’s name.
  • data The data property contains a dataset. That is, an array of key-value objects defined by the user. Roughly speaking, this is where you can put some extra information about your node. You’ll be able to access this information at different stages of the computation of the JIT visualizations by using a controller.
  • children An array of children nodes, or an empty array if the node is a leaf node.

For example,

var json = {
	"id": "aUniqueIdentifier",
	"name": "usually a nodes name",
	"data": [
	    {key:"some key",       value: "some value"},
		{key:"some other key", value: "some other value"}
	],
	children: [/* other nodes or empty */]
};

About datasets:

Sometimes some dataset objects are read by the JIT classes to perform proper layouts.
For example, the treemap class reads the first object’s value for each node’s dataset to perform calculations about the dimensions of the rectangles laid.
Also, if you enable the Config.Color.allow property, the treemap will add colors on the layout, and these colors will be based on your second dataset object value.
RGraphs and Hyperbolic Trees also read the first dataset object value in order to compute node diameters and angular widths, when setting Config.allowVariableNodeDiameters = true.

That’s all for now. I recommend you to read the On controllers section and then some spacetree, hypertree, treemap or RGraph tutorials.