8000 allow null and NaN values to be shown in hovertemplates and other tex… · plotly/plotly.js@94f76cb · GitHub
[go: up one dir, main page]

Skip to content

Commit 94f76cb

Browse files
committed
allow null and NaN values to be shown in hovertemplates and other text templates
1 parent 046d0ec commit 94f76cb

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

src/lib/index.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ lib.templateString = function(string, obj) {
10671067
v = obj[key];
10681068
} else {
10691069
getterCache[key] = getterCache[key] || lib.nestedProperty(obj, key).get;
1070-
v = getterCache[key]();
1070+
v = getterCache[key](true); // true means don't replace undefined with null
10711071
}
10721072
return lib.isValidTextValue(v) ? v : '';
10731073
});
@@ -1132,9 +1132,6 @@ function templateFormatString(string, labels, d3locale) {
11321132
var opts = this;
11331133
var args = arguments;
11341134
if(!labels) labels = {};
1135-
// Not all that useful, but cache nestedProperty instantiation
1136-
// just in case it speeds things up *slightly*:
1137-
var getterCache = {};
11381135

11391136
return string.replace(lib.TEMPLATE_STRING_REGEX, function(match, rawKey, format) {
11401137
var isOther =
@@ -1185,9 +1182,8 @@ function templateFormatString(string, labels, d3locale) {
11851182
}
11861183

11871184
if(!SIMPLE_PROPERTY_REGEX.test(key)) {
1188-
value = lib.nestedProperty(obj, key).get();
1189-
value = getterCache[key] || lib.nestedProperty(obj, key).get();
1190-
if(value) getterCache[key] = value;
1185+
// true here means don't convert null to undefined
1186+
value = lib.nestedProperty(obj, key).get(true);
11911187
}
11921188
if(value !== undefined) break;
11931189
}
@@ -1310,9 +1306,9 @@ lib.fillText = function(calcPt, trace, contOut) {
13101306
if(lib.isValidTextValue(tx)) return fill(tx);
13111307
};
13121308

1313-
// accept all truthy values and 0 (which gets cast to '0' in the hover labels)
1309+
// accept anything but undefined - was all truthy values and 0 (which gets cast to '0' in the hover labels)
13141310
lib.isValidTextValue = function(v) {
1315-
return v || v === 0;
1311+
return v !== undefined;
13161312
};
13171313

13181314
/**

src/lib/nested_property.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ module.exports = function nestedProperty(container, propStr) {
7373
};
7474

7575
function npGet(cont, parts) {
76-
return function() {
76+
return function(retainNull) {
7777
var curCont = cont;
7878
var curPart;
7979
var allSame;
@@ -105,7 +105,7 @@ function npGet(cont, parts) {
105105
if(typeof curCont !== 'object' || curCont === null) return undefined;
106106

107107
out = curCont[parts[i]];
108-
if(out === null) return undefined;
108+
if(!retainNull && (out === null)) return undefined;
109109
return out;
110110
};
111111
}

test/jasmine/tests/lib_test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,6 +2443,14 @@ describe('Test lib.js:', function() {
24432443
it('should work with the number *0* (nested case)', function() {
24442444
expect(Lib.templateString('%{x.y}', {x: {y: 0}})).toEqual('0');
24452445
});
2446+
2447+
it('preserves null and NaN', function() {
2448+
expect(Lib.templateString(
2449+
'%{a} %{b} %{c.d} %{c.e} %{f[0]} %{f[1]}',
2450+
{a: null, b: NaN, c: {d: null, e: NaN}, f: [null, NaN]}
2451+
))
2452+
.toEqual('null NaN null NaN null NaN');
2453+
});
24462454
});
24472455

24482456
describe('hovertemplateString', function() {
@@ -2471,6 +2479,16 @@ describe('Test lib.js:', function() {
24712479
expect(Lib.hovertemplateString('%{x.y}', {}, locale, {x: {y: 0}})).toEqual('0');
24722480
});
24732481

2482+
it('preserves null and NaN', function() {
2483+
expect(Lib.hovertemplateString(
2484+
'%{a} %{b} %{c.d} %{c.e} %{f[0]} %{f[1]}',
2485+
{},
2486+
locale,
2487+
{a: null, b: NaN, c: {d: null, e: NaN}, f: [null, NaN]}
2488+
))
2489+
.toEqual('null NaN null NaN null NaN');
2490+
});
2491+
24742492
it('subtitutes multiple matches', function() {
24752493
expect(Lib.hovertemplateString('foo %{group} %{trace}', {}, locale, {group: 'asdf', trace: 'jkl;'})).toEqual('foo asdf jkl;');
24762494
});
@@ -2537,6 +2555,16 @@ describe('Test lib.js:', function() {
25372555
expect(Lib.texttemplateString('y: %{y}', {yLabel: '0.1'}, locale, {y: 0.123})).toEqual('y: 0.1');
25382556
});
25392557

2558+
it('preserves null and NaN', function() {
2559+
expect(Lib.texttemplateString(
2560+
'%{a} %{b} %{c.d} %{c.e} %{f[0]} %{f[1]}',
2561+
{},
2562+
locale,
2563+
{a: null, b: NaN, c: {d: null, e: NaN}, f: [null, NaN]}
2564+
))
2565+
.toEqual('null NaN null NaN null NaN');
2566+
});
2567+
25402568
it('warns user up to 10 times if a variable cannot be found', function() {
25412569
spyOn(Lib, 'warn').and.callThrough();
25422570
Lib.texttemplateString('%{idontexist}', {});

0 commit comments

Comments
 (0)
0