billboard.js
Version:
Re-usable easy interface JavaScript chart library, based on D3 v4+
1,907 lines (1,684 loc) • 725 kB
JavaScript
/*!
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*
* billboard.js, JavaScript chart library
* https://naver.github.io/billboard.js/
*
* @version 3.3.3
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("d3-axis"), require("d3-brush"), require("d3-drag"), require("d3-dsv"), require("d3-ease"), require("d3-interpolate"), require("d3-scale"), require("d3-selection"), require("d3-shape"), require("d3-time-format"), require("d3-transition"), require("d3-zoom"));
else if(typeof define === 'function' && define.amd)
define(["d3-axis", "d3-brush", "d3-drag", "d3-dsv", "d3-ease", "d3-interpolate", "d3-scale", "d3-selection", "d3-shape", "d3-time-format", "d3-transition", "d3-zoom"], factory);
else {
var a = typeof exports === 'object' ? factory(require("d3-axis"), require("d3-brush"), require("d3-drag"), require("d3-dsv"), require("d3-ease"), require("d3-interpolate"), require("d3-scale"), require("d3-selection"), require("d3-shape"), require("d3-time-format"), require("d3-transition"), require("d3-zoom")) : factory(root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"], root["d3"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(this, function(__WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__9__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__13__) {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 1 */,
/* 2 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__2__;
/***/ }),
/* 3 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__3__;
/***/ }),
/* 4 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__4__;
/***/ }),
/* 5 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__5__;
/***/ }),
/* 6 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__6__;
/***/ }),
/* 7 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__7__;
/***/ }),
/* 8 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__8__;
/***/ }),
/* 9 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__9__;
/***/ }),
/* 10 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__10__;
/***/ }),
/* 11 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__11__;
/***/ }),
/* 12 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__12__;
/***/ }),
/* 13 */
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__13__;
/***/ })
/******/ ]);
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other entry modules.
!function() {
// extracted by mini-css-extract-plugin
}();
// This entry need to be wrapped in an IIFE because it need to be isolated against other entry modules.
!function() {
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"bb": function() { return /* reexport */ bb; },
"default": function() { return /* reexport */ bb; }
});
// NAMESPACE OBJECT: ./src/config/resolver/shape.ts
var resolver_shape_namespaceObject = {};
__webpack_require__.r(resolver_shape_namespaceObject);
__webpack_require__.d(resolver_shape_namespaceObject, {
"area": function() { return _area; },
"areaLineRange": function() { return areaLineRange; },
"areaSpline": function() { return areaSpline; },
"areaSplineRange": function() { return areaSplineRange; },
"areaStep": function() { return areaStep; },
"bar": function() { return resolver_shape_bar; },
"bubble": function() { return resolver_shape_bubble; },
"candlestick": function() { return resolver_shape_candlestick; },
"donut": function() { return shape_donut; },
"gauge": function() { return resolver_shape_gauge; },
"line": function() { return resolver_shape_line; },
"pie": function() { return shape_pie; },
"radar": function() { return resolver_shape_radar; },
"scatter": function() { return shape_scatter; },
"spline": function() { return shape_spline; },
"step": function() { return step; }
});
// NAMESPACE OBJECT: ./src/config/resolver/interaction.ts
var resolver_interaction_namespaceObject = {};
__webpack_require__.r(resolver_interaction_namespaceObject);
__webpack_require__.d(resolver_interaction_namespaceObject, {
"selection": function() { return _selectionModule; },
"subchart": function() { return subchartModule; },
"zoom": function() { return zoomModule; }
});
// EXTERNAL MODULE: external {"commonjs":"d3-time-format","commonjs2":"d3-time-format","amd":"d3-time-format","root":"d3"}
var external_commonjs_d3_time_format_commonjs2_d3_time_format_amd_d3_time_format_root_d3_ = __webpack_require__(4);
// EXTERNAL MODULE: external {"commonjs":"d3-selection","commonjs2":"d3-selection","amd":"d3-selection","root":"d3"}
var external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_ = __webpack_require__(2);
;// CONCATENATED MODULE: ./src/module/browser.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* Window object
* @private
*/
/* eslint-disable no-new-func, no-undef */
var win = function () {
var root = typeof globalThis === "object" && globalThis !== null && globalThis.Object === Object && globalThis || typeof global === "object" && global !== null && global.Object === Object && global || typeof self === "object" && self !== null && self.Object === Object && self;
return root || Function("return this")();
}();
/* eslint-enable no-new-func, no-undef */
// fallback for non-supported environments
win.requestIdleCallback = win.requestIdleCallback || function (cb) {
return setTimeout(cb, 1);
};
win.cancelIdleCallback = win.cancelIdleCallback || function (id) {
return clearTimeout(id);
};
var browser_doc = win == null ? void 0 : win.document;
;// CONCATENATED MODULE: ./src/config/const.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* Chart type constant
* @private
*/
var TYPE = {
AREA: "area",
AREA_LINE_RANGE: "area-line-range",
AREA_SPLINE: "area-spline",
AREA_SPLINE_RANGE: "area-spline-range",
AREA_STEP: "area-step",
BAR: "bar",
BUBBLE: "bubble",
CANDLESTICK: "candlestick",
DONUT: "donut",
GAUGE: "gauge",
LINE: "line",
PIE: "pie",
RADAR: "radar",
SCATTER: "scatter",
SPLINE: "spline",
STEP: "step"
};
/**
* Chart type module and its method from ChartInternal class, needed to be initialized.
* @private
*/
var TYPE_METHOD_NEEDED = {
AREA: "initArea",
AREA_LINE_RANGE: "initArea",
AREA_SPLINE: "initArea",
AREA_SPLINE_RANGE: "initArea",
AREA_STEP: "initArea",
BAR: "initBar",
BUBBLE: "initCircle",
CANDLESTICK: "initCandlestick",
DONUT: "initArc",
GAUGE: "initArc",
LINE: "initLine",
PIE: "initArc",
RADAR: "initCircle",
SCATTER: "initCircle",
SPLINE: "initLine",
STEP: "initLine"
};
/**
* chart types by category
* @private
*/
var TYPE_BY_CATEGORY = {
Area: [TYPE.AREA, TYPE.AREA_SPLINE, TYPE.AREA_SPLINE_RANGE, TYPE.AREA_LINE_RANGE, TYPE.AREA_STEP],
AreaRange: [TYPE.AREA_SPLINE_RANGE, TYPE.AREA_LINE_RANGE],
Arc: [TYPE.PIE, TYPE.DONUT, TYPE.GAUGE, TYPE.RADAR],
Line: [TYPE.LINE, TYPE.SPLINE, TYPE.AREA, TYPE.AREA_SPLINE, TYPE.AREA_SPLINE_RANGE, TYPE.AREA_LINE_RANGE, TYPE.STEP, TYPE.AREA_STEP],
Step: [TYPE.STEP, TYPE.AREA_STEP],
Spline: [TYPE.SPLINE, TYPE.AREA_SPLINE, TYPE.AREA_SPLINE_RANGE]
};
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/defineProperty.js
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
// EXTERNAL MODULE: external {"commonjs":"d3-brush","commonjs2":"d3-brush","amd":"d3-brush","root":"d3"}
var external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_ = __webpack_require__(3);
;// CONCATENATED MODULE: ./src/module/util.ts
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1, source; i < arguments.length; i++) { source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
* @ignore
*/
var isValue = function (v) {
return v || v === 0;
},
isFunction = function (v) {
return typeof v === "function";
},
isString = function (v) {
return typeof v === "string";
},
isNumber = function (v) {
return typeof v === "number";
},
isUndefined = function (v) {
return typeof v === "undefined";
},
isDefined = function (v) {
return typeof v !== "undefined";
},
isboolean = function (v) {
return typeof v === "boolean";
},
ceil10 = function (v) {
return Math.ceil(v / 10) * 10;
},
asHalfPixel = function (n) {
return Math.ceil(n) + .5;
},
diffDomain = function (d) {
return d[1] - d[0];
},
isObjectType = function (v) {
return typeof v === "object";
},
isEmpty = function (o) {
return isUndefined(o) || o === null || isString(o) && o.length === 0 || isObjectType(o) && !(o instanceof Date) && Object.keys(o).length === 0 || isNumber(o) && isNaN(o);
},
notEmpty = function (o) {
return !isEmpty(o);
},
isArray = function (arr) {
return Array.isArray(arr);
},
isObject = function (obj) {
return obj && !(obj != null && obj.nodeType) && isObjectType(obj) && !isArray(obj);
};
/**
* Get specified key value from object
* If default value is given, will return if given key value not found
* @param {object} options Source object
* @param {string} key Key value
* @param {*} defaultValue Default value
* @returns {*}
* @private
*/
function getOption(options, key, defaultValue) {
return isDefined(options[key]) ? options[key] : defaultValue;
}
/**
* Check if value exist in the given object
* @param {object} dict Target object to be checked
* @param {*} value Value to be checked
* @returns {boolean}
* @private
*/
function hasValue(dict, value) {
var found = !1;
Object.keys(dict).forEach(function (key) {
return dict[key] === value && (found = !0);
});
return found;
}
/**
* Call function with arguments
* @param {Function} fn Function to be called
* @param {*} thisArg "this" value for fn
* @param {*} args Arguments for fn
* @returns {boolean} true: fn is function, false: fn is not function
* @private
*/
function callFn(fn, thisArg) {
for (var isFn = isFunction(fn), _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
isFn && fn.call.apply(fn, [thisArg].concat(args));
return isFn;
}
/**
* Call function after all transitions ends
* @param {d3.transition} transition Transition
* @param {Fucntion} cb Callback function
* @private
*/
function endall(transition, cb) {
var n = 0,
end = function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
--n || cb.apply.apply(cb, [this].concat(args));
};
// if is transition selection
if ("duration" in transition) {
transition.each(function () {
return ++n;
}).on("end", end);
} else {
++n;
transition.call(end);
}
}
/**
* Replace tag sign to html entity
* @param {string} str Target string value
* @returns {string}
* @private
*/
function sanitise(str) {
return isString(str) ? str.replace(/</g, "<").replace(/>/g, ">") : str;
}
/**
* Set text value. If there's multiline add nodes.
* @param {d3Selection} node Text node
* @param {string} text Text value string
* @param {Array} dy dy value for multilined text
* @param {boolean} toMiddle To be alingned vertically middle
* @private
*/
function setTextValue(node, text, dy, toMiddle) {
if (dy === void 0) {
dy = [-1, 1];
}
if (toMiddle === void 0) {
toMiddle = !1;
}
if (!node || !isString(text)) {
return;
}
if (text.indexOf("\n") === -1) {
node.text(text);
} else {
var diff = [node.text(), text].map(function (v) {
return v.replace(/[\s\n]/g, "");
});
if (diff[0] !== diff[1]) {
var multiline = text.split("\n"),
len = toMiddle ? multiline.length - 1 : 1;
// reset possible text
node.html("");
multiline.forEach(function (v, i) {
node.append("tspan").attr("x", 0).attr("dy", (i === 0 ? dy[0] * len : dy[1]) + "em").text(v);
});
}
}
}
/**
* Substitution of SVGPathSeg API polyfill
* @param {SVGGraphicsElement} path Target svg element
* @returns {Array}
* @private
*/
function getRectSegList(path) {
/*
* seg1 ---------- seg2
* | |
* | |
* | |
* seg0 ---------- seg3
* */
var _path$getBBox = path.getBBox(),
x = _path$getBBox.x,
y = _path$getBBox.y,
width = _path$getBBox.width,
height = _path$getBBox.height;
return [{
x: x,
y: y + height
}, // seg0
{
x: x,
y: y
}, // seg1
{
x: x + width,
y: y
}, // seg2
{
x: x + width,
y: y + height
} // seg3
];
}
/**
* Get svg bounding path box dimension
* @param {SVGGraphicsElement} path Target svg element
* @returns {object}
* @private
*/
function getPathBox(path) {
var _path$getBoundingClie = path.getBoundingClientRect(),
width = _path$getBoundingClie.width,
height = _path$getBoundingClie.height,
items = getRectSegList(path),
x = items[0].x,
y = Math.min(items[0].y, items[1].y);
return {
x: x,
y: y,
width: width,
height: height
};
}
/**
* Get event's current position coordinates
* @param {object} event Event object
* @param {SVGElement|HTMLElement} element Target element
* @returns {Array} [x, y] Coordinates x, y array
* @private
*/
function getPointer(event, element) {
var _ref,
touches = event && ((_ref = event.touches || event.sourceEvent && event.sourceEvent.touches) == null ? void 0 : _ref[0]),
pointer = (0,external_commonjs_d3_selection_commonjs2_d3_selection_amd_d3_selection_root_d3_.pointer)(touches || event, element);
return pointer.map(function (v) {
return isNaN(v) ? 0 : v;
});
}
/**
* Return brush selection array
* @param {object} ctx Current instance
* @returns {d3.brushSelection}
* @private
*/
function getBrushSelection(ctx) {
var event = ctx.event,
$el = ctx.$el,
main = $el.subchart.main || $el.main,
selection;
// check from event
if (event && event.type === "brush") {
selection = event.selection; // check from brush area selection
} else if (main && (selection = main.select(".bb-brush").node())) {
selection = (0,external_commonjs_d3_brush_commonjs2_d3_brush_amd_d3_brush_root_d3_.brushSelection)(selection);
}
return selection;
}
/**
* Get boundingClientRect.
* Cache the evaluated value once it was called.
* @param {HTMLElement} node Target element
* @returns {object}
* @private
*/
function getBoundingRect(node) {
var needEvaluate = !("rect" in node) || "rect" in node && node.hasAttribute("width") && node.rect.width !== +node.getAttribute("width");
return needEvaluate ? node.rect = node.getBoundingClientRect() : node.rect;
}
/**
* Retrun random number
* @param {boolean} asStr Convert returned value as string
* @param {number} min Minimum value
* @param {number} max Maximum value
* @returns {number|string}
* @private
*/
function getRandom(asStr, min, max) {
if (asStr === void 0) {
asStr = !0;
}
if (min === void 0) {
min = 0;
}
if (max === void 0) {
max = 1e4;
}
var rand = Math.floor(Math.random() * (max - min) + min);
return asStr ? rand + "" : rand;
}
/**
* Find index based on binary search
* @param {Array} arr Data array
* @param {number} v Target number to find
* @param {number} start Start index of data array
* @param {number} end End index of data arr
* @param {boolean} isRotated Weather is roted axis
* @returns {number} Index number
* @private
*/
function findIndex(arr, v, start, end, isRotated) {
if (start > end) {
return -1;
}
var mid = Math.floor((start + end) / 2),
_arr$mid = arr[mid],
x = _arr$mid.x,
_arr$mid$w = _arr$mid.w,
w = _arr$mid$w === void 0 ? 0 : _arr$mid$w;
if (isRotated) {
x = arr[mid].y;
w = arr[mid].h;
}
if (v >= x && v <= x + w) {
return mid;
}
return v < x ? findIndex(arr, v, start, mid - 1, isRotated) : findIndex(arr, v, mid + 1, end, isRotated);
}
/**
* Check if brush is empty
* @param {object} ctx Bursh context
* @returns {boolean}
* @private
*/
function brushEmpty(ctx) {
var selection = getBrushSelection(ctx);
if (selection) {
// brush selected area
// two-dimensional: [[x0, y0], [x1, y1]]
// one-dimensional: [x0, x1] or [y0, y1]
return selection[0] === selection[1];
}
return !0;
}
/**
* Deep copy object
* @param {object} objectN Source object
* @returns {object} Cloned object
* @private
*/
function deepClone() {
for (var clone = function (v) {
if (isObject(v) && v.constructor) {
var r = new v.constructor();
for (var k in v) {
r[k] = clone(v[k]);
}
return r;
}
return v;
}, _len3 = arguments.length, objectN = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
objectN[_key3] = arguments[_key3];
}
return objectN.map(function (v) {
return clone(v);
}).reduce(function (a, c) {
return _objectSpread(_objectSpread({}, a), c);
});
}
/**
* Extend target from source object
* @param {object} target Target object
* @param {object|Array} source Source object
* @returns {object}
* @private
*/
function extend(target, source) {
if (target === void 0) {
target = {};
}
if (isArray(source)) {
source.forEach(function (v) {
return extend(target, v);
});
} // exclude name with only numbers
for (var p in source) {
if (/^\d+$/.test(p) || p in target) {
continue;
}
target[p] = source[p];
}
return target;
}
/**
* Return first letter capitalized
* @param {string} str Target string
* @returns {string} capitalized string
* @private
*/
var capitalize = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
/**
* Camelize from kebob style string
* @param {string} str Target string
* @param {string} separator Separator string
* @returns {string} camelized string
* @private
*/
function camelize(str, separator) {
if (separator === void 0) {
separator = "-";
}
return str.split(separator).map(function (v, i) {
return i ? v.charAt(0).toUpperCase() + v.slice(1).toLowerCase() : v.toLowerCase();
}).join("");
}
/**
* Convert to array
* @param {object} v Target to be converted
* @returns {Array}
* @private
*/
var toArray = function (v) {
return [].slice.call(v);
};
/**
* Get css rules for specified stylesheets
* @param {Array} styleSheets The stylesheets to get the rules from
* @returns {Array}
* @private
*/
function getCssRules(styleSheets) {
var rules = [];
styleSheets.forEach(function (sheet) {
try {
if (sheet.cssRules && sheet.cssRules.length) {
rules = rules.concat(toArray(sheet.cssRules));
}
} catch (e) {
console.error("Error while reading rules from " + sheet.href + ": " + e.toString());
}
});
return rules;
}
/**
* Gets the SVGMatrix of an SVGGElement
* @param {SVGElement} node Node element
* @returns {SVGMatrix} matrix
* @private
*/
function getTranslation(node) {
var transform = node ? node.transform : null,
baseVal = transform && transform.baseVal;
return baseVal && baseVal.numberOfItems ? baseVal.getItem(0).matrix : {
a: 0,
b: 0,
c: 0,
d: 0,
e: 0,
f: 0
};
}
/**
* Get unique value from array
* @param {Array} data Source data
* @returns {Array} Unique array value
* @private
*/
function getUnique(data) {
var isDate = data[0] instanceof Date,
d = (isDate ? data.map(Number) : data).filter(function (v, i, self) {
return self.indexOf(v) === i;
});
return isDate ? d.map(function (v) {
return new Date(v);
}) : d;
}
/**
* Merge array
* @param {Array} arr Source array
* @returns {Array}
* @private
*/
function mergeArray(arr) {
return arr && arr.length ? arr.reduce(function (p, c) {
return p.concat(c);
}) : [];
}
/**
* Merge object returning new object
* @param {object} target Target object
* @param {object} objectN Source object
* @returns {object} merged target object
* @private
*/
function mergeObj(target) {
for (var _len4 = arguments.length, objectN = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
objectN[_key4 - 1] = arguments[_key4];
}
if (!objectN.length || objectN.length === 1 && !objectN[0]) {
return target;
}
var source = objectN.shift();
if (isObject(target) && isObject(source)) {
Object.keys(source).forEach(function (key) {
var value = source[key];
if (isObject(value)) {
target[key] || (target[key] = {});
target[key] = mergeObj(target[key], value);
} else {
target[key] = isArray(value) ? value.concat() : value;
}
});
}
return mergeObj.apply(void 0, [target].concat(objectN));
}
/**
* Sort value
* @param {Array} data value to be sorted
* @param {boolean} isAsc true: asc, false: desc
* @returns {number|string|Date} sorted date
* @private
*/
function sortValue(data, isAsc) {
if (isAsc === void 0) {
isAsc = !0;
}
var fn;
if (data[0] instanceof Date) {
fn = isAsc ? function (a, b) {
return a - b;
} : function (a, b) {
return b - a;
};
} else {
if (isAsc && !data.every(isNaN)) {
fn = function (a, b) {
return a - b;
};
} else if (!isAsc) {
fn = function (a, b) {
return a > b && -1 || a < b && 1 || a === b && 0;
};
}
}
return data.concat().sort(fn);
}
/**
* Get min/max value
* @param {string} type 'min' or 'max'
* @param {Array} data Array data value
* @returns {number|Date|undefined}
* @private
*/
function getMinMax(type, data) {
var res = data.filter(function (v) {
return notEmpty(v);
});
if (res.length) {
if (isNumber(res[0])) {
res = Math[type].apply(Math, res);
} else if (res[0] instanceof Date) {
res = sortValue(res, type === "min")[0];
}
} else {
res = undefined;
}
return res;
}
/**
* Get range
* @param {number} start Start number
* @param {number} end End number
* @param {number} step Step number
* @returns {Array}
* @private
*/
var getRange = function (start, end, step) {
if (step === void 0) {
step = 1;
}
var res = [],
n = Math.max(0, Math.ceil((end - start) / step)) | 0;
for (var i = start; i < n; i++) {
res.push(start + i * step);
}
return res;
},
emulateEvent = {
mouse: function () {
var getParams = function () {
return {
bubbles: !1,
cancelable: !1,
screenX: 0,
screenY: 0,
clientX: 0,
clientY: 0
};
};
try {
// eslint-disable-next-line no-new
new MouseEvent("t");
return function (el, eventType, params) {
if (params === void 0) {
params = getParams();
}
el.dispatchEvent(new MouseEvent(eventType, params));
};
} catch (e) {
// Polyfills DOM4 MouseEvent
return function (el, eventType, params) {
if (params === void 0) {
params = getParams();
}
var mouseEvent = browser_doc.createEvent("MouseEvent"); // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, win, 0, // the event's mouse click count
params.screenX, params.screenY, params.clientX, params.clientY, !1, !1, !1, !1, 0, null);
el.dispatchEvent(mouseEvent);
};
}
}(),
touch: function touch(el, eventType, params) {
var touchObj = new Touch(mergeObj({
identifier: Date.now(),
target: el,
radiusX: 2.5,
radiusY: 2.5,
rotationAngle: 10,
force: .5
}, params));
el.dispatchEvent(new TouchEvent(eventType, {
cancelable: !0,
bubbles: !0,
shiftKey: !0,
touches: [touchObj],
targetTouches: [],
changedTouches: [touchObj]
}));
}
}; // emulate event
/**
* Process the template & return bound string
* @param {string} tpl Template string
* @param {object} data Data value to be replaced
* @returns {string}
* @private
*/
function tplProcess(tpl, data) {
var res = tpl;
for (var x in data) {
res = res.replace(new RegExp("{=" + x + "}", "g"), data[x]);
}
return res;
}
/**
* Get parsed date value
* (It must be called in 'ChartInternal' context)
* @param {Date|string|number} date Value of date to be parsed
* @returns {Date}
* @private
*/
function parseDate(date) {
var parsedDate;
if (date instanceof Date) {
parsedDate = date;
} else if (isString(date)) {
var config = this.config,
format = this.format;
parsedDate = format.dataTime(config.data_xFormat)(date);
} else if (isNumber(date) && !isNaN(date)) {
parsedDate = new Date(+date);
}
if (!parsedDate || isNaN(+parsedDate)) {
console && console.error && console.error("Failed to parse x '" + date + "' to Date object");
}
return parsedDate;
}
/**
* Return if the current doc is visible or not
* @returns {boolean}
* @private
*/
function isTabVisible() {
return !browser_doc.hidden;
}
/**
* Get the current input type
* @param {boolean} mouse Config value: interaction.inputType.mouse
* @param {boolean} touch Config value: interaction.inputType.touch
* @returns {string} "mouse" | "touch" | null
* @private
*/
function convertInputType(mouse, touch) {
var hasTouch = !1;
if (touch) {
// Some Edge desktop return true: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/20417074/
if (win.navigator && "maxTouchPoints" in win.navigator) {
hasTouch = win.navigator.maxTouchPoints > 0; // Ref: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
// On IE11 with IE9 emulation mode, ('ontouchstart' in window) is returning true
} else if ("ontouchmove" in win || win.DocumentTouch && browser_doc instanceof win.DocumentTouch) {
hasTouch = !0;
} else {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#avoiding_user_agent_detection
var mQ = win.matchMedia && matchMedia("(pointer:coarse)");
if (mQ && mQ.media === "(pointer:coarse)") {
hasTouch = !!mQ.matches;
}
}
}
var hasMouse = mouse && !hasTouch ? "onmouseover" in win : !1;
return hasMouse && "mouse" || hasTouch && "touch" || null;
}
;// CONCATENATED MODULE: ./src/module/error.ts
/**
* Copyright (c) 2021 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/* eslint no-console: "off" */
/**
* Check chart type module imports.
* @param {ChartInternal} ctx Context
* @private
*/
function checkModuleImport(ctx) {
var $$ = ctx,
config = $$.config,
type = "";
if (isEmpty(config.data_type || config.data_types) && !$$[TYPE_METHOD_NEEDED.LINE]) {
type = "line";
} else {
for (var x in TYPE_METHOD_NEEDED) {
var t = TYPE[x];
if ($$.hasType(t) && !$$[TYPE_METHOD_NEEDED[x]]) {
type = t;
break;
}
}
}
type && logError("Please, make sure if %c" + camelize(type), "module has been imported and specified correctly.");
}
/**
* Log error and throw error
* @param {string} head Message header
* @param {string} tail Message tail
* @private
*/
function logError(head, tail) {
var _window$console,
prefix = "[billboard.js]",
hasConsole = (_window$console = win.console) == null ? void 0 : _window$console.error;
if (hasConsole) {
console.error("\u274C " + prefix + " " + head, "background:red;color:white;display:block;font-size:15px", tail);
console.info("%cℹ️", "font-size:15px", "https://github.com/naver/billboard.js/wiki/CHANGELOG-v2#modularization-by-its-functionality");
}
throw Error(prefix + " " + head.replace(/\%c([a-z-]+)/i, "'$1' ") + " " + tail);
}
;// CONCATENATED MODULE: ./src/config/classes.ts
function classes_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function classes_objectSpread(target) { for (var i = 1, source; i < arguments.length; i++) { source = null != arguments[i] ? arguments[i] : {}; i % 2 ? classes_ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : classes_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* CSS class names definition
* @private
*/
var $COMMON = {
button: "bb-button",
chart: "bb-chart",
empty: "bb-empty",
main: "bb-main",
target: "bb-target",
EXPANDED: "_expanded_"
};
var $ARC = {
arc: "bb-arc",
arcLabelLine: "bb-arc-label-line",
arcs: "bb-arcs",
chartArc: "bb-chart-arc",
chartArcs: "bb-chart-arcs",
chartArcsBackground: "bb-chart-arcs-background",
chartArcsTitle: "bb-chart-arcs-title"
};
var $AREA = {
area: "bb-area",
areas: "bb-areas"
};
var $AXIS = {
axis: "bb-axis",
axisX: "bb-axis-x",
axisXLabel: "bb-axis-x-label",
axisY: "bb-axis-y",
axisY2: "bb-axis-y2",
axisY2Label: "bb-axis-y2-label",
axisYLabel: "bb-axis-y-label"
};
var $BAR = {
bar: "bb-bar",
bars: "bb-bars",
chartBar: "bb-chart-bar",
chartBars: "bb-chart-bars"
};
var $CANDLESTICK = {
candlestick: "bb-candlestick",
candlesticks: "bb-candlesticks",
chartCandlestick: "bb-chart-candlestick",
chartCandlesticks: "bb-chart-candlesticks",
valueDown: "bb-value-down",
valueUp: "bb-value-up"
};
var $CIRCLE = {
chartCircles: "bb-chart-circles",
circle: "bb-circle",
circles: "bb-circles"
};
var $COLOR = {
colorPattern: "bb-color-pattern",
colorScale: "bb-colorscale"
};
var $DRAG = {
dragarea: "bb-dragarea",
INCLUDED: "_included_"
};
var $GAUGE = {
chartArcsGaugeMax: "bb-chart-arcs-gauge-max",
chartArcsGaugeMin: "bb-chart-arcs-gauge-min",
chartArcsGaugeUnit: "bb-chart-arcs-gauge-unit",
chartArcsGaugeTitle: "bb-chart-arcs-gauge-title",
gaugeValue: "bb-gauge-value"
};
var $LEGEND = {
legend: "bb-legend",
legendBackground: "bb-legend-background",
legendItem: "bb-legend-item",
legendItemEvent: "bb-legend-item-event",
legendItemHidden: "bb-legend-item-hidden",
legendItemPoint: "bb-legend-item-point",
legendItemTile: "bb-legend-item-tile"
};
var $LINE = {
chartLine: "bb-chart-line",
chartLines: "bb-chart-lines",
line: "bb-line",
lines: "bb-lines"
};
var $EVENT = {
eventRect: "bb-event-rect",
eventRects: "bb-event-rects",
eventRectsMultiple: "bb-event-rects-multiple",
eventRectsSingle: "bb-event-rects-single"
};
var $FOCUS = {
focused: "bb-focused",
defocused: "bb-defocused",
legendItemFocused: "bb-legend-item-focused",
xgridFocus: "bb-xgrid-focus",
ygridFocus: "bb-ygrid-focus"
};
var $GRID = {
grid: "bb-grid",
gridLines: "bb-grid-lines",
xgrid: "bb-xgrid",
xgridLine: "bb-xgrid-line",
xgridLines: "bb-xgrid-lines",
xgrids: "bb-xgrids",
ygrid: "bb-ygrid",
ygridLine: "bb-ygrid-line",
ygridLines: "bb-ygrid-lines",
ygrids: "bb-ygrids"
};
var $RADAR = {
chartRadar: "bb-chart-radar",
chartRadars: "bb-chart-radars",
level: "bb-level",
levels: "bb-levels"
};
var $REGION = {
region: "bb-region",
regions: "bb-regions"
};
var $SELECT = {
selectedCircle: "bb-selected-circle",
selectedCircles: "bb-selected-circles",
SELECTED: "_selected_"
};
var $SHAPE = {
shape: "bb-shape",
shapes: "bb-shapes"
};
var $SUBCHART = {
brush: "bb-brush",
subchart: "bb-subchart"
};
var $TEXT = {
chartText: "bb-chart-text",
chartTexts: "bb-chart-texts",
text: "bb-text",
texts: "bb-texts",
title: "bb-title",
TextOverlapping: "text-overlapping"
};
var $TOOLTIP = {
tooltip: "bb-tooltip",
tooltipContainer: "bb-tooltip-container",
tooltipName: "bb-tooltip-name"
};
var $ZOOM = {
buttonZoomReset: "bb-zoom-reset",
zoomBrush: "bb-zoom-brush"
};
/* harmony default export */ var classes = (classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread(classes_objectSpread({}, $COMMON), $ARC), $AREA), $AXIS), $BAR), $CANDLESTICK), $CIRCLE), $COLOR), $DRAG), $GAUGE), $LEGEND), $LINE), $EVENT), $FOCUS), $GRID), $RADAR), $REGION), $SELECT), $SHAPE), $SUBCHART), $TEXT), $TOOLTIP), $ZOOM));
;// CONCATENATED MODULE: ./src/config/Store/Element.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* Elements class.
* @class Elements
* @ignore
* @private
*/
var Element = function () {
return {
chart: null,
main: null,
svg: null,
axis: {
// axes
x: null,
y: null,
y2: null,
subX: null
},
defs: null,
tooltip: null,
legend: null,
title: null,
subchart: {
main: null,
// $$.context
bar: null,
// $$.contextBar
line: null,
// $$.contextLine
area: null // $$.contextArea
},
arcs: null,
bar: null,
// mainBar,
candlestick: null,
line: null,
// mainLine,
area: null,
// mainArea,
circle: null,
// mainCircle,
radar: null,
text: null,
// mainText,
grid: {
main: null,
// grid (also focus)
x: null,
// xgrid,
y: null // ygrid,
},
gridLines: {
main: null,
// gridLines
x: null,
// xgridLines,
y: null // ygridLines
},
region: {
main: null,
// region
list: null // mainRegion
},
eventRect: null,
zoomResetBtn: null // drag zoom reset button
};
};
;// CONCATENATED MODULE: ./src/config/Store/State.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* State class.
* @class State
* @ignore
* @private
*/
var State = function () {
return {
// chart drawn area dimension, excluding axes
width: 0,
width2: 0,
height: 0,
height2: 0,
margin: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
margin2: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
margin3: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
arcWidth: 0,
arcHeight: 0,
xAxisHeight: 0,
hasAxis: !1,
hasRadar: !1,
current: {
// chart whole dimension
width: 0,
height: 0,
dataMax: 0,
maxTickWidths: {
x: {
size: 0,
ticks: [],
clipPath: 0,
domain: ""
},
y: {
size: 0,
domain: ""
},
y2: {
size: 0,
domain: ""
}
},
// current used chart type list
types: []
},
// legend
isLegendRight: !1,
isLegendInset: !1,
isLegendTop: !1,
isLegendLeft: !1,
legendStep: 0,
legendItemWidth: 0,
legendItemHeight: 0,
legendHasRendered: !1,
eventReceiver: {
currentIdx: -1,
// current event interaction index
rect: {},
// event rect's clientBoundingRect
data: [],
// event data bound of previoous eventRect
coords: [] // coordination value of previous eventRect
},
axis: {
x: {
padding: {
left: 0,
right: 0
},
tickCount: 0
}
},
rotatedPadding: {
left: 30,
right: 0,
top: 5
},
withoutFadeIn: {},
inputType: "",
datetimeId: "",
// clip id string
clip: {
id: "",
idXAxis: "",
idYAxis: "",
idXAxisTickTexts: "",
idGrid: "",
idSubchart: "",
// clipIdForSubchart
path: "",
pathXAxis: "",
pathYAxis: "",
pathXAxisTickTexts: "",
pathGrid: ""
},
// status
event: null,
// event object
dragStart: null,
dragging: !1,
flowing: !1,
cancelClick: !1,
mouseover: !1,
rendered: !1,
transiting: !1,
redrawing: !1,
// if redraw() is on process
resizing: !1,
// resize event called
toggling: !1,
// legend toggle
zooming: !1,
hasNegativeValue: !1,
hasPositiveValue: !0,
orgAreaOpacity: "0.2",
// ID strings
hiddenTargetIds: [],
hiddenLegendIds: [],
focusedTargetIds: [],
defocusedTargetIds: [],
// value for Arc
radius: 0,
innerRadius: 0,
outerRadius: undefined,
innerRadiusRatio: 0,
gaugeArcWidth: 0,
radiusExpanded: 0,
// xgrid attribute
xgridAttr: {
x1: null,
x2: null,
y1: null,
y2: null
}
};
};
;// CONCATENATED MODULE: ./src/config/Store/Store.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
// mapping
var Store_classes = {
element: Element,
state: State
};
/**
* Internal store class.
* @class Store
* @ignore
* @private
*/
var Store = /*#__PURE__*/function () {
function Store() {
var _this = this;
Object.keys(Store_classes).forEach(function (v) {
_this[v] = new Store_classes[v]();
});
}
var _proto = Store.prototype;
_proto.getStore = function getStore(name) {
return this[name];
};
return Store;
}();
;// CONCATENATED MODULE: ./src/config/Options/common/main.ts
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* main config options
*/
/* harmony default export */ var main = ({
/**
* Specify the CSS selector or the element which the chart will be set to. D3 selection object can be specified also.<br>
* If other chart is set already, it will be replaced with the new one (only one chart can be set in one element).
* - **NOTE:** In case of element doesn't exist or not specified, will add a `<div>` element to the body.
* @name bindto
* @memberof Options
* @property {string|HTMLElement|d3.selection|object} [bindto="#chart"] Specify the element where chart will be drawn.
* @property {string|HTMLElement|d3.selection} bindto.element="#chart" Specify the element where chart will be drawn.
* @property {string} [bindto.classname=bb] Specify the class name of bind element.<br>
* **NOTE:** When class name isn't `bb`, then you also need to update the default CSS to be rendered correctly.
* @default #chart
* @example
* bindto: "#myContainer"
*
* // or HTMLElement
* bindto: document.getElementById("myContainer")
*
* // or D3 selection object
* bindto: d3.select("#myContainer")
*
* // or to change default classname
* bindto: {
* element: "#chart",
* classname: "bill-board" // ex) <div id='chart' class='bill-board'>
* }
*/
bindto: "#chart",
/**
* Set chart background.
* @name background
* @memberof Options
* @property {object} background background object
* @property {string} background.class Specify the class name for background element.
* @property {string} background.color Specify the fill color for background element.<br>**NOTE:** Will be ignored if `imgUrl` option is set.
* @property {string} background.imgUrl Specify the image url string for background.
* @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Background)
* @example
* background: {
* class: "myClass",
* color: "red",
*
* // Set image url for background.
* // If specified, 'color' option will be ignored.
* imgUrl: "https://naver.github.io/billboard.js/img/logo/billboard.js.svg",
* }
*/
background: {},
/**
* Set 'clip-path' attribute for chart element
* - **NOTE:**
* > When is false, chart node element is positioned after the axis node in DOM tree hierarchy.
* > Is to make chart element positioned over axis element.
* @name clipPath
* @memberof Options
* @type {boolean}
* @default true
* @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.clipPath)
* @example
* // don't set 'clip-path' attribute
* clipPath: false
*/
clipPath: !0,
/**
* Set svg element's class name
* @name svg
* @memberof Options
* @type {object}
* @property {object} [svg] svg object
* @property {string} [svg.classname] class name for svg element
* @example
* svg: {
* classname: "test_class"
* }
*/
svg_classname: undefined,
/**
* The desired size of the chart element.
* If value is not specified, the width of the chart will be calculated by the size of the parent element it's appended to.
* @name size
* @memberof Options
* @type {object}
* @property {object} [size] size object
* @property {number} [size.width] width of the chart element
* @property {number} [size.height] height of the chart element
* @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.ChartSize)
* @example
* size: {
* width: 640,
* height: 480
* }
*/
size_width: undefined,
size_height: undefined,
/**
* The padding of the chart element.
* @name padding
* @memberof Options
* @type {object}
* @property {object|boolean} [padding=true] Set padding of chart, and accepts object or boolean type.
* - `Object`: Specify each side's padding.
* - `false`: Remove padding completely and make shape to fully occupy the container element.
* - In this case, axes and subchart will be hidden.
* - To adjust some padding from this state, use `axis.[x|y].padding` option.
* @property {number} [padding.top] padding on the top of chart
* @property {number} [padding.right] padding on the right of chart
* @property {number} [padding.bottom] padding on the bottom of chart
* @property {number} [padding.left] padding on the left of chart
* @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Padding)
* @example
* // remove padding completely.
* padding: false,
*
* // or specify padding value for each side
* padding: {
* top: 20,
* right: 20,
* bottom: 20,
* left: 20
* }
*/
padding: !0,
padding_left: undefined,
padding_right: undefined,
padding_top: undefined,
padding_bottom: undefined,
/**
* Set chart resize options
* @name resize
* @memberof Options
* @type {object}
* @property {object} [resize] resize object
* @property {boolean} [resize.auto=true] Set chart resize automatically on viewport changes.
* @example
* resize: {
* auto: false
* }
*/
resize_auto: !0,
/**
* Set a callback to execute when mouse/touch enters the chart.
* @name onover
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onover: function() {
* this; // chart instance itself
* ...
* }
*/
onover: undefined,
/**
* Set a callback to execute when mouse/touch leaves the chart.
* @name onout
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onout: function() {
* this; // chart instance itself
* ...
* }
*/
onout: undefined,
/**
* Set a callback to execute when user resizes the screen.
* @name onresize
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onresize: function() {
* this; // chart instance itself
* ...
* }
*/
onresize: undefined,
/**
* Set a callback to execute when screen resize finished.
* @name onresized
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onresized: function() {
* this; // chart instance itself
* ...
* }
*/
onresized: undefined,
/**
* Set a callback to execute before the chart is initialized
* @name onbeforeinit
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onbeforeinit: function() {
* this; // chart instance itself
* ...
* }
*/
onbeforeinit: undefined,
/**
* Set a callback to execute when the chart is initialized.
* @name oninit
* @memberof Options
* @type {Function}
* @default undefined
* @example
* oninit: function() {
* this; // chart instance itself
* ...
* }
*/
oninit: undefined,
/**
* Set a callback to execute after the chart is initialized
* @name onafterinit
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onafterinit: function() {
* this; // chart instance itself
* ...
* }
*/
onafterinit: undefined,
/**
* Set a callback which is executed when the chart is rendered. Basically, this callback will be called in each time when the chart is redrawed.
* @name onrendered
* @memberof Options
* @type {Function}
* @default undefined
* @example
* onrendered: function() {
* this; // chart instance itself
* ...
* }
*/
onrendered: undefined,
/**
* Set duration of transition (in milliseconds) for chart a