Search

Mobile tag

About Me

I am the "IBM Collaboration & Productivity Advisor" for IBM Asia Pacific. I'm based in Singapore.
Reach out to me via:
Follow notessensei on Twitter
(posts)
Skype
Sametime
IBM
Facebook
LinkedIn
XING
Amazon Store
Amazon Kindle

Twitter

Domino Upgrade

VersionSupport end
5.0
6.0
6.5
7.0
8.0
8.5
Upgrade to 9.x now!
(see the full Lotus lifcyle) To make your upgrade a success use the Upgrade Cheat Sheet.
Contemplating to replace Notes? You have to read this! (also available on Slideshare)

Languages

Other languages on request.

Visitors

Useful Tools

Get Firefox
Use OpenDNS
The support for Windows XP has come to an end . Time to consider an alternative to move on.

« Notes addressbook sync with IBM SmartCloud | Main| Driving Embedded Experiences Adoption »

Aggregating view data for use in d3js graphics

QuickImage 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 entry
		try {
			ve.recycle();
		} catch (e) {
			// We don't care
		}
		ve = nextVe;
	}
	result += " ]";
	// Cleanup all objects
	try {
		nav.recyle();
		v.recycle();
	} catch (e) {
		// We don't care
	}
	return result;
}


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

Comments

Gravatar Image1 - does not work very well in my IE browser (as more charting solutions do) :-?

Gravatar Image2 - @Patrick: you pick your own level of suffering.

Post A Comment

Please note: Comments without a valid and working eMail address will be removed. This is my site, so I decide what stays here and what goes.

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::rolleyes:;-)

Disclaimer

This site is in no way affiliated, endorsed, sanctioned, supported, nor enlightened by Lotus Software nor IBM Corporation. I may be an employee, but the opinions, theories, facts, etc. presented here are my own and are in now way given in any official capacity. In short, these are my words and this is my site, not IBM's - and don't even begin to think otherwise. (Disclaimer shamelessly plugged from Rocky Oliver)
© 2003 - 2014 Stephan H. Wissel - some rights reserved as listed here: Creative Commons License
Unless otherwise labeled by its originating author, the content found on this site is made available under the terms of an Attribution/NonCommercial/ShareAlike Creative Commons License, with the exception that no rights are granted -- since they are not mine to grant -- in any logo, graphic design, trademarks or trade names of any type. Code samples and code downloads on this site are, unless otherwise labeled, made available under an Apache 2.0 license. Other license models are available on written request and written confirmation.