How to change event (hover & click) on legend item in highcharts? - javascript

You can see point value in the pie center if you are hovering chart points. Also you can see total value if you stop hovering chart point. It'd like the same behavior, if you're hovering legend item.
const chart = Highcharts.chart('container', {
chart: {
type: 'pie',
events: {
load: function(){
this.title.attr({text: this.series[0].total});
},
render: function() {
this.series && this.title.attr({y: this.plotHeight / 2 + this.plotTop + 5});
}
}
},
title: {
text: ''
},
legend: {
enabled: true,
},
plotOptions: {
pie: {
showInLegend: true,
innerSize: '50%',
dataLabels: {
enabled: false
},
point: {
events: {
mouseOver: function() {
this.series.chart.title.attr({text: this.y});
},
mouseOut: function(){
this.series.chart.title.attr({text: this.total});
},
}
}
}
},
series: [{
name: 'Brands',
colorByPoint: true,
data: [{
name: 'Microsoft Internet Explorer',
y: 56.33
}, {
name: 'Chrome',
y: 24.03,
}, {
name: 'Firefox',
y: 10.38
}]
}]
});
https://jsfiddle.net/q5fh1nog/24/
Also I want that clicking on active legend item will recalculate total value and show it in the center

You can add mouseover and mouseout event listeners on legend's elements and update the title in the same way as in point's events listeners. For example:
chart: {
type: 'pie',
events: {
load: function() {
const series = this.series[0];
this.title.attr({
text: this.series[0].total
});
series.points.forEach(point => {
['label', 'symbol'].forEach(prop => {
point.legendItem[prop].on('mouseover', () => {
series.chart.title.attr({
text: point.y
});
});
point.legendItem[prop].on('mouseout', () => {
series.chart.title.attr({
text: point.total
});
});
});
});
},
...
}
}
Live demo: https://jsfiddle.net/BlackLabel/kq9vL7so/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#on

Related

How can I show only one x-axis in synchronous chart highchart

$('#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);
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
Highcharts.Point.prototype.highlight = function (event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
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
$.getJSON(
'https://cdn.rawgit.com/highcharts/highcharts/v6.0.4/samples/data/activity.json',
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 {
// right aligned
x: this.chart.chartWidth - this.label.width,
y: 10 // 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
}
}]
});
});
}
);
Any help will be appreciated
You can hide unwanted x axes using visible property:
xAxis: {
visible: i === 2,
(...)
},
Live demo: http://jsfiddle.net/BlackLabel/abf07jgc/
API reference: https://api.highcharts.com/highcharts/xAxis.visible

add drag option Polar in Echarts by baidu

I'm using Echarts by Baidu 3.0 and I'm wondering if it is possible to add drag option to a polar chart.
The drag option is explained here I could use it only with the scatter chart.
Here is the Polar chart example.
thanks
I have no experience over ECharts, but I like to hack codes :P and this was fun (took me an hour).
So, I modified this example for you. Now you can drag stuff around.
Here is the code:
var hours = ['12a', '1a', '2a', '3a', '4a', '5a', '6a',
'7a', '8a', '9a','10a','11a',
'12p', '1p', '2p', '3p', '4p', '5p',
'6p', '7p', '8p', '9p', '10p', '11p'];
var days = ['Saturday', 'Friday', 'Thursday',
'Wednesday', 'Tuesday', 'Monday', 'Sunday'];
var data = [[0,0,5],[0,1,1],[0,2,0],[0,3,0],[0,4,0],[0,5,0],[0,6,0],[0,7,0],[0,8,0],[0,9,0],[0,10,0],[0,11,2],[0,12,4],[0,13,1],[0,14,1],[0,15,3],[0,16,4],[0,17,6],[0,18,4],[0,19,4],[0,20,3],[0,21,3],[0,22,2],[0,23,5],[1,0,7],[1,1,0],[1,2,0],[1,3,0],[1,4,0],[1,5,0],[1,6,0],[1,7,0],[1,8,0],[1,9,0],[1,10,5],[1,11,2],[1,12,2],[1,13,6],[1,14,9],[1,15,11],[1,16,6],[1,17,7],[1,18,8],[1,19,12],[1,20,5],[1,21,5],[1,22,7],[1,23,2],[2,0,1],[2,1,1],[2,2,0],[2,3,0],[2,4,0],[2,5,0],[2,6,0],[2,7,0],[2,8,0],[2,9,0],[2,10,3],[2,11,2],[2,12,1],[2,13,9],[2,14,8],[2,15,10],[2,16,6],[2,17,5],[2,18,5],[2,19,5],[2,20,7],[2,21,4],[2,22,2],[2,23,4],[3,0,7],[3,1,3],[3,2,0],[3,3,0],[3,4,0],[3,5,0],[3,6,0],[3,7,0],[3,8,1],[3,9,0],[3,10,5],[3,11,4],[3,12,7],[3,13,14],[3,14,13],[3,15,12],[3,16,9],[3,17,5],[3,18,5],[3,19,10],[3,20,6],[3,21,4],[3,22,4],[3,23,1],[4,0,1],[4,1,3],[4,2,0],[4,3,0],[4,4,0],[4,5,1],[4,6,0],[4,7,0],[4,8,0],[4,9,2],[4,10,4],[4,11,4],[4,12,2],[4,13,4],[4,14,4],[4,15,14],[4,16,12],[4,17,1],[4,18,8],[4,19,5],[4,20,3],[4,21,7],[4,22,3],[4,23,0],[5,0,2],[5,1,1],[5,2,0],[5,3,3],[5,4,0],[5,5,0],[5,6,0],[5,7,0],[5,8,2],[5,9,0],[5,10,4],[5,11,1],[5,12,5],[5,13,10],[5,14,5],[5,15,7],[5,16,11],[5,17,6],[5,18,0],[5,19,5],[5,20,3],[5,21,4],[5,22,2],[5,23,0],[6,0,1],[6,1,0],[6,2,0],[6,3,0],[6,4,0],[6,5,0],[6,6,0],[6,7,0],[6,8,0],[6,9,0],[6,10,1],[6,11,0],[6,12,2],[6,13,1],[6,14,3],[6,15,4],[6,16,0],[6,17,0],[6,18,0],[6,19,0],[6,20,1],[6,21,2],[6,22,2],[6,23,6]];
option = {
title: {
text: 'Punch Card of Github',
link: 'https://github.com/pissang/echarts-next/graphs/punch-card'
},
legend: {
data: ['Punch Card'],
left: 'right'
},
polar: {},
tooltip: {
formatter: function (params) {
return params.value[2] + ' commits in ' + hours[params.value[1]] + ' of ' + days[params.value[0]];
}
},
angleAxis: {
type: 'category',
data: hours,
boundaryGap: false,
splitLine: {
show: true,
lineStyle: {
color: '#999',
type: 'dashed'
}
},
axisLine: {
show: false
}
},
radiusAxis: {
type: 'category',
data: days,
axisLine: {
show: false
},
axisLabel: {
rotate: 45
}
},
series: [{
id: 'a', // I added an id like the other example
name: 'Punch Card',
type: 'scatter',
coordinateSystem: 'polar',
symbolSize: function (val) {
return val[2] * 2;
},
data: data,
animationDelay: function (idx) {
return idx * 5;
}
}]
};
if (!app.inNode) {
setTimeout(function () {
myChart.setOption({
graphic: echarts.util.map(data, function (item, dataIndex) {
// I could not get `myChart.convertToPixel` to work
// So I searched and found myChart._coordSysMgr._coordinateSystems[0].dataToPoint
// and also myChart._coordSysMgr._coordinateSystems[0].pointToData
return {
type: 'circle',
position: myChart._coordSysMgr._coordinateSystems[0].dataToPoint(item),
shape: {
cx: 0,
cy: 0,
// The size is based on the 3rd data
r: (item[2] * 2) / 2
},
invisible: true,
draggable: true,
ondrag: echarts.util.curry(onPointDragging, dataIndex),
onmousemove: echarts.util.curry(showTooltip, dataIndex),
onmouseout: echarts.util.curry(hideTooltip, dataIndex),
z: 100
};
})
});
}, 0);
window.addEventListener('resize', updatePosition);
}
myChart.on('dataZoom', updatePosition);
function updatePosition() {
myChart.setOption({
graphic: echarts.util.map(data, function (item, dataIndex) {
return {
position: myChart._coordSysMgr._coordinateSystems[0].dataToPoint(item)
};
})
});
}
function showTooltip(dataIndex) {
myChart.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: dataIndex
});
}
function hideTooltip(dataIndex) {
myChart.dispatchAction({type: 'hideTip'});
}
function onPointDragging(dataIndex, dx, dy) {
// Since our data are on a grid, we have to check if data changed before we
// update the graph for no reason
var newData = myChart._coordSysMgr._coordinateSystems[0].pointToData(this.position);
// If data not changed
if (newData[0] == data[dataIndex][0] && newData[1] == data[dataIndex][1]) return;
// Update only the position data (not the 3rd)
data[dataIndex][0] = newData[0];
data[dataIndex][1] = newData[1];
// Update data
myChart.setOption({
series: [{
id: 'a',
data: data
}]
});
}

Highcharts bar chart wont animate

Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart,
function initializeData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push({
name: setName($scope.jsondata[x].name),
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 5000);
}
function updateData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
console.debug("here");
for (x = 0; x < 5; x++) {
$scope.chart.series[0].data[x].update({
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'category',
labels: {
style: {
fontSize: '11px'
}
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Total Score',
align: 'high'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total Score <b>{point.y:.3f}</b>'
},
series: [{
name: 'Active Users',
data: [],
dataLabels: {
enabled: true,
rotation: 30,
style: {
fontSize: '10px',
fontFamily: 'Verdana, sans-serif'
},
format: '{point.y:.3f}', // one decimal
}
}]
});
And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference.
Some edits:
So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically).
function initializeData() {
$interval.cancel(mainInterval);
$scope.previousPackets = '';
$http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) {
var newdata = [];
var x = (new Date()).getTime();
for (var step = 9; step >= 0; step--) {
newdata.push([x - 1000 * step, 0]);
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 2000);
}
function updateData() {
$http.get(url + acronym + '/latest').success(function(returnedData) {
var x = (new Date()).getTime();
if ($scope.previousPackets != returnedData[0].numPackets) {
$scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true);
$scope.previousPackets = returnedData[0].numPackets;
} else {
$scope.chart.series[0].addPoint([x, 0], true, true);
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'areaspline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Packets'
},
plotLines: [{
value: 0,
width: 1,
color: '#d9534f'
}]
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Packets',
data: []
}]
});
I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little
function initializeChart(initialData, onload) {
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: onload
}
....
series: [{
name: 'Active Users',
data: initialData,
dataLabels: {
enabled: true,
format: '{point.y:.3f}', // one decimal
}
}]
});
}
function getData(callback) {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push([setName(ret[x].name), ret[x].data]);
}
callback(newdata);
});
}
As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart.
function readDataFirst() {
getData(function(newdata) {
initializeChart(newdata);
});
}
function initializeChartFirst() {
initializeChart([], function() {
getData(function(newdata) {
$scope.chart.series[0].setData(newdata);
})
});
}
The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible.
However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update
function forceAnimationByDoubleInitialization() {
getData(function(newdata) {
initializeChart([]);
var zerodata = newdata.map(function(item) {
return [item[0], 0]
});
$scope.chart.series[0].setData(zerodata);
$scope.chart.series[0].setData(newdata);
});
All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc

How to add multiple series dynamically and update its data dynamically

my task is to add series dynamically and keep updating their data, which is received by ajax calls.
i know series can be added dynamically by declaring highchart funciton global. and using series.addseries() function , and also data can be updated by using settimout request to ajax call and updating points by using series.addpoint() function.
i have done both the work separably. but when i combine both the technique, data is not added to highchart. i have done lot of research on this, and i am not finding reason for not adding the data. infact script hang the browser.
i have checked the series object, which show x-data and y-data are processed. only difference i find is isDirty field and isDirtydata field are set to true. dont know the reason.
here is the full code
var serverUrl = 'http://'+window.location.hostname+':8000'
Highcharts.setOptions({
global: {
useUTC: false
}
});
data={}
$(document).ready(function(){
$(function () {
console.log("highcharts")
$('#first').highcharts({
chart: {
type: 'spline',
//marginRight: 150,
marginBottom: 5,
events: {
load: requestData(data)
}
},
title: {
text: 'Server Monitroting Tool'
},
subtitle: {
text: 'Cpu usage, Memory Usage,Disk Usage,Mongo Usage'
},
xAxis: {
type: 'datetime',
categories: ['TIME'],
dateTimeLabelFormats : {
hour: '%I %p',
minute: '%I:%M %p'
}
},
yAxis:{
showEmpty:false
},
legend:
{
backgroundColor: '#F5F5F5',
layout: 'horizontal',
floating: true,
align: 'left',
verticalAlign: 'bottom',
x: 60,
y: 9,
shadow: false,
border: 0,
borderRadius: 0,
borderWidth: 0
},
series: {}
});
});
from_date=new Date().getTime()-60000;
function requestData(data)
{
if(!data)
{
console.log("default ")
}
else
{
console.log("requesting")
$.ajax({
url:serverUrl+'/api/fetch_params/',
type:'GET',
data:data,
success:function(response)
{
console.log("in success")
//data = {'type':TypeOfParameter,'hostname':hostname,'sub-type':sub_type,'param':sub_type_parameter,'from-date':from_date}
var id=data['sub-type']+data['param']
var series = chart.get(id)
shift = series.data.length > 100; // shift if the series is longer than 300 (drop oldest point)
response= $.parseJSON(response)
var x=data['sub-type']
all_data=response.response.data[x]
// console.log(new Date(from_date),'latest timestamp')
console.log(series)
console.log("data",all_data)
from_date=all_data[all_data.length-1][0]
// console.log(from_date)
// series.isDirty=false
// series.isDirtyData=false
for (var i = 0; i < all_data.length; i++)
{
series.addPoint({ x: all_data[i][0],y: all_data[i][1],id: i},false,shift);
}
console.log("series object",series)
// chart.redraw();
console.log(" parameter",data)
data['from-date']=from_date
console.log("data",series.data)
// console.log(chart)
setTimeout(requestData(data), 10000);
console.log("out of success")
},
cache:false,
error:function()
{
console.log("err")
}
});
}
}
$.ajax({
url:serverUrl+'/api/fetch_all_servers/',
type:'GET',
success:function(response){
response = $.parseJSON(response)
sd = response.response.all_servers
$('input[name=select_menue]').optionTree(sd)
},
error:function(){
console.log('error')
}
});
$('.param-button').live('click',function(e){
e.stopPropagation()
})
$('param-select').live('hover',function(){
$(this).find('.type-select').show()
});
$('.final_value').live('change',function(){
select_name = 'select_menue_'
param_list = []
var param=$('select[name="'+select_name+'"] option:selected').attr('value')
while(param){
param_list.push(param)
select_name += '_'
var param=$('select[name="'+select_name+'"] option:selected').attr('value')
}
console.log(param_list,"param_list")
from_date=new Date().getTime()-300000 //5 minute data
hostname=param_list[0]
TypeOfParameter= param_list[1]
sub_type_parameter=param_list[param_list.length-1]
data = {'type':TypeOfParameter,'hostname':hostname,'param':sub_type_parameter,'from-date':from_date}
var sub_type;
if(param_list.length==4){
sub_type=param_list[2]
data['sub-type'] = sub_type
}
else
{
sub_type=sub_type_parameter
}
// console.log(hostname,TypeOfParameter,sub_type,sub_type_parameter)
data = {'type':TypeOfParameter,'hostname':hostname,'sub-type':sub_type,'param':sub_type_parameter,'from-date':from_date}
requestData(data)
$('#loadingmessage').show(); // show the loading message.
chart = $('#first').highcharts();
if(TypeOfParameter=='cpu')
{
console.log("adding axis")
chart.addAxis({ // Primary yAxis
id:'Cpu_axis'+sub_type_parameter,
labels: {
formatter: function() {
return this.value;
},
style: {
color: '#89A54E'
}
},
title: {
text: "core "+ sub_type+ " "+sub_type_parameter,
style: {
color: '#89A54E'
}
},
lineWidth: 1,
lineColor: '#08F'
});
console.log("adding series")
chart.addSeries({
id:sub_type+sub_type_parameter,
name: "core "+sub_type+" "+sub_type_parameter,
data :[],
tooltip : {
valueSuffix: ' %'
},
yAxis:'Cpu_axis'+sub_type_parameter
})
console.log("series out")
}
if(TypeOfParameter=='memory')
{
chart.addAxis ({
id:'memory'+sub_type_parameter,
labels:{
formatter: function() {
return this.value +'%';
},
style: {
color: '#89C54F'
}
},
title: {
text:sub_type+" "+sub_type_parameter
},
lineWidth: .5,
lineColor: '#08F',
opposite: true
});
chart.addSeries({
id:sub_type+sub_type_parameter,
name: sub_type+'memory usage',
data: [],
tooltip: {
valueSuffix: '%'
},
yAxis:'memory'+sub_type_parameter
});
}
if(TypeOfParameter=='disk')
{
chart = new Highcharts.Chart({
chart: {
renderTo: 'second',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'disk Usage'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'disk',
margin: 80
}
},
series: [{
id:sub_type+sub_type_parameter,
name: 'disk',
data: []
}]
});
}
if(TypeOfParameter=='db')
{
chart = new Highcharts.Chart({
chart: {
renderTo: 'second',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'mongo Usage'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'mmongo',
margin: 80
}
},
series: [{
id:sub_type+sub_type_parameter,
name: 'mongo',
data: []
}]
});
}
if(TypeOfParameter=='redis')
{
chart = new Highcharts.Chart({
chart: {
renderTo: 'second',
defaultSeriesType: 'spline',
events: {
load: requestData
}
},
title: {
text: 'redis Usage'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
maxZoom: 20 * 1000
},
yAxis: {
minPadding: 0.2,
maxPadding: 0.2,
title: {
text: 'redis',
margin: 80
}
},
series: [{
id:sub_type+sub_type_parameter,
name: 'redis',
data: []
}]
});
}
$('#loadingmessage').hide(); // hide the loading message
}
)
});
i am stuck on this problem for quite a while. and still not able to figure out the solution.
here is the full code link
someone please please help. feeling frustrated ..:-(
As you know the addPoint method is bit dangerous when dealing with quite lots points. It is recommended to disable redraw per point when dealing with many new points - more info http://api.highcharts.com/highcharts#Series.addPoint() , I notice you are doing that already in the loop statement, but why did you commented out? have you tried enabling again. Make sure chart.redraw works by adding a new redraw chart event, and set an alert or console log.
Also you may try using, below as part of ajax, instead of cache:false. I had some problems in past.
headers: { 'Cache-Control': 'no-cache' }
Cheers

Highcharts + Highslide: When opening a new highslide popup or clicking anywhere else, close any previously opened popups

So, I discovered that when you have are utilizing highslides in conjuction with highcharts data, its possible to keep clicking new datapoints and have an endless number of modal windows pop up. I wanted to build something that will close an existing highslide popup window if you open a new highslide or if you click anywhere else, either on the screen or on a filter.
I wrote this little function and added it to my beginning statement but it did not work.
<body onclick="javascript:parent.window.hs.close();">
And here is my full example:
The question is, can someone show me an example where I can accomplish my above described behavior?
$(function () {
$('#container').highcharts({
chart: {
type: 'scatter',
zoomType: 'xy'
},
title: {
text: 'Q1 Eanings and Outlook Forecast',
x: -100
},
subtitle: {
text: 'professional',
x:-100
},
xAxis: {
title: {
enabled: false,
text: 'Future Outlook'
},
labels:{formatter: function() {} },
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
enabled:false,
text: 'Current Quarter'
},
labels: {
formatter: function() {
//return this.value + ' ';
}
},
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
// x: 100,
y: 70,
floating: false,
backgroundColor: '#FFFFFF',
borderWidth: 1
},
load: function() {
var legend = $('#container .highcharts-legend');
var x = legend.position().left;
var y = legend.position().top - (this.chartHeight - this.plotTop - this.plotHeight - this.options.chart.spacingBottom);
legend.attr({
transform: 'translate(' + x + ',' + y + ')'
});
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: true
}
}
},
tooltip: {
headerFormat: '<b>{series.name}:</b><br>',
pointFormat: '{point.hover}<br><br><b>Current Q: </b>{point.y}/100<br><b>Outlook: </b>{point.x}/100<br><br><div style="text-align:center;">(click for more detail)</div>'
},
cursor: 'pointer',
point: {
events: {
click: function(event) {
hs.htmlExpand(null, {
pageOrigin: {
x: this.pageX,
y: this.pageY
},
headingText: this.ticker,
maincontentText: '<b>Detail:</b> ' + this.info,
width: 250
});
hs.Expander.prototype.onBeforeClose = function(sender) {
}
},
}
},
events: {
legendItemClick: function(event) {
if (!this.visible)
return true;
var seriesIndex = this.index;
var series = this.chart.series;
for (var i = 0; i < series.length; i++)
{
if (series[i].index != seriesIndex)
{
series[i].visible ? series[i].hide() : series[i].show();
}
}
return false;
}
},
}
},
series: [{
name: 'Weak Outlook (24)',color: 'red',data: [
{x: 40,y:10,ticker:'Michael Kors: (KORS)',info: 'O,.pyjxkne<br>1Q xjkxqs', hover:'Gtext<br>1Qlotatt<br>read more'},
{x: 20,y:50,ticker:'Soeuoeuoeu',info:'Doeuoeuoeull...<br><br>read more'},
{x:0,y:0,ticker:'Zynga: (ZNGA)'},
{x:3,y:4,ticker:'Avid: (AVID)'},
{x:30,y:10,ticker:'JCPenny: (JCP)'},
{x:29,y:25,ticker:'Deckers Outdoor: (DECK)'},
{x:25,y:5,ticker:'Zynga: (ZNGA)'},
{x:6,y:34,ticker:'Avid: (AVID)'},
{x:8,y:27,ticker:'JCPenny: (JCP)'},
{x:14,y:35,ticker:'Deckers Outdoor: (DECK)'},
{x:35,y:23,ticker:'Nutrisystem Corp: (NTRI)'},
]},
{name:'Strong Outlook (25)',color:'green',data:[
{x:100,y:100,ticker:'The Gap: (GPS)'},
{x:72,y:82,ticker:'Sodastream Intl: (SODA)'},
{x:82,y:74,ticker:'Under Armour: (UA)'},
{x:71,y:90,ticker:'Intuitive Surgical: (ISRG)'},
{x:88,y:69,ticker:'McDonalds: (MCD)'},
{x:95,y:87,ticker:'Lumber Liquidators: (LL)'},
{x:77,y:91,ticker:'Apple: (AAPL)'},
{x:96,y:78,ticker:'Walgreen Company: (WAG)'}, {x:100,y:100,ticker:'The Gap: (GPS)'},
{x:73,y:72,ticker:'Sodastream Intl: (SODA)'},
{x:84,y:74,ticker:'Under Armour: (UA)'},
{x:91,y:80,ticker:'Intuitive Surgical: (ISRG)'},
{x:68,y:93,ticker:'McDonalds: (MCD)'},
{x:95,y:67,ticker:'Lumber Liquidators: (LL)'},
{x:76,y:67,ticker:'Apple: (AAPL)'},
{x:79,y:84,ticker:'Walgreen Company: (WAG)'},
]},
{name:'Inline Company Performance (23)',color:'darkgrey',data:[
{x:40,y:44,ticker:'GIII'},
{x:53,y:43,ticker:'BNNY'},
{x:55,y:49,ticker:'SNE'},
{x:57,y:58,ticker:'WTW'},
{x:60,y:60,ticker:'LULU'},
{x:70,y:66,ticker:'FB'},
{x:51,y:24,ticker:'GIII'},
{x:45,y:26,ticker:'FB'},
{x:43,y:53,ticker:'BNNY'},
{x:47,y:59,ticker:'SNE'},
{x:51,y:48,ticker:'WTW'},
{x:56,y:40,ticker:'LULU'},
{x:59,y:52,ticker:'FB'},
{x:0,y:100,ticker:'Nutrisystem Corp: (NTRI)'},
]},
]
});
});
If allowMultipleInstances is set to false, opened expanders will close when you click to open another. Add this right after the included highslide.config.js file:
<script type="text/javascript">
hs.allowMultipleInstances = false;
</script>

Categories

Resources