diff --git a/src/axis-internal.js b/src/axis-internal.js index 5e97845d0..f405e07c1 100644 --- a/src/axis-internal.js +++ b/src/axis-internal.js @@ -1,3 +1,5 @@ +import { getBBox } from './util'; + function AxisInternal(component, params) { var internal = this; internal.component = component; @@ -82,7 +84,7 @@ AxisInternal.prototype.updateTickTextCharSize = function (tick) { w: 5.5 }; tick.select('text').text(function(d) { return internal.textFormatted(d); }).each(function (d) { - var box = this.getBBox(), + var box = getBBox(this), text = internal.textFormatted(d), h = box.height, w = text ? (box.width / text.length) : undefined; diff --git a/src/axis.js b/src/axis.js index 32caec380..0563ebb15 100644 --- a/src/axis.js +++ b/src/axis.js @@ -3,7 +3,8 @@ import { isValue, isFunction, isString, - isEmpty + isEmpty, + getBBox } from './util'; import { AxisInternal @@ -333,7 +334,7 @@ Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) svg = dummy.append("svg").style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0), svg.append('g').call(axis).each(function () { $$.d3.select(this).selectAll('text').each(function () { - var box = this.getBBox(); + var box = getBBox(this); if (maxWidth < box.width) { maxWidth = box.width; } diff --git a/src/colorscale.js b/src/colorscale.js index 2fb4a6a17..1965ffbb6 100644 --- a/src/colorscale.js +++ b/src/colorscale.js @@ -1,6 +1,6 @@ import {ChartInternal} from './core'; import CLASS from "./class"; -import {isFunction} from './util'; +import {isFunction, getBBox} from './util'; function powerOfTen(d) { return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1; @@ -97,7 +97,7 @@ ChartInternal.prototype.drawColorScale = function () { ChartInternal.prototype.xForColorScale = function () { var $$ = this; - return $$.config.stanford_padding.right + $$.colorScale.node().getBBox().width; + return $$.config.stanford_padding.right + getBBox($$.colorScale.node()).width; }; ChartInternal.prototype.getColorScalePadding = function () { diff --git a/src/data.js b/src/data.js index 8d88799e0..ab8e11460 100644 --- a/src/data.js +++ b/src/data.js @@ -9,7 +9,8 @@ import { isArray, notEmpty, hasValue, - flattenArray + flattenArray, + getBBox } from './util'; ChartInternal.prototype.isEpochs = function (key) { @@ -439,7 +440,7 @@ ChartInternal.prototype.getDataLabelLength = function (min, max, key) { return $$.dataLabelFormat(d.id)(d); }) .each(function (d, i) { - lengths[i] = this.getBBox()[key] * paddingCoef; + lengths[i] = getBBox(this)[key] * paddingCoef; }) .remove(); return lengths; diff --git a/src/shape.bar.js b/src/shape.bar.js index 0e26b86a7..86d413692 100644 --- a/src/shape.bar.js +++ b/src/shape.bar.js @@ -1,6 +1,6 @@ import CLASS from './class'; import { ChartInternal } from './core'; -import { isValue } from './util'; +import { getBBox, isValue } from './util'; ChartInternal.prototype.initBar = function () { var $$ = this; @@ -123,7 +123,7 @@ ChartInternal.prototype.isWithinBar = function (mouse, that) { if (that.pathSegList.numberOfItems < 2) { return false; } - var box = that.getBBox(), + var box = getBBox(that), seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1), x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y), w = box.width, h = box.height, offset = 2, diff --git a/src/text.js b/src/text.js index 73439b1dc..4d4c8501d 100644 --- a/src/text.js +++ b/src/text.js @@ -1,5 +1,6 @@ import CLASS from './class'; import { ChartInternal } from './core'; +import { getBBox } from './util'; ChartInternal.prototype.initText = function () { var $$ = this; @@ -64,7 +65,7 @@ ChartInternal.prototype.getTextRect = function (text, cls, element) { .classed(cls ? cls : "", true) .style('font', font) .text(text) - .each(function () { rect = this.getBBox(); }); + .each(function () { rect = getBBox(this); }); dummy.remove(); return rect; }; @@ -81,7 +82,7 @@ ChartInternal.prototype.generateXYForText = function (areaIndices, barIndices, l }; ChartInternal.prototype.getXForText = function (points, d, textElement) { var $$ = this, - box = textElement.getBBox(), xPos, padding; + box = getBBox(textElement), xPos, padding; if ($$.config.axis_rotated) { padding = $$.isBarType(d) ? 4 : 6; xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1); @@ -100,7 +101,7 @@ ChartInternal.prototype.getXForText = function (points, d, textElement) { }; ChartInternal.prototype.getYForText = function (points, d, textElement) { var $$ = this, - box = textElement.getBBox(), + box = getBBox(textElement), yPos; if ($$.config.axis_rotated) { yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2; diff --git a/src/util.js b/src/util.js index 72f193073..b43e25483 100644 --- a/src/util.js +++ b/src/util.js @@ -11,12 +11,26 @@ export var getOption = function(options, key, defaultValue) { return isDefined(options[key]) ? options[key] : defaultValue; }; export var getPathBox = function(path) { - var box = path.getBBox(), + var box = getBBox(path), items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], minX = items[0].x, minY = Math.min(items[0].y, items[1].y); return { x: minX, y: minY, width: box.width, height: box.height }; }; +export var getBBox = function(element) { + try { + return element.getBBox(); + } catch (ignore) { + // Firefox will throw an exception if getBBox() is called whereas the + // element is rendered with display:none + // See https://github.com/c3js/c3/issues/2692 + + // The previous code was using `getBoundingClientRect` which was returning + // everything at 0 in this case so let's reproduce this behavior here. + + return { x: 0, y: 0, width: 0, height: 0 }; + } +}; export var hasValue = function(dict, value) { var found = false; Object.keys(dict).forEach(function(key) {