Chartjs: common clickable legend does not work after update data - javascript

There are 2 charts and 1 common legend in one page. This legend is clickable to show/hide graph line of charts. This is forked this question.
I had tried to update data above code. It's an unrefined way, but i've been able to update the chart. "The legend" text will hide/show a line chart in here.
However after the update data, this toggle function is not work.
Please try here.
Click "The legend", it show and hide graph line --->OK
Click "ChangeData" button, graph line will be changed --->OK
Click "The legend" again, does not disappear graph line -->NG
First, it call the DrawChart function, which draws the data for the argument.
window.onload = function () {
DrawChart(data_A1, data_B1);
clickableCommonLegend();
}
The DrawChart function draw line chart by typical method of ChartJS.
function DrawChart(data_A, data_B) {
var ctxA = document.getElementById("myChartA").getContext("2d");
var ctxB = document.getElementById("myChartB").getContext("2d");
myChartA = new Chart(ctxA, {
type: 'line',
data:{.....
options:{....
});
myChartB = new Chart(ctxB, {
type: 'line',
data:{.....
options:{....
});
The clickableCommonLegend() is forked from this question.
On click button function that calls "changeData()".
This function execute destroy charts and reCall "DrawChart"
function changeData() {
myChartA.destroy();
myChartB.destroy();
DrawChart(data_A2, data_B2);
myChartA.update();
myChartB.update();
clickableCommonLegend();
}
I guess that destroy() delete all context of and re-define context by document.getElementById("myChartA")... in DrawChart().
I think it wii work fine, but result is not.
in clickableCommonLegend,
var legendItems = document.querySelector('.legend').innerHTML = myChartA.generateLegend();
Does legendItems removed from chart.destroy?
But I call it again.
I'm grad if you let me know what is wrong.
Current code is present here.

I've found a solution.
Change changeData() function
function changeData() {
// ---NOT WORK---
// myChartA.destroy();
// myChartB.destroy();
// DrawChart(data_A2, data_B2);
// --- OK ---
myChartA.data.datasets[0].data = data_A2;
myChartB.data.datasets[0].data = data_B2;
myChartA.update();
myChartB.update();
clickableCommonLegend();
}

Related

Add custom parameter to info.contentsFunction

I need to be able to add some custom info to the pie.info.contentsFunction in Zoomcharts. I have multiple charts on the page, each one created like so...
var pc = new PieChart({
pie: {
innerRadius: 0.5,
},
container: chartContainer1,
area: { height: 500 },
data:chartData,
toolbar: {
"fullscreen": true,
"enabled": true
},
info: {
contentsFunction: boomChartTT
}
});
In the "boomChartTT" function I need to know what chart is being hovered upon. I'd like to be able to do something like this...
info: {
contentsFunction: boomChartTT(i)
}
...where 'i' is the index of the chart.
The reason I need to know the chart index is because I have some other data saved in an indexed array for each chart. The index of the chart matches the index of the data.
EXAMPLE: if user hovers on a slice in chart2 I'd want to pass '2' to the boomChartTT function so I can access the totals data for that chart (say, totalsData[2]).
I've done this in the past with other chart libraries by simply adding a data attribute to the chart container to give me the index like so...
<div id="chartContainer1" data-index="1"></div>
...and then I'm able to access the chartContainer from the hover function (contentsFunction) and then get that index.
I don't want to add the totals data to the actual chart data because I'd have to add it to each slice which is redundant.
Is there a way to do this?
Please let me know if my post is unclear.
EDITED TO ADD:
I don't think it matters but here is the boomChartTT function:
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
//var thisData=dataSearch(totalsData[i],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
The commented line is where I would need the index (i) to to get the correct totalsData.
SOLVED. I simply added "chartIndex" to the data like so...
for(var i=0;i<r.length;i++){
var thisDataObj ={
id:r[i].REFERRINGSITE,
value:r[i].PCTOFSALES,
name:r[i].REFERRINGSITE,
chartIndex: arguments[1],//<----- arguments[1] is the chart index
style: { expandable: false, fillColor: dataSearch(dataRSList,"REFERRINGSITE",r[i].REFERRINGSITE)[0].COLOR }
};
chartData.preloaded.subvalues.push(thisDataObj);
}
Then in the boomChartTT function...
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
var thisData=dataSearch(totalsData[data.chartIndex-1],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
I feared that adding custom fields to the chart data would break the chart (which I believe I've experienced with other libraries). So, there you go.

Javascript - AmCharts hide and show graph using legends

I am using Amcharts plugins in making a graph. But I am having issues in hiding and showing the graph using legends.
This is my function code:
function handleLegendClick( graph ) {
var chart = graph.chart;
for( var i = 0; i < chart.graphs.length; i++ ) {
if ( graph.id == chart.graphs[i].id )
chart.hideGraph(chart.graphs[i]);
else
chart.showGraph(chart.graphs[i]);
}
if (graph.id == chart.graphs['3'].id)
chart.hideGraph(chart.graphs['4']);
if (graph.id ==chart.graphs['4'].id)
chart.hideGraph(chart.graphs['3']);
chart.validateNow();
// return false so that default action is canceled
return true;
}
This code is working but my problem is, it hides only one graph and show the graph again when the user click another legend. What I need to do is to hide multiple graphs by clicking it's assigned label text and marker, and when the graph is hidden I should click the same legend to show the hidden graph.
Please help me. Thank you.
From your description, the default legend behavior does exactly what you're asking for without needing to add your handleClick code. I'm not sure what's the point of it.
var chart = AmCharts.makeChart("chartdiv", {
// ...
"legend": { }, //default setup
});
Here's an example with multiple graphs.

How to trigger click event on a bar in Flot Stacked Bar Chart?

I wanted to trigger the click event of the lowest bar of the first stacked bar in Flot.
The rationale for this is that I wanted to select this portion of the chart on first load and at the same time execute the onClick handler of the bar.
I know that jQuery supports this behavior but I just don't know how to integrate it with Flot.
How can it be done?
Thank you.
You need to trigger a plotclick event on the desired column's point passing the trigger the appropriate item.
For instance, say you want to click the 4th column of the first series:
var col = 4; // 4th column
var series = somePlot.getData()[0]; // first series
var dataIndex = col - 1;
ps = series.datapoints.pointsize;
var item = {
datapoint: series.datapoints.points.slice(dataIndex * ps, (dataIndex + 1) * ps),
dataIndex: dataIndex,
series: series,
seriesIndex: 0
};
$('#placeholder').trigger('plotclick', [ null, item ]); // passing a null position, we don't need it
This will in turn call your plotclick event
$("#placeholder").bind("plotclick", function (event, pos, item) {
if (item) {
somePlot.highlight(item.series, item.datapoint);
}
});
Here's an example.
To trigger click events in the jQWidgets Chart (jqxChart), you can look at: Chart Events

Birt: change the dimension of chart through script

Can someone please tell me how to change the dimension of a chart through javascript in Birt. I tried the below method but the chart totally disappears after I put the below script in beforegeneration event of chart
function beforeGeneration( chart, icsc )
{
yAxis = chart.getAxes()[0].getAssociatedAxes()[0];
seriesDef = yAxis.getSeriesDefinitions()[0];
for(i=0;i<seriesDef.getSeries().size();i++)
{
if(seriesDef.getSeries()[i].getSeriesIdentifier() == "My Town")
{
ds = seriesDef.getSeries()[i].getDataSet();
}
}
ns = BarSeriesImpl.create();
ns.setDataSet(ds);
ns.setSeriesIdentifier("My Town");
seriesDef.getSeries().add(ns);
seriesDef.getSeries().move(0,ns);
setDimension(TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);
}
The whole function is working. Only problem I am facing is to change the chart type to 2D with Depth. I have problem with below syntax
setDimension(TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);
Any help will be appreciated
Arif
Isn't it the following instead....
chart.setDimension(actuate.report.Chart.CHART_DIMENSION_2D_WITH_DEPTH );

how to thoroughly remove JQPlot Chart

Do you know how to thoroughly remove/clean JQPlot chart. Here is my code to clean it:
$j("#reset").click(function() {
$j("#chart").empty();
if (plot1) {
plot1 = null;
}
});
when I click reset button, the chart can be removed from my page, but when I choose new conditions from drop down lists to generate new chart, the old chart will overlap with the new chart, like this image showed
Do you know how to truly clean the old chart? Thanks!
Maybe you want to use redraw method.
http://www.jqplot.com/docs/files/jqplot-core-js.html#jqPlot.redraw
You can redraw it with empty values using :
$.("#reset").click(function(){
if(plot1){
plot1 = $.jqplot('chart', [[[]]], {});
plot1.redraw();
}
});
Please see working example here
My method is "expensive" but works for me. Use .remove():
if ($("#chart").length) {
$("#chart1").remove();
} else {
$(parent).append("<div id=\"chart1\"></div>");
}
// put $.jqplot below here
You can use the destroy method.
e.g.
if (C.chart != null) {
C.chart.destroy();
C.chart = null;
}
C.chart = $.jqplot("chart", chartData, {

Categories