Flot event for range updates in response to panning/zooming - javascript

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);
};

Related

highcharts how to override reset zoom button event

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

Highcharts - how to get consistent mouseover and mouseout events for columns?

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).

Mouse over event and cursor pointer on the line series

I have the following implementation and it is functional. When user clicks on the line series, then it loads another data.
I want to give an impression to the first time user that line series clickable with implementing mouse over event and cursor: pointer.
var isHover=false;
function onClick (e) {
if (!isHover) {
var chart = $("#chart").data("kendoChart");
chart.options.series =[{data: stats2,name:stats2[0].name}] ;
chart.redraw();
isHover = true;
}
else if (isHover) {
var chart = $("#chart").data("kendoChart");
chart.options.series = [{data: stats,name:stats[0].name}];
chart.redraw();
isHover = false;
}
}
FIDDLE
A bit hacky, but this should work on stroke as well as the path:
circle:hover,
path[stroke="#ff6800"]:hover { cursor:pointer; }
See: http://jsfiddle.net/3yhbyy2g/78/
But would be better to set a class here (since you are tying the mouseover to a certain color), but not sure how this would work in kendo.
And since it's a bit hard to hit the line, maybe it would be enough to leave it on the circle alone.

SAPui5 sap.viz.ui5.StackedColumn custom tooltip on data point

I am trying to implement a custom tooltip in a sap viz stacked column chart. This is the small popup window that appears when the mouse hovers a datapoint. My problem is how to detect the position of the data point so that the tooltip popup points to it. Currently it always points to the graph itself, not the datapoint inside the graph.
Here's what I have:
graph = new sap.viz.ui5.StackedColumn({
width: graphWidth,
height : graphHeight,
//.. more properties here
interaction: new sap.viz.ui5.types.controller.Interaction({
decorations: [{name: "showDetail", fn: showDetailHandler}, {name: "hideDetail", fn:hideDetailHandler}]
}),
and the showDetailHandler is currently like this. It is supposed to display a popup pointing to the data point.
var showDetailHandler = function(oEvent){
var data = oEvent.data;
var offset = '0 0';
var tp3 = new sap.ui.ux3.ToolPopup({
content : [ new sap.ui.commons.Button({
text : "button"
}) ],
});
offset = '0 0';
offset = oEvent.position.x + " " + oEvent.position.y;
tp3.setPosition( sap.ui.core.Popup.Dock.CenterBottom,
sap.ui.core.Popup.Dock.CenterTop,
$(oEvent.container),
offset,
"none");
if (tp3.isOpen()) {
tp3.close();
} else {
tp3.open(sap.ui.core.Popup.Dock.CenterBottom, sap.ui.core.Popup.Dock.CenterTop);
}
};
The docs around this are here:
https://sapui5.hana.ondemand.com/sdk/#docs/api/symbols/sap.ui.core.Popup.html#setPosition
https://sapui5.hana.ondemand.com/sdk/docs/api/symbols/sap.viz.ui5.types.controller.Interaction.html#getDecorations
My understanding is that the offset is an offset to the point calculated by the anchor point. Problem is, offset is completely ignored. Popup always appears at the top of the graph.
However, the normal tooltip appears in the correct place.
Any idea/example?
Thank you in advance.

Highstock panning asynchronously loading data

Using Highstock is it possible to drag the chart and load the data asynchronously?
I've seen the async demo on the highcharts website http://jsfiddle.net/hcharge/5zPLV/
However this uses the navigator/scrollbar to move the chart along the series and loads the data when you stop sliding it along, Ideally I want to use the panning capability of highstock to move along instead of the navigator as it takes up too much space.
Playing around with the demo if I turn off the navigator and scrollbar and disable the zoomtype: x then as soon as you start dragging the chart it tries to fetch the data, making the chart unusable. Here is a fiddle of that http://jsfiddle.net/hcharge/6YSvk/
navigator: {enabled: false}, scrollbar: {enabled: false}
Ideally we'd need to know when the user starts dragging and when they stop then load the data.
Is this even possible to do? Thanks
I think this is possible, but it won't be easy.
As you wrote, you should start with detecting drag & drop. It's not possible using build-in options, but we can add our own event listeners. Take a look at this code:
new Highcharts.StockChart({
// here comes your chart options, but we can pass callback function as the second parameter
}, function (chart) {
var report = document.getElementById('report'), // just an element to display current extremes
xAxis = chart.xAxis[0],
startX;
function drag(e) {
e = chart.tracker.normalizeMouseEvent(e);
startX = e.chartX;
}
function drop(e) {
e = chart.tracker.normalizeMouseEvent(e);
var delta = e.chartX - startX,
extremes = xAxis.getExtremes(),
newMin = Math.round(extremes.min - delta),
newMax = Math.round(extremes.max - delta);
// display extremes retrieved by panning
report.innerHTML = "<b>From:</b> " + new Date(newMin) + " <b>to:</b> " + new Date(newMax);
}
// bind events
Highcharts.addEvent(chart.container, 'mousedown', drag);
Highcharts.addEvent(chart.container, 'mouseup', drop);
});
Simply we detect mouseDown & mouseUp events, then calculate the difference, translate difference to x data and finally, substract difference from extremes.
Here you can find the jsfiddle demo with code posted above: http://jsfiddle.net/dSEAA/1/
To make #slawekkolodziej's example work, you need to translate the delta into ms on the xAxis, then update the xAxis extremes like so:
window.chart = new Highcharts.StockChart({
// chart options go here
}, function(chart) {
var xAxis = chart.xAxis[0],
startX;
function drag(e) {
e = chart.pointer.normalize(e);
startX = e.chartX;
}
function drop(e) {
e = chart.pointer.normalize(e);
var delta = e.chartX - startX,
extremes = xAxis.getExtremes(),
deltaMs = (extremes.max - extremes.min) / chart.plotWidth * delta,
newMin = Math.round(extremes.min - deltaMs),
newMax = Math.round(extremes.max - deltaMs);
xAxis.setExtremes(newMin, newMax)
}
Highcharts.addEvent(chart.container, 'mousedown', drag);
Highcharts.addEvent(chart.container, 'mouseup', drop);
});
});
Here's a working example with async data loading: http://jsfiddle.net/xw7goLj4/5/

Categories