Skip to content

Commit 4eaad9b

Browse files
authored
Merge pull request #3548 from plotly/more-meta
More layout meta support
2 parents 5925c10 + a0ff6a1 commit 4eaad9b

File tree

10 files changed

+128
-17
lines changed

10 files changed

+128
-17
lines changed

Diff for: src/components/fx/hover.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
738738
var EXTRA_STRING_REGEX = /<extra>([\s\S]*)<\/extra>/;
739739

740740
function createHoverText(hoverData, opts, gd) {
741+
var fullLayout = gd._fullLayout;
741742
var hovermode = opts.hovermode;
742743
var rotateLabels = opts.rotateLabels;
743744
var bgColor = opts.bgColor;
@@ -925,6 +926,10 @@ function createHoverText(hoverData, opts, gd) {
925926
if(d.nameOverride !== undefined) d.name = d.nameOverride;
926927

927928
if(d.name) {
929+
if(fullLayout.meta) {
930+
d.name = Lib.templateString(d.name, {meta: fullLayout.meta});
931+
}
932+
928933
name = svgTextUtils.plainText(d.name || '', {
929934
len: d.nameLength,
930935
allowedTags: ['br', 'sub', 'sup', 'b', 'i', 'em']
@@ -970,7 +975,12 @@ function createHoverText(hoverData, opts, gd) {
970975
var hovertemplateLabels = d.hovertemplateLabels || d;
971976
var eventData = d.eventData[0] || {};
972977
if(hovertemplate) {
973-
text = Lib.hovertemplateString(hovertemplate, hovertemplateLabels, eventData);
978+
text = Lib.hovertemplateString(
979+
hovertemplate,
980+
hovertemplateLabels,
981+
eventData,
982+
{meta: fullLayout.meta}
983+
);
974984

975985
text = text.replace(EXTRA_STRING_REGEX, function(match, extra) {
976986
name = extra; // Assign name for secondary text label

Diff for: src/components/legend/draw.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,13 @@ function drawTexts(g, gd, maxLength) {
404404
var trace = legendItem.trace;
405405
var isPie = Registry.traceIs(trace, 'pie');
406406
var traceIndex = trace.index;
407-
var name = isPie ? legendItem.label : trace.name;
408407
var isEditable = gd._context.edits.legendText && !isPie;
409408

409+
var name = isPie ? legendItem.label : trace.name;
410+
if(fullLayout.meta) {
411+
name = Lib.templateString(name, {meta: fullLayout.meta});
412+
}
413+
410414
var textEl = Lib.ensureSingle(g, 'text', 'legendtext');
411415

412416
textEl.attr('text-anchor', 'start')

Diff for: src/components/rangeselector/draw.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ var FROM_BR = alignmentConstants.FROM_BR;
2626
var constants = require('./constants');
2727
var getUpdateObject = require('./get_update_object');
2828

29-
3029
module.exports = function draw(gd) {
3130
var fullLayout = gd._fullLayout;
3231

@@ -152,12 +151,16 @@ function drawButtonText(button, selectorLayout, d, gd) {
152151
});
153152

154153
text.call(Drawing.font, selectorLayout.font)
155-
.text(getLabel(d))
154+
.text(getLabel(d, gd._fullLayout.meta))
156155
.call(textLayout);
157156
}
158157

159-
function getLabel(opts) {
160-
if(opts.label) return opts.label;
158+
function getLabel(opts, meta) {
159+
if(opts.label) {
160+
return meta ?
161+
Lib.templateString(opts.label, {meta: meta}) :
162+
opts.label;
163+
}
161164

162165
if(opts.step === 'all') return 'all';
163166

Diff for: src/components/sliders/draw.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ function drawCurrentValue(sliderGroup, sliderOpts, valueOverride) {
317317
str += valueOverride;
318318
} else {
319319
var curVal = sliderOpts.steps[sliderOpts.active].label;
320+
var meta = sliderOpts._gd._fullLayout.meta;
321+
if(meta) {
322+
curVal = Lib.templateString(curVal, {meta: meta});
323+
}
320324
str += curVal;
321325
}
322326

@@ -364,8 +368,14 @@ function drawLabel(item, data, sliderOpts) {
364368
});
365369
});
366370

371+
var tx = data.step.label;
372+
var meta = sliderOpts._gd._fullLayout.meta;
373+
if(meta) {
374+
tx = Lib.templateString(tx, {meta: meta});
375+
}
376+
367377
text.call(Drawing.font, sliderOpts.font)
368-
.text(data.step.label)
378+
.text(tx)
369379
.call(svgTextUtils.convertToTspans, sliderOpts._gd);
370380

371381
return text;

Diff for: src/components/updatemenus/draw.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,14 @@ function drawItemText(item, menuOpts, itemOpts, gd) {
442442
});
443443
});
444444

445+
var tx = itemOpts.label;
446+
var meta = gd._fullLayout.meta;
447+
if(meta) {
448+
tx = Lib.templateString(tx, {meta: meta});
449+
}
450+
445451
text.call(Drawing.font, menuOpts.font)
446-
.text(itemOpts.label)
452+
.text(tx)
447453
.call(svgTextUtils.convertToTspans, gd);
448454
}
449455

Diff for: src/lib/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ lib.numSeparate = function(value, separators, separatethousands) {
994994
return x1 + x2;
995995
};
996996

997-
var TEMPLATE_STRING_REGEX = /%{([^\s%{}:]*)(:[^}]*)?}/g;
997+
lib.TEMPLATE_STRING_REGEX = /%{([^\s%{}:]*)(:[^}]*)?}/g;
998998
var SIMPLE_PROPERTY_REGEX = /^\w*$/;
999999

10001000
/**
@@ -1014,7 +1014,7 @@ lib.templateString = function(string, obj) {
10141014
// just in case it speeds things up *slightly*:
10151015
var getterCache = {};
10161016

1017-
return string.replace(TEMPLATE_STRING_REGEX, function(dummy, key) {
1017+
return string.replace(lib.TEMPLATE_STRING_REGEX, function(dummy, key) {
10181018
if(SIMPLE_PROPERTY_REGEX.test(key)) {
10191019
return obj[key] || '';
10201020
}
@@ -1047,7 +1047,7 @@ lib.hovertemplateString = function(string, labels) {
10471047
// just in case it speeds things up *slightly*:
10481048
var getterCache = {};
10491049

1050-
return string.replace(TEMPLATE_STRING_REGEX, function(match, key, format) {
1050+
return string.replace(lib.TEMPLATE_STRING_REGEX, function(match, key, format) {
10511051
var obj, value, i;
10521052
for(i = 2; i < args.length; i++) {
10531053
obj = args[i];

Diff for: src/plots/layout_attributes.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,9 @@ module.exports = {
416416
editType: 'plot',
417417
description: [
418418
'Assigns extra meta information that can be used in various `text` attributes.',
419-
'Attributes such as the graph, axis and colorbar `title.text` and annotation `text`',
420-
'support `meta`. One can access `meta` fields using template strings:',
419+
'Attributes such as the graph, axis and colorbar `title.text`, annotation `text`',
420+
'`trace.name` in legend items, `rangeselector`, `updatemenues` and `sliders` `label` text',
421+
'all support `meta`. One can access `meta` fields using template strings:',
421422
'`%{meta[i]}` where `i` is the index of the `meta`',
422423
'item in question.'
423424
].join(' ')

Diff for: test/image/baselines/layout_metatext.png

4.21 KB
Loading

Diff for: test/image/mocks/layout_metatext.json

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"data": [{
3-
"y": [1, 2, 1]
3+
"x": ["2019-01-01", "2019-02-10", "2019-03-24"],
4+
"y": [1, 2, 1],
5+
"name": "TRACE %{meta[3]}"
46
}, {
57
"type": "scatterpolar",
68
"r": [1, 2, 1]
@@ -29,12 +31,20 @@
2931
"width": 700,
3032
"height": 800,
3133
"margin": {"b": 40},
32-
"showlegend": false,
3334

3435
"title": {"text": "This graph is %{meta[2]}"},
3536
"xaxis": {
3637
"domain": {"row": 0, "column": 0},
37-
"title": {"text": "Worth more than %{meta[4]} %{meta[1]}"}
38+
"title": {"text": "Worth more than %{meta[4]} %{meta[1]}"},
39+
"rangeselector": {
40+
"buttons": [{
41+
"step": "all"
42+
}, {
43+
"step": "month",
44+
"count": 2,
45+
"label": "backup %{meta[2]}"
46+
}]
47+
}
3848
},
3949
"yaxis": {
4050
"domain": {"row": 0, "column": 0},
@@ -78,8 +88,30 @@
7888
"text": "<i>N.B.</i> %{meta[2]}",
7989
"xref": "x",
8090
"yref": "y",
81-
"x": 1,
91+
"x": "2019-02-10",
8292
"y": 2
93+
}],
94+
95+
"updatemenus": [{
96+
"buttons": [{
97+
"label": "Btn-%{meta[0]}",
98+
"method": "restyle",
99+
"args": ["visible", false]
100+
}],
101+
"y": 1,
102+
"yanchor": "bottom"
103+
}],
104+
105+
"sliders": [{
106+
"steps": [{
107+
"label": "step-%{meta[0]}",
108+
"method": "restyle",
109+
"args": ["marker.color", "red"]
110+
}, {
111+
"label": "step-%{meta[1]}",
112+
"method": "restyle",
113+
"args": ["marker.color", "blue"]
114+
}]
83115
}]
84116
}
85117
}

Diff for: test/jasmine/tests/hover_label_test.js

+45
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,51 @@ describe('hover info', function() {
17331733
.catch(failTest)
17341734
.then(done);
17351735
});
1736+
1737+
it('should work with layout.meta references', function(done) {
1738+
var gd = document.getElementById('graph');
1739+
1740+
Plotly.update(gd,
1741+
{hovertemplate: 'TRACE -- %{meta[0]}<extra>%{meta[1]}</extra>'},
1742+
{meta: ['A', '$$$']}
1743+
).then(function() {
1744+
Fx.hover('graph', evt, 'xy');
1745+
1746+
assertHoverLabelContent({
1747+
nums: 'TRACE -- A',
1748+
name: '$$$',
1749+
axis: '0.388'
1750+
});
1751+
})
1752+
.catch(failTest)
1753+
.then(done);
1754+
});
1755+
});
1756+
1757+
it('should work with trace.name linked to layout.meta', function(done) {
1758+
var gd = createGraphDiv();
1759+
1760+
Plotly.plot(gd, [{
1761+
y: [1, 1, 1],
1762+
name: '%{meta[0]}',
1763+
marker: {size: 40}
1764+
}, {
1765+
y: [1]
1766+
}], {
1767+
meta: ['yo!'],
1768+
width: 400,
1769+
height: 400
1770+
})
1771+
.then(function() { _hoverNatural(gd, 200, 200); })
1772+
.then(function() {
1773+
assertHoverLabelContent({
1774+
nums: '1',
1775+
name: 'yo!',
1776+
axis: '2'
1777+
});
1778+
})
1779+
.catch(failTest)
1780+
.then(done);
17361781
});
17371782
});
17381783

0 commit comments

Comments
 (0)