I search for a way to display a tooltip permanently:
click on the point --> tooltip is cloned and displayed permanently
if you click on the same point again, the clone is removed
multiple tooltips are allowed to be displayed at the same time
Most of the things I got to work but there are some little issues that needs to be fixed:
http://jsfiddle.net/jtnDz/1/
$(function () {
cloneToolTip = null;
checkx = [];
checky = [];
clone = [];
del = [];
chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
//check if point was already clicked
if (checkx.indexOf(event.point.x) >= 1 & checky.indexOf(event.point.y) >= 1) {
//remove tooltip
chart.container.firstChild.removeChild(clone[checkx.indexOf(event.point.x)]);
//remove xy coordinate and clone from array --> tooltip can be displayed again
/*del=checkx.indexOf(event.point.x);
clone.splice(del, 1);
checky.splice(del, 1);
checkx.splice(del, 1);*/
}
//cloneToolTip=null;
if (checkx.indexOf(event.point.x) == -1 & checky.indexOf(event.point.y) == -1) {
cloneToolTip = this.series.chart.tooltip.label.element.cloneNode(true);
chart.container.firstChild.appendChild(cloneToolTip);
//save coordinates and tooltip object
checkx.push(event.point.x);
checky.push(event.point.y);
clone.push(cloneToolTip);
}
}
}
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
});
My problems are:
the first selected tooltip, i.e. its clone, cannot be removed
When a clone is removed, you cannot display the tooltip again permanently. I tried to remove the corresponding entries in all three arrays (commented code block) but then none of the clones is removed after this correction
I'm really a beginner and google a lot to find examples but this problem I could not fix on my own. Can someone give me a hint?
Thanks!
The problem is with value returned from inArray(). It will return index of array, so it start from 0, while your if statement comapres with 1.
Also, I have made some other changes (otherwise in Chrome I get some errors). Example: http://jsfiddle.net/7vkZV/
Related
I am trying to create a custom button next to legend as per below use-case:
1) button right of horizontal legend
2) button below vertical legend
JS Fiddle Link
Using chart renderer, I can add the button on chart but its coordinates are fixed. It is rendered as rectangle on chart (got to know after inspecting button using developer tools). Is there any way I can always keep this custom button next to any element inside chart, in my case, next to legend.
chart.renderer.button(...); // code inside jsfiddle link
Use lagend labelFormatter with useHTML:true to add button next to It.If You are using vertical legend you can add line break in legend labelFormatter
var chart;
chart=new Highcharts.chart('container', {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
legend: {
useHTML:true,
labelFormatter: function () {
return this.name + ' (click to hide) <button onclick="buttonAction()">Button Action</button>';
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
function buttonAction(){
if(chart.series[0].visible==true){ //button click will interfere with legend text click
chart.series[0].visible=false
}else{
chart.series[0].visible=true
}
console.log('button clicked')
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
I want to indicate presence of null value in the graph.
I thought of replacing null with 0 but then, it would connect with rest of the real data and will draw incorrect graph. Is it possible to not connect zero value with rest of data points?
Alternatively, is it possible to indicate null value using plotband over it like shown in the image?
jsfiddle
var categoryText= ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Highcharts.stockChart('container',{
chart: {
defaultSeriesType: 'spline',
renderTo: 'container'
},
xAxis: {
labels: {
formatter: function() {
return categoryText[this.value];
}
}
},
plotOptions: {
series: {
marker: {
enabled: true
}
}
},
series: [{
data: [29.9, null, 106.4, 129.2, 144.0, 176.0, null, 148.5, 216.4, 194.1, 95.6, 54.4],
}]
});
If you have data declared above, then you can try this to include plot bands only for the nulls. I tried adjusting the offset of each tick to the middle of month but it seems a little inaccurate. Please adjust to your liking. Check out the fiddle.
plotBands: data.map(function(item, index) {
return { color: 'orange', from: index-0.5, to: index+0.5, data: item }
}).filter(function(item) { return item.data === null})
},
http://jsfiddle.net/95dLon47/3/
I'm using HighCharts Pattern Fill plugin to apply different patterns for each data bar in a Bar chart. Look at this fiddle: http://jsfiddle.net/ravinsp/tme364td/
var rawdata = [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4];
var datapoints = new Array();
for (var i = 0; i < 12; i++) {
datapoints.push({
y: rawdata[i],
color: 'url(#highcharts-default-pattern-' + (i % 10) + ')'
});
}
$('#container').highcharts({
chart: {
type: 'bar',
height: 50 * 12
},
title: {
text: 'Export and resize to see the issue'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: datapoints
}]
});
In Chrome only, if I Export the chart and then attempt to resize the chart, the pattern bars disappear. They are still there in the DOM svg but just not visually rendered. The actual exported image is correct. This only happens in Chrome. No issues on Firefox and IE Edge.
This only occurs if you use individual colors for each data point. This issue does not occur in charts with a single pattern for the entire series (eg. http://jsfiddle.net/9KtwA/1/).
Have anybody else encountered this issue?
In my chart I am combining a class together with datalables of each series.
At some point I am hiding datalables of one series. But If now I show/hide any other series, the hided datalables appears.
I made a jsfiddle example. Do the following steps to see my meaning:
1. click on button 1 to hide datalables on series1
2. Hide series 2
Now the datalables on series 1 shows up. How can I stop this behavior?
jsfiddle link: http://jsfiddle.net/jmogexfj/2/
$(function () {
button1();
$('#container').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
useHTML: true,
formatter: function () {
return '<div class="label_'+this.series._i+'">' + this.y + '</div>';
}
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
},
{
data: [10.9, 50.5, 60.4, 100.2, 104.0, 106.0, 120.6, 108.5, 106.4, 104.1, 90.6, 50.4]
}]
});
});
function button1(){
$("#b1").click(function(){
$(".label_0").toggle();
});
}
That's how Highcharts library works. When you update chart (like hiding by legend, resizing window browser etc.), elements are redrawn.
To hide dataLabels, use series.update():
$('#container').highcharts().series[0].update({
dataLabels: {
enabled: false
}
});
Demo: http://jsfiddle.net/jmogexfj/4/
If you really need to use classes, then use chart.events.redraw to show/hide dataLabel on each redraw: http://jsfiddle.net/jmogexfj/5/
Highcharts example:
chart: {
events: {
redraw: function () {
var showOrHide = display ? 'show' : 'hide';
$(".label_0")[showOrHide]();
}
}
},
Click button:
function button1() {
$("#b1").click(function () {
display = !display;
$(".label_0").toggle();
});
}
When we hover on may In example, we don't see tooltip for this month, because data is null. Can I set the settings to see the tooltip when data is null?
Well as far as I know there is no generic option for that since highcharts ignores null values from showing.
On the other hand, we can replace the null points with "fake" ones, that have an average value between the 2 closest points (this will cause the chart flow remain the same), and with a custom property isNull which can be used as a flag later.
After doing that, we can use a formatter function for the tooltip, and manipulate the tooltip the way we want, for example displaying only the series name when a point isNull.
$(function () {
$('#container').highcharts({
title: {
text: 'The line is connected from April to Juni, despite the null value in May'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
connectNulls: true
}
},
tooltip: {
formatter: function(){
if(this.point.isNull == undefined)
return this.series.name+"<br>"+"<b>value:</b>"+this.y;
return this.series.name;
}
},
series: [{
data: [null, 71.5, 106.4, 129.2, null, 176.0, 135.6, null, 216.4, 194.1, 95.6, 54.4]
}]
}, function(chart){
var series = chart.series[0];
var data = series.data;
$.each(data,function(i){
var point = data[i];
var prevPoint = data[i-1] != undefined ? data[i-1].y : 0;
var nextPoint = data[i+1] != undefined ? data[i+1].y : 0;
if(point.y == null){
series.addPoint({x:point.x,y:(prevPoint+nextPoint)/2, isNull:true});
}
});
});
});
http://jsfiddle.net/zb5ksxtc/1/
I hope this is what you meant.
UPDATE
We can also do something not less hacky... (I guess a little hacking could work fine in this unusuall case)
What I did here was creating a "fake" scatter series, with points located where null values from the real series (used same average logic).
The series has hidden markers, and has a unique name.
After that, I used a shared tooltip and a formatter to display the right tooltip.
I used the name attribute to determine what series is focused:
$(function () {
$('#container').highcharts({
title: {
text: 'The line is connected from April to Juni, despite the null value in May'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
plotOptions: {
series: {
connectNulls: true,
},
},
tooltip: {
shared:true,
formatter: function(){
var points = this.points;
var seriesName = points[0].series.name;
if(seriesName == 'fake')
return "Null tooltip";
return seriesName+"<br>value: <b>"+this.y+"</b>";
}
},
series: [{
type:'areaspline',
data: [null, 71.5, 106.4, 129.2, null, 176.0, 135.6, null, 216.4, 194.1, 95.6, 54.4]
},
{
type:'spline',
lineWidth:0,
name:'fake',
showInLegend:false,
marker:{
symbol:'circle',
radius:0,
}
}
]
}, function(chart){
var series = chart.series[0];
var fake_series = chart.series[1];
$.each(series.data, function(i){
var point = this;
var nextPoint = series.data[i+1] != undefined ? series.data[i+1].y : 0;
var prevPoint = series.data[i-1] != undefined ? series.data[i-1].y : 0;
if(series.data[i].y == null)
fake_series.addPoint([series.data[i].x, (nextPoint+prevPoint)/2]);
});
});
});
and the fiddle ofcourse: http://jsfiddle.net/zb5ksxtc/8/