Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 08da201

Browse filesBrowse files
authored
Merge pull request #7360 from plotly/alex/template-null
Allow null and NaN in text templates
2 parents 93f761f + a348c24 commit 08da201
Copy full SHA for 08da201

File tree

Expand file treeCollapse file tree

4 files changed

+40
-14
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+40
-14
lines changed

‎draftlogs/7360_fix.md

Copy file name to clipboard
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix hoverlabels and other text labels with null values templated in [[#7360](https://github.com/plotly/plotly.js/pull/7360)]

‎src/lib/index.js

Copy file name to clipboardExpand all lines: src/lib/index.js
+4-8Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,9 +1067,9 @@ 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
}
1072-
return lib.isValidTextValue(v) ? v : '';
1072+
return (v !== undefined) ? v : '';
10731073
});
10741074
};
10751075

@@ -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
}

‎src/lib/nested_property.js

Copy file name to clipboardExpand all lines: src/lib/nested_property.js
+3-3Lines changed: 3 additions & 3 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;
@@ -87,7 +87,7 @@ function npGet(cont, parts) {
8787
allSame = true;
8888
out = [];
8989
for(j = 0; j < curCont.length; j++) {
90-
out[j] = npGet(curCont[j], parts.slice(i + 1))();
90+
out[j] = npGet(curCont[j], parts.slice(i + 1))(retainNull);
9191
if(out[j] !== out[0]) allSame = false;
9292
}
9393
return allSame ? out[0] : out;
@@ -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

Copy file name to clipboardExpand all lines: test/jasmine/tests/lib_test.js
+32-3Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,12 @@ describe('Test lib.js:', function() {
340340
});
341341

342342
it('should access properties of objects in an array with index -1', function() {
343-
var obj = {arr: [{a: 1}, {a: 2}, {b: 3}]};
343+
var obj = {arr: [{a: 1}, {a: null}, {b: 3}]};
344344
var prop = np(obj, 'arr[-1].a');
345345

346-
expect(prop.get()).toEqual([1, 2, undefined]);
347-
expect(obj).toEqual({arr: [{a: 1}, {a: 2}, {b: 3}]});
346+
expect(prop.get()).toEqual([1, undefined, undefined]);
347+
expect(prop.get(true)).toEqual([1, null, undefined]);
348+
expect(obj).toEqual({arr: [{a: 1}, {a: null}, {b: 3}]});
348349

349350
prop.set(5);
350351
expect(prop.get()).toBe(5);
@@ -2443,6 +2444,14 @@ describe('Test lib.js:', function() {
24432444
it('should work with the number *0* (nested case)', function() {
24442445
expect(Lib.templateString('%{x.y}', {x: {y: 0}})).toEqual('0');
24452446
});
2447+
2448+
it('preserves null and NaN', function() {
2449+
expect(Lib.templateString(
2450+
'%{a} %{b} %{c.d} %{c.e} %{f[0]} %{f[1]}',
2451+
{a: null, b: NaN, c: {d: null, e: NaN}, f: [null, NaN]}
2452+
))
2453+
.toEqual('null NaN null NaN null NaN');
2454+
});
24462455
});
24472456

24482457
describe('hovertemplateString', function() {
@@ -2471,6 +2480,16 @@ describe('Test lib.js:', function() {
24712480
expect(Lib.hovertemplateString('%{x.y}', {}, locale, {x: {y: 0}})).toEqual('0');
24722481
});
24732482

2483+
it('preserves null and NaN', function() {
2484+
expect(Lib.hovertemplateString(
2485+
'%{a} %{b} %{c.d} %{c.e} %{f[0]} %{f[1]}',
2486+
{},
2487+
locale,
2488+
{a: null, b: NaN, c: {d: null, e: NaN}, f: [null, NaN]}
2489+
))
2490+
.toEqual('null NaN null NaN null NaN');
2491+
});
2492+
24742493
it('subtitutes multiple matches', function() {
24752494
expect(Lib.hovertemplateString('foo %{group} %{trace}', {}, locale, {group: 'asdf', trace: 'jkl;'})).toEqual('foo asdf jkl;');
24762495
});
@@ -2537,6 +2556,16 @@ describe('Test lib.js:', function() {
25372556
expect(Lib.texttemplateString('y: %{y}', {yLabel: '0.1'}, locale, {y: 0.123})).toEqual('y: 0.1');
25382557
});
25392558

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

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.