Skip to content

Commit 2100fe9

Browse files
committed
Merge remote-tracking branch 'origin/master' into switch-to-kaleido
2 parents 09eb8fa + 4f54bcd commit 2100fe9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+490
-299
lines changed

package-lock.json

Lines changed: 43 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@
6262
]
6363
},
6464
"dependencies": {
65-
"@plotly/d3": "^3.6.0",
65+
"@plotly/d3": "^3.6.1",
6666
"@plotly/d3-sankey": "0.7.2",
6767
"@plotly/d3-sankey-circular": "0.33.1",
6868
"@plotly/point-cluster": "^3.1.9",
69-
"@turf/area": "^6.0.1",
70-
"@turf/bbox": "^6.0.1",
69+
"@turf/area": "^6.4.0",
70+
"@turf/bbox": "^6.4.0",
7171
"@turf/centroid": "^6.0.2",
7272
"alpha-shape": "^1.0.0",
7373
"canvas-fit": "^1.5.0",

src/components/legend/draw.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -393,20 +393,26 @@ function drawTexts(g, gd, legendObj) {
393393
var isEditable = !legendObj._inHover && gd._context.edits.legendText && !isPieLike;
394394
var maxNameLength = legendObj._maxNameLength;
395395

396-
var name;
397-
if(!legendObj.entries) {
398-
name = isPieLike ? legendItem.label : trace.name;
399-
if(trace._meta) {
400-
name = Lib.templateString(name, trace._meta);
401-
}
396+
var name, font;
397+
if(legendItem.groupTitle) {
398+
name = legendItem.groupTitle.text;
399+
font = legendItem.groupTitle.font;
402400
} else {
403-
name = legendItem.text;
401+
font = legendObj.font;
402+
if(!legendObj.entries) {
403+
name = isPieLike ? legendItem.label : trace.name;
404+
if(trace._meta) {
405+
name = Lib.templateString(name, trace._meta);
406+
}
407+
} else {
408+
name = legendItem.text;
409+
}
404410
}
405411

406412
var textEl = Lib.ensureSingle(g, 'text', 'legendtext');
407413

408414
textEl.attr('text-anchor', 'start')
409-
.call(Drawing.font, legendObj.font)
415+
.call(Drawing.font, font)
410416
.text(isEditable ? ensureLength(name, maxNameLength) : name);
411417

412418
var textGap = legendObj.itemwidth + constants.itemGap * 2;
@@ -512,7 +518,15 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
512518
var mathjaxNode = mathjaxGroup.node();
513519
if(!legendObj) legendObj = gd._fullLayout.legend;
514520
var bw = legendObj.borderwidth;
515-
var lineHeight = (aTitle === MAIN_TITLE ? legendObj.title : legendObj).font.size * LINE_SPACING;
521+
var font;
522+
if(aTitle === MAIN_TITLE) {
523+
font = legendObj.title.font;
524+
} else if(legendItem.groupTitle) {
525+
font = legendItem.groupTitle.font;
526+
} else {
527+
font = legendObj.font;
528+
}
529+
var lineHeight = font.size * LINE_SPACING;
516530
var height, width;
517531

518532
if(mathjaxNode) {
@@ -549,8 +563,14 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
549563
bw + lineHeight
550564
);
551565
} else { // legend item
566+
var x = constants.itemGap * 2 + legendObj.itemwidth;
567+
if(legendItem.groupTitle) {
568+
x = constants.itemGap;
569+
width -= legendObj.itemwidth;
570+
}
571+
552572
svgTextUtils.positionText(textEl,
553-
legendObj.itemwidth + constants.itemGap * 2,
573+
x,
554574
-lineHeight * ((textLines - 1) / 2 - 0.3)
555575
);
556576
}

src/components/legend/get_legend_data.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,33 @@ module.exports = function getLegendData(calcdata, opts) {
117117
// sort considering trace.legendrank and legend.traceorder
118118
legendData[i].forEach(function(a, k) { a._preSort = k; });
119119
legendData[i].sort(orderFn2);
120+
121+
var firstItem = legendData[i][0];
122+
123+
var groupTitle = null;
124+
// get group title text
125+
for(j = 0; j < legendData[i].length; j++) {
126+
var gt = legendData[i][j].trace.legendgrouptitle;
127+
if(gt && gt.text) {
128+
groupTitle = gt;
129+
break;
130+
}
131+
}
132+
133+
// reverse order
120134
if(reversed) legendData[i].reverse();
121135

136+
if(groupTitle) {
137+
// set group title text
138+
legendData[i].unshift({
139+
i: -1,
140+
groupTitle: groupTitle,
141+
trace: {
142+
showlegend: firstItem.trace.showlegend
143+
}
144+
});
145+
}
146+
122147
// rearrange lgroupToTraces into a d3-friendly array of arrays
123148
for(j = 0; j < legendData[i].length; j++) {
124149
legendData[i][j] = [

src/components/legend/handle_click.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ module.exports = function handleClick(g, gd, numClicks) {
3232
[];
3333

3434
var legendItem = g.data()[0][0];
35+
if(legendItem.groupTitle) return; // no click on group legends for now
36+
3537
var fullData = gd._fullData;
3638
var fullTrace = legendItem.trace;
3739
var legendgroup = fullTrace.legendgroup;

src/lib/dates.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,19 @@ exports.cleanDate = function(v, dflt, calendar) {
370370
*/
371371

372372
/*
373-
* modDateFormat: Support world calendars, and add one item to
373+
* modDateFormat: Support world calendars, and add two items to
374374
* d3's vocabulary:
375375
* %{n}f where n is the max number of digits of fractional seconds
376+
* %h formats: half of the year as a decimal number [1,2]
376377
*/
377378
var fracMatch = /%\d?f/g;
379+
var halfYearMatch = /%h/g;
380+
var quarterToHalfYear = {
381+
'1': '1',
382+
'2': '1',
383+
'3': '2',
384+
'4': '2',
385+
};
378386
function modDateFormat(fmt, x, formatter, calendar) {
379387
fmt = fmt.replace(fracMatch, function(match) {
380388
var digits = Math.min(+(match.charAt(1)) || 6, 6);
@@ -386,6 +394,10 @@ function modDateFormat(fmt, x, formatter, calendar) {
386394

387395
var d = new Date(Math.floor(x + 0.05));
388396

397+
fmt = fmt.replace(halfYearMatch, function() {
398+
return quarterToHalfYear[formatter('%q')(d)];
399+
});
400+
389401
if(isWorldCalendar(calendar)) {
390402
try {
391403
fmt = Registry.getComponentMethod('calendars', 'worldCalFmt')(fmt, x, calendar);

src/plots/attributes.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
var fontAttrs = require('./font_attributes');
34
var fxAttrs = require('../components/fx/attributes');
45

56
module.exports = {
@@ -41,6 +42,23 @@ module.exports = {
4142
'when toggling legend items.'
4243
].join(' ')
4344
},
45+
legendgrouptitle: {
46+
text: {
47+
valType: 'string',
48+
dflt: '',
49+
editType: 'style',
50+
description: [
51+
'Sets the title of the legend group.'
52+
].join(' ')
53+
},
54+
font: fontAttrs({
55+
editType: 'style',
56+
description: [
57+
'Sets this legend group\'s title font.'
58+
].join(' '),
59+
}),
60+
editType: 'style',
61+
},
4462
legendrank: {
4563
valType: 'number',
4664
dflt: 1000,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
var docs = require('../../constants/docs');
4+
var FORMAT_LINK = docs.FORMAT_LINK;
5+
var DATE_FORMAT_LINK = docs.DATE_FORMAT_LINK;
6+
7+
function axisHoverFormat(x, noDates) {
8+
return {
9+
valType: 'string',
10+
dflt: '',
11+
editType: 'none',
12+
description: (
13+
noDates ? descriptionOnlyNumbers : descriptionWithDates
14+
)('hover text', x) + [
15+
'By default the values are formatted using ' + (
16+
noDates ?
17+
'generic number format' :
18+
('`' + x + 'axis.hoverformat`')
19+
) + '.',
20+
].join(' ')
21+
};
22+
}
23+
24+
function descriptionOnlyNumbers(label, x) {
25+
return [
26+
'Sets the ' + label + ' formatting rule' + (x ? 'for `' + x + '` ' : ''),
27+
'using d3 formatting mini-languages',
28+
'which are very similar to those in Python. For numbers, see: ' + FORMAT_LINK + '.'
29+
].join(' ');
30+
}
31+
32+
function descriptionWithDates(label, x) {
33+
return descriptionOnlyNumbers(label, x) + [
34+
' And for dates see: ' + DATE_FORMAT_LINK + '.',
35+
'We add two items to d3\'s date formatter:',
36+
'*%h* for half of the year as a decimal number as well as',
37+
'*%{n}f* for fractional seconds',
38+
'with n digits. For example, *2016-10-13 09:15:23.456* with tickformat',
39+
'*%H~%M~%S.%2f* would display *09~15~23.46*'
40+
].join(' ');
41+
}
42+
43+
module.exports = {
44+
axisHoverFormat: axisHoverFormat,
45+
descriptionOnlyNumbers: descriptionOnlyNumbers,
46+
descriptionWithDates: descriptionWithDates
47+
};

src/plots/cartesian/layout_attributes.js

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ var colorAttrs = require('../../components/color/attributes');
55
var dash = require('../../components/drawing/attributes').dash;
66
var extendFlat = require('../../lib/extend').extendFlat;
77
var templatedArray = require('../../plot_api/plot_template').templatedArray;
8-
9-
var docs = require('../../constants/docs');
10-
var FORMAT_LINK = docs.FORMAT_LINK;
11-
var DATE_FORMAT_LINK = docs.DATE_FORMAT_LINK;
8+
var descriptionWithDates = require('../../plots/cartesian/axis_format_attributes').descriptionWithDates;
129

1310
var ONEDAY = require('../../constants/numerical').ONEDAY;
1411
var constants = require('./constants');
@@ -702,16 +699,7 @@ module.exports = {
702699
valType: 'string',
703700
dflt: '',
704701
editType: 'ticks',
705-
description: [
706-
'Sets the tick label formatting rule using d3 formatting mini-languages',
707-
'which are very similar to those in Python. For numbers, see:',
708-
FORMAT_LINK,
709-
'And for dates see:',
710-
DATE_FORMAT_LINK,
711-
'We add one item to d3\'s date formatter: *%{n}f* for fractional seconds',
712-
'with n digits. For example, *2016-10-13 09:15:23.456* with tickformat',
713-
'*%H~%M~%S.%2f* would display *09~15~23.46*'
714-
].join(' ')
702+
description: descriptionWithDates('tick label')
715703
},
716704
tickformatstops: templatedArray('tickformatstop', {
717705
enabled: {
@@ -750,16 +738,7 @@ module.exports = {
750738
valType: 'string',
751739
dflt: '',
752740
editType: 'none',
753-
description: [
754-
'Sets the hover text formatting rule using d3 formatting mini-languages',
755-
'which are very similar to those in Python. For numbers, see:',
756-
FORMAT_LINK,
757-
'And for dates see:',
758-
DATE_FORMAT_LINK,
759-
'We add one item to d3\'s date formatter: *%{n}f* for fractional seconds',
760-
'with n digits. For example, *2016-10-13 09:15:23.456* with tickformat',
761-
'*%H~%M~%S.%2f* would display *09~15~23.46*'
762-
].join(' ')
741+
description: descriptionWithDates('hover text')
763742
},
764743
// lines and grids
765744
showline: {

0 commit comments

Comments
 (0)