plotly.js 2.6.2 → 2.8.0

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 +568 -225
  6. package/dist/plotly-basic.min.js +4 -4
  7. package/dist/plotly-cartesian.js +1029 -371
  8. package/dist/plotly-cartesian.min.js +3 -3
  9. package/dist/plotly-finance.js +618 -227
  10. package/dist/plotly-finance.min.js +4 -4
  11. package/dist/plotly-geo-assets.js +2 -2
  12. package/dist/plotly-geo.js +564 -223
  13. package/dist/plotly-geo.min.js +2 -2
  14. package/dist/plotly-gl2d.js +580 -224
  15. package/dist/plotly-gl2d.min.js +2 -2
  16. package/dist/plotly-gl3d.js +564 -223
  17. package/dist/plotly-gl3d.min.js +2 -2
  18. package/dist/plotly-mapbox.js +570 -226
  19. package/dist/plotly-mapbox.min.js +2 -2
  20. package/dist/plotly-strict.js +1253 -592
  21. package/dist/plotly-strict.min.js +3 -3
  22. package/dist/plotly-with-meta.js +1345 -654
  23. package/dist/plotly.js +1307 -646
  24. package/dist/plotly.min.js +10 -10
  25. package/package.json +9 -9
  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 +398 -141
  29. package/src/components/drawing/index.js +6 -3
  30. package/src/components/fx/hover.js +16 -17
  31. package/src/components/fx/hoverlabel_defaults.js +4 -2
  32. package/src/components/fx/layout_attributes.js +14 -4
  33. package/src/components/fx/layout_defaults.js +2 -0
  34. package/src/components/legend/attributes.js +7 -0
  35. package/src/components/legend/defaults.js +24 -7
  36. package/src/components/titles/index.js +8 -2
  37. package/src/plot_api/plot_api.js +38 -9
  38. package/src/plots/font_attributes.js +3 -0
  39. package/src/plots/layout_attributes.js +1 -0
  40. package/src/plots/mapbox/mapbox.js +6 -3
  41. package/src/plots/plots.js +7 -15
  42. package/src/traces/bar/plot.js +1 -1
  43. package/src/traces/contour/attributes.js +12 -0
  44. package/src/traces/contour/defaults.js +9 -1
  45. package/src/traces/heatmap/attributes.js +16 -0
  46. package/src/traces/heatmap/defaults.js +2 -0
  47. package/src/traces/heatmap/label_defaults.js +13 -0
  48. package/src/traces/heatmap/plot.js +203 -4
  49. package/src/traces/histogram/attributes.js +40 -0
  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 (geo) v2.6.2
2
+ * plotly.js (geo) v2.8.0
3
3
  * Copyright 2012-2021, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -35317,13 +35317,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
35317
35317
 
35318
35318
 
35319
35319
  module.exports = overrideAll({
35320
- // TODO: only right is supported currently
35321
- // orient: {
35322
- // valType: 'enumerated',
35323
- // values: ['left', 'right', 'top', 'bottom'],
35324
- // dflt: 'right',
35325
- //
35326
- // },
35320
+ orientation: {
35321
+ valType: 'enumerated',
35322
+ values: ['h', 'v'],
35323
+ dflt: 'v',
35324
+ },
35327
35325
  thicknessmode: {
35328
35326
  valType: 'enumerated',
35329
35327
  values: ['fraction', 'pixels'],
@@ -35346,14 +35344,12 @@ module.exports = overrideAll({
35346
35344
  },
35347
35345
  x: {
35348
35346
  valType: 'number',
35349
- dflt: 1.02,
35350
35347
  min: -2,
35351
35348
  max: 3,
35352
35349
  },
35353
35350
  xanchor: {
35354
35351
  valType: 'enumerated',
35355
35352
  values: ['left', 'center', 'right'],
35356
- dflt: 'left',
35357
35353
  },
35358
35354
  xpad: {
35359
35355
  valType: 'number',
@@ -35362,14 +35358,12 @@ module.exports = overrideAll({
35362
35358
  },
35363
35359
  y: {
35364
35360
  valType: 'number',
35365
- dflt: 0.5,
35366
35361
  min: -2,
35367
35362
  max: 3,
35368
35363
  },
35369
35364
  yanchor: {
35370
35365
  valType: 'enumerated',
35371
35366
  values: ['top', 'middle', 'bottom'],
35372
- dflt: 'middle',
35373
35367
  },
35374
35368
  ypad: {
35375
35369
  valType: 'number',
@@ -35401,15 +35395,21 @@ module.exports = overrideAll({
35401
35395
  ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
35402
35396
  ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
35403
35397
  }),
35398
+
35399
+ // ticklabelposition: not used directly, as values depend on orientation
35400
+ // left/right options are for x axes, and top/bottom options are for y axes
35404
35401
  ticklabelposition: {
35405
35402
  valType: 'enumerated',
35406
35403
  values: [
35407
35404
  'outside', 'inside',
35408
35405
  'outside top', 'inside top',
35406
+ 'outside left', 'inside left',
35407
+ 'outside right', 'inside right',
35409
35408
  'outside bottom', 'inside bottom'
35410
35409
  ],
35411
35410
  dflt: 'outside',
35412
35411
  },
35412
+
35413
35413
  ticklen: axesAttrs.ticklen,
35414
35414
  tickwidth: axesAttrs.tickwidth,
35415
35415
  tickcolor: axesAttrs.tickcolor,
@@ -35436,7 +35436,6 @@ module.exports = overrideAll({
35436
35436
  side: {
35437
35437
  valType: 'enumerated',
35438
35438
  values: ['right', 'top', 'bottom'],
35439
- dflt: 'top',
35440
35439
  }
35441
35440
  },
35442
35441
 
@@ -35495,23 +35494,30 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
35495
35494
  return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt);
35496
35495
  }
35497
35496
 
35497
+ var margin = layout.margin || {t: 0, b: 0, l: 0, r: 0};
35498
+ var w = layout.width - margin.l - margin.r;
35499
+ var h = layout.height - margin.t - margin.b;
35500
+
35501
+ var orientation = coerce('orientation');
35502
+ var isVertical = orientation === 'v';
35503
+
35498
35504
  var thicknessmode = coerce('thicknessmode');
35499
35505
  coerce('thickness', (thicknessmode === 'fraction') ?
35500
- 30 / (layout.width - layout.margin.l - layout.margin.r) :
35506
+ 30 / (isVertical ? w : h) :
35501
35507
  30
35502
35508
  );
35503
35509
 
35504
35510
  var lenmode = coerce('lenmode');
35505
35511
  coerce('len', (lenmode === 'fraction') ?
35506
35512
  1 :
35507
- layout.height - layout.margin.t - layout.margin.b
35513
+ isVertical ? h : w
35508
35514
  );
35509
35515
 
35510
- coerce('x');
35511
- coerce('xanchor');
35516
+ coerce('x', isVertical ? 1.02 : 0.5);
35517
+ coerce('xanchor', isVertical ? 'left' : 'center');
35512
35518
  coerce('xpad');
35513
- coerce('y');
35514
- coerce('yanchor');
35519
+ coerce('y', isVertical ? 0.5 : 1.02);
35520
+ coerce('yanchor', isVertical ? 'middle' : 'bottom');
35515
35521
  coerce('ypad');
35516
35522
  Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']);
35517
35523
 
@@ -35521,7 +35527,22 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
35521
35527
  coerce('borderwidth');
35522
35528
  coerce('bgcolor');
35523
35529
 
35524
- var ticklabelposition = coerce('ticklabelposition');
35530
+ var ticklabelposition = Lib.coerce(colorbarIn, colorbarOut, {
35531
+ ticklabelposition: {
35532
+ valType: 'enumerated',
35533
+ dflt: 'outside',
35534
+ values: isVertical ? [
35535
+ 'outside', 'inside',
35536
+ 'outside top', 'inside top',
35537
+ 'outside bottom', 'inside bottom'
35538
+ ] : [
35539
+ 'outside', 'inside',
35540
+ 'outside left', 'inside left',
35541
+ 'outside right', 'inside right'
35542
+ ]
35543
+ }
35544
+ }, 'ticklabelposition');
35545
+
35525
35546
  coerce('ticklabeloverflow', ticklabelposition.indexOf('inside') !== -1 ? 'hide past domain' : 'hide past div');
35526
35547
 
35527
35548
  handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear');
@@ -35543,7 +35564,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
35543
35564
  size: Lib.bigFont(tickFont.size)
35544
35565
  });
35545
35566
  Lib.coerceFont(coerce, 'title.font', dfltTitleFont);
35546
- coerce('title.side');
35567
+ coerce('title.side', isVertical ? 'top' : 'right');
35547
35568
  };
35548
35569
 
35549
35570
  },{"../../lib":248,"../../plot_api/plot_template":285,"../../plots/cartesian/prefix_suffix_defaults":315,"../../plots/cartesian/tick_label_defaults":320,"../../plots/cartesian/tick_mark_defaults":321,"../../plots/cartesian/tick_value_defaults":322,"./attributes":117}],120:[function(_dereq_,module,exports){
@@ -35716,6 +35737,21 @@ function makeColorBarData(gd) {
35716
35737
  }
35717
35738
 
35718
35739
  function drawColorBar(g, opts, gd) {
35740
+ var isVertical = opts.orientation === 'v';
35741
+ var len = opts.len;
35742
+ var lenmode = opts.lenmode;
35743
+ var thickness = opts.thickness;
35744
+ var thicknessmode = opts.thicknessmode;
35745
+ var outlinewidth = opts.outlinewidth;
35746
+ var borderwidth = opts.borderwidth;
35747
+ var bgcolor = opts.bgcolor;
35748
+ var xanchor = opts.xanchor;
35749
+ var yanchor = opts.yanchor;
35750
+ var xpad = opts.xpad;
35751
+ var ypad = opts.ypad;
35752
+ var optsX = opts.x;
35753
+ var optsY = isVertical ? opts.y : 1 - opts.y;
35754
+
35719
35755
  var fullLayout = gd._fullLayout;
35720
35756
  var gs = fullLayout._size;
35721
35757
 
@@ -35745,42 +35781,64 @@ function drawColorBar(g, opts, gd) {
35745
35781
  // when the colorbar itself is pushing the margins.
35746
35782
  // but then the fractional size is calculated based on the
35747
35783
  // actual graph size, so that the axes will size correctly.
35748
- var thickPx = Math.round(opts.thickness * (opts.thicknessmode === 'fraction' ? gs.w : 1));
35749
- var thickFrac = thickPx / gs.w;
35750
- var lenPx = Math.round(opts.len * (opts.lenmode === 'fraction' ? gs.h : 1));
35751
- var lenFrac = lenPx / gs.h;
35752
- var xpadFrac = opts.xpad / gs.w;
35753
- var yExtraPx = (opts.borderwidth + opts.outlinewidth) / 2;
35754
- var ypadFrac = opts.ypad / gs.h;
35784
+ var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
35785
+ var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
35786
+ var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
35787
+ var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
35755
35788
 
35756
35789
  // x positioning: do it initially just for left anchor,
35757
35790
  // then fix at the end (since we don't know the width yet)
35758
- var xLeft = Math.round(opts.x * gs.w + opts.xpad);
35759
- // for dragging... this is getting a little muddled...
35760
- var xLeftFrac = opts.x - thickFrac * ({center: 0.5, right: 1}[opts.xanchor] || 0);
35791
+ var uPx = Math.round(isVertical ?
35792
+ optsX * gs.w + xpad :
35793
+ optsY * gs.h + ypad
35794
+ );
35761
35795
 
35762
- // y positioning we can do correctly from the start
35763
- var yBottomFrac = opts.y + lenFrac * (({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5);
35764
- var yBottomPx = Math.round(gs.h * (1 - yBottomFrac));
35765
- var yTopPx = yBottomPx - lenPx;
35796
+ var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
35797
+ var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
35798
+
35799
+ // for dragging... this is getting a little muddled...
35800
+ var uFrac = isVertical ?
35801
+ optsX - xRatio * thickFrac :
35802
+ optsY - yRatio * thickFrac;
35803
+
35804
+ // y/x positioning (for v/h) we can do correctly from the start
35805
+ var vFrac = isVertical ?
35806
+ optsY - yRatio * lenFrac :
35807
+ optsX - xRatio * lenFrac;
35808
+
35809
+ var vPx = Math.round(isVertical ?
35810
+ gs.h * (1 - vFrac) :
35811
+ gs.w * vFrac
35812
+ );
35766
35813
 
35767
35814
  // stash a few things for makeEditable
35768
35815
  opts._lenFrac = lenFrac;
35769
35816
  opts._thickFrac = thickFrac;
35770
- opts._xLeftFrac = xLeftFrac;
35771
- opts._yBottomFrac = yBottomFrac;
35817
+ opts._uFrac = uFrac;
35818
+ opts._vFrac = vFrac;
35772
35819
 
35773
35820
  // stash mocked axis for contour label formatting
35774
35821
  var ax = opts._axis = mockColorBarAxis(gd, opts, zrange);
35775
35822
 
35776
35823
  // position can't go in through supplyDefaults
35777
35824
  // because that restricts it to [0,1]
35778
- ax.position = opts.x + xpadFrac + thickFrac;
35825
+ ax.position = thickFrac + (isVertical ?
35826
+ optsX + xpad / gs.w :
35827
+ optsY + ypad / gs.h
35828
+ );
35829
+
35830
+ var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
35831
+
35832
+ if(isVertical && topOrBottom) {
35833
+ ax.title.side = titleSide;
35834
+ ax.titlex = optsX + xpad / gs.w;
35835
+ ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
35836
+ }
35779
35837
 
35780
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
35838
+ if(!isVertical && !topOrBottom) {
35781
35839
  ax.title.side = titleSide;
35782
- ax.titlex = opts.x + xpadFrac;
35783
- ax.titley = yBottomFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
35840
+ ax.titley = optsY + ypad / gs.h;
35841
+ ax.titlex = vFrac + xpad / gs.w; // right side
35784
35842
  }
35785
35843
 
35786
35844
  if(line.color && opts.tickmode === 'auto') {
@@ -35788,7 +35846,7 @@ function drawColorBar(g, opts, gd) {
35788
35846
  ax.tick0 = levelsIn.start;
35789
35847
  var dtick = levelsIn.size;
35790
35848
  // expand if too many contours, so we don't get too many ticks
35791
- var autoNtick = Lib.constrain((yBottomPx - yTopPx) / 50, 4, 15) + 1;
35849
+ var autoNtick = Lib.constrain(lenPx / 50, 4, 15) + 1;
35792
35850
  var dtFactor = (zrange[1] - zrange[0]) / ((opts.nticks || autoNtick) * dtick);
35793
35851
  if(dtFactor > 1) {
35794
35852
  var dtexp = Math.pow(10, Math.floor(Math.log(dtFactor) / Math.LN10));
@@ -35805,9 +35863,12 @@ function drawColorBar(g, opts, gd) {
35805
35863
 
35806
35864
  // set domain after init, because we may want to
35807
35865
  // allow it outside [0,1]
35808
- ax.domain = [
35809
- yBottomFrac + ypadFrac,
35810
- yBottomFrac + lenFrac - ypadFrac
35866
+ ax.domain = isVertical ? [
35867
+ vFrac + ypad / gs.h,
35868
+ vFrac + lenFrac - ypad / gs.h
35869
+ ] : [
35870
+ vFrac + xpad / gs.w,
35871
+ vFrac + lenFrac - xpad / gs.w
35811
35872
  ];
35812
35873
 
35813
35874
  ax.setScale();
@@ -35817,9 +35878,13 @@ function drawColorBar(g, opts, gd) {
35817
35878
  var titleCont = g.select('.' + cn.cbtitleunshift)
35818
35879
  .attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
35819
35880
 
35881
+ var ticklabelposition = ax.ticklabelposition;
35882
+ var titleFontSize = ax.title.font.size;
35883
+
35820
35884
  var axLayer = g.select('.' + cn.cbaxis);
35821
35885
  var titleEl;
35822
35886
  var titleHeight = 0;
35887
+ var titleWidth = 0;
35823
35888
 
35824
35889
  function drawTitle(titleClass, titleOpts) {
35825
35890
  var dfltTitleOpts = {
@@ -35844,58 +35909,102 @@ function drawColorBar(g, opts, gd) {
35844
35909
  }
35845
35910
 
35846
35911
  function drawDummyTitle() {
35847
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
35848
- // draw the title so we know how much room it needs
35849
- // when we squish the axis. This one only applies to
35850
- // top or bottom titles, not right side.
35851
- var x = gs.l + (opts.x + xpadFrac) * gs.w;
35852
- var fontSize = ax.title.font.size;
35853
- var y;
35912
+ // draw the title so we know how much room it needs
35913
+ // when we squish the axis.
35914
+ // On vertical colorbars this only applies to top or bottom titles, not right side.
35915
+ // On horizontal colorbars this only applies to right, etc.
35916
+
35917
+ if(
35918
+ (isVertical && topOrBottom) ||
35919
+ (!isVertical && !topOrBottom)
35920
+ ) {
35921
+ var x, y;
35854
35922
 
35855
35923
  if(titleSide === 'top') {
35856
- y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h +
35857
- gs.t + 3 + fontSize * 0.75;
35858
- } else {
35859
- y = (1 - (yBottomFrac + ypadFrac)) * gs.h +
35860
- gs.t - 3 - fontSize * 0.25;
35924
+ x = xpad + gs.l + gs.w * optsX;
35925
+ y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
35926
+ }
35927
+
35928
+ if(titleSide === 'bottom') {
35929
+ x = xpad + gs.l + gs.w * optsX;
35930
+ y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
35931
+ }
35932
+
35933
+ if(titleSide === 'right') {
35934
+ y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
35935
+ x = xpad + gs.l + gs.w * vFrac;
35861
35936
  }
35937
+
35862
35938
  drawTitle(ax._id + 'title', {
35863
- attributes: {x: x, y: y, 'text-anchor': 'start'}
35939
+ attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
35864
35940
  });
35865
35941
  }
35866
35942
  }
35867
35943
 
35868
35944
  function drawCbTitle() {
35869
- if(['top', 'bottom'].indexOf(titleSide) === -1) {
35870
- var fontSize = ax.title.font.size;
35871
- var y = ax._offset + ax._length / 2;
35872
- var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ?
35873
- 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) :
35874
- -10 - fontSize * ((ax.showticklabels ? 0.5 : 0)));
35875
-
35876
- // the 'h' + is a hack to get around the fact that
35877
- // convertToTspans rotates any 'y...' class by 90 degrees.
35878
- // TODO: find a better way to control this.
35879
- drawTitle('h' + ax._id + 'title', {
35945
+ if(
35946
+ (isVertical && !topOrBottom) ||
35947
+ (!isVertical && topOrBottom)
35948
+ ) {
35949
+ var pos = ax.position || 0;
35950
+ var mid = ax._offset + ax._length / 2;
35951
+ var x, y;
35952
+
35953
+ if(titleSide === 'right') {
35954
+ y = mid;
35955
+ x = gs.l + gs.w * pos + 10 + titleFontSize * (
35956
+ ax.showticklabels ? 1 : 0.5
35957
+ );
35958
+ } else {
35959
+ x = mid;
35960
+
35961
+ if(titleSide === 'bottom') {
35962
+ y = gs.t + gs.h * pos + 10 + (
35963
+ ticklabelposition.indexOf('inside') === -1 ?
35964
+ ax.tickfont.size :
35965
+ 0
35966
+ ) + (
35967
+ ax.ticks !== 'intside' ?
35968
+ opts.ticklen || 0 :
35969
+ 0
35970
+ );
35971
+ }
35972
+
35973
+ if(titleSide === 'top') {
35974
+ var nlines = title.text.split('<br>').length;
35975
+ y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
35976
+ }
35977
+ }
35978
+
35979
+ drawTitle((isVertical ?
35980
+ // the 'h' + is a hack to get around the fact that
35981
+ // convertToTspans rotates any 'y...' class by 90 degrees.
35982
+ // TODO: find a better way to control this.
35983
+ 'h' :
35984
+ 'v'
35985
+ ) + ax._id + 'title', {
35880
35986
  avoid: {
35881
35987
  selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
35882
35988
  side: titleSide,
35883
- offsetLeft: gs.l,
35884
- offsetTop: 0,
35885
- maxShift: fullLayout.width
35989
+ offsetTop: isVertical ? 0 : gs.t,
35990
+ offsetLeft: isVertical ? gs.l : 0,
35991
+ maxShift: isVertical ? fullLayout.width : fullLayout.height
35886
35992
  },
35887
35993
  attributes: {x: x, y: y, 'text-anchor': 'middle'},
35888
- transform: {rotate: '-90', offset: 0}
35994
+ transform: {rotate: isVertical ? -90 : 0, offset: 0}
35889
35995
  });
35890
35996
  }
35891
35997
  }
35892
35998
 
35893
35999
  function drawAxis() {
35894
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
36000
+ if(
36001
+ (!isVertical && !topOrBottom) ||
36002
+ (isVertical && topOrBottom)
36003
+ ) {
35895
36004
  // squish the axis top to make room for the title
35896
36005
  var titleGroup = g.select('.' + cn.cbtitle);
35897
36006
  var titleText = titleGroup.select('text');
35898
- var titleTrans = [-opts.outlinewidth / 2, opts.outlinewidth / 2];
36007
+ var titleTrans = [-outlinewidth / 2, outlinewidth / 2];
35899
36008
  var mathJaxNode = titleGroup
35900
36009
  .select('.h' + ax._id + 'title-math-group')
35901
36010
  .node();
@@ -35903,39 +36012,63 @@ function drawColorBar(g, opts, gd) {
35903
36012
  if(titleText.node()) {
35904
36013
  lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
35905
36014
  }
36015
+
36016
+ var bb;
35906
36017
  if(mathJaxNode) {
35907
- titleHeight = Drawing.bBox(mathJaxNode).height;
36018
+ bb = Drawing.bBox(mathJaxNode);
36019
+ titleWidth = bb.width;
36020
+ titleHeight = bb.height;
35908
36021
  if(titleHeight > lineSize) {
35909
36022
  // not entirely sure how mathjax is doing
35910
36023
  // vertical alignment, but this seems to work.
35911
36024
  titleTrans[1] -= (titleHeight - lineSize) / 2;
35912
36025
  }
35913
36026
  } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
35914
- titleHeight = Drawing.bBox(titleText.node()).height;
36027
+ bb = Drawing.bBox(titleText.node());
36028
+ titleWidth = bb.width;
36029
+ titleHeight = bb.height;
35915
36030
  }
35916
- if(titleHeight) {
35917
- // buffer btwn colorbar and title
35918
- // TODO: configurable
35919
- titleHeight += 5;
35920
36031
 
35921
- if(titleSide === 'top') {
35922
- ax.domain[1] -= titleHeight / gs.h;
35923
- titleTrans[1] *= -1;
35924
- } else {
35925
- ax.domain[0] += titleHeight / gs.h;
35926
- var nlines = svgTextUtils.lineCount(titleText);
35927
- titleTrans[1] += (1 - nlines) * lineSize;
36032
+ if(isVertical) {
36033
+ if(titleHeight) {
36034
+ // buffer btwn colorbar and title
36035
+ // TODO: configurable
36036
+ titleHeight += 5;
36037
+
36038
+ if(titleSide === 'top') {
36039
+ ax.domain[1] -= titleHeight / gs.h;
36040
+ titleTrans[1] *= -1;
36041
+ } else {
36042
+ ax.domain[0] += titleHeight / gs.h;
36043
+ var nlines = svgTextUtils.lineCount(titleText);
36044
+ titleTrans[1] += (1 - nlines) * lineSize;
36045
+ }
36046
+
36047
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
36048
+ ax.setScale();
35928
36049
  }
36050
+ } else { // horizontal colorbars
36051
+ if(titleWidth) {
36052
+ if(titleSide === 'right') {
36053
+ ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
36054
+ }
35929
36055
 
35930
- titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
35931
- ax.setScale();
36056
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
36057
+ ax.setScale();
36058
+ }
35932
36059
  }
35933
36060
  }
35934
36061
 
35935
36062
  g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
35936
- .attr('transform', strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))));
36063
+ .attr('transform', isVertical ?
36064
+ strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
36065
+ strTranslate(Math.round(gs.w * ax.domain[0]), 0)
36066
+ );
35937
36067
 
35938
- axLayer.attr('transform', strTranslate(0, Math.round(-gs.t)));
36068
+ axLayer.attr('transform', isVertical ?
36069
+ strTranslate(0, Math.round(-gs.t)) :
36070
+ strTranslate(Math.round(-gs.l), 0)
36071
+ );
35939
36072
 
35940
36073
  var fills = g.select('.' + cn.cbfills)
35941
36074
  .selectAll('rect.' + cn.cbfill)
@@ -35961,20 +36094,22 @@ function drawColorBar(g, opts, gd) {
35961
36094
 
35962
36095
  // offset the side adjoining the next rectangle so they
35963
36096
  // overlap, to prevent antialiasing gaps
35964
- z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
35965
-
36097
+ if(isVertical) {
36098
+ z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
36099
+ } /* else {
36100
+ // TODO: horizontal case
36101
+ } */
35966
36102
 
35967
36103
  // Colorbar cannot currently support opacities so we
35968
36104
  // use an opaque fill even when alpha channels present
35969
- var fillEl = d3.select(this).attr({
35970
- x: xLeft,
35971
- width: Math.max(thickPx, 2),
35972
- y: d3.min(z),
35973
- height: Math.max(d3.max(z) - d3.min(z), 2),
35974
- });
36105
+ var fillEl = d3.select(this)
36106
+ .attr(isVertical ? 'x' : 'y', uPx)
36107
+ .attr(isVertical ? 'y' : 'x', d3.min(z))
36108
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
36109
+ .attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
35975
36110
 
35976
36111
  if(opts._fillgradient) {
35977
- Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
36112
+ Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
35978
36113
  } else {
35979
36114
  // tinycolor can't handle exponents and
35980
36115
  // at this scale, removing it makes no difference.
@@ -35990,17 +36125,23 @@ function drawColorBar(g, opts, gd) {
35990
36125
  .classed(cn.cbline, true);
35991
36126
  lines.exit().remove();
35992
36127
  lines.each(function(d) {
36128
+ var a = uPx;
36129
+ var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
36130
+
35993
36131
  d3.select(this)
35994
- .attr('d', 'M' + xLeft + ',' +
35995
- (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx)
36132
+ .attr('d', 'M' +
36133
+ (isVertical ? a + ',' + b : b + ',' + a) +
36134
+ (isVertical ? 'h' : 'v') +
36135
+ thickPx
36136
+ )
35996
36137
  .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
35997
36138
  });
35998
36139
 
35999
36140
  // force full redraw of labels and ticks
36000
36141
  axLayer.selectAll('g.' + ax._id + 'tick,path').remove();
36001
36142
 
36002
- var shift = xLeft + thickPx +
36003
- (opts.outlinewidth || 0) / 2 - (opts.ticks === 'outside' ? 1 : 0);
36143
+ var shift = uPx + thickPx +
36144
+ (outlinewidth || 0) / 2 - (opts.ticks === 'outside' ? 1 : 0);
36004
36145
 
36005
36146
  var vals = Axes.calcTicks(ax);
36006
36147
  var tickSign = Axes.getTickSigns(ax)[2];
@@ -36025,83 +36166,211 @@ function drawColorBar(g, opts, gd) {
36025
36166
  // TODO: why are we redrawing multiple times now with this?
36026
36167
  // I guess autoMargin doesn't like being post-promise?
36027
36168
  function positionCB() {
36028
- var innerWidth = thickPx + opts.outlinewidth / 2;
36029
- if(ax.ticklabelposition.indexOf('inside') === -1) {
36030
- innerWidth += Drawing.bBox(axLayer.node()).width;
36169
+ var bb;
36170
+ var innerThickness = thickPx + outlinewidth / 2;
36171
+ if(ticklabelposition.indexOf('inside') === -1) {
36172
+ bb = Drawing.bBox(axLayer.node());
36173
+ innerThickness += isVertical ? bb.width : bb.height;
36031
36174
  }
36032
36175
 
36033
36176
  titleEl = titleCont.select('text');
36034
36177
 
36178
+ var titleWidth = 0;
36179
+
36180
+ var topSideVertical = isVertical && titleSide === 'top';
36181
+ var rightSideHorizontal = !isVertical && titleSide === 'right';
36182
+
36183
+ var moveY = 0;
36184
+
36035
36185
  if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
36186
+ var _titleHeight;
36187
+
36036
36188
  var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
36037
- var titleWidth;
36038
- if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) {
36039
- titleWidth = Drawing.bBox(mathJaxNode).width;
36189
+ if(mathJaxNode && (
36190
+ (isVertical && topOrBottom) ||
36191
+ (!isVertical && !topOrBottom)
36192
+ )) {
36193
+ bb = Drawing.bBox(mathJaxNode);
36194
+ titleWidth = bb.width;
36195
+ _titleHeight = bb.height;
36040
36196
  } else {
36041
36197
  // note: the formula below works for all title sides,
36042
36198
  // (except for top/bottom mathjax, above)
36043
36199
  // but the weird gs.l is because the titleunshift
36044
36200
  // transform gets removed by Drawing.bBox
36045
- titleWidth = Drawing.bBox(titleCont.node()).right - xLeft - gs.l;
36201
+ bb = Drawing.bBox(titleCont.node());
36202
+ titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
36203
+ _titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
36204
+
36205
+ if(
36206
+ !isVertical && titleSide === 'top'
36207
+ ) {
36208
+ innerThickness += bb.height;
36209
+ moveY = bb.height;
36210
+ }
36046
36211
  }
36047
- innerWidth = Math.max(innerWidth, titleWidth);
36212
+
36213
+ if(rightSideHorizontal) {
36214
+ titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
36215
+
36216
+ titleWidth *= 2;
36217
+ }
36218
+
36219
+ innerThickness = Math.max(innerThickness,
36220
+ isVertical ? titleWidth : _titleHeight
36221
+ );
36048
36222
  }
36049
36223
 
36050
- var outerwidth = 2 * opts.xpad + innerWidth + opts.borderwidth + opts.outlinewidth / 2;
36051
- var outerheight = yBottomPx - yTopPx;
36224
+ var outerThickness = (isVertical ?
36225
+ xpad :
36226
+ ypad
36227
+ ) * 2 + innerThickness + borderwidth + outlinewidth / 2;
36052
36228
 
36053
- g.select('.' + cn.cbbg).attr({
36054
- x: xLeft - opts.xpad - (opts.borderwidth + opts.outlinewidth) / 2,
36055
- y: yTopPx - yExtraPx,
36056
- width: Math.max(outerwidth, 2),
36057
- height: Math.max(outerheight + 2 * yExtraPx, 2)
36058
- })
36059
- .call(Color.fill, opts.bgcolor)
36060
- .call(Color.stroke, opts.bordercolor)
36061
- .style('stroke-width', opts.borderwidth);
36229
+ var hColorbarMoveTitle = 0;
36230
+ if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
36231
+ hColorbarMoveTitle = outerThickness / 2;
36062
36232
 
36063
- g.selectAll('.' + cn.cboutline).attr({
36064
- x: xLeft,
36065
- y: yTopPx + opts.ypad + (titleSide === 'top' ? titleHeight : 0),
36066
- width: Math.max(thickPx, 2),
36067
- height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2)
36068
- })
36233
+ outerThickness += hColorbarMoveTitle;
36234
+ moveY += hColorbarMoveTitle;
36235
+ }
36236
+ fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
36237
+ fullLayout._hColorbarMoveCBTitle = moveY;
36238
+
36239
+ var extraW = borderwidth + outlinewidth;
36240
+
36241
+ g.select('.' + cn.cbbg)
36242
+ .attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
36243
+ .attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
36244
+ .attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
36245
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
36246
+ .call(Color.fill, bgcolor)
36247
+ .call(Color.stroke, opts.bordercolor)
36248
+ .style('stroke-width', borderwidth);
36249
+
36250
+ var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
36251
+
36252
+ g.selectAll('.' + cn.cboutline)
36253
+ .attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
36254
+ .attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
36255
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
36256
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
36257
+ 2 * ypad + titleHeight :
36258
+ 2 * xpad + moveX
36259
+ ), 2))
36069
36260
  .call(Color.stroke, opts.outlinecolor)
36070
36261
  .style({
36071
36262
  fill: 'none',
36072
- 'stroke-width': opts.outlinewidth
36263
+ 'stroke-width': outlinewidth
36073
36264
  });
36074
36265
 
36075
- // fix positioning for xanchor!='left'
36076
- var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) * outerwidth;
36077
- g.attr('transform', strTranslate(gs.l - xoffset, gs.t));
36266
+ g.attr('transform', strTranslate(
36267
+ gs.l - (isVertical ? xRatio * outerThickness : 0),
36268
+ gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
36269
+ ));
36270
+
36271
+ if(!isVertical && (
36272
+ borderwidth || (
36273
+ tinycolor(bgcolor).getAlpha() &&
36274
+ !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
36275
+ )
36276
+ )) {
36277
+ // for horizontal colorbars when there is a border line or having different background color
36278
+ // hide/adjust x positioning for the first/last tick labels if they go outside the border
36279
+ var tickLabels = axLayer.selectAll('text');
36280
+ var numTicks = tickLabels[0].length;
36281
+
36282
+ var border = g.select('.' + cn.cbbg).node();
36283
+ var oBb = Drawing.bBox(border);
36284
+ var oTr = Drawing.getTranslate(g);
36285
+
36286
+ var TEXTPAD = 2;
36287
+
36288
+ tickLabels.each(function(d, i) {
36289
+ var first = 0;
36290
+ var last = numTicks - 1;
36291
+ if(i === first || i === last) {
36292
+ var iBb = Drawing.bBox(this);
36293
+ var iTr = Drawing.getTranslate(this);
36294
+ var deltaX;
36295
+
36296
+ if(i === last) {
36297
+ var iRight = iBb.right + iTr.x;
36298
+ var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
36299
+
36300
+ deltaX = oRight - iRight;
36301
+ if(deltaX > 0) deltaX = 0;
36302
+ } else if(i === first) {
36303
+ var iLeft = iBb.left + iTr.x;
36304
+ var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
36305
+
36306
+ deltaX = oLeft - iLeft;
36307
+ if(deltaX < 0) deltaX = 0;
36308
+ }
36309
+
36310
+ if(deltaX) {
36311
+ if(numTicks < 3) { // adjust position
36312
+ this.setAttribute('transform',
36313
+ 'translate(' + deltaX + ',0) ' +
36314
+ this.getAttribute('transform')
36315
+ );
36316
+ } else { // hide
36317
+ this.setAttribute('visibility', 'hidden');
36318
+ }
36319
+ }
36320
+ }
36321
+ });
36322
+ }
36078
36323
 
36079
36324
  // auto margin adjustment
36080
36325
  var marginOpts = {};
36081
- var tFrac = FROM_TL[opts.yanchor];
36082
- var bFrac = FROM_BR[opts.yanchor];
36083
- if(opts.lenmode === 'pixels') {
36084
- marginOpts.y = opts.y;
36085
- marginOpts.t = outerheight * tFrac;
36086
- marginOpts.b = outerheight * bFrac;
36087
- } else {
36088
- marginOpts.t = marginOpts.b = 0;
36089
- marginOpts.yt = opts.y + opts.len * tFrac;
36090
- marginOpts.yb = opts.y - opts.len * bFrac;
36091
- }
36326
+ var lFrac = FROM_TL[xanchor];
36327
+ var rFrac = FROM_BR[xanchor];
36328
+ var tFrac = FROM_TL[yanchor];
36329
+ var bFrac = FROM_BR[yanchor];
36092
36330
 
36093
- var lFrac = FROM_TL[opts.xanchor];
36094
- var rFrac = FROM_BR[opts.xanchor];
36095
- if(opts.thicknessmode === 'pixels') {
36096
- marginOpts.x = opts.x;
36097
- marginOpts.l = outerwidth * lFrac;
36098
- marginOpts.r = outerwidth * rFrac;
36099
- } else {
36100
- var extraThickness = outerwidth - thickPx;
36101
- marginOpts.l = extraThickness * lFrac;
36102
- marginOpts.r = extraThickness * rFrac;
36103
- marginOpts.xl = opts.x - opts.thickness * lFrac;
36104
- marginOpts.xr = opts.x + opts.thickness * rFrac;
36331
+ var extraThickness = outerThickness - thickPx;
36332
+ if(isVertical) {
36333
+ if(lenmode === 'pixels') {
36334
+ marginOpts.y = optsY;
36335
+ marginOpts.t = lenPx * tFrac;
36336
+ marginOpts.b = lenPx * bFrac;
36337
+ } else {
36338
+ marginOpts.t = marginOpts.b = 0;
36339
+ marginOpts.yt = optsY + len * tFrac;
36340
+ marginOpts.yb = optsY - len * bFrac;
36341
+ }
36342
+
36343
+ if(thicknessmode === 'pixels') {
36344
+ marginOpts.x = optsX;
36345
+ marginOpts.l = outerThickness * lFrac;
36346
+ marginOpts.r = outerThickness * rFrac;
36347
+ } else {
36348
+ marginOpts.l = extraThickness * lFrac;
36349
+ marginOpts.r = extraThickness * rFrac;
36350
+ marginOpts.xl = optsX - thickness * lFrac;
36351
+ marginOpts.xr = optsX + thickness * rFrac;
36352
+ }
36353
+ } else { // horizontal colorbars
36354
+ if(lenmode === 'pixels') {
36355
+ marginOpts.x = optsX;
36356
+ marginOpts.l = lenPx * lFrac;
36357
+ marginOpts.r = lenPx * rFrac;
36358
+ } else {
36359
+ marginOpts.l = marginOpts.r = 0;
36360
+ marginOpts.xl = optsX + len * lFrac;
36361
+ marginOpts.xr = optsX - len * rFrac;
36362
+ }
36363
+
36364
+ if(thicknessmode === 'pixels') {
36365
+ marginOpts.y = 1 - optsY;
36366
+ marginOpts.t = outerThickness * tFrac;
36367
+ marginOpts.b = outerThickness * bFrac;
36368
+ } else {
36369
+ marginOpts.t = extraThickness * tFrac;
36370
+ marginOpts.b = extraThickness * bFrac;
36371
+ marginOpts.yt = optsY - thickness * tFrac;
36372
+ marginOpts.yb = optsY + thickness * bFrac;
36373
+ }
36105
36374
  }
36106
36375
 
36107
36376
  Plots.autoMargin(gd, opts._id, marginOpts);
@@ -36118,6 +36387,7 @@ function drawColorBar(g, opts, gd) {
36118
36387
  }
36119
36388
 
36120
36389
  function makeEditable(g, opts, gd) {
36390
+ var isVertical = opts.orientation === 'v';
36121
36391
  var fullLayout = gd._fullLayout;
36122
36392
  var gs = fullLayout._size;
36123
36393
  var t0, xf, yf;
@@ -36132,9 +36402,13 @@ function makeEditable(g, opts, gd) {
36132
36402
  moveFn: function(dx, dy) {
36133
36403
  g.attr('transform', t0 + strTranslate(dx, dy));
36134
36404
 
36135
- xf = dragElement.align(opts._xLeftFrac + (dx / gs.w), opts._thickFrac,
36405
+ xf = dragElement.align(
36406
+ (isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
36407
+ isVertical ? opts._thickFrac : opts._lenFrac,
36136
36408
  0, 1, opts.xanchor);
36137
- yf = dragElement.align(opts._yBottomFrac - (dy / gs.h), opts._lenFrac,
36409
+ yf = dragElement.align(
36410
+ (isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
36411
+ isVertical ? opts._lenFrac : opts._thickFrac,
36138
36412
  0, 1, opts.yanchor);
36139
36413
 
36140
36414
  var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
@@ -36211,6 +36485,8 @@ function calcLevels(gd, opts, zrange) {
36211
36485
  function mockColorBarAxis(gd, opts, zrange) {
36212
36486
  var fullLayout = gd._fullLayout;
36213
36487
 
36488
+ var isVertical = opts.orientation === 'v';
36489
+
36214
36490
  var cbAxisIn = {
36215
36491
  type: 'linear',
36216
36492
  range: zrange,
@@ -36241,17 +36517,19 @@ function mockColorBarAxis(gd, opts, zrange) {
36241
36517
  title: opts.title,
36242
36518
  showline: true,
36243
36519
  anchor: 'free',
36244
- side: 'right',
36520
+ side: isVertical ? 'right' : 'bottom',
36245
36521
  position: 1
36246
36522
  };
36247
36523
 
36524
+ var letter = isVertical ? 'y' : 'x';
36525
+
36248
36526
  var cbAxisOut = {
36249
36527
  type: 'linear',
36250
- _id: 'y' + opts._id
36528
+ _id: letter + opts._id
36251
36529
  };
36252
36530
 
36253
36531
  var axisOptions = {
36254
- letter: 'y',
36532
+ letter: letter,
36255
36533
  font: fullLayout.font,
36256
36534
  noHover: true,
36257
36535
  noTickson: true,
@@ -38713,7 +38991,7 @@ var TEXTOFFSETSIGN = {
38713
38991
  start: 1, end: -1, middle: 0, bottom: 1, top: -1
38714
38992
  };
38715
38993
 
38716
- function textPointPosition(s, textPosition, fontSize, markerRadius) {
38994
+ function textPointPosition(s, textPosition, fontSize, markerRadius, dontTouchParent) {
38717
38995
  var group = d3.select(s.node().parentNode);
38718
38996
 
38719
38997
  var v = textPosition.indexOf('top') !== -1 ?
@@ -38735,7 +39013,9 @@ function textPointPosition(s, textPosition, fontSize, markerRadius) {
38735
39013
 
38736
39014
  // fix the overall text group position
38737
39015
  s.attr('text-anchor', h);
38738
- group.attr('transform', strTranslate(dx, dy));
39016
+ if(!dontTouchParent) {
39017
+ group.attr('transform', strTranslate(dx, dy));
39018
+ }
38739
39019
  }
38740
39020
 
38741
39021
  function extracTextFontSize(d, trace) {
@@ -38805,7 +39085,8 @@ drawing.selectedTextStyle = function(s, trace) {
38805
39085
  var fontSize = extracTextFontSize(d, trace);
38806
39086
 
38807
39087
  Color.fill(tx, tc);
38808
- textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc);
39088
+ var dontTouchParent = Registry.traceIs(trace, 'bar-like');
39089
+ textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc, dontTouchParent);
38809
39090
  });
38810
39091
  };
38811
39092
 
@@ -40836,11 +41117,13 @@ var cartesianScatterPoints = {
40836
41117
  // The actual rendering is done by private function _hover.
40837
41118
  exports.hover = function hover(gd, evt, subplot, noHoverEvent) {
40838
41119
  gd = Lib.getGraphDiv(gd);
40839
-
41120
+ // The 'target' property changes when bubbling out of Shadow DOM.
41121
+ // Throttling can delay reading the target, so we save the current value.
41122
+ var eventTarget = evt.target;
40840
41123
  Lib.throttle(
40841
41124
  gd._fullLayout._uid + constants.HOVERID,
40842
41125
  constants.HOVERMINTIME,
40843
- function() { _hover(gd, evt, subplot, noHoverEvent); }
41126
+ function() { _hover(gd, evt, subplot, noHoverEvent, eventTarget); }
40844
41127
  );
40845
41128
  };
40846
41129
 
@@ -41005,7 +41288,7 @@ exports.loneHover = function loneHover(hoverItems, opts) {
41005
41288
  };
41006
41289
 
41007
41290
  // The actual implementation is here:
41008
- function _hover(gd, evt, subplot, noHoverEvent) {
41291
+ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
41009
41292
  if(!subplot) subplot = 'xy';
41010
41293
 
41011
41294
  // if the user passed in an array of subplots,
@@ -41124,7 +41407,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
41124
41407
  // [x|y]px: the pixels (from top left) of the mouse location
41125
41408
  // on the currently selected plot area
41126
41409
  // add pointerX|Y property for drawing the spikes in spikesnap 'cursor' situation
41127
- var hasUserCalledHover = !evt.target;
41410
+ var hasUserCalledHover = !eventTarget;
41128
41411
  var xpx, ypx;
41129
41412
 
41130
41413
  if(hasUserCalledHover) {
@@ -41141,13 +41424,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
41141
41424
  return;
41142
41425
  }
41143
41426
 
41144
- // Discover event target, traversing open shadow roots.
41145
- var target = evt.composedPath && evt.composedPath()[0];
41146
- if(!target) {
41147
- // Fallback for browsers not supporting composedPath
41148
- target = evt.target;
41149
- }
41150
- var dbb = target.getBoundingClientRect();
41427
+ var dbb = eventTarget.getBoundingClientRect();
41151
41428
 
41152
41429
  xpx = evt.clientX - dbb.left;
41153
41430
  ypx = evt.clientY - dbb.top;
@@ -41595,15 +41872,15 @@ function _hover(gd, evt, subplot, noHoverEvent) {
41595
41872
  if(!helpers.isUnifiedHover(hovermode)) {
41596
41873
  hoverAvoidOverlaps(hoverLabels, rotateLabels ? 'xa' : 'ya', fullLayout);
41597
41874
  alignHoverText(hoverLabels, rotateLabels, fullLayout._invScaleX, fullLayout._invScaleY);
41598
- } // TODO: tagName hack is needed to appease geo.js's hack of using evt.target=true
41875
+ } // TODO: tagName hack is needed to appease geo.js's hack of using eventTarget=true
41599
41876
  // we should improve the "fx" API so other plots can use it without these hack.
41600
- if(evt.target && evt.target.tagName) {
41877
+ if(eventTarget && eventTarget.tagName) {
41601
41878
  var hasClickToShow = Registry.getComponentMethod('annotations', 'hasClickToShow')(gd, newhoverdata);
41602
- overrideCursor(d3.select(evt.target), hasClickToShow ? 'pointer' : '');
41879
+ overrideCursor(d3.select(eventTarget), hasClickToShow ? 'pointer' : '');
41603
41880
  }
41604
41881
 
41605
41882
  // don't emit events if called manually
41606
- if(!evt.target || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
41883
+ if(!eventTarget || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
41607
41884
 
41608
41885
  if(oldhoverdata) {
41609
41886
  gd.emit('plotly_unhover', {
@@ -41865,7 +42142,9 @@ function createHoverText(hoverData, opts) {
41865
42142
  orientation: 'v'
41866
42143
  }
41867
42144
  };
41868
- var mockLayoutOut = {};
42145
+ var mockLayoutOut = {
42146
+ font: font
42147
+ };
41869
42148
  legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
41870
42149
  var mockLegend = mockLayoutOut.legend;
41871
42150
 
@@ -41906,7 +42185,8 @@ function createHoverText(hoverData, opts) {
41906
42185
 
41907
42186
  // Draw unified hover label
41908
42187
  mockLegend._inHover = true;
41909
- mockLegend._groupTitleFont = font;
42188
+ mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
42189
+
41910
42190
  legendDraw(gd, mockLegend);
41911
42191
 
41912
42192
  // Position the hover
@@ -42908,9 +43188,11 @@ var isUnifiedHover = _dereq_('./helpers').isUnifiedHover;
42908
43188
  module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
42909
43189
  opts = opts || {};
42910
43190
 
43191
+ var hasLegend = contOut.legend;
43192
+
42911
43193
  function inheritFontAttr(attr) {
42912
43194
  if(!opts.font[attr]) {
42913
- opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
43195
+ opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
42914
43196
  }
42915
43197
  }
42916
43198
 
@@ -42921,7 +43203,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
42921
43203
  inheritFontAttr('family');
42922
43204
  inheritFontAttr('color');
42923
43205
 
42924
- if(contOut.legend) {
43206
+ if(hasLegend) {
42925
43207
  if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
42926
43208
  if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
42927
43209
  } else {
@@ -43030,11 +43312,13 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
43030
43312
 
43031
43313
  var constants = _dereq_('./constants');
43032
43314
 
43033
- var fontAttrs = _dereq_('../../plots/font_attributes')({
43315
+ var fontAttrs = _dereq_('../../plots/font_attributes');
43316
+
43317
+ var font = fontAttrs({
43034
43318
  editType: 'none',
43035
43319
  });
43036
- fontAttrs.family.dflt = constants.HOVERFONT;
43037
- fontAttrs.size.dflt = constants.HOVERFONTSIZE;
43320
+ font.family.dflt = constants.HOVERFONT;
43321
+ font.size.dflt = constants.HOVERFONTSIZE;
43038
43322
 
43039
43323
  module.exports = {
43040
43324
  clickmode: {
@@ -43090,7 +43374,10 @@ module.exports = {
43090
43374
  valType: 'color',
43091
43375
  editType: 'none',
43092
43376
  },
43093
- font: fontAttrs,
43377
+ font: font,
43378
+ grouptitlefont: fontAttrs({
43379
+ editType: 'none',
43380
+ }),
43094
43381
  align: {
43095
43382
  valType: 'enumerated',
43096
43383
  values: ['left', 'right', 'auto'],
@@ -43103,6 +43390,7 @@ module.exports = {
43103
43390
  dflt: 15,
43104
43391
  editType: 'none',
43105
43392
  },
43393
+
43106
43394
  editType: 'none'
43107
43395
  },
43108
43396
  selectdirection: {
@@ -43150,6 +43438,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
43150
43438
  }
43151
43439
 
43152
43440
  handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
43441
+
43442
+ Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
43153
43443
  };
43154
43444
 
43155
43445
  },{"../../lib":248,"./hoverlabel_defaults":154,"./hovermode_defaults":155,"./layout_attributes":157}],159:[function(_dereq_,module,exports){
@@ -44033,6 +44323,9 @@ module.exports = {
44033
44323
  font: fontAttrs({
44034
44324
  editType: 'legend',
44035
44325
  }),
44326
+ grouptitlefont: fontAttrs({
44327
+ editType: 'legend',
44328
+ }),
44036
44329
  orientation: {
44037
44330
  valType: 'enumerated',
44038
44331
  values: ['v', 'h'],
@@ -44156,6 +44449,7 @@ var Registry = _dereq_('../../registry');
44156
44449
  var Lib = _dereq_('../../lib');
44157
44450
  var Template = _dereq_('../../plot_api/plot_template');
44158
44451
 
44452
+ var plotsAttrs = _dereq_('../../plots/attributes');
44159
44453
  var attributes = _dereq_('./attributes');
44160
44454
  var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes');
44161
44455
  var helpers = _dereq_('./helpers');
@@ -44163,13 +44457,30 @@ var helpers = _dereq_('./helpers');
44163
44457
 
44164
44458
  module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
44165
44459
  var containerIn = layoutIn.legend || {};
44460
+ var containerOut = Template.newContainer(layoutOut, 'legend');
44461
+
44462
+ function coerce(attr, dflt) {
44463
+ return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
44464
+ }
44465
+
44466
+ var trace;
44467
+ var traceCoerce = function(attr, dflt) {
44468
+ var traceIn = trace._input;
44469
+ var traceOut = trace;
44470
+ return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
44471
+ };
44472
+
44473
+ var globalFont = layoutOut.font || {};
44474
+ var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
44475
+ size: Math.round(globalFont.size * 1.1)
44476
+ }));
44166
44477
 
44167
44478
  var legendTraceCount = 0;
44168
44479
  var legendReallyHasATrace = false;
44169
44480
  var defaultOrder = 'normal';
44170
44481
 
44171
44482
  for(var i = 0; i < fullData.length; i++) {
44172
- var trace = fullData[i];
44483
+ trace = fullData[i];
44173
44484
 
44174
44485
  if(!trace.visible) continue;
44175
44486
 
@@ -44196,6 +44507,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
44196
44507
  legendTraceCount++;
44197
44508
  }
44198
44509
  }
44510
+
44511
+ Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
44199
44512
  }
44200
44513
 
44201
44514
  if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -44214,13 +44527,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
44214
44527
  basePlotLayoutAttributes, 'showlegend',
44215
44528
  legendReallyHasATrace && legendTraceCount > 1);
44216
44529
 
44217
- if(showLegend === false && !containerIn.uirevision) return;
44218
-
44219
- var containerOut = Template.newContainer(layoutOut, 'legend');
44530
+ // delete legend
44531
+ if(showLegend === false) layoutOut.legend = undefined;
44220
44532
 
44221
- function coerce(attr, dflt) {
44222
- return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
44223
- }
44533
+ if(showLegend === false && !containerIn.uirevision) return;
44224
44534
 
44225
44535
  coerce('uirevision', layoutOut.uirevision);
44226
44536
 
@@ -44282,7 +44592,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
44282
44592
  }
44283
44593
  };
44284
44594
 
44285
- },{"../../lib":248,"../../plot_api/plot_template":285,"../../plots/layout_attributes":337,"../../registry":342,"./attributes":166,"./helpers":172}],169:[function(_dereq_,module,exports){
44595
+ },{"../../lib":248,"../../plot_api/plot_template":285,"../../plots/attributes":292,"../../plots/layout_attributes":337,"../../registry":342,"./attributes":166,"./helpers":172}],169:[function(_dereq_,module,exports){
44286
44596
  'use strict';
44287
44597
 
44288
44598
  var d3 = _dereq_('@plotly/d3');
@@ -52734,8 +53044,10 @@ function draw(gd, titleClass, options) {
52734
53044
 
52735
53045
  var elShouldExist = txt || editable;
52736
53046
 
53047
+ var hColorbarMoveTitle;
52737
53048
  if(!group) {
52738
53049
  group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass);
53050
+ hColorbarMoveTitle = fullLayout._hColorbarMoveTitle;
52739
53051
  }
52740
53052
 
52741
53053
  var el = group.selectAll('text')
@@ -52759,13 +53071,17 @@ function draw(gd, titleClass, options) {
52759
53071
  function drawTitle(titleEl) {
52760
53072
  var transformVal;
52761
53073
 
53074
+ if(!transform && hColorbarMoveTitle) {
53075
+ transform = {};
53076
+ }
53077
+
52762
53078
  if(transform) {
52763
53079
  transformVal = '';
52764
53080
  if(transform.rotate) {
52765
53081
  transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')';
52766
53082
  }
52767
- if(transform.offset) {
52768
- transformVal += strTranslate(0, transform.offset);
53083
+ if(transform.offset || hColorbarMoveTitle) {
53084
+ transformVal += strTranslate(0, (transform.offset || 0) - (hColorbarMoveTitle || 0));
52769
53085
  }
52770
53086
  } else {
52771
53087
  transformVal = null;
@@ -64734,7 +65050,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
64734
65050
  if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
64735
65051
  (typeof value === 'string' || typeof value === 'number')) {
64736
65052
  replace(key, key.replace('title', 'title.text'));
64737
- } else if(key.indexOf('titlefont') > -1) {
65053
+ } else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
64738
65054
  replace(key, key.replace('titlefont', 'title.font'));
64739
65055
  } else if(key.indexOf('titleposition') > -1) {
64740
65056
  replace(key, key.replace('titleposition', 'title.position'));
@@ -65411,7 +65727,8 @@ function findUIPattern(key, patternSpecs) {
65411
65727
  var spec = patternSpecs[i];
65412
65728
  var match = key.match(spec.pattern);
65413
65729
  if(match) {
65414
- return {head: match[1], attr: spec.attr};
65730
+ var head = match[1] || '';
65731
+ return {head: head, tail: key.substr(head.length + 1), attr: spec.attr};
65415
65732
  }
65416
65733
  }
65417
65734
  }
@@ -65463,26 +65780,54 @@ function valsMatch(v1, v2) {
65463
65780
 
65464
65781
  function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
65465
65782
  var layoutPreGUI = oldFullLayout._preGUI;
65466
- var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal;
65783
+ var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal, head, tail;
65467
65784
  var bothInheritAutorange = [];
65785
+ var newAutorangeIn = {};
65468
65786
  var newRangeAccepted = {};
65469
65787
  for(key in layoutPreGUI) {
65470
65788
  match = findUIPattern(key, layoutUIControlPatterns);
65471
65789
  if(match) {
65472
- revAttr = match.attr || (match.head + '.uirevision');
65790
+ head = match.head;
65791
+ tail = match.tail;
65792
+ revAttr = match.attr || (head + '.uirevision');
65473
65793
  oldRev = nestedProperty(oldFullLayout, revAttr).get();
65474
65794
  newRev = oldRev && getNewRev(revAttr, layout);
65795
+
65475
65796
  if(newRev && (newRev === oldRev)) {
65476
65797
  preGUIVal = layoutPreGUI[key];
65477
65798
  if(preGUIVal === null) preGUIVal = undefined;
65478
65799
  newNP = nestedProperty(layout, key);
65479
65800
  newVal = newNP.get();
65801
+
65480
65802
  if(valsMatch(newVal, preGUIVal)) {
65481
- if(newVal === undefined && key.substr(key.length - 9) === 'autorange') {
65482
- bothInheritAutorange.push(key.substr(0, key.length - 10));
65803
+ if(newVal === undefined && tail === 'autorange') {
65804
+ bothInheritAutorange.push(head);
65483
65805
  }
65484
65806
  newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
65485
65807
  continue;
65808
+ } else if(tail === 'autorange' || tail.substr(0, 6) === 'range[') {
65809
+ // Special case for (auto)range since we push it back into the layout
65810
+ // so all null should be treated equivalently to autorange: true with any range
65811
+ var pre0 = layoutPreGUI[head + '.range[0]'];
65812
+ var pre1 = layoutPreGUI[head + '.range[1]'];
65813
+ var preAuto = layoutPreGUI[head + '.autorange'];
65814
+ if(preAuto || (preAuto === null && pre0 === null && pre1 === null)) {
65815
+ // Only read the input layout once and stash the result,
65816
+ // so we get it before we start modifying it
65817
+ if(!(head in newAutorangeIn)) {
65818
+ var newContainer = nestedProperty(layout, head).get();
65819
+ newAutorangeIn[head] = newContainer && (
65820
+ newContainer.autorange ||
65821
+ (newContainer.autorange !== false && (
65822
+ !newContainer.range || newContainer.range.length !== 2)
65823
+ )
65824
+ );
65825
+ }
65826
+ if(newAutorangeIn[head]) {
65827
+ newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
65828
+ continue;
65829
+ }
65830
+ }
65486
65831
  }
65487
65832
  }
65488
65833
  } else {
@@ -65493,12 +65838,12 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
65493
65838
  // so remove it from _preGUI for next time.
65494
65839
  delete layoutPreGUI[key];
65495
65840
 
65496
- if(key.substr(key.length - 8, 6) === 'range[') {
65497
- newRangeAccepted[key.substr(0, key.length - 9)] = 1;
65841
+ if(match && match.tail.substr(0, 6) === 'range[') {
65842
+ newRangeAccepted[match.head] = 1;
65498
65843
  }
65499
65844
  }
65500
65845
 
65501
- // Special logic for `autorange`, since it interacts with `range`:
65846
+ // More special logic for `autorange`, since it interacts with `range`:
65502
65847
  // If the new figure's matching `range` was kept, and `autorange`
65503
65848
  // wasn't supplied explicitly in either the original or the new figure,
65504
65849
  // we shouldn't alter that - but we may just have done that, so fix it.
@@ -82573,6 +82918,9 @@ module.exports = function(opts) {
82573
82918
  // TODO - that's uber hacky... better solution?
82574
82919
  };
82575
82920
 
82921
+ if(opts.autoSize) attrs.size.dflt = 'auto';
82922
+ if(opts.autoColor) attrs.color.dflt = 'auto';
82923
+
82576
82924
  if(opts.arrayOk) {
82577
82925
  attrs.family.arrayOk = true;
82578
82926
  attrs.size.arrayOk = true;
@@ -85001,6 +85349,7 @@ module.exports = {
85001
85349
  valType: 'boolean',
85002
85350
  editType: 'legend',
85003
85351
  },
85352
+
85004
85353
  colorway: {
85005
85354
  valType: 'colorlist',
85006
85355
  dflt: colorAttrs.defaults,
@@ -86413,13 +86762,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
86413
86762
  );
86414
86763
 
86415
86764
  coerce('legendgroup');
86416
- var titleText = coerce('legendgrouptitle.text');
86417
- if(titleText) {
86418
- Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
86419
- size: Math.round(layout.font.size * 1.1) // default to larger font size
86420
- }));
86421
- }
86422
-
86765
+ coerce('legendgrouptitle.text');
86423
86766
  coerce('legendrank');
86424
86767
 
86425
86768
  traceOut._dfltShowLegend = true;
@@ -86567,16 +86910,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
86567
86910
 
86568
86911
  coerce('autotypenumbers');
86569
86912
 
86570
- var globalFont = Lib.coerceFont(coerce, 'font');
86571
-
86572
- coerce('title.text', layoutOut._dfltTitle.plot);
86913
+ var font = Lib.coerceFont(coerce, 'font');
86914
+ var fontSize = font.size;
86573
86915
 
86574
- Lib.coerceFont(coerce, 'title.font', {
86575
- family: globalFont.family,
86576
- size: Math.round(globalFont.size * 1.4),
86577
- color: globalFont.color
86578
- });
86916
+ Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
86917
+ size: Math.round(fontSize * 1.4)
86918
+ }));
86579
86919
 
86920
+ coerce('title.text', layoutOut._dfltTitle.plot);
86580
86921
  coerce('title.xref');
86581
86922
  coerce('title.yref');
86582
86923
  coerce('title.x');
@@ -95037,7 +95378,7 @@ function getSortFunc(opts, d2c) {
95037
95378
  'use strict';
95038
95379
 
95039
95380
  // package version injected by `npm run preprocess`
95040
- exports.version = '2.6.2';
95381
+ exports.version = '2.8.0';
95041
95382
 
95042
95383
  },{}]},{},[8])(8)
95043
95384
  });