@kevinburke/flot 5.0.0 → 5.1.1

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.
package/dist/flot.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @kevinburke/flot v5.0.0 | MIT License | https://github.com/kevinburke/flot */
1
+ /*! @kevinburke/flot v5.1.1 | MIT License | https://github.com/kevinburke/flot */
2
2
  var browser = {
3
3
  getPageXY: function (e) {
4
4
  var doc = document.documentElement,
@@ -19,7 +19,9 @@ var browser = {
19
19
  },
20
20
 
21
21
  isSafari: function() {
22
- return /constructor/i.test(window.top.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window.top['safari'] || (typeof window.top.safari !== 'undefined' && window.top.safari.pushNotification));
22
+ var top = window.top;
23
+ if (!top) return false;
24
+ return /constructor/i.test(top.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!top['safari'] || (typeof top.safari !== 'undefined' && top.safari.pushNotification));
23
25
  },
24
26
 
25
27
  isMobileSafari: function() {
@@ -27,7 +29,7 @@ var browser = {
27
29
  },
28
30
 
29
31
  isOpera: function() {
30
- return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
32
+ return (!!window.opr && !!window.opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
31
33
  },
32
34
 
33
35
  isFirefox: function() {
@@ -345,7 +347,7 @@ var Canvas = function(cls, container) {
345
347
  // already been rendered, and remove those that are no longer active.
346
348
 
347
349
  for (var layerKey in cache) {
348
- if (hasOwnProperty.call(cache, layerKey)) {
350
+ if (Object.prototype.hasOwnProperty.call(cache, layerKey)) {
349
351
  var layer = this.getSVGLayer(layerKey),
350
352
  layerCache = cache[layerKey];
351
353
 
@@ -353,10 +355,10 @@ var Canvas = function(cls, container) {
353
355
  layer.style.display = 'none';
354
356
 
355
357
  for (var styleKey in layerCache) {
356
- if (hasOwnProperty.call(layerCache, styleKey)) {
358
+ if (Object.prototype.hasOwnProperty.call(layerCache, styleKey)) {
357
359
  var styleCache = layerCache[styleKey];
358
360
  for (var key in styleCache) {
359
- if (hasOwnProperty.call(styleCache, key)) {
361
+ if (Object.prototype.hasOwnProperty.call(styleCache, key)) {
360
362
  var val = styleCache[key],
361
363
  positions = val.positions;
362
364
 
@@ -710,14 +712,20 @@ var Canvas = function(cls, container) {
710
712
  var layerCache = this._textCache[layer];
711
713
  if (layerCache != null) {
712
714
  for (var styleKey in layerCache) {
713
- if (hasOwnProperty.call(layerCache, styleKey)) {
715
+ if (Object.prototype.hasOwnProperty.call(layerCache, styleKey)) {
714
716
  var styleCache = layerCache[styleKey];
715
717
  for (var key in styleCache) {
716
- if (hasOwnProperty.call(styleCache, key)) {
718
+ if (Object.prototype.hasOwnProperty.call(styleCache, key)) {
719
+ // styleCache entries can exist without a
720
+ // positions array (e.g. when a Flot plugin
721
+ // populates the cache outside the normal
722
+ // addText path). Upstream flot/flot#1444.
717
723
  var positions = styleCache[key].positions;
718
- positions.forEach(function(position) {
719
- position.active = false;
720
- });
724
+ if (positions != null) {
725
+ positions.forEach(function(position) {
726
+ position.active = false;
727
+ });
728
+ }
721
729
  }
722
730
  }
723
731
  }
@@ -746,7 +754,7 @@ var Canvas = function(cls, container) {
746
754
  Canvas.prototype.clearCache = function() {
747
755
  var cache = this._textCache;
748
756
  for (var layerKey in cache) {
749
- if (hasOwnProperty.call(cache, layerKey)) {
757
+ if (Object.prototype.hasOwnProperty.call(cache, layerKey)) {
750
758
  var layer = this.getSVGLayer(layerKey);
751
759
  while (layer.firstChild) {
752
760
  layer.removeChild(layer.firstChild);
@@ -3356,8 +3364,11 @@ Licensed under the MIT license.
3356
3364
  };
3357
3365
 
3358
3366
  // we might need an extra decimal since forced
3359
- // ticks don't necessarily fit naturally
3360
- if (!axis.mode && opts.tickDecimals == null) {
3367
+ // ticks don't necessarily fit naturally.
3368
+ // Guard against axis.delta <= 0 (min == max): Math.log(0)
3369
+ // is -Infinity, so extraDec would be +Infinity and
3370
+ // toFixed(Infinity) throws. Upstream #1869 / PR #1870.
3371
+ if (!axis.mode && opts.tickDecimals == null && axis.delta > 0) {
3361
3372
  var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
3362
3373
  ts = axis.tickGenerator(axis, plot);
3363
3374
 
@@ -3575,6 +3586,8 @@ Licensed under the MIT license.
3575
3586
  markings = markings(axes);
3576
3587
  }
3577
3588
 
3589
+ if (!markings) return;
3590
+
3578
3591
  var i;
3579
3592
  for (i = 0; i < markings.length; ++i) {
3580
3593
  var m = markings[i],
@@ -4262,7 +4275,13 @@ Licensed under the MIT license.
4262
4275
  maxy = maxDistance / series.yaxis.scale,
4263
4276
  points = series.datapoints.points,
4264
4277
  ps = series.datapoints.pointsize,
4265
- smallestDistance = Number.POSITIVE_INFINITY;
4278
+ // Seed with maxDistance (or its square, matching the
4279
+ // default squared-distance metric) so points outside
4280
+ // the hover radius are never selected. Without this,
4281
+ // the maxx/maxy coordinate-space pre-filter is the
4282
+ // only radius check, and it's disabled for axes with
4283
+ // inverseTransform — see upstream flot/flot#1871.
4284
+ smallestDistance = computeDistance ? maxDistance : maxDistance * maxDistance;
4266
4285
 
4267
4286
  // with inverse transforms, we can't use the maxx/maxy
4268
4287
  // optimization, sadly
@@ -4462,7 +4481,16 @@ Licensed under the MIT license.
4462
4481
  } else {
4463
4482
  // assume this is a gradient spec; IE currently only
4464
4483
  // supports a simple vertical gradient properly, so that's
4465
- // what we support too
4484
+ // what we support too.
4485
+ // createLinearGradient throws if any coordinate is NaN or
4486
+ // ±Infinity (e.g. when the plot container has zero size
4487
+ // or the user supplies bogus bounds) — fall back to the
4488
+ // default solid color instead. Global isFinite coerces
4489
+ // null → 0 (finite), matching the drawSeriesPoints path
4490
+ // that passes (null, null). Upstream flot/flot#1867.
4491
+ if (!isFinite(top) || !isFinite(bottom)) {
4492
+ return defaultColor;
4493
+ }
4466
4494
  var gradient = ctx.createLinearGradient(0, top, 0, bottom);
4467
4495
 
4468
4496
  for (var i = 0, l = spec.colors.length; i < l; ++i) {
@@ -4490,7 +4518,7 @@ Licensed under the MIT license.
4490
4518
  // Plugin registry. Plugins push to this array to register themselves.
4491
4519
  var plugins = [];
4492
4520
 
4493
- var version = "5.0.0";
4521
+ var version = "5.1.1";
4494
4522
 
4495
4523
  // The main plot function.
4496
4524
  function plot(placeholder, data, options) {
@@ -5751,6 +5779,17 @@ Licensed under the MIT license.
5751
5779
  var minD = axis.p2c(opts.panRange[0]) - axis.p2c(axis.min);
5752
5780
  // calc max delta (revealing right edge of plot)
5753
5781
  var maxD = axis.p2c(opts.panRange[1]) - axis.p2c(axis.max);
5782
+ // For the y-axis, screen coordinates are inverted
5783
+ // (p2c(smaller v) > p2c(larger v)), so minD/maxD end up
5784
+ // with the opposite signs from the x-axis case. Swap
5785
+ // them so the clamp comparisons below keep their
5786
+ // x-axis semantics. Upstream flot/flot#1789, ports the
5787
+ // minimal form of PR #1793.
5788
+ if (axis.direction === 'y') {
5789
+ var swap = minD;
5790
+ minD = maxD;
5791
+ maxD = swap;
5792
+ }
5754
5793
  // limit delta to min or max if enabled
5755
5794
  if (opts.panRange[0] !== undefined && d >= maxD) d = maxD;
5756
5795
  if (opts.panRange[1] !== undefined && d <= minD) d = minD;
@@ -5915,6 +5954,13 @@ Licensed under the MIT license.
5915
5954
  var minD = p + axis.p2c(opts.panRange[0]) - axis.p2c(axisMin);
5916
5955
  // calc max delta (revealing right edge of plot)
5917
5956
  var maxD = p + axis.p2c(opts.panRange[1]) - axis.p2c(axisMax);
5957
+ // Same y-axis swap as plot.pan — see comment there.
5958
+ // Upstream flot/flot#1789 / PR #1793.
5959
+ if (axis.direction === 'y') {
5960
+ var swap = minD;
5961
+ minD = maxD;
5962
+ maxD = swap;
5963
+ }
5918
5964
  // limit delta to min or max if enabled
5919
5965
  if (opts.panRange[0] !== undefined && d >= maxD) d = maxD;
5920
5966
  if (opts.panRange[1] !== undefined && d <= minD) d = minD;
@@ -9212,7 +9258,7 @@ temporary images load their data.
9212
9258
 
9213
9259
  // Encode the string as UTF-8 and convert it to a binary string. The UTF-8 encoding is required to
9214
9260
  // capture unicode characters correctly.
9215
- utf8BinaryString = buildBinaryString(new (TextEncoder || TextEncoderLite)('utf-8').encode(source));
9261
+ utf8BinaryString = buildBinaryString(new (TextEncoder || TextEncoderLite)().encode(source));
9216
9262
 
9217
9263
  data = "data:image/svg+xml;base64," + btoa(utf8BinaryString);
9218
9264
  img.src = data;
@@ -9478,6 +9524,17 @@ temporary images load their data.
9478
9524
  shape.strokeWidth = entry.options.points.lineWidth;
9479
9525
  iconHtml += getEntryIconHtml(shape);
9480
9526
  }
9527
+ // fallback for plugin-drawn series (pie, errorbars, etc.)
9528
+ // that don't turn on any of lines/bars/points — without
9529
+ // this the legend entry has a label but no icon. Upstream
9530
+ // flot/flot#1641, minus the switch to `else if` so series
9531
+ // that deliberately overlay (e.g. lines + points) keep
9532
+ // rendering both icons.
9533
+ if (iconHtml === '') {
9534
+ shape.name = 'box';
9535
+ shape.fillColor = entry.color;
9536
+ iconHtml += getEntryIconHtml(shape);
9537
+ }
9481
9538
 
9482
9539
  labelHtml = '<text x="' + shape.xPos + '" y="' + shape.yPos + '" text-anchor="start"><tspan dx="2em" dy="1.2em">' + shape.label + '</tspan></text>';
9483
9540
  html[j++] = '<g>' + iconHtml + labelHtml + '</g>';
@@ -9517,9 +9574,17 @@ temporary images load their data.
9517
9574
  legendEl.style.pointerEvents = 'none';
9518
9575
  placeholder.appendChild(legendEl);
9519
9576
  } else {
9520
- options.legend.container.innerHTML = html.join('');
9521
- options.legend.container.style.width = width + 'px';
9522
- options.legend.container.style.height = height + 'em';
9577
+ // Accept either a DOM Element or a jQuery-wrapped container.
9578
+ // Upstream flot/flot#1750 switched to `$(container).get(0)` to
9579
+ // always land on the underlying element; since this fork is
9580
+ // jQuery-optional, do the unwrap inline.
9581
+ var container = options.legend.container;
9582
+ if (container && typeof container.get === 'function' && container[0]) {
9583
+ container = container[0];
9584
+ }
9585
+ container.innerHTML = html.join('');
9586
+ container.style.width = width + 'px';
9587
+ container.style.height = height + 'em';
9523
9588
  }
9524
9589
  }
9525
9590
 
@@ -9613,6 +9678,14 @@ temporary images load their data.
9613
9678
  'width="1.5em" height="1.5em"' +
9614
9679
  '/>';
9615
9680
  break;
9681
+ case 'box':
9682
+ html = '<use xlink:href="#box" class="legendIcon" ' +
9683
+ 'x="' + x + '" ' +
9684
+ 'y="' + y + '" ' +
9685
+ 'fill="' + fill + '" ' +
9686
+ 'width="1.5em" height="1.5em"' +
9687
+ '/>';
9688
+ break;
9616
9689
  default:
9617
9690
  // default is circle
9618
9691
  html = '<use xlink:href="#circle" class="legendIcon" ' +
@@ -9635,6 +9708,12 @@ temporary images load their data.
9635
9708
  '<polyline points="0,15 5,5 10,10 15,0"/>' +
9636
9709
  '</symbol>' +
9637
9710
 
9711
+ // Fallback icon for plugin-drawn series that don't turn on
9712
+ // any of lines / bars / points. Upstream flot/flot#1641.
9713
+ '<symbol id="box" stroke-width="1" viewBox="-5 -5 25 25">' +
9714
+ '<rect x="0" y="0" width="15" height="15"/>' +
9715
+ '</symbol>' +
9716
+
9638
9717
  '<symbol id="area" stroke-width="1" viewBox="-5 -5 25 25">' +
9639
9718
  '<polyline points="0,15 5,5 10,10 15,0, 15,15, 0,15"/>' +
9640
9719
  '</symbol>' +
@@ -1,4 +1,4 @@
1
- /*! @kevinburke/flot v5.0.0 | MIT License | https://github.com/kevinburke/flot */
1
+ /*! @kevinburke/flot v5.1.1 | MIT License | https://github.com/kevinburke/flot */
2
2
  (function ($) {
3
3
  'use strict';
4
4
 
@@ -22,7 +22,9 @@
22
22
  },
23
23
 
24
24
  isSafari: function() {
25
- return /constructor/i.test(window.top.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window.top['safari'] || (typeof window.top.safari !== 'undefined' && window.top.safari.pushNotification));
25
+ var top = window.top;
26
+ if (!top) return false;
27
+ return /constructor/i.test(top.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!top['safari'] || (typeof top.safari !== 'undefined' && top.safari.pushNotification));
26
28
  },
27
29
 
28
30
  isMobileSafari: function() {
@@ -30,7 +32,7 @@
30
32
  },
31
33
 
32
34
  isOpera: function() {
33
- return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
35
+ return (!!window.opr && !!window.opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
34
36
  },
35
37
 
36
38
  isFirefox: function() {
@@ -348,7 +350,7 @@
348
350
  // already been rendered, and remove those that are no longer active.
349
351
 
350
352
  for (var layerKey in cache) {
351
- if (hasOwnProperty.call(cache, layerKey)) {
353
+ if (Object.prototype.hasOwnProperty.call(cache, layerKey)) {
352
354
  var layer = this.getSVGLayer(layerKey),
353
355
  layerCache = cache[layerKey];
354
356
 
@@ -356,10 +358,10 @@
356
358
  layer.style.display = 'none';
357
359
 
358
360
  for (var styleKey in layerCache) {
359
- if (hasOwnProperty.call(layerCache, styleKey)) {
361
+ if (Object.prototype.hasOwnProperty.call(layerCache, styleKey)) {
360
362
  var styleCache = layerCache[styleKey];
361
363
  for (var key in styleCache) {
362
- if (hasOwnProperty.call(styleCache, key)) {
364
+ if (Object.prototype.hasOwnProperty.call(styleCache, key)) {
363
365
  var val = styleCache[key],
364
366
  positions = val.positions;
365
367
 
@@ -713,14 +715,20 @@
713
715
  var layerCache = this._textCache[layer];
714
716
  if (layerCache != null) {
715
717
  for (var styleKey in layerCache) {
716
- if (hasOwnProperty.call(layerCache, styleKey)) {
718
+ if (Object.prototype.hasOwnProperty.call(layerCache, styleKey)) {
717
719
  var styleCache = layerCache[styleKey];
718
720
  for (var key in styleCache) {
719
- if (hasOwnProperty.call(styleCache, key)) {
721
+ if (Object.prototype.hasOwnProperty.call(styleCache, key)) {
722
+ // styleCache entries can exist without a
723
+ // positions array (e.g. when a Flot plugin
724
+ // populates the cache outside the normal
725
+ // addText path). Upstream flot/flot#1444.
720
726
  var positions = styleCache[key].positions;
721
- positions.forEach(function(position) {
722
- position.active = false;
723
- });
727
+ if (positions != null) {
728
+ positions.forEach(function(position) {
729
+ position.active = false;
730
+ });
731
+ }
724
732
  }
725
733
  }
726
734
  }
@@ -749,7 +757,7 @@
749
757
  Canvas.prototype.clearCache = function() {
750
758
  var cache = this._textCache;
751
759
  for (var layerKey in cache) {
752
- if (hasOwnProperty.call(cache, layerKey)) {
760
+ if (Object.prototype.hasOwnProperty.call(cache, layerKey)) {
753
761
  var layer = this.getSVGLayer(layerKey);
754
762
  while (layer.firstChild) {
755
763
  layer.removeChild(layer.firstChild);
@@ -3359,8 +3367,11 @@
3359
3367
  };
3360
3368
 
3361
3369
  // we might need an extra decimal since forced
3362
- // ticks don't necessarily fit naturally
3363
- if (!axis.mode && opts.tickDecimals == null) {
3370
+ // ticks don't necessarily fit naturally.
3371
+ // Guard against axis.delta <= 0 (min == max): Math.log(0)
3372
+ // is -Infinity, so extraDec would be +Infinity and
3373
+ // toFixed(Infinity) throws. Upstream #1869 / PR #1870.
3374
+ if (!axis.mode && opts.tickDecimals == null && axis.delta > 0) {
3364
3375
  var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),
3365
3376
  ts = axis.tickGenerator(axis, plot);
3366
3377
 
@@ -3578,6 +3589,8 @@
3578
3589
  markings = markings(axes);
3579
3590
  }
3580
3591
 
3592
+ if (!markings) return;
3593
+
3581
3594
  var i;
3582
3595
  for (i = 0; i < markings.length; ++i) {
3583
3596
  var m = markings[i],
@@ -4265,7 +4278,13 @@
4265
4278
  maxy = maxDistance / series.yaxis.scale,
4266
4279
  points = series.datapoints.points,
4267
4280
  ps = series.datapoints.pointsize,
4268
- smallestDistance = Number.POSITIVE_INFINITY;
4281
+ // Seed with maxDistance (or its square, matching the
4282
+ // default squared-distance metric) so points outside
4283
+ // the hover radius are never selected. Without this,
4284
+ // the maxx/maxy coordinate-space pre-filter is the
4285
+ // only radius check, and it's disabled for axes with
4286
+ // inverseTransform — see upstream flot/flot#1871.
4287
+ smallestDistance = computeDistance ? maxDistance : maxDistance * maxDistance;
4269
4288
 
4270
4289
  // with inverse transforms, we can't use the maxx/maxy
4271
4290
  // optimization, sadly
@@ -4465,7 +4484,16 @@
4465
4484
  } else {
4466
4485
  // assume this is a gradient spec; IE currently only
4467
4486
  // supports a simple vertical gradient properly, so that's
4468
- // what we support too
4487
+ // what we support too.
4488
+ // createLinearGradient throws if any coordinate is NaN or
4489
+ // ±Infinity (e.g. when the plot container has zero size
4490
+ // or the user supplies bogus bounds) — fall back to the
4491
+ // default solid color instead. Global isFinite coerces
4492
+ // null → 0 (finite), matching the drawSeriesPoints path
4493
+ // that passes (null, null). Upstream flot/flot#1867.
4494
+ if (!isFinite(top) || !isFinite(bottom)) {
4495
+ return defaultColor;
4496
+ }
4469
4497
  var gradient = ctx.createLinearGradient(0, top, 0, bottom);
4470
4498
 
4471
4499
  for (var i = 0, l = spec.colors.length; i < l; ++i) {
@@ -4493,7 +4521,7 @@
4493
4521
  // Plugin registry. Plugins push to this array to register themselves.
4494
4522
  var plugins = [];
4495
4523
 
4496
- var version = "5.0.0";
4524
+ var version = "5.1.1";
4497
4525
 
4498
4526
  // The main plot function.
4499
4527
  function plot(placeholder, data, options) {
@@ -5754,6 +5782,17 @@
5754
5782
  var minD = axis.p2c(opts.panRange[0]) - axis.p2c(axis.min);
5755
5783
  // calc max delta (revealing right edge of plot)
5756
5784
  var maxD = axis.p2c(opts.panRange[1]) - axis.p2c(axis.max);
5785
+ // For the y-axis, screen coordinates are inverted
5786
+ // (p2c(smaller v) > p2c(larger v)), so minD/maxD end up
5787
+ // with the opposite signs from the x-axis case. Swap
5788
+ // them so the clamp comparisons below keep their
5789
+ // x-axis semantics. Upstream flot/flot#1789, ports the
5790
+ // minimal form of PR #1793.
5791
+ if (axis.direction === 'y') {
5792
+ var swap = minD;
5793
+ minD = maxD;
5794
+ maxD = swap;
5795
+ }
5757
5796
  // limit delta to min or max if enabled
5758
5797
  if (opts.panRange[0] !== undefined && d >= maxD) d = maxD;
5759
5798
  if (opts.panRange[1] !== undefined && d <= minD) d = minD;
@@ -5918,6 +5957,13 @@
5918
5957
  var minD = p + axis.p2c(opts.panRange[0]) - axis.p2c(axisMin);
5919
5958
  // calc max delta (revealing right edge of plot)
5920
5959
  var maxD = p + axis.p2c(opts.panRange[1]) - axis.p2c(axisMax);
5960
+ // Same y-axis swap as plot.pan — see comment there.
5961
+ // Upstream flot/flot#1789 / PR #1793.
5962
+ if (axis.direction === 'y') {
5963
+ var swap = minD;
5964
+ minD = maxD;
5965
+ maxD = swap;
5966
+ }
5921
5967
  // limit delta to min or max if enabled
5922
5968
  if (opts.panRange[0] !== undefined && d >= maxD) d = maxD;
5923
5969
  if (opts.panRange[1] !== undefined && d <= minD) d = minD;
@@ -9215,7 +9261,7 @@
9215
9261
 
9216
9262
  // Encode the string as UTF-8 and convert it to a binary string. The UTF-8 encoding is required to
9217
9263
  // capture unicode characters correctly.
9218
- utf8BinaryString = buildBinaryString(new (TextEncoder || TextEncoderLite)('utf-8').encode(source));
9264
+ utf8BinaryString = buildBinaryString(new (TextEncoder || TextEncoderLite)().encode(source));
9219
9265
 
9220
9266
  data = "data:image/svg+xml;base64," + btoa(utf8BinaryString);
9221
9267
  img.src = data;
@@ -9481,6 +9527,17 @@
9481
9527
  shape.strokeWidth = entry.options.points.lineWidth;
9482
9528
  iconHtml += getEntryIconHtml(shape);
9483
9529
  }
9530
+ // fallback for plugin-drawn series (pie, errorbars, etc.)
9531
+ // that don't turn on any of lines/bars/points — without
9532
+ // this the legend entry has a label but no icon. Upstream
9533
+ // flot/flot#1641, minus the switch to `else if` so series
9534
+ // that deliberately overlay (e.g. lines + points) keep
9535
+ // rendering both icons.
9536
+ if (iconHtml === '') {
9537
+ shape.name = 'box';
9538
+ shape.fillColor = entry.color;
9539
+ iconHtml += getEntryIconHtml(shape);
9540
+ }
9484
9541
 
9485
9542
  labelHtml = '<text x="' + shape.xPos + '" y="' + shape.yPos + '" text-anchor="start"><tspan dx="2em" dy="1.2em">' + shape.label + '</tspan></text>';
9486
9543
  html[j++] = '<g>' + iconHtml + labelHtml + '</g>';
@@ -9520,9 +9577,17 @@
9520
9577
  legendEl.style.pointerEvents = 'none';
9521
9578
  placeholder.appendChild(legendEl);
9522
9579
  } else {
9523
- options.legend.container.innerHTML = html.join('');
9524
- options.legend.container.style.width = width + 'px';
9525
- options.legend.container.style.height = height + 'em';
9580
+ // Accept either a DOM Element or a jQuery-wrapped container.
9581
+ // Upstream flot/flot#1750 switched to `$(container).get(0)` to
9582
+ // always land on the underlying element; since this fork is
9583
+ // jQuery-optional, do the unwrap inline.
9584
+ var container = options.legend.container;
9585
+ if (container && typeof container.get === 'function' && container[0]) {
9586
+ container = container[0];
9587
+ }
9588
+ container.innerHTML = html.join('');
9589
+ container.style.width = width + 'px';
9590
+ container.style.height = height + 'em';
9526
9591
  }
9527
9592
  }
9528
9593
 
@@ -9616,6 +9681,14 @@
9616
9681
  'width="1.5em" height="1.5em"' +
9617
9682
  '/>';
9618
9683
  break;
9684
+ case 'box':
9685
+ html = '<use xlink:href="#box" class="legendIcon" ' +
9686
+ 'x="' + x + '" ' +
9687
+ 'y="' + y + '" ' +
9688
+ 'fill="' + fill + '" ' +
9689
+ 'width="1.5em" height="1.5em"' +
9690
+ '/>';
9691
+ break;
9619
9692
  default:
9620
9693
  // default is circle
9621
9694
  html = '<use xlink:href="#circle" class="legendIcon" ' +
@@ -9638,6 +9711,12 @@
9638
9711
  '<polyline points="0,15 5,5 10,10 15,0"/>' +
9639
9712
  '</symbol>' +
9640
9713
 
9714
+ // Fallback icon for plugin-drawn series that don't turn on
9715
+ // any of lines / bars / points. Upstream flot/flot#1641.
9716
+ '<symbol id="box" stroke-width="1" viewBox="-5 -5 25 25">' +
9717
+ '<rect x="0" y="0" width="15" height="15"/>' +
9718
+ '</symbol>' +
9719
+
9641
9720
  '<symbol id="area" stroke-width="1" viewBox="-5 -5 25 25">' +
9642
9721
  '<polyline points="0,15 5,5 10,10 15,0, 15,15, 0,15"/>' +
9643
9722
  '</symbol>' +