import Element from '../core/core.element';
-import {isObject} from '../helpers/helpers.core';
+import {toTRBL} from '../helpers/helpers.options';
/**
* Helper function to get the bounds of the bar regardless of the orientation
function parseBorderWidth(bar, maxW, maxH) {
const value = bar.options.borderWidth;
const skip = parseBorderSkipped(bar);
- let t, r, b, l;
-
- if (isObject(value)) {
- t = +value.top || 0;
- r = +value.right || 0;
- b = +value.bottom || 0;
- l = +value.left || 0;
- } else {
- t = r = b = l = +value || 0;
- }
+ const o = toTRBL(value);
return {
- t: skipOrLimit(skip.top, t, 0, maxH),
- r: skipOrLimit(skip.right, r, 0, maxW),
- b: skipOrLimit(skip.bottom, b, 0, maxH),
- l: skipOrLimit(skip.left, l, 0, maxW)
+ t: skipOrLimit(skip.top, o.top, 0, maxH),
+ r: skipOrLimit(skip.right, o.right, 0, maxW),
+ b: skipOrLimit(skip.bottom, o.bottom, 0, maxH),
+ l: skipOrLimit(skip.left, o.left, 0, maxW)
};
}
function inRange(bar, x, y, useFinalPosition) {
const skipX = x === null;
const skipY = y === null;
- const bounds = !bar || (skipX && skipY) ? false : getBarBounds(bar, useFinalPosition);
+ const skipBoth = skipX && skipY;
+ const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);
return bounds
&& (skipX || x >= bounds.left && x <= bounds.right)
* Binary search
* @param {array} table - the table search. must be sorted!
* @param {number} value - value to find
+ * @param {function} [cmp]
* @private
*/
-export function _lookup(table, value) {
+export function _lookup(table, value, cmp) {
+ cmp = cmp || ((index) => table[index] < value);
let hi = table.length - 1;
let lo = 0;
let mid;
while (hi - lo > 1) {
mid = (lo + hi) >> 1;
- if (table[mid] < value) {
+ if (cmp(mid)) {
lo = mid;
} else {
hi = mid;
* @param {number} value - value to find
* @private
*/
-export function _lookupByKey(table, key, value) {
- let hi = table.length - 1;
- let lo = 0;
- let mid;
-
- while (hi - lo > 1) {
- mid = (lo + hi) >> 1;
- if (table[mid][key] < value) {
- lo = mid;
- } else {
- hi = mid;
- }
- }
-
- return {lo, hi};
-}
+export const _lookupByKey = (table, key, value) =>
+ _lookup(table, value, index => table[index][key] < value);
/**
* Reverse binary search
* @param {number} value - value to find
* @private
*/
-export function _rlookupByKey(table, key, value) {
- let hi = table.length - 1;
- let lo = 0;
- let mid;
-
- while (hi - lo > 1) {
- mid = (lo + hi) >> 1;
- if (table[mid][key] < value) {
- hi = mid;
- } else {
- lo = mid;
- }
- }
-
- return {lo, hi};
-}
+export const _rlookupByKey = (table, key, value) =>
+ _lookup(table, value, index => table[index][key] >= value);
/**
* Return subset of `values` between `min` and `max` inclusive.
document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
}
-/** @return {number=} number or undefined if no constraint */
-function getConstraintWidth(domNode) {
- return getConstraintDimension(domNode, 'max-width', 'clientWidth');
-}
-
-/** @return {number=} number or undefined if no constraint */
-function getConstraintHeight(domNode) {
- return getConstraintDimension(domNode, 'max-height', 'clientHeight');
-}
-
/**
* @private
*/
return typeof measure === 'number' ? measure : fallback;
}
-export function getMaximumWidth(domNode) {
+function getMax(domNode, prop, fallback, paddings) {
const container = _getParentNode(domNode);
if (!container) {
- return fallbackIfNotValid(domNode.clientWidth, domNode.width);
+ return fallbackIfNotValid(domNode[prop], domNode[fallback]);
}
- const clientWidth = container.clientWidth;
- const paddingLeft = _calculatePadding(container, 'padding-left', clientWidth);
- const paddingRight = _calculatePadding(container, 'padding-right', clientWidth);
+ const value = container[prop];
+ const padding = paddings.reduce((acc, cur) => acc + _calculatePadding(container, 'padding-' + cur, value), 0);
- const w = clientWidth - paddingLeft - paddingRight;
- const cw = getConstraintWidth(domNode);
- return isNaN(cw) ? w : Math.min(w, cw);
+ const v = value - padding;
+ const cv = getConstraintDimension(domNode, 'max-' + fallback, prop);
+ return isNaN(cv) ? v : Math.min(v, cv);
}
-export function getMaximumHeight(domNode) {
- const container = _getParentNode(domNode);
- if (!container) {
- return fallbackIfNotValid(domNode.clientHeight, domNode.height);
- }
-
- const clientHeight = container.clientHeight;
- const paddingTop = _calculatePadding(container, 'padding-top', clientHeight);
- const paddingBottom = _calculatePadding(container, 'padding-bottom', clientHeight);
-
- const h = clientHeight - paddingTop - paddingBottom;
- const ch = getConstraintHeight(domNode);
- return isNaN(ch) ? h : Math.min(h, ch);
-}
+export const getMaximumWidth = (domNode) => getMax(domNode, 'clientWidth', 'width', ['left', 'right']);
+export const getMaximumHeight = (domNode) => getMax(domNode, 'clientHeight', 'height', ['top', 'bottom']);
export function retinaScale(chart, forceRatio) {
const pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1;
return size * value;
}
+const numberOrZero = v => +v || 0;
+
/**
- * Converts the given value into a padding object with pre-computed width/height.
+ * Converts the given value into a TRBL object.
* @param {number|object} value - If a number, set the value to all TRBL component,
* else, if an object, use defined properties and sets undefined ones to 0.
- * @returns {object} The padding values (top, right, bottom, left, width, height)
- * @since 2.7.0
+ * @returns {object} The padding values (top, right, bottom, left)
+ * @since 3.0.0
*/
-export function toPadding(value) {
+export function toTRBL(value) {
let t, r, b, l;
if (isObject(value)) {
- t = +value.top || 0;
- r = +value.right || 0;
- b = +value.bottom || 0;
- l = +value.left || 0;
+ t = numberOrZero(value.top);
+ r = numberOrZero(value.right);
+ b = numberOrZero(value.bottom);
+ l = numberOrZero(value.left);
} else {
- t = r = b = l = +value || 0;
+ t = r = b = l = numberOrZero(value);
}
return {
top: t,
right: r,
bottom: b,
- left: l,
- height: t + b,
- width: l + r
+ left: l
};
}
+/**
+ * Converts the given value into a padding object with pre-computed width/height.
+ * @param {number|object} value - If a number, set the value to all TRBL component,
+ * else, if an object, use defined properties and sets undefined ones to 0.
+ * @returns {object} The padding values (top, right, bottom, left, width, height)
+ * @since 2.7.0
+ */
+export function toPadding(value) {
+ const obj = toTRBL(value);
+
+ obj.width = obj.left + obj.right;
+ obj.height = obj.top + obj.bottom;
+
+ return obj;
+}
+
/**
* Parses font options and returns the font object.
* @param {object} options - A object that contains font options to be parsed.
cubicInterpolationMode: 'default' | 'monotone';
/**
* Bézier curve tension (0 for no Bézier curves).
- * @default 0.4 or 0 // TODO
+ * @default 0
*/
tension: number;
/**