Highcharts variable pie legendItemClick does not hide or update data - javascript

I am currently working with HighCharts variable Pie chart. I wanted to add more functionality to the legend click, so I added a separate legendItemClick event to perform two things: it should behave like the default (which it doesn't), but also correct the text value inside the donut, which also does not work.
Here is some code to work with:
this._chart = Highcharts.chart(this.$.chartsContainer, {
title: {
text: '<div style="font-size: 30px; font-weight:600;">' + ySum + '</div><div>Total demands</div>',
align: 'center',
verticalAlign: 'middle',
useHTML: true,
style: {
'font-size': '16px',
'font-weight': 'normal',
'text-align': 'center',
'text-transform': 'inherit'
},
x: -2,
y: -27,
},
colors: ['#315674', '#006281', '#006D81', '#00BFE2', '#53A1B4', '#4FB4B5', '#00E8D2', '#FFC35F', '#9ECBD6'],
plotOptions: {
series: {
dataLabels: {
enabled: false },
showInLegend: true,
style: {'border-radius': '15px', 'font-weight': 'normal'},
},
variablepie: {
name: '',
borderWidth: 5, borderColor: 'white', minPointSize: 16,
color: 'white', innerSize: '60%',
point: {
events: {
legendItemClick: function(event) {
console.log(event);
if (this.visible) {
this.series.visible = false;
ySum = ySum - event.target.options.y;
} else {
ySum = ySum + event.target.options.y;
}
}
}
}
},
},
tooltip: {
useHTML: true,
headerFormat: '<small>{point.y}</small><table>',
pointFormat: '',
footerFormat: ''
},
series: [{
type: 'variablepie',
data: ySerie,
},
]
});
this.reflowChart();
I tried hiding the clicked series data via its visible attribute, but that does not work properly, because it hides the clicked data, but does not redraw the chart to form a full circle again ( if you know what I am talking about ).
The second problem is the text title. I want it to show the new corrected value ( it is the ySum variable up inside the title: { text: block ). I tried setting the new value but it does not update the chart's data for some reason. For example, we have 3 slices of value 10 each. It shows "30 total". When 1 legend item is clicked and hidden, it should update ySum to now show " 20 total".
So in short, I need help with
1) How to properly hide and show clicked legend series data
2) Make the text attribute ySum update its value accordingly
Thank you for your help!
------------------- UPDATE -----------------
I figured out the first problem by myself ( I will leave the problem nonetheless if anyone else faces it ):
legendItemClick event is a function that can return a boolean value:
You can manipulate its behavior by setting
true = standard behavior -> it will hide the data series AND redraw the chart
false = it will do nothing -> similar as event.preventDefault()

To change chart title you can use setTitle method:
legendItemClick: function(event) {
var chart = this.series.chart
if (this.visible) {
// this.series.visible = false;
ySum = ySum - event.target.options.y;
} else {
ySum = ySum + event.target.options.y;
}
chart.setTitle({
text: ySum
}, false, false);
return true
}
API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#setTitle
Live demo: https://jsfiddle.net/BlackLabel/sdh1y0tw/

Related

Highcharts dynamically move dataLabel if it doesnt fit

Hi I am trying to present the columns values at the top of each column so it is easier for the user to compare values.
I have got this working but when some columns are very close to each other some of the values aren't being dispalyed because I'm presuming highcharts works out that it wqouldnt fit unless it overlapped so it doesnt show the value.
Here is the code for my chart -
var chart_1_Options = {
chart: {
renderTo: 'container_chart_1',
backgroundColor: '#FFFFFF'
},
credits: {
enabled: false
},
title: {
text: ''
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
}
},
plotOptions: {
column: {
animation: false,
borderWidth: 0,
dataLabels: {
enabled: true,
formatter: function() {
return '<p style="font-size: 8px;">' + this.y + '% </p>';
}
}
}
},
legend: {
enabled: true
}
};
Here is an image of what the chart looks like, I have circled areas where the value is missing
I just want the value to show even if it can't fit, I want it to place the value somewhere inside the column if it cant fit at the top.
Thanks for any help!
I think that you can try to find those labels and show them by doing something like code below:
events: {
load() {
let chart = this;
chart.series[0].points.forEach(p => {
setTimeout(function() {
if (p.dataLabel.translateY === -9999) {
p.dataLabel.translate(p.dataLabel.alignAttr.x, p.dataLabel.alignAttr.y + 20)
p.dataLabel.css({
opacity: 1
})
}
}, 50)
})
}
}
Demo: https://jsfiddle.net/BlackLabel/unzgsmfr/
API: https://api.highcharts.com/highcharts/chart.events.load

Remove Tooltip in Synchronized Charts, When user leaves the chart area

I am using Synchronized chart of Highcharts to demonstrate the statistics.
For reference : http://www.highcharts.com/demo/synchronized-charts.
Here, when the chart is getting plotted for the first time, no data points is selected. As, the cursor enters into the chart area, the tooltip, crosshairs and data points get highlighted. It works as expected.
The modification I need is, when the user comes out of the chart, the chart should look like as it was in the loading stage.
i.e. If the cursor is not on any of the chart,then no data points should remain selected. In other words, the tooltip, crosshair and the highlighted shadow on data point should get removed.
Thanks in advance for any help or suggestion.
use mouseleave to detect when the mouse is out of the container:
$('#container').bind('mouseleave', function(e) {
use hide method to hide the tooltip and hide Crosshair method to hide the crosshair:
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
Check the example (jsfiddle):
$(function() {
$('#container').bind('mouseleave', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
point.onMouseOut();
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
}
});
$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.onMouseOver(); // Show the hover marker
chart.tooltip.refresh(point); // Show the tooltip
chart.xAxis[0].drawCrosshair(event, point); // Show the crosshair
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
trigger: 'syncExtremes'
});
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function(activity) {
$.each(activity.datasets, function(i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function(val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function() {
return {
x: this.chart.chartWidth - this.label.width, // right aligned
y: -1 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
});
});

SetData() not working on Change Event HighCharts Pie Chart

I'm looking for a way to dynamically update data in a highcharts pie chart based on the change event on a dropdownlist. I have seen a couple examples but I am really unable to figure out why I can't get this working. Here is my whole code, I wrap my stuff inside a function so I can call the function with the Change() event of the dropdownlist, but I get the error of CRIPT438: Object doesn't support property or method 'setData'
function showClass(){
var total = 0;
var options = {
chart:{type:'pie',
renderTo: 'ctl00_ContentPlaceHolder1_Overview1_tcAssetAllocation_body',
events: {
load: function(event) {
$('.highcharts-legend-item').last().append('<br/><div style="width:220px"><hr/> <span style="float:left"> Total </span><span style="float:right">100%</span> </div>')
}
}
},
credits:{enabled: false},
colors:[
'#5485BC', '#AA8C30', '#5C9384', '#981A37', '#FCB319', '#86A033', '#614931', '#00526F', '#594266', '#cb6828', '#aaaaab', '#a89375'
],
title:{text: null},
tooltip:{
enabled: true,
animation: true
},
plotOptions: {
pie: {
allowPointSelect: true,
animation: true,
cursor: 'pointer',
showInLegend: true,
dataLabels: {
enabled: false,
formatter: function() {
return this.percentage.toFixed(2) + '%';
}
}
}
},
legend: {
enabled: true,
layout: 'vertical',
align: 'right',
width: 220,
verticalAlign: 'top',
borderWidth: 0,
useHTML: true,
labelFormatter: function() {
total += this.y;
return '<div style="width:200px"><span style="float:left">' + this.name + '</span><span style="float:right">' + this.y + '%</span></div>';
},
title: {
text: 'Primary',
style: {
fontWeight: 'bold'
}
}
},
series: [{
type: 'pie',
data: [['Domestic Equity', 38.5],['International Equity', 26.85],['Other', 15.70],['Cash and Equivalents', 10.48],['Fixed Income', 8.48]]
}]
}
var chart = new Highcharts.Chart(options);
$("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").change(function(){
var selVal = $("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").val();
if(selVal == '1124042'){
chart.series[0].setData([['Domestic Equity', 18.5], ['International Equity', 46.85], ['Other', 5.70], ['Cash and Equivalents', 20.48], ['Fixed Income', 8.48]]); }
});
}
is it because i am nested inside another function? it's jsut that all the fiddles use the document.ready function and it loads properly calling the function in the document.ready() but getting it on the change event is messing with me.
Any help is greatly appreciated.
Tahnk you very much,
NickG
You are wrong to use object options as part of Highcharts API. Find that line: options.series[0].setData and change to chart.series[0].setData(). Then remove creating new chart ( you don't need that - chart is already created ).

Add legend name to JQPlot tooltip and format date correctly in tool tip

I want to add the plot's legend name to the mouse over tool tip for a series line. I've used one of the solutions to this jqplot tooltip on bar chart.
Specifically I used the following function:
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
// display series_label, x-axis_tick, y-axis value
return plot.series[seriesIndex]["label"] + ", " + plot.data[seriesIndex][pointIndex];
}
However, the problem I have is that it does not use the legend name 'My legend name' instead it will use the JQPlot default of 'Series 1' or 'Series 5' (number depending on series position).
The second problem is that I lose my date formatting once I start using the above function. So I get a number e.g. something like 123672378328 instead of it being converted to the format I specified in tickOptions.
My code to generate the chart is below:
var plot;
function buildChart(chartDivId, graphData, chartTitle, graphSeriesNames, labelNames) {
var id = "#" + chartDivId;
$(id).empty();
var seriesLine = { lineWidth:1, markerOptions: { show:false } };
plot = $.jqplot(chartDivId, graphData,
{
title: chartTitle,
axes:
{
xaxis:
{
label:'Date',
renderer:$.jqplot.DateAxisRenderer,
tickOptions: { formatString:'%b %#d %H:%M' }
},
yaxis: { label: 'Parameter Values', tickOptions: { formatString:'%.2f' }, labelRenderer: $.jqplot.CanvasAxisLabelRenderer, labelOptions : { angle: 270, fontFamily: 'Arial, Verdana, Helvetica', fontSize: '8pt' }, autoscale: true },
},
seriesDefaults: {
markerOptions: {
show: true, style:'filledCircle', size: 4.5
}
},
highlighter:
{
show: true,
sizeAdjust: 7.5,
tooltipContentEditor:tooltipContentEditor //new code added to attempt to add legend name to mouse over tool tip
},
cursor:
{
show: true,
zoom: true,
showTooltip: false
},
legend:
{
labels: labelNames ,
show: true,
location: 's',
renderer: $.jqplot.EnhancedLegendRenderer,
rendererOptions:
{
numberColumns: 10,
numberRows: 5,
seriesToggle: 900,
disableIEFading: false
},
marginTop: '100px',
marginBottom: '100px',
placement: 'outside'
}
}
);
}
FURTHER UPDATE:
After being a bit silly and digging down deep into the plot object of JQPlot I realised that the str variable passed into the tooltipContentEditor method has what I need. So the following is the solution:
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
// display series_label with x and y values value
return plot.legend.labels[seriesIndex] + ", " + str;
}
No help or advice provided so I thought I'd provide the solution I found after spending a few hours trying to fix.

Highcharts X-Axis New Values

I am using highcharts to draw a column chart as following:
var chart;
var count = 0;
$(function () {
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'graph',
type: 'column',
margin: [ 50, 50, 100, 80]
},
title: {
text: 'Random Data'
},
xAxis: {
categories: [
'T1',
'T2'
],
startOnTick: true,
endOnTick: true,
labels: {
rotation: -45,
align: 'right',
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Y-Axis'
}
},
legend: {
enabled: false
},
tooltip: {
formatter: function() {
return '<b>'+ this.x +'</b><br/>'+
'Tip is: '+ Highcharts.numberFormat(this.y, 1);
}
},
series: [{
name: 'Population',
data: [34.4, 21.8],
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
x: 4,
y: 10,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
});
I added the following function in order to add new points to the chart
function addPoints(name,acc)
{
var series = chart.series[0];
series.addPoint(acc, false, true);
categories = chart.xAxis[0].categories;
categories.push(name+count);
count++;
chart.xAxis[0].setCategories(categories, false);
chart.redraw();
}
The problem is that everytime I add a new point, one column shifts out of the chart. I would like to keep all columns in the chart view, so when I add a new point the chart just zooms out.
Check it on JSFiddle
Thanks in Advance ....
addPoint (Object options, [Boolean redraw], [Boolean shift], [Mixed animation])
Add a point to the series after render time.
Parameters
options: Number|Array|Object
The point options. If options isa single number, a point with that y value is appended to the series.If it is an array, it will be interpreted as x and y values respectively, or inthe case of OHLC or candlestick, as [x, open, high, low, close]. If it is an object, advanced options as outlined under series.data are applied.
redraw: Boolean
Defaults to true. Whether to redraw the chart after the point is added. When adding more thanone point, it is highly recommended that the redraw option beset to false, and instead chart.redraw() is explicitly calledafter the adding of points is finished.
shift: Boolean
Defaults to false. When shift is true, one point is shifted off the start of the series as one is appended to the end. Use this option for live charts monitoring a value over time.
animation: Mixed
Defaults to true. When true, the graph will be animated with default animationoptions. The animation can also be a configuration object with properties durationand easing.
series.addPoint(acc, false, true);
/\ here's the problem, it should be false
Reference
http://api.highcharts.com/highstock#Series
Updated demo

Categories