Highcharts dataLabels allowOverlap not working - javascript

In my dataLabels options for a series I have set allowOverlap to false. However, I'm still getting overlapping labels. My actual implementation is admittedly really custom and bespoke, and I've tried to create a simple jsfiddle to reproduce this, but can't.
However, I have tracked it down to what I think is the problem, at least in the html output.
In this example, when I inspect the labels elements in Chrome Dev Tools, I see something like the following for the first few labels:
It seems that the class highcharts-data-label-hidden goes together with an opacity: 0 and this acts to hide the label concerned. Where that class label is not applied, opacity is set to 1, to show the label. It works as it should; there are no overlapping labels in this example.
However, with the output from my own code I see something like:
In my output, all labels are shown; none are hidden; and many are overlapping. It seems that the highcharts-data-label-hidden class is being correctly applied to certain labels, i.e. those that should be hidden to avoid overlap. But at the same time, the opacity of these elements is set to 1 rather than 0... in fact all elements have an opacity of 1... and hence all my labels are showing, and many are overlapping as a result.
Sure enough, if I dynamically edit the style tags in Dev Tools to change opacity to 0 for those elements having the highcharts-data-label-hidden class, the labels are nicely laid out without any overlap.
I have tried in vain for hours to work out why my code is setting opacity to 1 even for these labels that should be hidden, despite apparently assigning the highcharts-data-label-hidden class correctly. I need your help, even based on this admittedly limited information.
One clue may be that I also notice that highcharts-data-label-color-0 class appears in the working example for each element, whereas highcharts-data-label-color-undefined appears in mine. Looking at the HC source code, this appears to come from dataLabel.addClass(' highcharts-data-label-color-' + point.colorIndex ..., so point.colorIndex in mine must be ending up as undefined, but I'm not sure why, or whether that is related to the problem I'm seeing with the non-hidden labels. I am doing some 'advanced' stuff with point and label colouring in my code, so that I can set the colour of the label to match the colour of the point, even where a colour gradient is in effect (this is done after the chart loads). But I don't do anything to the label opacity, so far as I know... wouldn't even know how... the dataLabels object doesn't even have an opacity element to change.
Any help appreciated!
EDIT
Finally managed to make a simple repro, just to prove that I'm not going mad! If you run this example, and inspect the overlapping label elements, you will see that (like described above) many have the highcharts-data-label-hidden class and yet also have opacity: 1, making them visible when they shouldn't be.
The (partial) solution appears to be to do a series.update(false) after each series loop (only one series in this example), rather than a chart.update() at the end... as per this updated example. Question: why isn't it necessary to pass true into the update?
However, whilst this is an improvement, there is still an oddity... after loading, try hitting the Unset Extremes button... the labels overlap again.
And it's not just calling setExtremes() with no args that does this... load this example and hit Set Extremes once (OK) and then twice (NOT OK)... the only change in this example is to use wider extremes than in the original, so that labels overlap. Even more weirdly in this example, some labels remain hidden, while others don't... it's not all or nothing.
Even with the first simple repro, which doesn't work on opening, if you hit Set Extremes, then Unset Extremes, the labels no longer overlap. But hit Unset Extremes again, and they overlap again. Can't work out what is going on here.
In fact, having spent a while producing this repro, I now notice that the original example I gave at the very start of my post also shows this behaviour, without needing the load() event... open this again... looks fine at first but then hit the Unset Extremes button... labels overlap! And in this slight modification all I have done is widen the range for Set Extremes... load that and hit Set Extremes (OK) and then again (NOT OK).
How do I ensure non-overlapping labels in this context, at all times, regardless of what axis extremes are set (and in what order the extremes are set)?

Thank you for reproducing the issue. Just like I thought before - it is a regression. Everything used to work fine in the 8.0.4 version. I already reported it on Highcharts GitHub issue channel where you can follow this thread:
https://github.com/highcharts/highcharts/issues/13742
The last stable version: https://jsfiddle.net/BlackLabel/vwc34nhz/
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/8.0.4/highcharts.js"></script>
<div id="container"></div>
<button id="setextremes">Set extremes</button>
<button id="unsetextremes">Unset extremes</button>
If you don't need any new features please use the 8.0.4 version until our core developers will fix this issue.

Related

How to prevent a Vis.js Timeline from resizing "unnecessarily"?

Does anyone know how to prevent a Vis.js Timeline from resizing "unnecessarily"? By "unnecessarily" I of course mean relative to a visual context not the "code context". In the screengrab below, I understand that the code is "doing its job", as it were, but the visual result is not acceptable.
I've tried all the various settings I could find under the setup options but they didn't help. It is a huge codebase and I'd rather not muck around with it, if I can help it.
While you can't configure it in the javascript, a bit of css can do the trick for you :)
.vis-label .vis-inner {
min-height: 200px;
}
I had similar issues so I thought I would post a response here in the event someone else is experiencing the same problems I had. Changing the CSS didn't work for me. This just created gaps on the Y Axis inside the first or last group item and pushed the timeline items out of whack. There's an option called 'stack' which I had overlooked. For items that overlap slightly their corresponding group will expand in height to accommodate them. In my case I had an item that ended at 16:00 and the item directly after this would have a start time of 16:00. This was causing some overlap but I did not want the height of the group to expand. Setting 'stack: false' in the options prevented the expanding effect. There was still some minor expanding in the region of a couple of pixles but nowhere near the height issues I was having with multiple items sharing the same start/end times.

C3 rendering before bootstrap kicks in

I am using c3.js, AngularJs and bootstrap to render some charts. The setup is as follows:
Bind a variable to <select> form to change between chart types
I have a $watch on the same variable which triggers the chart rendering.
Depending on variable I render multiple charts, different types depending on it's value. I have two charts per row, each one inside a col-XX-6.
Each chart group is hidden/shown using ng-show="myVariable== 'typeX'" depending on the same variable that triggers the render.
So, view and c3 render are acting on the same variable.
The first render is triggered by watch on $viewContentLoaded and everything works fine. After I change the select option, the first chart in the column renders with 100% width, disregarding bootstrap template. My theory is that c3.js renders the chart "too fast", before the view kicks in and sets the proper width. Further investigation:
Adding a $timeout on renderer fixes the problem but this is unacceptable solution
Adding a fixed width on charts works but is not acceptable, it needs to adapt to bootstrap
So far it seems that the only solution is to listen to the actual DOM change to see when the DOM actually becomes visible and only then start the render. But it seems that this technique is highly discouraged.
How do I fix this problem the proper way?
Edit 1: It seems that even if I render all the charts once and never refresh them, they still rarely but randomly oversize when shown.
Edit 2:
Plunkr: http://plnkr.co/edit/mU5m694VoDB5GtXrmPdP
Plunkr works (...) but basically, it happens to me when you'd switch from type2 to type1, the first graph would take 100% width and mess up everything. I'll see if I can find something in Plunkr that would make it break.
Edit 3: Well, perhaps not working that well afterall. I noticed charts sometimes do not render (blank page) and they only appear after I inspect element or fiddle with the screen in some way. Seems like it could be the same problem behind this. You should increase the plunker preview to simulate a wider screen.
You mention that you are having problems with initial size, but actually, there is going to be problems when browser size changes too.
We use d3.js (not c3) extensively in our project, and we found that the best option is to set viewBox attribute of svg element created by d3 to the parent element's size when browser size change event is emitted by window.
viewBox basically translates coordinate system of svg to origin and size defined by it.

hidden/not displayed elements receiving mouse over events

I'm pretty new to event-handling inside svgs and there is a little weirdness happening here. I'm doing an infovis where I build an interface and want to display different column-graphs.
That's rather easy and working pretty nicely.
But I'm using hover-events to show the actual numbers when hovering a rect. it works with the one chart I'm generating first. But even though that chart is hidden (I tried both: visibility: hidden and display: none properties) the one that's drawn first still gets the event.
Do I need to remove that one completely in order to generate a new one? So should I better work with separate SVGs and have an external interface, hiding the different svgs?
Any advice/best-practice would be welcome!
Thanks already!
Suse
The other way of hiding things is to push them off the screen, as with hidden iframes. Just give them a negative x/y position. That should take care of mouse-over issues.

Small HighCharts disappear

I want this highchart - http://jsfiddle.net/zPDca/ inside a popup. But if i decrease its width to lets say to 200 px, it dissapers. Any suggestions!
It looks like 251 px is the lower limit for the width.
This was probably a decision the developers made due to readability. Think about it:
This is a stock chart and it contains the "detail" view and a navigator view, you have export enabled and by default you are showing the buttons, the default selection buttons for zooming are also shown. Wouldn't this be really crowded for the user? Why not use a different kind of chart (standard highchart maybe) that shows latest data and gives user option to expand view. This would save a lot of space in the view.
Things you can try:
Remove the export buttons (you can write your own extension to still do exporting without useing the built-in buttons)
Remove the "Zoom" text
Change chart to be less "busy" overall
Having a data visualization is all about quickly seeing the data you need - not necessarily seeing all the options you may need in a tight space. If this chart is to be used for continuous monitoring you can strip it of all option settings but have it use the options set by the user in a "primary/setup" chart.
Look this example http://jsfiddle.net/zPDca/1/
It's working well.
If you take a look the reference you can see that it can be calculated by the containing element. So you just have to remove width from your chart as you can see on my example.
Okay I got the answer. Versions higher than 1.1.5 do not allow charts smaller than certain dimension. I do not know why. But I'm detouring right now by using version 1.1.5.

Highcharts hover bug - with video to demonstrate

I recently posted an issue regarding unpredictable hover on points in Highcharts, but the question didn't get much traction. Probably because it's difficult to explain.
I now posted a video here
http://www.youtube.com/watch?v=LovfLWpVVtc
showing this behavior.
It happens both on Chrome and Firefox (the video was done on FF on a high spec MacPro).
The video was done using this JsFiddle from the docs.
http://jsfiddle.net/HnwbQ/1/
As you can see, when approaching the first or last point from outside of the chart, no tootlip is shown. However if the cursor enters the chart and then approaches the first/last point, then a tooltip is rendered. This is erratic, and sometimes a tooltip is rendered when coming from the outside, sometimes it's not.
Any ideas what's the issue?
MORE INFO
This seems to occur mostly when using xAxis: {type: 'datetime'},
I am using Highcharts v2.1.9.
There is no need in 'hack' - just use the latest version of Highcharts http://jsfiddle.net/WdVtE/
OK I think I found a hackish solution to this.
It seems to me this is a bug related to the fact that
xAxis: {type: 'datetime'}
pushes the first and last datapoint to the limits of the plot area (this doesn't happen when using category).
So the way around this problem is to create some padding using
x-axis: {
minPadding:0.02,
maxPadding:0.02
}
Then hover behaves correctly, similar to when x-axis is category.
Note that minPadding and maxPadding have to be > 0.02. If you use 0.01 you'll have a buggy hover.

Categories