/*
* Google Visualization API Wrapper -- v1.0
* Published : 25/05/2009
* http://www.smallmeans.com/apps/googleVizAPI
* Copyright (c) 2009 smallmeans.com
* Dual licensed under MIT and GPL.
*/
if(typeof googleVizAPI == 'undefined')
googleVizAPI = {
};
googleVizAPI = {
timeValueIndex:1,
bubbles:[],
config:{
width :700, //size in pixels
height:400, //uhmm.. me, too!
showBubbles:true,
showTrails:false,
playDuration:2,
stateVersion:3,
xLambda:0, // 1 for linear scale
yLambda:0, // 0 for LOG scale
defaults:{
}
},
$: function(id) {
return document.getElementById(id);
},
$E: function(tag) {
return document.getElementsByTagName(tag);
},
// once the module is loaded, this function is called and we're good to go
onload: function() {
(function(){
this.draw();
}
).call(googleVizAPI);
},
draw: function(chartElement) {
var data=this.data;
var items=data.rows.length;
var table = new google.visualization.DataTable(),c=0;
var chartElement=chartElement||this.$(this.config.containerID);
if(!chartElement){
chartElement=document.getElementsByTagName("div")[0];
}
table.addRows(items);
for(column in data.columns){
try{
table.addColumn(data.columns[column].toString(),column);
if(data.columns[column].equals('date')){
this.isNativeDate=true;
}
}
catch(aarrrrghh){
this.appendText(chartElement,'could not add column: '+aarrrrghh);
}
}
isFiltered=typeof this.config.filterBubbles === "object" && this.config.filterBubbles.fieldNr>=0;
hasThreshold=typeof this.config.filterData === "object" && this.config.filterData.fieldNr>=0;
var _native=['function','object'];
//psst.. 'native' is a keyword in Google Chrome, now I/U know..
for(row in data.rows){
for(column in data.rows[row]){
if(_native.contains(typeof data.rows[row][column])){
continue;
}
if(c==this.timeValueIndex && this.isNativeDate){
value=this.parseDate(data.rows[row][column]);
}
else{
value=data.rows[row][column];
}
if(c==0){
name=value;
}
/*if(hasThreshold&&this.config.filterData.fieldNr==c+1){
if(!eval(value+this.config.filterData.expr)){
continue;
}
}*/
if(this.config.charttype.equals('MotionChart')){
if(isFiltered){
if(this.config.filterBubbles.fieldNr==c+1 && eval(value+this.config.filterBubbles.expr)){
this.bubbles.push('{"key":{"dim0":"'+name+'"}}');
}
}else{
this.bubbles.push('{"key":{"dim0":"'+name+'"}}');
}
}
try{
table.setValue(row*1, c++, value);
}
catch(ohhhScheisse){
this.appendText(chartElement,'Could not set value at row '+row+' --- '+ohhhScheisse);
this.debug('choked on row: '+row+", field:"+c+", containing ->"+value);
return;
}
}
c=0;
}
this.debug('..throwing '+items+' paintballs at the canvas..');
this.chart = this.getConstructor(chartElement);
this.table=table;
this.render();
},
setVal: function(key,val) {
this.config[key]=val;
this.render();
},
render: function() {
var vars=[];
var icons=[];
delete this.config.state;
for(i in this.config){
vars.push('"'+i+'":'+'"'+this.config[i]+'"');
}
if(this.config.charttype.equals('MotionChart') &&
this.config.showBubbles){
icons=this.bubbles;
vars.push('"iconKeySettings":['+icons+']');
this.config.state='{'+vars+'}';
}
this.chart.draw(this.table, this.config);
google.visualization.events.addListener(this.chart, 'select', this.selectHandler);
},
selectHandler: function(s,t,u) {
},
parseDate: function(s) {
m=s.split("/");
with(d=new Date()){
setDate(m[0]);
setMonth(m[1]-1);
setYear(m[2]);
}
return d;
},
getConstructor: function(container) {
return eval('new google.visualization.'+googleVizAPI.config.charttype + '(container)');
},
parseConfig: function(type) {
var configs=[];
for(i in this.config){
configs.push(i+'='+this.config[i])
}
return configs.join('&');
},
loadChart: function() {
if(!this.isModuleLoaded()){
google.load("visualization", "1", {packages:[googleVizAPI.config.charttype,"table"], "callback" : googleVizAPI.onload});
}
else{
this.onload();
}
},
appendText: function(parent,string) {
(e=document.createElement("p")).appendChild(document.createTextNode(string));
e.setAttribute("style","color:red;background-color:#FFF6BF;border:1px solid #FFD324;padding:6px;margin:4px");
e.id='googleChartInfo';
parent.appendChild(e);
},
require: function(src) {
var script = document.createElement("script");
script.src = src;
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
},
isModuleLoaded: function() {
return (window.google && window.google.visualization && eval('window.google.visualization.'+googleVizAPI.config.charttype));
},
reset: function() {
if(window.google){
delete window.google;
}
},
debug : function(s, isError) {
if(typeof(console) != 'undefined'){
isError? console.error(s):console.log(s);
}
else{//no Firebug?.. gahh!
}
},
setup: function(data,conf) {
this.data=arguments[0][0]||data;
options=arguments[0][1]||conf;
if(options && typeof options === "object"){
if(options.overwrite){
this.config=options;
}else{
for(i in options){
this.config[i]=options[i];
}
}
}
switch(options.charttype){
case 'timeline':
this.timeValueIndex=0;
this.config.charttype='AnnotatedTimeLine';
break;
case 'area':
this.config.charttype='AreaChart';
break;
case 'column':
this.config.charttype='ColumnChart';
break;
case 'line':
this.config.charttype='LineChart';
break;
case 'bar':
this.config.charttype='BarChart';
break;
case 'motion':
default:
this.config.charttype='MotionChart';
break;
}
// window.onload=function(){
// this.appendText(this.$(this.config.containerID),"Loading..");
// }.bind(this);
if(this.isModuleLoaded()){
this.loadChart();
}
else{
this.require('http://www.google.com/jsapi?&callback=googleVizAPI.loadChart');
}
}
}
String.prototype.equals = function (s) {
return String(this) === s;
};
Function.prototype.bind = function(object) {
var newbind = this;
return function() {
return newbind.apply(object);
};
};
Array.prototype.contains = function ( obj ) {
var len = this.length;
for ( var x = 0 ; x <= len ; x++ ) {
if ( this[x] == obj )
return true;
}
return false;
}
googleVizAPI.init = function() {
with(googleVizAPI){
setup(arguments);
}
};