HyperTree – Converting JIT Examples to JQuery

2 Comments

Recently, while working on the Kiobo project with Lynn we stumbled across the JIT (JavaScript Information Visualization Toolkit) library. It is an amazing toolkit that has helped us see the future of JavaScript visualizations, which has previously been an area where only Flash/ActionScript has had the power to display highly animated and appealing client side visualization of data. On the current Kiobo site, you can see it is almost entirely written in Flash/ActionScript, but the future leads us in another direction.

The JIT is quite easy to integrate into your own site. Simply taking the examples and filling in your own JSON object with data can make quite an impression on people visiting your project. One issue that I ran into during implementation was that all the examples were written with the MooTools framework in mind. MooTools is a great framework, but Kiobo was already using the JQuery library for our JavaScript needs. I took on the task of converting the examples into JQuery to use them with Kiobo.

To implement JQuery with Kiobo I used the JRails plugin to replace all the Prototype methods. What follows won’t be a recreation of the entire tutorial, only the situations where you will need to change things.

First, rather than calling the MooTools library, we’ll call the JQuery library (and while we’re at it we’ll convert all the standard HTML to Rails).

So in the example you have this code:

<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/mootools-1.2.js" ></script>
<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();">
<div id="infovis"></div>
</body>
</html>

Once you have converted everything and called your JQuery library it should look like this:

<html>
<head>

<!--[if IE]>
<%= javascript_include_tag 'excanvas' %>
<![endif]-->

<%= javascript_include_tag :defaults %>
<%= javascript_include_tag 'example/example-hypertree' %>
<%= javascript_include_tag 'Hypertree' %>
<%= stylesheet_link_tag 'example-hypertree' %>
</head>
<body onload="init();">
<div id="infovis"></div>
</body>
</html>

This will load the JQuery Library, as well as the Hypertree library, the example-hypertree library and the stylesheet example-hypertree.

At this point you will be able to continue the tutorial and see your first HyperTree. However, when you get to adding labels things once again diverge.

The example uses this code:

function init() {
var json = //json data mentioned above...
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
var ht= new Hypertree(canvas, {

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

});

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

This will not work the same with JQuery as it has some MooTools specific calls, particularly:
$(domElement).set(‘html’, node.name + ” and text”)
However this is an easy fix with JQuery
$(domElement).html(node.name + ” and text”)
So your entire file should look like

function init() {
var json = //json data mentioned above...
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
var ht= new Hypertree(canvas, {

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

});

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

When placing the labels you will also need to change the code a bit. I couldn’t find a similar method inside the JQuery core for the .toInt() method so we’ll fall back to parseInt.

function init() {
var json = //json data...
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
var ht= new Hypertree(canvas, {
onCreateLabel: function(domElement, node) {
$(domElement).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();
}

Use this example instead:

function init() {
var json = //json data...
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
var ht= new Hypertree(canvas, {
onCreateLabel: function(domElement, node) {
$(domElement).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 = parseInt(tag.style.left);
intX = intX-(width/2);
tag.style.left = intX + 'px';
},

});

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

Finally, adding events to the HyperTree. This is actually completely different than the MooTools example
.addEvents({‘click’: function(e) {ht.onClick(node.id)}});
It will instead be replaced with click method
.click( function () {ht.onClick(node.id)} );

So your final code should look like this:

function init() {
var json = //some json data
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
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 clicked node's id.
'click': function(e) {
ht.onClick(node.id);
}
});

},

//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();
}

Your code:

function init() {
var json = //some json data
//Create a new canvas instance.
var canvas = new Canvas('mycanvas', {
//Where to inject the canvas. Any HTML container will do.
'injectInto':'infovis',
//Width and height of canvas, default's to 200.
'width': 900,
'height':500,
//Canvas styles.
'styles': {
'fillStyle': '#ddd',
'strokeStyle': '#dd00bb'
}
});
var ht= new Hypertree(canvas, {
onCreateLabel: function(domElement, node) {
$(domElement).html(node.name + " and text").click( function () {ht.onClick(node.id)} );
},

//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();
}