Template:GraphHeader/GraphCreator.js

var loaded = 0;

function onLoadCallback { loaded++; if (loaded==2) { loadGraphs; } }

google.load('visualization', '1', {}); google.setOnLoadCallback(onLoadCallback);

dojo.require("dojox.charting.Chart2D"); dojo.require("dojox.charting.widget.Legend"); dojo.addOnLoad(onLoadCallback);

function loadGraphs { var graphs = dojo.query('.graph'); for(var g=0; g<graphs.length; g++) { loadGraph(graphs[g]); } }

function loadGraph(graph) { var links = dojo.query('a',graph); if (links.length!=1) return; // TODO: Nicer error handling? dojo.xhrGet( {   url: links[0].href.replace(/\#.*/,),    content: {action: 'raw', templates: 'expand'},    preventCache: true,    handleAs: "json",    load: function(responseObject, ioArgs) {      createGraph(graph, responseObject);    },    error: function(responseObject, ioArgs) {      graph.innerHTML = ;      graph.appendChild(document.createTextNode('Error loading '));      graph.appendChild(links[0]);      graph.appendChild(document.createTextNode('!'));      graph.appendChild(document.createElement('br'));      graph.appendChild(document.createTextNode(responseObject.message));    }  }); }

var onDataSourceFetched = {}; var cachedDataSource = {}; var tableId = 0;

function createGraph(graph, desc) { // Some layout stuff graph.innerHTML = '';

// Create div's for graph var chartDiv = document.createElement('div'); graph.appendChild(chartDiv); // Has to be appended here so we can determine width/height later on. var autoWidth = graph.style.width ===undefined || graph.style.width ===null || graph.style.width ==0 || graph.style.width =='' || graph.style.width =='auto'; var autoHeight = graph.style.height===undefined || graph.style.height===null || graph.style.height==0 || graph.style.height=='' || graph.style.height=='auto'; if (autoWidth && autoHeight) { chartDiv.style.width = desc.width; chartDiv.style.height = desc.height; } else if (autoWidth) { chartDiv.style.width = desc.width; chartDiv.style.height = desc.height; var graphSize = dojo.contentBox(graph); var chartSize = dojo.contentBox(chartDiv); chartDiv.style.width = (graphSize.h*chartSize.w/chartSize.h) + 'px' chartDiv.style.height = graph.style.height; } else if (autoHeight) { chartDiv.style.width = desc.width; chartDiv.style.height = desc.height; var graphSize = dojo.contentBox(graph); var chartSize = dojo.contentBox(chartDiv); chartDiv.style.width = graph.style.width; chartDiv.style.height = (graphSize.w*chartSize.h/chartSize.w) + 'px' } else { chartDiv.style.width = graph.style.width; chartDiv.style.height = graph.style.height; } graph.style.width = chartDiv.style.width; graph.style.height = 'auto'; // The legend may take extra space. chartDiv.style.textAlign = 'left';

var legendCenter = document.createElement('center'); graph.appendChild(legendCenter); var legendDiv = document.createElement('div'); legendCenter.appendChild(legendDiv);

// Create chart and legend var chart = new dojox.charting.Chart2D(chartDiv); for(var a in desc.axes) { chart.addAxis(a, desc.axes[a]); } for(var p in desc.plots) { chart.addPlot(p, desc.plots[p]); } var legend = new dojox.charting.widget.Legend({chart: chart}, legendDiv);

if (desc.datasource!=undefined) { graph.refresh = function { // Query spreadsheet (if necessary) and let result be drawn if (!cachedDataSource[desc.datasource] && !onDataSourceFetched[desc.datasource]) { onDataSourceFetched[desc.datasource] = [function(response) { cachedDataSource[desc.datasource]=response; drawDataGraph(desc,chart,legend,response); }];       var query = new google.visualization.Query(desc.datasource); query.send(function(response){         for(var i=0; i<onDataSourceFetched[desc.datasource].length; i++) {            onDataSourceFetched[desc.datasource][i](response);          }        }); } else if (!cachedDataSource[desc.datasource]) { onDataSourceFetched[desc.datasource].push(function(response) {         drawDataGraph(desc,chart,legend,response);        }); } else { drawDataGraph(desc,chart,legend,cachedDataSource[desc.datasource]); }   };  } else if (desc.datatable!=undefined) { var urlComponents = desc.datatable.split('#',1); var iframeId = "graphDataTableIframe-" + urlComponents[0]; graph.refresh = function { var doc = window.frames[iframeId]; if (doc==undefined) { if (onDataSourceFetched[urlComponents[0]]) { onDataSourceFetched[urlComponents[0]].push(function(fetchedDoc) {           drawTableGraph(desc,chart,legend,fetchedDoc,urlComponents[1]);          }); } else { onDataSourceFetched[urlComponents[0]] = [function(fetchedDoc) {

drawTableGraph(desc,chart,legend,fetchedDoc,urlComponents[1]); }];         dojo.xhrGet( {            url: urlComponents[0],            content: {action: 'render'},            preventCache: true,            handleAs: "text",            load: function(responseObject, ioArgs) {              var iframeId = "graphDataTableIframe-" + urlComponents[0];              var iframe = document.createElement('iframe');              iframe.id = iframeId;              iframe.name = iframeId;              iframe.style.display = 'none';              graph.appendChild(iframe);              var doc = window.frames[iframeId].document;              doc.write(responseObject);              for(var i=0; i<onDataSourceFetched[urlComponents[0]].length; i++) {                onDataSourceFetched[urlComponents[0]][i](doc);              }            },            error: function(responseObject, ioArgs) {              graph.innerHTML = '';              graph.appendChild(document.createTextNode('Error loading data table ' + desc.datatable + '!')); graph.appendChild(document.createElement('br')); graph.appendChild(document.createTextNode(responseObject.message)); }         });        }      } else {        drawTableGraph(desc,chart,legend,doc.document,urlComponents[1]);      }    };  } else if (desc.script!=undefined) {    graph.refresh = function {      try {        drawGraph(desc,chart,legend,eval(desc.script));      } catch(err) {        alert('Error drawing graph:\n'+err.message);      }    };  }  if (graph.refresh!=undefined) graph.refresh; }

function drawDataGraph(desc,chart,legend,response) { if (response.isError) { alert('Error in query: ' + response.getMessage + ' ' + response.getDetailedMessage); return; }

var data = response.getDataTable; var series = dojoSeriesFromDataTable(data,desc.series); drawGraph(desc,chart,legend,series); }

function drawTableGraph(desc,chart,legend,doc,id) { if (id==null) { var table = doc.getElementsByTagName('table')[0]; } else { var table = doc.getElementById(id); }

// Read table var cols = table.rows[0].cells; var headers = [], columns = []; for(var c=0; c<cols.length; c++) { headers.push(cols[c].innerHTML.replace(/^\s*/,).replace(/\s*$/,)); columns.push([]); } for(var r=1; r<table.rows.length; r++) { var cols = table.rows[r].cells; for(var c=0; c<cols.length; c++) { var v = cols[c].innerHTML.replace(/^\s*/,).replace(/\s*$/,); if (isFinite(v)) v = Number(v); columns[c].push(v); }   for(var c=cols.length; c<headers.length; c++) { columns[c].push(undefined); } }

// Draw graph var dataTable = { getNumberOfRows: function { return table.rows.length-1; }, getNumberOfColumns: function { return headers.length; }, getColumnLabel: function(c) { return headers[c]; }, getValue: function(r,c) { return columns[c][r]; } }; var series = dojoSeriesFromDataTable(dataTable,desc.series); drawGraph(desc,chart,legend,series); }

function drawGraph(desc,chart,legend,series) { if (chart.series.length==0) { for(var i=0; i<series.length; i++) { chart.addSeries(series[i].title, series[i].data, series[i].args); } } else { for(var i=0; i<series.length; i++) { chart.updateSeries(series[i].title, series[i].data, series[i].args); } }  chart.render; for(var a in desc.axes) { // This works around axis titles not being supported!!! if (desc.axes[a].title!=undefined) setAxisTitle(chart, a, desc.axes[a].title, 10); } legend.refresh; }

function dojoSeriesFromDataTable(dataTable,series) { var dojoSeriesArray = []; var numrows = dataTable.getNumberOfRows; for(var s=0; s<series.length; s++) { if (series[s]==null) continue; var xc = series[s].x, xf = series[s].xf, yc = series[s].y, yf = series[s].yf, textc = series[s].text, colorc = series[s].color, fontcolorc = series[s].fontColor; var dojoSeries = []; if (xc==undefined && xf==undefined && textc==undefined && colorc==undefined && fontcolorc==undefined) { // Just an ordinary list of values for(var r=0; r=numrows) return undefined; return dataTable.getValue(r+ro,c); }     for(r=0; r<numrows; r++) { if (yf!=undefined) { var v = {y: eval(yf)}; if (!isFinite(v.y)) continue; } else { var v = {y: dataTable.getValue(r,yc)}; }       if (xf!=undefined) { v['x'] = eval(xf); if (!isFinite(v.x)) continue; } else if (xc!=undefined) { v['x'] = dataTable.getValue(r,xc); }        if (textc!=undefined) v['text'] = dataTable.getValue(r,textc); if (colorc!=undefined) v['color'] = dataTable.getValue(r,colorc); if (fontcolorc!=undefined) v['fontColor'] = dataTable.getValue(r,fontcolorc); dojoSeries.push(v); }   }    dojoSeriesArray.push({title: series[s].title===undefined && yc!=undefined ?                                   dataTable.getColumnLabel(yc) : series[s].title,                          data: dojoSeries,                          args: getSeriesArgs(series[s])}); } return dojoSeriesArray; }

function getSeriesArgs(series) { var args = {}; for(var p in series) { if (p=='title' || p=='x' || p=='y' || p=='text' || p=='color' || p=='fontColor') continue; args[p] = series[p]; } return args; }

// Code from http://trac.dojotoolkit.org/ticket/7746 var setAxisTitle=function(chart, axisname, title, fontsizept) { var axis = chart.axes[axisname]; var dim = chart.dim; var offsets=chart.offsets; var ta = chart.theme.axis; var taFont = "font" in axis.opt ? axis.opt.font : ta.font; var x;   var y;    var label; var rotate=0; if(axis.vertical && axis.opt.leftBottom) { rotate=270; label = title; y=dim.height/2 - offsets.b/2 + offsets.t/2; x=0+2*fontsizept; } else if(axis.vertical && !axis.leftBottom) { rotate=90; label = title; y=dim.height/2 - offsets.b/2 + offsets.t/2; x=dim.width-2*fontsizept; } else { label = title; x=dim.width/2 + offsets.l/2 - offsets.r/2; y=dim.height-fontsizept/2; }   var m = dojox.gfx.matrix; var elem = axis.group.createText({x:x, y:y, text:label, align: "middle"}); elem.setFont({family:taFont.family, size: fontsizept+"pt", weight: "bold"}); elem.setFill('grey'); elem.setTransform(m.rotategAt(rotate, x,y)); }