Skip to content

Commit 0b2bb2a

Browse files
committed
handle datetimes and log axes, small refactor, fix docstrings
1 parent 5f54668 commit 0b2bb2a

File tree

6 files changed

+79
-50
lines changed

6 files changed

+79
-50
lines changed

src/components/shapes/attributes.js

+3-13
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ var annAttrs = require('../annotations/attributes');
44
var fontAttrs = require('../../plots/font_attributes');
55
var scatterLineAttrs = require('../../traces/scatter/attributes').line;
66
var dash = require('../drawing/attributes').dash;
7-
var templateFormatStringDescriptionForShapes = require('../../plots/template_attributes').templateFormatStringDescriptionForShapes;
8-
var describeVariables = require('../../plots/template_attributes').describeVariables;
97
var extendFlat = require('../../lib/extend').extendFlat;
108
var templatedArray = require('../../plot_api/plot_template').templatedArray;
119
var axisPlaceableObjs = require('../../constants/axis_placeable_objects');
10+
var shapeTexttemplateAttrs = require('../../plots/template_attributes').shapeTexttemplateAttrs;
11+
var shapeLabelTexttemplateVars = require('./label_texttemplate').shapeLabelTexttemplateVars;
1212

1313
module.exports = templatedArray('shape', {
1414
visible: {
@@ -234,17 +234,7 @@ module.exports = templatedArray('shape', {
234234
editType: 'arraydraw',
235235
description: 'Sets the text to display with shape.'
236236
},
237-
texttemplate: {
238-
valType: 'string',
239-
dflt: '',
240-
editType: 'arraydraw',
241-
description: [
242-
'Template string used for rendering the shape\'s label.',
243-
'Note that this will override `text`.',
244-
templateFormatStringDescriptionForShapes(),
245-
describeVariables(['x0', 'y0', 'x1', 'y1', 'slope']),
246-
].join(' ')
247-
},
237+
texttemplate: shapeTexttemplateAttrs({}, {keys: Object.keys(shapeLabelTexttemplateVars)}),
248238
font: fontAttrs({
249239
editType: 'calc+arraydraw',
250240
colorEditType: 'arraydraw',

src/components/shapes/draw.js

+7-16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var svgTextUtils = require('../../lib/svg_text_utils');
2323
var constants = require('./constants');
2424
var helpers = require('./helpers');
2525
var getPathString = helpers.getPathString;
26+
var shapeLabelTexttemplateVars = require('./label_texttemplate').shapeLabelTexttemplateVars;
2627
var FROM_TL = require('../../constants/alignment').FROM_TL;
2728

2829

@@ -35,24 +36,11 @@ var FROM_TL = require('../../constants/alignment').FROM_TL;
3536
// if opt is blank, val can be 'add' or a full options object to add a new
3637
// annotation at that point in the array, or 'remove' to delete this one
3738

38-
var shapeLabelTemplateVars = {
39-
x0: (function(shape) { return shape.x0; }),
40-
x1: (function(shape) { return shape.x1; }),
41-
y0: (function(shape) { return shape.y0; }),
42-
y1: (function(shape) { return shape.y1; }),
43-
slope: (function(shape) { return (shape.y1 - shape.y0) / (shape.x1 - shape.x0); }),
44-
width: (function(shape) { return shape.x1 - shape.x0; }),
45-
height: (function(shape) { return shape.y1 - shape.y0; }),
46-
length: (function(shape) { return Math.sqrt(Math.pow((shape.x1 - shape.x0), 2) + Math.pow((shape.y1 - shape.y0), 2)); }),
47-
xcenter: (function(shape) { return (shape.x1 - shape.x0) / 2; }),
48-
ycenter: (function(shape) { return (shape.y1 - shape.y0) / 2; }),
49-
};
50-
5139
module.exports = {
5240
draw: draw,
5341
drawOne: drawOne,
5442
eraseActiveShape: eraseActiveShape,
55-
shapeLabelTemplateVars: Object.keys(shapeLabelTemplateVars),
43+
drawLabel: drawLabel,
5644
};
5745

5846
function draw(gd) {
@@ -627,8 +615,11 @@ function drawLabel(gd, index, options, shapeGroup) {
627615
if(options.label.texttemplate) {
628616
var templateValues = {};
629617
if(options.type !== 'path') {
630-
Object.keys(shapeLabelTemplateVars).forEach(function(key) {
631-
templateValues[key] = shapeLabelTemplateVars[key](options);
618+
var _xa = Axes.getFromId(gd, options.xref);
619+
var _ya = Axes.getFromId(gd, options.yref);
620+
Object.keys(shapeLabelTexttemplateVars).forEach(function(key) {
621+
var val = shapeLabelTexttemplateVars[key](options, _xa, _ya);
622+
if(val !== undefined) templateValues[key] = val;
632623
});
633624
}
634625
text = Lib.texttemplateStringForShapes(options.label.texttemplate,

src/components/shapes/draw_newshape/attributes.js

+4-13
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
var fontAttrs = require('../../../plots/font_attributes');
44
var dash = require('../../drawing/attributes').dash;
5-
var templateFormatStringDescriptionForShapes = require('../../../plots/template_attributes').templateFormatStringDescriptionForShapes;
6-
var describeVariables = require('../../../plots/template_attributes').describeVariables;
75
var extendFlat = require('../../../lib/extend').extendFlat;
6+
var shapeTexttemplateAttrs = require('../../../plots/template_attributes').shapeTexttemplateAttrs;
7+
var shapeLabelTexttemplateVars = require('../label_texttemplate').shapeLabelTexttemplateVars;
8+
89

910
module.exports = {
1011
newshape: {
@@ -88,17 +89,7 @@ module.exports = {
8889
editType: 'none',
8990
description: 'Sets the text to display with the new shape.'
9091
},
91-
texttemplate: {
92-
valType: 'string',
93-
dflt: '',
94-
editType: 'none',
95-
description: [
96-
'Template string used for rendering the new shape\'s label.',
97-
'Note that this will override `text`.',
98-
templateFormatStringDescriptionForShapes(),
99-
describeVariables(['x0', 'y0', 'x1', 'y1', 'slope']),
100-
].join(' ')
101-
},
92+
texttemplate: shapeTexttemplateAttrs({newshape: true, editType: 'none'}, {keys: Object.keys(shapeLabelTexttemplateVars)}),
10293
font: fontAttrs({
10394
editType: 'none',
10495
description: 'Sets the new shape label text font.'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
3+
module.exports = {
4+
shapeLabelTexttemplateVars: {
5+
x0: (function(shape, _xa) { return (_xa.type === 'date') ? shape.x0 : _xa.d2l(shape.x0); }),
6+
x1: (function(shape, _xa) { return (_xa.type === 'date') ? shape.x1 : _xa.d2l(shape.x1); }),
7+
y0: (function(shape, _xa, _ya) { return (_ya.type === 'date') ? shape.y0 : _ya.d2l(shape.y0); }),
8+
y1: (function(shape, _xa, _ya) { return (_ya.type === 'date') ? shape.y1 : _ya.d2l(shape.y1); }),
9+
slope: (function(shape, _xa, _ya) {
10+
return (_ya.d2l(shape.y1) - _ya.d2l(shape.y0)) / (_xa.d2l(shape.x1) - _xa.d2l(shape.x0));
11+
}),
12+
dx: (function(shape, _xa) { return _xa.d2l(shape.x1) - _xa.d2l(shape.x0); }),
13+
dy: (function(shape, _xa, _ya) { return _ya.d2l(shape.y1) - _ya.d2l(shape.y0); }),
14+
width: (function(shape, _xa) { return Math.abs(_xa.d2l(shape.x1) - _xa.d2l(shape.x0)); }),
15+
height: (function(shape, _xa, _ya) { return Math.abs(_ya.d2l(shape.y1) - _ya.d2l(shape.y0)); }),
16+
length: (function(shape, _xa, _ya) {
17+
return (shape.type === 'line') ? Math.sqrt(Math.pow((_xa.d2l(shape.x1) - _xa.d2l(shape.x0)), 2) + Math.pow((_ya.d2l(shape.y1) - _ya.d2l(shape.y0)), 2)) : undefined;
18+
}),
19+
xcenter: (function(shape, _xa) {
20+
var val = (_xa.d2l(shape.x1) + _xa.d2l(shape.x0)) / 2;
21+
return (_xa.type === 'date') ? _xa.l2d(val) : val;
22+
}),
23+
ycenter: (function(shape, _xa, _ya) {
24+
var val = (_ya.d2l(shape.y1) + _ya.d2l(shape.y0)) / 2;
25+
return (_ya.type === 'date') ? _ya.l2d(val) : val;
26+
}),
27+
}
28+
};

src/lib/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ function templateFormatString(string, labels, d3locale) {
11781178

11791179
// Apply mult/div operation (if applicable)
11801180
if(parsedOp) {
1181-
value = {
1181+
value = (value === undefined) ? undefined : {
11821182
'*': (function(v) { return v * parsedNumber; }),
11831183
'/': (function(v) { return v / parsedNumber; }),
11841184
}[parsedOp](value);

src/plots/template_attributes.js

+36-7
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,21 @@ function templateFormatStringDescription(opts) {
2323
].join(' ');
2424
}
2525

26-
function templateFormatStringDescriptionForShapes() {
26+
function shapeTemplateFormatStringDescription() {
2727
return [
2828
'Variables are inserted using %{variable},',
2929
'for example "x0: %{x0}".',
3030
'Numbers are formatted using d3-format\'s syntax %{variable:d3-format}, for example "Price: %{x0:$.2f}".',
3131
FORMAT_LINK,
3232
'for details on the formatting syntax.',
33-
'A single multiplication or division operation may be applied to the variable, and combined with',
34-
'd3 number formatting, for example "Length in cm: %{x0*2.54}", "%{slope*60:.1f} meters per second."'
33+
'Dates are formatted using d3-time-format\'s syntax %{variable|d3-time-format}, for example "Day: %{2019-01-01|%A}".',
34+
DATE_FORMAT_LINK,
35+
'A single multiplication or division operation may be applied to numeric variables, and combined with',
36+
'd3 number formatting, for example "Length in cm: %{x0*2.54}", "%{slope*60:.1f} meters per second."',
37+
'For log axes, variable values are given in log units.',
38+
'For date axes, x/y coordinate variables and center variables use datetimes, while all other variable values use values in ms.',
3539
].join(' ');
3640
}
37-
exports.templateFormatStringDescriptionForShapes = templateFormatStringDescriptionForShapes;
3841

3942
function describeVariables(extra) {
4043
var descPart = extra.description ? ' ' + extra.description : '';
@@ -46,14 +49,13 @@ function describeVariables(extra) {
4649
}
4750
descPart = descPart + 'Finally, the template string has access to ';
4851
if(keys.length === 1) {
49-
descPart = 'variable ' + quotedKeys[0];
52+
descPart = descPart + 'variable ' + quotedKeys[0];
5053
} else {
51-
descPart = 'variables ' + quotedKeys.slice(0, -1).join(', ') + ' and ' + quotedKeys.slice(-1) + '.';
54+
descPart = descPart + 'variables ' + quotedKeys.slice(0, -1).join(', ') + ' and ' + quotedKeys.slice(-1) + '.';
5255
}
5356
}
5457
return descPart;
5558
}
56-
exports.describeVariables = describeVariables;
5759

5860
exports.hovertemplateAttrs = function(opts, extra) {
5961
opts = opts || {};
@@ -108,3 +110,30 @@ exports.texttemplateAttrs = function(opts, extra) {
108110
}
109111
return texttemplate;
110112
};
113+
114+
115+
exports.shapeTexttemplateAttrs = function(opts, extra) {
116+
opts = opts || {};
117+
extra = extra || {};
118+
119+
var newStr = opts.newshape ? 'new ' : '';
120+
121+
var descPart = describeVariables(extra);
122+
123+
var texttemplate = {
124+
valType: 'string',
125+
dflt: '',
126+
editType: opts.editType || 'arraydraw',
127+
description: [
128+
'Template string used for rendering the ' + newStr + 'shape\'s label.',
129+
'Note that this will override `text`.',
130+
shapeTemplateFormatStringDescription(),
131+
descPart,
132+
].join(' ')
133+
};
134+
135+
if(opts.arrayOk !== false) {
136+
texttemplate.arrayOk = true;
137+
}
138+
return texttemplate;
139+
};

0 commit comments

Comments
 (0)