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

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

Related

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.

Flot event for range updates in response to panning/zooming

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

Updating fontsize with highcharts using zoomtype

I have a column chart in Highcharts with a big number of columns so the columns are very small.
That's fine but I want to do zoom.
So I used zoomtype: 'x' and it work well.
The problem is that I want to make the font bigger on the xAxis when they are selected.
I tried by doing this:
chart: {
type: 'column',
zoomType: 'x',
events: {
redraw: function(event) {
if(this.xAxis[0].tickPositions.length>80){
this.xAxis[0].options.labels.style.fontSize = 1;
}else{
this.xAxis[0].options.labels.style.fontSize = 20;
console.log(this.xAxis[0].options.labels.style.fontSize);
}
}
}
}
When I check the console the value of this.xAxis[0].options.labels.style.fontSize is updated to 20.
This code works only when I press the Reset zoom button.
So my question is how can I update the chart when the event is triggered so it takes the same effects as if I use the Reset zoom button?
Or how can I make changes in the font when I make zoom and when reseting the zoom?
You can catch afterSetExtremes event and then axis.update() with new styles for bales.
events:{
afterSetExtremes:function(){
this.update({
labels:{
style:{
fontSize:20
}
}
});
}
}
Example: http://jsfiddle.net/m180dxsu/

How to trigger click event on a bar in Flot Stacked Bar Chart?

I wanted to trigger the click event of the lowest bar of the first stacked bar in Flot.
The rationale for this is that I wanted to select this portion of the chart on first load and at the same time execute the onClick handler of the bar.
I know that jQuery supports this behavior but I just don't know how to integrate it with Flot.
How can it be done?
Thank you.
You need to trigger a plotclick event on the desired column's point passing the trigger the appropriate item.
For instance, say you want to click the 4th column of the first series:
var col = 4; // 4th column
var series = somePlot.getData()[0]; // first series
var dataIndex = col - 1;
ps = series.datapoints.pointsize;
var item = {
datapoint: series.datapoints.points.slice(dataIndex * ps, (dataIndex + 1) * ps),
dataIndex: dataIndex,
series: series,
seriesIndex: 0
};
$('#placeholder').trigger('plotclick', [ null, item ]); // passing a null position, we don't need it
This will in turn call your plotclick event
$("#placeholder").bind("plotclick", function (event, pos, item) {
if (item) {
somePlot.highlight(item.series, item.datapoint);
}
});
Here's an example.
To trigger click events in the jQWidgets Chart (jqxChart), you can look at: Chart Events

jQuery multi-draggable

Edit#1:
Since I asked this problem, I made a script which allows the elements to move together, but with problems. :(
$(this).append(
$('<div class="elem '+classes+'" style="width: 210px; height: 30px" data-modby="'+ui.draggable.attr("data-for")+'"><p>'+text+'</p></div>')
.resizable({
grid: 10,
maxHeight: 120,
maxWidth: 600,
minHeight: 30,
minWidth: 210,
containment: ".box-section"
})
.draggable({
grid: [10,10],
containment: ".box-section",
scroll: false,
helper: "original",
start: function(event, ui) {
posTopArray = [];
posLeftArray = [];
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
thiscsstop = $(this).css('top');
if (thiscsstop == 'auto') thiscsstop = 0;
thiscssleft = $(this).css('left');
if (thiscssleft == 'auto') thiscssleft = 0;
posTopArray[i] = parseInt(thiscsstop);
posLeftArray[i] = parseInt(thiscssleft);
});
}
begintop = $(this).offset().top;
beginleft = $(this).offset().left;
},
drag: function(event, ui) {
var topdiff = $(this).offset().top - begintop;
var leftdiff = $(this).offset().left - beginleft;
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
$(this).css('top', posTopArray[i] + topdiff);
$(this).css('left', posLeftArray[i] + leftdiff);
});
}
}
})
);
The actual problem is the moved elements have to stay in the containment box (called .box-section and if I have a single element it works fine. Also if i have two elements has not the same width, if i pick the sorter one and drag, I can pull out the longer of the container.
Also, if I move them fast (like a ninja) they will slip, and they won't be in the same grid they used to be.
30 percent solved since:
I'm going to make a new thingy which can drag and drop items to a box, and resize them.
My problem is that, I can't make them move together. But with some rules.
Rule one: They must move based on a 10x10px grid.
Rule two: They can't move outside their frame.
(Resize is an issue which i simply can't imagine, so I don't care about it, resize will be later)
I made a fiddle for it here: http://jsfiddle.net/9fueY/ you can see this.
In the right side, you can see inputs and a and a checkbox (and on hover a button).
The checkbox is the draggable object, drag it to the image. Now you have some text or a star appeared on the left.
If you type anything to the inputs, it refreshes the text.
OnHover the right boxes you can see a button. By clicking on it, will make a clone of the first element. Drag it inside.
If you click to a right-side box, it will glow blue. Click to two boxes on the right, makes all the two textfields glow blue in the image.
Now this is the case when i want them to move together. :D
What's your opinion, what should I do with this?
Thank you very much. - Répás
There is a plugin i developed for dragging elements together. Please do use it if it makes sense.
https://github.com/someshwara/MultiDraggable

Categories