wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Aggregating view data for use in d3js graphics


Dashboards are all the rage, so it is natural that your XPages application need a dash of a dashboard. A view makes an excellent source for dashboard data and the ability to categorize views handles the heavy lifting of aggregating the values you want to use e.g. in a bar or pie chart. I've been fallen in love with d3js since she is the ultimate visualization (if in doubt, read the classics ).
D3Js is a harsh mistress of exceptional beauty, so you might want to check out some of her offsprings like RickShaw, NVD3 or xCharts. Indulge in myriads of tutorials and reviews (check part 2 too) and the over 1000 examples.
With just a few lines of JavaScript any categorized view can be used as source for d3js. The script can read a categorized view with one to three categories. If you have one it reads the view, for two you get hierarchical data or provide a key, so you only retrieve the selected category etc.Since I use a viewNavigator performance is quite good:
function getCategoryData(viewName, dataColumn, getChildren, key) {var v = database.getView(viewName);var nav;if (key) {
  nav = v.createViewNavFromCategory(key);} else {
    nav= v.createViewNav();}var ve = nav.getFirst();var isFirst = true;var result = "[";while (ve) {if (!ve.isTotal()) {var curData = ve.getColumnValues();if (!isFirst) {
    result += ",";}
   result += "{label : \"";if (key) {
    result += curData[1 ];} else {
    result += curData[0 ]; 
   }   
   result += "\", value : ";
   result += curData[dataColumn ];/*for 2 level categories we fetch additional data*/if (getChildren) {var childve = nav.getChild();var firstChild = true;
    result += ", children : [";while (childve) {var childData = childve.getColumnValues();if (!firstChild) {
      result += ",";}
     result += "{label : \"";
     result += childData[1 ];
     result += "\", value : ";
     result += childData[dataColumn ];
     result += "}";   
     firstChild = false;
     childve = nav.getNextSibling(childve);}
    result += " ]"}
   result += "}";   
   isFirst = false;}  
  ve = nav.getNextSibling(ve);}
 result += " ]";return result;}
A very typical use are year-to-date graphs, that accummulate the values from category to category. Here I use this:
function getCumulativeCategoryData(viewName, key, dataColumn, fetchChildren) {var v = database.getView(viewName);var nav = v.createViewNavFromCategory(key);var ve = nav.getFirst();var nextVe;var isFirst = true;var result = "[";var runningTotal = 0;while (ve) {// Prefetch the next entry
  nextVe = nav.getNextSibling(ve);if (!ve.isTotal()) {var curData = ve.getColumnValues();if (!isFirst) {
    result += ",";}
   result += "{label : \"";
   result += curData[1 ];
   result += "\", value : ";
   runningTotal += Number(curData[dataColumn ]);
   result += runningTotal;/*for 2 level categories we fetch additional data*/if (fetchChildren) {var runningSubTotal = 0;var childve = nav.getChild();var nextChildVe;var firstChild = true;
    result += ", children : [";while (childve) {
     nextChildVe = nav.getNextSibling(childve);var childData = childve.getColumnValues();if (!firstChild) {
      result += ",";}
     result += "{label : \"";
     result += childData[2 ];
     result += "\", value : ";
     runningSubTotal += Number(childData[dataColumn ]);
     result += runningSubTotal;
     result += "}";   
     firstChild = false;try {
      childve.recycle();} catch (e) {// No action}
     childve = nextChildVe;    
    result += " ]"} 
   }
   result += "}";   
   isFirst = false;}// Cleanup view entrytry {
   ve.recycle();} catch (e) {// We don't care}
  ve = nextVe;}
 result += " ]";// Cleanup all objectstry {
  nav.recyle();
  v.recycle();} catch (e) {// We don't care}return result;}


As usual: YMMV
P.S.: for end-users, check out Tableau

Posted by on 24 September 2013 | Comments (2) | categories: XPages

Comments

  1. posted by Patrick Kwinten on Thursday 24 October 2013 AD:
    does not work very well in my IE browser (as more charting solutions do) :-?
  2. posted by Stephan H. Wissel on Thursday 24 October 2013 AD:
    @Patrick: you pick your own level of suffering.