plotly.js 2.6.2 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +3 -3
  3. package/dist/README.md +26 -26
  4. package/dist/plot-schema.json +1015 -407
  5. package/dist/plotly-basic.js +568 -225
  6. package/dist/plotly-basic.min.js +4 -4
  7. package/dist/plotly-cartesian.js +1029 -371
  8. package/dist/plotly-cartesian.min.js +3 -3
  9. package/dist/plotly-finance.js +618 -227
  10. package/dist/plotly-finance.min.js +4 -4
  11. package/dist/plotly-geo-assets.js +2 -2
  12. package/dist/plotly-geo.js +564 -223
  13. package/dist/plotly-geo.min.js +2 -2
  14. package/dist/plotly-gl2d.js +580 -224
  15. package/dist/plotly-gl2d.min.js +2 -2
  16. package/dist/plotly-gl3d.js +564 -223
  17. package/dist/plotly-gl3d.min.js +2 -2
  18. package/dist/plotly-mapbox.js +570 -226
  19. package/dist/plotly-mapbox.min.js +2 -2
  20. package/dist/plotly-strict.js +1253 -592
  21. package/dist/plotly-strict.min.js +3 -3
  22. package/dist/plotly-with-meta.js +1345 -654
  23. package/dist/plotly.js +1307 -646
  24. package/dist/plotly.min.js +10 -10
  25. package/package.json +9 -9
  26. package/src/components/colorbar/attributes.js +29 -20
  27. package/src/components/colorbar/defaults.js +30 -8
  28. package/src/components/colorbar/draw.js +398 -141
  29. package/src/components/drawing/index.js +6 -3
  30. package/src/components/fx/hover.js +16 -17
  31. package/src/components/fx/hoverlabel_defaults.js +4 -2
  32. package/src/components/fx/layout_attributes.js +14 -4
  33. package/src/components/fx/layout_defaults.js +2 -0
  34. package/src/components/legend/attributes.js +7 -0
  35. package/src/components/legend/defaults.js +24 -7
  36. package/src/components/titles/index.js +8 -2
  37. package/src/plot_api/plot_api.js +38 -9
  38. package/src/plots/font_attributes.js +3 -0
  39. package/src/plots/layout_attributes.js +1 -0
  40. package/src/plots/mapbox/mapbox.js +6 -3
  41. package/src/plots/plots.js +7 -15
  42. package/src/traces/bar/plot.js +1 -1
  43. package/src/traces/contour/attributes.js +12 -0
  44. package/src/traces/contour/defaults.js +9 -1
  45. package/src/traces/heatmap/attributes.js +16 -0
  46. package/src/traces/heatmap/defaults.js +2 -0
  47. package/src/traces/heatmap/label_defaults.js +13 -0
  48. package/src/traces/heatmap/plot.js +203 -4
  49. package/src/traces/histogram/attributes.js +40 -0
  50. package/src/traces/histogram/defaults.js +11 -0
  51. package/src/traces/histogram2d/attributes.js +8 -0
  52. package/src/traces/histogram2d/defaults.js +4 -0
  53. package/src/traces/histogram2dcontour/attributes.js +3 -1
  54. package/src/traces/histogram2dcontour/defaults.js +8 -1
  55. package/src/traces/pie/calc.js +3 -1
  56. package/src/version.js +1 -1
  57. package/tasks/test_mock.js +1 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * plotly.js (mapbox) v2.6.2
2
+ * plotly.js (mapbox) v2.8.0
3
3
  * Copyright 2012-2021, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -68827,13 +68827,11 @@ var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
68827
68827
 
68828
68828
 
68829
68829
  module.exports = overrideAll({
68830
- // TODO: only right is supported currently
68831
- // orient: {
68832
- // valType: 'enumerated',
68833
- // values: ['left', 'right', 'top', 'bottom'],
68834
- // dflt: 'right',
68835
- //
68836
- // },
68830
+ orientation: {
68831
+ valType: 'enumerated',
68832
+ values: ['h', 'v'],
68833
+ dflt: 'v',
68834
+ },
68837
68835
  thicknessmode: {
68838
68836
  valType: 'enumerated',
68839
68837
  values: ['fraction', 'pixels'],
@@ -68856,14 +68854,12 @@ module.exports = overrideAll({
68856
68854
  },
68857
68855
  x: {
68858
68856
  valType: 'number',
68859
- dflt: 1.02,
68860
68857
  min: -2,
68861
68858
  max: 3,
68862
68859
  },
68863
68860
  xanchor: {
68864
68861
  valType: 'enumerated',
68865
68862
  values: ['left', 'center', 'right'],
68866
- dflt: 'left',
68867
68863
  },
68868
68864
  xpad: {
68869
68865
  valType: 'number',
@@ -68872,14 +68868,12 @@ module.exports = overrideAll({
68872
68868
  },
68873
68869
  y: {
68874
68870
  valType: 'number',
68875
- dflt: 0.5,
68876
68871
  min: -2,
68877
68872
  max: 3,
68878
68873
  },
68879
68874
  yanchor: {
68880
68875
  valType: 'enumerated',
68881
68876
  values: ['top', 'middle', 'bottom'],
68882
- dflt: 'middle',
68883
68877
  },
68884
68878
  ypad: {
68885
68879
  valType: 'number',
@@ -68911,15 +68905,21 @@ module.exports = overrideAll({
68911
68905
  ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}),
68912
68906
  ticklabeloverflow: extendFlat({}, axesAttrs.ticklabeloverflow, {
68913
68907
  }),
68908
+
68909
+ // ticklabelposition: not used directly, as values depend on orientation
68910
+ // left/right options are for x axes, and top/bottom options are for y axes
68914
68911
  ticklabelposition: {
68915
68912
  valType: 'enumerated',
68916
68913
  values: [
68917
68914
  'outside', 'inside',
68918
68915
  'outside top', 'inside top',
68916
+ 'outside left', 'inside left',
68917
+ 'outside right', 'inside right',
68919
68918
  'outside bottom', 'inside bottom'
68920
68919
  ],
68921
68920
  dflt: 'outside',
68922
68921
  },
68922
+
68923
68923
  ticklen: axesAttrs.ticklen,
68924
68924
  tickwidth: axesAttrs.tickwidth,
68925
68925
  tickcolor: axesAttrs.tickcolor,
@@ -68946,7 +68946,6 @@ module.exports = overrideAll({
68946
68946
  side: {
68947
68947
  valType: 'enumerated',
68948
68948
  values: ['right', 'top', 'bottom'],
68949
- dflt: 'top',
68950
68949
  }
68951
68950
  },
68952
68951
 
@@ -69005,23 +69004,30 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
69005
69004
  return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt);
69006
69005
  }
69007
69006
 
69007
+ var margin = layout.margin || {t: 0, b: 0, l: 0, r: 0};
69008
+ var w = layout.width - margin.l - margin.r;
69009
+ var h = layout.height - margin.t - margin.b;
69010
+
69011
+ var orientation = coerce('orientation');
69012
+ var isVertical = orientation === 'v';
69013
+
69008
69014
  var thicknessmode = coerce('thicknessmode');
69009
69015
  coerce('thickness', (thicknessmode === 'fraction') ?
69010
- 30 / (layout.width - layout.margin.l - layout.margin.r) :
69016
+ 30 / (isVertical ? w : h) :
69011
69017
  30
69012
69018
  );
69013
69019
 
69014
69020
  var lenmode = coerce('lenmode');
69015
69021
  coerce('len', (lenmode === 'fraction') ?
69016
69022
  1 :
69017
- layout.height - layout.margin.t - layout.margin.b
69023
+ isVertical ? h : w
69018
69024
  );
69019
69025
 
69020
- coerce('x');
69021
- coerce('xanchor');
69026
+ coerce('x', isVertical ? 1.02 : 0.5);
69027
+ coerce('xanchor', isVertical ? 'left' : 'center');
69022
69028
  coerce('xpad');
69023
- coerce('y');
69024
- coerce('yanchor');
69029
+ coerce('y', isVertical ? 0.5 : 1.02);
69030
+ coerce('yanchor', isVertical ? 'middle' : 'bottom');
69025
69031
  coerce('ypad');
69026
69032
  Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']);
69027
69033
 
@@ -69031,7 +69037,22 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
69031
69037
  coerce('borderwidth');
69032
69038
  coerce('bgcolor');
69033
69039
 
69034
- var ticklabelposition = coerce('ticklabelposition');
69040
+ var ticklabelposition = Lib.coerce(colorbarIn, colorbarOut, {
69041
+ ticklabelposition: {
69042
+ valType: 'enumerated',
69043
+ dflt: 'outside',
69044
+ values: isVertical ? [
69045
+ 'outside', 'inside',
69046
+ 'outside top', 'inside top',
69047
+ 'outside bottom', 'inside bottom'
69048
+ ] : [
69049
+ 'outside', 'inside',
69050
+ 'outside left', 'inside left',
69051
+ 'outside right', 'inside right'
69052
+ ]
69053
+ }
69054
+ }, 'ticklabelposition');
69055
+
69035
69056
  coerce('ticklabeloverflow', ticklabelposition.indexOf('inside') !== -1 ? 'hide past domain' : 'hide past div');
69036
69057
 
69037
69058
  handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear');
@@ -69053,7 +69074,7 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
69053
69074
  size: Lib.bigFont(tickFont.size)
69054
69075
  });
69055
69076
  Lib.coerceFont(coerce, 'title.font', dfltTitleFont);
69056
- coerce('title.side');
69077
+ coerce('title.side', isVertical ? 'top' : 'right');
69057
69078
  };
69058
69079
 
69059
69080
  },{"../../lib":246,"../../plot_api/plot_template":282,"../../plots/cartesian/prefix_suffix_defaults":312,"../../plots/cartesian/tick_label_defaults":317,"../../plots/cartesian/tick_mark_defaults":318,"../../plots/cartesian/tick_value_defaults":319,"./attributes":115}],118:[function(_dereq_,module,exports){
@@ -69226,6 +69247,21 @@ function makeColorBarData(gd) {
69226
69247
  }
69227
69248
 
69228
69249
  function drawColorBar(g, opts, gd) {
69250
+ var isVertical = opts.orientation === 'v';
69251
+ var len = opts.len;
69252
+ var lenmode = opts.lenmode;
69253
+ var thickness = opts.thickness;
69254
+ var thicknessmode = opts.thicknessmode;
69255
+ var outlinewidth = opts.outlinewidth;
69256
+ var borderwidth = opts.borderwidth;
69257
+ var bgcolor = opts.bgcolor;
69258
+ var xanchor = opts.xanchor;
69259
+ var yanchor = opts.yanchor;
69260
+ var xpad = opts.xpad;
69261
+ var ypad = opts.ypad;
69262
+ var optsX = opts.x;
69263
+ var optsY = isVertical ? opts.y : 1 - opts.y;
69264
+
69229
69265
  var fullLayout = gd._fullLayout;
69230
69266
  var gs = fullLayout._size;
69231
69267
 
@@ -69255,42 +69291,64 @@ function drawColorBar(g, opts, gd) {
69255
69291
  // when the colorbar itself is pushing the margins.
69256
69292
  // but then the fractional size is calculated based on the
69257
69293
  // actual graph size, so that the axes will size correctly.
69258
- var thickPx = Math.round(opts.thickness * (opts.thicknessmode === 'fraction' ? gs.w : 1));
69259
- var thickFrac = thickPx / gs.w;
69260
- var lenPx = Math.round(opts.len * (opts.lenmode === 'fraction' ? gs.h : 1));
69261
- var lenFrac = lenPx / gs.h;
69262
- var xpadFrac = opts.xpad / gs.w;
69263
- var yExtraPx = (opts.borderwidth + opts.outlinewidth) / 2;
69264
- var ypadFrac = opts.ypad / gs.h;
69294
+ var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
69295
+ var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
69296
+ var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
69297
+ var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
69265
69298
 
69266
69299
  // x positioning: do it initially just for left anchor,
69267
69300
  // then fix at the end (since we don't know the width yet)
69268
- var xLeft = Math.round(opts.x * gs.w + opts.xpad);
69269
- // for dragging... this is getting a little muddled...
69270
- var xLeftFrac = opts.x - thickFrac * ({center: 0.5, right: 1}[opts.xanchor] || 0);
69301
+ var uPx = Math.round(isVertical ?
69302
+ optsX * gs.w + xpad :
69303
+ optsY * gs.h + ypad
69304
+ );
69271
69305
 
69272
- // y positioning we can do correctly from the start
69273
- var yBottomFrac = opts.y + lenFrac * (({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5);
69274
- var yBottomPx = Math.round(gs.h * (1 - yBottomFrac));
69275
- var yTopPx = yBottomPx - lenPx;
69306
+ var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
69307
+ var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
69308
+
69309
+ // for dragging... this is getting a little muddled...
69310
+ var uFrac = isVertical ?
69311
+ optsX - xRatio * thickFrac :
69312
+ optsY - yRatio * thickFrac;
69313
+
69314
+ // y/x positioning (for v/h) we can do correctly from the start
69315
+ var vFrac = isVertical ?
69316
+ optsY - yRatio * lenFrac :
69317
+ optsX - xRatio * lenFrac;
69318
+
69319
+ var vPx = Math.round(isVertical ?
69320
+ gs.h * (1 - vFrac) :
69321
+ gs.w * vFrac
69322
+ );
69276
69323
 
69277
69324
  // stash a few things for makeEditable
69278
69325
  opts._lenFrac = lenFrac;
69279
69326
  opts._thickFrac = thickFrac;
69280
- opts._xLeftFrac = xLeftFrac;
69281
- opts._yBottomFrac = yBottomFrac;
69327
+ opts._uFrac = uFrac;
69328
+ opts._vFrac = vFrac;
69282
69329
 
69283
69330
  // stash mocked axis for contour label formatting
69284
69331
  var ax = opts._axis = mockColorBarAxis(gd, opts, zrange);
69285
69332
 
69286
69333
  // position can't go in through supplyDefaults
69287
69334
  // because that restricts it to [0,1]
69288
- ax.position = opts.x + xpadFrac + thickFrac;
69335
+ ax.position = thickFrac + (isVertical ?
69336
+ optsX + xpad / gs.w :
69337
+ optsY + ypad / gs.h
69338
+ );
69339
+
69340
+ var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
69341
+
69342
+ if(isVertical && topOrBottom) {
69343
+ ax.title.side = titleSide;
69344
+ ax.titlex = optsX + xpad / gs.w;
69345
+ ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
69346
+ }
69289
69347
 
69290
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
69348
+ if(!isVertical && !topOrBottom) {
69291
69349
  ax.title.side = titleSide;
69292
- ax.titlex = opts.x + xpadFrac;
69293
- ax.titley = yBottomFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac);
69350
+ ax.titley = optsY + ypad / gs.h;
69351
+ ax.titlex = vFrac + xpad / gs.w; // right side
69294
69352
  }
69295
69353
 
69296
69354
  if(line.color && opts.tickmode === 'auto') {
@@ -69298,7 +69356,7 @@ function drawColorBar(g, opts, gd) {
69298
69356
  ax.tick0 = levelsIn.start;
69299
69357
  var dtick = levelsIn.size;
69300
69358
  // expand if too many contours, so we don't get too many ticks
69301
- var autoNtick = Lib.constrain((yBottomPx - yTopPx) / 50, 4, 15) + 1;
69359
+ var autoNtick = Lib.constrain(lenPx / 50, 4, 15) + 1;
69302
69360
  var dtFactor = (zrange[1] - zrange[0]) / ((opts.nticks || autoNtick) * dtick);
69303
69361
  if(dtFactor > 1) {
69304
69362
  var dtexp = Math.pow(10, Math.floor(Math.log(dtFactor) / Math.LN10));
@@ -69315,9 +69373,12 @@ function drawColorBar(g, opts, gd) {
69315
69373
 
69316
69374
  // set domain after init, because we may want to
69317
69375
  // allow it outside [0,1]
69318
- ax.domain = [
69319
- yBottomFrac + ypadFrac,
69320
- yBottomFrac + lenFrac - ypadFrac
69376
+ ax.domain = isVertical ? [
69377
+ vFrac + ypad / gs.h,
69378
+ vFrac + lenFrac - ypad / gs.h
69379
+ ] : [
69380
+ vFrac + xpad / gs.w,
69381
+ vFrac + lenFrac - xpad / gs.w
69321
69382
  ];
69322
69383
 
69323
69384
  ax.setScale();
@@ -69327,9 +69388,13 @@ function drawColorBar(g, opts, gd) {
69327
69388
  var titleCont = g.select('.' + cn.cbtitleunshift)
69328
69389
  .attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
69329
69390
 
69391
+ var ticklabelposition = ax.ticklabelposition;
69392
+ var titleFontSize = ax.title.font.size;
69393
+
69330
69394
  var axLayer = g.select('.' + cn.cbaxis);
69331
69395
  var titleEl;
69332
69396
  var titleHeight = 0;
69397
+ var titleWidth = 0;
69333
69398
 
69334
69399
  function drawTitle(titleClass, titleOpts) {
69335
69400
  var dfltTitleOpts = {
@@ -69354,58 +69419,102 @@ function drawColorBar(g, opts, gd) {
69354
69419
  }
69355
69420
 
69356
69421
  function drawDummyTitle() {
69357
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
69358
- // draw the title so we know how much room it needs
69359
- // when we squish the axis. This one only applies to
69360
- // top or bottom titles, not right side.
69361
- var x = gs.l + (opts.x + xpadFrac) * gs.w;
69362
- var fontSize = ax.title.font.size;
69363
- var y;
69422
+ // draw the title so we know how much room it needs
69423
+ // when we squish the axis.
69424
+ // On vertical colorbars this only applies to top or bottom titles, not right side.
69425
+ // On horizontal colorbars this only applies to right, etc.
69426
+
69427
+ if(
69428
+ (isVertical && topOrBottom) ||
69429
+ (!isVertical && !topOrBottom)
69430
+ ) {
69431
+ var x, y;
69364
69432
 
69365
69433
  if(titleSide === 'top') {
69366
- y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h +
69367
- gs.t + 3 + fontSize * 0.75;
69368
- } else {
69369
- y = (1 - (yBottomFrac + ypadFrac)) * gs.h +
69370
- gs.t - 3 - fontSize * 0.25;
69434
+ x = xpad + gs.l + gs.w * optsX;
69435
+ y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
69371
69436
  }
69437
+
69438
+ if(titleSide === 'bottom') {
69439
+ x = xpad + gs.l + gs.w * optsX;
69440
+ y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
69441
+ }
69442
+
69443
+ if(titleSide === 'right') {
69444
+ y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
69445
+ x = xpad + gs.l + gs.w * vFrac;
69446
+ }
69447
+
69372
69448
  drawTitle(ax._id + 'title', {
69373
- attributes: {x: x, y: y, 'text-anchor': 'start'}
69449
+ attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
69374
69450
  });
69375
69451
  }
69376
69452
  }
69377
69453
 
69378
69454
  function drawCbTitle() {
69379
- if(['top', 'bottom'].indexOf(titleSide) === -1) {
69380
- var fontSize = ax.title.font.size;
69381
- var y = ax._offset + ax._length / 2;
69382
- var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ?
69383
- 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) :
69384
- -10 - fontSize * ((ax.showticklabels ? 0.5 : 0)));
69385
-
69386
- // the 'h' + is a hack to get around the fact that
69387
- // convertToTspans rotates any 'y...' class by 90 degrees.
69388
- // TODO: find a better way to control this.
69389
- drawTitle('h' + ax._id + 'title', {
69455
+ if(
69456
+ (isVertical && !topOrBottom) ||
69457
+ (!isVertical && topOrBottom)
69458
+ ) {
69459
+ var pos = ax.position || 0;
69460
+ var mid = ax._offset + ax._length / 2;
69461
+ var x, y;
69462
+
69463
+ if(titleSide === 'right') {
69464
+ y = mid;
69465
+ x = gs.l + gs.w * pos + 10 + titleFontSize * (
69466
+ ax.showticklabels ? 1 : 0.5
69467
+ );
69468
+ } else {
69469
+ x = mid;
69470
+
69471
+ if(titleSide === 'bottom') {
69472
+ y = gs.t + gs.h * pos + 10 + (
69473
+ ticklabelposition.indexOf('inside') === -1 ?
69474
+ ax.tickfont.size :
69475
+ 0
69476
+ ) + (
69477
+ ax.ticks !== 'intside' ?
69478
+ opts.ticklen || 0 :
69479
+ 0
69480
+ );
69481
+ }
69482
+
69483
+ if(titleSide === 'top') {
69484
+ var nlines = title.text.split('<br>').length;
69485
+ y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
69486
+ }
69487
+ }
69488
+
69489
+ drawTitle((isVertical ?
69490
+ // the 'h' + is a hack to get around the fact that
69491
+ // convertToTspans rotates any 'y...' class by 90 degrees.
69492
+ // TODO: find a better way to control this.
69493
+ 'h' :
69494
+ 'v'
69495
+ ) + ax._id + 'title', {
69390
69496
  avoid: {
69391
69497
  selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
69392
69498
  side: titleSide,
69393
- offsetLeft: gs.l,
69394
- offsetTop: 0,
69395
- maxShift: fullLayout.width
69499
+ offsetTop: isVertical ? 0 : gs.t,
69500
+ offsetLeft: isVertical ? gs.l : 0,
69501
+ maxShift: isVertical ? fullLayout.width : fullLayout.height
69396
69502
  },
69397
69503
  attributes: {x: x, y: y, 'text-anchor': 'middle'},
69398
- transform: {rotate: '-90', offset: 0}
69504
+ transform: {rotate: isVertical ? -90 : 0, offset: 0}
69399
69505
  });
69400
69506
  }
69401
69507
  }
69402
69508
 
69403
69509
  function drawAxis() {
69404
- if(['top', 'bottom'].indexOf(titleSide) !== -1) {
69510
+ if(
69511
+ (!isVertical && !topOrBottom) ||
69512
+ (isVertical && topOrBottom)
69513
+ ) {
69405
69514
  // squish the axis top to make room for the title
69406
69515
  var titleGroup = g.select('.' + cn.cbtitle);
69407
69516
  var titleText = titleGroup.select('text');
69408
- var titleTrans = [-opts.outlinewidth / 2, opts.outlinewidth / 2];
69517
+ var titleTrans = [-outlinewidth / 2, outlinewidth / 2];
69409
69518
  var mathJaxNode = titleGroup
69410
69519
  .select('.h' + ax._id + 'title-math-group')
69411
69520
  .node();
@@ -69413,39 +69522,63 @@ function drawColorBar(g, opts, gd) {
69413
69522
  if(titleText.node()) {
69414
69523
  lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
69415
69524
  }
69525
+
69526
+ var bb;
69416
69527
  if(mathJaxNode) {
69417
- titleHeight = Drawing.bBox(mathJaxNode).height;
69528
+ bb = Drawing.bBox(mathJaxNode);
69529
+ titleWidth = bb.width;
69530
+ titleHeight = bb.height;
69418
69531
  if(titleHeight > lineSize) {
69419
69532
  // not entirely sure how mathjax is doing
69420
69533
  // vertical alignment, but this seems to work.
69421
69534
  titleTrans[1] -= (titleHeight - lineSize) / 2;
69422
69535
  }
69423
69536
  } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
69424
- titleHeight = Drawing.bBox(titleText.node()).height;
69537
+ bb = Drawing.bBox(titleText.node());
69538
+ titleWidth = bb.width;
69539
+ titleHeight = bb.height;
69425
69540
  }
69426
- if(titleHeight) {
69427
- // buffer btwn colorbar and title
69428
- // TODO: configurable
69429
- titleHeight += 5;
69430
69541
 
69431
- if(titleSide === 'top') {
69432
- ax.domain[1] -= titleHeight / gs.h;
69433
- titleTrans[1] *= -1;
69434
- } else {
69435
- ax.domain[0] += titleHeight / gs.h;
69436
- var nlines = svgTextUtils.lineCount(titleText);
69437
- titleTrans[1] += (1 - nlines) * lineSize;
69542
+ if(isVertical) {
69543
+ if(titleHeight) {
69544
+ // buffer btwn colorbar and title
69545
+ // TODO: configurable
69546
+ titleHeight += 5;
69547
+
69548
+ if(titleSide === 'top') {
69549
+ ax.domain[1] -= titleHeight / gs.h;
69550
+ titleTrans[1] *= -1;
69551
+ } else {
69552
+ ax.domain[0] += titleHeight / gs.h;
69553
+ var nlines = svgTextUtils.lineCount(titleText);
69554
+ titleTrans[1] += (1 - nlines) * lineSize;
69555
+ }
69556
+
69557
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
69558
+ ax.setScale();
69438
69559
  }
69560
+ } else { // horizontal colorbars
69561
+ if(titleWidth) {
69562
+ if(titleSide === 'right') {
69563
+ ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
69564
+ }
69439
69565
 
69440
- titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
69441
- ax.setScale();
69566
+ titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
69567
+ ax.setScale();
69568
+ }
69442
69569
  }
69443
69570
  }
69444
69571
 
69445
69572
  g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
69446
- .attr('transform', strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))));
69573
+ .attr('transform', isVertical ?
69574
+ strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
69575
+ strTranslate(Math.round(gs.w * ax.domain[0]), 0)
69576
+ );
69447
69577
 
69448
- axLayer.attr('transform', strTranslate(0, Math.round(-gs.t)));
69578
+ axLayer.attr('transform', isVertical ?
69579
+ strTranslate(0, Math.round(-gs.t)) :
69580
+ strTranslate(Math.round(-gs.l), 0)
69581
+ );
69449
69582
 
69450
69583
  var fills = g.select('.' + cn.cbfills)
69451
69584
  .selectAll('rect.' + cn.cbfill)
@@ -69471,20 +69604,22 @@ function drawColorBar(g, opts, gd) {
69471
69604
 
69472
69605
  // offset the side adjoining the next rectangle so they
69473
69606
  // overlap, to prevent antialiasing gaps
69474
- z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
69475
-
69607
+ if(isVertical) {
69608
+ z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
69609
+ } /* else {
69610
+ // TODO: horizontal case
69611
+ } */
69476
69612
 
69477
69613
  // Colorbar cannot currently support opacities so we
69478
69614
  // use an opaque fill even when alpha channels present
69479
- var fillEl = d3.select(this).attr({
69480
- x: xLeft,
69481
- width: Math.max(thickPx, 2),
69482
- y: d3.min(z),
69483
- height: Math.max(d3.max(z) - d3.min(z), 2),
69484
- });
69615
+ var fillEl = d3.select(this)
69616
+ .attr(isVertical ? 'x' : 'y', uPx)
69617
+ .attr(isVertical ? 'y' : 'x', d3.min(z))
69618
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
69619
+ .attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
69485
69620
 
69486
69621
  if(opts._fillgradient) {
69487
- Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
69622
+ Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
69488
69623
  } else {
69489
69624
  // tinycolor can't handle exponents and
69490
69625
  // at this scale, removing it makes no difference.
@@ -69500,17 +69635,23 @@ function drawColorBar(g, opts, gd) {
69500
69635
  .classed(cn.cbline, true);
69501
69636
  lines.exit().remove();
69502
69637
  lines.each(function(d) {
69638
+ var a = uPx;
69639
+ var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
69640
+
69503
69641
  d3.select(this)
69504
- .attr('d', 'M' + xLeft + ',' +
69505
- (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx)
69642
+ .attr('d', 'M' +
69643
+ (isVertical ? a + ',' + b : b + ',' + a) +
69644
+ (isVertical ? 'h' : 'v') +
69645
+ thickPx
69646
+ )
69506
69647
  .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
69507
69648
  });
69508
69649
 
69509
69650
  // force full redraw of labels and ticks
69510
69651
  axLayer.selectAll('g.' + ax._id + 'tick,path').remove();
69511
69652
 
69512
- var shift = xLeft + thickPx +
69513
- (opts.outlinewidth || 0) / 2 - (opts.ticks === 'outside' ? 1 : 0);
69653
+ var shift = uPx + thickPx +
69654
+ (outlinewidth || 0) / 2 - (opts.ticks === 'outside' ? 1 : 0);
69514
69655
 
69515
69656
  var vals = Axes.calcTicks(ax);
69516
69657
  var tickSign = Axes.getTickSigns(ax)[2];
@@ -69535,83 +69676,211 @@ function drawColorBar(g, opts, gd) {
69535
69676
  // TODO: why are we redrawing multiple times now with this?
69536
69677
  // I guess autoMargin doesn't like being post-promise?
69537
69678
  function positionCB() {
69538
- var innerWidth = thickPx + opts.outlinewidth / 2;
69539
- if(ax.ticklabelposition.indexOf('inside') === -1) {
69540
- innerWidth += Drawing.bBox(axLayer.node()).width;
69679
+ var bb;
69680
+ var innerThickness = thickPx + outlinewidth / 2;
69681
+ if(ticklabelposition.indexOf('inside') === -1) {
69682
+ bb = Drawing.bBox(axLayer.node());
69683
+ innerThickness += isVertical ? bb.width : bb.height;
69541
69684
  }
69542
69685
 
69543
69686
  titleEl = titleCont.select('text');
69544
69687
 
69688
+ var titleWidth = 0;
69689
+
69690
+ var topSideVertical = isVertical && titleSide === 'top';
69691
+ var rightSideHorizontal = !isVertical && titleSide === 'right';
69692
+
69693
+ var moveY = 0;
69694
+
69545
69695
  if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
69696
+ var _titleHeight;
69697
+
69546
69698
  var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
69547
- var titleWidth;
69548
- if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) {
69549
- titleWidth = Drawing.bBox(mathJaxNode).width;
69699
+ if(mathJaxNode && (
69700
+ (isVertical && topOrBottom) ||
69701
+ (!isVertical && !topOrBottom)
69702
+ )) {
69703
+ bb = Drawing.bBox(mathJaxNode);
69704
+ titleWidth = bb.width;
69705
+ _titleHeight = bb.height;
69550
69706
  } else {
69551
69707
  // note: the formula below works for all title sides,
69552
69708
  // (except for top/bottom mathjax, above)
69553
69709
  // but the weird gs.l is because the titleunshift
69554
69710
  // transform gets removed by Drawing.bBox
69555
- titleWidth = Drawing.bBox(titleCont.node()).right - xLeft - gs.l;
69711
+ bb = Drawing.bBox(titleCont.node());
69712
+ titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
69713
+ _titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
69714
+
69715
+ if(
69716
+ !isVertical && titleSide === 'top'
69717
+ ) {
69718
+ innerThickness += bb.height;
69719
+ moveY = bb.height;
69720
+ }
69556
69721
  }
69557
- innerWidth = Math.max(innerWidth, titleWidth);
69722
+
69723
+ if(rightSideHorizontal) {
69724
+ titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
69725
+
69726
+ titleWidth *= 2;
69727
+ }
69728
+
69729
+ innerThickness = Math.max(innerThickness,
69730
+ isVertical ? titleWidth : _titleHeight
69731
+ );
69558
69732
  }
69559
69733
 
69560
- var outerwidth = 2 * opts.xpad + innerWidth + opts.borderwidth + opts.outlinewidth / 2;
69561
- var outerheight = yBottomPx - yTopPx;
69734
+ var outerThickness = (isVertical ?
69735
+ xpad :
69736
+ ypad
69737
+ ) * 2 + innerThickness + borderwidth + outlinewidth / 2;
69562
69738
 
69563
- g.select('.' + cn.cbbg).attr({
69564
- x: xLeft - opts.xpad - (opts.borderwidth + opts.outlinewidth) / 2,
69565
- y: yTopPx - yExtraPx,
69566
- width: Math.max(outerwidth, 2),
69567
- height: Math.max(outerheight + 2 * yExtraPx, 2)
69568
- })
69569
- .call(Color.fill, opts.bgcolor)
69570
- .call(Color.stroke, opts.bordercolor)
69571
- .style('stroke-width', opts.borderwidth);
69739
+ var hColorbarMoveTitle = 0;
69740
+ if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
69741
+ hColorbarMoveTitle = outerThickness / 2;
69572
69742
 
69573
- g.selectAll('.' + cn.cboutline).attr({
69574
- x: xLeft,
69575
- y: yTopPx + opts.ypad + (titleSide === 'top' ? titleHeight : 0),
69576
- width: Math.max(thickPx, 2),
69577
- height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2)
69578
- })
69743
+ outerThickness += hColorbarMoveTitle;
69744
+ moveY += hColorbarMoveTitle;
69745
+ }
69746
+ fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
69747
+ fullLayout._hColorbarMoveCBTitle = moveY;
69748
+
69749
+ var extraW = borderwidth + outlinewidth;
69750
+
69751
+ g.select('.' + cn.cbbg)
69752
+ .attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
69753
+ .attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
69754
+ .attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
69755
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
69756
+ .call(Color.fill, bgcolor)
69757
+ .call(Color.stroke, opts.bordercolor)
69758
+ .style('stroke-width', borderwidth);
69759
+
69760
+ var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
69761
+
69762
+ g.selectAll('.' + cn.cboutline)
69763
+ .attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
69764
+ .attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
69765
+ .attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
69766
+ .attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
69767
+ 2 * ypad + titleHeight :
69768
+ 2 * xpad + moveX
69769
+ ), 2))
69579
69770
  .call(Color.stroke, opts.outlinecolor)
69580
69771
  .style({
69581
69772
  fill: 'none',
69582
- 'stroke-width': opts.outlinewidth
69773
+ 'stroke-width': outlinewidth
69583
69774
  });
69584
69775
 
69585
- // fix positioning for xanchor!='left'
69586
- var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) * outerwidth;
69587
- g.attr('transform', strTranslate(gs.l - xoffset, gs.t));
69776
+ g.attr('transform', strTranslate(
69777
+ gs.l - (isVertical ? xRatio * outerThickness : 0),
69778
+ gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
69779
+ ));
69780
+
69781
+ if(!isVertical && (
69782
+ borderwidth || (
69783
+ tinycolor(bgcolor).getAlpha() &&
69784
+ !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
69785
+ )
69786
+ )) {
69787
+ // for horizontal colorbars when there is a border line or having different background color
69788
+ // hide/adjust x positioning for the first/last tick labels if they go outside the border
69789
+ var tickLabels = axLayer.selectAll('text');
69790
+ var numTicks = tickLabels[0].length;
69791
+
69792
+ var border = g.select('.' + cn.cbbg).node();
69793
+ var oBb = Drawing.bBox(border);
69794
+ var oTr = Drawing.getTranslate(g);
69795
+
69796
+ var TEXTPAD = 2;
69797
+
69798
+ tickLabels.each(function(d, i) {
69799
+ var first = 0;
69800
+ var last = numTicks - 1;
69801
+ if(i === first || i === last) {
69802
+ var iBb = Drawing.bBox(this);
69803
+ var iTr = Drawing.getTranslate(this);
69804
+ var deltaX;
69805
+
69806
+ if(i === last) {
69807
+ var iRight = iBb.right + iTr.x;
69808
+ var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
69809
+
69810
+ deltaX = oRight - iRight;
69811
+ if(deltaX > 0) deltaX = 0;
69812
+ } else if(i === first) {
69813
+ var iLeft = iBb.left + iTr.x;
69814
+ var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
69815
+
69816
+ deltaX = oLeft - iLeft;
69817
+ if(deltaX < 0) deltaX = 0;
69818
+ }
69819
+
69820
+ if(deltaX) {
69821
+ if(numTicks < 3) { // adjust position
69822
+ this.setAttribute('transform',
69823
+ 'translate(' + deltaX + ',0) ' +
69824
+ this.getAttribute('transform')
69825
+ );
69826
+ } else { // hide
69827
+ this.setAttribute('visibility', 'hidden');
69828
+ }
69829
+ }
69830
+ }
69831
+ });
69832
+ }
69588
69833
 
69589
69834
  // auto margin adjustment
69590
69835
  var marginOpts = {};
69591
- var tFrac = FROM_TL[opts.yanchor];
69592
- var bFrac = FROM_BR[opts.yanchor];
69593
- if(opts.lenmode === 'pixels') {
69594
- marginOpts.y = opts.y;
69595
- marginOpts.t = outerheight * tFrac;
69596
- marginOpts.b = outerheight * bFrac;
69597
- } else {
69598
- marginOpts.t = marginOpts.b = 0;
69599
- marginOpts.yt = opts.y + opts.len * tFrac;
69600
- marginOpts.yb = opts.y - opts.len * bFrac;
69601
- }
69836
+ var lFrac = FROM_TL[xanchor];
69837
+ var rFrac = FROM_BR[xanchor];
69838
+ var tFrac = FROM_TL[yanchor];
69839
+ var bFrac = FROM_BR[yanchor];
69602
69840
 
69603
- var lFrac = FROM_TL[opts.xanchor];
69604
- var rFrac = FROM_BR[opts.xanchor];
69605
- if(opts.thicknessmode === 'pixels') {
69606
- marginOpts.x = opts.x;
69607
- marginOpts.l = outerwidth * lFrac;
69608
- marginOpts.r = outerwidth * rFrac;
69609
- } else {
69610
- var extraThickness = outerwidth - thickPx;
69611
- marginOpts.l = extraThickness * lFrac;
69612
- marginOpts.r = extraThickness * rFrac;
69613
- marginOpts.xl = opts.x - opts.thickness * lFrac;
69614
- marginOpts.xr = opts.x + opts.thickness * rFrac;
69841
+ var extraThickness = outerThickness - thickPx;
69842
+ if(isVertical) {
69843
+ if(lenmode === 'pixels') {
69844
+ marginOpts.y = optsY;
69845
+ marginOpts.t = lenPx * tFrac;
69846
+ marginOpts.b = lenPx * bFrac;
69847
+ } else {
69848
+ marginOpts.t = marginOpts.b = 0;
69849
+ marginOpts.yt = optsY + len * tFrac;
69850
+ marginOpts.yb = optsY - len * bFrac;
69851
+ }
69852
+
69853
+ if(thicknessmode === 'pixels') {
69854
+ marginOpts.x = optsX;
69855
+ marginOpts.l = outerThickness * lFrac;
69856
+ marginOpts.r = outerThickness * rFrac;
69857
+ } else {
69858
+ marginOpts.l = extraThickness * lFrac;
69859
+ marginOpts.r = extraThickness * rFrac;
69860
+ marginOpts.xl = optsX - thickness * lFrac;
69861
+ marginOpts.xr = optsX + thickness * rFrac;
69862
+ }
69863
+ } else { // horizontal colorbars
69864
+ if(lenmode === 'pixels') {
69865
+ marginOpts.x = optsX;
69866
+ marginOpts.l = lenPx * lFrac;
69867
+ marginOpts.r = lenPx * rFrac;
69868
+ } else {
69869
+ marginOpts.l = marginOpts.r = 0;
69870
+ marginOpts.xl = optsX + len * lFrac;
69871
+ marginOpts.xr = optsX - len * rFrac;
69872
+ }
69873
+
69874
+ if(thicknessmode === 'pixels') {
69875
+ marginOpts.y = 1 - optsY;
69876
+ marginOpts.t = outerThickness * tFrac;
69877
+ marginOpts.b = outerThickness * bFrac;
69878
+ } else {
69879
+ marginOpts.t = extraThickness * tFrac;
69880
+ marginOpts.b = extraThickness * bFrac;
69881
+ marginOpts.yt = optsY - thickness * tFrac;
69882
+ marginOpts.yb = optsY + thickness * bFrac;
69883
+ }
69615
69884
  }
69616
69885
 
69617
69886
  Plots.autoMargin(gd, opts._id, marginOpts);
@@ -69628,6 +69897,7 @@ function drawColorBar(g, opts, gd) {
69628
69897
  }
69629
69898
 
69630
69899
  function makeEditable(g, opts, gd) {
69900
+ var isVertical = opts.orientation === 'v';
69631
69901
  var fullLayout = gd._fullLayout;
69632
69902
  var gs = fullLayout._size;
69633
69903
  var t0, xf, yf;
@@ -69642,9 +69912,13 @@ function makeEditable(g, opts, gd) {
69642
69912
  moveFn: function(dx, dy) {
69643
69913
  g.attr('transform', t0 + strTranslate(dx, dy));
69644
69914
 
69645
- xf = dragElement.align(opts._xLeftFrac + (dx / gs.w), opts._thickFrac,
69915
+ xf = dragElement.align(
69916
+ (isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
69917
+ isVertical ? opts._thickFrac : opts._lenFrac,
69646
69918
  0, 1, opts.xanchor);
69647
- yf = dragElement.align(opts._yBottomFrac - (dy / gs.h), opts._lenFrac,
69919
+ yf = dragElement.align(
69920
+ (isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
69921
+ isVertical ? opts._lenFrac : opts._thickFrac,
69648
69922
  0, 1, opts.yanchor);
69649
69923
 
69650
69924
  var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
@@ -69721,6 +69995,8 @@ function calcLevels(gd, opts, zrange) {
69721
69995
  function mockColorBarAxis(gd, opts, zrange) {
69722
69996
  var fullLayout = gd._fullLayout;
69723
69997
 
69998
+ var isVertical = opts.orientation === 'v';
69999
+
69724
70000
  var cbAxisIn = {
69725
70001
  type: 'linear',
69726
70002
  range: zrange,
@@ -69751,17 +70027,19 @@ function mockColorBarAxis(gd, opts, zrange) {
69751
70027
  title: opts.title,
69752
70028
  showline: true,
69753
70029
  anchor: 'free',
69754
- side: 'right',
70030
+ side: isVertical ? 'right' : 'bottom',
69755
70031
  position: 1
69756
70032
  };
69757
70033
 
70034
+ var letter = isVertical ? 'y' : 'x';
70035
+
69758
70036
  var cbAxisOut = {
69759
70037
  type: 'linear',
69760
- _id: 'y' + opts._id
70038
+ _id: letter + opts._id
69761
70039
  };
69762
70040
 
69763
70041
  var axisOptions = {
69764
- letter: 'y',
70042
+ letter: letter,
69765
70043
  font: fullLayout.font,
69766
70044
  noHover: true,
69767
70045
  noTickson: true,
@@ -72223,7 +72501,7 @@ var TEXTOFFSETSIGN = {
72223
72501
  start: 1, end: -1, middle: 0, bottom: 1, top: -1
72224
72502
  };
72225
72503
 
72226
- function textPointPosition(s, textPosition, fontSize, markerRadius) {
72504
+ function textPointPosition(s, textPosition, fontSize, markerRadius, dontTouchParent) {
72227
72505
  var group = d3.select(s.node().parentNode);
72228
72506
 
72229
72507
  var v = textPosition.indexOf('top') !== -1 ?
@@ -72245,7 +72523,9 @@ function textPointPosition(s, textPosition, fontSize, markerRadius) {
72245
72523
 
72246
72524
  // fix the overall text group position
72247
72525
  s.attr('text-anchor', h);
72248
- group.attr('transform', strTranslate(dx, dy));
72526
+ if(!dontTouchParent) {
72527
+ group.attr('transform', strTranslate(dx, dy));
72528
+ }
72249
72529
  }
72250
72530
 
72251
72531
  function extracTextFontSize(d, trace) {
@@ -72315,7 +72595,8 @@ drawing.selectedTextStyle = function(s, trace) {
72315
72595
  var fontSize = extracTextFontSize(d, trace);
72316
72596
 
72317
72597
  Color.fill(tx, tc);
72318
- textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc);
72598
+ var dontTouchParent = Registry.traceIs(trace, 'bar-like');
72599
+ textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc, dontTouchParent);
72319
72600
  });
72320
72601
  };
72321
72602
 
@@ -74346,11 +74627,13 @@ var cartesianScatterPoints = {
74346
74627
  // The actual rendering is done by private function _hover.
74347
74628
  exports.hover = function hover(gd, evt, subplot, noHoverEvent) {
74348
74629
  gd = Lib.getGraphDiv(gd);
74349
-
74630
+ // The 'target' property changes when bubbling out of Shadow DOM.
74631
+ // Throttling can delay reading the target, so we save the current value.
74632
+ var eventTarget = evt.target;
74350
74633
  Lib.throttle(
74351
74634
  gd._fullLayout._uid + constants.HOVERID,
74352
74635
  constants.HOVERMINTIME,
74353
- function() { _hover(gd, evt, subplot, noHoverEvent); }
74636
+ function() { _hover(gd, evt, subplot, noHoverEvent, eventTarget); }
74354
74637
  );
74355
74638
  };
74356
74639
 
@@ -74515,7 +74798,7 @@ exports.loneHover = function loneHover(hoverItems, opts) {
74515
74798
  };
74516
74799
 
74517
74800
  // The actual implementation is here:
74518
- function _hover(gd, evt, subplot, noHoverEvent) {
74801
+ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
74519
74802
  if(!subplot) subplot = 'xy';
74520
74803
 
74521
74804
  // if the user passed in an array of subplots,
@@ -74634,7 +74917,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
74634
74917
  // [x|y]px: the pixels (from top left) of the mouse location
74635
74918
  // on the currently selected plot area
74636
74919
  // add pointerX|Y property for drawing the spikes in spikesnap 'cursor' situation
74637
- var hasUserCalledHover = !evt.target;
74920
+ var hasUserCalledHover = !eventTarget;
74638
74921
  var xpx, ypx;
74639
74922
 
74640
74923
  if(hasUserCalledHover) {
@@ -74651,13 +74934,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
74651
74934
  return;
74652
74935
  }
74653
74936
 
74654
- // Discover event target, traversing open shadow roots.
74655
- var target = evt.composedPath && evt.composedPath()[0];
74656
- if(!target) {
74657
- // Fallback for browsers not supporting composedPath
74658
- target = evt.target;
74659
- }
74660
- var dbb = target.getBoundingClientRect();
74937
+ var dbb = eventTarget.getBoundingClientRect();
74661
74938
 
74662
74939
  xpx = evt.clientX - dbb.left;
74663
74940
  ypx = evt.clientY - dbb.top;
@@ -75105,15 +75382,15 @@ function _hover(gd, evt, subplot, noHoverEvent) {
75105
75382
  if(!helpers.isUnifiedHover(hovermode)) {
75106
75383
  hoverAvoidOverlaps(hoverLabels, rotateLabels ? 'xa' : 'ya', fullLayout);
75107
75384
  alignHoverText(hoverLabels, rotateLabels, fullLayout._invScaleX, fullLayout._invScaleY);
75108
- } // TODO: tagName hack is needed to appease geo.js's hack of using evt.target=true
75385
+ } // TODO: tagName hack is needed to appease geo.js's hack of using eventTarget=true
75109
75386
  // we should improve the "fx" API so other plots can use it without these hack.
75110
- if(evt.target && evt.target.tagName) {
75387
+ if(eventTarget && eventTarget.tagName) {
75111
75388
  var hasClickToShow = Registry.getComponentMethod('annotations', 'hasClickToShow')(gd, newhoverdata);
75112
- overrideCursor(d3.select(evt.target), hasClickToShow ? 'pointer' : '');
75389
+ overrideCursor(d3.select(eventTarget), hasClickToShow ? 'pointer' : '');
75113
75390
  }
75114
75391
 
75115
75392
  // don't emit events if called manually
75116
- if(!evt.target || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
75393
+ if(!eventTarget || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
75117
75394
 
75118
75395
  if(oldhoverdata) {
75119
75396
  gd.emit('plotly_unhover', {
@@ -75375,7 +75652,9 @@ function createHoverText(hoverData, opts) {
75375
75652
  orientation: 'v'
75376
75653
  }
75377
75654
  };
75378
- var mockLayoutOut = {};
75655
+ var mockLayoutOut = {
75656
+ font: font
75657
+ };
75379
75658
  legendSupplyDefaults(mockLayoutIn, mockLayoutOut, gd._fullData);
75380
75659
  var mockLegend = mockLayoutOut.legend;
75381
75660
 
@@ -75416,7 +75695,8 @@ function createHoverText(hoverData, opts) {
75416
75695
 
75417
75696
  // Draw unified hover label
75418
75697
  mockLegend._inHover = true;
75419
- mockLegend._groupTitleFont = font;
75698
+ mockLegend._groupTitleFont = hoverlabel.grouptitlefont;
75699
+
75420
75700
  legendDraw(gd, mockLegend);
75421
75701
 
75422
75702
  // Position the hover
@@ -76418,9 +76698,11 @@ var isUnifiedHover = _dereq_('./helpers').isUnifiedHover;
76418
76698
  module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) {
76419
76699
  opts = opts || {};
76420
76700
 
76701
+ var hasLegend = contOut.legend;
76702
+
76421
76703
  function inheritFontAttr(attr) {
76422
76704
  if(!opts.font[attr]) {
76423
- opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr];
76705
+ opts.font[attr] = hasLegend ? contOut.legend.font[attr] : contOut.font[attr];
76424
76706
  }
76425
76707
  }
76426
76708
 
@@ -76431,7 +76713,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
76431
76713
  inheritFontAttr('family');
76432
76714
  inheritFontAttr('color');
76433
76715
 
76434
- if(contOut.legend) {
76716
+ if(hasLegend) {
76435
76717
  if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor);
76436
76718
  if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor;
76437
76719
  } else {
@@ -76540,11 +76822,13 @@ function castHoverinfo(trace, fullLayout, ptNumber) {
76540
76822
 
76541
76823
  var constants = _dereq_('./constants');
76542
76824
 
76543
- var fontAttrs = _dereq_('../../plots/font_attributes')({
76825
+ var fontAttrs = _dereq_('../../plots/font_attributes');
76826
+
76827
+ var font = fontAttrs({
76544
76828
  editType: 'none',
76545
76829
  });
76546
- fontAttrs.family.dflt = constants.HOVERFONT;
76547
- fontAttrs.size.dflt = constants.HOVERFONTSIZE;
76830
+ font.family.dflt = constants.HOVERFONT;
76831
+ font.size.dflt = constants.HOVERFONTSIZE;
76548
76832
 
76549
76833
  module.exports = {
76550
76834
  clickmode: {
@@ -76600,7 +76884,10 @@ module.exports = {
76600
76884
  valType: 'color',
76601
76885
  editType: 'none',
76602
76886
  },
76603
- font: fontAttrs,
76887
+ font: font,
76888
+ grouptitlefont: fontAttrs({
76889
+ editType: 'none',
76890
+ }),
76604
76891
  align: {
76605
76892
  valType: 'enumerated',
76606
76893
  values: ['left', 'right', 'auto'],
@@ -76613,6 +76900,7 @@ module.exports = {
76613
76900
  dflt: 15,
76614
76901
  editType: 'none',
76615
76902
  },
76903
+
76616
76904
  editType: 'none'
76617
76905
  },
76618
76906
  selectdirection: {
@@ -76660,6 +76948,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
76660
76948
  }
76661
76949
 
76662
76950
  handleHoverLabelDefaults(layoutIn, layoutOut, coerce);
76951
+
76952
+ Lib.coerceFont(coerce, 'hoverlabel.grouptitlefont', layoutOut.hoverlabel.font);
76663
76953
  };
76664
76954
 
76665
76955
  },{"../../lib":246,"./hoverlabel_defaults":152,"./hovermode_defaults":153,"./layout_attributes":155}],157:[function(_dereq_,module,exports){
@@ -77543,6 +77833,9 @@ module.exports = {
77543
77833
  font: fontAttrs({
77544
77834
  editType: 'legend',
77545
77835
  }),
77836
+ grouptitlefont: fontAttrs({
77837
+ editType: 'legend',
77838
+ }),
77546
77839
  orientation: {
77547
77840
  valType: 'enumerated',
77548
77841
  values: ['v', 'h'],
@@ -77666,6 +77959,7 @@ var Registry = _dereq_('../../registry');
77666
77959
  var Lib = _dereq_('../../lib');
77667
77960
  var Template = _dereq_('../../plot_api/plot_template');
77668
77961
 
77962
+ var plotsAttrs = _dereq_('../../plots/attributes');
77669
77963
  var attributes = _dereq_('./attributes');
77670
77964
  var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes');
77671
77965
  var helpers = _dereq_('./helpers');
@@ -77673,13 +77967,30 @@ var helpers = _dereq_('./helpers');
77673
77967
 
77674
77968
  module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
77675
77969
  var containerIn = layoutIn.legend || {};
77970
+ var containerOut = Template.newContainer(layoutOut, 'legend');
77971
+
77972
+ function coerce(attr, dflt) {
77973
+ return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
77974
+ }
77975
+
77976
+ var trace;
77977
+ var traceCoerce = function(attr, dflt) {
77978
+ var traceIn = trace._input;
77979
+ var traceOut = trace;
77980
+ return Lib.coerce(traceIn, traceOut, plotsAttrs, attr, dflt);
77981
+ };
77982
+
77983
+ var globalFont = layoutOut.font || {};
77984
+ var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
77985
+ size: Math.round(globalFont.size * 1.1)
77986
+ }));
77676
77987
 
77677
77988
  var legendTraceCount = 0;
77678
77989
  var legendReallyHasATrace = false;
77679
77990
  var defaultOrder = 'normal';
77680
77991
 
77681
77992
  for(var i = 0; i < fullData.length; i++) {
77682
- var trace = fullData[i];
77993
+ trace = fullData[i];
77683
77994
 
77684
77995
  if(!trace.visible) continue;
77685
77996
 
@@ -77706,6 +78017,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
77706
78017
  legendTraceCount++;
77707
78018
  }
77708
78019
  }
78020
+
78021
+ Lib.coerceFont(traceCoerce, 'legendgrouptitle.font', grouptitlefont);
77709
78022
  }
77710
78023
 
77711
78024
  if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') ||
@@ -77724,13 +78037,10 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
77724
78037
  basePlotLayoutAttributes, 'showlegend',
77725
78038
  legendReallyHasATrace && legendTraceCount > 1);
77726
78039
 
77727
- if(showLegend === false && !containerIn.uirevision) return;
78040
+ // delete legend
78041
+ if(showLegend === false) layoutOut.legend = undefined;
77728
78042
 
77729
- var containerOut = Template.newContainer(layoutOut, 'legend');
77730
-
77731
- function coerce(attr, dflt) {
77732
- return Lib.coerce(containerIn, containerOut, attributes, attr, dflt);
77733
- }
78043
+ if(showLegend === false && !containerIn.uirevision) return;
77734
78044
 
77735
78045
  coerce('uirevision', layoutOut.uirevision);
77736
78046
 
@@ -77792,7 +78102,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
77792
78102
  }
77793
78103
  };
77794
78104
 
77795
- },{"../../lib":246,"../../plot_api/plot_template":282,"../../plots/layout_attributes":328,"../../registry":340,"./attributes":164,"./helpers":170}],167:[function(_dereq_,module,exports){
78105
+ },{"../../lib":246,"../../plot_api/plot_template":282,"../../plots/attributes":289,"../../plots/layout_attributes":328,"../../registry":340,"./attributes":164,"./helpers":170}],167:[function(_dereq_,module,exports){
77796
78106
  'use strict';
77797
78107
 
77798
78108
  var d3 = _dereq_('@plotly/d3');
@@ -86244,8 +86554,10 @@ function draw(gd, titleClass, options) {
86244
86554
 
86245
86555
  var elShouldExist = txt || editable;
86246
86556
 
86557
+ var hColorbarMoveTitle;
86247
86558
  if(!group) {
86248
86559
  group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass);
86560
+ hColorbarMoveTitle = fullLayout._hColorbarMoveTitle;
86249
86561
  }
86250
86562
 
86251
86563
  var el = group.selectAll('text')
@@ -86269,13 +86581,17 @@ function draw(gd, titleClass, options) {
86269
86581
  function drawTitle(titleEl) {
86270
86582
  var transformVal;
86271
86583
 
86584
+ if(!transform && hColorbarMoveTitle) {
86585
+ transform = {};
86586
+ }
86587
+
86272
86588
  if(transform) {
86273
86589
  transformVal = '';
86274
86590
  if(transform.rotate) {
86275
86591
  transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')';
86276
86592
  }
86277
- if(transform.offset) {
86278
- transformVal += strTranslate(0, transform.offset);
86593
+ if(transform.offset || hColorbarMoveTitle) {
86594
+ transformVal += strTranslate(0, (transform.offset || 0) - (hColorbarMoveTitle || 0));
86279
86595
  }
86280
86596
  } else {
86281
86597
  transformVal = null;
@@ -98218,7 +98534,7 @@ function cleanDeprecatedAttributeKeys(aobj) {
98218
98534
  if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) &&
98219
98535
  (typeof value === 'string' || typeof value === 'number')) {
98220
98536
  replace(key, key.replace('title', 'title.text'));
98221
- } else if(key.indexOf('titlefont') > -1) {
98537
+ } else if(key.indexOf('titlefont') > -1 && key.indexOf('grouptitlefont') === -1) {
98222
98538
  replace(key, key.replace('titlefont', 'title.font'));
98223
98539
  } else if(key.indexOf('titleposition') > -1) {
98224
98540
  replace(key, key.replace('titleposition', 'title.position'));
@@ -98895,7 +99211,8 @@ function findUIPattern(key, patternSpecs) {
98895
99211
  var spec = patternSpecs[i];
98896
99212
  var match = key.match(spec.pattern);
98897
99213
  if(match) {
98898
- return {head: match[1], attr: spec.attr};
99214
+ var head = match[1] || '';
99215
+ return {head: head, tail: key.substr(head.length + 1), attr: spec.attr};
98899
99216
  }
98900
99217
  }
98901
99218
  }
@@ -98947,26 +99264,54 @@ function valsMatch(v1, v2) {
98947
99264
 
98948
99265
  function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
98949
99266
  var layoutPreGUI = oldFullLayout._preGUI;
98950
- var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal;
99267
+ var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal, head, tail;
98951
99268
  var bothInheritAutorange = [];
99269
+ var newAutorangeIn = {};
98952
99270
  var newRangeAccepted = {};
98953
99271
  for(key in layoutPreGUI) {
98954
99272
  match = findUIPattern(key, layoutUIControlPatterns);
98955
99273
  if(match) {
98956
- revAttr = match.attr || (match.head + '.uirevision');
99274
+ head = match.head;
99275
+ tail = match.tail;
99276
+ revAttr = match.attr || (head + '.uirevision');
98957
99277
  oldRev = nestedProperty(oldFullLayout, revAttr).get();
98958
99278
  newRev = oldRev && getNewRev(revAttr, layout);
99279
+
98959
99280
  if(newRev && (newRev === oldRev)) {
98960
99281
  preGUIVal = layoutPreGUI[key];
98961
99282
  if(preGUIVal === null) preGUIVal = undefined;
98962
99283
  newNP = nestedProperty(layout, key);
98963
99284
  newVal = newNP.get();
99285
+
98964
99286
  if(valsMatch(newVal, preGUIVal)) {
98965
- if(newVal === undefined && key.substr(key.length - 9) === 'autorange') {
98966
- bothInheritAutorange.push(key.substr(0, key.length - 10));
99287
+ if(newVal === undefined && tail === 'autorange') {
99288
+ bothInheritAutorange.push(head);
98967
99289
  }
98968
99290
  newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
98969
99291
  continue;
99292
+ } else if(tail === 'autorange' || tail.substr(0, 6) === 'range[') {
99293
+ // Special case for (auto)range since we push it back into the layout
99294
+ // so all null should be treated equivalently to autorange: true with any range
99295
+ var pre0 = layoutPreGUI[head + '.range[0]'];
99296
+ var pre1 = layoutPreGUI[head + '.range[1]'];
99297
+ var preAuto = layoutPreGUI[head + '.autorange'];
99298
+ if(preAuto || (preAuto === null && pre0 === null && pre1 === null)) {
99299
+ // Only read the input layout once and stash the result,
99300
+ // so we get it before we start modifying it
99301
+ if(!(head in newAutorangeIn)) {
99302
+ var newContainer = nestedProperty(layout, head).get();
99303
+ newAutorangeIn[head] = newContainer && (
99304
+ newContainer.autorange ||
99305
+ (newContainer.autorange !== false && (
99306
+ !newContainer.range || newContainer.range.length !== 2)
99307
+ )
99308
+ );
99309
+ }
99310
+ if(newAutorangeIn[head]) {
99311
+ newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get()));
99312
+ continue;
99313
+ }
99314
+ }
98970
99315
  }
98971
99316
  }
98972
99317
  } else {
@@ -98977,12 +99322,12 @@ function applyUIRevisions(data, layout, oldFullData, oldFullLayout) {
98977
99322
  // so remove it from _preGUI for next time.
98978
99323
  delete layoutPreGUI[key];
98979
99324
 
98980
- if(key.substr(key.length - 8, 6) === 'range[') {
98981
- newRangeAccepted[key.substr(0, key.length - 9)] = 1;
99325
+ if(match && match.tail.substr(0, 6) === 'range[') {
99326
+ newRangeAccepted[match.head] = 1;
98982
99327
  }
98983
99328
  }
98984
99329
 
98985
- // Special logic for `autorange`, since it interacts with `range`:
99330
+ // More special logic for `autorange`, since it interacts with `range`:
98986
99331
  // If the new figure's matching `range` was kept, and `autorange`
98987
99332
  // wasn't supplied explicitly in either the original or the new figure,
98988
99333
  // we shouldn't alter that - but we may just have done that, so fix it.
@@ -116057,6 +116402,9 @@ module.exports = function(opts) {
116057
116402
  // TODO - that's uber hacky... better solution?
116058
116403
  };
116059
116404
 
116405
+ if(opts.autoSize) attrs.size.dflt = 'auto';
116406
+ if(opts.autoColor) attrs.color.dflt = 'auto';
116407
+
116060
116408
  if(opts.arrayOk) {
116061
116409
  attrs.family.arrayOk = true;
116062
116410
  attrs.size.arrayOk = true;
@@ -116416,6 +116764,7 @@ module.exports = {
116416
116764
  valType: 'boolean',
116417
116765
  editType: 'legend',
116418
116766
  },
116767
+
116419
116768
  colorway: {
116420
116769
  valType: 'colorlist',
116421
116770
  dflt: colorAttrs.defaults,
@@ -118354,11 +118703,14 @@ proto.project = function(v) {
118354
118703
  proto.getView = function() {
118355
118704
  var map = this.map;
118356
118705
  var mapCenter = map.getCenter();
118357
- var center = { lon: mapCenter.lng, lat: mapCenter.lat };
118706
+ var lon = mapCenter.lng;
118707
+ var lat = mapCenter.lat;
118708
+ var center = { lon: lon, lat: lat };
118358
118709
 
118359
118710
  var canvas = map.getCanvas();
118360
- var w = canvas.width;
118361
- var h = canvas.height;
118711
+ var w = parseInt(canvas.style.width);
118712
+ var h = parseInt(canvas.style.height);
118713
+
118362
118714
  return {
118363
118715
  center: center,
118364
118716
  zoom: map.getZoom(),
@@ -119795,13 +120147,7 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
119795
120147
  );
119796
120148
 
119797
120149
  coerce('legendgroup');
119798
- var titleText = coerce('legendgrouptitle.text');
119799
- if(titleText) {
119800
- Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
119801
- size: Math.round(layout.font.size * 1.1) // default to larger font size
119802
- }));
119803
- }
119804
-
120150
+ coerce('legendgrouptitle.text');
119805
120151
  coerce('legendrank');
119806
120152
 
119807
120153
  traceOut._dfltShowLegend = true;
@@ -119949,16 +120295,14 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) {
119949
120295
 
119950
120296
  coerce('autotypenumbers');
119951
120297
 
119952
- var globalFont = Lib.coerceFont(coerce, 'font');
119953
-
119954
- coerce('title.text', layoutOut._dfltTitle.plot);
120298
+ var font = Lib.coerceFont(coerce, 'font');
120299
+ var fontSize = font.size;
119955
120300
 
119956
- Lib.coerceFont(coerce, 'title.font', {
119957
- family: globalFont.family,
119958
- size: Math.round(globalFont.size * 1.4),
119959
- color: globalFont.color
119960
- });
120301
+ Lib.coerceFont(coerce, 'title.font', Lib.extendFlat({}, font, {
120302
+ size: Math.round(fontSize * 1.4)
120303
+ }));
119961
120304
 
120305
+ coerce('title.text', layoutOut._dfltTitle.plot);
119962
120306
  coerce('title.xref');
119963
120307
  coerce('title.yref');
119964
120308
  coerce('title.x');
@@ -129495,7 +129839,7 @@ function getSortFunc(opts, d2c) {
129495
129839
  'use strict';
129496
129840
 
129497
129841
  // package version injected by `npm run preprocess`
129498
- exports.version = '2.6.2';
129842
+ exports.version = '2.8.0';
129499
129843
 
129500
129844
  },{}]},{},[9])(9)
129501
129845
  });