I'm using multiple highChart in a dashboard page e.g linearea, spline, pie and synchronisation of multiple charts
Set tooltip synchronisation for prototype
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
Highcharts.Point.prototype.highlight = function (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
};
But above function effect all highchart e.g linearea and spline chart etc. what I want to apply on synchronisation only
Refer to this live demo: http://jsfiddle.net/kkulig/eec3mg9t/
I put every chart to a separate container - it's easier to manipulate them then. class="sync" indicates that chart should be synchronized:
<div id="container0"></div>
<div id="container1" class="sync"></div>
<div id="container2" class="sync"></div>
Then I set common events using this class:
$('.sync').bind('mousemove touchmove touchstart', function(e) {
(...)
I applied wrapping instead of overwriting for Highcharts.Pointer.prototype.reset function so that the default action fires for unsynchronized charts.
// Custom wrap
Highcharts.wrap(Highcharts.Pointer.prototype, 'reset', function(proceed, allowMove, delay) {
if (!this.chart.options.chart.isSynchronized) {
proceed.apply(this, allowMove, delay);
}
});
Related
There are 2 charts and 1 common legend in one page. This legend is clickable to show/hide graph line of charts. This is forked this question.
I had tried to update data above code. It's an unrefined way, but i've been able to update the chart. "The legend" text will hide/show a line chart in here.
However after the update data, this toggle function is not work.
Please try here.
Click "The legend", it show and hide graph line --->OK
Click "ChangeData" button, graph line will be changed --->OK
Click "The legend" again, does not disappear graph line -->NG
First, it call the DrawChart function, which draws the data for the argument.
window.onload = function () {
DrawChart(data_A1, data_B1);
clickableCommonLegend();
}
The DrawChart function draw line chart by typical method of ChartJS.
function DrawChart(data_A, data_B) {
var ctxA = document.getElementById("myChartA").getContext("2d");
var ctxB = document.getElementById("myChartB").getContext("2d");
myChartA = new Chart(ctxA, {
type: 'line',
data:{.....
options:{....
});
myChartB = new Chart(ctxB, {
type: 'line',
data:{.....
options:{....
});
The clickableCommonLegend() is forked from this question.
On click button function that calls "changeData()".
This function execute destroy charts and reCall "DrawChart"
function changeData() {
myChartA.destroy();
myChartB.destroy();
DrawChart(data_A2, data_B2);
myChartA.update();
myChartB.update();
clickableCommonLegend();
}
I guess that destroy() delete all context of and re-define context by document.getElementById("myChartA")... in DrawChart().
I think it wii work fine, but result is not.
in clickableCommonLegend,
var legendItems = document.querySelector('.legend').innerHTML = myChartA.generateLegend();
Does legendItems removed from chart.destroy?
But I call it again.
I'm grad if you let me know what is wrong.
Current code is present here.
I've found a solution.
Change changeData() function
function changeData() {
// ---NOT WORK---
// myChartA.destroy();
// myChartB.destroy();
// DrawChart(data_A2, data_B2);
// --- OK ---
myChartA.data.datasets[0].data = data_A2;
myChartB.data.datasets[0].data = data_B2;
myChartA.update();
myChartB.update();
clickableCommonLegend();
}
Is there a way to override the reset zoom button click event in highcharts? When I click the reset zoom button, I want the chart to display the specific interval using setExtremes instead of zooming out the whole chart.
you can capture it in the selection property of your chart object. Just use the setExtremes()function with where you want to zoom, and a timeout of 0ms so that the graph's 'reset graph' function doesn't overwrite it.
chart: {
events: {
selection: function(event) {
if (!event.xAxis) {
setTimeout(function(){chart.xAxis[0].setExtremes(0, 5)}, 0);
}
}
...
}
working example: http://jsfiddle.net/rhavelka/M7cfm/64/
edit: but make sure that you want to zoom in on that specific interval and essentially hiding data from the user (unless you have a scrollbar on the graph like this example)
You can overwrite default Chart.prototype.showResetZoom and provide your own logic in zoomOut function:
(function(H) {
H.Chart.prototype.showResetZoom = function() {
var chart = this,
defaultOptions = H.defaultOptions,
fireEvent = H.fireEvent,
lang = defaultOptions.lang,
btnOptions = chart.options.chart.resetZoomButton,
theme = btnOptions.theme,
states = theme.states,
alignTo = btnOptions.relativeTo === 'chart' ? null : 'plotBox';
function zoomOut() {
//chart.zoomOut(); // default action
chart.xAxis[0].setExtremes(3, 7); // new action
}
fireEvent(this, 'beforeShowResetZoom', null, function() {
chart.resetZoomButton = chart.renderer.button(
lang.resetZoom,
null,
null,
zoomOut,
theme,
states && states.hover
)
.attr({
align: btnOptions.position.align,
title: lang.resetZoomTitle
})
.addClass('highcharts-reset-zoom')
.add()
.align(btnOptions.position, false, alignTo);
});
}
})(Highcharts);
Live demo: http://jsfiddle.net/BlackLabel/ay0t2e9f/
Docs reference: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
I'm making charts using node.js and Chartist.js where I'm creating tooltips for the points using jQuery and CSS.
Now, the problem is the chart is being generated in the server and will always have the same root class ct-chart and same other classes as they are being generated by Chartist.js. Since I have multiple charts with my code, when I hover over a point on one chart it displays tooltips over all the charts rather than just that chart itself.
How can I fix this?
Here is my code:
var $tooltip = $('<div class="tooltip tooltip-hidden"></div>').appendTo($('.ct-chart'));
console.log($tooltip);
$(document).on('mouseenter', '.ct-point', function() {
var seriesName = $(this).closest('.ct-point').attr('ct:meta'),
value = $(this).attr('ct:value');
$tooltip.text(seriesName);
$tooltip.removeClass('tooltip-hidden');
});
$(document).on('mouseleave', '.ct-point', function() {
$tooltip.addClass('tooltip-hidden');
});
$(document).on('mousemove', '.ct-point', function(event) {
$tooltip.css({
left: event.offsetX - $tooltip.width() / 2,
top: event.offsetY - $tooltip.height() - 20
});
});
I think what's happening is that $tooltip variable contains a jquery array of all of your charts. So when you do $tooltip.removeClass('tooltip-hidden'); it is removing the class from all of them.
You need a way to distinguish between them - I'd suggest something like:
$(document).on('mouseenter', '.ct-point', function() {
var seriesName = $(this).closest('.ct-point').attr('ct:meta'),
value = $(this).attr('ct:value'),
index = $(this).index(); // get the index of the point
$tooltip.eq(index).text(seriesName);
$tooltip.eq(index).removeClass('tooltip-hidden'); // use the index to remove only one class
});
I haven't tested this, but I think it should work. You'll have to apply this across all of your code.
I built this little test to show that when you use "appendTo", that variable gets populated with all of those elements you targeted. https://jsfiddle.net/wvLy2enm/
You should see this in your console log as well.
How to get consistent mouseover and mouseout events for highcharts columns?
The issue can be replicated by hovering the mouse horizontally back and forth along the middle of the chart in this js fiddle
EDIT :
This issue has been resolved by the below accepted answer.
In addition, I recommend setting tooltip.shared to false, and plotOptions.column.stickyTracking to false.
tooltip:
shared: false
plotOptions:
column:
stickyTracking: false # Mouse events will occur on column vs surrounding area
point:
events:
mouseOut: onItemMouseOut
mouseOver: onItemMouseOver
states:
hover:
enabled: false # Removes default mouse over behavior.
In the screenshot, the arrows represent the mouse hovering back and forth along the middle of the chart. The expected behavior is that the currently hovered column will be full opacity.
This is how the mouse events are declared in the highcharts options configuration :
plotOptions:{
column:{
point: {
events: {
mouseOut: onItemMouseOut,
mouseOver: onItemMouseOver
},
},
states:{hover:{enabled:false}},
},
},
These are the mouse event handlers :
var onItemMouseOver = function(){
console.log('mouseover');
var chart = $('#container').highcharts();
var series = chart.get('series-1');
var currentItem = this;
// Reduce opacity of all columns besides currently hovered column.
for(var i=0; i<series.segments[0].length;i++){
var segment = series.segments[0][i];
if(segment!==currentItem){
segment.graphic.attr({opacity: 0.3});
}
}
}
var onItemMouseOut = function(){
console.log('mouseout');
var chart = $('#container').highcharts();
var series = chart.get('series-1');
var currentItem = this;
for(var i=0; i<series.segments[0].length;i++){
var segment = series.segments[0][i];
segment.graphic.attr({opacity: 1});
}
}
I'm using a custom tooltip style, I had some suspicion the tooltip is interfering with the normal mouse events.
How about simply setting the opacity of the item you mouse over to 1 along with the other items to 0.3:
if(segment!==currentItem){
segment.graphic.attr({opacity: 0.3});
} else {
segment.graphic.attr({opacity: 1});
}
Fiddle Example
This way the hovered column will be for sure highlighted. In some cases when moving to a new column the item you moved to would still have an opacity of 0.3 causing the seemingly inconsistent behaviour, this means that two mouseover events happened rather than a in-between mouseout. This can happen when you have mouse events happening nearly the same time and the elements being very close to as each other (or even overlapping).
For Flot, is there an event that fires after the user has completed panning or zooming using the mouse scroll wheel (after the range.xaxis.to/from and range.yaxis.to/from have settled)? I am trying to use the line below to update the selection on an overview plot after the user has panned or zoomed in the main plot, but am finding that either the update to the overview plot happens after panning or zooming(not both).
$("#plot").bind("mouseup scroll",updateOverviewSelection);
Edit: http://jsfiddle.net/apandit/nu2rr58h/9/
In the jsfiddle, I am unable to pan in the main plot and the cursor does not seem to change back to normal. The user can click and drag in the overview plot to make a selection, which leads to zooming in the main plot. I would also like to be able to allow the user to pan and zoom in the main plot and have the selection box in the overview plot updated; I am attempting to do this by binding the updateOverviewSelection method to the plot div for the scroll and mouseup events. Is there an event in Flot that fires every time the x- and y-axis limits are updated?
The solution to this issue is below. The issue was that setting the overview plot's selection(overview.setSelection(ranges);) was triggering the zoom method because it was bound to the plotselected event in the overview plot. At the end of the zoom method, the main plot was plotted, which was again calling the overview.setSelection(ranges); line in the updateOverviewSelection method. To prevent this ping-pong between the two methods/events, I added an updatingOverviewSelection flag.
http://jsfiddle.net/apandit/nu2rr58h/12/
var datasets = [[
[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]
],
[
[0,0],[-1,-1],[-2,-2],[-3,-3],[-4,-4],[-5,-5],[-6,-6],[-7,-7],[-8,-8],[-9,-9]
]];
var plot = $.plot("#plot",datasets,{
pan: {
interactive: true
},
zoom: {
interactive: true,
mode: "x"
}
});
var overview = $.plot("#overview",datasets,{
selection: {
mode: "xy"
}
});
var updatingOverviewSelection = false;
$("#plot").bind("plotpan plotzoom",updateOverviewSelection);
$("#overview").bind("plotselected", zoom);
function zoom(event,ranges) {
if(updatingOverviewSelection) {
updatingOverviewSelection = false;
}
else {
var options = plot.getOptions();
options.xaxes[0].min = ranges.xaxis.from;
options.xaxes[0].max = ranges.xaxis.to;
options.yaxes[0].min = ranges.yaxis.from;
options.yaxes[0].max = ranges.yaxis.to;
plot = $.plot("#plot",datasets,options);
}
};
// get the window x-axis and y-axis ranges for the main plot
// and set the selection in the overview plot to those ranges
function updateOverviewSelection(event) {
var options = plot.getOptions();
var ranges = {
xaxis: {
from: options.xaxes[0].min,
to: options.xaxes[0].max
},
yaxis: {
from: options.yaxes[0].min,
to: options.yaxes[0].max
}
};
updatingOverviewSelection = true;
overview.setSelection(ranges);
};