Error while clicking links on highchart columns - javascript

I get an error
{"error": "Please use POST request"}
While clicking on the link, I enabled for the columns in the column chart. What is the cause for this error and how do I overcome this error.
My Series
series: [{
name: 'Capital',
data: [1000000.00, 1000000.00, 1000000.00, 1000000.00, 900000.00],
url:'http://www.google.com'
}, {
name: 'Material',
data: [8753.15, 529.00, 5620.00, 35000.00, 30988.86]
}, {
name: 'HR',
data: [66400.00, 320000.00, 488000.00, 48000.00, 512000.00]
}, {
name: 'Equipment',
data: [0.00, 160000.00, 1600000.00, 32000.00, 64000.00]
}, {
name: 'Petty Cash',
data: [10000.00, 100000.00, 100000.00, 10000.00, 150000.00]
}],
Plot options
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function (e) {
location.href = this.options.url;
e.preventDefault();
}
}
}
}
}
My consolidated code fiddled here.
Is this the right way to provide links to navigate while clicking ?

You have two bugs:
1) in click event you are using this.options.url, which is undefined, while should be (according to your series configuration) this.series.options.url
2) Add point.events under plotOptions.series:
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
console.log(this.series.options.url);
location.href = this.series.options.url;
}
}
}
}
}
And 'working' jsFiddle for you: http://jsfiddle.net/3TRL6/5/show/ - (works for Capital series). Full code is here: http://jsfiddle.net/3TRL6/5/

If you are testing the code with jsFiddle, you might get this error "{"error": "Please use POST request"}", since you are requesting a non secure site "url:'http://www.google.com'" on jsFiddle which is secured i.e 'https://jsfiddle.net/'. Try replacing Http with Https.
Please find jsFiddle link https://jsfiddle.net/ajaytripathi10/dk5ogkj9/1/
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}'
},
cursor: 'pointer',
point: {
events: {
click: function() {
console.log(this.options.url);
location.href = this.options.url;
}
}
}
}
},

Related

Highchart drill up function now working in reactjs

I'm using highchart large tree map demo. I'm getting level data on click of each section. But also need to get the data on back button. So I'm using events drill up function to get data on click of back button. below is my code.
this.setState({
data: {
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 0,
}],
data: points,
events: {
click:(e)=>{
console.log(e)
},
drillup:(e)=>{
console.log(e)
}
}
}],
// subtitle: {
// text: 'Click points to drill down. Source: WHO.'
// },
title: {
text: ''
}
}
})
But don't know drill up is not working even click is working and also I added
import drilldown from "highcharts/modules/drilldown";
drilldown(Highcharts);
But still not getting any data. Please help.
Notice that treemap series don't use the drilldown module, but has own drilldown implementation, which logic you can find here: https://code.highcharts.com/modules/treemap.src.js
What you will need to do is render a custom button while clicking the point and attach an update functionality on this button. Something like here:
Demo: https://jsfiddle.net/BlackLabel/gas07t34/
events: {
click() {
let chart = this.chart;
chart.button = chart.renderer.button('back', 500, 0, function() {
chart.series[0].update({
data: data1
})
chart.button.destroy();
}).add()
this.update({
data: data2
})
}
}
API: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#button
API: https://api.highcharts.com/class-reference/Highcharts.Series#update

How to add radio button in highchart legend symbol

I have 3 line series in my highchart , i want to make one series fixed (user) cant disable/hide it by clicking the legend.
And other two i want to work as radio button i.e user can choose among those 2 which one to show , now i was able to make that happen , but now i want a radio button next to those two legend symbols which user can choose from .
legend should be like this.
and the radio button should toggle the series. the working code (without radio button and legend allignment) is :
drawChart(data1, data2, data3) {
let chart = Highcharts.chart("container", {
chart: {
zoomType: "xy"
},
title: {
text: null
},
plotOptions: {
series: {
events: {
show: function () {
let chart = this.chart,
series = chart.series,
i = series.length,
otherSeries;
while (i--) {
if (i != 0)
otherSeries = series[i];
if (otherSeries != this && otherSeries.visible) {
otherSeries.hide();
}
}
},
legendItemClick: function () {
if (this.visible) {
return false;
}
}
}
}
},
series: [{
name: "series1",
data: data1
}, {
name: "series2",
data: data2
}, {
name: "series3",
data: data3,
visible: false
}]
}
You need to set the plotOptions and set showCheckbox: true
plotOptions: {
line: {
marker: { enabled: false }
},
turboThreshold: 0,
series: {
cursor: 'pointer',
showCheckbox: true,
events: {
checkboxClick: function (event) {
if (event.checked) {
this.show();
this.legendSymbol.show();
} else {
this.hide();
this.legendSymbol.hide();
}
},
legendItemClick: function() {
return false;
}
}
}
},
By default the checkboxes are placed right next to series label but we can override it according to our need,
Here is a fiddle that might help !!! It's just a pointer, You can customize according to your need.

Unable to USE tooltips when viewing svg code

I've searched around for several days and have not been able to find a solution to this issue. I'm generating highcharts with not problem. Inaddition, I'm using the below simple function to get the svg code for each chart.
function generateSVG (){
var svg_xml = $('#container').highcharts().getSVG();
document.getElementById('svg_code').innerHTML = svg_xml;
}
My issue is that with the chart originally generated by highcharts I am able to mouseover the chart and see tooltips. However, when I later embed the generated svg code, even with including all the external resources, the tooltips do not work - everything becomes like a static image. After inspecting the svg code extracted next to the code used to generate the initial chart, I noticed that the line of code which includes the tooltip class for highcharts was missing in the extracted code. Am I missing something here. Below is an example of one of the functions used to generate a chart.
function highArea(theD){
setHighSize();
var theData = theD;
$.get(theData, function(data) {
Highcharts.chart('chartDisplay', {
colors: ["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff"],
chart: {
type: "area",
useHTML: true
},
exporting: {
buttons: {
contextButton: {
enabled: false
}
}
},
title: {
text: chart_title
},
data: {
csv: data
},
title: {
text: chart_title
},
subtitle: {
text: ''
},
xAxis: {
allowDecimals: false,
labels: {
formatter: function () {
return this.value;
}
}
},
yAxis: {
title: {
text: some_label
},
},
tooltip: {
pointFormat: '{series.name} <b>{point.y:,.0f}</b><br/> {point.x}'
},
plotOptions: {
area: {
marker: {
enabled: true,
symbol: 'circle',
radius: 2,
states: {
hover: {
enabled: true
}
}
}
}
}
});
generateSVG();
});
}
Is what I'm trying to do even possible? I would really appreciate any feedback on this matter.
Thanks :)

Highcharts Stacked Percentage Column Hyperlink

I have a Stacked % Column Highchart which without Hyperlinks on data sets works perfectly, however I need to link away to another page from the chart, If it was a standard column chart, I would have no issue (I have one already). But i cannot seem to work out why I'm getting an undefined error on the link.
Ive searched around for a working example but havent been able to find one matching the stacked percentage column.
I've setup a fiddle to indicate where im up to, any help appreciated.
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Space Overview'
},
xAxis: {
categories: ['a', 'b', 'c', 'd']
},
yAxis: {
min: 0,
title: {
text: 'Total Space (%)'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.percentage:.0f}%)<br/>',
shared: true
},
plotOptions: {
column: {
stacking: 'percent'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
location.href = this.options.url;
}
}
}
}
},
subtitle: {
text: '+ Items relate to items in the dispay cabinets.',
align: 'left',
x: 10
},
series: [{
name: 'Free',
data: [1498, 1123, 556, 1176],
url: ['Spaces.aspx?box=a', 'Spaces.aspx?box=b', 'Spaces.aspx?box=c', 'Spaces.aspx?box=d']
}, {
name: 'Used',
data: [1234,233,23,759],
url: ['Spaces.aspx?box=a', 'Spaces.aspx?box=b', 'Spaces.aspx?box=c', 'Spaces.aspx?box=d']
}]
});
http://jsfiddle.net/Mooglekins/qv8z5a2o/
This is a great question! I did some digging and think I've found a good solution for you.
First, I needed to update how you defined the custom value in your series. To capture certain values in events, I moved the url attribute within each data point. So now, each point has their y value and the new url value.
(Note: I used dummy URLs here since I wouldn't be able to connect to the ones you provided outside your website.)
series: [{
name: 'Free',
data: [
{ y: 1498, url: 'http://www.google.com' },
{ y: 1123, url: 'http://www.yahoo.com' },
{ y: 556, url: 'http://www.bing.com' },
{ y: 1176, url: 'http://www.msn.com' }
]
}, {
// second series here
}
]
Next, I updated your events call. Now that we've moved the url attribute to each point, we can refer to that value as point.url (as you could the y value using point.y).
What I also did here is use window.open vs. window.location. This will be a better experience for your users so they don't lose sight of the chart. Keep this if you wish.
plotOptions: {
column: {
stacking: 'percent'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function (event) {
window.open(event.point.url);
}
}
}
}
}
Here's your updated fiddle with these changes: http://jsfiddle.net/brightmatrix/qv8z5a2o/5/
I hope this helps!

Optimize JavaScript DrillDown code

I have a drilldown map on my page which I would like to optimise.
Right now I am loading every "drilldown" map even if it is not clicked.
Here is an example that shows how the data is load if the state is clicked.I would like to achieve that.
But this is my code and as you can see, I am loading all drilldown jsons even if the map is not clicked. In my example I have only 2 drilldown option, but in my real life problem I have it like 15 so it really slows down a little bit everything.
So this is my code:
// get main map
$.getJSON('json/generate_json_main_map.php', function(data) {
// get region 1 map
$.getJSON('json/generate_json_region_1.php', function(first_region) {
// get region 2 map
$.getJSON('json/generate_json_region_2.php', function(second_region) {
// Initiate the chart
$('#interactive').highcharts('Map', {
title: {
text: ''
},
colorAxis: {
min: 1,
max: 10,
minColor: '#8cbdee',
maxColor: '#1162B3',
type: 'logarithmic'
},
series: [{
data: data,
"type": 'map',
name: st_ponudb,
animation: {
duration: 1000
},
states: {
//highlight barva
hover: {
color: '#dd4814'
}
}
}],
drilldown: {
drillUpButton: {
relativeTo: 'plotBox',
position: {
x: 0,
y: 0
},
theme: {
fill: 'white',
'stroke-width': 0,
stroke: 'white',
r: 0,
states: {
hover: {
fill: 'white'
},
select: {
stroke: 'white',
fill: 'white'
}
}
}
},
series: [{
id: 'a',
name: 'First',
joinBy: ['hc-key', 'code'],
type: 'map',
data: first_region,
point: {
events: {
click: function() {
var key = this.key;
location.href = key;
}
}
}
}, {
id: 'b',
name: 'Second',
joinBy: ['hc-key', 'code'],
type: 'map',
data: second_region,
point: {
events: {
click: function() {
var key = this.key;
location.href = key;
}
}
}
}]
}
});
});
});
});
JSON from generate_json_main_map.php:
[{"drilldown":"a","name":"region 1","value":"1","path":""},{"drilldown":"b","name":"region 2","value":"2","path":""}]
JSON from generate_json_region_1.php:
[{"name":"Place 1","key":"place.php?id=1","value":"1","path":""},{"name":"Place 2","key":"place.php?id=2","value":"2","path":""}]
This is my attempt to make ajax calls load in parallel, but the map is not loading, I get just the coloraxis.
$(function() {
$.when($.getJSON('json/generate_json_main_map.php'), $.getJSON('json/generate_json_region_1.php'), $.getJSON('json/generate_json_region_2.php')).done(function(data,first_region,second_region){
$('#interactive').highcharts('Map', {
title: {
text: ''
},
colorAxis: {
min: 1,
max: 10,
minColor: '#8cbdee',
maxColor: '#1162B3',
type: 'logarithmic'
},
series: [{
data: data,
"type": 'map',
name: st_ponudb,
animation: {
duration: 1000
},
states: {
hover: {
color: '#dd4814'
}
}
}],
drilldown: {
drillUpButton: {
relativeTo: 'plotBox',
position: {
x: 0,
y: 0
},
theme: {
fill: 'white',
'stroke-width': 0,
stroke: 'white',
r: 0,
states: {
hover: {
fill: 'white'
},
select: {
stroke: 'white',
fill: 'white'
}
}
}
},
series: [{
id: 'a',
name: 'First',
joinBy: ['hc-key', 'code'],
type: 'map',
data: first_region,
point: {
events: {
click: function() {
var key = this.key;
location.href = key;
}
}
}
}, {
id: 'b',
name: 'Second',
joinBy: ['hc-key', 'code'],
type: 'map',
data: second_region,
point: {
events: {
click: function() {
var key = this.key;
location.href = key;
}
}
}
}]
}
});
});
});
I can see that the jsons are loaded and there is no JS error shown by firebug.
If you want to load on click, you need to call the state data on click_event (and not at startup).
Just like your JSFiddle example:
chart : {
events: {
drilldown: function (e) {
// Load you data
// show it with chart.addSeriesAsDrilldown(e.point, {...});
}
}
}
Or as #Whymarrh suggests, you can load them all in parallel (instead of one after the other) and once they are all retrieved, compute your map.
See https://lostechies.com/joshuaflanagan/2011/10/20/coordinating-multiple-ajax-requests-with-jquery-when/ for example on how to execute a code after all ajax calls have completed.
When you load your map data as you did, in the following manner:
$.when(
$.getJSON('json/generate_json_main_map.php'),
$.getJSON('json/generate_json_region_1.php'),
$.getJSON('json/generate_json_region_2.php')
).done(...);
The effect is this - when any of the three requests fail, all promises will be rejected and ultimately, your map never gets to be initialised.
A better approach could be to request all data independently, and the outcomes would be handled as follows:
If the request for the main data fails, abort the other requests unconditionally (there would be no need for a drill down if the primary data is non-existent).
If request for main data succeeds, you may go on and initialise the map as data becomes available. The request for drill down data may or may not succeed though (but half bread is better than none?). Assuming everything goes well, then in the event that user initiates a drill down action, you show a loading message and ultimately add the drill down series when it becomes available.
Here's an implementation of the method I offered:
$(function () {
// immediately trigger requests for data
var loadMainData = $.getJSON("json/generate_json_main_map.php");
var loadRegionData = {
"region-1-name": $.getJSON("json/generate_json_region_1.php"),
"region-2-name": $.getJSON("json/generate_json_region_2.php")
};
// region drilldown options
var regionalSeriesOptions = {
"region-1-name": {
id: 'a',
name: 'First',
joinBy: ['hc-key', 'code'],
type: 'map',
point: {
events: {
click: function () {
var key = this.key;
location.href = key;
}
}
}
},
"region-2-name": {
id: 'b',
name: 'Second',
joinBy: ['hc-key', 'code'],
type: 'map',
point: {
events: {
click: function () {
var key = this.key;
location.href = key;
}
}
}
},
// ...
"region-(n-1)-name": {
// series options for region 'n-1'
},
"region-n-name": {
// series options for region 'n'
},
"region-(n+1)-name": {
// series options for region 'n+1'
}
};
// main options
var options = {
title: {
text: ""
},
series: [{
type: "map",
name: st_ponudb,
animation: {
duration: 1000
},
states: {
hover: {
color: "#dd4814"
}
}
}],
events: {
drilldown: function (e) {
var regionName, request, series, chart;
if (e.seriesOptions) {
// drilldown data is already loaded for the currently
// selected region, so simply return
return;
}
regionName = e.point.name;
request = loadRegionData[regionName];
series = regionalSeriesOptions[regionName];
chart = this;
chart.showLoading("Loading data, please wait...");
request.done(function (data) {
// series data has been loaded successfully
series.data = data;
chart.addSeriesAsDrilldown(e.point, series);
});
request.fail(function () {
if (loadMainData.readyState !== 4) {
// do you really want to cancel main request
// due to lack of drilldown data?
// Maybe half bread is better than none??
loadMainData.abort();
}
});
// whether success or fail, hide the loading UX notification
request.always(chart.hideLoading);
}
},
colorAxis: {
min: 1,
max: 10,
minColor: '#8cbdee',
maxColor: '#1162B3',
type: 'logarithmic'
},
drilldown: {
drillUpButton: {
relativeTo: 'plotBox',
position: {
x: 0,
y: 0
},
theme: {
fill: 'white',
'stroke-width': 0,
stroke: 'white',
r: 0,
states: {
hover: {
fill: 'white'
},
select: {
stroke: 'white',
fill: 'white'
}
}
}
},
series: []
}
};
loadMainData.done(function (data) {
options.series[0].data = data;
$("#interactive").highcharts("Map", options);
}).fail(function () {
Object.keys(loadRegionData).forEach(function (name) {
// if primary data can't be fetched,
// then there's no need for auxilliary data
loadRegionData[name].abort();
});
});
});
Since I don't know every detail of your code, it's left for you to find a way to fit it into your solution.

Categories