Can I have a chart automatically size the height (rather than using 400px) using the Highcharts .NET Wrapper? - asp.net-mvc

There is another similar question, but that seems to be focused on the js library, not Highsoft.Highcharts (and I'm using v8.1.1.1) I tried some of these solutions, but they didn't seem to work.

Try to use those CSS options:
body, html {
height: 100%;
}
#container {
height: 100%;
}

Not the most elegant when you're working with a .NET wrapper, but this seemed to work (from a colleague of mine). When using the wrapper, "chart" comes from the Id of the Highcharts object. So you will need to change that if you use something else for Id.
var chart = new Highcharts { Id = "chart" };
And then this script in the .cshtml file:
<script>
$(window).load(function () {
// "chart" is the Id of the Highcharts container
var chart = $('#chart').highcharts();
var width = $('#chart').width();
// 100 is an approximation for the hight of the navbar + margin for panel. Removing that from the entire height of the window.
var height = $(window).innerHeight() - 100;
$('panel-body').height = height;
// setsize will trigger the graph redraw
chart.setSize(width, height, false);
});
$(window).resize(function () {
// "chart" is the Id of the Highcharts container
var chart = $('#chart').highcharts();
var width = $('#chart').width();
// 100 is an approximation for the hight of the navbar + margin for panel. Removing that from the entire height of the window.
var height = $(window).innerHeight() - 100;
// setsize will trigger the graph redraw
chart.setSize(width, height, false);
});
</script>

Related

How to position highcharts tooltip above chart with outside:true

I have a system with lots of highcharts which can be positioned basically anywhere on the page.
Some are very small (e.g. 50px x 50px).
I see we can set tooltip.outside : true
tooltip: {
outside: true
}
This stops the tooltip taking over the whole chart container by breaking it out of the chart and into the window.
However this can cause overflow issues with the window when you're near the edge of the page and I personally prefer a static tooltip.
I'd like to always fix the tooltip to float above the chart, top left with a bit of padding, which for my application will almost always be visible and will avoid overflow issues, e.g.;
I've looked into setting a custom positioner, however, as the "outside" tooltip is now part of the window and not relative to the chart, the positioner sets a fixed position, which isn't suitable for my application.
I'd like the tooltip to always be above the chart regardless of mouse or scroll positions.
Of course I could add a custom element and position it above the chart myself, then applying the tooltip to that, but we have a lot of charts and this seems cumbersome.
Tooltip outside Fiddle
Suggestions?
Thanks
After a bit of poking around in the highstock Tooltip.prototype.getPosition code, it turns out what I needed was this.point.chart.pointer.getChartPosition();
tooltip: {
distance: 40,
outside: true,
positioner: function () {
var point = this;
var chart = point.chart;
var chartPosition = chart.pointer.getChartPosition();
var distance = point.distance;
//Position relative to renderTo container
return {
x: chartPosition.left - distance,
y: chartPosition.top - distance - (point.options.useHTML == true ? point.label.div.offsetHeight : point.label.height)
}
//Alternatively - Position relative to chart plot (ignoring legend)
var containerScaling = chart.containerScaling;
var scaleX = function (val) {
return (containerScaling ? val * containerScaling.scaleX : val);
};
var scaleY = function (val) {
return (containerScaling ? val * containerScaling.scaleY : val);
};
return {
x: chartPosition.left - distance + scaleX(chart.plotLeft),
y: chartPosition.top - distance + scaleY(chart.plotTop) - point.label.height
}
},
},
See working fiddle.
I find it odd that this method is attached to pointer, but it's what I was after.
One thing to note, in the fiddle I use point.label.height, if useHTML:true; use point.label.div.height.
What about using the positioner callback without setting the 'outside' option? It will set the wanted position inside the chart area.
Demo: https://jsfiddle.net/BlackLabel/gabjwd2e/
API: https://api.highcharts.com/highcharts/tooltip.positioner

How to check if jQM popup fits user's viewport?

So I've managed to add scrollbars to large jQM popups with css('overflow-y', 'scroll'). But how to do this only when the popup is larger than the user's viewport?
I'm trying with the jquery-visible plugin but I can't get it to respond:
http://jsfiddle.net/mmRnq/124/
$('#test-button').on('click', function(e) {
$('#confirmDialog').popup('open');
// https://stackoverflow.com/questions/20791374/jquery-check-if-element-is-visible-in-viewport
if(!$('#confirmDialog').visible(true)) {
alert('Popup not fully visible - add overflow scrolling');
$('#confirmDialog').css('overflow-y', 'scroll');
}
});
You can use
overflow-y: auto
This makes the scrollbar only visible when it is needed.
Updated FIDDLE
UPDATE:
You can also just make the content of the popup scrollable so the titlebar remains in view:
#confirmDialog .ui-content {
overflow-y: auto;
}
$('#confirmDialog').on({
popupbeforeposition: function() {
var maxHeight = $(window).height() - 120;
$('#confirmDialog .ui-content').height(maxHeight);
}
});
DEMO
I had a popup too large, although it was because of a searchable list. As I wanted to keep the search field at the top whilst scrolling the list only, I had to do this:
$("#confirmDialog").on({
popupbeforeposition: function (e, ui) {
var maxHeight = $(window).height() - 100 + "px";
$("#confirmDialog .ui-content").css("max-height", maxHeight);
},
popupafteropen: function (e, ui) {
var maxHeight = $(window).height() - 150 + "px";
$("#confirmDialog .ui-content ul").css("max-height", maxHeight).css("overflow-y", "scroll");
}
});
Remember do not perform arithmetic on maxHeight once assigned as it's a string, so this doesn't work:
$("#confirmDialog .ui-content").css("max-height", maxHeight - 50);

Highcharts - resize legend on chart resize?

Is there anyway to dynamically set a specific width of legend items when resizing the chart? I have some really long item names possible in the legend so I need to specify a width to force the text to wrap, but I would like to change the width when the width the chart changes. Thanks.
I found a better work around for this:
chart.legend.options.width = newwidth;
chart.legend.itemStyle.width = newwidth;
for(var index in this.chart.series) {
chart.legend.destroyItem(chart.series[index]);
}
chart.legend.render()
Generally it is not possible, but you can disable highcharts legend, and prepare your own div (positioned absolutely) which will include list of all series and click event. Simple example is available here
$legend = $('#customLegend');
$.each(chart.series[0].data, function (j, data) {
$legend.append('<div class="item"><div class="symbol" style="background-color:'+data.color+'"></div><div class="serieName" id="">' + data.name + '</div></div>');
});
$('#customLegend .item').click(function(){
var inx = $(this).index(),
point = chart.series[0].data[inx];
if(point.visible)
point.setVisible(false);
else
point.setVisible(true);
});
http://jsfiddle.net/N3KAC/10/
Than only what you need is adapt this to your chart by catching $(window).resize() function and resize element.

Reveal.js with highcharts

I'm using reveal.js (http://lab.hakim.se/reveal-js/) together with Highcharts JS but i have problems with tooltips position. For example, if i use a line with the months on the x axis, when i put the mouse over the point in january the tooltip its ok, but when i put the mouse over december the tooltip shows me the october data. The tooltip for each month is displaced more and more.
You can see http://lideria.net/presentacion/index1.php to see the problem
This may be problem with Highcharts which us already reported here. Also there is suggested workaround: http://jsfiddle.net/highcharts/BD3R7/
reveal.js autoscales the viewport with a css zoom tag. If you inspect class="slides" div, you'll see something like this:
<div class="slides" style="width: 960px; height: 700px; zoom: 0.8331428571428572;">
Here the content (the chart) is scaled 80% of normal size and Highcharts loses it's ability to calculate positions properly if the chart is scaled outside of its control.
With that knowledge, a quick stack overflow search talks about the ability to force 'reveal.js` to not auto-scale content.
You must overwrite the normalize of the H.Pointer.prototype (referenced WRAPPING UP A PLUGIN). Add the following code to document.ready function (maybe somewhere else works, I guess). The reasons are:
reveal.js has separate ways when zoom>1 and zoom<1, e.g., zoom:1.25 and transform:scale(0.75).
So, when a section has several charts and zoom>1, must adjust e.chartX by e.pageX.
(function (H) {
H.wrap(H.Pointer.prototype, 'normalize', function (proceed, e) {
var e = proceed.call(this,e);
var zoom = Reveal.getScale();
if(zoom>1) {
var positionX = e.pageX - e.chartX;
var positionY = e.pageY - e.chartY;
e.chartX = Math.round((e.pageX - positionX*zoom)/zoom);
e.chartY = Math.round((e.pageY - positionY*zoom)/zoom);
} else {
e.chartX = Math.round(e.chartX/zoom);
e.chartY = Math.round(e.chartY/zoom);
}
return e;
});
}(Highcharts));

How do I get my highcharts to reduce in size when the window is resized down

I'm having trouble getting my highchart to reduce in size when the window is resized down.
I have created an example of my code in JSFiddle http://jsfiddle.net/britboy/UvFaQ/
<table border='1' width='100%'><tr><td width='100%'>
<div id="container" width='100%'></div>
</td></tr></table>
Its a simple Highchart chart displayed in a table - if I make the window bigger the chart expands, however if I make the window smaller the chart doesn't want to reduce instead the table gets scroll bars.
I've tried setting up a resize event and then adjusting the chart size with chart.setSize( ) but the problem is the div containing the chart never reduces any further in size, so the setSize() does not get triggered. Since the chart resizes automatically when the chart container gets bigger I would have though the same should work when the chart gets smaller. I think the problem is that the chart's size is preventing its container from shrinking.
How do I code a chart in a table that will reduce in size when the table is reduced?
Thanks
There are n number of ways to accomplish it.
One would be as pointed out by #Azeem. in the comment.
Other way, I actually, bind it with window. Whenever the window re-sizes, bind event would trigger a function to re-size the div element used to render the chart.
$(window).bind("resize", resizeChart);
then,
function resizeChart() {
var width = $(document).width() - 55;
var height = $(document).height() - 60;
$("#container").css("width", width);
$("#container").css("height", height);
}
Check out the sample fiddle here.
Try this method :
var chart = $('#graph1').highcharts();
var DetailsWidth = $('#graph1');
http://jsfiddle.net/cjohn/5ghzk4t8/4/
[Adding a solution for react-highcharts here, because this pops up as first SO solution when searching for "react-highcharts shrink" on Google]
For react-highcharts you can simply call the React Component forceUpdate() method in the window resize event listener. It will trigger Highcharts to redraw to the new, smaller area. See also Rerender view on browser resize with React
NOTE: my code was tested using flex-auto (see CSS Flexible Box Layout) in the parent and the Highcharts DOM elements. It would be interesting to know if this works for other layouts too.
import React from 'react';
import Highcharts from 'react-highcharts';
...
export default class Chart extends React.Component {
constructor(props) {
...
// install callbacks
this.resize = () => {
// throttle resize events as redraw is expensive
if (this.timeout)
return;
this.timeout = setTimeout(
() => {
// force Highcharts to always adhere
// to changes in the view area
this.forceUpdate();
this.timeout = undefined;
},
50); // milliseconds
};
...
}
...
componentDidMount() {
...
// listen to window resize events
window.addEventListener('resize', this.resize);
...
}
...
componentWillUnmount() {
...
// remove listener when component goes away
window.removeEventListener('resize', this.resize);
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = undefined;
}
...
}
...
render() {
...
return (
<Highcharts
config={...}
domProps={{
className: 'd-flex flex-auto',
...
}}
...
/>
);
}
...
}

Resources