Chart.js can't push dataset to charts made dynamically - javascript

I am currently making a web application where users can add their own chart panels, and can then drag certain database tables into said panel to make it show in the chart. My problem is that I can't push datasets into the dynamically created charts, because the variable which holds the chart are not written directly in the document, so the function I made to push those datasets can't push to the variables like it would normally.
Here's the function to make new panels and charts:
function addnewchart(x) {
eval("ctx" + x + "= document.getElementById('linechart" + x + "').getContext('2d');");
eval("var lineChart" + x + " = new Chart(ctx" + x + ", {type: 'line',data: {labels: '',datasets: ''},options: {legend: {display: false},scales: {xAxes: [{gridLines: {display: false},scaleLabel: {display: true,labelString: ''}}],yAxes: [{ticks: {beginAtZero: true},scaleLabel: {display: true,labelString: ''}}]}}});");
};
And this is the function to push datasets to those charts:
function addData(chart, Datalabel, Tabledata) {
datasintable.push(Tabledata + "S");
var curColor = randomColor();
var newDataset =
{
label: Datalabel,
fill: false,
backgroundColor: curColor,
borderColor: curColor,
data: Tabledata
}
console.log(chart,Datalabel,Tabledata, newDataset);
chart.data.labels.push(['test1', 'test2', 'test3', 'test4', 'test5']);
chart.data.datasets.push(newDataset);
chart.update();
}
How should I approach this problem?

Apparently, the way to fix this was instead of using the variable chart in addData(), use window[chartname + index] when manipulating dynamically created charts. I found this out by trying to point to the chart by using both eval() and window[]. Eval didn't work at all, but Window did the trick.
Example:
var number = 1;
window['linechart' + number];
This will call chart linechart1.

Related

How to change chart position in Google Sheets?

I currently have a script that takes data, formats it, and creates a chart below the data.
I know how to move the chart within the tab using setPosition, but can't figure out how to write the chart to a different tab (to create a 'dashboard' where you wouldn't have to see all of the source data). Any ideas on this?
I've tried changing what's in .setPosition, but that only moves the chart within the existing tab.
I've also had glitches with this where I've gotten the chart to move to the right of the data in some cases, but using the same code in a different sheet it doesn't write the chart at all.
Here's the code I'm working with:
var chartTitle = columnHeader;
if (typeof subtitle[columnHeader] != 'undefined') {
chartTitle = chartTitle + " - " + subtitle[columnHeader];
}
var chartBuilder = sheet.newChart()
.setChartType(Charts.ChartType.LINE)
.setOption('chartArea', {left:'10%',top:'15%',width:'80%',height:'70%'})
.setPosition(4 + output.length, 1, 0, 0)
.setOption('width', width)
.setOption('height', 500)
.setOption('title', chartTitle)
.setOption('legend', {position: 'top'});
var statFormat = {CPC: 'currency', CTR: 'percent', Impressions: 'decimal', Searches: 'decimal'};
if (statsInChart.length == 0) {
chartBuilder.setOption('vAxes', {
// Adds titles to the axis.
0: {title: columnHeader} });
} else if (statsInChart.length == 1) {
chartBuilder.setOption('vAxes', {
// Adds titles to both axes.
0: {title: columnHeader} ,
1: {title: statsInChart[0], format: statFormat[statsInChart[0]]}});
} else {
chartBuilder.setOption('vAxes', {
// Adds title to the first axis, blanks the others.
0: {title: columnHeader} ,
1: {format: statFormat[statsInChart[0]], textPosition: 'in'},
2: {format: statFormat[statsInChart[1]], textPosition: 'out'},
3: {textStyle: {color: 'white'}}
});
}
The code you provided does not cover when you actually build the chart, nor when you insert it into a sheet.
When you create the EmbeddedChartBuilder by calling the sheet.newChart() method, you have a sheet object that's associated with a particular sheet within the spreadsheet.
What you want to do is call the insertChart() method with a different sheet object, one that is associated with the sheet where you'd like the chart to appear.
Here's a small example:
function createChart() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('data');
var chartSheet = ss.getSheetByName('chart');
var dataRange = dataSheet.getDataRange();
var chart = chartSheet.newChart()
.addRange(dataRange)
.setPosition(1, 1, 0, 0)
.build();
chartSheet.insertChart(chart);
}
In my test spreadsheet, I have two sheets. One is named data and it contains a small table of data. The other is a blank sheet named chart.
When I execute the above function, a chart is placed in the chart sheet based on the data extracted from the data sheet.

Series for tooltip only in highcharts

I need to use several series in tooltip in a highchart chart. These series should be completely invisible except tooltip. I 've tried setting visible to false. However in this case, legends for that series are still visible though faded. If I state "ignoreHiddenSeries: true", hidden series are not there at all and I cannot use them at tooltip. Is there a way for this type of usage? Currently I am keeping those series in global javascript arrays outside the highchart's scope and using them in tooltip formatter. I prefer to keep those data in highchart as well.
By the way setting showInLegend: false, visible: false also makes the series unusable in tooltip.
Each invisible serie should have two params:
visible: false,
showInLegend: false,
You need to use the tooltip formatter and use loop over each serie / each point to print values.
tooltip: {
formatter: function() {
var series = this.series.chart.series,
x = this.x,
each = Highcharts.each,
txt = '<span style="font-size: 10px">' + this.key + '</span><br/>';
each(series, function(serie, i) {
each(serie.data, function(data, j){
if(data.x === x) {
txt += '<span style="color:' + data.color + '">\u25CF</span> ' + data.series.name + ': <b>' + data.y + '</b><br/>';
}
});
});
return txt;
}
},
Example: http://jsfiddle.net/697e8seo/

Bar chart looks bad before change data

Hi here I set the data to the bar chart:
setDatosBarra: function(data){ //
var self = this;
var horaEstim = 0;
var horaReal = 0;
var horaTotal = 0;
if(data[0].horas_estim != '-'){
horaEstim = data[0].horas_estim;
}
if(data[0].horas_real != '-'){
horaReal = data[0].horas_real;
}
if(data[0].total_horas != '-'){
horaTotal = data[0].total_horas;
}
var datosBarra =[{data: [[0,horaEstim]], color: "#691717"}, {data: [[1,horaReal]], color: "#173D69"},{data: [[2,horaTotal]], color: "#176469"}];
self.flotLinea(datosBarra);
},
When all is ready I send the data to self.flotBar;
This is the flotBar function:
flotBar: function(datos){
var self = this;
if(datos == 0){
var data = [["SIN REGISTROS",0]];
}else{
var data = datos;
}
function getTooltip(label, x, y) {
return "<strong style='font-size:18px;'> " + y + " </strong> horas";
}
var plot = $.plot("#placeholder",data, {
series: {
bars: {
show: true,
barWidth: 0.3,
align: "center",
lineWidth: 0,
fill:.75
}
},
xaxis: {
ticks: [[0,"Horas estimadas"],[1,"Horas reales"],[2,"Total horas"]],
mode: "categories",
tickLength: 0
},
grid: {
hoverable: true,
clickable: true
},
tooltip: true,
tooltipOpts : {
content : getTooltip,
defaultTheme : false
},
});
},
Ok , and this is my problem, example:
I select a option in an dropDown:
And the bar chart looks like this:
If I select other option in the dropDown:
The bar chart looks like this:
And if I select again the first option "Correcion de errores", the bar chart looks like this:
So.. always the first time that I show the bar chart looks like in the first image , with the numbers in the line, but If I select other option looks good.
I need see good the bar chart always and no just when I select other option.
I'm using flot javascript library.
How can I fix this? sorry by my english
The main issue with the question as stated is that we do not have all the code. In essence, you should either provide all the code, or shrink down the problem to something that shows the issue and then, well, provide all the code. As far as I can guess, you have some other code somewhere else that is drawing the initial chart. The second and subsequent times? Drawn properly. To support my assertion, notice that in your initial image the captions for the x-axis tick markers (ditto the bars themselves) are right aligned not centered.
For fun, I wrote a quick jsFiddle that showed how to switch datasets using a button (much as you want to do with the drop-down) and redraw the chart:
drawChart = function(index) {
var chartData = getDataForChart(rawData[index]);
if (chart) {
chart.setData(chartData);
chart.draw();
}
else {
chart = $.plot("#barchart", chartData, chartOptions);
}
},
switchDataset = function() {
datasetIndex = (datasetIndex + 1) % datasetCount;
drawChart(datasetIndex);
};
$("#switchButton").on("click", switchDataset);
Because I decided to load new data into the chart rather than redraw it all from scratch (to be honest I saw no real difference either way), it meant that I had to pre-calculate the maximum value for the y-axis:
calcValueMax = function() {
var max = 0;
rawData.forEach(function(values) {
values.forEach(function(value) {
if (value > max) {
max = value;
}
});
});
return max;
},
// other code
chartOptions.yaxis.max = calcValueMax();
Hope that helps.

jqplot set data series from table

I am using jqplot to create a pie chart from an HTML table.
However, when attempting to set a var the chart doesn't plot.
If i simply set a number for the var, such as:
var DataTest = 22;
then the chart works fine.
However, when I get the value from the table it doesn't, as below:
var DataTest = $(dataID + ' td:nth-child(46)').text();
The pie chart wont display.
The pie chart series is being set through a var also:
var PieChartS1 = [ ['Label', DataTest] ];
Then included in the chart code as follows:
var PieChartPlot = $.jqplot('PieChart', [PieChartS1, PieChartS2 ], {
seriesDefaults: {
renderer:$.jqplot.DonutRenderer,
rendererOptions:{
sliceMargin: 1,
startAngle: -145,
showDataLabels: true,
dataLabels: 'label',
padding: '5',
ringMargin: '5',
dataLabelThreshold: '1',
highlightMouseOver: true,
}
},
grid: {background: 'transparent', borderWidth: '0', cursor: 'pointer',},
});
I'm wondering whether it is a format issue?
Thanks for any help
Richard
Update:
Am wondering whether the graph is being formed by the script before the data has been obtained, so it is just showing blank as it is finding no data. Perhaps I need to delay the graph formation until the 'get data' scripts are fully executed?
Had some help from elsewhere.
It needs to be specified as an integer, so the change needs to be:
var DataTest = parseInt($(dataID + ' td:nth-child(46)').text());
This works fine.

is it possible to ignore 0 values when creating a graph in dygraph

<html>
<head>
<script type="text/javascript"
src="dygraph-combined.js"></script>
</head>
<body>
<div id="graphdiv"></div>
<script type="text/javascript">
g = new Dygraph(
// containing div
document.getElementById("graphdiv"),
// CSV or path to a CSV file.
"Date,Duration,Error\n" +
"2008-05-07,75,23\n" +
"2008-05-08,70,45\n" +
"2008-05-09,70,0\n" +
"2008-05-10,70,23\n" +
"2008-05-11,70,11\n" +
"2008-05-12,70,\n" +
"2008-05-13,80,33\n",
{
// options go here. See http://dygraphs.com/options.html
legend: 'always',
animatedZooms: true,
title: 'dygraphs chart template',
includeZero: false
}
);
</script>
</body>
</html>
Is it possible to for the graph to ignore the zero or null values so it connects directly from 45 to 23 or 11 to 33. in excel we the option does this option exists? incluedZero does not seem to have any affect.
The really simple answer is to remove the comma where the value is unneeded or not wanted.
So for example
"2008-05-09,70,0\n"+
//Should be "2008-05-09,70\n"+
and
"2008-05-12,70,\n"+
//Should be "2008-05-12,70\n"+
However, if you really cannot modify the data that is being passed to DyGraphs, then you have two options
Create the graph, pull out the data, and then remove the column value where it equals 0 or null using array.pop(), then reload the modified data back into Dygraphs using updateOptions(). You can use the method I describe in my answer here as a starting point
OR
Create a custom plotter (as below) that just draws a line to the next non-zero/null value. The above two are better solutions because Dygraphs will still think that there are zero values at certain points in time (because it is afterall in the data you gave it).
//Define the custom plotter
var custom_plotter = function(e) {
var context = e.drawingContext;
var points = e.points;
var num_points = points.length;
context.beginPath(); //Start
//Move "paint brush" to the start location
context.moveTo(points[0].canvasx, points[0].canvasy);
var p; //var to store current point
for(var i = 1; i < num_points; i++) {
p = points[i];
if(p.yval != 0 && p.yval != null) {
//Map out a line if the current value is desirable
context.lineTo(p.canvasx, p.canvasy);
}
}
context.stroke(); //Actually draw the lines mapped out in the loop above
context.closePath(); //Close
}
g = new Dygraph(
// containing div
document.getElementById("graphdiv"),
// CSV or path to a CSV file.
"Date,Duration,Error\n" +
"2008-05-07,75,23\n" +
"2008-05-08,70,45\n" +
"2008-05-09,70,0\n" +
"2008-05-10,70,23\n" +
"2008-05-11,70,11\n" +
"2008-05-12,70,\n" +
"2008-05-13,80,33\n",
{
// options go here. See http://dygraphs.com/options.html
legend: 'always',
animatedZooms: true,
title: 'dygraphs chart template',
plotter: custom_plotter, //Pass Dygraphs the custom plotter defined above
}
);

Categories