Dojox Charting Update – Part Two
First of all, with the demo database, there are a couple of basic, standard changes. The first is that I’m using the XPages extension library, so that’s enabled in the Xsp Properties. That’s used for the Java code, to leverage the ExtLibUtil class to give easy access to standard XPages objects and virtually every Java XPages developer will be using ExtLibUtil. Whether or not you use Java in XPages is a matter of choice, personally I moved to using Java for anything significant after my first production XPages application, now I rarely write more than a handful of lines of SSJS in a block. But regardless of SSJS or Java, I would not be happy working on any XPages application now that does not use the extension library.
The second is I’ve removed the beforePageLoad code covering Internet Explorer 8. Internet Explorer 9 was released March 2011. New XPages applications should target at least that version, in my opinion. If a more modern browser is not available, there will be other applications that cannot be used. As of June 2017, according to NetMarketShare, IE 8 has 1.62% market share (indeed IE9 has 1.07%). One wonders how much of that 1.62% have only Internet Explorer 8.
The first big difference is no resource added to the XPage to load Dojo modules. That is no longer necessary. But we still have two divs, one for the chart and one for the legend. I’m using xp:divs, which is what you’ll want if you are using a custom control, in order to ensure unique IDs for DOM manipulation. I’ve also got an xe:objectData at the top of the page. There are various methods for accessing Java code – static methods in a utility class, managed beans, controller classes backing your XPage, or an xe:objectData as here. How the XPage gets to the Java code is not an important point here, more is that this maps to a Java class called
uk.co.intec.ChartSample in the Code/Java area of the application.
First, in lines 1 – 29 is a
dojo/domReady. This means the function loads when Dojo has finished. So there’s no longer any need to use
Then comes the function itself, as the second argument passed to the
require function. So we’re still creating a function variable to load the chart, it’s just that instead of passing it to
XSP.addOnLoad() we’re passing it to
require. But this time the function takes a number of arguments, namely the modules we’re requiring.
One difference is that when adding a plot, instead of using a String for the
type property, we’re mapping directly to the Dojo module passed in as an argument to our function, for example in lines 39 and 46. Strings still seem to work (I didn’t notice I’d still got
type: "Grid"), but it makes sense to pass the Dojo module object. Another new element added here (I think it was added in Dojo 1.6) is that we’re adding settings for the
animate property on line 42, to add animation to the loading of the line plot.
In lines 49 – 53 we’re adding custom labels to the x axis. There are a couple of ways of doing this by passing a JSON object in or a label function, as here. However, if you look at all the JSON objects in this Dojo code, you’ll see the key is a variable, not a string. So for the x axis, it’s
"max". The Java code we’ll see later for creating the JSON objects makes the key a String, so the latter, which won’t work. So we have to use a label function.
data are populated from getters in the Java class, so I’ll just gloss over those for now. The data is a JSON object where the key is the name of the series (it also appears in the legend) and the value is an array of points to plot on the y axis. So we can just use a for loop to iterate over them and return the value, the array of points on the y axis.
The Magnify widget on line 70 just magnifies the point when you hover on it and display the tooltip, same as with the previous version of the chart. Rendering the chart is the same as before.
Instead of the normal Legend, this time I’ve used the SelectableLegend widget on line 76. This puts checkboxes beside each series in the legend, allowing you to show or hide each without needing to re-draw the whole chart. One point of particular note is the
horizontal property. In previous versions this was set to
false and I wrote a Dojo widget extension specifically for my Lotusphere 2010 session on Dojo in order to allow it to be multi-column. When I started looking at the SelectableLegend widget I wanted to see if it supported multiple columns in a horizontal format. When I read the code this time, it became apparent that it’s not a boolean vallule but an int value, corresponding to the number of columns to display in a horizontal layout. So here you’ll see it’s 8, giving eight columns. The same is also true of the Legend.
Documentation is a bugbear of mine. Here again it rears its head. The API documentation lists all the properties of the SelectableLegend and Legend widgets, and includes the
horizontal property. But it doesn’t specify what the expected values are. I don’t know whether something has changed in how this propertty works or whether I guessed wrong when I read the documentation back in 2009. But I had to guess and I guessed wrong.
I said before that I would come back to the Java code that generates the JSON. It uses two classes that have been used in Domino Access Services,
com.ibm.commons.util.io.json.JsonJavaObject. First let me show the code for the x axis labels.
This code is very straightforward. The JsonJavaArray acts like any Java List, so we just add elements to it. To output as JSON, we just call the
toString() method. Using this instead of manually generating JSON for a list is an absolute no-brainer!
The code for the chart data is a bit more complicated, but not significantly so. Note, it doesn’t use ODA so I had to remember what to recycle and to ensure I didn’t create an infinite loop. I always use ODA now and I would strongly recommend anyone else to do so as well. Here is the code.
We get the data as we nornally would – I won’t cover that. But we create a JsonJavaObject at line 6 to hold our map of series. But notice we create an ArrayList for the series data itself. We don’t create a JsonJavaArray – we don’t need to. That’s because you can put Java Maps and Java Lists into a JsonJavaObject (or indeed a JsonJavaArray) and the
toString() method will automatically convert them out. You just need to use JsonJavaObject or JsonJavaArray at the top level. Here we need a series label, so we use a JsonJavaObject (which corresponds to a Java Map), passing the series label as the key and the List of y-axis points as the value. Then we call the
toString() method at the end. Again, this is much easier than manually constructing JSON data.
The only caveat is to be wary of dates. The in-built conversion in Domino 9.0.1 doesn’t include timezones properly, but if that’s not a problem, it’s fine. The alternative is to convert dates to the correct ISO format before you add them to your JSON.
I think this is a massive improvement over the original code I used, which is why I’ve took the time to update the series. The sample database is attached below.