Selecting Points over multiple Highcharts treemaps - javascript

Aim: I have two identical Highcharts treemaps and if I select one point of one chart, I also want to send a select event to the second chart's point with the same id/ same position.
Progress:
I followed these answers that tackle the same problem, only for line graphs, and then adopted the fiddle posted there for treemaps. You can find it here as well as below:
$(function () {
var prevPid = 0;
var chart = {
plotOptions: {
series: {
allowPointSelect: true,
point: {
'events': {
select: function () {
var pId = this.series.data.indexOf(this);
var chart1 = $('#container').highcharts();
var chart2 = $('#container2').highcharts();
chart1.series[0].data[pId].setState('select');
chart2.series[0].data[pId].setState('select');
chart2.series[0].data[prevPid].setState('');
prevPid = pId;
}
}
}
}
},
series: [{
type: "treemap",
data: [{
name: 'A',
value: 6,
colorValue: 1
}, {
name: 'B',
value: 6,
colorValue: 2
}, {
name: 'C',
value: 4,
colorValue: 3
}]
}]
};
$('#container').highcharts(chart);
$('#container2').highcharts(chart);
});
Problem: However the corresponding point of the other chart is not selected. Any advice on how to fix it?

Highcharts v5+
Instead of playing around with states, it's easier to use point.update(), demo: http://jsfiddle.net/BlackLabel/hy12z5u7/
Settings:
chart: {
events: {
load: function() {
$.each(this.series, function(i, s) {
$.each(s.data, function(j, p) {
p.pointAttr = {
select: {
color: "red"
}
};
});
});
}
}
},
And action:
point: {
'events': {
click: function() {
var pId = this.series.data.indexOf(this);
var chart1 = $('#container').highcharts();
var chart2 = $('#container2').highcharts();
chart1.series[0].data[prevPid].update({
color: chart1.series[0].color
});
chart2.series[0].data[prevPid].update({
color: chart2.series[0].color
});
chart1.series[0].data[pId].update({
color: chart1.series[0].data[pId].pointAttr.select.color
});
chart2.series[0].data[pId].update({
color: chart2.series[0].data[pId].pointAttr.select.color
});
prevPid = pId;
}
}
}
Highcharts < v4
The problem is that treemap doesn't have states.select option (API: http://api.highcharts.com/highcharts#plotOptions.treemap.states ) so even, when you force select-ed state, then nothing visually changes on your chart. You can add that state manually: http://jsfiddle.net/tqa6uxdb/3/
chart: {
events: {
load: function() {
$.each(this.series, function(i, s) {
$.each(s.data, function(j, p) {
p.pointAttr.select = {
fill: "red"
}
});
});
}
}
},
Note: your logic for selecting/deselecting points is missing checking if currently clicked point is already clicked.

Related

plotBands Hide and Show parameters do not work in Highcharts

When I clicked in legend, the plotBands parameters hide() and show() do not work.
I wish I could click on the legend and remove a specific PlotBand.
I tried using destroy() but it cleans the html dom and I can't return with PlotBand when I click on the legend again.
I couldn't find how to remove and put the PlotBand back on:
var a = 1,
b = 2,
c = 4,
d = 5,
dados = [[a, b, '#32CD32','manutenção','Mantuenção'], [c, d, '#FF0000','falha','Falha']];
Highcharts.chart('container', {
chart: {
zoomType: 'xy',
},
showInLegend: true,
title: {
text: 'Zoom Geral e Barras Verticais'
},
yAxis: {
scrollbar: {
enabled: true,
showFull: false
}
},
plotOptions: {
series: {
shadow:false,
borderWidth:0,
events:{
legendItemClick:function(e){
console.log(this.userOptions)
var ids = this.userOptions['id'];
console.log(ids)
if(this.userOptions['id'] === ids){
var hides = this.xAxis.plotLinesAndBands.filter(id => id.id == ids);
if(this.visible == true){
hides[0].svgElem.hide()
} else {
hides[0].svgElem.show()
}
}
}
}
}
},
series: [{
name:'Série A',
data: [-10, 31, 35, 40, 15, 10]
}
]
},
function(){
for (let i = 0; i < dados.length; i++ ){
this.xAxis[0].addPlotBand({
from: dados[i][0],
to: dados[i][1],
color: dados[i][2],
name: dados[i][4],
id: dados[i][3]
}, )
this.addSeries({
marker: {
symbol: 'square',
radius: 20},
name: dados[i][4],
color: dados[i][2],
type: 'scatter',
id: dados[i][3]
}, )
}
}
)
The plot bands are not hidden because the chart is redrawn after the event. You can return false from the callback function, but all plot bands will be visible after another redraw. Example: http://jsfiddle.net/BlackLabel/m2xrjhLk/
I recommend you to remove/add the plot band on legend click:
plotOptions: {
series: {
...,
events: {
legendItemClick: function(e) {
var id = this.options.id;
if (this.visible) {
this.xAxis.removePlotBand(id);
} else {
this.xAxis.addPlotBand(plotBands.find(
plotBand => plotBand.id === id
));
}
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/n1jgew27/

Dynamically load in series HighCharts

I am trying to dynamically load in a number of series, depending on projects chosen by the user. I am using Laravel 5.2, PHP 5.6 and HighCharts.
I have managed to load in one JSON file, which is generated when the user selects projects. But I would like it if the JavaScript could parse the different series from the JSON file and dynamically load this into the series.
This is the code which I am using:
$(function () {
// Set up the chart
var processed_json = new Array();
$.getJSON('/uploads/test.json', function(data) {
for (i = 0; i < data.length; i++) {
processed_json.push([data[i].key, data[i].value]);
}
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
options3d: {
enabled: true,
alpha: 0,
beta: 0,
depth: 0,
viewDistance: 25
}
},
title: {
text: 'Grades'
},
subtitle: {
text: 'Dataset'
},
plotOptions: {
column: {
depth: 0
}
},
series: [{
name: 'Grades',
data: processed_json
}],
credits: {
enabled: false
}
});
function showValues() {
$('#alpha-value').html(chart.options.chart.options3d.alpha);
$('#beta-value').html(chart.options.chart.options3d.beta);
$('#depth-value').html(chart.options.chart.options3d.depth);
}
// Activate the sliders
$('#sliders input').on('input change', function () {
chart.options.chart.options3d[this.id] = this.value;
showValues();
chart.redraw(false);
});
showValues();
});
});
My JSON is formatted like:
[{"key":"Math","value":6},{"key":"Biology","value":"8"},{"key":"English","value":"7"},{"key":"Gym","value":"4"}]
So I would like to have more JSONs like so, in one file to be parsed in the Javascript and be loaded in into the series.
Thank you!
EDIT
thanks for your reply. I have edited my code:
$(function () {
var processed_json = new Array();
var options = {
chart: {
renderTo: 'container',
type: 'column',
options3d: {
enabled: true,
alpha: 0,
beta: 0,
depth: 0,
viewDistance: 25
}
},
title: {
text: 'Grades'
},
subtitle: {
text: 'Dataset'
},
plotOptions: {
column: {
depth: 0
}
},
series: [{
}],
credits: {
enabled: false
}
};
$.getJSON('/uploads/test.json', function(data) {
for (i = 0; i < data.length; i++) {
processed_json.push([data[i].key, data[i].value]);
}
});
options.series[0].remove();
options.series[0].setData = {
name: 'Grades',
data: processed_json
}
var chart = new Highcharts.Chart(options);
chart.redraw(true);
function showValues() {
$('#alpha-value').html(chart.options.chart.options3d.alpha);
$('#beta-value').html(chart.options.chart.options3d.beta);
$('#depth-value').html(chart.options.chart.options3d.depth);
}
// Activate the sliders
$('#sliders input').on('input change', function () {
chart.options.chart.options3d[this.id] = this.value;
showValues();
chart.redraw(false);
});
showValues();
});
But nothing is displayed anymore and the following error is given
TypeError: options.series[0].remove is not a function
I have also tried
var chart = new Highcharts.Chart(options);
chart.series[0].remove();
chart.series[0].setData = {
name: 'Grades',
data: processed_json
}
chart.redraw(true);
But this gives:
TypeError: Cannot set property 'setData' of undefined
I think highcharts has a method chart.addSeries for adding a new series. If you want to replace the current series with a new series, you can try removing first the current series using chart.series[0].remove( ) then add the new series with chart.addSeries. The parameter for the chart.addSeries can be an object like your
{
name: 'Grades',
data: processed_json
}
Then, define method with load data.. example:
function(chart) {
$.each(chart.series, function(i, v){
chart.series[i].remove(true);
});
chart.addSeries({your_data}, true);
}
check http://api.highcharts.com/highcharts/Chart.addSeries/Chart.addSeries
In my webapp, i use 10 of 15 types of graphs highchart and all dynamically load and work fine :) Highcharts is awesome.

Drilldown on multiple Highcharts with the same data

Is it possible to have Highcharts drilldown on multiple graphs that are sharing the same data when one graph is clicked?
As an example, I included a JSFiddle that uses the demo code (browser percentages).
http://jsfiddle.net/Pq6gb/
var gridster;
$(function(){
gridster = $(".gridster ul").gridster({
widget_base_dimensions: [150, 150],
widget_margins: [5, 5],
helper: 'clone',
resize: {
enabled: true,
stop: function(e, ui, $widget) {
for (var i = 0; i < Highcharts.charts.length; i++) {
Highcharts.charts[i].reflow();
}
}
}
}).data('gridster');
});
$(function () {
Highcharts.data({
csv: document.getElementById('tsv').innerHTML,
itemDelimiter: '\t',
parsed: function (columns) {
var brands = {},
brandsData = [],
versions = {},
drilldownSeries = [];
// Parse percentage strings
columns[1] = $.map(columns[1], function (value) {
if (value.indexOf('%') === value.length - 1) {
value = parseFloat(value);
}
return value;
});
$.each(columns[0], function (i, name) {
var brand,
version;
if (i > 0) {
// Remove special edition notes
name = name.split(' -')[0];
// Split into brand and version
version = name.match(/([0-9]+[\.0-9x]*)/);
if (version) {
version = version[0];
}
brand = name.replace(version, '');
// Create the main data
if (!brands[brand]) {
brands[brand] = columns[1][i];
} else {
brands[brand] += columns[1][i];
}
// Create the version data
if (version !== null) {
if (!versions[brand]) {
versions[brand] = [];
}
versions[brand].push(['v' + version, columns[1][i]]);
}
}
});
$.each(brands, function (name, y) {
brandsData.push({
name: name,
y: y,
drilldown: versions[name] ? name : null
});
});
$.each(versions, function (key, value) {
drilldownSeries.push({
name: key,
id: key,
data: value
});
});
// Create the chart
$('#container').highcharts({
chart: {
type: 'pie'
},
title: {
text: 'Browser market shares. November, 2013.'
},
subtitle: {
text: 'Click the slices to view versions. Source: netmarketshare.com.'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
format: '{point.name}: {point.y:.1f}%'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>'
},
series: [{
name: 'Brands',
colorByPoint: true,
data: brandsData
}],
drilldown: {
series: drilldownSeries
}
})
}
});
});
$(function () {
Highcharts.data({
csv: document.getElementById('tsv').innerHTML,
itemDelimiter: '\t',
parsed: function (columns) {
var brands = {},
brandsData = [],
versions = {},
drilldownSeries = [];
// Parse percentage strings
columns[1] = $.map(columns[1], function (value) {
if (value.indexOf('%') === value.length - 1) {
value = parseFloat(value);
}
return value;
});
$.each(columns[0], function (i, name) {
var brand,
version;
if (i > 0) {
// Remove special edition notes
name = name.split(' -')[0];
// Split into brand and version
version = name.match(/([0-9]+[\.0-9x]*)/);
if (version) {
version = version[0];
}
brand = name.replace(version, '');
// Create the main data
if (!brands[brand]) {
brands[brand] = columns[1][i];
} else {
brands[brand] += columns[1][i];
}
// Create the version data
if (version !== null) {
if (!versions[brand]) {
versions[brand] = [];
}
versions[brand].push(['v' + version, columns[1][i]]);
}
}
});
$.each(brands, function (name, y) {
brandsData.push({
name: name,
y: y,
drilldown: versions[name] ? name : null
});
});
$.each(versions, function (key, value) {
drilldownSeries.push({
name: key,
id: key,
data: value
});
});
// Create the chart
$('#container2').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Browser market shares. November, 2013'
},
subtitle: {
text: 'Click the columns to view versions. Source: netmarketshare.com.'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>'
},
series: [{
name: 'Brands',
colorByPoint: true,
data: brandsData
}],
drilldown: {
series: drilldownSeries
}
})
}
});
});
There is a pie chart and a bar chart displaying the same data and can drilldown individually. I would like to click on any browser in the pie/bar chart and have both charts filter down to versions of that browser.
How would I go about doing this? Thanks.
Yes, it's possible. This is what you need to implement:
on drilldown event you can find respective point on a second chart and simple call 1point.doDrilldown()1
on drillup even in one chart, call on a second chart.drillUp()
Note: You need to be aware of infinite loop (for example drillUp() in one chart will call drillup event, which will drillUp() first chart again.. ) - just add some flag to call drillUp/doDrilldown only once per user click.

Update Highchart data form exported button

I'm trying to use the exporting option to add a button which is then used to switch between a line chart with the real point and another with the cumulative sum of them.
I'm using the following code:
$(function () {
$('#container').highcharts({
chart: {
type: 'line'
},
xAxis: {
tickPixelInterval: 200,
categories: jsonResponse["Date"]
},
series: {
data: jsonResponse["values"]
},
exporting: {
buttons: {
'myButton': {
_id: 'myButton',
symbol: 'diamond',
text: 'Cumulative',
x: -62,
symbolFill: '#B5C9DF',
hoverSymbolFill: '#779ABF',
onclick: function() {
if(!cumulative){
this.series[0].setData = cumcum(jsonResponse["values"]);
alert(this.series[1].setData);
cumulative = true;
} else {
this.series[0].setData = jsonResponse["values"];
cumulative = false;
alert(this.series[1].setData);
}
},
_titleKey: "myButtonTitle"
}
}
}
});
});
function cumcum(data){
var res = new Array();
res[0] = data[0];
for(var i=1; i<data.length; i++) {
res[i] = res[i-1] + data[i];
}
return res;
}
From the alert I can see that the data are correctly calculated but the plot stays the same.
I also tried series[0].yData and series[0].processedYData
setData is a function, you have to call it like:
this.series[0].setData(cumcum(jsonResponse["values"])
See API http://api.highcharts.com/highstock#Series for more information.

Highcharts - column chart redraw animation

I'm trying to update an existing data series with a new data array and invoke the redraw function when done. While this works perfectly, I'm not quite satisfied as I'd like to have a sort of grow/shrink transition. I have seen an example by Highcharts (fiddle around with the existing data set then click on the button "Set new data to selected series") but I can't replicate this behavior.
This is what code that I've written:
var series, newSeriesThreshold = this.chart.series.length * 2;
for (var i = 0; i < data.length; i += 2) {
series = {
name: this.data[i].title,
data: this.data[i].data,
color: this.data[i].color
};
if (i >= newSeriesThreshold) {
this.chart.addSeries(series, false);
} else {
var currentSeries = this.chart.series[i / 2];
currentSeries.setData(series.data, false);
}
}
this.chart.redraw();
These are the options when creating the chart:
var config = {
chart: {
renderTo: $(this.container).attr('id'),
type: this.settings.type,
animation: {
duration: 500,
easing: 'swing'
}
},
title: {
text: null
},
legend: {
enabled: this.settings.legend.show
},
tooltip: {
formatter: function() {
return this.x.toFixed(0) + ": <b>" + this.y.toString().toCurrency(0) + '</b>';
}
},
xAxis: {
title: {
text: this.settings.xaxis.title,
style: {
color: '#666'
}
}
},
yAxis: {
title: {
text: this.settings.yaxis.title,
style: {
color: '#666'
}
}
},
series: series,
plotOptions: {
column: {
color: '#FF7400'
}
},
credits: {
enabled: false
}
};
This yields an immediate update without transitioning effects. Any ideas what I might be doing wrong?
I have solved this problem by destroying and creating again the chart.
Here is the link on highcharts forum that helps me : http://forum.highcharts.com/highcharts-usage/animation-on-redraw-t8636/#p93199
The answer comes from the highcharts support team.
$(document).ready(function() {
var chartOptions = {
// Your chart options
series: [
{name: 'Serie 1' , color: '#303AFF', data: [1,1,1,1,1,1,1}
]
};
var chart = new Highcharts.Chart(chartOptions);
$("#my_button").click(function(){
chart.destroy();
chartOptions.series[0].data = [10,5,2,10,5,2,10];
chart = new Highcharts.Chart(chartOptions);
});
});
This remain a mystery. I managed to make the axis update which suggests that there is some kind of animation going on, but it's applied only to the axis, and not the columns.
In the end, I've settled with this behavior.
This might help:
var mychart = $("#mychart").highcharts();
var height = mychart.renderTo.clientHeight;
var width = mychart.renderTo.clientWidth;
mychart.setSize(width, height);
to update all charts
$(Highcharts.charts).each(function(i,chart){
var height = chart.renderTo.clientHeight;
var width = chart.renderTo.clientWidth;
chart.setSize(width, height);
});

Categories

Resources