I've created a form that will allow me to edit parts of my chart. One of them is the subtitle but for some reason the chart.redraw() isn't working and I'm not getting an error message back. The chart needs to redraw once the input field has changed. The chart already updates with a redraw every minute so I know it works otherwise but for some reason in this single function it won't call redraw(). This is very important because another option is to hide/show the legend and that will need a redraw().
HTML:
<input type="text" placeholder="Sub Title" data-chart="chart_3972002" data-action="chartSub">
JavaScript:
$('input[data-action="chartSub"]').change(function(){
$('.unSaved').html('Saving').css('color','#669900').delay(800).fadeOut();
var key = $(this).data('chart');
var chart = JSON.parse(localStorage.getItem(key));
chart.subTitle = $(this).val();
localStorage.setItem(key, JSON.stringify(chart));
var Chart = $('#'+key).highcharts();
Chart.setTitle(null, {text: chart.subTitle});
Chart.redraw();
});
Set title function redraws chart automatically, so you don't need to use redraw() function.
http://api.highcharts.com/highcharts#Chart.setTitle()
Related
In my project I have I have ten graphs in a table with each graph showing two datasets.
I want to toggle the visibility of each dataset by clicking it which is default behaviour in ChartJS.
All the charts are held in an array and following the built in toggle method of ChartJS, every chart is updated to the dataset of the first chart. So to be clear, when the page loads, each chart is shown correctly, but if I made the dataset invisible and visible again, it becomes visible but with the wrong data.
I tried writing my own update function to toggle the visibility.
var option = {
legend: {
onClick: ToggleDatasetVisibility,
}}
and then
function ToggleDatasetVisibility() {
this.chart.getDatasetMeta(1).hidden = !this.chart.getDatasetMeta(1).hidden;
// this.chart.update();
}
However exactly the same thing happens. After the update,
*Note, I'm only toggling the second dataset of each DatasetMeta so that's why the 1 is hardcoded in this example. That's not the chart in question.
In case it's useful, we is the code when the charts are primed with data when the page loads and here the update shows the correct data.
for (var i = 0; i < 10; i++) {
var MyArray= await fetch("http://localhost:1234/Demo/FetchResults?model_id=" + i);
//Add the recorded tunnel data to dataset 0
LineChartArray[i].data.datasets[0].data = ResultsArray;
LineChartArray[i].data.datasets[0].label = '';
LineChartArray[i].data.datasets[1].data = MyArray;
LineChartArray[i].data.datasets[1].label = 'LabelXYZ';
LineChartArray[i].update(); //This update updates the graph with the correct data.
}
}
So, I don't know if there's a bug with chart JS or a correct determine which chart to update but I discovered that the render method works. This updates the chart following the visibility toggle loads the correct data back in when made visible. I thought it might be my use of the 'this' command but it works fine with the render method.
I just updated the toggle function like so,
function ToggleDatasetVisibility() {
this.chart.getDatasetMeta(1).hidden = !this.chart.getDatasetMeta(1).hidden;
this.chart.render();
}
I have another question regarding AmCharts. I have got numerous graphs, but want to show only one Balloon. I am using the
chartCursor.oneBalloonOnly
right now. I am also using AmLegend. I want to dynamically change the information within the one balloon whenever the user dismisses or adds a graph via legend.
I imagine if kind of like this:
function adjustBalloonText(graphDataItem, graph){
var date = ""; //some kind of getDateInScrollbar here
var distance = ""; // some kind of getGraph1Value here
var duration = ""; // some kind of getGraph2Value here as well
return "date <br> distance <br> duration";
}
Please help me.
Thanks!
I would like to visualise a number of variables per country on a world map. With Google Fusion Tables I set up the map. Now I would like to flip between the variables/layers (Var_A and Var_B) I would like to visualise with a dropdown menu. I followed the code the Guardian used in this article.
In this example the formatting of the info window in the FusionTable itself seems to simply show up but that doesn't work for me.
This is the fusion table: https://www.google.com/fusiontables/embedviz?viz=GVIZ&t=TABLE&q=select+col0%2C+col1%2C+col2%2C+col3%2C+col4%2C+col5%2C+col6%2C+col7+from+19I14XgRDOk7697iWA8XSukbYBBelNRymFOqjw_ru&containerId=googft-gviz-canvas
Clicking on the respective country I would like to display an info window, which shows a chart (bar chart for example) showing the values Var_A and Var_A1 when Layer 'Var_A' is selected and Var_B and Var_B1 when Layer 'Var_B' is selected.
I tried with the code example in Add a google chart to a infowindow using google maps api ....
function drawChart(marker) {
var node = document.createElement('div'),
infoWindow = new google.maps.InfoWindow(),
chart = new google.visualization.PieChart(node);
chart.draw(data, options);
infoWindow.setContent(node);
infoWindow.open(marker.getMap(),marker);
}
... but not even the static google chart worked for me.
So I really have three problems here:
1) show ANY chart in the info window
2) show a chart using data from the respective data row (country)
3) show a chart using data from the respective data row (country) and depending on the selected layer
I tried for a couple of days now with many unsuccessful ways and I am stuck - ready to leave google maps if I can not get it to work. This is the fiddle of the last thing that did at least show a map - I had to remove all event listeners again...
fiddle: http://jsfiddle.net/sytpp/ovfauhwb/
Any help greatly apprechiated!!
observe the click-event of the FusionTablesLayer, you will get there the values for the particular row:
google.maps.event.addListener(layer,'click',function(e){
//which values need to be drawn in the chart, A or B ?
var prefix=document.getElementById('selector').value,
//collect the data
row={title:e.row.Country.value,rows:[]};
//Var_A or Var_B
row.rows.push([prefix,Number(e.row[prefix].value)]);
//Var_A or Var_B1
row.rows.push([prefix+'1',Number(e.row[prefix+'1'].value)]);
//call drawChart by passing the collected data and clicked position as arguments
drawChart(row,e.latLng);
});
Now use the data(Note: you may initially set the content of the infoWindow to an empty div-element, there is no need to create a new node each time)
function drawChart(row,position) {
// Create the data table.
var data = new google.visualization.DataTable();
//set the scheme
data.addColumn('string', 'label');
data.addColumn('number', 'amount');
//add the data
data.addRows(row.rows);
// Set chart options
var options = {'title':row.title,
'width':300,
'height':200,
legend:'none'};
//assuming the infoWindow already has the content set to a DOMNode, e.g. a div
var chart = new google.visualization.BarChart(infoWindow.getContent());
chart.draw(data, options);
infoWindow.setOptions({map:map,position:position});
}
Note: you must set the suppressInfoWindows-option of the FusionTablesLayer to true, otherwise 2 InfoWindows will open, the built-in and the custom where the chart will be drawn.
Demo: http://jsfiddle.net/doktormolle/o1fyarnf/
I am using c3.js and c3.css to make several graphs on one page. I have multiple charts and want to update the data every 60 seconds so I use set interval, get the updated data, and then load it to a chart, however, it puts all of the data in the most recently made chart. I attempted to add a bindto to the data so it goes to the correct graph, but it still loads onto the bottom graph. how can I fix this?
...
<div id='chart1'></div>
<div id='chart2'></div>
...
function update()//this function collects the new data in arrays cols and xrows
...
setInterval(function(){
update();
chart.unload();
chart.load({bindto:'#chart1',columns:cols, xs:xrows});
},3000);
For showing update data atfirst
hide previous data's DIV
Use CLEAR to for cleaning Data
Again Load the DIV
If anyone's still looking to do this I've found a solution.
When you generate each chart, the declaration ends with:
}); }, chart = generate();
If you rename chart like so:
}); }, first_chart = generate();
Then you can manipulate that chart like so:
first_chart.load ({ <some_stuff> })
Give each chart variable a distinct name and you can edit them distinctly.
I have a scenario where I want to toggle series based on checkbox selection. I have added the checkbox to the legend using labelFormatting in legend option like:
var otherOptions = {
legend: {
container: legend,
labelFormatter: function (label, series) {
var cb = '<input type="checkbox" name="' + label + '" checked="checked" id="id' + label + '"> ' + label;
return cb;
}
},
};
And I have added the click event for the legend so that I can manipulate the series based on checked items. It all works fine except when I uncheck a label in legend, on re-draw it removes that series line from the legend as well. So for ex., below is the before and after image:
Before
After
Notice that in after image "USA" checkbox is missing.
Is there any way I can still show the unchecked "USA" checkbox in legend?
I looked at the suggestion here: flot graph, use legend to turn on/off series
But the only problem is that I don't want to have legend AND checkbox legend separate. The question on the given link was answered 1+ year ago so I thought I am gonna take a chance and ask the question again in case someone knows a way to do this.
Please let me know.
Thanks!
Instead of removing the series all together if the checkbox is unchecked, add it with empty data.
Something like this:
function plotByChoice(doAll)
{
$('#legend .legendCB').each(
function(){
if (this.checked)
{
data.push(datasets[someLabel]);
}
else
{
data.push({label: someLabel, data: []})
}
}
);
// plot call etc...
}
Working fiddle is here.
For anyone looking for a clean solution AND for Chart.js v3 :
This is unfortunately not possible for Chart.js v3 as legends are generated with text (no HTML can be appended to the legend itself, unfortunately).
We have to use generateLabels function to render the legend labels.
I suggest using the pointStyle option to render an image (checkbox, actually), instead of a rectangle by default, so we can rerender automatically everytime the user checks or not the legend (it's dynamic, ofc, and we don't have to do something complicated programmatically).
So, first, generate the 2 images, corresponding to the checkboxes (I'm using FontAwesome icons that I've generated in PNG from SVG files) :
let checkboxYes = new Image(14, 14);
checkboxYes.src = '/static/img/check_yes.png';
let checkboxNo = new Image(14, 14);
checkboxNo.src = '/static/img/check_no.png';
Then, we can use it in the Chart.js options:
legend: {
labels: {
usePointStyle: true,
generateLabels: function(chart) {
labels = Chart.defaults.plugins.legend.labels.generateLabels(chart);
for (var key in labels) {
labels[key].pointStyle = labels[key].hidden ? checkboxNo : checkboxYes
}
return labels;
}
}
},
Explanations
I'm setting usePointStyle to true so that I can customize the point style
later
Chart.defaults.plugins.legend.labels.generateLabels(chart) kind of pre generate the labels for me (and store it into labels), so it's like a function override!
Then for each label, I'm changing its pointStyle to the checkbox image depending on the hidden parameter (if the user checked the box)
Finally, return the labels
It's perhaps not the best solution, but works amazingly well for me:
Click here to see the animated result in GIF :)