plotly.js 2.7.0 → 2.8.3

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 (54) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +3 -3
  3. package/dist/README.md +26 -26
  4. package/dist/plot-schema.json +898 -407
  5. package/dist/plotly-basic.js +497 -186
  6. package/dist/plotly-basic.min.js +4 -4
  7. package/dist/plotly-cartesian.js +907 -329
  8. package/dist/plotly-cartesian.min.js +3 -3
  9. package/dist/plotly-finance.js +500 -188
  10. package/dist/plotly-finance.min.js +4 -4
  11. package/dist/plotly-geo-assets.js +2 -2
  12. package/dist/plotly-geo.js +486 -184
  13. package/dist/plotly-geo.min.js +4 -4
  14. package/dist/plotly-gl2d.js +505 -187
  15. package/dist/plotly-gl2d.min.js +2 -2
  16. package/dist/plotly-gl3d.js +486 -184
  17. package/dist/plotly-gl3d.min.js +2 -2
  18. package/dist/plotly-mapbox.js +486 -184
  19. package/dist/plotly-mapbox.min.js +2 -2
  20. package/dist/plotly-strict.js +1125 -547
  21. package/dist/plotly-strict.min.js +3 -3
  22. package/dist/plotly-with-meta.js +1214 -609
  23. package/dist/plotly.js +1179 -601
  24. package/dist/plotly.min.js +10 -10
  25. package/package.json +4 -4
  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 +1 -1
  37. package/src/plots/font_attributes.js +3 -0
  38. package/src/plots/layout_attributes.js +1 -0
  39. package/src/plots/plots.js +7 -15
  40. package/src/traces/bar/plot.js +8 -1
  41. package/src/traces/contour/attributes.js +12 -0
  42. package/src/traces/contour/defaults.js +9 -1
  43. package/src/traces/heatmap/attributes.js +16 -0
  44. package/src/traces/heatmap/defaults.js +2 -0
  45. package/src/traces/heatmap/label_defaults.js +13 -0
  46. package/src/traces/heatmap/plot.js +205 -4
  47. package/src/traces/histogram/calc.js +3 -2
  48. package/src/traces/histogram2d/attributes.js +8 -0
  49. package/src/traces/histogram2d/defaults.js +4 -0
  50. package/src/traces/histogram2dcontour/attributes.js +3 -1
  51. package/src/traces/histogram2dcontour/defaults.js +8 -1
  52. package/src/traces/pie/calc.js +3 -1
  53. package/src/version.js +1 -1
  54. package/tasks/test_mock.js +1 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * plotly.js (finance) v2.7.0
2
+ * plotly.js (finance) v2.8.3
3
3
  * Copyright 2012-2021, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -22784,13 +22784,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
22784
22784
 
22785
22785
 
22786
22786
  module.exports = overrideAll({
22787
- // TODO: only right is supported currently
22788
- // orient: {
22789
- // valType: 'enumerated',
22790
- // values: ['left', 'right', 'top', 'bottom'],
22791
- // dflt: 'right',
22792
- //
22793
- // },
22787
+ orientation: {
22788
+ valType: 'enumerated',
22789
+ values: ['h', 'v'],
22790
+ dflt: 'v',
22791
+ },
22794
22792
  thicknessmode: {
22795
22793
  valType: 'enumerated',
22796
22794
  values: ['fraction', 'pixels'],
@@ -22813,14 +22811,12 @@ module.exports = overrideAll({
22813
22811
  },
22814
22812
  x: {
22815
22813
  valType: 'number',
22816
- dflt: 1.02,
22817
22814
  min: -2,
22818
22815
  max: 3,
22819
22816
  },
22820
22817
  xanchor: {
22821
22818
  valType: 'enumerated',
22822
22819
  values: ['left', 'center', 'right'],
22823
- dflt: 'left',
22824
22820
  },
22825
22821
  xpad: {
22826
22822
  valType: 'number',
@@ -22829,14 +22825,12 @@ module.exports = overrideAll({
22829
22825
  },
22830
22826
  y: {
22831
22827
  valType: 'number',
22832
- dflt: 0.5,
22833
22828
  min: -2,
22834
22829
  max: 3,
22835
22830
  },
22836
22831
  yanchor: {
22837
22832
  valType: 'enumerated',
22838
22833
  values: ['top', 'middle', 'bottom'],
22839
- dflt: 'middle',
22840
22834
  },
22841
22835
  ypad: {
22842
22836
  valType: 'number',
@@ -22868,15 +22862,21 @@ module.exports = overrideAll({
22868
22862
  ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
22869
22863
  ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
22870
22864
  }),
22865
+
22866
+ // ticklabelposition: not used directly, as values depend on orientation
22867
+ // left/right options are for x axes, and top/bottom options are for y axes
22871
22868
  ticklabelposition: {
22872
22869
  valType: 'enumerated',
22873
22870
  values: [
22874
22871
  'outside', 'inside',
22875
22872
  'outside top', 'inside top',
22873
+ 'outside left', 'inside left',
22874
+ 'outside right', 'inside right',
22876
22875
  'outside bottom', 'inside bottom'
22877
22876
  ],
22878
22877
  dflt: 'outside',
22879
22878
  },
22879
+
22880
22880
  ticklen: axesAttrs.ticklen,
22881
22881
  tickwidth: axesAttrs.tickwidth,
22882
22882
  tickcolor: axesAttrs.tickcolor,
@@ -22903,7 +22903,6 @@ module.exports = overrideAll({
22903
22903
  side: {
22904
22904
  valType: 'enumerated',
22905
22905
  values: ['right', 'top', 'bottom'],
22906
- dflt: 'top',
22907
22906
  }
22908
22907
  },
22909
22908
 
@@ -22962,23 +22961,30 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
22962
22961
  return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt);
22963
22962
  }
22964
22963
 
22964
+ var margin = layout.margin || {t: 0, b: 0, l: 0, r: 0};
22965
+ var w = layout.width - margin.l - margin.r;
22966
+ var h = layout.height - margin.t - margin.b;
22967
+
22968
+ var orientation = coerce('orientation');
22969
+ var isVertical = orientation === 'v';
22970
+
22965
22971
  var thicknessmode = coerce('thicknessmode');
22966
22972
  coerce('thickness', (thicknessmode === 'fraction') ?
22967
- 30 / (layout.width - layout.margin.l - layout.margin.r) :
22973
+ 30 / (isVertical ? w : h) :
22968
22974
  30
22969
22975
  );
22970
22976
 
22971
22977
  var lenmode = coerce('lenmode');
22972
22978
  coerce('len', (lenmode === 'fraction') ?
22973
22979
  1 :
22974
- layout.height - layout.margin.t - layout.margin.b
22980
+ isVertical ? h : w
22975
22981
  );
22976
22982
 
22977
- coerce('x');
22978
- coerce('xanchor');
22983
+ coerce('x', isVertical ? 1.02 : 0.5);
22984
+ coerce('xanchor', isVertical ? 'left' : 'center');
22979
22985
  coerce('xpad');
22980
- coerce('y');
22981
- coerce('yanchor');
22986
+ coerce('y', isVertical ? 0.5 : 1.02);
22987
+ coerce('yanchor', isVertical ? 'middle' : 'bottom');
22982
22988
  coerce('ypad');
22983
22989
  Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']);
22984
22990
 
@@ -22988,7 +22994,22 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
22988
22994
  coerce('borderwidth');
22989
22995
  coerce('bgcolor');
22990
22996
 
22991
- var ticklabelposition = coerce('ticklabelposition');
22997
+ var ticklabelposition = Lib.coerce(colorbarIn, colorbarOut, {
22998
+ ticklabelposition: {
22999
+ valType: 'enumerated',
23000
+ dflt: 'outside',
23001
+ values: isVertical ? [
23002
+ 'outside', 'inside',
23003
+ 'outside top', 'inside top',
23004
+ 'outside bottom', 'inside bottom'
23005
+ ] : [
23006
+ 'outside', 'inside',
23007
+ 'outside left', 'inside left',
23008
+ 'outside right', 'inside right'
23009
+ ]
23010
+ }
23011
+ }, 'ticklabelposition');
23012
+
22992
23013
  coerce('ticklabeloverflow', ticklabelposition.indexOf('inside') !== -1 ? 'hide past domain' : 'hide past div');
22993
23014
 
22994
23015
  handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear');
@@ -23010,7 +23031,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
23010
23031
  size: Lib.bigFont(tickFont.size)
23011
23032
  });
23012
23033
  Lib.coerceFont(coerce, 'title.font', dfltTitleFont);
23013
- coerce('title.side');
23034
+ coerce('title.side', isVertical ? 'top' : 'right');
23014
23035
  };
23015
23036
 
23016
23037
  },{"../../lib":242,"../../plot_api/plot_template":278,"../../plots/cartesian/prefix_suffix_defaults":308,"../../plots/cartesian/tick_label_defaults":313,"../../plots/cartesian/tick_mark_defaults":314,"../../plots/cartesian/tick_value_defaults":315,"./attributes":112}],115:[function(_dereq_,module,exports){
@@ -23183,18 +23204,20 @@ function makeColorBarData(gd) {
23183
23204
  }
23184
23205
 
23185
23206
  function drawColorBar(g, opts, gd) {
23207
+ var isVertical = opts.orientation === 'v';
23186
23208
  var len = opts.len;
23187
23209
  var lenmode = opts.lenmode;
23188
23210
  var thickness = opts.thickness;
23189
23211
  var thicknessmode = opts.thicknessmode;
23190
23212
  var outlinewidth = opts.outlinewidth;
23191
23213
  var borderwidth = opts.borderwidth;
23214
+ var bgcolor = opts.bgcolor;
23192
23215
  var xanchor = opts.xanchor;
23193
23216
  var yanchor = opts.yanchor;
23194
23217
  var xpad = opts.xpad;
23195
23218
  var ypad = opts.ypad;
23196
23219
  var optsX = opts.x;
23197
- var optsY = opts.y;
23220
+ var optsY = isVertical ? opts.y : 1 - opts.y;
23198
23221
 
23199
23222
  var fullLayout = gd._fullLayout;
23200
23223
  var gs = fullLayout._size;
@@ -23225,23 +23248,35 @@ function drawColorBar(g, opts, gd) {
23225
23248
  // when the colorbar itself is pushing the margins.
23226
23249
  // but then the fractional size is calculated based on the
23227
23250
  // actual graph size, so that the axes will size correctly.
23228
- var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? gs.w : 1));
23229
- var thickFrac = thickPx / gs.w;
23230
- var lenPx = Math.round(len * (lenmode === 'fraction' ? gs.h : 1));
23231
- var lenFrac = lenPx / gs.h;
23232
- var xpadFrac = xpad / gs.w;
23233
- var yExtraPx = (borderwidth + outlinewidth) / 2;
23234
- var ypadFrac = ypad / gs.h;
23251
+ var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
23252
+ var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
23253
+ var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
23254
+ var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
23235
23255
 
23236
23256
  // x positioning: do it initially just for left anchor,
23237
23257
  // then fix at the end (since we don't know the width yet)
23238
- var uPx = Math.round(optsX * gs.w + xpad);
23239
- // for dragging... this is getting a little muddled...
23240
- var uFrac = optsX - thickFrac * ({center: 0.5, right: 1}[xanchor] || 0);
23258
+ var uPx = Math.round(isVertical ?
23259
+ optsX * gs.w + xpad :
23260
+ optsY * gs.h + ypad
23261
+ );
23241
23262
 
23242
- // y positioning we can do correctly from the start
23243
- var vFrac = optsY + lenFrac * (({top: -0.5, bottom: 0.5}[yanchor] || 0) - 0.5);
23244
- var vPx = Math.round(gs.h * (1 - vFrac));
23263
+ var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
23264
+ var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
23265
+
23266
+ // for dragging... this is getting a little muddled...
23267
+ var uFrac = isVertical ?
23268
+ optsX - xRatio * thickFrac :
23269
+ optsY - yRatio * thickFrac;
23270
+
23271
+ // y/x positioning (for v/h) we can do correctly from the start
23272
+ var vFrac = isVertical ?
23273
+ optsY - yRatio * lenFrac :
23274
+ optsX - xRatio * lenFrac;
23275
+
23276
+ var vPx = Math.round(isVertical ?
23277
+ gs.h * (1 - vFrac) :
23278
+ gs.w * vFrac
23279
+ );
23245
23280
 
23246
23281
  // stash a few things for makeEditable
23247
23282
  opts._lenFrac = lenFrac;
@@ -23254,12 +23289,23 @@ function drawColorBar(g, opts, gd) {
23254
23289
 
23255
23290
  // position can't go in through supplyDefaults
23256
23291
  // because that restricts it to [0,1]
23257
- ax.position = optsX + xpadFrac + thickFrac;
23292
+ ax.position = thickFrac + (isVertical ?
23293
+ optsX + xpad / gs.w :
23294
+ optsY + ypad / gs.h
23295
+ );
23296
+
23297
+ var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
23298
+
23299
+ if(isVertical && topOrBottom) {
23300
+ ax.title.side = titleSide;
23301
+ ax.titlex = optsX + xpad / gs.w;
23302
+ ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
23303
+ }
23258
23304
 
23259
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
23305
+ if(!isVertical && !topOrBottom) {
23260
23306
  ax.title.side = titleSide;
23261
- ax.titlex = optsX + xpadFrac;
23262
- ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
23307
+ ax.titley = optsY + ypad / gs.h;
23308
+ ax.titlex = vFrac + xpad / gs.w; // right side
23263
23309
  }
23264
23310
 
23265
23311
  if(line.color && opts.tickmode === 'auto') {
@@ -23284,9 +23330,12 @@ function drawColorBar(g, opts, gd) {
23284
23330
 
23285
23331
  // set domain after init, because we may want to
23286
23332
  // allow it outside [0,1]
23287
- ax.domain = [
23288
- vFrac + ypadFrac,
23289
- vFrac + lenFrac - ypadFrac
23333
+ ax.domain = isVertical ? [
23334
+ vFrac + ypad / gs.h,
23335
+ vFrac + lenFrac - ypad / gs.h
23336
+ ] : [
23337
+ vFrac + xpad / gs.w,
23338
+ vFrac + lenFrac - xpad / gs.w
23290
23339
  ];
23291
23340
 
23292
23341
  ax.setScale();
@@ -23296,9 +23345,13 @@ function drawColorBar(g, opts, gd) {
23296
23345
  var titleCont = g.select('.' + cn.cbtitleunshift)
23297
23346
  .attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
23298
23347
 
23348
+ var ticklabelposition = ax.ticklabelposition;
23349
+ var titleFontSize = ax.title.font.size;
23350
+
23299
23351
  var axLayer = g.select('.' + cn.cbaxis);
23300
23352
  var titleEl;
23301
23353
  var titleHeight = 0;
23354
+ var titleWidth = 0;
23302
23355
 
23303
23356
  function drawTitle(titleClass, titleOpts) {
23304
23357
  var dfltTitleOpts = {
@@ -23323,54 +23376,98 @@ function drawColorBar(g, opts, gd) {
23323
23376
  }
23324
23377
 
23325
23378
  function drawDummyTitle() {
23326
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
23327
- // draw the title so we know how much room it needs
23328
- // when we squish the axis. This one only applies to
23329
- // top or bottom titles, not right side.
23330
- var x = gs.l + (optsX + xpadFrac) * gs.w;
23331
- var fontSize = ax.title.font.size;
23332
- var y;
23379
+ // draw the title so we know how much room it needs
23380
+ // when we squish the axis.
23381
+ // On vertical colorbars this only applies to top or bottom titles, not right side.
23382
+ // On horizontal colorbars this only applies to right, etc.
23383
+
23384
+ if(
23385
+ (isVertical && topOrBottom) ||
23386
+ (!isVertical && !topOrBottom)
23387
+ ) {
23388
+ var x, y;
23333
23389
 
23334
23390
  if(titleSide === 'top') {
23335
- y = (1 - (vFrac + lenFrac - ypadFrac)) * gs.h +
23336
- gs.t + 3 + fontSize * 0.75;
23337
- } else {
23338
- y = (1 - (vFrac + ypadFrac)) * gs.h +
23339
- gs.t - 3 - fontSize * 0.25;
23391
+ x = xpad + gs.l + gs.w * optsX;
23392
+ y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
23393
+ }
23394
+
23395
+ if(titleSide === 'bottom') {
23396
+ x = xpad + gs.l + gs.w * optsX;
23397
+ y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
23398
+ }
23399
+
23400
+ if(titleSide === 'right') {
23401
+ y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
23402
+ x = xpad + gs.l + gs.w * vFrac;
23340
23403
  }
23404
+
23341
23405
  drawTitle(ax._id + 'title', {
23342
- attributes: {x: x, y: y, 'text-anchor': 'start'}
23406
+ attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
23343
23407
  });
23344
23408
  }
23345
23409
  }
23346
23410
 
23347
23411
  function drawCbTitle() {
23348
- if(['top', 'bottom'].indexOf(titleSide) === -1) {
23349
- var fontSize = ax.title.font.size;
23350
- var y = ax._offset + ax._length / 2;
23351
- var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ?
23352
- 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) :
23353
- -10 - fontSize * ((ax.showticklabels ? 0.5 : 0)));
23354
-
23355
- // the 'h' + is a hack to get around the fact that
23356
- // convertToTspans rotates any 'y...' class by 90 degrees.
23357
- // TODO: find a better way to control this.
23358
- drawTitle('h' + ax._id + 'title', {
23412
+ if(
23413
+ (isVertical && !topOrBottom) ||
23414
+ (!isVertical && topOrBottom)
23415
+ ) {
23416
+ var pos = ax.position || 0;
23417
+ var mid = ax._offset + ax._length / 2;
23418
+ var x, y;
23419
+
23420
+ if(titleSide === 'right') {
23421
+ y = mid;
23422
+ x = gs.l + gs.w * pos + 10 + titleFontSize * (
23423
+ ax.showticklabels ? 1 : 0.5
23424
+ );
23425
+ } else {
23426
+ x = mid;
23427
+
23428
+ if(titleSide === 'bottom') {
23429
+ y = gs.t + gs.h * pos + 10 + (
23430
+ ticklabelposition.indexOf('inside') === -1 ?
23431
+ ax.tickfont.size :
23432
+ 0
23433
+ ) + (
23434
+ ax.ticks !== 'intside' ?
23435
+ opts.ticklen || 0 :
23436
+ 0
23437
+ );
23438
+ }
23439
+
23440
+ if(titleSide === 'top') {
23441
+ var nlines = title.text.split('<br>').length;
23442
+ y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
23443
+ }
23444
+ }
23445
+
23446
+ drawTitle((isVertical ?
23447
+ // the 'h' + is a hack to get around the fact that
23448
+ // convertToTspans rotates any 'y...' class by 90 degrees.
23449
+ // TODO: find a better way to control this.
23450
+ 'h' :
23451
+ 'v'
23452
+ ) + ax._id + 'title', {
23359
23453
  avoid: {
23360
23454
  selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
23361
23455
  side: titleSide,
23362
- offsetLeft: gs.l,
23363
- offsetTop: 0,
23364
- maxShift: fullLayout.width
23456
+ offsetTop: isVertical ? 0 : gs.t,
23457
+ offsetLeft: isVertical ? gs.l : 0,
23458
+ maxShift: isVertical ? fullLayout.width : fullLayout.height
23365
23459
  },
23366
23460
  attributes: {x: x, y: y, 'text-anchor': 'middle'},
23367
- transform: {rotate: '-90', offset: 0}
23461
+ transform: {rotate: isVertical ? -90 : 0, offset: 0}
23368
23462
  });
23369
23463
  }
23370
23464
  }
23371
23465
 
23372
23466
  function drawAxis() {
23373
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
23467
+ if(
23468
+ (!isVertical && !topOrBottom) ||
23469
+ (isVertical && topOrBottom)
23470
+ ) {
23374
23471
  // squish the axis top to make room for the title
23375
23472
  var titleGroup = g.select('.' + cn.cbtitle);
23376
23473
  var titleText = titleGroup.select('text');
@@ -23382,39 +23479,63 @@ function drawColorBar(g, opts, gd) {
23382
23479
  if(titleText.node()) {
23383
23480
  lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
23384
23481
  }
23482
+
23483
+ var bb;
23385
23484
  if(mathJaxNode) {
23386
- titleHeight = Drawing.bBox(mathJaxNode).height;
23485
+ bb = Drawing.bBox(mathJaxNode);
23486
+ titleWidth = bb.width;
23487
+ titleHeight = bb.height;
23387
23488
  if(titleHeight > lineSize) {
23388
23489
  // not entirely sure how mathjax is doing
23389
23490
  // vertical alignment, but this seems to work.
23390
23491
  titleTrans[1] -= (titleHeight - lineSize) / 2;
23391
23492
  }
23392
23493
  } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
23393
- titleHeight = Drawing.bBox(titleText.node()).height;
23494
+ bb = Drawing.bBox(titleText.node());
23495
+ titleWidth = bb.width;
23496
+ titleHeight = bb.height;
23394
23497
  }
23395
- if(titleHeight) {
23396
- // buffer btwn colorbar and title
23397
- // TODO: configurable
23398
- titleHeight += 5;
23399
23498
 
23400
- if(titleSide === 'top') {
23401
- ax.domain[1] -= titleHeight / gs.h;
23402
- titleTrans[1] *= -1;
23403
- } else {
23404
- ax.domain[0] += titleHeight / gs.h;
23405
- var nlines = svgTextUtils.lineCount(titleText);
23406
- titleTrans[1] += (1 - nlines) * lineSize;
23499
+ if(isVertical) {
23500
+ if(titleHeight) {
23501
+ // buffer btwn colorbar and title
23502
+ // TODO: configurable
23503
+ titleHeight += 5;
23504
+
23505
+ if(titleSide === 'top') {
23506
+ ax.domain[1] -= titleHeight / gs.h;
23507
+ titleTrans[1] *= -1;
23508
+ } else {
23509
+ ax.domain[0] += titleHeight / gs.h;
23510
+ var nlines = svgTextUtils.lineCount(titleText);
23511
+ titleTrans[1] += (1 - nlines) * lineSize;
23512
+ }
23513
+
23514
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
23515
+ ax.setScale();
23407
23516
  }
23517
+ } else { // horizontal colorbars
23518
+ if(titleWidth) {
23519
+ if(titleSide === 'right') {
23520
+ ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
23521
+ }
23408
23522
 
23409
- titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
23410
- ax.setScale();
23523
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
23524
+ ax.setScale();
23525
+ }
23411
23526
  }
23412
23527
  }
23413
23528
 
23414
23529
  g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
23415
- .attr('transform', strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))));
23530
+ .attr('transform', isVertical ?
23531
+ strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
23532
+ strTranslate(Math.round(gs.w * ax.domain[0]), 0)
23533
+ );
23416
23534
 
23417
- axLayer.attr('transform', strTranslate(0, Math.round(-gs.t)));
23535
+ axLayer.attr('transform', isVertical ?
23536
+ strTranslate(0, Math.round(-gs.t)) :
23537
+ strTranslate(Math.round(-gs.l), 0)
23538
+ );
23418
23539
 
23419
23540
  var fills = g.select('.' + cn.cbfills)
23420
23541
  .selectAll('rect.' + cn.cbfill)
@@ -23440,20 +23561,22 @@ function drawColorBar(g, opts, gd) {
23440
23561
 
23441
23562
  // offset the side adjoining the next rectangle so they
23442
23563
  // overlap, to prevent antialiasing gaps
23443
- z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
23444
-
23564
+ if(isVertical) {
23565
+ z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
23566
+ } /* else {
23567
+ // TODO: horizontal case
23568
+ } */
23445
23569
 
23446
23570
  // Colorbar cannot currently support opacities so we
23447
23571
  // use an opaque fill even when alpha channels present
23448
- var fillEl = d3.select(this).attr({
23449
- x: uPx,
23450
- width: Math.max(thickPx, 2),
23451
- y: d3.min(z),
23452
- height: Math.max(d3.max(z) - d3.min(z), 2),
23453
- });
23572
+ var fillEl = d3.select(this)
23573
+ .attr(isVertical ? 'x' : 'y', uPx)
23574
+ .attr(isVertical ? 'y' : 'x', d3.min(z))
23575
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
23576
+ .attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
23454
23577
 
23455
23578
  if(opts._fillgradient) {
23456
- Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
23579
+ Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
23457
23580
  } else {
23458
23581
  // tinycolor can't handle exponents and
23459
23582
  // at this scale, removing it makes no difference.
@@ -23469,9 +23592,15 @@ function drawColorBar(g, opts, gd) {
23469
23592
  .classed(cn.cbline, true);
23470
23593
  lines.exit().remove();
23471
23594
  lines.each(function(d) {
23595
+ var a = uPx;
23596
+ var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
23597
+
23472
23598
  d3.select(this)
23473
- .attr('d', 'M' + uPx + ',' +
23474
- (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx)
23599
+ .attr('d', 'M' +
23600
+ (isVertical ? a + ',' + b : b + ',' + a) +
23601
+ (isVertical ? 'h' : 'v') +
23602
+ thickPx
23603
+ )
23475
23604
  .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
23476
23605
  });
23477
23606
 
@@ -23504,82 +23633,211 @@ function drawColorBar(g, opts, gd) {
23504
23633
  // TODO: why are we redrawing multiple times now with this?
23505
23634
  // I guess autoMargin doesn't like being post-promise?
23506
23635
  function positionCB() {
23636
+ var bb;
23507
23637
  var innerThickness = thickPx + outlinewidth / 2;
23508
- if(ax.ticklabelposition.indexOf('inside') === -1) {
23509
- innerThickness += Drawing.bBox(axLayer.node()).width;
23638
+ if(ticklabelposition.indexOf('inside') === -1) {
23639
+ bb = Drawing.bBox(axLayer.node());
23640
+ innerThickness += isVertical ? bb.width : bb.height;
23510
23641
  }
23511
23642
 
23512
23643
  titleEl = titleCont.select('text');
23513
23644
 
23645
+ var titleWidth = 0;
23646
+
23647
+ var topSideVertical = isVertical && titleSide === 'top';
23648
+ var rightSideHorizontal = !isVertical && titleSide === 'right';
23649
+
23650
+ var moveY = 0;
23651
+
23514
23652
  if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
23653
+ var _titleHeight;
23654
+
23515
23655
  var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
23516
- var titleWidth;
23517
- if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) {
23518
- titleWidth = Drawing.bBox(mathJaxNode).width;
23656
+ if(mathJaxNode && (
23657
+ (isVertical && topOrBottom) ||
23658
+ (!isVertical && !topOrBottom)
23659
+ )) {
23660
+ bb = Drawing.bBox(mathJaxNode);
23661
+ titleWidth = bb.width;
23662
+ _titleHeight = bb.height;
23519
23663
  } else {
23520
23664
  // note: the formula below works for all title sides,
23521
23665
  // (except for top/bottom mathjax, above)
23522
23666
  // but the weird gs.l is because the titleunshift
23523
23667
  // transform gets removed by Drawing.bBox
23524
- titleWidth = Drawing.bBox(titleCont.node()).right - uPx - gs.l;
23668
+ bb = Drawing.bBox(titleCont.node());
23669
+ titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
23670
+ _titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
23671
+
23672
+ if(
23673
+ !isVertical && titleSide === 'top'
23674
+ ) {
23675
+ innerThickness += bb.height;
23676
+ moveY = bb.height;
23677
+ }
23525
23678
  }
23526
- innerThickness = Math.max(innerThickness, titleWidth);
23679
+
23680
+ if(rightSideHorizontal) {
23681
+ titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
23682
+
23683
+ titleWidth *= 2;
23684
+ }
23685
+
23686
+ innerThickness = Math.max(innerThickness,
23687
+ isVertical ? titleWidth : _titleHeight
23688
+ );
23527
23689
  }
23528
23690
 
23529
- var outerThickness = 2 * xpad + innerThickness + borderwidth + outlinewidth / 2;
23691
+ var outerThickness = (isVertical ?
23692
+ xpad :
23693
+ ypad
23694
+ ) * 2 + innerThickness + borderwidth + outlinewidth / 2;
23530
23695
 
23531
- g.select('.' + cn.cbbg).attr({
23532
- x: uPx - xpad - (borderwidth + outlinewidth) / 2,
23533
- y: vPx - lenPx - yExtraPx,
23534
- width: Math.max(outerThickness, 2),
23535
- height: Math.max(lenPx + 2 * yExtraPx, 2)
23536
- })
23537
- .call(Color.fill, opts.bgcolor)
23696
+ var hColorbarMoveTitle = 0;
23697
+ if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
23698
+ hColorbarMoveTitle = outerThickness / 2;
23699
+
23700
+ outerThickness += hColorbarMoveTitle;
23701
+ moveY += hColorbarMoveTitle;
23702
+ }
23703
+ fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
23704
+ fullLayout._hColorbarMoveCBTitle = moveY;
23705
+
23706
+ var extraW = borderwidth + outlinewidth;
23707
+
23708
+ g.select('.' + cn.cbbg)
23709
+ .attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
23710
+ .attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
23711
+ .attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
23712
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
23713
+ .call(Color.fill, bgcolor)
23538
23714
  .call(Color.stroke, opts.bordercolor)
23539
23715
  .style('stroke-width', borderwidth);
23540
23716
 
23541
- g.selectAll('.' + cn.cboutline).attr({
23542
- x: uPx,
23543
- y: vPx - lenPx + ypad + (titleSide === 'top' ? titleHeight : 0),
23544
- width: Math.max(thickPx, 2),
23545
- height: Math.max(lenPx - 2 * ypad - titleHeight, 2)
23546
- })
23717
+ var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
23718
+
23719
+ g.selectAll('.' + cn.cboutline)
23720
+ .attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
23721
+ .attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
23722
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
23723
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
23724
+ 2 * ypad + titleHeight :
23725
+ 2 * xpad + moveX
23726
+ ), 2))
23547
23727
  .call(Color.stroke, opts.outlinecolor)
23548
23728
  .style({
23549
23729
  fill: 'none',
23550
23730
  'stroke-width': outlinewidth
23551
23731
  });
23552
23732
 
23553
- // fix positioning for xanchor!='left'
23554
- var xoffset = ({center: 0.5, right: 1}[xanchor] || 0) * outerThickness;
23555
- g.attr('transform', strTranslate(gs.l - xoffset, gs.t));
23733
+ g.attr('transform', strTranslate(
23734
+ gs.l - (isVertical ? xRatio * outerThickness : 0),
23735
+ gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
23736
+ ));
23737
+
23738
+ if(!isVertical && (
23739
+ borderwidth || (
23740
+ tinycolor(bgcolor).getAlpha() &&
23741
+ !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
23742
+ )
23743
+ )) {
23744
+ // for horizontal colorbars when there is a border line or having different background color
23745
+ // hide/adjust x positioning for the first/last tick labels if they go outside the border
23746
+ var tickLabels = axLayer.selectAll('text');
23747
+ var numTicks = tickLabels[0].length;
23748
+
23749
+ var border = g.select('.' + cn.cbbg).node();
23750
+ var oBb = Drawing.bBox(border);
23751
+ var oTr = Drawing.getTranslate(g);
23752
+
23753
+ var TEXTPAD = 2;
23754
+
23755
+ tickLabels.each(function(d, i) {
23756
+ var first = 0;
23757
+ var last = numTicks - 1;
23758
+ if(i === first || i === last) {
23759
+ var iBb = Drawing.bBox(this);
23760
+ var iTr = Drawing.getTranslate(this);
23761
+ var deltaX;
23762
+
23763
+ if(i === last) {
23764
+ var iRight = iBb.right + iTr.x;
23765
+ var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
23766
+
23767
+ deltaX = oRight - iRight;
23768
+ if(deltaX > 0) deltaX = 0;
23769
+ } else if(i === first) {
23770
+ var iLeft = iBb.left + iTr.x;
23771
+ var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
23772
+
23773
+ deltaX = oLeft - iLeft;
23774
+ if(deltaX < 0) deltaX = 0;
23775
+ }
23776
+
23777
+ if(deltaX) {
23778
+ if(numTicks < 3) { // adjust position
23779
+ this.setAttribute('transform',
23780
+ 'translate(' + deltaX + ',0) ' +
23781
+ this.getAttribute('transform')
23782
+ );
23783
+ } else { // hide
23784
+ this.setAttribute('visibility', 'hidden');
23785
+ }
23786
+ }
23787
+ }
23788
+ });
23789
+ }
23556
23790
 
23557
23791
  // auto margin adjustment
23558
23792
  var marginOpts = {};
23793
+ var lFrac = FROM_TL[xanchor];
23794
+ var rFrac = FROM_BR[xanchor];
23559
23795
  var tFrac = FROM_TL[yanchor];
23560
23796
  var bFrac = FROM_BR[yanchor];
23561
- if(lenmode === 'pixels') {
23562
- marginOpts.y = optsY;
23563
- marginOpts.t = lenPx * tFrac;
23564
- marginOpts.b = lenPx * bFrac;
23565
- } else {
23566
- marginOpts.t = marginOpts.b = 0;
23567
- marginOpts.yt = optsY + len * tFrac;
23568
- marginOpts.yb = optsY - len * bFrac;
23569
- }
23570
23797
 
23571
- var lFrac = FROM_TL[xanchor];
23572
- var rFrac = FROM_BR[xanchor];
23573
- if(thicknessmode === 'pixels') {
23574
- marginOpts.x = optsX;
23575
- marginOpts.l = outerThickness * lFrac;
23576
- marginOpts.r = outerThickness * rFrac;
23577
- } else {
23578
- var extraThickness = outerThickness - thickPx;
23579
- marginOpts.l = extraThickness * lFrac;
23580
- marginOpts.r = extraThickness * rFrac;
23581
- marginOpts.xl = optsX - thickness * lFrac;
23582
- marginOpts.xr = optsX + thickness * rFrac;
23798
+ var extraThickness = outerThickness - thickPx;
23799
+ if(isVertical) {
23800
+ if(lenmode === 'pixels') {
23801
+ marginOpts.y = optsY;
23802
+ marginOpts.t = lenPx * tFrac;
23803
+ marginOpts.b = lenPx * bFrac;
23804
+ } else {
23805
+ marginOpts.t = marginOpts.b = 0;
23806
+ marginOpts.yt = optsY + len * tFrac;
23807
+ marginOpts.yb = optsY - len * bFrac;
23808
+ }
23809
+
23810
+ if(thicknessmode === 'pixels') {
23811
+ marginOpts.x = optsX;
23812
+ marginOpts.l = outerThickness * lFrac;
23813
+ marginOpts.r = outerThickness * rFrac;
23814
+ } else {
23815
+ marginOpts.l = extraThickness * lFrac;
23816
+ marginOpts.r = extraThickness * rFrac;
23817
+ marginOpts.xl = optsX - thickness * lFrac;
23818
+ marginOpts.xr = optsX + thickness * rFrac;
23819
+ }
23820
+ } else { // horizontal colorbars
23821
+ if(lenmode === 'pixels') {
23822
+ marginOpts.x = optsX;
23823
+ marginOpts.l = lenPx * lFrac;
23824
+ marginOpts.r = lenPx * rFrac;
23825
+ } else {
23826
+ marginOpts.l = marginOpts.r = 0;
23827
+ marginOpts.xl = optsX + len * lFrac;
23828
+ marginOpts.xr = optsX - len * rFrac;
23829
+ }
23830
+
23831
+ if(thicknessmode === 'pixels') {
23832
+ marginOpts.y = 1 - optsY;
23833
+ marginOpts.t = outerThickness * tFrac;
23834
+ marginOpts.b = outerThickness * bFrac;
23835
+ } else {
23836
+ marginOpts.t = extraThickness * tFrac;
23837
+ marginOpts.b = extraThickness * bFrac;
23838
+ marginOpts.yt = optsY - thickness * tFrac;
23839
+ marginOpts.yb = optsY + thickness * bFrac;
23840
+ }
23583
23841
  }
23584
23842
 
23585
23843
  Plots.autoMargin(gd, opts._id, marginOpts);
@@ -23596,6 +23854,7 @@ function drawColorBar(g, opts, gd) {
23596
23854
  }
23597
23855
 
23598
23856
  function makeEditable(g, opts, gd) {
23857
+ var isVertical = opts.orientation === 'v';
23599
23858
  var fullLayout = gd._fullLayout;
23600
23859
  var gs = fullLayout._size;
23601
23860
  var t0, xf, yf;
@@ -23610,9 +23869,13 @@ function makeEditable(g, opts, gd) {
23610
23869
  moveFn: function(dx, dy) {
23611
23870
  g.attr('transform', t0 + strTranslate(dx, dy));
23612
23871
 
23613
- xf = dragElement.align(opts._uFrac + (dx / gs.w), opts._thickFrac,
23872
+ xf = dragElement.align(
23873
+ (isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
23874
+ isVertical ? opts._thickFrac : opts._lenFrac,
23614
23875
  0, 1, opts.xanchor);
23615
- yf = dragElement.align(opts._vFrac - (dy / gs.h), opts._lenFrac,
23876
+ yf = dragElement.align(
23877
+ (isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
23878
+ isVertical ? opts._lenFrac : opts._thickFrac,
23616
23879
  0, 1, opts.yanchor);
23617
23880
 
23618
23881
  var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
@@ -23689,6 +23952,8 @@ function calcLevels(gd, opts, zrange) {
23689
23952
  function mockColorBarAxis(gd, opts, zrange) {
23690
23953
  var fullLayout = gd._fullLayout;
23691
23954
 
23955
+ var isVertical = opts.orientation === 'v';
23956
+
23692
23957
  var cbAxisIn = {
23693
23958
  type: 'linear',
23694
23959
  range: zrange,
@@ -23719,17 +23984,19 @@ function mockColorBarAxis(gd, opts, zrange) {
23719
23984
  title: opts.title,
23720
23985
  showline: true,
23721
23986
  anchor: 'free',
23722
- side: 'right',
23987
+ side: isVertical ? 'right' : 'bottom',
23723
23988
  position: 1
23724
23989
  };
23725
23990
 
23991
+ var letter = isVertical ? 'y' : 'x';
23992
+
23726
23993
  var cbAxisOut = {
23727
23994
  type: 'linear',
23728
- _id: 'y' + opts._id
23995
+ _id: letter + opts._id
23729
23996
  };
23730
23997
 
23731
23998
  var axisOptions = {
23732
- letter: 'y',
23999
+ letter: letter,
23733
24000
  font: fullLayout.font,
23734
24001
  noHover: true,
23735
24002
  noTickson: true,
@@ -29342,7 +29609,9 @@ function createHoverText(hoverData, opts) {
29342
29609
  orientation: 'v'
29343
29610
  }
29344
29611
  };
29345
- var mockLayoutOut = {};
29612
+ var mockLayoutOut = {
29613
+ font: font
29614
+ };
29346
29615
  legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
29347
29616
  var mockLegend = mockLayoutOut.legend;
29348
29617
 
@@ -29383,7 +29652,8 @@ function createHoverText(hoverData, opts) {
29383
29652
 
29384
29653
  // Draw unified hover label
29385
29654
  mockLegend._inHover = true;
29386
- mockLegend._groupTitleFont = font;
29655
+ mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
29656
+
29387
29657
  legendDraw(gd, mockLegend);
29388
29658
 
29389
29659
  // Position the hover
@@ -30385,9 +30655,11 @@ var isUnifiedHover = _dereq_('./helpers').isUnifiedHover;
30385
30655
  module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
30386
30656
  opts = opts || {};
30387
30657
 
30658
+ var hasLegend = contOut.legend;
30659
+
30388
30660
  function inheritFontAttr(attr) {
30389
30661
  if(!opts.font[attr]) {
30390
- opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
30662
+ opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
30391
30663
  }
30392
30664
  }
30393
30665
 
@@ -30398,7 +30670,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
30398
30670
  inheritFontAttr('family');
30399
30671
  inheritFontAttr('color');
30400
30672
 
30401
- if(contOut.legend) {
30673
+ if(hasLegend) {
30402
30674
  if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
30403
30675
  if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
30404
30676
  } else {
@@ -30507,11 +30779,13 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
30507
30779
 
30508
30780
  var constants = _dereq_('./constants');
30509
30781
 
30510
- var fontAttrs = _dereq_('../../plots/font_attributes')({
30782
+ var fontAttrs = _dereq_('../../plots/font_attributes');
30783
+
30784
+ var font = fontAttrs({
30511
30785
  editType: 'none',
30512
30786
  });
30513
- fontAttrs.family.dflt = constants.HOVERFONT;
30514
- fontAttrs.size.dflt = constants.HOVERFONTSIZE;
30787
+ font.family.dflt = constants.HOVERFONT;
30788
+ font.size.dflt = constants.HOVERFONTSIZE;
30515
30789
 
30516
30790
  module.exports = {
30517
30791
  clickmode: {
@@ -30567,7 +30841,10 @@ module.exports = {
30567
30841
  valType: 'color',
30568
30842
  editType: 'none',
30569
30843
  },
30570
- font: fontAttrs,
30844
+ font: font,
30845
+ grouptitlefont: fontAttrs({
30846
+ editType: 'none',
30847
+ }),
30571
30848
  align: {
30572
30849
  valType: 'enumerated',
30573
30850
  values: ['left', 'right', 'auto'],
@@ -30580,6 +30857,7 @@ module.exports = {
30580
30857
  dflt: 15,
30581
30858
  editType: 'none',
30582
30859
  },
30860
+
30583
30861
  editType: 'none'
30584
30862
  },
30585
30863
  selectdirection: {
@@ -30627,6 +30905,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
30627
30905
  }
30628
30906
 
30629
30907
  handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
30908
+
30909
+ Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
30630
30910
  };
30631
30911
 
30632
30912
  },{"../../lib":242,"./hoverlabel_defaults":149,"./hovermode_defaults":150,"./layout_attributes":152}],154:[function(_dereq_,module,exports){
@@ -31510,6 +31790,9 @@ module.exports = {
31510
31790
  font: fontAttrs({
31511
31791
  editType: 'legend',
31512
31792
  }),
31793
+ grouptitlefont: fontAttrs({
31794
+ editType: 'legend',
31795
+ }),
31513
31796
  orientation: {
31514
31797
  valType: 'enumerated',
31515
31798
  values: ['v', 'h'],
@@ -31633,6 +31916,7 @@ var Registry = _dereq_('../../registry');
31633
31916
  var Lib = _dereq_('../../lib');
31634
31917
  var Template = _dereq_('../../plot_api/plot_template');
31635
31918
 
31919
+ var plotsAttrs = _dereq_('../../plots/attributes');
31636
31920
  var attributes = _dereq_('./attributes');
31637
31921
  var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes');
31638
31922
  var helpers = _dereq_('./helpers');
@@ -31640,13 +31924,30 @@ var helpers = _dereq_('./helpers');
31640
31924
 
31641
31925
  module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31642
31926
  var containerIn = layoutIn.legend || {};
31927
+ var containerOut = Template.newContainer(layoutOut, 'legend');
31928
+
31929
+ function coerce(attr, dflt) {
31930
+ return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
31931
+ }
31932
+
31933
+ var trace;
31934
+ var traceCoerce = function(attr, dflt) {
31935
+ var traceIn = trace._input;
31936
+ var traceOut = trace;
31937
+ return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
31938
+ };
31939
+
31940
+ var globalFont = layoutOut.font || {};
31941
+ var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
31942
+ size: Math.round(globalFont.size * 1.1)
31943
+ }));
31643
31944
 
31644
31945
  var legendTraceCount = 0;
31645
31946
  var legendReallyHasATrace = false;
31646
31947
  var defaultOrder = 'normal';
31647
31948
 
31648
31949
  for(var i = 0; i < fullData.length; i++) {
31649
- var trace = fullData[i];
31950
+ trace = fullData[i];
31650
31951
 
31651
31952
  if(!trace.visible) continue;
31652
31953
 
@@ -31673,6 +31974,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31673
31974
  legendTraceCount++;
31674
31975
  }
31675
31976
  }
31977
+
31978
+ Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
31676
31979
  }
31677
31980
 
31678
31981
  if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -31691,13 +31994,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31691
31994
  basePlotLayoutAttributes, 'showlegend',
31692
31995
  legendReallyHasATrace && legendTraceCount > 1);
31693
31996
 
31694
- if(showLegend === false && !containerIn.uirevision) return;
31695
-
31696
- var containerOut = Template.newContainer(layoutOut, 'legend');
31997
+ // delete legend
31998
+ if(showLegend === false) layoutOut.legend = undefined;
31697
31999
 
31698
- function coerce(attr, dflt) {
31699
- return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
31700
- }
32000
+ if(showLegend === false && !containerIn.uirevision) return;
31701
32001
 
31702
32002
  coerce('uirevision', layoutOut.uirevision);
31703
32003
 
@@ -31759,7 +32059,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
31759
32059
  }
31760
32060
  };
31761
32061
 
31762
- },{"../../lib":242,"../../plot_api/plot_template":278,"../../plots/layout_attributes":324,"../../registry":328,"./attributes":161,"./helpers":167}],164:[function(_dereq_,module,exports){
32062
+ },{"../../lib":242,"../../plot_api/plot_template":278,"../../plots/attributes":285,"../../plots/layout_attributes":324,"../../registry":328,"./attributes":161,"./helpers":167}],164:[function(_dereq_,module,exports){
31763
32063
  'use strict';
31764
32064
 
31765
32065
  var d3 = _dereq_('@plotly/d3');
@@ -40211,8 +40511,10 @@ function draw(gd, titleClass, options) {
40211
40511
 
40212
40512
  var elShouldExist = txt || editable;
40213
40513
 
40514
+ var hColorbarMoveTitle;
40214
40515
  if(!group) {
40215
40516
  group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass);
40517
+ hColorbarMoveTitle = fullLayout._hColorbarMoveTitle;
40216
40518
  }
40217
40519
 
40218
40520
  var el = group.selectAll('text')
@@ -40236,13 +40538,17 @@ function draw(gd, titleClass, options) {
40236
40538
  function drawTitle(titleEl) {
40237
40539
  var transformVal;
40238
40540
 
40541
+ if(!transform && hColorbarMoveTitle) {
40542
+ transform = {};
40543
+ }
40544
+
40239
40545
  if(transform) {
40240
40546
  transformVal = '';
40241
40547
  if(transform.rotate) {
40242
40548
  transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')';
40243
40549
  }
40244
- if(transform.offset) {
40245
- transformVal += strTranslate(0, transform.offset);
40550
+ if(transform.offset || hColorbarMoveTitle) {
40551
+ transformVal += strTranslate(0, (transform.offset || 0) - (hColorbarMoveTitle || 0));
40246
40552
  }
40247
40553
  } else {
40248
40554
  transformVal = null;
@@ -51714,7 +52020,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
51714
52020
  if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
51715
52021
  (typeof value === 'string' || typeof value === 'number')) {
51716
52022
  replace(key, key.replace('title', 'title.text'));
51717
- } else if(key.indexOf('titlefont') > -1) {
52023
+ } else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
51718
52024
  replace(key, key.replace('titlefont', 'title.font'));
51719
52025
  } else if(key.indexOf('titleposition') > -1) {
51720
52026
  replace(key, key.replace('titleposition', 'title.position'));
@@ -69582,6 +69888,9 @@ module.exports = function(opts) {
69582
69888
  // TODO - that's uber hacky... better solution?
69583
69889
  };
69584
69890
 
69891
+ if(opts.autoSize) attrs.size.dflt = 'auto';
69892
+ if(opts.autoColor) attrs.color.dflt = 'auto';
69893
+
69585
69894
  if(opts.arrayOk) {
69586
69895
  attrs.family.arrayOk = true;
69587
69896
  attrs.size.arrayOk = true;
@@ -69941,6 +70250,7 @@ module.exports = {
69941
70250
  valType: 'boolean',
69942
70251
  editType: 'legend',
69943
70252
  },
70253
+
69944
70254
  colorway: {
69945
70255
  valType: 'colorlist',
69946
70256
  dflt: colorAttrs.defaults,
@@ -71353,13 +71663,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
71353
71663
  );
71354
71664
 
71355
71665
  coerce('legendgroup');
71356
- var titleText = coerce('legendgrouptitle.text');
71357
- if(titleText) {
71358
- Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
71359
- size: Math.round(layout.font.size * 1.1) // default to larger font size
71360
- }));
71361
- }
71362
-
71666
+ coerce('legendgrouptitle.text');
71363
71667
  coerce('legendrank');
71364
71668
 
71365
71669
  traceOut._dfltShowLegend = true;
@@ -71507,16 +71811,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
71507
71811
 
71508
71812
  coerce('autotypenumbers');
71509
71813
 
71510
- var globalFont = Lib.coerceFont(coerce, 'font');
71511
-
71512
- coerce('title.text', layoutOut._dfltTitle.plot);
71814
+ var font = Lib.coerceFont(coerce, 'font');
71815
+ var fontSize = font.size;
71513
71816
 
71514
- Lib.coerceFont(coerce, 'title.font', {
71515
- family: globalFont.family,
71516
- size: Math.round(globalFont.size * 1.4),
71517
- color: globalFont.color
71518
- });
71817
+ Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
71818
+ size: Math.round(fontSize * 1.4)
71819
+ }));
71519
71820
 
71821
+ coerce('title.text', layoutOut._dfltTitle.plot);
71520
71822
  coerce('title.xref');
71521
71823
  coerce('title.yref');
71522
71824
  coerce('title.x');
@@ -77054,12 +77356,14 @@ function calcTexttemplate(fullLayout, cd, index, xa, ya) {
77054
77356
  var trace = cd[0].trace;
77055
77357
  var texttemplate = Lib.castOption(trace, index, 'texttemplate');
77056
77358
  if(!texttemplate) return '';
77359
+ var isHistogram = (trace.type === 'histogram');
77057
77360
  var isWaterfall = (trace.type === 'waterfall');
77058
77361
  var isFunnel = (trace.type === 'funnel');
77362
+ var isHorizontal = trace.orientation === 'h';
77059
77363
 
77060
77364
  var pLetter, pAxis;
77061
77365
  var vLetter, vAxis;
77062
- if(trace.orientation === 'h') {
77366
+ if(isHorizontal) {
77063
77367
  pLetter = 'y';
77064
77368
  pAxis = ya;
77065
77369
  vLetter = 'x';
@@ -77094,6 +77398,11 @@ function calcTexttemplate(fullLayout, cd, index, xa, ya) {
77094
77398
  var pt = {};
77095
77399
  appendArrayPointValue(pt, trace, cdi.i);
77096
77400
 
77401
+ if(isHistogram || pt.x === undefined) pt.x = isHorizontal ? obj.value : obj.label;
77402
+ if(isHistogram || pt.y === undefined) pt.y = isHorizontal ? obj.label : obj.value;
77403
+ if(isHistogram || pt.xLabel === undefined) pt.xLabel = isHorizontal ? obj.valueLabel : obj.labelLabel;
77404
+ if(isHistogram || pt.yLabel === undefined) pt.yLabel = isHorizontal ? obj.labelLabel : obj.valueLabel;
77405
+
77097
77406
  if(isWaterfall) {
77098
77407
  obj.delta = +cdi.rawS || cdi.s;
77099
77408
  obj.deltaLabel = formatNumber(obj.delta);
@@ -80528,8 +80837,9 @@ var getBinSpanLabelRound = _dereq_('./bin_label_vals');
80528
80837
  function calc(gd, trace) {
80529
80838
  var pos = [];
80530
80839
  var size = [];
80531
- var pa = Axes.getFromId(gd, trace.orientation === 'h' ? trace.yaxis : trace.xaxis);
80532
- var mainData = trace.orientation === 'h' ? 'y' : 'x';
80840
+ var isHorizontal = trace.orientation === 'h';
80841
+ var pa = Axes.getFromId(gd, isHorizontal ? trace.yaxis : trace.xaxis);
80842
+ var mainData = isHorizontal ? 'y' : 'x';
80533
80843
  var counterData = {x: 'y', y: 'x'}[mainData];
80534
80844
  var calendar = trace[mainData + 'calendar'];
80535
80845
  var cumulativeSpec = trace.cumulative;
@@ -83888,7 +84198,6 @@ function calc(gd, trace) {
83888
84198
  v = vals[i];
83889
84199
  if(!isNumeric(v)) continue;
83890
84200
  v = +v;
83891
- if(v < 0) continue;
83892
84201
  } else v = 1;
83893
84202
 
83894
84203
  label = labels[i];
@@ -83925,6 +84234,9 @@ function calc(gd, trace) {
83925
84234
  }
83926
84235
  }
83927
84236
 
84237
+ // Drop aggregate sums of value 0 or less
84238
+ cd = cd.filter(function(elem) { return elem.v >= 0; });
84239
+
83928
84240
  var shouldSort = (trace.type === 'funnelarea') ? isAggregated : trace.sort;
83929
84241
  if(shouldSort) cd.sort(function(a, b) { return b.v - a.v; });
83930
84242
 
@@ -90306,7 +90618,7 @@ function getSortFunc(opts, d2c) {
90306
90618
  'use strict';
90307
90619
 
90308
90620
  // package version injected by `npm run preprocess`
90309
- exports.version = '2.7.0';
90621
+ exports.version = '2.8.3';
90310
90622
 
90311
90623
  },{}]},{},[12])(12)
90312
90624
  });