Due to popular demand in pentaho forums, here's some guidelines on how to use the protovis component in CDE.


Even though CCC defines the charts that we're interested in using 90% of the time, the other 10% are fundamental. Even if it's "just because we can".


The protovis component in CDE allows the dashboard developer to take full use of protovis language but goes a bit further than that; Does all the necessary link with the dashboard layout, does the necessary initialization so that it runs in IE and even connects with the data.


I'll show 2 samples: in one of them we'll supply an object to be used as the data, and in the second one we'll use the result of a query to build a chart.


Example 1: Bubble Charts


Create a new dashboard in CDE, and save it in some location (always start by doing this). Then in the layout panel, add one row and 2 columns with span 12, thus totaling 24, the full extent of the layout. Name the 2 columns as chart1 and chart2 respectively.


Add a custom component called "flare" and define the contents as what's in this flare.js file. This will be the data we'll use in the sample.

Now add a protovis component, call it anything you like (I called it protovisComp1). I used 400 for both width and height. In the htmlObject chose the first column.


Now all that's left is the definition of the function. It has the form:


function(vis,data){
// vis - the container where protovis objects will be drawn
// data - result of the query, if applicable
}

For this sample, I'll use the code in the bubble chart sample


function(vis,data){

/* Produce a flat hierarchy of the Flare classes. */
var classes = pv.nodes(pv.flatten(flare).leaf(Number).array());
classes.slice(1).forEach(function(d) {
d.nodeName = "flare." + d.nodeValue.keys.join(".");
var i = d.nodeName.lastIndexOf(".");
d.className = d.nodeName.substring(i + 1);
d.packageName = d.nodeName.substring(0, i);
d.nodeValue = d.nodeValue.value;
});

/* For pretty number formatting. */
var format = pv.Format.number();

vis.add(pv.Layout.Pack)
.top(-50)
.bottom(-50)
.nodes(classes)
.size(function(d) d.nodeValue)
.spacing(0)
.order(null)
.node.add(pv.Dot)
.fillStyle(pv.Colors.category20().by(function(d) d.packageName))
.strokeStyle(function() this.fillStyle().darker())
.visible(function(d) d.parentNode)
.title(function(d) d.nodeName + ": " + format(d.nodeValue))
.anchor("center").add(pv.Label)
.text(function(d) d.className.substring(0, Math.sqrt(d.nodeValue) >> 4));

}

If you save and preview, you should see the bubble chart:




Example 2: Pie & Donut Charts

In the first example I defined the data that rendered the bubble chart in a custom parameter. Here, I'll show how to use a CDA query to feed the data.

Note: the pie chart I chose for example 2 is a rather uninteresting one. If you want a pie chart you'll better use CCC Pie Chart Component. I used this one of the sake of simplicity, but virtually any other protovis sample could be used here

Create a sql input over jndi query named "myQuery", choose SampleData for the source and use the query:



select c.TERRITORY, SUM(o.QUANTITYORDERED) as quantity
from ORDERFACT o
inner join CUSTOMER_W_TER c on (c.CUSTOMERNUMBER=o.CUSTOMERNUMBER)
group by c.TERRITORY


Now create a second protovis component, repeat the same instructions as for the first one but this time select "myQuery" as the datasource. The difference is that our protovis function is
called after the query runs, and the object "data" is the result of the query. Here's the function I used, slightly modified to take into account the format of the data cda returns.


function(vis,queryResult){

var data = queryResult.resultset;

/* Sizing and scales. */
var w = this.width,
h = this.height,
r = w / 2,
a = pv.Scale.linear(0, pv.sum(data.map(function(d){return d[1]}))).range(0, 2 * Math.PI);


/* The wedge, with centered label. */
vis.add(pv.Wedge)
.data(data)
.bottom(w / 2)
.left(w / 2)
.innerRadius(r - 40)
.outerRadius(r)
.angle(function(d){return a(d[1])})
.event("mouseover", function(){return this.innerRadius(0)})
.event("mouseout", function(){return this.innerRadius(r - 40)})
.anchor("center").add(pv.Label)
.visible(function(d){return a(d[1]) > .15})
.textAngle(0)
.text(function(d){return d[0]});
}


If all went well, you should now have a protovis sample with both charts running, one of them with data from your query


Some important notes:

  • Don't create the vis object (the protovis root panel) - cdf takes care of that for you. The size and placement comes out of the options you provide
  • Don't call the render() method. Let the cdf lifecycle take care of that for you
  • Don't use 1.8 syntax. You'll see a lot of functions defined like function(d) d . While very practical, it will guarantee to break in internet explorer. Use the extended format of function(d){return d}.
  • CDF will make the necessary arrangements so that it will work on IE 8 or less, by converting it to flash. Flash 10 required and, as usual, make sure your javascript code is foul proof...

Hope that helps. By now, you should also be able to understand why we created CCC. It's a royal PITA to write pure protovis code for every basic chart we need :)


More...