plotly.js 2.6.4 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +3 -3
  3. package/dist/README.md +26 -26
  4. package/dist/plot-schema.json +1015 -407
  5. package/dist/plotly-basic.js +534 -195
  6. package/dist/plotly-basic.min.js +4 -4
  7. package/dist/plotly-cartesian.js +1000 -343
  8. package/dist/plotly-cartesian.min.js +3 -3
  9. package/dist/plotly-finance.js +587 -199
  10. package/dist/plotly-finance.min.js +4 -4
  11. package/dist/plotly-geo-assets.js +2 -2
  12. package/dist/plotly-geo.js +523 -192
  13. package/dist/plotly-geo.min.js +4 -4
  14. package/dist/plotly-gl2d.js +542 -195
  15. package/dist/plotly-gl2d.min.js +2 -2
  16. package/dist/plotly-gl3d.js +523 -192
  17. package/dist/plotly-gl3d.min.js +8 -8
  18. package/dist/plotly-mapbox.js +529 -195
  19. package/dist/plotly-mapbox.min.js +2 -2
  20. package/dist/plotly-strict.js +1224 -564
  21. package/dist/plotly-strict.min.js +3 -3
  22. package/dist/plotly-with-meta.js +1316 -626
  23. package/dist/plotly.js +1278 -618
  24. package/dist/plotly.min.js +10 -10
  25. package/package.json +5 -5
  26. package/src/components/colorbar/attributes.js +29 -20
  27. package/src/components/colorbar/defaults.js +30 -8
  28. package/src/components/colorbar/draw.js +374 -128
  29. package/src/components/fx/hover.js +5 -2
  30. package/src/components/fx/hoverlabel_defaults.js +4 -2
  31. package/src/components/fx/layout_attributes.js +14 -4
  32. package/src/components/fx/layout_defaults.js +2 -0
  33. package/src/components/legend/attributes.js +7 -0
  34. package/src/components/legend/defaults.js +24 -7
  35. package/src/components/titles/index.js +8 -2
  36. package/src/plot_api/plot_api.js +38 -9
  37. package/src/plots/font_attributes.js +3 -0
  38. package/src/plots/layout_attributes.js +1 -0
  39. package/src/plots/mapbox/mapbox.js +6 -3
  40. package/src/plots/plots.js +7 -15
  41. package/src/traces/bar/plot.js +8 -2
  42. package/src/traces/contour/attributes.js +12 -0
  43. package/src/traces/contour/defaults.js +9 -1
  44. package/src/traces/heatmap/attributes.js +16 -0
  45. package/src/traces/heatmap/defaults.js +2 -0
  46. package/src/traces/heatmap/label_defaults.js +13 -0
  47. package/src/traces/heatmap/plot.js +205 -4
  48. package/src/traces/histogram/attributes.js +40 -0
  49. package/src/traces/histogram/calc.js +3 -2
  50. package/src/traces/histogram/defaults.js +11 -0
  51. package/src/traces/histogram2d/attributes.js +8 -0
  52. package/src/traces/histogram2d/defaults.js +4 -0
  53. package/src/traces/histogram2dcontour/attributes.js +3 -1
  54. package/src/traces/histogram2dcontour/defaults.js +8 -1
  55. package/src/traces/pie/calc.js +3 -1
  56. package/src/version.js +1 -1
  57. package/tasks/test_mock.js +1 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * plotly.js (gl3d) v2.6.4
2
+ * plotly.js (gl3d) v2.8.2
3
3
  * Copyright 2012-2021, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -22254,13 +22254,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
22254
22254
 
22255
22255
 
22256
22256
  module.exports = overrideAll({
22257
- // TODO: only right is supported currently
22258
- // orient: {
22259
- // valType: 'enumerated',
22260
- // values: ['left', 'right', 'top', 'bottom'],
22261
- // dflt: 'right',
22262
- //
22263
- // },
22257
+ orientation: {
22258
+ valType: 'enumerated',
22259
+ values: ['h', 'v'],
22260
+ dflt: 'v',
22261
+ },
22264
22262
  thicknessmode: {
22265
22263
  valType: 'enumerated',
22266
22264
  values: ['fraction', 'pixels'],
@@ -22283,14 +22281,12 @@ module.exports = overrideAll({
22283
22281
  },
22284
22282
  x: {
22285
22283
  valType: 'number',
22286
- dflt: 1.02,
22287
22284
  min: -2,
22288
22285
  max: 3,
22289
22286
  },
22290
22287
  xanchor: {
22291
22288
  valType: 'enumerated',
22292
22289
  values: ['left', 'center', 'right'],
22293
- dflt: 'left',
22294
22290
  },
22295
22291
  xpad: {
22296
22292
  valType: 'number',
@@ -22299,14 +22295,12 @@ module.exports = overrideAll({
22299
22295
  },
22300
22296
  y: {
22301
22297
  valType: 'number',
22302
- dflt: 0.5,
22303
22298
  min: -2,
22304
22299
  max: 3,
22305
22300
  },
22306
22301
  yanchor: {
22307
22302
  valType: 'enumerated',
22308
22303
  values: ['top', 'middle', 'bottom'],
22309
- dflt: 'middle',
22310
22304
  },
22311
22305
  ypad: {
22312
22306
  valType: 'number',
@@ -22338,15 +22332,21 @@ module.exports = overrideAll({
22338
22332
  ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
22339
22333
  ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
22340
22334
  }),
22335
+
22336
+ // ticklabelposition: not used directly, as values depend on orientation
22337
+ // left/right options are for x axes, and top/bottom options are for y axes
22341
22338
  ticklabelposition: {
22342
22339
  valType: 'enumerated',
22343
22340
  values: [
22344
22341
  'outside', 'inside',
22345
22342
  'outside top', 'inside top',
22343
+ 'outside left', 'inside left',
22344
+ 'outside right', 'inside right',
22346
22345
  'outside bottom', 'inside bottom'
22347
22346
  ],
22348
22347
  dflt: 'outside',
22349
22348
  },
22349
+
22350
22350
  ticklen: axesAttrs.ticklen,
22351
22351
  tickwidth: axesAttrs.tickwidth,
22352
22352
  tickcolor: axesAttrs.tickcolor,
@@ -22373,7 +22373,6 @@ module.exports = overrideAll({
22373
22373
  side: {
22374
22374
  valType: 'enumerated',
22375
22375
  values: ['right', 'top', 'bottom'],
22376
- dflt: 'top',
22377
22376
  }
22378
22377
  },
22379
22378
 
@@ -22432,23 +22431,30 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
22432
22431
  return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt);
22433
22432
  }
22434
22433
 
22434
+ var margin = layout.margin || {t: 0, b: 0, l: 0, r: 0};
22435
+ var w = layout.width - margin.l - margin.r;
22436
+ var h = layout.height - margin.t - margin.b;
22437
+
22438
+ var orientation = coerce('orientation');
22439
+ var isVertical = orientation === 'v';
22440
+
22435
22441
  var thicknessmode = coerce('thicknessmode');
22436
22442
  coerce('thickness', (thicknessmode === 'fraction') ?
22437
- 30 / (layout.width - layout.margin.l - layout.margin.r) :
22443
+ 30 / (isVertical ? w : h) :
22438
22444
  30
22439
22445
  );
22440
22446
 
22441
22447
  var lenmode = coerce('lenmode');
22442
22448
  coerce('len', (lenmode === 'fraction') ?
22443
22449
  1 :
22444
- layout.height - layout.margin.t - layout.margin.b
22450
+ isVertical ? h : w
22445
22451
  );
22446
22452
 
22447
- coerce('x');
22448
- coerce('xanchor');
22453
+ coerce('x', isVertical ? 1.02 : 0.5);
22454
+ coerce('xanchor', isVertical ? 'left' : 'center');
22449
22455
  coerce('xpad');
22450
- coerce('y');
22451
- coerce('yanchor');
22456
+ coerce('y', isVertical ? 0.5 : 1.02);
22457
+ coerce('yanchor', isVertical ? 'middle' : 'bottom');
22452
22458
  coerce('ypad');
22453
22459
  Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']);
22454
22460
 
@@ -22458,7 +22464,22 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
22458
22464
  coerce('borderwidth');
22459
22465
  coerce('bgcolor');
22460
22466
 
22461
- var ticklabelposition = coerce('ticklabelposition');
22467
+ var ticklabelposition = Lib.coerce(colorbarIn, colorbarOut, {
22468
+ ticklabelposition: {
22469
+ valType: 'enumerated',
22470
+ dflt: 'outside',
22471
+ values: isVertical ? [
22472
+ 'outside', 'inside',
22473
+ 'outside top', 'inside top',
22474
+ 'outside bottom', 'inside bottom'
22475
+ ] : [
22476
+ 'outside', 'inside',
22477
+ 'outside left', 'inside left',
22478
+ 'outside right', 'inside right'
22479
+ ]
22480
+ }
22481
+ }, 'ticklabelposition');
22482
+
22462
22483
  coerce('ticklabeloverflow', ticklabelposition.indexOf('inside') !== -1 ? 'hide past domain' : 'hide past div');
22463
22484
 
22464
22485
  handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear');
@@ -22480,7 +22501,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
22480
22501
  size: Lib.bigFont(tickFont.size)
22481
22502
  });
22482
22503
  Lib.coerceFont(coerce, 'title.font', dfltTitleFont);
22483
- coerce('title.side');
22504
+ coerce('title.side', isVertical ? 'top' : 'right');
22484
22505
  };
22485
22506
 
22486
22507
  },{"../../lib":252,"../../plot_api/plot_template":290,"../../plots/cartesian/prefix_suffix_defaults":320,"../../plots/cartesian/tick_label_defaults":325,"../../plots/cartesian/tick_mark_defaults":326,"../../plots/cartesian/tick_value_defaults":327,"./attributes":120}],123:[function(_dereq_,module,exports){
@@ -22653,18 +22674,20 @@ function makeColorBarData(gd) {
22653
22674
  }
22654
22675
 
22655
22676
  function drawColorBar(g, opts, gd) {
22677
+ var isVertical = opts.orientation === 'v';
22656
22678
  var len = opts.len;
22657
22679
  var lenmode = opts.lenmode;
22658
22680
  var thickness = opts.thickness;
22659
22681
  var thicknessmode = opts.thicknessmode;
22660
22682
  var outlinewidth = opts.outlinewidth;
22661
22683
  var borderwidth = opts.borderwidth;
22684
+ var bgcolor = opts.bgcolor;
22662
22685
  var xanchor = opts.xanchor;
22663
22686
  var yanchor = opts.yanchor;
22664
22687
  var xpad = opts.xpad;
22665
22688
  var ypad = opts.ypad;
22666
22689
  var optsX = opts.x;
22667
- var optsY = opts.y;
22690
+ var optsY = isVertical ? opts.y : 1 - opts.y;
22668
22691
 
22669
22692
  var fullLayout = gd._fullLayout;
22670
22693
  var gs = fullLayout._size;
@@ -22695,23 +22718,35 @@ function drawColorBar(g, opts, gd) {
22695
22718
  // when the colorbar itself is pushing the margins.
22696
22719
  // but then the fractional size is calculated based on the
22697
22720
  // actual graph size, so that the axes will size correctly.
22698
- var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? gs.w : 1));
22699
- var thickFrac = thickPx / gs.w;
22700
- var lenPx = Math.round(len * (lenmode === 'fraction' ? gs.h : 1));
22701
- var lenFrac = lenPx / gs.h;
22702
- var xpadFrac = xpad / gs.w;
22703
- var yExtraPx = (borderwidth + outlinewidth) / 2;
22704
- var ypadFrac = ypad / gs.h;
22721
+ var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
22722
+ var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
22723
+ var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
22724
+ var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
22705
22725
 
22706
22726
  // x positioning: do it initially just for left anchor,
22707
22727
  // then fix at the end (since we don't know the width yet)
22708
- var uPx = Math.round(optsX * gs.w + xpad);
22709
- // for dragging... this is getting a little muddled...
22710
- var uFrac = optsX - thickFrac * ({center: 0.5, right: 1}[xanchor] || 0);
22728
+ var uPx = Math.round(isVertical ?
22729
+ optsX * gs.w + xpad :
22730
+ optsY * gs.h + ypad
22731
+ );
22711
22732
 
22712
- // y positioning we can do correctly from the start
22713
- var vFrac = optsY + lenFrac * (({top: -0.5, bottom: 0.5}[yanchor] || 0) - 0.5);
22714
- var vPx = Math.round(gs.h * (1 - vFrac));
22733
+ var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
22734
+ var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
22735
+
22736
+ // for dragging... this is getting a little muddled...
22737
+ var uFrac = isVertical ?
22738
+ optsX - xRatio * thickFrac :
22739
+ optsY - yRatio * thickFrac;
22740
+
22741
+ // y/x positioning (for v/h) we can do correctly from the start
22742
+ var vFrac = isVertical ?
22743
+ optsY - yRatio * lenFrac :
22744
+ optsX - xRatio * lenFrac;
22745
+
22746
+ var vPx = Math.round(isVertical ?
22747
+ gs.h * (1 - vFrac) :
22748
+ gs.w * vFrac
22749
+ );
22715
22750
 
22716
22751
  // stash a few things for makeEditable
22717
22752
  opts._lenFrac = lenFrac;
@@ -22724,12 +22759,23 @@ function drawColorBar(g, opts, gd) {
22724
22759
 
22725
22760
  // position can't go in through supplyDefaults
22726
22761
  // because that restricts it to [0,1]
22727
- ax.position = optsX + xpadFrac + thickFrac;
22762
+ ax.position = thickFrac + (isVertical ?
22763
+ optsX + xpad / gs.w :
22764
+ optsY + ypad / gs.h
22765
+ );
22766
+
22767
+ var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
22768
+
22769
+ if(isVertical && topOrBottom) {
22770
+ ax.title.side = titleSide;
22771
+ ax.titlex = optsX + xpad / gs.w;
22772
+ ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
22773
+ }
22728
22774
 
22729
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22775
+ if(!isVertical && !topOrBottom) {
22730
22776
  ax.title.side = titleSide;
22731
- ax.titlex = optsX + xpadFrac;
22732
- ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
22777
+ ax.titley = optsY + ypad / gs.h;
22778
+ ax.titlex = vFrac + xpad / gs.w; // right side
22733
22779
  }
22734
22780
 
22735
22781
  if(line.color && opts.tickmode === 'auto') {
@@ -22754,9 +22800,12 @@ function drawColorBar(g, opts, gd) {
22754
22800
 
22755
22801
  // set domain after init, because we may want to
22756
22802
  // allow it outside [0,1]
22757
- ax.domain = [
22758
- vFrac + ypadFrac,
22759
- vFrac + lenFrac - ypadFrac
22803
+ ax.domain = isVertical ? [
22804
+ vFrac + ypad / gs.h,
22805
+ vFrac + lenFrac - ypad / gs.h
22806
+ ] : [
22807
+ vFrac + xpad / gs.w,
22808
+ vFrac + lenFrac - xpad / gs.w
22760
22809
  ];
22761
22810
 
22762
22811
  ax.setScale();
@@ -22766,9 +22815,13 @@ function drawColorBar(g, opts, gd) {
22766
22815
  var titleCont = g.select('.' + cn.cbtitleunshift)
22767
22816
  .attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
22768
22817
 
22818
+ var ticklabelposition = ax.ticklabelposition;
22819
+ var titleFontSize = ax.title.font.size;
22820
+
22769
22821
  var axLayer = g.select('.' + cn.cbaxis);
22770
22822
  var titleEl;
22771
22823
  var titleHeight = 0;
22824
+ var titleWidth = 0;
22772
22825
 
22773
22826
  function drawTitle(titleClass, titleOpts) {
22774
22827
  var dfltTitleOpts = {
@@ -22793,54 +22846,98 @@ function drawColorBar(g, opts, gd) {
22793
22846
  }
22794
22847
 
22795
22848
  function drawDummyTitle() {
22796
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22797
- // draw the title so we know how much room it needs
22798
- // when we squish the axis. This one only applies to
22799
- // top or bottom titles, not right side.
22800
- var x = gs.l + (optsX + xpadFrac) * gs.w;
22801
- var fontSize = ax.title.font.size;
22802
- var y;
22849
+ // draw the title so we know how much room it needs
22850
+ // when we squish the axis.
22851
+ // On vertical colorbars this only applies to top or bottom titles, not right side.
22852
+ // On horizontal colorbars this only applies to right, etc.
22853
+
22854
+ if(
22855
+ (isVertical && topOrBottom) ||
22856
+ (!isVertical && !topOrBottom)
22857
+ ) {
22858
+ var x, y;
22803
22859
 
22804
22860
  if(titleSide === 'top') {
22805
- y = (1 - (vFrac + lenFrac - ypadFrac)) * gs.h +
22806
- gs.t + 3 + fontSize * 0.75;
22807
- } else {
22808
- y = (1 - (vFrac + ypadFrac)) * gs.h +
22809
- gs.t - 3 - fontSize * 0.25;
22861
+ x = xpad + gs.l + gs.w * optsX;
22862
+ y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
22810
22863
  }
22864
+
22865
+ if(titleSide === 'bottom') {
22866
+ x = xpad + gs.l + gs.w * optsX;
22867
+ y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
22868
+ }
22869
+
22870
+ if(titleSide === 'right') {
22871
+ y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
22872
+ x = xpad + gs.l + gs.w * vFrac;
22873
+ }
22874
+
22811
22875
  drawTitle(ax._id + 'title', {
22812
- attributes: {x: x, y: y, 'text-anchor': 'start'}
22876
+ attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
22813
22877
  });
22814
22878
  }
22815
22879
  }
22816
22880
 
22817
22881
  function drawCbTitle() {
22818
- if(['top', 'bottom'].indexOf(titleSide) === -1) {
22819
- var fontSize = ax.title.font.size;
22820
- var y = ax._offset + ax._length / 2;
22821
- var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ?
22822
- 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) :
22823
- -10 - fontSize * ((ax.showticklabels ? 0.5 : 0)));
22824
-
22825
- // the 'h' + is a hack to get around the fact that
22826
- // convertToTspans rotates any 'y...' class by 90 degrees.
22827
- // TODO: find a better way to control this.
22828
- drawTitle('h' + ax._id + 'title', {
22882
+ if(
22883
+ (isVertical && !topOrBottom) ||
22884
+ (!isVertical && topOrBottom)
22885
+ ) {
22886
+ var pos = ax.position || 0;
22887
+ var mid = ax._offset + ax._length / 2;
22888
+ var x, y;
22889
+
22890
+ if(titleSide === 'right') {
22891
+ y = mid;
22892
+ x = gs.l + gs.w * pos + 10 + titleFontSize * (
22893
+ ax.showticklabels ? 1 : 0.5
22894
+ );
22895
+ } else {
22896
+ x = mid;
22897
+
22898
+ if(titleSide === 'bottom') {
22899
+ y = gs.t + gs.h * pos + 10 + (
22900
+ ticklabelposition.indexOf('inside') === -1 ?
22901
+ ax.tickfont.size :
22902
+ 0
22903
+ ) + (
22904
+ ax.ticks !== 'intside' ?
22905
+ opts.ticklen || 0 :
22906
+ 0
22907
+ );
22908
+ }
22909
+
22910
+ if(titleSide === 'top') {
22911
+ var nlines = title.text.split('<br>').length;
22912
+ y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
22913
+ }
22914
+ }
22915
+
22916
+ drawTitle((isVertical ?
22917
+ // the 'h' + is a hack to get around the fact that
22918
+ // convertToTspans rotates any 'y...' class by 90 degrees.
22919
+ // TODO: find a better way to control this.
22920
+ 'h' :
22921
+ 'v'
22922
+ ) + ax._id + 'title', {
22829
22923
  avoid: {
22830
22924
  selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
22831
22925
  side: titleSide,
22832
- offsetLeft: gs.l,
22833
- offsetTop: 0,
22834
- maxShift: fullLayout.width
22926
+ offsetTop: isVertical ? 0 : gs.t,
22927
+ offsetLeft: isVertical ? gs.l : 0,
22928
+ maxShift: isVertical ? fullLayout.width : fullLayout.height
22835
22929
  },
22836
22930
  attributes: {x: x, y: y, 'text-anchor': 'middle'},
22837
- transform: {rotate: '-90', offset: 0}
22931
+ transform: {rotate: isVertical ? -90 : 0, offset: 0}
22838
22932
  });
22839
22933
  }
22840
22934
  }
22841
22935
 
22842
22936
  function drawAxis() {
22843
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22937
+ if(
22938
+ (!isVertical && !topOrBottom) ||
22939
+ (isVertical && topOrBottom)
22940
+ ) {
22844
22941
  // squish the axis top to make room for the title
22845
22942
  var titleGroup = g.select('.' + cn.cbtitle);
22846
22943
  var titleText = titleGroup.select('text');
@@ -22852,39 +22949,63 @@ function drawColorBar(g, opts, gd) {
22852
22949
  if(titleText.node()) {
22853
22950
  lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
22854
22951
  }
22952
+
22953
+ var bb;
22855
22954
  if(mathJaxNode) {
22856
- titleHeight = Drawing.bBox(mathJaxNode).height;
22955
+ bb = Drawing.bBox(mathJaxNode);
22956
+ titleWidth = bb.width;
22957
+ titleHeight = bb.height;
22857
22958
  if(titleHeight > lineSize) {
22858
22959
  // not entirely sure how mathjax is doing
22859
22960
  // vertical alignment, but this seems to work.
22860
22961
  titleTrans[1] -= (titleHeight - lineSize) / 2;
22861
22962
  }
22862
22963
  } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
22863
- titleHeight = Drawing.bBox(titleText.node()).height;
22964
+ bb = Drawing.bBox(titleText.node());
22965
+ titleWidth = bb.width;
22966
+ titleHeight = bb.height;
22864
22967
  }
22865
- if(titleHeight) {
22866
- // buffer btwn colorbar and title
22867
- // TODO: configurable
22868
- titleHeight += 5;
22869
22968
 
22870
- if(titleSide === 'top') {
22871
- ax.domain[1] -= titleHeight / gs.h;
22872
- titleTrans[1] *= -1;
22873
- } else {
22874
- ax.domain[0] += titleHeight / gs.h;
22875
- var nlines = svgTextUtils.lineCount(titleText);
22876
- titleTrans[1] += (1 - nlines) * lineSize;
22969
+ if(isVertical) {
22970
+ if(titleHeight) {
22971
+ // buffer btwn colorbar and title
22972
+ // TODO: configurable
22973
+ titleHeight += 5;
22974
+
22975
+ if(titleSide === 'top') {
22976
+ ax.domain[1] -= titleHeight / gs.h;
22977
+ titleTrans[1] *= -1;
22978
+ } else {
22979
+ ax.domain[0] += titleHeight / gs.h;
22980
+ var nlines = svgTextUtils.lineCount(titleText);
22981
+ titleTrans[1] += (1 - nlines) * lineSize;
22982
+ }
22983
+
22984
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22985
+ ax.setScale();
22877
22986
  }
22987
+ } else { // horizontal colorbars
22988
+ if(titleWidth) {
22989
+ if(titleSide === 'right') {
22990
+ ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
22991
+ }
22878
22992
 
22879
- titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22880
- ax.setScale();
22993
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22994
+ ax.setScale();
22995
+ }
22881
22996
  }
22882
22997
  }
22883
22998
 
22884
22999
  g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
22885
- .attr('transform', strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))));
23000
+ .attr('transform', isVertical ?
23001
+ strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
23002
+ strTranslate(Math.round(gs.w * ax.domain[0]), 0)
23003
+ );
22886
23004
 
22887
- axLayer.attr('transform', strTranslate(0, Math.round(-gs.t)));
23005
+ axLayer.attr('transform', isVertical ?
23006
+ strTranslate(0, Math.round(-gs.t)) :
23007
+ strTranslate(Math.round(-gs.l), 0)
23008
+ );
22888
23009
 
22889
23010
  var fills = g.select('.' + cn.cbfills)
22890
23011
  .selectAll('rect.' + cn.cbfill)
@@ -22910,20 +23031,22 @@ function drawColorBar(g, opts, gd) {
22910
23031
 
22911
23032
  // offset the side adjoining the next rectangle so they
22912
23033
  // overlap, to prevent antialiasing gaps
22913
- z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
22914
-
23034
+ if(isVertical) {
23035
+ z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
23036
+ } /* else {
23037
+ // TODO: horizontal case
23038
+ } */
22915
23039
 
22916
23040
  // Colorbar cannot currently support opacities so we
22917
23041
  // use an opaque fill even when alpha channels present
22918
- var fillEl = d3.select(this).attr({
22919
- x: uPx,
22920
- width: Math.max(thickPx, 2),
22921
- y: d3.min(z),
22922
- height: Math.max(d3.max(z) - d3.min(z), 2),
22923
- });
23042
+ var fillEl = d3.select(this)
23043
+ .attr(isVertical ? 'x' : 'y', uPx)
23044
+ .attr(isVertical ? 'y' : 'x', d3.min(z))
23045
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
23046
+ .attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
22924
23047
 
22925
23048
  if(opts._fillgradient) {
22926
- Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
23049
+ Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
22927
23050
  } else {
22928
23051
  // tinycolor can't handle exponents and
22929
23052
  // at this scale, removing it makes no difference.
@@ -22939,9 +23062,15 @@ function drawColorBar(g, opts, gd) {
22939
23062
  .classed(cn.cbline, true);
22940
23063
  lines.exit().remove();
22941
23064
  lines.each(function(d) {
23065
+ var a = uPx;
23066
+ var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
23067
+
22942
23068
  d3.select(this)
22943
- .attr('d', 'M' + uPx + ',' +
22944
- (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx)
23069
+ .attr('d', 'M' +
23070
+ (isVertical ? a + ',' + b : b + ',' + a) +
23071
+ (isVertical ? 'h' : 'v') +
23072
+ thickPx
23073
+ )
22945
23074
  .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
22946
23075
  });
22947
23076
 
@@ -22974,82 +23103,211 @@ function drawColorBar(g, opts, gd) {
22974
23103
  // TODO: why are we redrawing multiple times now with this?
22975
23104
  // I guess autoMargin doesn't like being post-promise?
22976
23105
  function positionCB() {
23106
+ var bb;
22977
23107
  var innerThickness = thickPx + outlinewidth / 2;
22978
- if(ax.ticklabelposition.indexOf('inside') === -1) {
22979
- innerThickness += Drawing.bBox(axLayer.node()).width;
23108
+ if(ticklabelposition.indexOf('inside') === -1) {
23109
+ bb = Drawing.bBox(axLayer.node());
23110
+ innerThickness += isVertical ? bb.width : bb.height;
22980
23111
  }
22981
23112
 
22982
23113
  titleEl = titleCont.select('text');
22983
23114
 
23115
+ var titleWidth = 0;
23116
+
23117
+ var topSideVertical = isVertical && titleSide === 'top';
23118
+ var rightSideHorizontal = !isVertical && titleSide === 'right';
23119
+
23120
+ var moveY = 0;
23121
+
22984
23122
  if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
23123
+ var _titleHeight;
23124
+
22985
23125
  var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
22986
- var titleWidth;
22987
- if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) {
22988
- titleWidth = Drawing.bBox(mathJaxNode).width;
23126
+ if(mathJaxNode && (
23127
+ (isVertical && topOrBottom) ||
23128
+ (!isVertical && !topOrBottom)
23129
+ )) {
23130
+ bb = Drawing.bBox(mathJaxNode);
23131
+ titleWidth = bb.width;
23132
+ _titleHeight = bb.height;
22989
23133
  } else {
22990
23134
  // note: the formula below works for all title sides,
22991
23135
  // (except for top/bottom mathjax, above)
22992
23136
  // but the weird gs.l is because the titleunshift
22993
23137
  // transform gets removed by Drawing.bBox
22994
- titleWidth = Drawing.bBox(titleCont.node()).right - uPx - gs.l;
23138
+ bb = Drawing.bBox(titleCont.node());
23139
+ titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
23140
+ _titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
23141
+
23142
+ if(
23143
+ !isVertical && titleSide === 'top'
23144
+ ) {
23145
+ innerThickness += bb.height;
23146
+ moveY = bb.height;
23147
+ }
23148
+ }
23149
+
23150
+ if(rightSideHorizontal) {
23151
+ titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
23152
+
23153
+ titleWidth *= 2;
22995
23154
  }
22996
- innerThickness = Math.max(innerThickness, titleWidth);
23155
+
23156
+ innerThickness = Math.max(innerThickness,
23157
+ isVertical ? titleWidth : _titleHeight
23158
+ );
22997
23159
  }
22998
23160
 
22999
- var outerThickness = 2 * xpad + innerThickness + borderwidth + outlinewidth / 2;
23161
+ var outerThickness = (isVertical ?
23162
+ xpad :
23163
+ ypad
23164
+ ) * 2 + innerThickness + borderwidth + outlinewidth / 2;
23000
23165
 
23001
- g.select('.' + cn.cbbg).attr({
23002
- x: uPx - xpad - (borderwidth + outlinewidth) / 2,
23003
- y: vPx - lenPx - yExtraPx,
23004
- width: Math.max(outerThickness, 2),
23005
- height: Math.max(lenPx + 2 * yExtraPx, 2)
23006
- })
23007
- .call(Color.fill, opts.bgcolor)
23166
+ var hColorbarMoveTitle = 0;
23167
+ if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
23168
+ hColorbarMoveTitle = outerThickness / 2;
23169
+
23170
+ outerThickness += hColorbarMoveTitle;
23171
+ moveY += hColorbarMoveTitle;
23172
+ }
23173
+ fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
23174
+ fullLayout._hColorbarMoveCBTitle = moveY;
23175
+
23176
+ var extraW = borderwidth + outlinewidth;
23177
+
23178
+ g.select('.' + cn.cbbg)
23179
+ .attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
23180
+ .attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
23181
+ .attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
23182
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
23183
+ .call(Color.fill, bgcolor)
23008
23184
  .call(Color.stroke, opts.bordercolor)
23009
23185
  .style('stroke-width', borderwidth);
23010
23186
 
23011
- g.selectAll('.' + cn.cboutline).attr({
23012
- x: uPx,
23013
- y: vPx - lenPx + ypad + (titleSide === 'top' ? titleHeight : 0),
23014
- width: Math.max(thickPx, 2),
23015
- height: Math.max(lenPx - 2 * ypad - titleHeight, 2)
23016
- })
23187
+ var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
23188
+
23189
+ g.selectAll('.' + cn.cboutline)
23190
+ .attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
23191
+ .attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
23192
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
23193
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
23194
+ 2 * ypad + titleHeight :
23195
+ 2 * xpad + moveX
23196
+ ), 2))
23017
23197
  .call(Color.stroke, opts.outlinecolor)
23018
23198
  .style({
23019
23199
  fill: 'none',
23020
23200
  'stroke-width': outlinewidth
23021
23201
  });
23022
23202
 
23023
- // fix positioning for xanchor!='left'
23024
- var xoffset = ({center: 0.5, right: 1}[xanchor] || 0) * outerThickness;
23025
- g.attr('transform', strTranslate(gs.l - xoffset, gs.t));
23203
+ g.attr('transform', strTranslate(
23204
+ gs.l - (isVertical ? xRatio * outerThickness : 0),
23205
+ gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
23206
+ ));
23207
+
23208
+ if(!isVertical && (
23209
+ borderwidth || (
23210
+ tinycolor(bgcolor).getAlpha() &&
23211
+ !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
23212
+ )
23213
+ )) {
23214
+ // for horizontal colorbars when there is a border line or having different background color
23215
+ // hide/adjust x positioning for the first/last tick labels if they go outside the border
23216
+ var tickLabels = axLayer.selectAll('text');
23217
+ var numTicks = tickLabels[0].length;
23218
+
23219
+ var border = g.select('.' + cn.cbbg).node();
23220
+ var oBb = Drawing.bBox(border);
23221
+ var oTr = Drawing.getTranslate(g);
23222
+
23223
+ var TEXTPAD = 2;
23224
+
23225
+ tickLabels.each(function(d, i) {
23226
+ var first = 0;
23227
+ var last = numTicks - 1;
23228
+ if(i === first || i === last) {
23229
+ var iBb = Drawing.bBox(this);
23230
+ var iTr = Drawing.getTranslate(this);
23231
+ var deltaX;
23232
+
23233
+ if(i === last) {
23234
+ var iRight = iBb.right + iTr.x;
23235
+ var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
23236
+
23237
+ deltaX = oRight - iRight;
23238
+ if(deltaX > 0) deltaX = 0;
23239
+ } else if(i === first) {
23240
+ var iLeft = iBb.left + iTr.x;
23241
+ var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
23242
+
23243
+ deltaX = oLeft - iLeft;
23244
+ if(deltaX < 0) deltaX = 0;
23245
+ }
23246
+
23247
+ if(deltaX) {
23248
+ if(numTicks < 3) { // adjust position
23249
+ this.setAttribute('transform',
23250
+ 'translate(' + deltaX + ',0) ' +
23251
+ this.getAttribute('transform')
23252
+ );
23253
+ } else { // hide
23254
+ this.setAttribute('visibility', 'hidden');
23255
+ }
23256
+ }
23257
+ }
23258
+ });
23259
+ }
23026
23260
 
23027
23261
  // auto margin adjustment
23028
23262
  var marginOpts = {};
23263
+ var lFrac = FROM_TL[xanchor];
23264
+ var rFrac = FROM_BR[xanchor];
23029
23265
  var tFrac = FROM_TL[yanchor];
23030
23266
  var bFrac = FROM_BR[yanchor];
23031
- if(lenmode === 'pixels') {
23032
- marginOpts.y = optsY;
23033
- marginOpts.t = lenPx * tFrac;
23034
- marginOpts.b = lenPx * bFrac;
23035
- } else {
23036
- marginOpts.t = marginOpts.b = 0;
23037
- marginOpts.yt = optsY + len * tFrac;
23038
- marginOpts.yb = optsY - len * bFrac;
23039
- }
23040
23267
 
23041
- var lFrac = FROM_TL[xanchor];
23042
- var rFrac = FROM_BR[xanchor];
23043
- if(thicknessmode === 'pixels') {
23044
- marginOpts.x = optsX;
23045
- marginOpts.l = outerThickness * lFrac;
23046
- marginOpts.r = outerThickness * rFrac;
23047
- } else {
23048
- var extraThickness = outerThickness - thickPx;
23049
- marginOpts.l = extraThickness * lFrac;
23050
- marginOpts.r = extraThickness * rFrac;
23051
- marginOpts.xl = optsX - thickness * lFrac;
23052
- marginOpts.xr = optsX + thickness * rFrac;
23268
+ var extraThickness = outerThickness - thickPx;
23269
+ if(isVertical) {
23270
+ if(lenmode === 'pixels') {
23271
+ marginOpts.y = optsY;
23272
+ marginOpts.t = lenPx * tFrac;
23273
+ marginOpts.b = lenPx * bFrac;
23274
+ } else {
23275
+ marginOpts.t = marginOpts.b = 0;
23276
+ marginOpts.yt = optsY + len * tFrac;
23277
+ marginOpts.yb = optsY - len * bFrac;
23278
+ }
23279
+
23280
+ if(thicknessmode === 'pixels') {
23281
+ marginOpts.x = optsX;
23282
+ marginOpts.l = outerThickness * lFrac;
23283
+ marginOpts.r = outerThickness * rFrac;
23284
+ } else {
23285
+ marginOpts.l = extraThickness * lFrac;
23286
+ marginOpts.r = extraThickness * rFrac;
23287
+ marginOpts.xl = optsX - thickness * lFrac;
23288
+ marginOpts.xr = optsX + thickness * rFrac;
23289
+ }
23290
+ } else { // horizontal colorbars
23291
+ if(lenmode === 'pixels') {
23292
+ marginOpts.x = optsX;
23293
+ marginOpts.l = lenPx * lFrac;
23294
+ marginOpts.r = lenPx * rFrac;
23295
+ } else {
23296
+ marginOpts.l = marginOpts.r = 0;
23297
+ marginOpts.xl = optsX + len * lFrac;
23298
+ marginOpts.xr = optsX - len * rFrac;
23299
+ }
23300
+
23301
+ if(thicknessmode === 'pixels') {
23302
+ marginOpts.y = 1 - optsY;
23303
+ marginOpts.t = outerThickness * tFrac;
23304
+ marginOpts.b = outerThickness * bFrac;
23305
+ } else {
23306
+ marginOpts.t = extraThickness * tFrac;
23307
+ marginOpts.b = extraThickness * bFrac;
23308
+ marginOpts.yt = optsY - thickness * tFrac;
23309
+ marginOpts.yb = optsY + thickness * bFrac;
23310
+ }
23053
23311
  }
23054
23312
 
23055
23313
  Plots.autoMargin(gd, opts._id, marginOpts);
@@ -23066,6 +23324,7 @@ function drawColorBar(g, opts, gd) {
23066
23324
  }
23067
23325
 
23068
23326
  function makeEditable(g, opts, gd) {
23327
+ var isVertical = opts.orientation === 'v';
23069
23328
  var fullLayout = gd._fullLayout;
23070
23329
  var gs = fullLayout._size;
23071
23330
  var t0, xf, yf;
@@ -23080,9 +23339,13 @@ function makeEditable(g, opts, gd) {
23080
23339
  moveFn: function(dx, dy) {
23081
23340
  g.attr('transform', t0 + strTranslate(dx, dy));
23082
23341
 
23083
- xf = dragElement.align(opts._uFrac + (dx / gs.w), opts._thickFrac,
23342
+ xf = dragElement.align(
23343
+ (isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
23344
+ isVertical ? opts._thickFrac : opts._lenFrac,
23084
23345
  0, 1, opts.xanchor);
23085
- yf = dragElement.align(opts._vFrac - (dy / gs.h), opts._lenFrac,
23346
+ yf = dragElement.align(
23347
+ (isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
23348
+ isVertical ? opts._lenFrac : opts._thickFrac,
23086
23349
  0, 1, opts.yanchor);
23087
23350
 
23088
23351
  var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
@@ -23159,6 +23422,8 @@ function calcLevels(gd, opts, zrange) {
23159
23422
  function mockColorBarAxis(gd, opts, zrange) {
23160
23423
  var fullLayout = gd._fullLayout;
23161
23424
 
23425
+ var isVertical = opts.orientation === 'v';
23426
+
23162
23427
  var cbAxisIn = {
23163
23428
  type: 'linear',
23164
23429
  range: zrange,
@@ -23189,17 +23454,19 @@ function mockColorBarAxis(gd, opts, zrange) {
23189
23454
  title: opts.title,
23190
23455
  showline: true,
23191
23456
  anchor: 'free',
23192
- side: 'right',
23457
+ side: isVertical ? 'right' : 'bottom',
23193
23458
  position: 1
23194
23459
  };
23195
23460
 
23461
+ var letter = isVertical ? 'y' : 'x';
23462
+
23196
23463
  var cbAxisOut = {
23197
23464
  type: 'linear',
23198
- _id: 'y' + opts._id
23465
+ _id: letter + opts._id
23199
23466
  };
23200
23467
 
23201
23468
  var axisOptions = {
23202
- letter: 'y',
23469
+ letter: letter,
23203
23470
  font: fullLayout.font,
23204
23471
  noHover: true,
23205
23472
  noTickson: true,
@@ -28812,7 +29079,9 @@ function createHoverText(hoverData, opts) {
28812
29079
  orientation: 'v'
28813
29080
  }
28814
29081
  };
28815
- var mockLayoutOut = {};
29082
+ var mockLayoutOut = {
29083
+ font: font
29084
+ };
28816
29085
  legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
28817
29086
  var mockLegend = mockLayoutOut.legend;
28818
29087
 
@@ -28853,7 +29122,8 @@ function createHoverText(hoverData, opts) {
28853
29122
 
28854
29123
  // Draw unified hover label
28855
29124
  mockLegend._inHover = true;
28856
- mockLegend._groupTitleFont = font;
29125
+ mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
29126
+
28857
29127
  legendDraw(gd, mockLegend);
28858
29128
 
28859
29129
  // Position the hover
@@ -29855,9 +30125,11 @@ var isUnifiedHover = _dereq_('./helpers').isUnifiedHover;
29855
30125
  module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
29856
30126
  opts = opts || {};
29857
30127
 
30128
+ var hasLegend = contOut.legend;
30129
+
29858
30130
  function inheritFontAttr(attr) {
29859
30131
  if(!opts.font[attr]) {
29860
- opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
30132
+ opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
29861
30133
  }
29862
30134
  }
29863
30135
 
@@ -29868,7 +30140,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
29868
30140
  inheritFontAttr('family');
29869
30141
  inheritFontAttr('color');
29870
30142
 
29871
- if(contOut.legend) {
30143
+ if(hasLegend) {
29872
30144
  if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
29873
30145
  if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
29874
30146
  } else {
@@ -29977,11 +30249,13 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
29977
30249
 
29978
30250
  var constants = _dereq_('./constants');
29979
30251
 
29980
- var fontAttrs = _dereq_('../../plots/font_attributes')({
30252
+ var fontAttrs = _dereq_('../../plots/font_attributes');
30253
+
30254
+ var font = fontAttrs({
29981
30255
  editType: 'none',
29982
30256
  });
29983
- fontAttrs.family.dflt = constants.HOVERFONT;
29984
- fontAttrs.size.dflt = constants.HOVERFONTSIZE;
30257
+ font.family.dflt = constants.HOVERFONT;
30258
+ font.size.dflt = constants.HOVERFONTSIZE;
29985
30259
 
29986
30260
  module.exports = {
29987
30261
  clickmode: {
@@ -30037,7 +30311,10 @@ module.exports = {
30037
30311
  valType: 'color',
30038
30312
  editType: 'none',
30039
30313
  },
30040
- font: fontAttrs,
30314
+ font: font,
30315
+ grouptitlefont: fontAttrs({
30316
+ editType: 'none',
30317
+ }),
30041
30318
  align: {
30042
30319
  valType: 'enumerated',
30043
30320
  values: ['left', 'right', 'auto'],
@@ -30050,6 +30327,7 @@ module.exports = {
30050
30327
  dflt: 15,
30051
30328
  editType: 'none',
30052
30329
  },
30330
+
30053
30331
  editType: 'none'
30054
30332
  },
30055
30333
  selectdirection: {
@@ -30097,6 +30375,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
30097
30375
  }
30098
30376
 
30099
30377
  handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
30378
+
30379
+ Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
30100
30380
  };
30101
30381
 
30102
30382
  },{"../../lib":252,"./hoverlabel_defaults":157,"./hovermode_defaults":158,"./layout_attributes":160}],162:[function(_dereq_,module,exports){
@@ -30980,6 +31260,9 @@ module.exports = {
30980
31260
  font: fontAttrs({
30981
31261
  editType: 'legend',
30982
31262
  }),
31263
+ grouptitlefont: fontAttrs({
31264
+ editType: 'legend',
31265
+ }),
30983
31266
  orientation: {
30984
31267
  valType: 'enumerated',
30985
31268
  values: ['v', 'h'],
@@ -31103,6 +31386,7 @@ var Registry = _dereq_('../../registry');
31103
31386
  var Lib = _dereq_('../../lib');
31104
31387
  var Template = _dereq_('../../plot_api/plot_template');
31105
31388
 
31389
+ var plotsAttrs = _dereq_('../../plots/attributes');
31106
31390
  var attributes = _dereq_('./attributes');
31107
31391
  var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes');
31108
31392
  var helpers = _dereq_('./helpers');
@@ -31110,13 +31394,30 @@ var helpers = _dereq_('./helpers');
31110
31394
 
31111
31395
  module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31112
31396
  var containerIn = layoutIn.legend || {};
31397
+ var containerOut = Template.newContainer(layoutOut, 'legend');
31398
+
31399
+ function coerce(attr, dflt) {
31400
+ return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
31401
+ }
31402
+
31403
+ var trace;
31404
+ var traceCoerce = function(attr, dflt) {
31405
+ var traceIn = trace._input;
31406
+ var traceOut = trace;
31407
+ return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
31408
+ };
31409
+
31410
+ var globalFont = layoutOut.font || {};
31411
+ var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
31412
+ size: Math.round(globalFont.size * 1.1)
31413
+ }));
31113
31414
 
31114
31415
  var legendTraceCount = 0;
31115
31416
  var legendReallyHasATrace = false;
31116
31417
  var defaultOrder = 'normal';
31117
31418
 
31118
31419
  for(var i = 0; i < fullData.length; i++) {
31119
- var trace = fullData[i];
31420
+ trace = fullData[i];
31120
31421
 
31121
31422
  if(!trace.visible) continue;
31122
31423
 
@@ -31143,6 +31444,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31143
31444
  legendTraceCount++;
31144
31445
  }
31145
31446
  }
31447
+
31448
+ Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
31146
31449
  }
31147
31450
 
31148
31451
  if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -31161,13 +31464,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31161
31464
  basePlotLayoutAttributes, 'showlegend',
31162
31465
  legendReallyHasATrace && legendTraceCount > 1);
31163
31466
 
31164
- if(showLegend === false && !containerIn.uirevision) return;
31165
-
31166
- var containerOut = Template.newContainer(layoutOut, 'legend');
31467
+ // delete legend
31468
+ if(showLegend === false) layoutOut.legend = undefined;
31167
31469
 
31168
- function coerce(attr, dflt) {
31169
- return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
31170
- }
31470
+ if(showLegend === false && !containerIn.uirevision) return;
31171
31471
 
31172
31472
  coerce('uirevision', layoutOut.uirevision);
31173
31473
 
@@ -31229,7 +31529,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31229
31529
  }
31230
31530
  };
31231
31531
 
31232
- },{"../../lib":252,"../../plot_api/plot_template":290,"../../plots/layout_attributes":347,"../../registry":352,"./attributes":169,"./helpers":175}],172:[function(_dereq_,module,exports){
31532
+ },{"../../lib":252,"../../plot_api/plot_template":290,"../../plots/attributes":297,"../../plots/layout_attributes":347,"../../registry":352,"./attributes":169,"./helpers":175}],172:[function(_dereq_,module,exports){
31233
31533
  'use strict';
31234
31534
 
31235
31535
  var d3 = _dereq_('@plotly/d3');
@@ -39681,8 +39981,10 @@ function draw(gd, titleClass, options) {
39681
39981
 
39682
39982
  var elShouldExist = txt || editable;
39683
39983
 
39984
+ var hColorbarMoveTitle;
39684
39985
  if(!group) {
39685
39986
  group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass);
39987
+ hColorbarMoveTitle = fullLayout._hColorbarMoveTitle;
39686
39988
  }
39687
39989
 
39688
39990
  var el = group.selectAll('text')
@@ -39706,13 +40008,17 @@ function draw(gd, titleClass, options) {
39706
40008
  function drawTitle(titleEl) {
39707
40009
  var transformVal;
39708
40010
 
40011
+ if(!transform && hColorbarMoveTitle) {
40012
+ transform = {};
40013
+ }
40014
+
39709
40015
  if(transform) {
39710
40016
  transformVal = '';
39711
40017
  if(transform.rotate) {
39712
40018
  transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')';
39713
40019
  }
39714
- if(transform.offset) {
39715
- transformVal += strTranslate(0, transform.offset);
40020
+ if(transform.offset || hColorbarMoveTitle) {
40021
+ transformVal += strTranslate(0, (transform.offset || 0) - (hColorbarMoveTitle || 0));
39716
40022
  }
39717
40023
  } else {
39718
40024
  transformVal = null;
@@ -51356,7 +51662,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
51356
51662
  if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
51357
51663
  (typeof value === 'string' || typeof value === 'number')) {
51358
51664
  replace(key, key.replace('title', 'title.text'));
51359
- } else if(key.indexOf('titlefont') > -1) {
51665
+ } else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
51360
51666
  replace(key, key.replace('titlefont', 'title.font'));
51361
51667
  } else if(key.indexOf('titleposition') > -1) {
51362
51668
  replace(key, key.replace('titleposition', 'title.position'));
@@ -52033,7 +52339,8 @@ function findUIPattern(key, patternSpecs) {
52033
52339
  var spec = patternSpecs[i];
52034
52340
  var match = key.match(spec.pattern);
52035
52341
  if(match) {
52036
- return {head: match[1], attr: spec.attr};
52342
+ var head = match[1] || '';
52343
+ return {head: head, tail: key.substr(head.length + 1), attr: spec.attr};
52037
52344
  }
52038
52345
  }
52039
52346
  }
@@ -52085,26 +52392,54 @@ function valsMatch(v1, v2) {
52085
52392
 
52086
52393
  function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
52087
52394
  var layoutPreGUI = oldFullLayout._preGUI;
52088
- var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal;
52395
+ var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal, head, tail;
52089
52396
  var bothInheritAutorange = [];
52397
+ var newAutorangeIn = {};
52090
52398
  var newRangeAccepted = {};
52091
52399
  for(key in layoutPreGUI) {
52092
52400
  match = findUIPattern(key, layoutUIControlPatterns);
52093
52401
  if(match) {
52094
- revAttr = match.attr || (match.head + '.uirevision');
52402
+ head = match.head;
52403
+ tail = match.tail;
52404
+ revAttr = match.attr || (head + '.uirevision');
52095
52405
  oldRev = nestedProperty(oldFullLayout, revAttr).get();
52096
52406
  newRev = oldRev && getNewRev(revAttr, layout);
52407
+
52097
52408
  if(newRev && (newRev === oldRev)) {
52098
52409
  preGUIVal = layoutPreGUI[key];
52099
52410
  if(preGUIVal === null) preGUIVal = undefined;
52100
52411
  newNP = nestedProperty(layout, key);
52101
52412
  newVal = newNP.get();
52413
+
52102
52414
  if(valsMatch(newVal, preGUIVal)) {
52103
- if(newVal === undefined && key.substr(key.length - 9) === 'autorange') {
52104
- bothInheritAutorange.push(key.substr(0, key.length - 10));
52415
+ if(newVal === undefined && tail === 'autorange') {
52416
+ bothInheritAutorange.push(head);
52105
52417
  }
52106
52418
  newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
52107
52419
  continue;
52420
+ } else if(tail === 'autorange' || tail.substr(0, 6) === 'range[') {
52421
+ // Special case for (auto)range since we push it back into the layout
52422
+ // so all null should be treated equivalently to autorange: true with any range
52423
+ var pre0 = layoutPreGUI[head + '.range[0]'];
52424
+ var pre1 = layoutPreGUI[head + '.range[1]'];
52425
+ var preAuto = layoutPreGUI[head + '.autorange'];
52426
+ if(preAuto || (preAuto === null && pre0 === null && pre1 === null)) {
52427
+ // Only read the input layout once and stash the result,
52428
+ // so we get it before we start modifying it
52429
+ if(!(head in newAutorangeIn)) {
52430
+ var newContainer = nestedProperty(layout, head).get();
52431
+ newAutorangeIn[head] = newContainer && (
52432
+ newContainer.autorange ||
52433
+ (newContainer.autorange !== false && (
52434
+ !newContainer.range || newContainer.range.length !== 2)
52435
+ )
52436
+ );
52437
+ }
52438
+ if(newAutorangeIn[head]) {
52439
+ newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
52440
+ continue;
52441
+ }
52442
+ }
52108
52443
  }
52109
52444
  }
52110
52445
  } else {
@@ -52115,12 +52450,12 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
52115
52450
  // so remove it from _preGUI for next time.
52116
52451
  delete layoutPreGUI[key];
52117
52452
 
52118
- if(key.substr(key.length - 8, 6) === 'range[') {
52119
- newRangeAccepted[key.substr(0, key.length - 9)] = 1;
52453
+ if(match && match.tail.substr(0, 6) === 'range[') {
52454
+ newRangeAccepted[match.head] = 1;
52120
52455
  }
52121
52456
  }
52122
52457
 
52123
- // Special logic for `autorange`, since it interacts with `range`:
52458
+ // More special logic for `autorange`, since it interacts with `range`:
52124
52459
  // If the new figure's matching `range` was kept, and `autorange`
52125
52460
  // wasn't supplied explicitly in either the original or the new figure,
52126
52461
  // we shouldn't alter that - but we may just have done that, so fix it.
@@ -69195,6 +69530,9 @@ module.exports = function(opts) {
69195
69530
  // TODO - that's uber hacky... better solution?
69196
69531
  };
69197
69532
 
69533
+ if(opts.autoSize) attrs.size.dflt = 'auto';
69534
+ if(opts.autoColor) attrs.color.dflt = 'auto';
69535
+
69198
69536
  if(opts.arrayOk) {
69199
69537
  attrs.family.arrayOk = true;
69200
69538
  attrs.size.arrayOk = true;
@@ -71589,6 +71927,7 @@ module.exports = {
71589
71927
  valType: 'boolean',
71590
71928
  editType: 'legend',
71591
71929
  },
71930
+
71592
71931
  colorway: {
71593
71932
  valType: 'colorlist',
71594
71933
  dflt: colorAttrs.defaults,
@@ -73001,13 +73340,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
73001
73340
  );
73002
73341
 
73003
73342
  coerce('legendgroup');
73004
- var titleText = coerce('legendgrouptitle.text');
73005
- if(titleText) {
73006
- Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
73007
- size: Math.round(layout.font.size * 1.1) // default to larger font size
73008
- }));
73009
- }
73010
-
73343
+ coerce('legendgrouptitle.text');
73011
73344
  coerce('legendrank');
73012
73345
 
73013
73346
  traceOut._dfltShowLegend = true;
@@ -73155,16 +73488,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
73155
73488
 
73156
73489
  coerce('autotypenumbers');
73157
73490
 
73158
- var globalFont = Lib.coerceFont(coerce, 'font');
73159
-
73160
- coerce('title.text', layoutOut._dfltTitle.plot);
73491
+ var font = Lib.coerceFont(coerce, 'font');
73492
+ var fontSize = font.size;
73161
73493
 
73162
- Lib.coerceFont(coerce, 'title.font', {
73163
- family: globalFont.family,
73164
- size: Math.round(globalFont.size * 1.4),
73165
- color: globalFont.color
73166
- });
73494
+ Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
73495
+ size: Math.round(fontSize * 1.4)
73496
+ }));
73167
73497
 
73498
+ coerce('title.text', layoutOut._dfltTitle.plot);
73168
73499
  coerce('title.xref');
73169
73500
  coerce('title.yref');
73170
73501
  coerce('title.x');
@@ -85954,7 +86285,7 @@ function getSortFunc(opts, d2c) {
85954
86285
  'use strict';
85955
86286
 
85956
86287
  // package version injected by `npm run preprocess`
85957
- exports.version = '2.6.4';
86288
+ exports.version = '2.8.2';
85958
86289
 
85959
86290
  },{}],435:[function(_dereq_,module,exports){
85960
86291
  (function (global){(function (){