Skip to content

Commit adf7ca2

Browse files
authored
Merge pull request #3734 from plotly/namelength-zero-fix
Fix namelength=0 case + implement namelength to loneHover traces
2 parents ae878a8 + b2975c9 commit adf7ca2

File tree

19 files changed

+252
-72
lines changed

19 files changed

+252
-72
lines changed

src/components/fx/attributes.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module.exports = {
3838
namelength: {
3939
valType: 'integer',
4040
min: -1,
41+
dflt: 15,
4142
arrayOk: true,
4243
role: 'style',
4344
editType: 'none',
@@ -47,7 +48,8 @@ module.exports = {
4748
'regardless of length. 0-3 shows the first 0-3 characters, and',
4849
'an integer >3 will show the whole name if it is less than that',
4950
'many characters, but if it is longer, will truncate to',
50-
'`namelength - 3` characters and add an ellipsis.'
51+
'`namelength - 3` characters and add an ellipsis.',
52+
'Note that when `hovertemplate` is set, `namelength` defaults to *-1*.'
5153
].join(' ')
5254
},
5355
editType: 'calc'

src/components/fx/defaults.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,8 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
1717
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
1818
}
1919

20-
handleHoverLabelDefaults(traceIn, traceOut, coerce, layout.hoverlabel);
20+
var opts = Lib.extendFlat({}, layout.hoverlabel);
21+
if(traceOut.hovertemplate) opts.namelength = -1;
22+
23+
handleHoverLabelDefaults(traceIn, traceOut, coerce, opts);
2124
};

src/components/fx/hover.js

+21-10
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ exports.loneHover = function loneHover(hoverItem, opts) {
124124
fontFamily: hoverItem.fontFamily,
125125
fontSize: hoverItem.fontSize,
126126
fontColor: hoverItem.fontColor,
127+
nameLength: hoverItem.nameLength,
127128

128129
// filler to make createHoverText happy
129130
trace: hoverItem.trace || {
@@ -180,6 +181,7 @@ exports.multiHovers = function multiHovers(hoverItems, opts) {
180181
fontFamily: hoverItem.fontFamily,
181182
fontSize: hoverItem.fontSize,
182183
fontColor: hoverItem.fontColor,
184+
nameLength: hoverItem.nameLength,
183185

184186
// filler to make createHoverText happy
185187
trace: hoverItem.trace || {
@@ -938,11 +940,7 @@ function createHoverText(hoverData, opts, gd) {
938940
if(fullLayout.meta) {
939941
d.name = Lib.templateString(d.name, {meta: fullLayout.meta});
940942
}
941-
942-
name = svgTextUtils.plainText(d.name || '', {
943-
len: d.nameLength,
944-
allowedTags: ['br', 'sub', 'sup', 'b', 'i', 'em']
945-
});
943+
name = plainText(d.name, d.nameLength);
946944
}
947945

948946
if(d.zLabel !== undefined) {
@@ -994,8 +992,10 @@ function createHoverText(hoverData, opts, gd) {
994992
);
995993

996994
text = text.replace(EXTRA_STRING_REGEX, function(match, extra) {
997-
name = extra; // Assign name for secondary text label
998-
return ''; // Remove from main text label
995+
// assign name for secondary text label
996+
name = plainText(extra, d.nameLength);
997+
// remove from main text label
998+
return '';
999999
});
10001000
}
10011001

@@ -1339,18 +1339,22 @@ function cleanPoint(d, hovermode) {
13391339
var cd0 = d.cd[0];
13401340
var cd = d.cd[index] || {};
13411341

1342+
function pass(v) {
1343+
return v || (isNumeric(v) && v === 0);
1344+
}
1345+
13421346
var getVal = Array.isArray(index) ?
13431347
function(calcKey, traceKey) {
1344-
return Lib.castOption(cd0, index, calcKey) ||
1345-
Lib.extractOption({}, trace, '', traceKey);
1348+
var v = Lib.castOption(cd0, index, calcKey);
1349+
return pass(v) ? v : Lib.extractOption({}, trace, '', traceKey);
13461350
} :
13471351
function(calcKey, traceKey) {
13481352
return Lib.extractOption(cd, trace, calcKey, traceKey);
13491353
};
13501354

13511355
function fill(key, calcKey, traceKey) {
13521356
var val = getVal(calcKey, traceKey);
1353-
if(val) d[key] = val;
1357+
if(pass(val)) d[key] = val;
13541358
}
13551359

13561360
fill('hoverinfo', 'hi', 'hoverinfo');
@@ -1618,3 +1622,10 @@ function spikesChanged(gd, oldspikepoints) {
16181622
) return true;
16191623
return false;
16201624
}
1625+
1626+
function plainText(s, len) {
1627+
return svgTextUtils.plainText(s || '', {
1628+
len: len,
1629+
allowedTags: ['br', 'sub', 'sup', 'b', 'i', 'em']
1630+
});
1631+
}

src/lib/svg_text_utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ var COLORMATCH = /(^|;)\s*color:/;
317317
*
318318
* @param {string} _str : input string
319319
* @param {object} opts :
320-
* - maxLen {number} max length of output string
320+
* - len {number} max length of output string
321321
* - allowedTags {array} list of pseudo-html tags to NOT strip
322322
* @return {string}
323323
*/

src/plot_api/plot_schema.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,7 @@ function getTraceAttributes(type) {
453453
if(type === 'area') {
454454
_module = { attributes: polarAreaAttrs };
455455
basePlotModule = {};
456-
}
457-
else {
456+
} else {
458457
_module = Registry.modules[type]._module,
459458
basePlotModule = _module.basePlotModule;
460459
}
@@ -464,7 +463,6 @@ function getTraceAttributes(type) {
464463
// make 'type' the first attribute in the object
465464
attributes.type = null;
466465

467-
468466
var copyBaseAttributes = extendDeepAll({}, baseAttributes);
469467
var copyModuleAttributes = extendDeepAll({}, _module.attributes);
470468

@@ -478,6 +476,22 @@ function getTraceAttributes(type) {
478476
// base attributes (same for all trace types)
479477
extendDeepAll(attributes, copyBaseAttributes);
480478

479+
// prune-out base attributes based on trace module categories
480+
if(Registry.traceIs(type, 'noOpacity')) {
481+
delete attributes.opacity;
482+
}
483+
if(!Registry.traceIs(type, 'showLegend')) {
484+
delete attributes.showlegend;
485+
delete attributes.legendgroup;
486+
}
487+
if(Registry.traceIs(type, 'noHover')) {
488+
delete attributes.hoverinfo;
489+
delete attributes.hoverlabel;
490+
}
491+
if(!_module.selectPoints) {
492+
delete attributes.selectedpoints;
493+
}
494+
481495
// module attributes
482496
extendDeepAll(attributes, copyModuleAttributes);
483497

src/plots/gl2d/scene2d.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,8 @@ proto.draw = function() {
686686
borderColor: Fx.castHoverOption(trace, ptNumber, 'bordercolor'),
687687
fontFamily: Fx.castHoverOption(trace, ptNumber, 'font.family'),
688688
fontSize: Fx.castHoverOption(trace, ptNumber, 'font.size'),
689-
fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color')
689+
fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color'),
690+
nameLength: Fx.castHoverOption(trace, ptNumber, 'namelength')
690691
}, {
691692
container: this.svgContainer,
692693
gd: this.graphDiv

src/plots/gl3d/scene.js

+22-20
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var computeTickMarks = require('./layout/tick_marks');
3232
var STATIC_CANVAS, STATIC_CONTEXT;
3333

3434
function render(scene) {
35+
var gd = scene.graphDiv;
3536
var trace;
3637

3738
// update size of svg container
@@ -70,6 +71,7 @@ function render(scene) {
7071
if(lastPicked !== null) {
7172
var pdata = project(scene.glplot.cameraParams, selection.dataCoordinate);
7273
trace = lastPicked.data;
74+
var traceNow = gd._fullData[trace.index];
7375
var ptNumber = selection.index;
7476

7577
var labels = {
@@ -78,11 +80,11 @@ function render(scene) {
7880
zLabel: formatter('zaxis', selection.traceCoordinate[2])
7981
};
8082

81-
var hoverinfo = Fx.castHoverinfo(trace, scene.fullLayout, ptNumber);
83+
var hoverinfo = Fx.castHoverinfo(traceNow, scene.fullLayout, ptNumber);
8284
var hoverinfoParts = (hoverinfo || '').split('+');
8385
var isHoverinfoAll = hoverinfo && hoverinfo === 'all';
8486

85-
if(!trace.hovertemplate && !isHoverinfoAll) {
87+
if(!traceNow.hovertemplate && !isHoverinfoAll) {
8688
if(hoverinfoParts.indexOf('x') === -1) labels.xLabel = undefined;
8789
if(hoverinfoParts.indexOf('y') === -1) labels.yLabel = undefined;
8890
if(hoverinfoParts.indexOf('z') === -1) labels.zLabel = undefined;
@@ -138,55 +140,55 @@ function render(scene) {
138140
x: selection.traceCoordinate[0],
139141
y: selection.traceCoordinate[1],
140142
z: selection.traceCoordinate[2],
141-
data: trace._input,
142-
fullData: trace,
143-
curveNumber: trace.index,
143+
data: traceNow._input,
144+
fullData: traceNow,
145+
curveNumber: traceNow.index,
144146
pointNumber: ptNumber
145147
};
146148

147-
Fx.appendArrayPointValue(pointData, trace, ptNumber);
149+
Fx.appendArrayPointValue(pointData, traceNow, ptNumber);
148150

149151
if(trace._module.eventData) {
150-
pointData = trace._module.eventData(pointData, selection, trace, {}, ptNumber);
152+
pointData = traceNow._module.eventData(pointData, selection, traceNow, {}, ptNumber);
151153
}
152154

153155
var eventData = {points: [pointData]};
154156

155157
if(scene.fullSceneLayout.hovermode) {
156158
Fx.loneHover({
157-
trace: trace,
159+
trace: traceNow,
158160
x: (0.5 + 0.5 * pdata[0] / pdata[3]) * width,
159161
y: (0.5 - 0.5 * pdata[1] / pdata[3]) * height,
160162
xLabel: labels.xLabel,
161163
yLabel: labels.yLabel,
162164
zLabel: labels.zLabel,
163165
text: tx,
164166
name: lastPicked.name,
165-
color: Fx.castHoverOption(trace, ptNumber, 'bgcolor') || lastPicked.color,
166-
borderColor: Fx.castHoverOption(trace, ptNumber, 'bordercolor'),
167-
fontFamily: Fx.castHoverOption(trace, ptNumber, 'font.family'),
168-
fontSize: Fx.castHoverOption(trace, ptNumber, 'font.size'),
169-
fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color'),
170-
hovertemplate: Lib.castOption(trace, ptNumber, 'hovertemplate'),
167+
color: Fx.castHoverOption(traceNow, ptNumber, 'bgcolor') || lastPicked.color,
168+
borderColor: Fx.castHoverOption(traceNow, ptNumber, 'bordercolor'),
169+
fontFamily: Fx.castHoverOption(traceNow, ptNumber, 'font.family'),
170+
fontSize: Fx.castHoverOption(traceNow, ptNumber, 'font.size'),
171+
fontColor: Fx.castHoverOption(traceNow, ptNumber, 'font.color'),
172+
nameLength: Fx.castHoverOption(traceNow, ptNumber, 'namelength'),
173+
hovertemplate: Lib.castOption(traceNow, ptNumber, 'hovertemplate'),
171174
hovertemplateLabels: Lib.extendFlat({}, pointData, labels),
172175
eventData: [pointData]
173176
}, {
174177
container: svgContainer,
175-
gd: scene.graphDiv
178+
gd: gd
176179
});
177180
}
178181

179182
if(selection.buttons && selection.distance < 5) {
180-
scene.graphDiv.emit('plotly_click', eventData);
183+
gd.emit('plotly_click', eventData);
181184
} else {
182-
scene.graphDiv.emit('plotly_hover', eventData);
185+
gd.emit('plotly_hover', eventData);
183186
}
184187

185188
oldEventData = eventData;
186-
}
187-
else {
189+
} else {
188190
Fx.loneUnhover(svgContainer);
189-
scene.graphDiv.emit('plotly_unhover', oldEventData);
191+
gd.emit('plotly_unhover', oldEventData);
190192
}
191193

192194
scene.drawAnnotations(scene);

src/plots/plots.js

+14-27
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
12231223
if(subplots[attri]) Lib.pushUnique(subplots[attri], vali);
12241224
subplotId += vali;
12251225
}
1226-
}
1227-
else {
1226+
} else {
12281227
subplotId = Lib.coerce(traceIn, traceOut, subplotAttrs, subplotAttr);
12291228
}
12301229

@@ -1235,18 +1234,6 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
12351234
}
12361235
}
12371236

1238-
function coerceUnlessPruned(attr, dflt, cb) {
1239-
if(_module && (attr in _module.attributes) && _module.attributes[attr] === undefined) {
1240-
// Pruned
1241-
} else {
1242-
if(cb && typeof cb === 'function') {
1243-
cb();
1244-
} else {
1245-
coerce(attr, dflt);
1246-
}
1247-
}
1248-
}
1249-
12501237
if(visible) {
12511238
coerce('customdata');
12521239
coerce('ids');
@@ -1255,33 +1242,33 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
12551242
traceOut._dfltShowLegend = true;
12561243
coerce('showlegend');
12571244
coerce('legendgroup');
1258-
}
1259-
else {
1245+
} else {
12601246
traceOut._dfltShowLegend = false;
12611247
}
12621248

1263-
coerceUnlessPruned('hoverlabel', '', function() {
1264-
Registry.getComponentMethod(
1265-
'fx',
1266-
'supplyDefaults'
1267-
)(traceIn, traceOut, defaultColor, layout);
1268-
});
1269-
1270-
// TODO add per-base-plot-module trace defaults step
1271-
12721249
if(_module) {
12731250
_module.supplyDefaults(traceIn, traceOut, defaultColor, layout);
1274-
if(!traceOut.hovertemplate) Lib.coerceHoverinfo(traceIn, traceOut, layout);
12751251
}
12761252

1277-
if(!Registry.traceIs(traceOut, 'noOpacity')) coerce('opacity');
1253+
if(!Registry.traceIs(traceOut, 'noOpacity')) {
1254+
coerce('opacity');
1255+
}
12781256

12791257
if(Registry.traceIs(traceOut, 'notLegendIsolatable')) {
12801258
// This clears out the legendonly state for traces like carpet that
12811259
// cannot be isolated in the legend
12821260
traceOut.visible = !!traceOut.visible;
12831261
}
12841262

1263+
if(!Registry.traceIs(traceOut, 'noHover')) {
1264+
if(!traceOut.hovertemplate) Lib.coerceHoverinfo(traceIn, traceOut, layout);
1265+
1266+
// parcats support hover, but not hoverlabel stylings (yet)
1267+
if(traceOut.type !== 'parcats') {
1268+
Registry.getComponentMethod('fx', 'supplyDefaults')(traceIn, traceOut, defaultColor, layout);
1269+
}
1270+
}
1271+
12851272
if(_module && _module.selectPoints) {
12861273
coerce('selectedpoints');
12871274
}

src/traces/parcoords/attributes.js

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ var templatedArray = require('../../plot_api/plot_template').templatedArray;
2020
module.exports = {
2121
domain: domainAttrs({name: 'parcoords', trace: true, editType: 'calc'}),
2222

23-
hoverlabel: undefined,
24-
2523
labelfont: fontAttrs({
2624
editType: 'calc',
2725
description: 'Sets the font for the `dimension` labels.'

src/traces/parcoords/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Parcoords.colorbar = {
2323
Parcoords.moduleType = 'trace';
2424
Parcoords.name = 'parcoords';
2525
Parcoords.basePlotModule = require('./base_plot');
26-
Parcoords.categories = ['gl', 'regl', 'noOpacity'];
26+
Parcoords.categories = ['gl', 'regl', 'noOpacity', 'noHover'];
2727
Parcoords.meta = {
2828
description: [
2929
'Parallel coordinates for multidimensional exploratory data analysis.',

src/traces/pie/plot.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,11 @@ function attachFxHandlers(sliceTop, gd, cd) {
363363
pt.percentLabel = helpers.formatPiePercent(pt.percent, separators);
364364
if(hoverinfo && hoverinfo.indexOf('percent') !== -1) thisText.push(pt.percentLabel);
365365

366-
var hoverLabel = trace.hoverlabel;
366+
var hoverLabel = trace2.hoverlabel;
367367
var hoverFont = hoverLabel.font;
368368

369369
Fx.loneHover({
370+
trace: trace,
370371
x0: hoverCenterX - rInscribed * cd0.r,
371372
x1: hoverCenterX + rInscribed * cd0.r,
372373
y: hoverCenterY,
@@ -378,8 +379,7 @@ function attachFxHandlers(sliceTop, gd, cd) {
378379
fontFamily: helpers.castOption(hoverFont.family, pt.pts),
379380
fontSize: helpers.castOption(hoverFont.size, pt.pts),
380381
fontColor: helpers.castOption(hoverFont.color, pt.pts),
381-
382-
trace: trace2,
382+
nameLength: helpers.castOption(hoverLabel.namelength, pt.pts),
383383
hovertemplate: helpers.castOption(trace2.hovertemplate, pt.pts),
384384
hovertemplateLabels: pt,
385385
eventData: [eventData(pt, trace2)]

0 commit comments

Comments
 (0)