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 (basic) v2.6.4
2
+ * plotly.js (basic) v2.8.2
3
3
  * Copyright 2012-2021, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -21564,13 +21564,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
21564
21564
 
21565
21565
 
21566
21566
  module.exports = overrideAll({
21567
- // TODO: only right is supported currently
21568
- // orient: {
21569
- // valType: 'enumerated',
21570
- // values: ['left', 'right', 'top', 'bottom'],
21571
- // dflt: 'right',
21572
- //
21573
- // },
21567
+ orientation: {
21568
+ valType: 'enumerated',
21569
+ values: ['h', 'v'],
21570
+ dflt: 'v',
21571
+ },
21574
21572
  thicknessmode: {
21575
21573
  valType: 'enumerated',
21576
21574
  values: ['fraction', 'pixels'],
@@ -21593,14 +21591,12 @@ module.exports = overrideAll({
21593
21591
  },
21594
21592
  x: {
21595
21593
  valType: 'number',
21596
- dflt: 1.02,
21597
21594
  min: -2,
21598
21595
  max: 3,
21599
21596
  },
21600
21597
  xanchor: {
21601
21598
  valType: 'enumerated',
21602
21599
  values: ['left', 'center', 'right'],
21603
- dflt: 'left',
21604
21600
  },
21605
21601
  xpad: {
21606
21602
  valType: 'number',
@@ -21609,14 +21605,12 @@ module.exports = overrideAll({
21609
21605
  },
21610
21606
  y: {
21611
21607
  valType: 'number',
21612
- dflt: 0.5,
21613
21608
  min: -2,
21614
21609
  max: 3,
21615
21610
  },
21616
21611
  yanchor: {
21617
21612
  valType: 'enumerated',
21618
21613
  values: ['top', 'middle', 'bottom'],
21619
- dflt: 'middle',
21620
21614
  },
21621
21615
  ypad: {
21622
21616
  valType: 'number',
@@ -21648,15 +21642,21 @@ module.exports = overrideAll({
21648
21642
  ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
21649
21643
  ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
21650
21644
  }),
21645
+
21646
+ // ticklabelposition: not used directly, as values depend on orientation
21647
+ // left/right options are for x axes, and top/bottom options are for y axes
21651
21648
  ticklabelposition: {
21652
21649
  valType: 'enumerated',
21653
21650
  values: [
21654
21651
  'outside', 'inside',
21655
21652
  'outside top', 'inside top',
21653
+ 'outside left', 'inside left',
21654
+ 'outside right', 'inside right',
21656
21655
  'outside bottom', 'inside bottom'
21657
21656
  ],
21658
21657
  dflt: 'outside',
21659
21658
  },
21659
+
21660
21660
  ticklen: axesAttrs.ticklen,
21661
21661
  tickwidth: axesAttrs.tickwidth,
21662
21662
  tickcolor: axesAttrs.tickcolor,
@@ -21683,7 +21683,6 @@ module.exports = overrideAll({
21683
21683
  side: {
21684
21684
  valType: 'enumerated',
21685
21685
  values: ['right', 'top', 'bottom'],
21686
- dflt: 'top',
21687
21686
  }
21688
21687
  },
21689
21688
 
@@ -21742,23 +21741,30 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
21742
21741
  return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt);
21743
21742
  }
21744
21743
 
21744
+ var margin = layout.margin || {t: 0, b: 0, l: 0, r: 0};
21745
+ var w = layout.width - margin.l - margin.r;
21746
+ var h = layout.height - margin.t - margin.b;
21747
+
21748
+ var orientation = coerce('orientation');
21749
+ var isVertical = orientation === 'v';
21750
+
21745
21751
  var thicknessmode = coerce('thicknessmode');
21746
21752
  coerce('thickness', (thicknessmode === 'fraction') ?
21747
- 30 / (layout.width - layout.margin.l - layout.margin.r) :
21753
+ 30 / (isVertical ? w : h) :
21748
21754
  30
21749
21755
  );
21750
21756
 
21751
21757
  var lenmode = coerce('lenmode');
21752
21758
  coerce('len', (lenmode === 'fraction') ?
21753
21759
  1 :
21754
- layout.height - layout.margin.t - layout.margin.b
21760
+ isVertical ? h : w
21755
21761
  );
21756
21762
 
21757
- coerce('x');
21758
- coerce('xanchor');
21763
+ coerce('x', isVertical ? 1.02 : 0.5);
21764
+ coerce('xanchor', isVertical ? 'left' : 'center');
21759
21765
  coerce('xpad');
21760
- coerce('y');
21761
- coerce('yanchor');
21766
+ coerce('y', isVertical ? 0.5 : 1.02);
21767
+ coerce('yanchor', isVertical ? 'middle' : 'bottom');
21762
21768
  coerce('ypad');
21763
21769
  Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']);
21764
21770
 
@@ -21768,7 +21774,22 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
21768
21774
  coerce('borderwidth');
21769
21775
  coerce('bgcolor');
21770
21776
 
21771
- var ticklabelposition = coerce('ticklabelposition');
21777
+ var ticklabelposition = Lib.coerce(colorbarIn, colorbarOut, {
21778
+ ticklabelposition: {
21779
+ valType: 'enumerated',
21780
+ dflt: 'outside',
21781
+ values: isVertical ? [
21782
+ 'outside', 'inside',
21783
+ 'outside top', 'inside top',
21784
+ 'outside bottom', 'inside bottom'
21785
+ ] : [
21786
+ 'outside', 'inside',
21787
+ 'outside left', 'inside left',
21788
+ 'outside right', 'inside right'
21789
+ ]
21790
+ }
21791
+ }, 'ticklabelposition');
21792
+
21772
21793
  coerce('ticklabeloverflow', ticklabelposition.indexOf('inside') !== -1 ? 'hide past domain' : 'hide past div');
21773
21794
 
21774
21795
  handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear');
@@ -21790,7 +21811,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
21790
21811
  size: Lib.bigFont(tickFont.size)
21791
21812
  });
21792
21813
  Lib.coerceFont(coerce, 'title.font', dfltTitleFont);
21793
- coerce('title.side');
21814
+ coerce('title.side', isVertical ? 'top' : 'right');
21794
21815
  };
21795
21816
 
21796
21817
  },{"../../lib":232,"../../plot_api/plot_template":268,"../../plots/cartesian/prefix_suffix_defaults":298,"../../plots/cartesian/tick_label_defaults":303,"../../plots/cartesian/tick_mark_defaults":304,"../../plots/cartesian/tick_value_defaults":305,"./attributes":103}],106:[function(_dereq_,module,exports){
@@ -21963,18 +21984,20 @@ function makeColorBarData(gd) {
21963
21984
  }
21964
21985
 
21965
21986
  function drawColorBar(g, opts, gd) {
21987
+ var isVertical = opts.orientation === 'v';
21966
21988
  var len = opts.len;
21967
21989
  var lenmode = opts.lenmode;
21968
21990
  var thickness = opts.thickness;
21969
21991
  var thicknessmode = opts.thicknessmode;
21970
21992
  var outlinewidth = opts.outlinewidth;
21971
21993
  var borderwidth = opts.borderwidth;
21994
+ var bgcolor = opts.bgcolor;
21972
21995
  var xanchor = opts.xanchor;
21973
21996
  var yanchor = opts.yanchor;
21974
21997
  var xpad = opts.xpad;
21975
21998
  var ypad = opts.ypad;
21976
21999
  var optsX = opts.x;
21977
- var optsY = opts.y;
22000
+ var optsY = isVertical ? opts.y : 1 - opts.y;
21978
22001
 
21979
22002
  var fullLayout = gd._fullLayout;
21980
22003
  var gs = fullLayout._size;
@@ -22005,23 +22028,35 @@ function drawColorBar(g, opts, gd) {
22005
22028
  // when the colorbar itself is pushing the margins.
22006
22029
  // but then the fractional size is calculated based on the
22007
22030
  // actual graph size, so that the axes will size correctly.
22008
- var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? gs.w : 1));
22009
- var thickFrac = thickPx / gs.w;
22010
- var lenPx = Math.round(len * (lenmode === 'fraction' ? gs.h : 1));
22011
- var lenFrac = lenPx / gs.h;
22012
- var xpadFrac = xpad / gs.w;
22013
- var yExtraPx = (borderwidth + outlinewidth) / 2;
22014
- var ypadFrac = ypad / gs.h;
22031
+ var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
22032
+ var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
22033
+ var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
22034
+ var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
22015
22035
 
22016
22036
  // x positioning: do it initially just for left anchor,
22017
22037
  // then fix at the end (since we don't know the width yet)
22018
- var uPx = Math.round(optsX * gs.w + xpad);
22019
- // for dragging... this is getting a little muddled...
22020
- var uFrac = optsX - thickFrac * ({center: 0.5, right: 1}[xanchor] || 0);
22038
+ var uPx = Math.round(isVertical ?
22039
+ optsX * gs.w + xpad :
22040
+ optsY * gs.h + ypad
22041
+ );
22021
22042
 
22022
- // y positioning we can do correctly from the start
22023
- var vFrac = optsY + lenFrac * (({top: -0.5, bottom: 0.5}[yanchor] || 0) - 0.5);
22024
- var vPx = Math.round(gs.h * (1 - vFrac));
22043
+ var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
22044
+ var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
22045
+
22046
+ // for dragging... this is getting a little muddled...
22047
+ var uFrac = isVertical ?
22048
+ optsX - xRatio * thickFrac :
22049
+ optsY - yRatio * thickFrac;
22050
+
22051
+ // y/x positioning (for v/h) we can do correctly from the start
22052
+ var vFrac = isVertical ?
22053
+ optsY - yRatio * lenFrac :
22054
+ optsX - xRatio * lenFrac;
22055
+
22056
+ var vPx = Math.round(isVertical ?
22057
+ gs.h * (1 - vFrac) :
22058
+ gs.w * vFrac
22059
+ );
22025
22060
 
22026
22061
  // stash a few things for makeEditable
22027
22062
  opts._lenFrac = lenFrac;
@@ -22034,12 +22069,23 @@ function drawColorBar(g, opts, gd) {
22034
22069
 
22035
22070
  // position can't go in through supplyDefaults
22036
22071
  // because that restricts it to [0,1]
22037
- ax.position = optsX + xpadFrac + thickFrac;
22072
+ ax.position = thickFrac + (isVertical ?
22073
+ optsX + xpad / gs.w :
22074
+ optsY + ypad / gs.h
22075
+ );
22076
+
22077
+ var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
22078
+
22079
+ if(isVertical && topOrBottom) {
22080
+ ax.title.side = titleSide;
22081
+ ax.titlex = optsX + xpad / gs.w;
22082
+ ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
22083
+ }
22038
22084
 
22039
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22085
+ if(!isVertical && !topOrBottom) {
22040
22086
  ax.title.side = titleSide;
22041
- ax.titlex = optsX + xpadFrac;
22042
- ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
22087
+ ax.titley = optsY + ypad / gs.h;
22088
+ ax.titlex = vFrac + xpad / gs.w; // right side
22043
22089
  }
22044
22090
 
22045
22091
  if(line.color && opts.tickmode === 'auto') {
@@ -22064,9 +22110,12 @@ function drawColorBar(g, opts, gd) {
22064
22110
 
22065
22111
  // set domain after init, because we may want to
22066
22112
  // allow it outside [0,1]
22067
- ax.domain = [
22068
- vFrac + ypadFrac,
22069
- vFrac + lenFrac - ypadFrac
22113
+ ax.domain = isVertical ? [
22114
+ vFrac + ypad / gs.h,
22115
+ vFrac + lenFrac - ypad / gs.h
22116
+ ] : [
22117
+ vFrac + xpad / gs.w,
22118
+ vFrac + lenFrac - xpad / gs.w
22070
22119
  ];
22071
22120
 
22072
22121
  ax.setScale();
@@ -22076,9 +22125,13 @@ function drawColorBar(g, opts, gd) {
22076
22125
  var titleCont = g.select('.' + cn.cbtitleunshift)
22077
22126
  .attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
22078
22127
 
22128
+ var ticklabelposition = ax.ticklabelposition;
22129
+ var titleFontSize = ax.title.font.size;
22130
+
22079
22131
  var axLayer = g.select('.' + cn.cbaxis);
22080
22132
  var titleEl;
22081
22133
  var titleHeight = 0;
22134
+ var titleWidth = 0;
22082
22135
 
22083
22136
  function drawTitle(titleClass, titleOpts) {
22084
22137
  var dfltTitleOpts = {
@@ -22103,54 +22156,98 @@ function drawColorBar(g, opts, gd) {
22103
22156
  }
22104
22157
 
22105
22158
  function drawDummyTitle() {
22106
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22107
- // draw the title so we know how much room it needs
22108
- // when we squish the axis. This one only applies to
22109
- // top or bottom titles, not right side.
22110
- var x = gs.l + (optsX + xpadFrac) * gs.w;
22111
- var fontSize = ax.title.font.size;
22112
- var y;
22159
+ // draw the title so we know how much room it needs
22160
+ // when we squish the axis.
22161
+ // On vertical colorbars this only applies to top or bottom titles, not right side.
22162
+ // On horizontal colorbars this only applies to right, etc.
22163
+
22164
+ if(
22165
+ (isVertical && topOrBottom) ||
22166
+ (!isVertical && !topOrBottom)
22167
+ ) {
22168
+ var x, y;
22113
22169
 
22114
22170
  if(titleSide === 'top') {
22115
- y = (1 - (vFrac + lenFrac - ypadFrac)) * gs.h +
22116
- gs.t + 3 + fontSize * 0.75;
22117
- } else {
22118
- y = (1 - (vFrac + ypadFrac)) * gs.h +
22119
- gs.t - 3 - fontSize * 0.25;
22171
+ x = xpad + gs.l + gs.w * optsX;
22172
+ y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
22120
22173
  }
22174
+
22175
+ if(titleSide === 'bottom') {
22176
+ x = xpad + gs.l + gs.w * optsX;
22177
+ y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
22178
+ }
22179
+
22180
+ if(titleSide === 'right') {
22181
+ y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
22182
+ x = xpad + gs.l + gs.w * vFrac;
22183
+ }
22184
+
22121
22185
  drawTitle(ax._id + 'title', {
22122
- attributes: {x: x, y: y, 'text-anchor': 'start'}
22186
+ attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
22123
22187
  });
22124
22188
  }
22125
22189
  }
22126
22190
 
22127
22191
  function drawCbTitle() {
22128
- if(['top', 'bottom'].indexOf(titleSide) === -1) {
22129
- var fontSize = ax.title.font.size;
22130
- var y = ax._offset + ax._length / 2;
22131
- var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ?
22132
- 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) :
22133
- -10 - fontSize * ((ax.showticklabels ? 0.5 : 0)));
22134
-
22135
- // the 'h' + is a hack to get around the fact that
22136
- // convertToTspans rotates any 'y...' class by 90 degrees.
22137
- // TODO: find a better way to control this.
22138
- drawTitle('h' + ax._id + 'title', {
22192
+ if(
22193
+ (isVertical && !topOrBottom) ||
22194
+ (!isVertical && topOrBottom)
22195
+ ) {
22196
+ var pos = ax.position || 0;
22197
+ var mid = ax._offset + ax._length / 2;
22198
+ var x, y;
22199
+
22200
+ if(titleSide === 'right') {
22201
+ y = mid;
22202
+ x = gs.l + gs.w * pos + 10 + titleFontSize * (
22203
+ ax.showticklabels ? 1 : 0.5
22204
+ );
22205
+ } else {
22206
+ x = mid;
22207
+
22208
+ if(titleSide === 'bottom') {
22209
+ y = gs.t + gs.h * pos + 10 + (
22210
+ ticklabelposition.indexOf('inside') === -1 ?
22211
+ ax.tickfont.size :
22212
+ 0
22213
+ ) + (
22214
+ ax.ticks !== 'intside' ?
22215
+ opts.ticklen || 0 :
22216
+ 0
22217
+ );
22218
+ }
22219
+
22220
+ if(titleSide === 'top') {
22221
+ var nlines = title.text.split('<br>').length;
22222
+ y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
22223
+ }
22224
+ }
22225
+
22226
+ drawTitle((isVertical ?
22227
+ // the 'h' + is a hack to get around the fact that
22228
+ // convertToTspans rotates any 'y...' class by 90 degrees.
22229
+ // TODO: find a better way to control this.
22230
+ 'h' :
22231
+ 'v'
22232
+ ) + ax._id + 'title', {
22139
22233
  avoid: {
22140
22234
  selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
22141
22235
  side: titleSide,
22142
- offsetLeft: gs.l,
22143
- offsetTop: 0,
22144
- maxShift: fullLayout.width
22236
+ offsetTop: isVertical ? 0 : gs.t,
22237
+ offsetLeft: isVertical ? gs.l : 0,
22238
+ maxShift: isVertical ? fullLayout.width : fullLayout.height
22145
22239
  },
22146
22240
  attributes: {x: x, y: y, 'text-anchor': 'middle'},
22147
- transform: {rotate: '-90', offset: 0}
22241
+ transform: {rotate: isVertical ? -90 : 0, offset: 0}
22148
22242
  });
22149
22243
  }
22150
22244
  }
22151
22245
 
22152
22246
  function drawAxis() {
22153
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
22247
+ if(
22248
+ (!isVertical && !topOrBottom) ||
22249
+ (isVertical && topOrBottom)
22250
+ ) {
22154
22251
  // squish the axis top to make room for the title
22155
22252
  var titleGroup = g.select('.' + cn.cbtitle);
22156
22253
  var titleText = titleGroup.select('text');
@@ -22162,39 +22259,63 @@ function drawColorBar(g, opts, gd) {
22162
22259
  if(titleText.node()) {
22163
22260
  lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
22164
22261
  }
22262
+
22263
+ var bb;
22165
22264
  if(mathJaxNode) {
22166
- titleHeight = Drawing.bBox(mathJaxNode).height;
22265
+ bb = Drawing.bBox(mathJaxNode);
22266
+ titleWidth = bb.width;
22267
+ titleHeight = bb.height;
22167
22268
  if(titleHeight > lineSize) {
22168
22269
  // not entirely sure how mathjax is doing
22169
22270
  // vertical alignment, but this seems to work.
22170
22271
  titleTrans[1] -= (titleHeight - lineSize) / 2;
22171
22272
  }
22172
22273
  } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
22173
- titleHeight = Drawing.bBox(titleText.node()).height;
22274
+ bb = Drawing.bBox(titleText.node());
22275
+ titleWidth = bb.width;
22276
+ titleHeight = bb.height;
22174
22277
  }
22175
- if(titleHeight) {
22176
- // buffer btwn colorbar and title
22177
- // TODO: configurable
22178
- titleHeight += 5;
22179
22278
 
22180
- if(titleSide === 'top') {
22181
- ax.domain[1] -= titleHeight / gs.h;
22182
- titleTrans[1] *= -1;
22183
- } else {
22184
- ax.domain[0] += titleHeight / gs.h;
22185
- var nlines = svgTextUtils.lineCount(titleText);
22186
- titleTrans[1] += (1 - nlines) * lineSize;
22279
+ if(isVertical) {
22280
+ if(titleHeight) {
22281
+ // buffer btwn colorbar and title
22282
+ // TODO: configurable
22283
+ titleHeight += 5;
22284
+
22285
+ if(titleSide === 'top') {
22286
+ ax.domain[1] -= titleHeight / gs.h;
22287
+ titleTrans[1] *= -1;
22288
+ } else {
22289
+ ax.domain[0] += titleHeight / gs.h;
22290
+ var nlines = svgTextUtils.lineCount(titleText);
22291
+ titleTrans[1] += (1 - nlines) * lineSize;
22292
+ }
22293
+
22294
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22295
+ ax.setScale();
22187
22296
  }
22297
+ } else { // horizontal colorbars
22298
+ if(titleWidth) {
22299
+ if(titleSide === 'right') {
22300
+ ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
22301
+ }
22188
22302
 
22189
- titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22190
- ax.setScale();
22303
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
22304
+ ax.setScale();
22305
+ }
22191
22306
  }
22192
22307
  }
22193
22308
 
22194
22309
  g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
22195
- .attr('transform', strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))));
22310
+ .attr('transform', isVertical ?
22311
+ strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
22312
+ strTranslate(Math.round(gs.w * ax.domain[0]), 0)
22313
+ );
22196
22314
 
22197
- axLayer.attr('transform', strTranslate(0, Math.round(-gs.t)));
22315
+ axLayer.attr('transform', isVertical ?
22316
+ strTranslate(0, Math.round(-gs.t)) :
22317
+ strTranslate(Math.round(-gs.l), 0)
22318
+ );
22198
22319
 
22199
22320
  var fills = g.select('.' + cn.cbfills)
22200
22321
  .selectAll('rect.' + cn.cbfill)
@@ -22220,20 +22341,22 @@ function drawColorBar(g, opts, gd) {
22220
22341
 
22221
22342
  // offset the side adjoining the next rectangle so they
22222
22343
  // overlap, to prevent antialiasing gaps
22223
- z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
22224
-
22344
+ if(isVertical) {
22345
+ z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
22346
+ } /* else {
22347
+ // TODO: horizontal case
22348
+ } */
22225
22349
 
22226
22350
  // Colorbar cannot currently support opacities so we
22227
22351
  // use an opaque fill even when alpha channels present
22228
- var fillEl = d3.select(this).attr({
22229
- x: uPx,
22230
- width: Math.max(thickPx, 2),
22231
- y: d3.min(z),
22232
- height: Math.max(d3.max(z) - d3.min(z), 2),
22233
- });
22352
+ var fillEl = d3.select(this)
22353
+ .attr(isVertical ? 'x' : 'y', uPx)
22354
+ .attr(isVertical ? 'y' : 'x', d3.min(z))
22355
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
22356
+ .attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
22234
22357
 
22235
22358
  if(opts._fillgradient) {
22236
- Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
22359
+ Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
22237
22360
  } else {
22238
22361
  // tinycolor can't handle exponents and
22239
22362
  // at this scale, removing it makes no difference.
@@ -22249,9 +22372,15 @@ function drawColorBar(g, opts, gd) {
22249
22372
  .classed(cn.cbline, true);
22250
22373
  lines.exit().remove();
22251
22374
  lines.each(function(d) {
22375
+ var a = uPx;
22376
+ var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
22377
+
22252
22378
  d3.select(this)
22253
- .attr('d', 'M' + uPx + ',' +
22254
- (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx)
22379
+ .attr('d', 'M' +
22380
+ (isVertical ? a + ',' + b : b + ',' + a) +
22381
+ (isVertical ? 'h' : 'v') +
22382
+ thickPx
22383
+ )
22255
22384
  .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
22256
22385
  });
22257
22386
 
@@ -22284,82 +22413,211 @@ function drawColorBar(g, opts, gd) {
22284
22413
  // TODO: why are we redrawing multiple times now with this?
22285
22414
  // I guess autoMargin doesn't like being post-promise?
22286
22415
  function positionCB() {
22416
+ var bb;
22287
22417
  var innerThickness = thickPx + outlinewidth / 2;
22288
- if(ax.ticklabelposition.indexOf('inside') === -1) {
22289
- innerThickness += Drawing.bBox(axLayer.node()).width;
22418
+ if(ticklabelposition.indexOf('inside') === -1) {
22419
+ bb = Drawing.bBox(axLayer.node());
22420
+ innerThickness += isVertical ? bb.width : bb.height;
22290
22421
  }
22291
22422
 
22292
22423
  titleEl = titleCont.select('text');
22293
22424
 
22425
+ var titleWidth = 0;
22426
+
22427
+ var topSideVertical = isVertical && titleSide === 'top';
22428
+ var rightSideHorizontal = !isVertical && titleSide === 'right';
22429
+
22430
+ var moveY = 0;
22431
+
22294
22432
  if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
22433
+ var _titleHeight;
22434
+
22295
22435
  var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
22296
- var titleWidth;
22297
- if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) {
22298
- titleWidth = Drawing.bBox(mathJaxNode).width;
22436
+ if(mathJaxNode && (
22437
+ (isVertical && topOrBottom) ||
22438
+ (!isVertical && !topOrBottom)
22439
+ )) {
22440
+ bb = Drawing.bBox(mathJaxNode);
22441
+ titleWidth = bb.width;
22442
+ _titleHeight = bb.height;
22299
22443
  } else {
22300
22444
  // note: the formula below works for all title sides,
22301
22445
  // (except for top/bottom mathjax, above)
22302
22446
  // but the weird gs.l is because the titleunshift
22303
22447
  // transform gets removed by Drawing.bBox
22304
- titleWidth = Drawing.bBox(titleCont.node()).right - uPx - gs.l;
22448
+ bb = Drawing.bBox(titleCont.node());
22449
+ titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
22450
+ _titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
22451
+
22452
+ if(
22453
+ !isVertical && titleSide === 'top'
22454
+ ) {
22455
+ innerThickness += bb.height;
22456
+ moveY = bb.height;
22457
+ }
22458
+ }
22459
+
22460
+ if(rightSideHorizontal) {
22461
+ titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
22462
+
22463
+ titleWidth *= 2;
22305
22464
  }
22306
- innerThickness = Math.max(innerThickness, titleWidth);
22465
+
22466
+ innerThickness = Math.max(innerThickness,
22467
+ isVertical ? titleWidth : _titleHeight
22468
+ );
22307
22469
  }
22308
22470
 
22309
- var outerThickness = 2 * xpad + innerThickness + borderwidth + outlinewidth / 2;
22471
+ var outerThickness = (isVertical ?
22472
+ xpad :
22473
+ ypad
22474
+ ) * 2 + innerThickness + borderwidth + outlinewidth / 2;
22310
22475
 
22311
- g.select('.' + cn.cbbg).attr({
22312
- x: uPx - xpad - (borderwidth + outlinewidth) / 2,
22313
- y: vPx - lenPx - yExtraPx,
22314
- width: Math.max(outerThickness, 2),
22315
- height: Math.max(lenPx + 2 * yExtraPx, 2)
22316
- })
22317
- .call(Color.fill, opts.bgcolor)
22476
+ var hColorbarMoveTitle = 0;
22477
+ if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
22478
+ hColorbarMoveTitle = outerThickness / 2;
22479
+
22480
+ outerThickness += hColorbarMoveTitle;
22481
+ moveY += hColorbarMoveTitle;
22482
+ }
22483
+ fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
22484
+ fullLayout._hColorbarMoveCBTitle = moveY;
22485
+
22486
+ var extraW = borderwidth + outlinewidth;
22487
+
22488
+ g.select('.' + cn.cbbg)
22489
+ .attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
22490
+ .attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
22491
+ .attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
22492
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
22493
+ .call(Color.fill, bgcolor)
22318
22494
  .call(Color.stroke, opts.bordercolor)
22319
22495
  .style('stroke-width', borderwidth);
22320
22496
 
22321
- g.selectAll('.' + cn.cboutline).attr({
22322
- x: uPx,
22323
- y: vPx - lenPx + ypad + (titleSide === 'top' ? titleHeight : 0),
22324
- width: Math.max(thickPx, 2),
22325
- height: Math.max(lenPx - 2 * ypad - titleHeight, 2)
22326
- })
22497
+ var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
22498
+
22499
+ g.selectAll('.' + cn.cboutline)
22500
+ .attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
22501
+ .attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
22502
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
22503
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
22504
+ 2 * ypad + titleHeight :
22505
+ 2 * xpad + moveX
22506
+ ), 2))
22327
22507
  .call(Color.stroke, opts.outlinecolor)
22328
22508
  .style({
22329
22509
  fill: 'none',
22330
22510
  'stroke-width': outlinewidth
22331
22511
  });
22332
22512
 
22333
- // fix positioning for xanchor!='left'
22334
- var xoffset = ({center: 0.5, right: 1}[xanchor] || 0) * outerThickness;
22335
- g.attr('transform', strTranslate(gs.l - xoffset, gs.t));
22513
+ g.attr('transform', strTranslate(
22514
+ gs.l - (isVertical ? xRatio * outerThickness : 0),
22515
+ gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
22516
+ ));
22517
+
22518
+ if(!isVertical && (
22519
+ borderwidth || (
22520
+ tinycolor(bgcolor).getAlpha() &&
22521
+ !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
22522
+ )
22523
+ )) {
22524
+ // for horizontal colorbars when there is a border line or having different background color
22525
+ // hide/adjust x positioning for the first/last tick labels if they go outside the border
22526
+ var tickLabels = axLayer.selectAll('text');
22527
+ var numTicks = tickLabels[0].length;
22528
+
22529
+ var border = g.select('.' + cn.cbbg).node();
22530
+ var oBb = Drawing.bBox(border);
22531
+ var oTr = Drawing.getTranslate(g);
22532
+
22533
+ var TEXTPAD = 2;
22534
+
22535
+ tickLabels.each(function(d, i) {
22536
+ var first = 0;
22537
+ var last = numTicks - 1;
22538
+ if(i === first || i === last) {
22539
+ var iBb = Drawing.bBox(this);
22540
+ var iTr = Drawing.getTranslate(this);
22541
+ var deltaX;
22542
+
22543
+ if(i === last) {
22544
+ var iRight = iBb.right + iTr.x;
22545
+ var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
22546
+
22547
+ deltaX = oRight - iRight;
22548
+ if(deltaX > 0) deltaX = 0;
22549
+ } else if(i === first) {
22550
+ var iLeft = iBb.left + iTr.x;
22551
+ var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
22552
+
22553
+ deltaX = oLeft - iLeft;
22554
+ if(deltaX < 0) deltaX = 0;
22555
+ }
22556
+
22557
+ if(deltaX) {
22558
+ if(numTicks < 3) { // adjust position
22559
+ this.setAttribute('transform',
22560
+ 'translate(' + deltaX + ',0) ' +
22561
+ this.getAttribute('transform')
22562
+ );
22563
+ } else { // hide
22564
+ this.setAttribute('visibility', 'hidden');
22565
+ }
22566
+ }
22567
+ }
22568
+ });
22569
+ }
22336
22570
 
22337
22571
  // auto margin adjustment
22338
22572
  var marginOpts = {};
22573
+ var lFrac = FROM_TL[xanchor];
22574
+ var rFrac = FROM_BR[xanchor];
22339
22575
  var tFrac = FROM_TL[yanchor];
22340
22576
  var bFrac = FROM_BR[yanchor];
22341
- if(lenmode === 'pixels') {
22342
- marginOpts.y = optsY;
22343
- marginOpts.t = lenPx * tFrac;
22344
- marginOpts.b = lenPx * bFrac;
22345
- } else {
22346
- marginOpts.t = marginOpts.b = 0;
22347
- marginOpts.yt = optsY + len * tFrac;
22348
- marginOpts.yb = optsY - len * bFrac;
22349
- }
22350
22577
 
22351
- var lFrac = FROM_TL[xanchor];
22352
- var rFrac = FROM_BR[xanchor];
22353
- if(thicknessmode === 'pixels') {
22354
- marginOpts.x = optsX;
22355
- marginOpts.l = outerThickness * lFrac;
22356
- marginOpts.r = outerThickness * rFrac;
22357
- } else {
22358
- var extraThickness = outerThickness - thickPx;
22359
- marginOpts.l = extraThickness * lFrac;
22360
- marginOpts.r = extraThickness * rFrac;
22361
- marginOpts.xl = optsX - thickness * lFrac;
22362
- marginOpts.xr = optsX + thickness * rFrac;
22578
+ var extraThickness = outerThickness - thickPx;
22579
+ if(isVertical) {
22580
+ if(lenmode === 'pixels') {
22581
+ marginOpts.y = optsY;
22582
+ marginOpts.t = lenPx * tFrac;
22583
+ marginOpts.b = lenPx * bFrac;
22584
+ } else {
22585
+ marginOpts.t = marginOpts.b = 0;
22586
+ marginOpts.yt = optsY + len * tFrac;
22587
+ marginOpts.yb = optsY - len * bFrac;
22588
+ }
22589
+
22590
+ if(thicknessmode === 'pixels') {
22591
+ marginOpts.x = optsX;
22592
+ marginOpts.l = outerThickness * lFrac;
22593
+ marginOpts.r = outerThickness * rFrac;
22594
+ } else {
22595
+ marginOpts.l = extraThickness * lFrac;
22596
+ marginOpts.r = extraThickness * rFrac;
22597
+ marginOpts.xl = optsX - thickness * lFrac;
22598
+ marginOpts.xr = optsX + thickness * rFrac;
22599
+ }
22600
+ } else { // horizontal colorbars
22601
+ if(lenmode === 'pixels') {
22602
+ marginOpts.x = optsX;
22603
+ marginOpts.l = lenPx * lFrac;
22604
+ marginOpts.r = lenPx * rFrac;
22605
+ } else {
22606
+ marginOpts.l = marginOpts.r = 0;
22607
+ marginOpts.xl = optsX + len * lFrac;
22608
+ marginOpts.xr = optsX - len * rFrac;
22609
+ }
22610
+
22611
+ if(thicknessmode === 'pixels') {
22612
+ marginOpts.y = 1 - optsY;
22613
+ marginOpts.t = outerThickness * tFrac;
22614
+ marginOpts.b = outerThickness * bFrac;
22615
+ } else {
22616
+ marginOpts.t = extraThickness * tFrac;
22617
+ marginOpts.b = extraThickness * bFrac;
22618
+ marginOpts.yt = optsY - thickness * tFrac;
22619
+ marginOpts.yb = optsY + thickness * bFrac;
22620
+ }
22363
22621
  }
22364
22622
 
22365
22623
  Plots.autoMargin(gd, opts._id, marginOpts);
@@ -22376,6 +22634,7 @@ function drawColorBar(g, opts, gd) {
22376
22634
  }
22377
22635
 
22378
22636
  function makeEditable(g, opts, gd) {
22637
+ var isVertical = opts.orientation === 'v';
22379
22638
  var fullLayout = gd._fullLayout;
22380
22639
  var gs = fullLayout._size;
22381
22640
  var t0, xf, yf;
@@ -22390,9 +22649,13 @@ function makeEditable(g, opts, gd) {
22390
22649
  moveFn: function(dx, dy) {
22391
22650
  g.attr('transform', t0 + strTranslate(dx, dy));
22392
22651
 
22393
- xf = dragElement.align(opts._uFrac + (dx / gs.w), opts._thickFrac,
22652
+ xf = dragElement.align(
22653
+ (isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
22654
+ isVertical ? opts._thickFrac : opts._lenFrac,
22394
22655
  0, 1, opts.xanchor);
22395
- yf = dragElement.align(opts._vFrac - (dy / gs.h), opts._lenFrac,
22656
+ yf = dragElement.align(
22657
+ (isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
22658
+ isVertical ? opts._lenFrac : opts._thickFrac,
22396
22659
  0, 1, opts.yanchor);
22397
22660
 
22398
22661
  var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
@@ -22469,6 +22732,8 @@ function calcLevels(gd, opts, zrange) {
22469
22732
  function mockColorBarAxis(gd, opts, zrange) {
22470
22733
  var fullLayout = gd._fullLayout;
22471
22734
 
22735
+ var isVertical = opts.orientation === 'v';
22736
+
22472
22737
  var cbAxisIn = {
22473
22738
  type: 'linear',
22474
22739
  range: zrange,
@@ -22499,17 +22764,19 @@ function mockColorBarAxis(gd, opts, zrange) {
22499
22764
  title: opts.title,
22500
22765
  showline: true,
22501
22766
  anchor: 'free',
22502
- side: 'right',
22767
+ side: isVertical ? 'right' : 'bottom',
22503
22768
  position: 1
22504
22769
  };
22505
22770
 
22771
+ var letter = isVertical ? 'y' : 'x';
22772
+
22506
22773
  var cbAxisOut = {
22507
22774
  type: 'linear',
22508
- _id: 'y' + opts._id
22775
+ _id: letter + opts._id
22509
22776
  };
22510
22777
 
22511
22778
  var axisOptions = {
22512
- letter: 'y',
22779
+ letter: letter,
22513
22780
  font: fullLayout.font,
22514
22781
  noHover: true,
22515
22782
  noTickson: true,
@@ -28122,7 +28389,9 @@ function createHoverText(hoverData, opts) {
28122
28389
  orientation: 'v'
28123
28390
  }
28124
28391
  };
28125
- var mockLayoutOut = {};
28392
+ var mockLayoutOut = {
28393
+ font: font
28394
+ };
28126
28395
  legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
28127
28396
  var mockLegend = mockLayoutOut.legend;
28128
28397
 
@@ -28163,7 +28432,8 @@ function createHoverText(hoverData, opts) {
28163
28432
 
28164
28433
  // Draw unified hover label
28165
28434
  mockLegend._inHover = true;
28166
- mockLegend._groupTitleFont = font;
28435
+ mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
28436
+
28167
28437
  legendDraw(gd, mockLegend);
28168
28438
 
28169
28439
  // Position the hover
@@ -29165,9 +29435,11 @@ var isUnifiedHover = _dereq_('./helpers').isUnifiedHover;
29165
29435
  module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
29166
29436
  opts = opts || {};
29167
29437
 
29438
+ var hasLegend = contOut.legend;
29439
+
29168
29440
  function inheritFontAttr(attr) {
29169
29441
  if(!opts.font[attr]) {
29170
- opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
29442
+ opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
29171
29443
  }
29172
29444
  }
29173
29445
 
@@ -29178,7 +29450,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
29178
29450
  inheritFontAttr('family');
29179
29451
  inheritFontAttr('color');
29180
29452
 
29181
- if(contOut.legend) {
29453
+ if(hasLegend) {
29182
29454
  if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
29183
29455
  if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
29184
29456
  } else {
@@ -29287,11 +29559,13 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
29287
29559
 
29288
29560
  var constants = _dereq_('./constants');
29289
29561
 
29290
- var fontAttrs = _dereq_('../../plots/font_attributes')({
29562
+ var fontAttrs = _dereq_('../../plots/font_attributes');
29563
+
29564
+ var font = fontAttrs({
29291
29565
  editType: 'none',
29292
29566
  });
29293
- fontAttrs.family.dflt = constants.HOVERFONT;
29294
- fontAttrs.size.dflt = constants.HOVERFONTSIZE;
29567
+ font.family.dflt = constants.HOVERFONT;
29568
+ font.size.dflt = constants.HOVERFONTSIZE;
29295
29569
 
29296
29570
  module.exports = {
29297
29571
  clickmode: {
@@ -29347,7 +29621,10 @@ module.exports = {
29347
29621
  valType: 'color',
29348
29622
  editType: 'none',
29349
29623
  },
29350
- font: fontAttrs,
29624
+ font: font,
29625
+ grouptitlefont: fontAttrs({
29626
+ editType: 'none',
29627
+ }),
29351
29628
  align: {
29352
29629
  valType: 'enumerated',
29353
29630
  values: ['left', 'right', 'auto'],
@@ -29360,6 +29637,7 @@ module.exports = {
29360
29637
  dflt: 15,
29361
29638
  editType: 'none',
29362
29639
  },
29640
+
29363
29641
  editType: 'none'
29364
29642
  },
29365
29643
  selectdirection: {
@@ -29407,6 +29685,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
29407
29685
  }
29408
29686
 
29409
29687
  handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
29688
+
29689
+ Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
29410
29690
  };
29411
29691
 
29412
29692
  },{"../../lib":232,"./hoverlabel_defaults":140,"./hovermode_defaults":141,"./layout_attributes":143}],145:[function(_dereq_,module,exports){
@@ -30290,6 +30570,9 @@ module.exports = {
30290
30570
  font: fontAttrs({
30291
30571
  editType: 'legend',
30292
30572
  }),
30573
+ grouptitlefont: fontAttrs({
30574
+ editType: 'legend',
30575
+ }),
30293
30576
  orientation: {
30294
30577
  valType: 'enumerated',
30295
30578
  values: ['v', 'h'],
@@ -30413,6 +30696,7 @@ var Registry = _dereq_('../../registry');
30413
30696
  var Lib = _dereq_('../../lib');
30414
30697
  var Template = _dereq_('../../plot_api/plot_template');
30415
30698
 
30699
+ var plotsAttrs = _dereq_('../../plots/attributes');
30416
30700
  var attributes = _dereq_('./attributes');
30417
30701
  var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes');
30418
30702
  var helpers = _dereq_('./helpers');
@@ -30420,13 +30704,30 @@ var helpers = _dereq_('./helpers');
30420
30704
 
30421
30705
  module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
30422
30706
  var containerIn = layoutIn.legend || {};
30707
+ var containerOut = Template.newContainer(layoutOut, 'legend');
30708
+
30709
+ function coerce(attr, dflt) {
30710
+ return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
30711
+ }
30712
+
30713
+ var trace;
30714
+ var traceCoerce = function(attr, dflt) {
30715
+ var traceIn = trace._input;
30716
+ var traceOut = trace;
30717
+ return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
30718
+ };
30719
+
30720
+ var globalFont = layoutOut.font || {};
30721
+ var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
30722
+ size: Math.round(globalFont.size * 1.1)
30723
+ }));
30423
30724
 
30424
30725
  var legendTraceCount = 0;
30425
30726
  var legendReallyHasATrace = false;
30426
30727
  var defaultOrder = 'normal';
30427
30728
 
30428
30729
  for(var i = 0; i < fullData.length; i++) {
30429
- var trace = fullData[i];
30730
+ trace = fullData[i];
30430
30731
 
30431
30732
  if(!trace.visible) continue;
30432
30733
 
@@ -30453,6 +30754,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
30453
30754
  legendTraceCount++;
30454
30755
  }
30455
30756
  }
30757
+
30758
+ Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
30456
30759
  }
30457
30760
 
30458
30761
  if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -30471,13 +30774,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
30471
30774
  basePlotLayoutAttributes, 'showlegend',
30472
30775
  legendReallyHasATrace && legendTraceCount > 1);
30473
30776
 
30474
- if(showLegend === false && !containerIn.uirevision) return;
30475
-
30476
- var containerOut = Template.newContainer(layoutOut, 'legend');
30777
+ // delete legend
30778
+ if(showLegend === false) layoutOut.legend = undefined;
30477
30779
 
30478
- function coerce(attr, dflt) {
30479
- return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
30480
- }
30780
+ if(showLegend === false && !containerIn.uirevision) return;
30481
30781
 
30482
30782
  coerce('uirevision', layoutOut.uirevision);
30483
30783
 
@@ -30539,7 +30839,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
30539
30839
  }
30540
30840
  };
30541
30841
 
30542
- },{"../../lib":232,"../../plot_api/plot_template":268,"../../plots/layout_attributes":314,"../../registry":318,"./attributes":152,"./helpers":158}],155:[function(_dereq_,module,exports){
30842
+ },{"../../lib":232,"../../plot_api/plot_template":268,"../../plots/attributes":275,"../../plots/layout_attributes":314,"../../registry":318,"./attributes":152,"./helpers":158}],155:[function(_dereq_,module,exports){
30543
30843
  'use strict';
30544
30844
 
30545
30845
  var d3 = _dereq_('@plotly/d3');
@@ -38991,8 +39291,10 @@ function draw(gd, titleClass, options) {
38991
39291
 
38992
39292
  var elShouldExist = txt || editable;
38993
39293
 
39294
+ var hColorbarMoveTitle;
38994
39295
  if(!group) {
38995
39296
  group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass);
39297
+ hColorbarMoveTitle = fullLayout._hColorbarMoveTitle;
38996
39298
  }
38997
39299
 
38998
39300
  var el = group.selectAll('text')
@@ -39016,13 +39318,17 @@ function draw(gd, titleClass, options) {
39016
39318
  function drawTitle(titleEl) {
39017
39319
  var transformVal;
39018
39320
 
39321
+ if(!transform && hColorbarMoveTitle) {
39322
+ transform = {};
39323
+ }
39324
+
39019
39325
  if(transform) {
39020
39326
  transformVal = '';
39021
39327
  if(transform.rotate) {
39022
39328
  transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')';
39023
39329
  }
39024
- if(transform.offset) {
39025
- transformVal += strTranslate(0, transform.offset);
39330
+ if(transform.offset || hColorbarMoveTitle) {
39331
+ transformVal += strTranslate(0, (transform.offset || 0) - (hColorbarMoveTitle || 0));
39026
39332
  }
39027
39333
  } else {
39028
39334
  transformVal = null;
@@ -50480,7 +50786,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
50480
50786
  if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
50481
50787
  (typeof value === 'string' || typeof value === 'number')) {
50482
50788
  replace(key, key.replace('title', 'title.text'));
50483
- } else if(key.indexOf('titlefont') > -1) {
50789
+ } else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
50484
50790
  replace(key, key.replace('titlefont', 'title.font'));
50485
50791
  } else if(key.indexOf('titleposition') > -1) {
50486
50792
  replace(key, key.replace('titleposition', 'title.position'));
@@ -51157,7 +51463,8 @@ function findUIPattern(key, patternSpecs) {
51157
51463
  var spec = patternSpecs[i];
51158
51464
  var match = key.match(spec.pattern);
51159
51465
  if(match) {
51160
- return {head: match[1], attr: spec.attr};
51466
+ var head = match[1] || '';
51467
+ return {head: head, tail: key.substr(head.length + 1), attr: spec.attr};
51161
51468
  }
51162
51469
  }
51163
51470
  }
@@ -51209,26 +51516,54 @@ function valsMatch(v1, v2) {
51209
51516
 
51210
51517
  function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
51211
51518
  var layoutPreGUI = oldFullLayout._preGUI;
51212
- var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal;
51519
+ var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal, head, tail;
51213
51520
  var bothInheritAutorange = [];
51521
+ var newAutorangeIn = {};
51214
51522
  var newRangeAccepted = {};
51215
51523
  for(key in layoutPreGUI) {
51216
51524
  match = findUIPattern(key, layoutUIControlPatterns);
51217
51525
  if(match) {
51218
- revAttr = match.attr || (match.head + '.uirevision');
51526
+ head = match.head;
51527
+ tail = match.tail;
51528
+ revAttr = match.attr || (head + '.uirevision');
51219
51529
  oldRev = nestedProperty(oldFullLayout, revAttr).get();
51220
51530
  newRev = oldRev && getNewRev(revAttr, layout);
51531
+
51221
51532
  if(newRev && (newRev === oldRev)) {
51222
51533
  preGUIVal = layoutPreGUI[key];
51223
51534
  if(preGUIVal === null) preGUIVal = undefined;
51224
51535
  newNP = nestedProperty(layout, key);
51225
51536
  newVal = newNP.get();
51537
+
51226
51538
  if(valsMatch(newVal, preGUIVal)) {
51227
- if(newVal === undefined && key.substr(key.length - 9) === 'autorange') {
51228
- bothInheritAutorange.push(key.substr(0, key.length - 10));
51539
+ if(newVal === undefined && tail === 'autorange') {
51540
+ bothInheritAutorange.push(head);
51229
51541
  }
51230
51542
  newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
51231
51543
  continue;
51544
+ } else if(tail === 'autorange' || tail.substr(0, 6) === 'range[') {
51545
+ // Special case for (auto)range since we push it back into the layout
51546
+ // so all null should be treated equivalently to autorange: true with any range
51547
+ var pre0 = layoutPreGUI[head + '.range[0]'];
51548
+ var pre1 = layoutPreGUI[head + '.range[1]'];
51549
+ var preAuto = layoutPreGUI[head + '.autorange'];
51550
+ if(preAuto || (preAuto === null && pre0 === null && pre1 === null)) {
51551
+ // Only read the input layout once and stash the result,
51552
+ // so we get it before we start modifying it
51553
+ if(!(head in newAutorangeIn)) {
51554
+ var newContainer = nestedProperty(layout, head).get();
51555
+ newAutorangeIn[head] = newContainer && (
51556
+ newContainer.autorange ||
51557
+ (newContainer.autorange !== false && (
51558
+ !newContainer.range || newContainer.range.length !== 2)
51559
+ )
51560
+ );
51561
+ }
51562
+ if(newAutorangeIn[head]) {
51563
+ newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
51564
+ continue;
51565
+ }
51566
+ }
51232
51567
  }
51233
51568
  }
51234
51569
  } else {
@@ -51239,12 +51574,12 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
51239
51574
  // so remove it from _preGUI for next time.
51240
51575
  delete layoutPreGUI[key];
51241
51576
 
51242
- if(key.substr(key.length - 8, 6) === 'range[') {
51243
- newRangeAccepted[key.substr(0, key.length - 9)] = 1;
51577
+ if(match && match.tail.substr(0, 6) === 'range[') {
51578
+ newRangeAccepted[match.head] = 1;
51244
51579
  }
51245
51580
  }
51246
51581
 
51247
- // Special logic for `autorange`, since it interacts with `range`:
51582
+ // More special logic for `autorange`, since it interacts with `range`:
51248
51583
  // If the new figure's matching `range` was kept, and `autorange`
51249
51584
  // wasn't supplied explicitly in either the original or the new figure,
51250
51585
  // we shouldn't alter that - but we may just have done that, so fix it.
@@ -68319,6 +68654,9 @@ module.exports = function(opts) {
68319
68654
  // TODO - that's uber hacky... better solution?
68320
68655
  };
68321
68656
 
68657
+ if(opts.autoSize) attrs.size.dflt = 'auto';
68658
+ if(opts.autoColor) attrs.color.dflt = 'auto';
68659
+
68322
68660
  if(opts.arrayOk) {
68323
68661
  attrs.family.arrayOk = true;
68324
68662
  attrs.size.arrayOk = true;
@@ -68678,6 +69016,7 @@ module.exports = {
68678
69016
  valType: 'boolean',
68679
69017
  editType: 'legend',
68680
69018
  },
69019
+
68681
69020
  colorway: {
68682
69021
  valType: 'colorlist',
68683
69022
  dflt: colorAttrs.defaults,
@@ -70090,13 +70429,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
70090
70429
  );
70091
70430
 
70092
70431
  coerce('legendgroup');
70093
- var titleText = coerce('legendgrouptitle.text');
70094
- if(titleText) {
70095
- Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
70096
- size: Math.round(layout.font.size * 1.1) // default to larger font size
70097
- }));
70098
- }
70099
-
70432
+ coerce('legendgrouptitle.text');
70100
70433
  coerce('legendrank');
70101
70434
 
70102
70435
  traceOut._dfltShowLegend = true;
@@ -70244,16 +70577,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
70244
70577
 
70245
70578
  coerce('autotypenumbers');
70246
70579
 
70247
- var globalFont = Lib.coerceFont(coerce, 'font');
70248
-
70249
- coerce('title.text', layoutOut._dfltTitle.plot);
70580
+ var font = Lib.coerceFont(coerce, 'font');
70581
+ var fontSize = font.size;
70250
70582
 
70251
- Lib.coerceFont(coerce, 'title.font', {
70252
- family: globalFont.family,
70253
- size: Math.round(globalFont.size * 1.4),
70254
- color: globalFont.color
70255
- });
70583
+ Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
70584
+ size: Math.round(fontSize * 1.4)
70585
+ }));
70256
70586
 
70587
+ coerce('title.text', layoutOut._dfltTitle.plot);
70257
70588
  coerce('title.xref');
70258
70589
  coerce('title.yref');
70259
70590
  coerce('title.x');
@@ -75590,7 +75921,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts, makeOnCom
75590
75921
  }
75591
75922
 
75592
75923
  transform.fontSize = font.size;
75593
- recordMinTextSize(trace.type, transform, fullLayout);
75924
+ recordMinTextSize(trace.type === 'histogram' ? 'bar' : trace.type, transform, fullLayout);
75594
75925
  calcBar.transform = transform;
75595
75926
 
75596
75927
  transition(textSelection, fullLayout, opts, makeOnCompleteCallback)
@@ -75793,10 +76124,11 @@ function calcTexttemplate(fullLayout, cd, index, xa, ya) {
75793
76124
  if(!texttemplate) return '';
75794
76125
  var isWaterfall = (trace.type === 'waterfall');
75795
76126
  var isFunnel = (trace.type === 'funnel');
76127
+ var isHorizontal = trace.orientation === 'h';
75796
76128
 
75797
76129
  var pLetter, pAxis;
75798
76130
  var vLetter, vAxis;
75799
- if(trace.orientation === 'h') {
76131
+ if(isHorizontal) {
75800
76132
  pLetter = 'y';
75801
76133
  pAxis = ya;
75802
76134
  vLetter = 'x';
@@ -75831,6 +76163,11 @@ function calcTexttemplate(fullLayout, cd, index, xa, ya) {
75831
76163
  var pt = {};
75832
76164
  appendArrayPointValue(pt, trace, cdi.i);
75833
76165
 
76166
+ if(pt.x === undefined) pt.x = isHorizontal ? obj.value : obj.label;
76167
+ if(pt.y === undefined) pt.y = isHorizontal ? obj.label : obj.value;
76168
+ if(pt.xLabel === undefined) pt.xLabel = isHorizontal ? obj.valueLabel : obj.labelLabel;
76169
+ if(pt.yLabel === undefined) pt.yLabel = isHorizontal ? obj.labelLabel : obj.valueLabel;
76170
+
75834
76171
  if(isWaterfall) {
75835
76172
  obj.delta = +cdi.rawS || cdi.s;
75836
76173
  obj.deltaLabel = formatNumber(obj.delta);
@@ -76658,7 +76995,6 @@ function calc(gd, trace) {
76658
76995
  v = vals[i];
76659
76996
  if(!isNumeric(v)) continue;
76660
76997
  v = +v;
76661
- if(v < 0) continue;
76662
76998
  } else v = 1;
76663
76999
 
76664
77000
  label = labels[i];
@@ -76695,6 +77031,9 @@ function calc(gd, trace) {
76695
77031
  }
76696
77032
  }
76697
77033
 
77034
+ // Drop aggregate sums of value 0 or less
77035
+ cd = cd.filter(function(elem) { return elem.v >= 0; });
77036
+
76698
77037
  var shouldSort = (trace.type === 'funnelarea') ? isAggregated : trace.sort;
76699
77038
  if(shouldSort) cd.sort(function(a, b) { return b.v - a.v; });
76700
77039
 
@@ -82291,7 +82630,7 @@ function getSortFunc(opts, d2c) {
82291
82630
  'use strict';
82292
82631
 
82293
82632
  // package version injected by `npm run preprocess`
82294
- exports.version = '2.6.4';
82633
+ exports.version = '2.8.2';
82295
82634
 
82296
82635
  },{}]},{},[8])(8)
82297
82636
  });