Null Values in Zones in Highcharts - javascript

I have graphs that have zones. Currently if there is a null value, that null value is displayed in the tooltip with the zone color of the point before it. I want the null value to always be the color black.
For example,
The tooltip in graph 1 has all the correct information... but "Strength: null" has a green dot. I want to make this dot black because it is a null value.
Is it possible to make this happen? Thanks so much.
https://codepen.io/austeng/pen/gOppRWY
zones: [
{
value: 0.3,
color: "green"
},
{
value: 0.5,
color: "black",
},
{
color: "red"
}
]

look at this code. change AFTER point = chart.series[0].points[pointIndex]; BEFORE });
if (thisChart === Highcharts.charts[Highcharts.hoverChartIndex]) {
Highcharts.charts.forEach(function(chart) {
point = chart.series[0].points[pointIndex];
// CHANGE START
if (point.y == null) {
// set here your color for null values
result +=
'<span style="color:black' +
'">●</span> ' +
point.series.name +
": <b>" +
point.y +
"</b><br/>";
} else {
result +=
'<span style="color:' +
point.color +
'">●</span> ' +
point.series.name +
": <b>" +
point.y +
"</b><br/>";
}
// CHANGE END
});
} else {
result =
'<span style="color:' +
this.color +
'">●</span> ' +
this.series.name +
": <b>" +
this.y +
"</b><br/>";
}

I have added this functionality by defining the color point like this:
let color = point.y === null ? 'black' : point.color
and use this color variable in the result:
result +=
'<span style="color:' +
color +
'">●</span> ' +
point.series.name +
": <b>" +
point.y +
"</b><br/>";
Demo: https://jsfiddle.net/BlackLabel/7x1oc2pw/
Is that what you had in mind?

Related

Why does </span> add a new array position entry?

I don't understand why my placement of the first /span (_S) in the defFD variable is creating a new position in the array. I want to set one color for the portion dayname[i] and another after the span variable ND. But when I put the /span (_S) after the dayname section (before ND) in that position it splits the dayname into array position [0] and the rest into pos [1]. Why?
The result of the above code looks like this for the Day forecast: defFD = ["Wednesday Jan 5-", "A foggy day with a high of 47º. Hum 47%. Winds ESE at 10mph. Prec 10% chance.] I need there to be a single long string at position [0] without being split after "Wednesday Jan 5". I've come at this from several angles. Need fellow pros to help.
// STYLING VARIABLES for EXTRA DATA
var DN = '<span style= color:' + ( (where == "day") ? font_color_night : font_color_day ) + '>'; //Day-Night Color Swap
var ND = '<span style= color:' + ( (where == "day") ? font_color_day : font_color_night ) + '>'; //Night-Day Color Swap
var _S = "</span>"; //remove styling
// BUILD WEATHER DATA
var defFD = [];
for (i=0; i < (ForecastDays)+1; i++) {
defFD[i] = DN + obj.dayname[i] + " " + Suffix(dates[i]) + "- " + _S
+ ND + convertTxtDay(obj.day_desc[i]) + ((obj.code[i] == 24 && obj.day_desc[i].indexOf("wind") == -1) ? " and windy " : " ")
+ "with a high of " + obj.high[i] + "°" + Unit + ". "
+ "Hum " + obj.day_humidity[i] + "%. "
+ "Winds " + obj.day_cardinal[i] + " at " + obj.day_speed[i] + windspeedunit + ". "
+ ((obj.pop[i] != 0) ? "Prec." + obj.pop[i]+ "% chance." : "") + _S + "<P>"
;
defFN[i] = DN + obj.dayname[i] + nighttext + "- " + _S
+ ND + convertTxtNight(obj.ndesc[i]) + ((obj.code[i] == 24 && obj.ndesc[i].indexOf("wind") == -1) ? " and windy " : " ")
+ "with a low of " + obj.low[i] + "°" + Unit + ". "
+ "Hum " + obj.nhum[i] + "%. "
+ "Winds " + obj.ncard[i] + " at " + obj.nspeed[i] + windspeedunit + ". "
+ ((obj.npop[i] != 0) ? "Prec." + obj.npop[i]+ "% chance." : "") + _S + "<P>"
;
if (DayOnly == false) { defForecast.push(defFD[i], defFN[i]); } //move day & night alternating into 1 array
else { defForecast.push(defFD[i]); }
} ```
It looks like you might be missing the quotation marks around your style attributes:
var DN = '<span style="color:' + ( (where == "day") ? font_color_night : font_color_day ) + '">';
var ND = '<span style="color:' + ( (where == "day") ? font_color_day : font_color_night ) + '">';
It seems like what solves my issue is to simply add the /span's both at the end and not the middle.. Though no idea why I can't add an /span in the middle of the variable declaration without it adding a new array position.
var DN = '<span style="color:' + ( (where == "day") ? font_color_night : font_color_day ) + '">';
var ND = '<span style="color:' + ( (where == "day") ? font_color_day : font_color_night ) + '">';
var _S = "</span>"; //remove styling
defFD[i] = DN + (other variables here) +
ND + (other variables here) +
_S + _S;

Formatting tooltip in Highcharts

How to make sure that in the tooltip, "(name)" is displayed only after the value along the axis? With the current codes "(name)" is also displayed after string "Series 1:.. (name)".
Highcharts.chart('container', {
tooltip: {
formatter: function () {
return this.points.reduce(function (s, point) {
return s + '(name)' + '<br/>' + point.series.name + ': ' +
point.y + 'm';
}, '<b>' + this.x + '</b>');
},
shared: true
}
});
Example: https://jsfiddle.net/nsdtf7ah/
Printscreen: http://joxi.ru/Dr8501zTowVWGm
If you need (name) only after Month name then replace tooltip with :
tooltip: {
formatter: function () {
return this.points.reduce(function (s, point) {
return s + '<br/>' + point.series.name + ': ' + point.y + 'm';
}, '<b>' + this.x + '(name)'+ '</b>');
},
shared: true
},
https://jsfiddle.net/m4q2sh7t/
If you need 2 (name)'s each after String N then:
tooltip: {
formatter: function () {
return this.points.reduce(function (s, point) {
return s + '<br/>' + point.series.name + ': ' + point.y + 'm' + '(name)';
}, '<b>' + this.x+ '</b>');
},
shared: true
},
https://jsfiddle.net/m4q2sh7t/1/

Google Charts; Offsetting Annotations from horizontal Axis

I'm looking for a way to offset the annotation labels I have on a Google Chart I'm making. I've included an image below, but essentially what I've done is created a column chart with hidden lines that the annotations are set from.
I did this because the bar type apparently doesn't support annotations. My end goal is to get the percentage of each week to display at the top of the bars. The problem is that because of the way I had to do this the percentage annotations center on the x-axis label and not on the column bar itself.
Image of Chart
As you can see from the image link above, this causes problems with overlapping when the values for each location are similar. I'm looking for a solution to the overlapping.
Here is the code I'm using to impliment the chart (C# string appender for the google api javascript):
str.Append(#"<script type=*text/javascript*> google.load( *visualization*, *1*, {packages:[*corechart*, *bars*]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn({type: 'string', label: 'Date'});
data.addColumn({type: 'number', label: 'NC'});
data.addColumn({type: 'number', label: 'WA'});
data.addColumn({type: 'number', label: 'Std Cap'});
data.addColumn({type: 'number', label: 'NC'});
data.addColumn({type: 'string', role: 'annotation', label: 'NCa' });
data.addColumn({type: 'number', label: 'WA'});
data.addColumn({type: 'string', role: 'annotation', label: 'WAa' });
data.addRows(" + dt.Rows.Count + ");");
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
// Data values.
str.Append("data.setValue(" + i + "," + 0 + "," + "'" + dt.Rows[i]["WeekNum"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 1 + "," + "'" + dt.Rows[i]["NC"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 2 + "," + "'" + dt.Rows[i]["WA"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 3 + "," + "'" + dt.Rows[i]["Std Cap"].ToString() + "');");
// Invisible line to set annotations off of.
str.Append("data.setValue(" + i + "," + 4 + "," + "'" + double.Parse(dt.Rows[i]["NC"].ToString()) + "');");
// Annotation value; Multiply value by 100 to get percentage.
str.Append("data.setValue(" + i + "," + 5 + "," + "'" + String.Format("{0}%", (100 * double.Parse(dt.Rows[i]["NC"].ToString()))) + "');");
// Invisible line to set annotations off of.
str.Append("data.setValue(" + i + "," + 6 + "," + "'" + double.Parse(dt.Rows[i]["WA"].ToString()) + "');");
// Annotation value; Multiply value by 100 to get percentage.
str.Append("data.setValue(" + i + "," + 7 + "," + "'" + String.Format("{0}%", (100 * double.Parse(dt.Rows[i]["WA"].ToString()))) + "');");
}
str.Append(" var formatter = new google.visualization.NumberFormat({ pattern:'#.#%' });");
str.Append(" formatter.format(data, 1);");
str.Append(" formatter.format(data, 2);");
str.Append(" var chart = new google.visualization.ComboChart(document.getElementById('chart_div1'));");
str.Append(" chart.draw(data, {width: 1000, height: 600, title: '',");
str.Append(" stackSeries: true, isStacked: false, legend: {alignment: 'end'},");
str.Append(#" vAxes:{
0: { 'maxValue': " + maxVal + #", format: '#%'},
1: { 'maxValue': " + maxVal + #"},
2: { 'maxValue': " + maxVal + #"}
},");
str.Append(#" hAxis: {title: ''},
seriesType: 'bars',
series: {
0: {type: 'bars', color: 'blue'},
1: {type: 'bars', color: 'green'},
2: {type: 'line', color: 'red', lineDashStyle: [4, 4]},
3: {type: 'line', lineWidth: 0, visibleInLegend:false, pointSize: 0},
4: {type: 'line', lineWidth: 0, visibleInLegend:false, pointSize: 0}
},");
str.Append(#" annotations: {
style: 'point',
stemColor: 'none',
textStyle: { color: 'black' },
alwaysOutside: 'true'
}");
str.Append("}); }");
str.Append("<" + "/script>");
Literal lit = this.Master.FindControl("body").FindControl("lt1") as Literal;
lit.Text = str.ToString().Replace('*', '"');
The chart is populated by a dynamic table, named dt. Here's the layout of that table:
Datatable Example
Chart drawing code (Javascript):
var options = { packages: ['corechart'], callback : drawChart};
google.load('visualization', '1', options);
function drawChart() { }
Chart Div on page (HTML/ASP.NET):
<div>
<asp:Literal ID="lt1" runat="server"></asp:Literal>
<div id="chart_div1" style="width:1000px; height:600px"></div>
</div>
I'm not glued to the offset idea, this is just where I've landed from all my research. Ultimately I just want to display the percentages at the top of each column, so if there is a better way to go about that, I'm all ears!
Thank you in advance.
::EDIT::
After considering WhiteHat's comments below. I made the following adjustment to my for loop that does offset them (vertically) when the values are within 10 points of each other. This isn't the most elegant solution, but it does seem to work.
double ncVal;
double waVal;
double ncOffset;
double waOffset;
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
ncOffset = 0;
waOffset = 0;
ncVal = double.Parse(dt.Rows[i]["NC"].ToString());
waVal = double.Parse(dt.Rows[i]["WA"].ToString());
// If values are within 10 points of each other, offset by 5 each positive/negative.
if ((ncVal - waVal) < 0.10)
{
if ((ncVal - waVal) > 0)
{
if (ncVal < 1)
{
ncOffset = 0.03;
waOffset = -0.03;
}
else
{
ncOffset = -0.03;
waOffset = 0.03;
}
}
}
else
{
if ((waVal - ncVal) < 0.10)
{
if ((waVal - ncVal) > 0)
{
if (ncVal < 1)
{
waOffset = 0.03;
ncOffset = -0.03;
}
else
{
waOffset = -0.03;
ncOffset = 0.03;
}
}
}
}
// Data values.
str.Append("data.setValue(" + i + "," + 0 + "," + "'" + dt.Rows[i]["WeekNum"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 1 + "," + "'" + dt.Rows[i]["NC"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 2 + "," + "'" + dt.Rows[i]["WA"].ToString() + "');");
str.Append("data.setValue(" + i + "," + 3 + "," + "'" + dt.Rows[i]["Std Cap"].ToString() + "');");
// Invisible line to set annotations off of.
str.Append("data.setValue(" + i + "," + 4 + "," + "'" + (ncVal + ncOffset) + "');");
// Annotation value; Multiply value by 100 to get percentage.
str.Append("data.setValue(" + i + "," + 5 + "," + "'" + String.Format("{0}%", (100 * ncVal)) + "');");
// Invisible line to set annotations off of.
str.Append("data.setValue(" + i + "," + 6 + "," + "'" + (waVal + waOffset) + "');");
// Annotation value; Multiply value by 100 to get percentage.
str.Append("data.setValue(" + i + "," + 7 + "," + "'" + String.Format("{0}%", (100 * waVal)) + "');");
}
Still, if anyone knows a way to center them on the columns, that would be ideal.

Highchart step line chart tooltip show old data when there is no data

On the following JS Fiddle
I have created a chart with a step line.
step: true
I am trying to show the old data in tooltip when there is no data for the series. E.g. on mouse over on 1 July 2015, I have the data so the tooltip show the data. But if you move forwared the tooltip don't show any thing.
Is the HighChart support some thing like show latest old data if no data is present.
You should use the tooltip.formatter and then use loop to find points with the same x. If not exists then extract last point from step series. Simple demo: http://jsfiddle.net/vs6scfch.
tooltip: {
shared: false,
formatter: function() {
var x = this.x,
series = this.series.chart.series,
stepSeries = series[1],
lastPointStepSerie = stepSeries.points[stepSeries.points.length - 1],
each = Highcharts.each,
txt = '<span style="font-size: 10px">' + Highcharts.dateFormat('%A, %b %d, %Y', this.x) + '</span><br/>';
each(series, function(s,i) {
each(s.points, function(p, j) {
if(p.x === x) {
txt += '<span style="color:' + p.color + '">\u25CF</span> ' + s.name + ': <b>' + p.y + '</b><br/>'
}
});
});
if(x > lastPointStepSerie.x) {
txt += '<span style="color:' + lastPointStepSerie.color + '">\u25CF</span> ' + stepSeries.name + ': <b>' + lastPointStepSerie.y + '</b><br/>'
}
return txt;
}
},

Make hover text smaller using Tipsy in D3

Tipsy is used to display a lot of text when hovering over my nodes and I'd like to make that text smaller. How do I do that?
$('.node').tipsy({
gravity: 'w',
html: true,
title: function() {
var d = this.__data__, id = d.id, inc_calls = d.inc_calls, out_calls = d.out_calls, inc_texts = d.inc_texts, out_texts = d.out_texts;
return 'Incoming Calls: ' + inc_calls + '<br/>' + 'Outgoing Calls: ' + out_calls + '<br/>' + 'Incoming Texts: ' + inc_texts + '<br/>' + 'Outgoing Texts: ' + out_texts ;
}
});
wrap the text that you are returning for title with a span which has style with font-size that you wish.. for example i have set the font size to 10 px you can reset it to a size which fits for your situation.
<span style="font-size:10px">+ your_title_text +</span>
$('.node').tipsy({
gravity: 'w',
html: true,
title: function() {
var d = this.__data__, id = d.id, inc_calls = d.inc_calls, out_calls = d.out_calls, inc_texts = d.inc_texts, out_texts = d.out_texts;
return '<span style="font-size:10px">Incoming Calls: ' + inc_calls + '<br/>' + 'Outgoing Calls: ' + out_calls + '<br/>' + 'Incoming Texts: ' + inc_texts + '<br/>' + 'Outgoing Texts: ' + out_texts + '</span>' ;
}
});

Categories