UNPKG

billboard.js

Version:

Re-usable easy interface JavaScript chart library, based on D3 v4+

1,907 lines (1,684 loc) 725 kB
/*! * 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, "&lt;").replace(/>/g, "&gt;") : 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