I am delighted to present the first in my series of articles highlighting some extremely cool jQuery plugins and how to integrate them within XPages. During the course of the articles I will always demonstrate at least at some level, basic integration with XPages. In many cases I will not be able to cover all the examples of everything possible with each plugin, but I hope to give at least a good teaser to the possibilities and show the myriad of possibilities.
I have to also say a HUGE thank you to David Leedy (www.notesin9.com) who is hosting my demonstration for this and the rest of this series when I get to them.
So without further ad0 – welcome to jQuery in XPages #1 🙂
Highcharts
For full disclosure, Highcharts is not free for commercial use. “Do you want to use Highcharts for a personal or non-profit project? Then you can use Highchcarts for free under the Creative Commons Attribution-NonCommercial 3.0 License.”.
But part of the reason I chose it as the #1 is because it really rocks well with an XPage environment. It has direct business applicability, unlike many other jQuery plugins which are pretty, but hardly “corporate”. The format and structure of the chart instantiation also jibes well with XPages and I was able to create a custom control which can be applied to any formatted viewPanel or dataTable.
In the example below you can see a simple form with a viewPanel. Adding a new value to the form refreshes the page and displays the value entered. The exact same functionality would be seen if I had a basic data table looking at the same view of data.
The Example
Initial XPages form
Submitting the form gives us our new value
XPage with new Apples value added
The XPage is laid out very simply and our View control is called viewPanel1
View Panel on the XPage
We add the drawHighchart Custom Control to the XPage
Adding the drawHighchart custom control to the page
And let’s refresh our webpage – et voila – a chart
A simple Highchart added to our XPage
Changing the chart type is as simple as selecting a new theme and/or a new chart type
Changing the Highchart style
For more information on how this works check out the next article
This how does it work article is a follow on from the original jQuery in XPages #1 – Highcharts and goes into depth as to how the functionality was created and how you can modify it yourself.
Be fore-warned this is quite dry and not for the faint of heart, but hopefully will provide a good insight and understanding.
How does this work?
This Highchart demonstration is made up of the following design elements
To avoid making this article long(er than it already is) I am going to focus just on the drawHighchart custom control and the Highchart theme. The sample database is available for download and you can pick it to pieces at your leisure.
Highcharts Theme
The theme works by:
Extending the oneuiv2 theme (as a demonstration that it does not conflict)
Imports the jQuery library we need (jquery-1.7.1.min.js)
Imports the highchart.js library. Because this is a pure JavaScript library there are no associated image files (amazing really)
This custom control is intended to be self contained for the sake of this demonstration and can be dropped onto any XPage in your application. The example has a dropdown for theme and graph type choices. These parameters are fed into the Highchart.js file based on the selected field values, but in your application where you only want a specific chart type they could be hard-coded. Later in the article you will see where the parameters are fed into the highchart.js library and how you can configure them yourself.
The code for the custom control breaks down like this:
Both the chart theme and chart type fields have a full refresh set on the “onchange” event. This reloads the page and data when a change is made. Again for the sake of a demonstration this is ok, but in your real-world application you would only provide one chart type and remove these drop downs.
NOTE: because the code is instantiated in the $(document).ready(function() that means a partial refresh will NOT work
Full update onchange event
The onClientLoad event of the custom control contains all the JavaScript which makes this work
onClientLoad event of the custom control
The JavaScript is shown below and performs two basic tasks
It determines the selected theme and calls a function in the jsFormFruit library which sets the theme
e.g. callGray()
It instantiates the Highchart and passes the chart type as a value derived from the XPage
“#{id:viewPanel1}” is the idTag for the viewPanel <—change this if your view panel is called something different
“#{javascript: getComponent(‘chartType’).getValue()}” is the value chosen for chart type
$(document).ready(function() {
var sTheme=x$('#{id:theme1}').val() //get the value from the theme dropdown on the webpage
switch(sTheme)
{
case 'gray':
callGray()
break;
case 'darkBlue':
callDarkBlue()
break;
case 'grid':
callGrid()
break;
default:
""
}
htmlTableGraph("#{id:viewPanel1}", "#{javascript: getComponent('chartType').getValue()}")
})
jsFormFruit JavascriptLibrary
The callGray(), callDarkBlue and callGrid() functions are all very similar and while it might look like a lot, it is actually very readable and you can see how the color scheme is created. NOTE : this is all JavaScript and can therefore be changed to suit your own needs – no images!! This is a snippet and the whole code is available in the database in the script library
The htmlTableGraph is my modified version of the example given at the Highcharts website. I had to modify it because the viewPanel table created by XPages is not the same as the simple example given. Here’s the breakdown……
function htmlTableGraph(idTag, sType){
/**
* Visualize an HTML table using Highcharts. The top (horizontal) header
* is used for series names, and the left (vertical) header is used
* for category names. This function is based on jQuery.
* @param {Object} table The reference to the HTML table to visualize
* @param {Object} options Highcharts options
*/
Highcharts.visualize = function(table, options) {
// the categories
options.xAxis.categories = [];
$('tbody tr td:first-child', table).each( function(i) {
options.xAxis.categories.push(this.lastChild.innerHTML);
});
// the data series
options.series = [];
$('tr', table).each( function(i) {
var tr = this;
$('th, td', tr).each( function(j) {
if (j > 0) { // skip first column
if (i == 0) { // get the name and init the series
options.series[j - 1] = {
name: this.lastChild.innerHTML,
data: []
};
} else { // add values
options.series[j - 1].data.push(parseFloat(this.lastChild.innerHTML));
}
}
});
});
var chart = new Highcharts.Chart(options);
}
//idTag is the viewPanel1 id passed into the function
var table = document.getElementById(idTag),
options = {
chart: {
renderTo: 'container',
type: sType
},
title: {
text: 'Data extracted from a HTML table in the page'
},
xAxis: {
},
yAxis: {
title: {
text: 'Units'
}
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.y +' '+ this.x.toLowerCase();
}
}
};
Highcharts.visualize(table, options);
}
The HTML created by the XPages server
The HTML generated by the XPage to display the viewPanel looks like this where every table row TR has three table cells – inside each TD cell there is a span and inside that a value
options.xAxis.categories = []; //sets up the array into which we will add the xAxis (the fruit)
We will work right to left to read what is going on
$('tbody tr td:first-child', table)
within the table (viewPanel1) element select everything which matches
the first td (td:first-child)
inside the tr
inside the tdbody
.each( function(i) {
because we can chain jQuery functions together we are cycling through each of the selected elements and for each element we are going to execute the function
.lastChild (the last DOM element within the TD) – this bypasses the span within the TD
.innerHTML – the HTML within the element
options.xAxis.categories.push (add (push) the value into the options object on the xAxis.categories value)
Simply put this 4 lines of code cycles through the table, extracts the fruit values and adds them to an array for display on the xAxis (Apples, Oranges etc)
Parsing the table values
options.series = [];
$('tr', table).each( function(i) {
var tr = this;
$('th, td', tr).each( function(j) {
if (j > 0) { // skip first column
if (i == 0) { // get the name and init the series
options.series[j - 1] = {
name: this.lastChild.innerHTML,
data: []
};
} else { // add values
options.series[j - 1].data.push(parseFloat(this.lastChild.innerHTML));
}
}
});
});
options.series = [];
Creates the array for drawing the chart values
$('tr', table).each( function(i) {
});
For each TR within the table (viewPanel) provided cycle through each row
i is the counter here as to which row we are on going down the table
var tr = this;
$('th, td', tr).each( function(j) {
});
for every th or td in each tr
j is the counter here as we are going across the row
if (j > 0) { // skip first column
if (i == 0) { // get the name and init the series
options.series[j - 1] = {
name: this.lastChild.innerHTML,
data: []
};
} else { // add values
options.series[j - 1].data.push(parseFloat(this.lastChild.innerHTML));
}
}
We ignore the first column (xAxis)
if j > 0 (skiping the first column which is the xAxis (apples) values)
if i = 0 (we are on the first row (the top one) and therefore we have the name Jane and John
add this (tr).lastChild.innerHTML (the HTML within the span) to the NAME value within the options.series array (NO DATA)
else (we are not on the top row) add the innerHTML value (converted to a number with parseFloat) to the options.series array
This section creates a string which looks like this – that is then parsed by the highchart.js