Template:GraphHeader/GraphCreator.js
From 2009.igem.org
m |
|||
(103 intermediate revisions not shown) | |||
Line 49: | Line 49: | ||
<!-- Create graphs --> | <!-- Create graphs --> | ||
+ | |||
+ | var onDataSourceFetched = {}; | ||
+ | var cachedDataSource = {}; | ||
+ | var tableId = 0; | ||
function createGraph(graph, desc) { | function createGraph(graph, desc) { | ||
Line 101: | Line 105: | ||
if (desc.datasource!=undefined) { | if (desc.datasource!=undefined) { | ||
graph.refresh = function() { | graph.refresh = function() { | ||
- | // Query spreadsheet and let result be drawn | + | // Query spreadsheet (if necessary) and let result be drawn |
- | var query = new google.visualization.Query(desc.datasource); | + | 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) { | } else if (desc.script!=undefined) { | ||
graph.refresh = function() { | graph.refresh = function() { | ||
- | + | try { | |
- | + | drawGraph(desc,chart,legend,eval(desc.script)); | |
+ | } catch(err) { | ||
+ | alert('Error drawing graph:\n'+err.message); | ||
+ | } | ||
}; | }; | ||
} | } | ||
Line 118: | Line 186: | ||
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage()); | alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage()); | ||
return; | return; | ||
- | } | + | } |
+ | |||
var data = response.getDataTable(); | var data = response.getDataTable(); | ||
var series = dojoSeriesFromDataTable(data,desc.series); | 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); | drawGraph(desc,chart,legend,series); | ||
} | } | ||
function drawGraph(desc,chart,legend,series) { | function drawGraph(desc,chart,legend,series) { | ||
- | |||
if (chart.series.length==0) { | if (chart.series.length==0) { | ||
for(var i=0; i<series.length; i++) { | for(var i=0; i<series.length; i++) { | ||
Line 144: | Line 249: | ||
function dojoSeriesFromDataTable(dataTable,series) { | function dojoSeriesFromDataTable(dataTable,series) { | ||
var dojoSeriesArray = []; | var dojoSeriesArray = []; | ||
+ | var numrows = dataTable.getNumberOfRows(); | ||
for(var s=0; s<series.length; s++) { | for(var s=0; s<series.length; s++) { | ||
- | var xc = series[s].x, yc = series[s].y, textc = series[s].text, colorc = series[s].color, fontcolorc = series[s].fontColor; | + | 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 = []; | var dojoSeries = []; | ||
- | if (xc==undefined && textc==undefined && colorc==undefined && fontcolorc==undefined) { | + | if (xc==undefined && xf==undefined && textc==undefined && colorc==undefined && fontcolorc==undefined) { |
// Just an ordinary list of values | // Just an ordinary list of values | ||
- | for(var r=0; r< | + | for(var r=0; r<numrows; r++) { |
dojoSeries.push(dataTable.getValue(r,yc)); | dojoSeries.push(dataTable.getValue(r,yc)); | ||
} | } | ||
} else { | } else { | ||
// An object | // An object | ||
- | + | var r; | |
- | var v = {y: dataTable.getValue(r,yc)}; | + | var cell = function(c,ro) { |
- | if (xc!=undefined) v['x'] = dataTable.getValue(r,xc); | + | if (r+ro<0 || r+ro>=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 (textc!=undefined) v['text'] = dataTable.getValue(r,textc); | ||
if (colorc!=undefined) v['color'] = dataTable.getValue(r,colorc); | if (colorc!=undefined) v['color'] = dataTable.getValue(r,colorc); | ||
Line 163: | Line 285: | ||
} | } | ||
} | } | ||
- | dojoSeriesArray.push({title: series[s].title===undefined ? | + | dojoSeriesArray.push({title: series[s].title===undefined && yc!=undefined ? |
dataTable.getColumnLabel(yc) : series[s].title, | dataTable.getColumnLabel(yc) : series[s].title, | ||
data: dojoSeries, | data: dojoSeries, | ||
Line 191: | Line 313: | ||
var label; | var label; | ||
var rotate=0; | var rotate=0; | ||
- | if(axis.vertical) { | + | if(axis.vertical && axis.opt.leftBottom) { |
- | rotate=270 | + | rotate=270; |
label = title; | label = title; | ||
- | y=dim.height/2 - offsets.b/2; | + | y=dim.height/2 - offsets.b/2 + offsets.t/2; |
x=0+2*fontsizept; | 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 { | } else { | ||
label = title; | label = title; | ||
- | x=dim.width/2 + offsets.l/2; | + | x=dim.width/2 + offsets.l/2 - offsets.r/2; |
y=dim.height-fontsizept/2; | y=dim.height-fontsizept/2; | ||
} | } |
Latest revision as of 14:58, 4 August 2009
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; r++) { dojoSeries.push(dataTable.getValue(r,yc)); } } else { // An object var r; var cell = function(c,ro) { if (r+ro<0 || r+ro>=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));
}