Highcharts show all categories even when no data - javascript

I am working with high charts, I have a set of controls on a web page that allows the user to select months and locations. The issue is if they select a location that has no data. So lets say they select January and Hawaii but there is no data for Hawaii in January. Nothing will be displayed at all, but I would like the axis to appear along with the labels.
NOTE: I am trying to create a heatmap so I don't want to see the minimun color when there is no data.

A value of null seems to work. You can change your tooltip to not display if the value is null too: http://jsfiddle.net/SheldonNeilson/95um4x0q/1/
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/heatmap.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px; min-width: 310px; max-width: 800px; margin: 0 auto"></div>
$(function () {
$('#container').highcharts({
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80
},
title: {
text: 'Sales per employee per weekday'
},
xAxis: {
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null
},
colorAxis: {
min: 0,
minColor: Highcharts.getOptions().colors[0],
maxColor: '#FFFFFF'
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip: {
formatter: function () {
if(this.point.value == null){
return 'No data' ;
}else{
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> sold <br><b>' +
this.point.value + '</b> items on <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
}
},
series: [{
name: 'Sales per employee',
borderWidth: 1,
data: [[0, 0, null], [0, 1, 19], [0, 2, 8], [0, 3, 24], [0, 4, 67], [1, 0, 92], [1, 1, 58], [1, 2, 78], [1, 3, 117], [1, 4, 48], [2, 0, 35], [2, 1, 15], [2, 2, 123], [2, 3, 64], [2, 4, 52], [3, 0, 72], [3, 1, 132], [3, 2, 114], [3, 3, 19], [3, 4, 16], [4, 0, 38], [4, 1, 5], [4, 2, 8], [4, 3, 117], [4, 4, 115], [5, 0, 88], [5, 1, 32], [5, 2, 12], [5, 3, 6], [5, 4, 120], [6, 0, 13], [6, 1, 44], [6, 2, 88], [6, 3, 98], [6, 4, 96], [7, 0, 31], [7, 1, 1], [7, 2, 82], [7, 3, 32], [7, 4, 30], [8, 0, 85], [8, 1, 97], [8, 2, 123], [8, 3, 64], [8, 4, 84], [9, 0, 47], [9, 1, 114], [9, 2, 31], [9, 3, 48], [9, 4, 91]],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
});
});

Related

Highcharts Heatmap - How to get blocks next to each other when separated by more then '1' in value

Attached is an image of the problem I'm currently having.
Attached is an example of the issue manually created with JSFiddle
https://jsfiddle.net/ekjrLsz2/
My goal is to have each of the blocks be next to each other without all the space in-between like the default demos for the heatmap show.
I can get it to work correctly if the data is going 1 by 1, for example; 1,2,3,4,5,6
But if the data is going 5,10,15,20, etc... then you get what you see in my attached image.
So to be more clear the X direction is going 1 by 1 in my demo image and shows without spacing, the Y direction however has the large spacing since the data does not have numbers 21,22,23,24 or the space inbetween every 5 so to speak.
Below is the code I use to generate the chart.
Highcharts.setOptions({
lang: {
decimalPoint: '.',
thousandsSep: ','
}
});
Highcharts.chart('heatmap-container', {
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
title: {
text: 'Report Data'
},
xAxis: {
//categories: ['1%', '2%', '3%', '4%', '5%', '6%', '7%', '8%', '9%', '10%'],
title: {text:$('#x-values').val()},
//showEmpty:true,
},
yAxis: {
categories: ['5', '10', '15', '20', '25'],
title: {text:$('#y-values').val()},
reversed: false,
//visible: true,
//showEmpty:true,
},
colorAxis: {
max: goodColorVal,
min: badColorVal,
reversed: false,
tickInterval: 1,
//min: -150,
//minColor: '#FFFFFF',
//maxColor: '#00FF00',//Highcharts.getOptions().colors[4]
stops: [
[0.0,'#FF0000'],
[0.5,'#FFFFFF'],
[1.0,"#00FF00"]]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280,
reversed:true
},
tooltip: {
headerFormat: '',
pointFormat: `<b style="text-transform:capitalize;">${$("#x-values option:selected").text()}</b>:{point.x:,.2f} - <b style="text-transform:capitalize;">${$("#y-values option:selected").text()}</b>:{point.y:,.2f} - <b style="text-transform:capitalize;">${$("#z-values option:selected").text()}</b>:{point.value:,.2f}`
// formatter: function () {
// return '<b>' + getPointCategoryName(this.point, 'x') + '</b> sold <br><b>' +
// this.point.value + '</b> items on <br><b>' + getPointCategoryName(this.point, 'y') + '</b>';
// }
},
series: [{
name: 'Report Data For Input 1',
borderWidth: 1,
//data: [[0, 0, 10], [0, 1, 19], [0, 2, 9], [0, 3, 24], [0, 4, 67], [1, 0, 92], [1, 1, 58], [1, 2, 78], [1, 3, 117], [1, 4, 48], [2, 0, 35], [2, 1, 15], [2, 2, 123], [2, 3, 64], [2, 4, 52], [3, 0, 72], [3, 1, 132], [3, 2, 114], [3, 3, 19], [3, 4, 16], [4, 0, 38], [4, 1, 5], [4, 2, 8], [4, 3, 117], [4, 4, 115], [5, 0, 88], [5, 1, 32], [5, 2, 12], [5, 3, 6], [5, 4, 120], [6, 0, 13], [6, 1, 44], [6, 2, 88], [6, 3, 98], [6, 4, 96], [7, 0, 31], [7, 1, 1], [7, 2, 82], [7, 3, 32], [7, 4, 30], [8, 0, 85], [8, 1, 97], [8, 2, 123], [8, 3, 64], [8, 4, 84], [9, 0, 47], [9, 1, 114], [9, 2, 31], [9, 3, 48], [9, 4, 91]],
data: arraydata, //[[0,0,-87],[1,0,22],[2,0,33],[3,0,55]],
dataLabels: {
enabled: false,
color: '#000000'
}
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
yAxis: {
labels: {
formatter: function () {
return this.value.charAt(0);
}
}
}
}
}]
}
});
I have tried pointInterval and tickInterval with no luck so far.
The simplest way to have your points next to each other (without any spaces) is to give them x attributes without skipping any number, e.g 1,2,3,4...
Why don't you try to do it this way?
Demo:
https://jsfiddle.net/BlackLabel/39vx468s/
To skip the empty spaces between points you can use breaks functionality.
API references:
https://api.highcharts.com/highcharts/xAxis.breaks
Demo:
https://jsfiddle.net/BlackLabel/et4kryvz/
xAxis: {
breaks: [{
from: 0.5,
to: 1.5,
breakSize: 0
}]
}
There is also another solution, which uses colsize and rowsize properties. Thanks to that you can avoid using the breaks altogether this way and it even works with floating-point data.
Demo: https://jsfiddle.net/87tL3ogh/1/

Highcharts and boost with multiple charts

So I have two charts on the same page and I am using boost for both of these graphs. I wish to allow zooming and if I do a zoom then the line chart disappears. The data appears to still be there as the mouse over shows the data.
See this fiddle:
https://jsfiddle.net/CaptainBli/wa7o2bL8/3/
function getData(n) {
var arr = [],
i,
x,
a,
b,
c,
spike;
for (
i = 0, x = Date.UTC(new Date().getUTCFullYear(), 0, 1) - n * 36e5;
i < n;
i = i + 1, x = x + 36e5
) {
if (i % 100 === 0) {
a = 2 * Math.random();
}
if (i % 1000 === 0) {
b = 2 * Math.random();
}
if (i % 10000 === 0) {
c = 2 * Math.random();
}
if (i % 50000 === 0) {
spike = 10;
} else {
spike = 0;
}
arr.push([
x,
2 * Math.sin(i / 100) + a + b + c + spike + Math.random()
]);
}
return arr;
}
var n = 500000,
data = getData(n);
console.time('line');
Highcharts.chart('container', {
chart: {
zoomType: 'x'
},
title: {
text: 'Highcharts drawing ' + n + ' points'
},
subtitle: {
text: 'Using the Boost module'
},
tooltip: {
valueDecimals: 2
},
xAxis: {
type: 'datetime'
},
series: [{
data: data,
lineWidth: 0.5,
name: 'Hourly data points'
}]
});
console.timeEnd('line');
Highcharts.chart('heatcont', {
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
title: {
text: 'Sales per employee per weekday'
},
xAxis: {
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip: {
formatter: function () {
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> sold <br><b>' +
this.point.value + '</b> items on <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
},
series: [{
name: 'Sales per employee',
boostThreshold: 1,
borderWidth: 1,
data: [[0, 0, 10], [0, 1, 19], [0, 2, 8], [0, 3, 24], [0, 4, 67], [1, 0, 92], [1, 1, 58], [1, 2, 78], [1, 3, 117], [1, 4, 48], [2, 0, 35], [2, 1, 15], [2, 2, 123], [2, 3, 64], [2, 4, 52], [3, 0, 72], [3, 1, 132], [3, 2, 114], [3, 3, 19], [3, 4, 16], [4, 0, 38], [4, 1, 5], [4, 2, 8], [4, 3, 117], [4, 4, 115], [5, 0, 88], [5, 1, 32], [5, 2, 12], [5, 3, 6], [5, 4, 120], [6, 0, 13], [6, 1, 44], [6, 2, 88], [6, 3, 98], [6, 4, 96], [7, 0, 31], [7, 1, 1], [7, 2, 82], [7, 3, 32], [7, 4, 30], [8, 0, 85], [8, 1, 97], [8, 2, 123], [8, 3, 64], [8, 4, 84], [9, 0, 47], [9, 1, 114], [9, 2, 31], [9, 3, 48], [9, 4, 91]],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
});

Highcharts - Synchronized heat maps

Let's say we have two high charts - heat maps (can be more in future). Check it like below jsfiddle.
http://jsfiddle.net/xzq5bzy5/1/
<div id="container" style="height: 400px; min-width: 310px; max-width: 800px; margin: 0 auto"></div>
<div id="container2" style="height: 400px; min-width: 310px; max-width: 800px; margin: 0 auto"></div>
What I want if I hover on first cell of first high charts. It should simultaneously hover the second high chart first cell and both should show data in their respective tool-tips.
I have tried to search but I didn't find anything. Let me know if I need to add anymore information.
Here is a basic example using synchronised-charts highchars demo:
/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.highlight(e);
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
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
};
for (var i = 0; i < 2; ++i) {
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
title: {
text: 'Sales for Feb'
},
xAxis: {
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip: {
formatter: function() {
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> sold <br><b>' +
this.point.value + '</b> items on <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
},
series: [{
name: 'Sales per employee',
borderWidth: 1,
data: [
[0, 0, 10],
[0, 1, 19],
[0, 2, 8],
[0, 3, 24],
[0, 4, 67],
[1, 0, 92],
[1, 1, 58],
[1, 2, 78],
[1, 3, 117],
[1, 4, 48],
[2, 0, 35],
[2, 1, 15],
[2, 2, 123],
[2, 3, 64],
[2, 4, 52],
[3, 0, 72],
[3, 1, 132],
[3, 2, 114],
[3, 3, 19],
[3, 4, 16],
[4, 0, 38],
[4, 1, 5],
[4, 2, 8],
[4, 3, 117],
[4, 4, 115],
[5, 0, 88],
[5, 1, 32],
[5, 2, 12],
[5, 3, 6],
[5, 4, 120],
[6, 0, 13],
[6, 1, 44],
[6, 2, 88],
[6, 3, 98],
[6, 4, 96],
[7, 0, 31],
[7, 1, 1],
[7, 2, 82],
[7, 3, 32],
[7, 4, 30],
[8, 0, 85],
[8, 1, 97],
[8, 2, 123],
[8, 3, 64],
[8, 4, 84],
[9, 0, 47],
[9, 1, 114],
[9, 2, 31],
[9, 3, 48],
[9, 4, 91]
],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
})
}
Live example:
http://jsfiddle.net/atkf70cv/

Highchart legend has clipped text

I've a heat map using Highcharts where I'm facing some issues with text clippings.
When I add a label on the colorAxis the text gets clipped:
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0],
labels: {
format: '{value} test test test'
},
}
I've only added the colorAxis.labels.format property.
See my example here:
http://jsfiddle.net/dennismadsen/7sp8ddpq/1/
It's based/forked on this official Highchart sample:
http://jsfiddle.net/highcharts/4aqhB/
HighCharts does have its quirks in the legend layout. You have to explicitly set the width, i.e.
legend: {
...
width: 140,
...
},
Found a way to make it dynamic, based on a post by TorsteinHonsi on GitHub. The code basically measures the width of the label and redraws the chart. See if it suits your needs.
$(function () {
var leg = 'Whatever';
var aChart = new Highcharts.Chart({
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 40,
renderTo: 'container'
},
title: {
text: 'Sales per employee per weekday'
},
xAxis: {
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0],
labels: {
format: '{value} ' + leg,
style: {
textOverflow: "clip",
overflow: "visible",
whiteSpace: "nowrap"
}
},
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 320
},
tooltip: {
formatter: function () {
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> sold <br><b>' +
this.point.value + '</b> items on <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
},
series: [{
name: 'Sales per employee',
borderWidth: 1,
data: [[0, 0, 10], [0, 1, 19], [0, 2, 8], [0, 3, 24], [0, 4, 67], [1, 0, 92], [1, 1, 58], [1, 2, 78], [1, 3, 117], [1, 4, 48], [2, 0, 35], [2, 1, 15], [2, 2, 123], [2, 3, 64], [2, 4, 52], [3, 0, 72], [3, 1, 132], [3, 2, 114], [3, 3, 19], [3, 4, 16], [4, 0, 38], [4, 1, 5], [4, 2, 8], [4, 3, 117], [4, 4, 115], [5, 0, 88], [5, 1, 32], [5, 2, 12], [5, 3, 6], [5, 4, 120], [6, 0, 13], [6, 1, 44], [6, 2, 88], [6, 3, 98], [6, 4, 96], [7, 0, 31], [7, 1, 1], [7, 2, 82], [7, 3, 32], [7, 4, 30], [8, 0, 85], [8, 1, 97], [8, 2, 123], [8, 3, 64], [8, 4, 84], [9, 0, 47], [9, 1, 114], [9, 2, 31], [9, 3, 48], [9, 4, 91]],
dataLabels: {
enabled: true,
color: 'black',
style: {
textShadow: 'none'
}
}
}]
});
Highcharts.Legend.prototype.update = function (options) {
this.options = Highcharts.merge(this.options, options);
this.chart.isDirtyLegend = true;
this.chart.isDirtyBox = true;
this.chart.redraw();
};
aChart.legend.update({
width: 50 + $('.highcharts-axis-labels tspan').outerWidth()
});
});

Retrieve Data in mvc View

I currently have this script in MVC view
<script type="text/javascript">
$(document).ready(function () {
$(".bar_dashboard").peity("bar", {
fill: ["#1ab394", "#d7d7d7"],
width: 100
})
$("#sparkline8").sparkline([5, 6, 7, 2, 0, 4, 2, 4, 5, 7, 2, 4, 12, 14, 4, 2, 14, 12, 7], {
type: 'bar',
barWidth: 8,
height: '150px',
barColor: '#1ab394',
negBarColor: '#c6c6c6'
});
var updatingChart = $(".updating-chart").peity("line", { fill: '#1ab394', stroke: '#169c81', width: 64 })
setInterval(function () {
var random = Math.round(Math.random() * 10)
var values = updatingChart.text().split(",")
values.shift()
values.push(random)
updatingChart
.text(values.join(","))
.change()
}, 1000);
var data1 = [
[0, 4], [1, 8], [2, 5], [3, 10], [4, 4], [5, 16], [6, 5], [7, 11], [8, 6], [9, 11], [10, 30], [11, 10], [12, 13], [13, 4], [14, 3], [15, 3], [16, 6]
];
var data2 = [
[0, 1], [1, 0], [2, 2], [3, 0], [4, 1], [5, 3], [6, 1], [7, 5], [8, 2], [9, 3], [10, 2], [11, 1], [12, 0], [13, 2], [14, 8], [15, 0], [16, 0]
];
$("#flot-dashboard-chart").length && $.plot($("#flot-dashboard-chart"), [
data1, data2
],
{
series: {
lines: {
show: false,
fill: true
},
splines: {
show: true,
tension: 0.4,
lineWidth: 1,
fill: 0.4
},
points: {
radius: 0,
show: true
},
shadowSize: 2
},
grid: {
hoverable: true,
clickable: true,
tickColor: "#d5d5d5",
borderWidth: 1,
color: '#d5d5d5'
},
colors: ["#1ab394", "#464f88"],
xaxis: {
},
yaxis: {
ticks: 4
},
tooltip: false
}
);
var doughnutData = [
{
value: 300,
color: "#a3e1d4",
highlight: "#1ab394",
label: "App"
},
{
value: 50,
color: "#dedede",
highlight: "#1ab394",
label: "Software"
},
{
value: 100,
color: "#b5b8cf",
highlight: "#1ab394",
label: "Laptop"
}
];
var doughnutOptions = {
segmentShowStroke: true,
segmentStrokeColor: "#fff",
segmentStrokeWidth: 2,
percentageInnerCutout: 45, // This is 0 for Pie charts
animationSteps: 100,
animationEasing: "easeOutBounce",
animateRotate: true,
animateScale: false,
};
var ctx = document.getElementById("doughnutChart").getContext("2d");
var DoughnutChart = new Chart(ctx).Doughnut(doughnutData, doughnutOptions);
var polarData = [
{
value: 300,
color: "#a3e1d4",
highlight: "#1ab394",
label: "App"
},
{
value: 140,
color: "#dedede",
highlight: "#1ab394",
label: "Software"
},
{
value: 200,
color: "#b5b8cf",
highlight: "#1ab394",
label: "Laptop"
}
];
var polarOptions = {
scaleShowLabelBackdrop: true,
scaleBackdropColor: "rgba(255,255,255,0.75)",
scaleBeginAtZero: true,
scaleBackdropPaddingY: 1,
scaleBackdropPaddingX: 1,
scaleShowLine: true,
segmentShowStroke: true,
segmentStrokeColor: "#fff",
segmentStrokeWidth: 2,
animationSteps: 100,
animationEasing: "easeOutBounce",
animateRotate: true,
animateScale: false,
};
var ctx = document.getElementById("polarChart").getContext("2d");
var Polarchart = new Chart(ctx).PolarArea(polarData, polarOptions);
});
</script>
I want to change
var data1 = [
[0, 4], [1, 8], [2, 5], [3, 10], [4, 4], [5, 16], [6, 5], [7, 11], [8, 6], [9, 11], [10, 30], [11, 10], [12, 13], [13, 4], [14, 3], [15, 3], [16, 6]
];
var data2 = [
[0, 1], [1, 0], [2, 2], [3, 0], [4, 1], [5, 3], [6, 1], [7, 5], [8, 2], [9, 3], [10, 2], [11, 1], [12, 0], [13, 2], [14, 8], [15, 0], [16, 0]
];
to read dynamic data from my Controller using JSON how can I do that?
You need a method in your controller which provides you the information you want.
public String getData(){
int[,] ints = new int[,] { {1,1},{2,2},{3,3} };
var json = Newtonsoft.Json.JsonConvert.SerializeObject(ints);
}
In your view you can get it like this:
$.get("/Controller/getData", null, function (data) {
thisismydata = data;
});
If you want to do this async take a look at $.ajax(). You can find more information here.

Categories

Resources