Skip to content

Commit 7df59a5

Browse files
committed
Merge branch 'master' into treemap-sunburst-colors-in-colorscale
2 parents f068cb2 + 75d007e commit 7df59a5

File tree

12 files changed

+239
-50
lines changed

12 files changed

+239
-50
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ plotly.js charts can also be created and saved online for free at [plot.ly/creat
158158

159159
### Active
160160

161-
| | Github | Twitter |
161+
| | GitHub | Twitter |
162162
|---|--------|---------|
163163
|**Alex C. Johnson**| [@alexcjohnson](https://github.com/alexcjohnson) | |
164164
|**Étienne Tétreault-Pinard**| [@etpinard](https://github.com/etpinard) | [@etpinard](https://twitter.com/etpinard) |
@@ -167,7 +167,7 @@ plotly.js charts can also be created and saved online for free at [plot.ly/creat
167167

168168
### Hall of Fame
169169

170-
| | Github | Twitter |
170+
| | GitHub | Twitter |
171171
|---|--------|---------|
172172
|**Mikola Lysenko**| [@mikolalysenko](https://github.com/mikolalysenko) | [@MikolaLysenko](https://twitter.com/MikolaLysenko) |
173173
|**Ricky Reusser**| [@rreusser](https://github.com/rreusser) | [@rickyreusser](https://twitter.com/rickyreusser) |

src/components/modebar/buttons.js

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ function handleCartesian(gd, ev) {
199199
var fullLayout = gd._fullLayout;
200200
var aobj = {};
201201
var axList = axisIds.list(gd, null, true);
202-
var allSpikesEnabled = 'on';
202+
var allSpikesEnabled = fullLayout._cartesianSpikesEnabled;
203203

204204
var ax, i;
205205

@@ -214,15 +214,18 @@ function handleCartesian(gd, ev) {
214214

215215
if(!ax.fixedrange) {
216216
axName = ax._name;
217-
if(val === 'auto') aobj[axName + '.autorange'] = true;
218-
else if(val === 'reset') {
217+
if(val === 'auto') {
218+
aobj[axName + '.autorange'] = true;
219+
} else if(val === 'reset') {
219220
if(ax._rangeInitial === undefined) {
220221
aobj[axName + '.autorange'] = true;
221222
} else {
222223
var rangeInitial = ax._rangeInitial.slice();
223224
aobj[axName + '.range[0]'] = rangeInitial[0];
224225
aobj[axName + '.range[1]'] = rangeInitial[1];
225226
}
227+
228+
// N.B. "reset" also resets showspikes
226229
if(ax._showSpikeInitial !== undefined) {
227230
aobj[axName + '.showspikes'] = ax._showSpikeInitial;
228231
if(allSpikesEnabled === 'on' && !ax._showSpikeInitial) {
@@ -245,25 +248,18 @@ function handleCartesian(gd, ev) {
245248
}
246249
}
247250
}
248-
fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
249251
} else {
250252
// if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y'
251253
if(astr === 'hovermode' && (val === 'x' || val === 'y')) {
252254
val = fullLayout._isHoriz ? 'y' : 'x';
253255
button.setAttribute('data-val', val);
254-
} else if(astr === 'hovermode' && val === 'closest') {
255-
for(i = 0; i < axList.length; i++) {
256-
ax = axList[i];
257-
if(allSpikesEnabled === 'on' && !ax.showspikes) {
258-
allSpikesEnabled = 'off';
259-
}
260-
}
261-
fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
262256
}
263257

264258
aobj[astr] = val;
265259
}
266260

261+
fullLayout._cartesianSpikesEnabled = allSpikesEnabled;
262+
267263
Registry.call('_guiRelayout', gd, aobj);
268264
}
269265

@@ -581,26 +577,22 @@ modeBarButtons.toggleSpikelines = {
581577
val: 'on',
582578
click: function(gd) {
583579
var fullLayout = gd._fullLayout;
580+
var allSpikesEnabled = fullLayout._cartesianSpikesEnabled;
584581

585-
fullLayout._cartesianSpikesEnabled = fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on';
586-
587-
var aobj = setSpikelineVisibility(gd);
588-
589-
Registry.call('_guiRelayout', gd, aobj);
582+
fullLayout._cartesianSpikesEnabled = allSpikesEnabled === 'on' ? 'off' : 'on';
583+
Registry.call('_guiRelayout', gd, setSpikelineVisibility(gd));
590584
}
591585
};
592586

593587
function setSpikelineVisibility(gd) {
594588
var fullLayout = gd._fullLayout;
589+
var areSpikesOn = fullLayout._cartesianSpikesEnabled === 'on';
595590
var axList = axisIds.list(gd, null, true);
596591
var aobj = {};
597592

598-
var ax, axName;
599-
600593
for(var i = 0; i < axList.length; i++) {
601-
ax = axList[i];
602-
axName = ax._name;
603-
aobj[axName + '.showspikes'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : ax._showSpikeInitial;
594+
var ax = axList[i];
595+
aobj[ax._name + '.showspikes'] = areSpikesOn ? true : ax._showSpikeInitial;
604596
}
605597

606598
return aobj;

src/plots/cartesian/transition_axes.js

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
var d3 = require('d3');
1212

1313
var Registry = require('../../registry');
14+
var Lib = require('../../lib');
1415
var Drawing = require('../../components/drawing');
1516
var Axes = require('./axes');
1617

@@ -69,37 +70,35 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
6970
var plotinfo = edit.plotinfo;
7071
var xa = plotinfo.xaxis;
7172
var ya = plotinfo.yaxis;
72-
73-
var xr0 = edit.xr0;
74-
var xr1 = edit.xr1;
7573
var xlen = xa._length;
76-
var yr0 = edit.yr0;
77-
var yr1 = edit.yr1;
7874
var ylen = ya._length;
79-
80-
var editX = !!xr1;
81-
var editY = !!yr1;
75+
var editX = !!edit.xr1;
76+
var editY = !!edit.yr1;
8277
var viewBox = [];
8378

8479
if(editX) {
80+
var xr0 = Lib.simpleMap(edit.xr0, xa.r2l);
81+
var xr1 = Lib.simpleMap(edit.xr1, xa.r2l);
8582
var dx0 = xr0[1] - xr0[0];
8683
var dx1 = xr1[1] - xr1[0];
8784
viewBox[0] = (xr0[0] * (1 - progress) + progress * xr1[0] - xr0[0]) / (xr0[1] - xr0[0]) * xlen;
8885
viewBox[2] = xlen * ((1 - progress) + progress * dx1 / dx0);
89-
xa.range[0] = xr0[0] * (1 - progress) + progress * xr1[0];
90-
xa.range[1] = xr0[1] * (1 - progress) + progress * xr1[1];
86+
xa.range[0] = xa.l2r(xr0[0] * (1 - progress) + progress * xr1[0]);
87+
xa.range[1] = xa.l2r(xr0[1] * (1 - progress) + progress * xr1[1]);
9188
} else {
9289
viewBox[0] = 0;
9390
viewBox[2] = xlen;
9491
}
9592

9693
if(editY) {
94+
var yr0 = Lib.simpleMap(edit.yr0, ya.r2l);
95+
var yr1 = Lib.simpleMap(edit.yr1, ya.r2l);
9796
var dy0 = yr0[1] - yr0[0];
9897
var dy1 = yr1[1] - yr1[0];
9998
viewBox[1] = (yr0[1] * (1 - progress) + progress * yr1[1] - yr0[1]) / (yr0[0] - yr0[1]) * ylen;
10099
viewBox[3] = ylen * ((1 - progress) + progress * dy1 / dy0);
101-
ya.range[0] = yr0[0] * (1 - progress) + progress * yr1[0];
102-
ya.range[1] = yr0[1] * (1 - progress) + progress * yr1[1];
100+
ya.range[0] = xa.l2r(yr0[0] * (1 - progress) + progress * yr1[0]);
101+
ya.range[1] = ya.l2r(yr0[1] * (1 - progress) + progress * yr1[1]);
103102
} else {
104103
viewBox[1] = 0;
105104
viewBox[3] = ylen;
@@ -144,8 +143,10 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
144143

145144
for(var i = 0; i < edits.length; i++) {
146145
var edit = edits[i];
147-
if(edit.xr1) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr1.slice();
148-
if(edit.yr1) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr1.slice();
146+
var xa = edit.plotinfo.xaxis;
147+
var ya = edit.plotinfo.yaxis;
148+
if(edit.xr1) aobj[xa._name + '.range'] = edit.xr1.slice();
149+
if(edit.yr1) aobj[ya._name + '.range'] = edit.yr1.slice();
149150
}
150151

151152
// Signal that this transition has completed:
@@ -163,8 +164,10 @@ module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnComple
163164

164165
for(var i = 0; i < edits.length; i++) {
165166
var edit = edits[i];
166-
if(edit.xr0) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr0.slice();
167-
if(edit.yr0) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr0.slice();
167+
var xa = edit.plotinfo.xaxis;
168+
var ya = edit.plotinfo.yaxis;
169+
if(edit.xr0) aobj[xa._name + '.range'] = edit.xr0.slice();
170+
if(edit.yr0) aobj[ya._name + '.range'] = edit.yr0.slice();
168171
}
169172

170173
return Registry.call('relayout', gd, aobj).then(function() {

src/plots/plots.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,10 +2462,14 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts)
24622462
yr1 = newLayout[ya._name].range.slice();
24632463
}
24642464

2465-
if(xr0 && xr1 && (xr0[0] !== xr1[0] || xr0[1] !== xr1[1])) {
2465+
if(xr0 && xr1 &&
2466+
(xa.r2l(xr0[0]) !== xa.r2l(xr1[0]) || xa.r2l(xr0[1]) !== xa.r2l(xr1[1]))
2467+
) {
24662468
editX = {xr0: xr0, xr1: xr1};
24672469
}
2468-
if(yr0 && yr1 && (yr0[0] !== yr1[0] || yr0[1] !== yr1[1])) {
2470+
if(yr0 && yr1 &&
2471+
(ya.r2l(yr0[0]) !== ya.r2l(yr1[0]) || ya.r2l(yr0[1]) !== ya.r2l(yr1[1]))
2472+
) {
24692473
editY = {yr0: yr0, yr1: yr1};
24702474
}
24712475

@@ -2559,10 +2563,10 @@ plots.transitionFromReact = function(gd, restyleFlags, relayoutFlags, oldFullLay
25592563
var editX = null;
25602564
var editY = null;
25612565

2562-
if(xr0[0] !== xr1[0] || xr0[1] !== xr1[1]) {
2566+
if(xa.r2l(xr0[0]) !== xa.r2l(xr1[0]) || xa.r2l(xr0[1]) !== xa.r2l(xr1[1])) {
25632567
editX = {xr0: xr0, xr1: xr1};
25642568
}
2565-
if(yr0[0] !== yr1[0] || yr0[1] !== yr1[1]) {
2569+
if(ya.r2l(yr0[0]) !== ya.r2l(yr1[0]) || ya.r2l(yr0[1]) !== ya.r2l(yr1[1])) {
25662570
editY = {yr0: yr0, yr1: yr1};
25672571
}
25682572

src/traces/indicator/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ module.exports = {
2424

2525
meta: {
2626
description: [
27-
'TODO: add description'
27+
'An indicator is used to visualize a single `value` along with some',
28+
'contextual information such as `steps` or a `threshold`, using a',
29+
'combination of three visual elements: a number, a delta, and/or a gauge.',
30+
'Deltas are taken with respect to a `reference`.',
31+
'Gauges can be either angular or bullet (aka linear) gauges.'
2832
].join(' ')
2933
}
3034
};

src/traces/sunburst/attributes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ module.exports = {
7070
editType: 'calc',
7171
role: 'info',
7272
description: [
73-
'Determines counting the number of *leaves* and/or *branches*,',
74-
'when a `values` array is not provided.'
73+
'Determines default for `values` when it is not provided,',
74+
'by inferring a 1 for each of the *leaves* and/or *branches*, otherwise 0.'
7575
].join(' ')
7676
},
7777

src/traces/sunburst/calc.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ exports.calc = function(gd, trace) {
103103
if(impliedRoots.length === 1) {
104104
k = impliedRoots[0];
105105
cd.unshift({
106+
hasImpliedRoot: true,
106107
id: k,
107108
pid: '',
108109
label: k
@@ -150,12 +151,20 @@ exports.calc = function(gd, trace) {
150151
break;
151152
case 'total':
152153
hierarchy.each(function(d) {
153-
var v = d.data.data.v;
154+
var cdi = d.data.data;
155+
var v = cdi.v;
154156

155157
if(d.children) {
156158
var partialSum = d.children.reduce(function(a, c) {
157159
return a + c.data.data.v;
158160
}, 0);
161+
162+
// N.B. we must fill in `value` for generated sectors
163+
// with the partialSum to compute the correct partition
164+
if(cdi.hasImpliedRoot || cdi.hasMultipleRoots) {
165+
v = partialSum;
166+
}
167+
159168
if(v < partialSum) {
160169
failed = true;
161170
return Lib.warn([

test/jasmine/tests/animate_test.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,55 @@ describe('Animating multiple axes', function() {
750750
.then(done);
751751
});
752752

753+
it('@flaky updates ranges of secondary axes (date + category case)', function(done) {
754+
Plotly.plot(gd, [
755+
{x: ['2018-01-01', '2019-01-01', '2020-01-01'], y: [1, 2, 3]},
756+
{x: ['a', 'b', 'c'], y: [1, 2, 3], xaxis: 'x2', yaxis: 'y2'}
757+
], {
758+
grid: {rows: 1, columns: 2, pattern: 'independent'},
759+
xaxis: {range: ['2018-01-01', '2020-01-01']},
760+
yaxis: {range: [0, 4]},
761+
xaxis2: {range: [0, 2]},
762+
yaxis2: {range: [0, 4]}
763+
})
764+
.then(function() {
765+
expect(gd._fullLayout.xaxis.range).toEqual(['2018-01-01', '2020-01-01']);
766+
expect(gd._fullLayout.xaxis2.range).toEqual([0, 2]);
767+
768+
var promise = Plotly.animate(gd, [{
769+
layout: {
770+
'xaxis.range': ['2018-06-01', '2019-06-01'],
771+
'xaxis2.range': [0.5, 1.5]
772+
}
773+
}], {
774+
frame: {redraw: false, duration: 60},
775+
transition: {duration: 30}
776+
});
777+
778+
setTimeout(function() {
779+
var fullLayout = gd._fullLayout;
780+
781+
var xa = fullLayout.xaxis;
782+
var xr = xa.range.slice();
783+
expect(xa.r2l(xr[0])).toBeGreaterThan(xa.r2l('2018-01-01'));
784+
expect(xa.r2l(xr[1])).toBeLessThan(xa.r2l('2020-01-01'));
785+
786+
var xa2 = fullLayout.xaxis2;
787+
var xr2 = xa2.range.slice();
788+
expect(xr2[0]).toBeGreaterThan(0);
789+
expect(xr2[1]).toBeLessThan(2);
790+
}, 15);
791+
792+
return promise;
793+
})
794+
.then(function() {
795+
expect(gd._fullLayout.xaxis.range).toEqual(['2018-06-01', '2019-06-01']);
796+
expect(gd._fullLayout.xaxis2.range).toEqual([0.5, 1.5]);
797+
})
798+
.catch(failTest)
799+
.then(done);
800+
});
801+
753802
it('should not leak axis update from subplot to subplot', function(done) {
754803
function _animate(frameLayout) {
755804
return function() {

test/jasmine/tests/modebar_test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,20 +1201,23 @@ describe('ModeBar', function() {
12011201
expect(gd._fullLayout.hovermode).toBe('x');
12021202
assertActive(hovermodeButtons, buttonCompare);
12031203
});
1204+
12041205
it('should makes spikelines visible', function() {
12051206
buttonToggle.click();
12061207
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
12071208

12081209
buttonToggle.click();
12091210
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
12101211
});
1212+
12111213
it('should not become disabled when hovermode is switched off closest', function() {
12121214
buttonToggle.click();
12131215
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
12141216

12151217
buttonCompare.click();
12161218
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
12171219
});
1220+
12181221
it('should keep the state on changing the hovermode', function() {
12191222
buttonToggle.click();
12201223
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
@@ -1228,6 +1231,36 @@ describe('ModeBar', function() {
12281231
buttonClosest.click();
12291232
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
12301233
});
1234+
1235+
it('should work after clicking on "autoScale2d"', function() {
1236+
var buttonAutoScale = selectButton(modeBar, 'autoScale2d');
1237+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1238+
1239+
buttonAutoScale.click();
1240+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1241+
1242+
buttonToggle.click();
1243+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
1244+
1245+
buttonToggle.click();
1246+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1247+
});
1248+
1249+
it('should work after clicking on "resetScale2d"', function() {
1250+
var buttonResetScale = selectButton(modeBar, 'resetScale2d');
1251+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1252+
1253+
buttonToggle.click();
1254+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
1255+
1256+
buttonResetScale.click();
1257+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1258+
1259+
buttonToggle.click();
1260+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('on');
1261+
buttonToggle.click();
1262+
expect(gd._fullLayout._cartesianSpikesEnabled).toBe('off');
1263+
});
12311264
});
12321265
});
12331266

0 commit comments

Comments
 (0)