UNPKG

673 kBSource Map (JSON)View Raw
1{"version":3,"file":"billboard.js","sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///./src/scss/billboard.scss?98ba","webpack:///external {\"commonjs\":\"d3-time-format\",\"commonjs2\":\"d3-time-format\",\"amd\":\"d3-time-format\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-selection\",\"commonjs2\":\"d3-selection\",\"amd\":\"d3-selection\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-transition\",\"commonjs2\":\"d3-transition\",\"amd\":\"d3-transition\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-axis\",\"commonjs2\":\"d3-axis\",\"amd\":\"d3-axis\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-scale\",\"commonjs2\":\"d3-scale\",\"amd\":\"d3-scale\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-brush\",\"commonjs2\":\"d3-brush\",\"amd\":\"d3-brush\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-dsv\",\"commonjs2\":\"d3-dsv\",\"amd\":\"d3-dsv\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-drag\",\"commonjs2\":\"d3-drag\",\"amd\":\"d3-drag\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-shape\",\"commonjs2\":\"d3-shape\",\"amd\":\"d3-shape\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-interpolate\",\"commonjs2\":\"d3-interpolate\",\"amd\":\"d3-interpolate\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-color\",\"commonjs2\":\"d3-color\",\"amd\":\"d3-color\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-zoom\",\"commonjs2\":\"d3-zoom\",\"amd\":\"d3-zoom\",\"root\":\"d3\"}","webpack:///external {\"commonjs\":\"d3-ease\",\"commonjs2\":\"d3-ease\",\"amd\":\"d3-ease\",\"root\":\"d3\"}","webpack:///./node_modules/@babel/runtime/helpers/esm/classCallCheck.js","webpack:///./node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js","webpack:///./node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js","webpack:///./node_modules/@babel/runtime/helpers/esm/nonIterableRest.js","webpack:///./node_modules/@babel/runtime/helpers/esm/slicedToArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/createClass.js","webpack:///./src/config/classes.js","webpack:///./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js","webpack:///./node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js","webpack:///./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/typeof.js","webpack:///./src/internals/browser.js","webpack:///./src/internals/util.js","webpack:///./src/axis/AxisRendererHelper.js","webpack:///./src/axis/AxisRenderer.js","webpack:///./src/axis/Axis.js","webpack:///./src/internals/ChartInternal.js","webpack:///./src/internals/Chart.js","webpack:///./src/config/Options.js","webpack:///./src/config/config.js","webpack:///./src/internals/scale.js","webpack:///./src/internals/domain.js","webpack:///./src/data/data.js","webpack:///./src/data/data.convert.js","webpack:///./src/data/data.load.js","webpack:///./src/internals/category.js","webpack:///./src/interactions/interaction.js","webpack:///./src/internals/size.js","webpack:///./src/shape/shape.js","webpack:///./src/shape/arc.js","webpack:///./src/shape/bar.js","webpack:///./src/shape/bubble.js","webpack:///./src/shape/line.js","webpack:///./src/shape/point.js","webpack:///./src/shape/radar.js","webpack:///./src/internals/text.js","webpack:///./src/internals/type.js","webpack:///./src/internals/grid.js","webpack:///./src/internals/tooltip.js","webpack:///./src/internals/legend.js","webpack:///./src/internals/title.js","webpack:///./src/internals/clip.js","webpack:///./src/internals/region.js","webpack:///./src/interactions/drag.js","webpack:///./src/internals/selection.js","webpack:///./src/interactions/subchart.js","webpack:///./src/interactions/zoom.js","webpack:///./src/internals/color.js","webpack:///./src/internals/format.js","webpack:///./src/internals/cache.js","webpack:///./src/internals/class.js","webpack:///./src/api/api.focus.js","webpack:///./src/api/api.show.js","webpack:///./src/api/api.zoom.js","webpack:///./src/api/api.load.js","webpack:///./src/api/api.flow.js","webpack:///./src/api/api.selection.js","webpack:///./src/api/api.transform.js","webpack:///./src/api/api.group.js","webpack:///./src/api/api.grid.js","webpack:///./src/api/api.region.js","webpack:///./src/api/api.data.js","webpack:///./src/api/api.category.js","webpack:///./src/api/api.color.js","webpack:///./src/api/api.x.js","webpack:///./src/api/api.axis.js","webpack:///./src/api/api.legend.js","webpack:///./src/api/api.chart.js","webpack:///./src/api/api.tooltip.js","webpack:///./src/api/api.export.js","webpack:///./src/core.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"d3-time-format\"), require(\"d3-selection\"), require(\"d3-transition\"), require(\"d3-axis\"), require(\"d3-scale\"), require(\"d3-brush\"), require(\"d3-dsv\"), require(\"d3-drag\"), require(\"d3-shape\"), require(\"d3-interpolate\"), require(\"d3-color\"), require(\"d3-zoom\"), require(\"d3-ease\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"d3-time-format\", \"d3-selection\", \"d3-transition\", \"d3-axis\", \"d3-scale\", \"d3-brush\", \"d3-dsv\", \"d3-drag\", \"d3-shape\", \"d3-interpolate\", \"d3-color\", \"d3-zoom\", \"d3-ease\"], factory);\n\telse {\n\t\tvar a = typeof exports === 'object' ? factory(require(\"d3-time-format\"), require(\"d3-selection\"), require(\"d3-transition\"), require(\"d3-axis\"), require(\"d3-scale\"), require(\"d3-brush\"), require(\"d3-dsv\"), require(\"d3-drag\"), require(\"d3-shape\"), require(\"d3-interpolate\"), require(\"d3-color\"), require(\"d3-zoom\"), require(\"d3-ease\")) : 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\"], root[\"d3\"]);\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(this, function(__WEBPACK_EXTERNAL_MODULE__2__, __WEBPACK_EXTERNAL_MODULE__3__, __WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__5__, __WEBPACK_EXTERNAL_MODULE__6__, __WEBPACK_EXTERNAL_MODULE__7__, __WEBPACK_EXTERNAL_MODULE__8__, __WEBPACK_EXTERNAL_MODULE__9__, __WEBPACK_EXTERNAL_MODULE__10__, __WEBPACK_EXTERNAL_MODULE__11__, __WEBPACK_EXTERNAL_MODULE__12__, __WEBPACK_EXTERNAL_MODULE__13__, __WEBPACK_EXTERNAL_MODULE__14__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","// extracted by mini-css-extract-plugin","module.exports = __WEBPACK_EXTERNAL_MODULE__2__;","module.exports = __WEBPACK_EXTERNAL_MODULE__3__;","module.exports = __WEBPACK_EXTERNAL_MODULE__4__;","module.exports = __WEBPACK_EXTERNAL_MODULE__5__;","module.exports = __WEBPACK_EXTERNAL_MODULE__6__;","module.exports = __WEBPACK_EXTERNAL_MODULE__7__;","module.exports = __WEBPACK_EXTERNAL_MODULE__8__;","module.exports = __WEBPACK_EXTERNAL_MODULE__9__;","module.exports = __WEBPACK_EXTERNAL_MODULE__10__;","module.exports = __WEBPACK_EXTERNAL_MODULE__11__;","module.exports = __WEBPACK_EXTERNAL_MODULE__12__;","module.exports = __WEBPACK_EXTERNAL_MODULE__13__;","module.exports = __WEBPACK_EXTERNAL_MODULE__14__;","export default function _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}","export default function _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}","export default function _iterableToArrayLimit(arr, i) {\n if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === \"[object Arguments]\")) {\n return;\n }\n\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}","export default function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n}","import arrayWithHoles from \"./arrayWithHoles\";\nimport iterableToArrayLimit from \"./iterableToArrayLimit\";\nimport nonIterableRest from \"./nonIterableRest\";\nexport default function _slicedToArray(arr, i) {\n return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();\n}","function _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nexport default function _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\n/**\n * CSS class names definition\n * @private\n */\nexport default {\n\tarc: \"bb-arc\",\n\tarcLabelLine: \"bb-arc-label-line\",\n\tarcs: \"bb-arcs\",\n\tarea: \"bb-area\",\n\tareas: \"bb-areas\",\n\taxis: \"bb-axis\",\n\taxisX: \"bb-axis-x\",\n\taxisXLabel: \"bb-axis-x-label\",\n\taxisY: \"bb-axis-y\",\n\taxisY2: \"bb-axis-y2\",\n\taxisY2Label: \"bb-axis-y2-label\",\n\taxisYLabel: \"bb-axis-y-label\",\n\tbar: \"bb-bar\",\n\tbars: \"bb-bars\",\n\tbrush: \"bb-brush\",\n\tbutton: \"bb-button\",\n\tbuttonZoomReset: \"bb-zoom-reset\",\n\tchart: \"bb-chart\",\n\tchartArc: \"bb-chart-arc\",\n\tchartArcs: \"bb-chart-arcs\",\n\tchartArcsBackground: \"bb-chart-arcs-background\",\n\tchartArcsGaugeMax: \"bb-chart-arcs-gauge-max\",\n\tchartArcsGaugeMin: \"bb-chart-arcs-gauge-min\",\n\tchartArcsGaugeUnit: \"bb-chart-arcs-gauge-unit\",\n\tchartArcsTitle: \"bb-chart-arcs-title\",\n\tchartArcsGaugeTitle: \"bb-chart-arcs-gauge-title\",\n\tchartBar: \"bb-chart-bar\",\n\tchartBars: \"bb-chart-bars\",\n\tchartLine: \"bb-chart-line\",\n\tchartLines: \"bb-chart-lines\",\n\tchartRadar: \"bb-chart-radar\",\n\tchartRadars: \"bb-chart-radars\",\n\tchartText: \"bb-chart-text\",\n\tchartTexts: \"bb-chart-texts\",\n\tcircle: \"bb-circle\",\n\tcircles: \"bb-circles\",\n\tcolorPattern: \"bb-color-pattern\",\n\tcolorScale: \"bb-colorscale\",\n\tdefocused: \"bb-defocused\",\n\tdragarea: \"bb-dragarea\",\n\tempty: \"bb-empty\",\n\teventRect: \"bb-event-rect\",\n\teventRects: \"bb-event-rects\",\n\teventRectsMultiple: \"bb-event-rects-multiple\",\n\teventRectsSingle: \"bb-event-rects-single\",\n\tfocused: \"bb-focused\",\n\tgaugeValue: \"bb-gauge-value\",\n\tgrid: \"bb-grid\",\n\tgridLines: \"bb-grid-lines\",\n\tlegendBackground: \"bb-legend-background\",\n\tlegendItem: \"bb-legend-item\",\n\tlegendItemEvent: \"bb-legend-item-event\",\n\tlegendItemFocused: \"bb-legend-item-focused\",\n\tlegendItemHidden: \"bb-legend-item-hidden\",\n\tlegendItemPoint: \"bb-legend-item-point\",\n\tlegendItemTile: \"bb-legend-item-tile\",\n\tlevel: \"bb-level\",\n\tlevels: \"bb-levels\",\n\tline: \"bb-line\",\n\tlines: \"bb-lines\",\n\tregion: \"bb-region\",\n\tregions: \"bb-regions\",\n\tselectedCircle: \"bb-selected-circle\",\n\tselectedCircles: \"bb-selected-circles\",\n\tshape: \"bb-shape\",\n\tshapes: \"bb-shapes\",\n\tstanfordElements: \"bb-stanford-elements\",\n\tstanfordLine: \"bb-stanford-line\",\n\tstanfordLines: \"bb-stanford-lines\",\n\tstanfordRegion: \"bb-stanford-region\",\n\tstanfordRegions: \"bb-stanford-regions\",\n\ttarget: \"bb-target\",\n\ttext: \"bb-text\",\n\ttexts: \"bb-texts\",\n\ttitle: \"bb-title\",\n\ttooltip: \"bb-tooltip\",\n\ttooltipContainer: \"bb-tooltip-container\",\n\ttooltipName: \"bb-tooltip-name\",\n\txgrid: \"bb-xgrid\",\n\txgridFocus: \"bb-xgrid-focus\",\n\txgridLine: \"bb-xgrid-line\",\n\txgridLines: \"bb-xgrid-lines\",\n\txgrids: \"bb-xgrids\",\n\tygrid: \"bb-ygrid\",\n\tygridFocus: \"bb-ygrid-focus\",\n\tygridLine: \"bb-ygrid-line\",\n\tygridLines: \"bb-ygrid-lines\",\n\tygrids: \"bb-ygrids\",\n\tzoomBrush: \"bb-zoom-brush\",\n\tzoomRect: \"bb-zoom-rect\",\n\tEXPANDED: \"_expanded_\",\n\tSELECTED: \"_selected_\",\n\tINCLUDED: \"_included_\",\n\tTextOverlapping: \"text-overlapping\"\n};\n","export default function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n }\n}","export default function _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n}","export default function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n}","import arrayWithoutHoles from \"./arrayWithoutHoles\";\nimport iterableToArray from \"./iterableToArray\";\nimport nonIterableSpread from \"./nonIterableSpread\";\nexport default function _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();\n}","export default function _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\n/**\n * Window object\n * @module\n * @ignore\n */\n/* eslint-disable no-new-func, no-undef */\nconst win = (() => {\n\tconst def = o => typeof o !== \"undefined\" && o;\n\n\treturn def(self) || def(window) || def(global) || def(globalThis) || Function(\"return this\")();\n})();\n/* eslint-enable no-new-func, no-undef */\n\nconst doc = win && win.document;\n\nexport {\n\twin as window,\n\tdoc as document\n};\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n * @ignore\n */\nimport {event as d3Event} from \"d3-selection\";\nimport {brushSelection as d3BrushSelection} from \"d3-brush\";\nimport {document, window} from \"./browser\";\nimport CLASS from \"../config/classes\";\n\nconst isValue = v => v || v === 0;\nconst isFunction = v => typeof v === \"function\";\nconst isString = v => typeof v === \"string\";\nconst isNumber = v => typeof v === \"number\";\nconst isUndefined = v => typeof v === \"undefined\";\nconst isDefined = v => typeof v !== \"undefined\";\nconst isBoolean = v => typeof v === \"boolean\";\nconst ceil10 = v => Math.ceil(v / 10) * 10;\nconst asHalfPixel = n => Math.ceil(n) + 0.5;\nconst diffDomain = d => d[1] - d[0];\nconst isObjectType = v => typeof v === \"object\";\nconst isEmpty = o => (\n\tisUndefined(o) || o === null ||\n\t(isString(o) && o.length === 0) ||\n\t(isObjectType(o) && !(o instanceof Date) && Object.keys(o).length === 0) ||\n\t(isNumber(o) && isNaN(o))\n);\nconst notEmpty = o => !isEmpty(o);\n\n/**\n * Check if is array\n * @param {Array} arr\n * @returns {Boolean}\n * @private\n */\nconst isArray = arr => arr && arr.constructor === Array;\n\n/**\n * Check if is object\n * @param {Object} obj\n * @returns {Boolean}\n * @private\n */\nconst isObject = obj => obj && !obj.nodeType && isObjectType(obj) && !isArray(obj);\n\nconst getOption = (options, key, defaultValue) => (\n\tisDefined(options[key]) ? options[key] : defaultValue\n);\n\nconst hasValue = (dict, value) => {\n\tlet found = false;\n\n\tObject.keys(dict).forEach(key => (dict[key] === value) && (found = true));\n\n\treturn found;\n};\n\n/**\n * Call function with arguments\n * @param {Function} fn Function to be called\n * @param {*} args Arguments\n * @return {Boolean} true: fn is function, false: fn is not function\n * @private\n */\nconst callFn = (fn, ...args) => {\n\tconst isFn = isFunction(fn);\n\n\tisFn && fn.call(...args);\n\treturn isFn;\n};\n\n/**\n * Replace tag sign to html entity\n * @param {String} str\n * @return {String}\n * @private\n */\nconst sanitise = str => (isString(str) ? str.replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\") : str);\n\n/**\n * Set text value. If there's multiline add nodes.\n * @param {d3Selection} node Text node\n * @param {String} text Text value string\n * @param {Array} dy dy value for multilined text\n * @param {Boolean} toMiddle To be alingned vertically middle\n * @private\n */\nconst setTextValue = (node, text, dy = [-1, 1], toMiddle = false) => {\n\tif (!node || !isString(text)) {\n\t\treturn;\n\t}\n\n\tif (text.indexOf(\"\\n\") === -1) {\n\t\tnode.text(text);\n\t} else {\n\t\tconst diff = [node.text(), text].map(v => v.replace(/[\\s\\n]/g, \"\"));\n\n\t\tif (diff[0] !== diff[1]) {\n\t\t\tconst multiline = text.split(\"\\n\");\n\t\t\tconst len = toMiddle ? multiline.length - 1 : 1;\n\n\t\t\t// reset possible text\n\t\t\tnode.html(\"\");\n\n\t\t\tmultiline.forEach((v, i) => {\n\t\t\t\tnode.append(\"tspan\")\n\t\t\t\t\t.attr(\"x\", 0)\n\t\t\t\t\t.attr(\"dy\", `${i === 0 ? dy[0] * len : dy[1]}em`)\n\t\t\t\t\t.text(v);\n\t\t\t});\n\t\t}\n\t}\n};\n\n// substitution of SVGPathSeg API polyfill\nconst getRectSegList = path => {\n\t/*\n\t * seg1 ---------- seg2\n\t * | |\n\t * | |\n\t * | |\n\t * seg0 ---------- seg3\n\t * */\n\tconst {x, y, width, height} = path.getBBox();\n\n\treturn [\n\t\t{x, y: y + height}, // seg0\n\t\t{x, y}, // seg1\n\t\t{x: x + width, y}, // seg2\n\t\t{x: x + width, y: y + height} // seg3\n\t];\n};\n\nconst getPathBox = path => {\n\tconst {width, height} = path.getBoundingClientRect();\n\tconst items = getRectSegList(path);\n\tconst x = items[0].x;\n\tconst y = Math.min(items[0].y, items[1].y);\n\n\treturn {\n\t\tx, y, width, height\n\t};\n};\n\n// return brush selection array\nconst getBrushSelection = ctx => {\n\tlet selection = null;\n\tconst event = d3Event;\n\tconst main = ctx.context || ctx.main;\n\n\t// check from event\n\tif (event && event.constructor.name === \"BrushEvent\") {\n\t\tselection = event.selection;\n\t// check from brush area selection\n\t} else if (main && (selection = main.select(`.${CLASS.brush}`).node())) {\n\t\tselection = d3BrushSelection(selection);\n\t}\n\n\treturn selection;\n};\n\n// Get boundingClientRect. Cache the evaluated value once it was called.\nconst getBoundingRect = node => node.rect || (node.rect = node.getBoundingClientRect());\n\n// retrun random number\nconst getRandom = (asStr = true) => Math.random() + (asStr ? \"\" : 0);\n\nconst brushEmpty = ctx => {\n\tconst selection = getBrushSelection(ctx);\n\n\tif (selection) {\n\t\t// brush selected area\n\t\t// two-dimensional: [[x0, y0], [x1, y1]]\n\t\t// one-dimensional: [x0, x1] or [y0, y1]\n\t\treturn selection[0] === selection[1];\n\t}\n\n\treturn true;\n};\n\nconst extend = (target = {}, source) => {\n\tfor (const p in source) {\n\t\ttarget[p] = source[p];\n\t}\n\n\treturn target;\n};\n\n/**\n * Return first letter capitalized\n * @param {String} str\n * @return {String} capitalized string\n * @private\n */\nconst capitalize = str => str.charAt(0).toUpperCase() + str.slice(1);\n\n/**\n * Convert to array\n * @param {Object} v\n * @returns {Array}\n * @private\n */\nconst toArray = v => [].slice.call(v);\n\n/**\n * Get css rules for specified stylesheets\n * @param {Array} styleSheets The stylesheets to get the rules from\n * @returns {Array}\n * @private\n */\nconst getCssRules = styleSheets => {\n\tlet rules = [];\n\n\tstyleSheets.forEach(sheet => {\n\t\ttry {\n\t\t\tif (sheet.cssRules && sheet.cssRules.length) {\n\t\t\t\trules = rules.concat(toArray(sheet.cssRules));\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(`Error while reading rules from ${sheet.href}: ${e.toString()}`);\n\t\t}\n\t});\n\n\treturn rules;\n};\n\n/**\n * Gets the SVGMatrix of an SVGElement\n * @param {SVGElement} element\n * @return {SVGMatrix} matrix\n * @private\n */\nconst getTranslation = node => {\n\tconst transform = node ? node.transform : null;\n\tconst baseVal = transform ? transform.baseVal : [];\n\n\treturn baseVal.length ? baseVal.getItem(0).matrix : {a: 0, b: 0, c: 0, d: 0, e: 0, f: 0};\n};\n\n/**\n * Get unique value from array\n * @param {Array} data\n * @return {Array} Unique array value\n * @private\n */\nconst getUnique = data => {\n\tconst isDate = data[0] instanceof Date;\n\tconst d = (isDate ? data.map(Number) : data)\n\t\t.filter((v, i, self) => self.indexOf(v) === i);\n\n\treturn isDate ? d.map(v => new Date(v)) : d;\n};\n\n/**\n * Merge array\n * @param {Array} arr\n * @return {Array}\n * @private\n */\nconst mergeArray = arr => (arr && arr.length ? arr.reduce((p, c) => p.concat(c)) : []);\n\n/**\n * Merge object returning new object\n * @param {Object} target\n * @param {Object} objectN\n * @returns {Object} merged target object\n * @private\n */\nconst mergeObj = (target, ...objectN) => {\n\tif (!objectN.length || (objectN.length === 1 && !objectN[0])) {\n\t\treturn target;\n\t}\n\n\tconst source = objectN.shift();\n\n\tif (isObject(target) && isObject(source)) {\n\t\tObject.keys(source).forEach(key => {\n\t\t\tconst value = source[key];\n\n\t\t\tif (isObject(value)) {\n\t\t\t\t!target[key] && (target[key] = {});\n\t\t\t\ttarget[key] = mergeObj(target[key], value);\n\t\t\t} else {\n\t\t\t\ttarget[key] = isArray(value) ?\n\t\t\t\t\tvalue.concat() : value;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn mergeObj(target, ...objectN);\n};\n\n/**\n * Sort value\n * @param {Array} data value to be sorted\n * @param {Boolean} isAsc true: asc, false: desc\n * @return {Number|String|Date} sorted date\n * @private\n */\nconst sortValue = (data, isAsc = true) => {\n\tlet fn;\n\n\tif (data[0] instanceof Date) {\n\t\tfn = isAsc ? (a, b) => a - b : (a, b) => b - a;\n\t} else {\n\t\tif (isAsc && !data.every(isNaN)) {\n\t\t\tfn = (a, b) => a - b;\n\t\t} else if (!isAsc) {\n\t\t\tfn = (a, b) => (a > b && -1) || (a < b && 1) || (a === b && 0);\n\t\t}\n\t}\n\n\treturn data.concat().sort(fn);\n};\n\n/**\n * Get min/max value\n * @param {String} type 'min' or 'max'\n * @param {Array} data Array data value\n * @return {Number|Date|undefined}\n * @private\n */\nconst getMinMax = (type, data) => {\n\tlet res = data.filter(v => notEmpty(v));\n\n\tif (res.length) {\n\t\tif (isNumber(res[0])) {\n\t\t\tres = Math[type](...res);\n\t\t} else if (res[0] instanceof Date) {\n\t\t\tres = sortValue(res, type === \"min\")[0];\n\t\t}\n\t} else {\n\t\tres = undefined;\n\t}\n\n\treturn res;\n};\n\n/**\n * Get range\n * @param {Number} start Start number\n * @param {Number} end End number\n * @return {Array}\n * @private\n */\nconst getRange = (start, end) => {\n\tconst res = [];\n\n\tfor (let i = start; i < end; i++) {\n\t\tres.push(i);\n\t}\n\n\treturn res;\n};\n\n// emulate event\nconst emulateEvent = {\n\tmouse: (() => {\n\t\tconst getParams = () => ({\n\t\t\tbubbles: false, cancelable: false, screenX: 0, screenY: 0, clientX: 0, clientY: 0\n\t\t});\n\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-new\n\t\t\tnew MouseEvent(\"t\");\n\n\t\t\treturn (el, eventType, params = getParams()) => {\n\t\t\t\tel.dispatchEvent(new MouseEvent(eventType, params));\n\t\t\t};\n\t\t} catch (e) {\n\t\t\t// Polyfills DOM4 MouseEvent\n\t\t\treturn (el, eventType, params = getParams()) => {\n\t\t\t\tconst mouseEvent = document.createEvent(\"MouseEvent\");\n\n\t\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent\n\t\t\t\tmouseEvent.initMouseEvent(\n\t\t\t\t\teventType,\n\t\t\t\t\tparams.bubbles,\n\t\t\t\t\tparams.cancelable,\n\t\t\t\t\twindow,\n\t\t\t\t\t0, // the event's mouse click count\n\t\t\t\t\tparams.screenX, params.screenY,\n\t\t\t\t\tparams.clientX, params.clientY,\n\t\t\t\t\tfalse, false, false, false, 0, null\n\t\t\t\t);\n\n\t\t\t\tel.dispatchEvent(mouseEvent);\n\t\t\t};\n\t\t}\n\t})(),\n\ttouch: (el, eventType, params) => {\n\t\tconst touchObj = new Touch(mergeObj({\n\t\t\tidentifier: Date.now(),\n\t\t\ttarget: el,\n\t\t\tradiusX: 2.5,\n\t\t\tradiusY: 2.5,\n\t\t\trotationAngle: 10,\n\t\t\tforce: 0.5\n\t\t}, params));\n\n\t\tel.dispatchEvent(new TouchEvent(eventType, {\n\t\t\tcancelable: true,\n\t\t\tbubbles: true,\n\t\t\tshiftKey: true,\n\t\t\ttouches: [touchObj],\n\t\t\ttargetTouches: [],\n\t\t\tchangedTouches: [touchObj]\n\t\t}));\n\t}\n};\n\n/**\n * Process the template & return bound string\n * @param {String} tpl Template string\n * @param {Object} data Data value to be replaced\n * @return {String}\n * @private\n */\nconst tplProcess = (tpl, data) => {\n\tlet res = tpl;\n\n\tfor (const x in data) {\n\t\tres = res.replace(new RegExp(`{=${x}}`, \"g\"), data[x]);\n\t}\n\n\treturn res;\n};\n\nexport {\n\tasHalfPixel,\n\tbrushEmpty,\n\tcallFn,\n\tcapitalize,\n\tceil10,\n\tdiffDomain,\n\temulateEvent,\n\textend,\n\tgetBrushSelection,\n\tgetBoundingRect,\n\tgetCssRules,\n\tgetMinMax,\n\tgetOption,\n\tgetPathBox,\n\tgetRandom,\n\tgetRange,\n\tgetRectSegList,\n\tgetTranslation,\n\tgetUnique,\n\thasValue,\n\tisArray,\n\tisBoolean,\n\tisDefined,\n\tisEmpty,\n\tisFunction,\n\tisNumber,\n\tisObject,\n\tisObjectType,\n\tisString,\n\tisUndefined,\n\tisValue,\n\tmergeArray,\n\tmergeObj,\n\tnotEmpty,\n\tsanitise,\n\tsetTextValue,\n\tsortValue,\n\ttoArray,\n\ttplProcess\n};\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n * @ignore\n */\nimport {scaleLinear as d3ScaleLinear} from \"d3-scale\";\nimport {isDefined, isNumber, isString} from \"../internals/util\";\n\nexport default class AxisRendererHelper {\n\tconstructor(owner) {\n\t\tconst scale = d3ScaleLinear();\n\t\tconst {config, params} = owner;\n\n\t\tthis.owner = owner;\n\t\tthis.config = config;\n\t\tthis.scale = scale;\n\n\t\tif (config.noTransition || !params.config.transition_duration) {\n\t\t\tconfig.withoutTransition = true;\n\t\t}\n\n\t\t// set range\n\t\tconfig.range = scale.rangeExtent ?\n\t\t\tscale.rangeExtent() :\n\t\t\tthis.scaleExtent((params.orgXScale || scale).range());\n\t}\n\n\t/**\n\t * Compute a character dimension\n\t * @param {d3.selection} node\n\t * @return {{w: number, h: number}}\n\t * @private\n\t */\n\tstatic getSizeFor1Char(node) {\n\t\t// default size for one character\n\t\tconst size = {\n\t\t\tw: 5.5,\n\t\t\th: 11.5\n\t\t};\n\n\t\t!node.empty() && node.select(\"text\")\n\t\t\t.text(\"0\")\n\t\t\t.call(el => {\n\t\t\t\ttry {\n\t\t\t\t\tconst {width, height} = el.node().getBBox();\n\n\t\t\t\t\tif (width && height) {\n\t\t\t\t\t\tsize.w = width;\n\t\t\t\t\t\tsize.h = height;\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t} finally {\n\t\t\t\t\tel.text(\"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.getSizeFor1Char = () => size;\n\n\t\treturn size;\n\t}\n\n\t/**\n\t * Get tick transform setter function\n\t * @param {String} id Axis id\n\t * @private\n\t */\n\tgetTickTransformSetter(id) {\n\t\tconst {config} = this;\n\t\tconst fn = id === \"x\" ?\n\t\t\tvalue => `translate(${value + config.tickOffset},0)` :\n\t\t\tvalue => `translate(0,${value})`;\n\n\t\treturn (selection, scale) => {\n\t\t\tselection.attr(\"transform\", d => fn(Math.ceil(scale(d))));\n\t\t};\n\t}\n\n\tscaleExtent(domain) {\n\t\tconst start = domain[0];\n\t\tconst stop = domain[domain.length - 1];\n\n\t\treturn start < stop ? [start, stop] : [stop, start];\n\t}\n\n\tgenerateTicks(scale, isYAxes) {\n\t\tconst {tickStepSize} = this.owner.params;\n\t\tlet ticks = [];\n\n\t\t// When 'axis[y|y2].tick.stepSize' option is set\n\t\tif (isYAxes && tickStepSize) {\n\t\t\tconst [start, end] = scale.domain();\n\t\t\tlet interval = start;\n\n\t\t\twhile (interval <= end) {\n\t\t\t\tticks.push(interval);\n\t\t\t\tinterval += tickStepSize;\n\t\t\t}\n\t\t} else if (scale.ticks) {\n\t\t\tticks = scale.ticks(\n\t\t\t\t...(this.config.tickArguments || [])\n\t\t\t).map(v => (\n\t\t\t\t// round the tick value if is number\n\t\t\t\t(isString(v) && isNumber(v) && !isNaN(v) &&\n\t\t\t\t\tMath.round(v * 10) / 10\n\t\t\t\t) || v\n\t\t\t));\n\t\t} else {\n\t\t\tconst domain = scale.domain();\n\n\t\t\tfor (let i = Math.ceil(domain[0]); i < domain[1]; i++) {\n\t\t\t\tticks.push(i);\n\t\t\t}\n\n\t\t\tif (ticks.length > 0 && ticks[0] > 0) {\n\t\t\t\tticks.unshift(ticks[0] - (ticks[1] - ticks[0]));\n\t\t\t}\n\t\t}\n\n\t\treturn ticks;\n\t}\n\n\tcopyScale() {\n\t\tconst newScale = this.scale.copy();\n\n\t\tif (!newScale.domain().length) {\n\t\t\tnewScale.domain(this.scale.domain());\n\t\t}\n\n\t\treturn newScale;\n\t}\n\n\ttextFormatted(v) {\n\t\tconst tickFormat = this.config.tickFormat;\n\n\t\t// to round float numbers from 'binary floating point'\n\t\t// https://en.wikipedia.org/wiki/Double-precision_floating-point_format\n\t\t// https://stackoverflow.com/questions/17849101/laymans-explanation-for-why-javascript-has-weird-floating-math-ieee-754-stand\n\t\tconst value = /\\d+\\.\\d+0{5,}\\d$/.test(v) ? +String(v).replace(/0+\\d$/, \"\") : v;\n\t\tconst formatted = tickFormat ? tickFormat(value) : value;\n\n\t\treturn isDefined(formatted) ? formatted : \"\";\n\t}\n\n\ttransitionise(selection) {\n\t\tconst config = this.config;\n\n\t\treturn config.withoutTransition ?\n\t\t\tselection.interrupt() : selection.transition(config.transition);\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n * @ignore\n */\nimport {select as d3Select} from \"d3-selection\";\nimport Helper from \"./AxisRendererHelper\";\nimport {isArray, toArray, isFunction, isString, isNumber} from \"../internals/util\";\n\nexport default class AxisRenderer {\n\tconstructor(params = {}) {\n\t\tconst config = {\n\t\t\tinnerTickSize: 6,\n\t\t\touterTickSize: params.outerTick ? 6 : 0,\n\t\t\torient: \"bottom\",\n\t\t\trange: [],\n\t\t\ttickArguments: null,\n\t\t\ttickCentered: null,\n\t\t\ttickCulling: true,\n\t\t\ttickFormat: null,\n\t\t\ttickLength: 9,\n\t\t\ttickOffset: 0,\n\t\t\ttickPadding: 3,\n\t\t\ttickValues: null,\n\t\t\ttransition: null,\n\t\t\tnoTransition: params.noTransition\n\t\t};\n\n\t\tconfig.tickLength = Math.max(config.innerTickSize, 0) + config.tickPadding;\n\n\t\tthis.config = config;\n\t\tthis.params = params;\n\t\tthis.helper = new Helper(this);\n\t}\n\n\t/**\n\t * Create axis element\n\t * @param {d3.selection} g\n\t * @private\n\t */\n\tcreate(g) {\n\t\tconst ctx = this;\n\t\tconst config = this.config;\n\t\tconst params = this.params;\n\t\tconst helperInst = this.helper;\n\t\tconst scale = helperInst.scale;\n\t\tconst orient = config.orient;\n\t\tconst splitTickText = this.splitTickText.bind(this);\n\t\tconst isLeftRight = /^(left|right)$/.test(orient);\n\t\tconst isTopBottom = /^(top|bottom)$/.test(orient);\n\n\t\t// line/text enter and path update\n\t\tconst tickTransform = helperInst.getTickTransformSetter(isTopBottom ? \"x\" : \"y\");\n\t\tconst axisPx = tickTransform === helperInst.axisX ? \"y\" : \"x\";\n\t\tconst sign = /^(top|left)$/.test(orient) ? -1 : 1;\n\n\t\t// tick text helpers\n\t\tconst rotate = params.tickTextRotate;\n\n\t\tthis.config.range = scale.rangeExtent ?\n\t\t\tscale.rangeExtent() :\n\t\t\thelperInst.scaleExtent((params.orgXScale || scale).range());\n\n\t\tconst {innerTickSize, tickLength, range} = config;\n\n\t\t// // get the axis' tick position configuration\n\t\tconst name = params.name;\n\t\tconst tickTextPos = name && /^(x|y|y2)$/.test(name) ?\n\t\t\tparams.config[`axis_${name}_tick_text_position`] : {x: 0, y: 0};\n\n\t\t// tick visiblity\n\t\tconst prefix = name === \"subX\" ? `subchart_axis_x` : `axis_${name}`;\n\t\tconst axisShow = params.config[`${prefix}_show`];\n\t\tconst tickShow = {\n\t\t\ttick: axisShow ? params.config[`${prefix}_tick_show`] : false,\n\t\t\ttext: axisShow ? params.config[`${prefix}_tick_text_show`] : false\n\t\t};\n\n\t\tlet $g = null;\n\n\t\tg.each(function() {\n\t\t\tconst g = d3Select(this);\n\t\t\tlet scale0 = this.__chart__ || scale;\n\t\t\tlet scale1 = helperInst.copyScale();\n\n\t\t\t$g = g;\n\t\t\tthis.__chart__ = scale1;\n\n\t\t\tconfig.tickOffset = params.isCategory ?\n\t\t\t\tMath.ceil((scale1(1) - scale1(0)) / 2) : 0;\n\n\t\t\t// update selection - data join\n\t\t\tconst path = g.selectAll(\".domain\").data([0]);\n\n\t\t\t// enter + update selection\n\t\t\tpath.enter().append(\"path\")\n\t\t\t\t.attr(\"class\", \"domain\")\n\t\t\t\t.merge(helperInst.transitionise(path))\n\t\t\t\t.attr(\"d\", () => {\n\t\t\t\t\tconst outerTickSized = config.outerTickSize * sign;\n\n\t\t\t\t\treturn isTopBottom ?\n\t\t\t\t\t\t`M${range[0]},${outerTickSized}V0H${range[1]}V${outerTickSized}` :\n\t\t\t\t\t\t`M${outerTickSized},${range[0]}H0V${range[1]}H${outerTickSized}`;\n\t\t\t\t});\n\n\t\t\tif (tickShow.tick || tickShow.text) {\n\t\t\t\t// count of tick data in array\n\t\t\t\tconst ticks = config.tickValues || helperInst.generateTicks(scale1, isLeftRight);\n\n\t\t\t\t// update selection\n\t\t\t\tlet tick = g.selectAll(\".tick\")\n\t\t\t\t\t.data(ticks, scale1);\n\n\t\t\t\t// enter selection\n\t\t\t\tconst tickEnter = tick\n\t\t\t\t\t.enter()\n\t\t\t\t\t.insert(\"g\", \".domain\")\n\t\t\t\t\t.attr(\"class\", \"tick\")\n\t\t\t\t\t.style(\"opacity\", \"1\");\n\n\t\t\t\t// MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.\n\t\t\t\tconst tickExit = tick.exit().remove();\n\n\t\t\t\t// enter + update selection\n\t\t\t\ttick = tickEnter.merge(tick);\n\n\t\t\t\ttickShow.tick && tickEnter.append(\"line\");\n\t\t\t\ttickShow.text && tickEnter.append(\"text\");\n\n\t\t\t\tconst sizeFor1Char = Helper.getSizeFor1Char(tick);\n\t\t\t\tconst counts = [];\n\n\t\t\t\tlet tspan = tick.select(\"text\")\n\t\t\t\t\t.selectAll(\"tspan\")\n\t\t\t\t\t.data((d, index) => {\n\t\t\t\t\t\tconst split = params.tickMultiline ?\n\t\t\t\t\t\t\tsplitTickText(d, scale1, ticks, isLeftRight, sizeFor1Char.w) : (\n\t\t\t\t\t\t\t\tisArray(helperInst.textFormatted(d)) ?\n\t\t\t\t\t\t\t\t\thelperInst.textFormatted(d).concat() : [helperInst.textFormatted(d)]\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\tcounts[index] = split.length;\n\n\t\t\t\t\t\treturn split.map(splitted => ({index, splitted}));\n\t\t\t\t\t});\n\n\t\t\t\ttspan.exit().remove();\n\n\t\t\t\ttspan = tspan\n\t\t\t\t\t.enter()\n\t\t\t\t\t.append(\"tspan\")\n\t\t\t\t\t.merge(tspan)\n\t\t\t\t\t.text(d => d.splitted);\n\n\t\t\t\t// set <tspan>'s position\n\t\t\t\ttspan\n\t\t\t\t\t.attr(\"x\", isTopBottom ? 0 : tickLength * sign)\n\t\t\t\t\t.attr(\"dx\", (() => {\n\t\t\t\t\t\tlet dx = 0;\n\n\t\t\t\t\t\tif (/(top|bottom)/.test(orient) && rotate) {\n\t\t\t\t\t\t\tdx = 8 * Math.sin(Math.PI * (rotate / 180)) * (orient === \"top\" ? -1 : 1);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn dx + (tickTextPos.x || 0);\n\t\t\t\t\t})())\n\t\t\t\t\t.attr(\"dy\", (d, i) => {\n\t\t\t\t\t\tconst defValue = \".71em\";\n\t\t\t\t\t\tlet dy = 0;\n\n\t\t\t\t\t\tif (orient !== \"top\") {\n\t\t\t\t\t\t\tdy = sizeFor1Char.h;\n\n\t\t\t\t\t\t\tif (i === 0) {\n\t\t\t\t\t\t\t\tdy = isLeftRight ? -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3) :\n\t\t\t\t\t\t\t\t\t(tickTextPos.y === 0 ? defValue : 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn isNumber(dy) && tickTextPos.y ?\n\t\t\t\t\t\t\tdy + tickTextPos.y : dy || defValue;\n\t\t\t\t\t});\n\n\t\t\t\tconst lineUpdate = tick.select(\"line\");\n\t\t\t\tconst textUpdate = tick.select(\"text\");\n\n\t\t\t\ttickEnter.select(\"line\").attr(`${axisPx}2`, innerTickSize * sign);\n\t\t\t\ttickEnter.select(\"text\").attr(axisPx, tickLength * sign);\n\n\t\t\t\tctx.setTickLineTextPosition(lineUpdate, textUpdate);\n\n\t\t\t\t// Append <title> for tooltip display\n\t\t\t\tif (params.tickTitle) {\n\t\t\t\t\tconst title = textUpdate.select(\"title\");\n\n\t\t\t\t\t(title.empty() ? textUpdate.append(\"title\") : title)\n\t\t\t\t\t\t.text(index => params.tickTitle[index]);\n\t\t\t\t}\n\n\t\t\t\tif (scale1.bandwidth) {\n\t\t\t\t\tconst x = scale1;\n\t\t\t\t\tconst dx = x.bandwidth() / 2;\n\n\t\t\t\t\tscale0 = d => x(d) + dx;\n\t\t\t\t\tscale1 = scale0;\n\t\t\t\t} else if (scale0.bandwidth) {\n\t\t\t\t\tscale0 = scale1;\n\t\t\t\t} else {\n\t\t\t\t\ttickTransform(tickExit, scale1);\n\t\t\t\t}\n\n\t\t\t\ttickTransform(tickEnter, scale0);\n\t\t\t\ttickTransform(helperInst.transitionise(tick).style(\"opacity\", \"1\"), scale1);\n\t\t\t}\n\t\t});\n\n\t\tthis.g = $g;\n\t}\n\n\t/**\n\t * Get tick x/y coordinate\n\t * @return {{x: number, y: number}}\n\t * @private\n\t */\n\tgetTickXY() {\n\t\tconst config = this.config;\n\t\tconst pos = {x: 0, y: 0};\n\n\t\tif (this.params.isCategory) {\n\t\t\tpos.x = config.tickCentered ? 0 : config.tickOffset;\n\t\t\tpos.y = config.tickCentered ? config.tickOffset : 0;\n\t\t}\n\n\t\treturn pos;\n\t}\n\n\t/**\n\t * Get tick size\n\t * @param d\n\t * @return {number}\n\t * @private\n\t */\n\tgetTickSize(d) {\n\t\tconst scale = this.helper.scale;\n\t\tconst config = this.config;\n\t\tconst innerTickSize = config.innerTickSize;\n\t\tconst range = config.range;\n\n\t\tconst tickPosition = scale(d) +\n\t\t\t(config.tickCentered ? 0 : config.tickOffset);\n\n\t\treturn range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;\n\t}\n\n\t/**\n\t * Set tick's line & text position\n\t * @param lineUpdate\n\t * @param textUpdate\n\t * @param scale\n\t * @private\n\t */\n\tsetTickLineTextPosition(lineUpdate, textUpdate) {\n\t\tconst tickPos = this.getTickXY();\n\t\tconst {innerTickSize, orient, tickLength, tickOffset} = this.config;\n\t\tconst rotate = this.params.tickTextRotate;\n\n\t\tconst textAnchorForText = r => {\n\t\t\tconst value = [\"start\", \"end\"];\n\n\t\t\torient === \"top\" && value.reverse();\n\n\t\t\treturn !r ? \"middle\" : (r > 0 ? value[0] : value[1]);\n\t\t};\n\t\tconst textTransform = r => (r ? `rotate(${r})` : null);\n\t\tconst yForText = r => {\n\t\t\tconst r2 = r / (orient === \"bottom\" ? 15 : 23);\n\n\t\t\treturn r ? 11.5 - 2.5 * r2 * (r > 0 ? 1 : -1) : tickLength;\n\t\t};\n\n\t\tswitch (orient) {\n\t\t\tcase \"bottom\":\n\t\t\t\tlineUpdate\n\t\t\t\t\t.attr(\"x1\", tickPos.x)\n\t\t\t\t\t.attr(\"x2\", tickPos.x)\n\t\t\t\t\t.attr(\"y2\", this.getTickSize.bind(this));\n\n\t\t\t\ttextUpdate\n\t\t\t\t\t.attr(\"x\", 0)\n\t\t\t\t\t.attr(\"y\", yForText(rotate))\n\t\t\t\t\t.style(\"text-anchor\", textAnchorForText(rotate))\n\t\t\t\t\t.attr(\"transform\", textTransform(rotate));\n\t\t\t\tbreak;\n\t\t\tcase \"top\":\n\t\t\t\tlineUpdate\n\t\t\t\t\t.attr(\"x2\", 0)\n\t\t\t\t\t.attr(\"y2\", -innerTickSize);\n\n\t\t\t\ttextUpdate\n\t\t\t\t\t.attr(\"x\", 0)\n\t\t\t\t\t.attr(\"y\", -yForText(rotate) * 2)\n\t\t\t\t\t.style(\"text-anchor\", textAnchorForText(rotate))\n\t\t\t\t\t.attr(\"transform\", textTransform(rotate));\n\t\t\t\tbreak;\n\t\t\tcase \"left\":\n\t\t\t\tlineUpdate\n\t\t\t\t\t.attr(\"x2\", -innerTickSize)\n\t\t\t\t\t.attr(\"y1\", tickPos.y)\n\t\t\t\t\t.attr(\"y2\", tickPos.y);\n\n\t\t\t\ttextUpdate\n\t\t\t\t\t.attr(\"x\", -tickLength)\n\t\t\t\t\t.attr(\"y\", tickOffset)\n\t\t\t\t\t.style(\"text-anchor\", \"end\");\n\t\t\t\tbreak;\n\t\t\tcase \"right\":\n\t\t\t\tlineUpdate\n\t\t\t\t\t.attr(\"x2\", innerTickSize)\n\t\t\t\t\t.attr(\"y2\", 0);\n\n\t\t\t\ttextUpdate\n\t\t\t\t\t.attr(\"x\", tickLength)\n\t\t\t\t\t.attr(\"y\", 0)\n\t\t\t\t\t.style(\"text-anchor\", \"start\");\n\t\t}\n\t}\n\n\t// this should be called only when category axis\n\tsplitTickText(d, scale, ticks, isLeftRight, charWidth) {\n\t\tconst params = this.params;\n\t\tconst tickText = this.helper.textFormatted(d);\n\t\tconst splitted = isString(tickText) && tickText.indexOf(\"\\n\") > -1 ?\n\t\t\ttickText.split(\"\\n\") : [];\n\n\t\tif (splitted.length) {\n\t\t\treturn splitted;\n\t\t}\n\n\t\tif (isArray(tickText)) {\n\t\t\treturn tickText;\n\t\t}\n\n\t\tlet tickWidth = params.tickWidth;\n\n\t\tif (!tickWidth || tickWidth <= 0) {\n\t\t\ttickWidth = isLeftRight ? 95 : (\n\t\t\t\tparams.isCategory ?\n\t\t\t\t\t(Math.ceil(scale(ticks[1]) - scale(ticks[0])) - 12) : 110\n\t\t\t);\n\t\t}\n\n\t\tfunction split(splitted, text) {\n\t\t\tlet subtext;\n\t\t\tlet spaceIndex;\n\t\t\tlet textWidth;\n\n\t\t\tfor (let i = 1; i < text.length; i++) {\n\t\t\t\tif (text.charAt(i) === \" \") {\n\t\t\t\t\tspaceIndex = i;\n\t\t\t\t}\n\n\t\t\t\tsubtext = text.substr(0, i + 1);\n\t\t\t\ttextWidth = charWidth * subtext.length;\n\n\t\t\t\t// if text width gets over tick width, split by space index or current index\n\t\t\t\tif (tickWidth < textWidth) {\n\t\t\t\t\treturn split(\n\t\t\t\t\t\tsplitted.concat(text.substr(0, spaceIndex || i)),\n\t\t\t\t\t\ttext.slice(spaceIndex ? spaceIndex + 1 : i)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn splitted.concat(text);\n\t\t}\n\n\t\treturn split(splitted, String(tickText));\n\t}\n\n\tscale(x) {\n\t\tif (!arguments.length) {\n\t\t\treturn this.helper.scale;\n\t\t}\n\n\t\tthis.helper.scale = x;\n\n\t\treturn this;\n\t}\n\n\torient(x) {\n\t\tif (!arguments.length) {\n\t\t\treturn this.config.orient;\n\t\t}\n\n\t\tthis.config.orient = x in {\n\t\t\ttop: 1,\n\t\t\tright: 1,\n\t\t\tbottom: 1,\n\t\t\tleft: 1\n\t\t} ? String(x) : \"bottom\";\n\n\t\treturn this;\n\t}\n\n\ttickFormat(format) {\n\t\tif (!arguments.length) {\n\t\t\treturn this.config.tickFormat;\n\t\t}\n\n\t\tthis.config.tickFormat = format;\n\n\t\treturn this;\n\t}\n\n\ttickCentered(isCentered) {\n\t\tconst config = this.config;\n\n\t\tif (!arguments.length) {\n\t\t\treturn config.tickCentered;\n\t\t}\n\n\t\tconfig.tickCentered = isCentered;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Return tick's offset value.\n\t * The value will be set for 'category' axis type.\n\t * @return {number}\n\t * @private\n\t */\n\ttickOffset() {\n\t\treturn this.config.tickOffset;\n\t}\n\n\t/**\n\t * Get tick interval count\n\t * @private\n\t * @param {Number} size Total data size\n\t * @return {number}\n\t */\n\ttickInterval(size) {\n\t\tlet interval;\n\n\t\tif (this.params.isCategory) {\n\t\t\tinterval = this.config.tickOffset * 2;\n\t\t} else {\n\t\t\tconst length = this.g.select(\"path.domain\")\n\t\t\t\t.node()\n\t\t\t\t.getTotalLength() - this.config.outerTickSize * 2;\n\n\t\t\tinterval = length / (size || this.g.selectAll(\"line\").size());\n\t\t}\n\n\t\treturn interval === Infinity ? 0 : interval;\n\t}\n\n\tticks(...args) {\n\t\tconst config = this.config;\n\n\t\tif (!args.length) {\n\t\t\treturn config.tickArguments;\n\t\t}\n\n\t\tconfig.tickArguments = toArray(args);\n\n\t\treturn this;\n\t}\n\n\ttickCulling(culling) {\n\t\tconst config = this.config;\n\n\t\tif (!arguments.length) {\n\t\t\treturn config.tickCulling;\n\t\t}\n\n\t\tconfig.tickCulling = culling;\n\n\t\treturn this;\n\t}\n\n\ttickValues(x) {\n\t\tconst config = this.config;\n\n\t\tif (isFunction(x)) {\n\t\t\tconfig.tickValues = () => x(this.helper.scale.domain());\n\t\t} else {\n\t\t\tif (!arguments.length) {\n\t\t\t\treturn config.tickValues;\n\t\t\t}\n\n\t\t\tconfig.tickValues = x;\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tsetTransition(t) {\n\t\tthis.config.transition = t;\n\n\t\treturn this;\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\taxisTop as d3AxisTop,\n\taxisBottom as d3AxisBottom,\n\taxisLeft as d3AxisLeft,\n\taxisRight as d3AxisRight\n} from \"d3-axis\";\nimport {scaleLinear as d3ScaleLinear} from \"d3-scale\";\nimport CLASS from \"../config/classes\";\nimport {capitalize, isArray, isFunction, isString, isValue, isEmpty, isNumber, isObjectType, mergeObj, sortValue} from \"../internals/util\";\nimport AxisRenderer from \"./AxisRenderer\";\n\nconst isHorizontal = ($$, forHorizontal) => {\n\tconst isRotated = $$.config.axis_rotated;\n\n\treturn forHorizontal ? isRotated : !isRotated;\n};\n\nconst getAxisClassName = id => `${CLASS.axis} ${CLASS[`axis${capitalize(id)}`]}`;\n\nexport default class Axis {\n\tconstructor(owner) {\n\t\tthis.owner = owner;\n\t\tthis.setOrient();\n\t}\n\n\tinit() {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst main = $$.main;\n\t\tconst target = [\"x\", \"y\"];\n\n\t\tconfig.axis_y2_show && target.push(\"y2\");\n\n\t\t$$.axesList = {};\n\n\t\ttarget.forEach(v => {\n\t\t\tconst classAxis = getAxisClassName(v);\n\t\t\tconst classLabel = CLASS[`axis${v.toUpperCase()}Label`];\n\n\t\t\t$$.axes[v] = main.append(\"g\")\n\t\t\t\t.attr(\"class\", classAxis)\n\t\t\t\t.attr(\"clip-path\", () => {\n\t\t\t\t\tlet res = null;\n\n\t\t\t\t\tif (v === \"x\") {\n\t\t\t\t\t\tres = $$.clipPathForXAxis;\n\t\t\t\t\t} else if (v === \"y\" && config.axis_y_inner) {\n\t\t\t\t\t\tres = $$.clipPathForYAxis;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn res;\n\t\t\t\t})\n\t\t\t\t.attr(\"transform\", $$.getTranslate(v))\n\t\t\t\t.style(\"visibility\", config[`axis_${v}_show`] ? \"visible\" : \"hidden\");\n\n\t\t\t$$.axes[v].append(\"text\")\n\t\t\t\t.attr(\"class\", classLabel)\n\t\t\t\t.attr(\"transform\", [\"rotate(-90)\", null][\n\t\t\t\t\tv === \"x\" ? +!isRotated : +isRotated\n\t\t\t\t])\n\t\t\t\t.style(\"text-anchor\", () => this.textAnchorForAxisLabel(v));\n\n\t\t\tthis.generateAxes(v);\n\t\t});\n\t}\n\n\t/**\n\t * Set axis orient according option value\n\t * @private\n\t */\n\tsetOrient() {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst yInner = config.axis_y_inner;\n\t\tconst y2Inner = config.axis_y2_inner;\n\n\t\t$$.xOrient = isRotated ? \"left\" : \"bottom\";\n\t\t$$.yOrient = isRotated ? (yInner ? \"top\" : \"bottom\") : (yInner ? \"right\" : \"left\");\n\t\t$$.y2Orient = isRotated ? (y2Inner ? \"bottom\" : \"top\") : (y2Inner ? \"left\" : \"right\");\n\t\t$$.subXOrient = isRotated ? \"left\" : \"bottom\";\n\t}\n\n\t/**\n\t * Generate axes\n\t * It's used when axis' axes option is set\n\t * @param {String} id Axis id\n\t * @private\n\t */\n\tgenerateAxes(id) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst axes = [];\n\t\tconst axesConfig = config[`axis_${id}_axes`];\n\t\tconst isRotated = config.axis_rotated;\n\t\tlet d3Axis;\n\n\t\tif (id === \"x\") {\n\t\t\td3Axis = isRotated ? d3AxisLeft : d3AxisBottom;\n\t\t} else if (id === \"y\") {\n\t\t\td3Axis = isRotated ? d3AxisBottom : d3AxisLeft;\n\t\t} else if (id === \"y2\") {\n\t\t\td3Axis = isRotated ? d3AxisTop : d3AxisRight;\n\t\t}\n\n\t\tif (axesConfig.length) {\n\t\t\taxesConfig.forEach(v => {\n\t\t\t\tconst tick = v.tick || {};\n\t\t\t\tconst scale = $$[id].copy();\n\n\t\t\t\tv.domain && scale.domain(v.domain);\n\n\t\t\t\taxes.push(\n\t\t\t\t\td3Axis(scale)\n\t\t\t\t\t\t.ticks(tick.count)\n\t\t\t\t\t\t.tickFormat(tick.format || (x => x))\n\t\t\t\t\t\t.tickValues(tick.values)\n\t\t\t\t\t\t.tickSizeOuter(tick.outer === false ? 0 : 6)\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\n\t\t$$.axesList[id] = axes;\n\t}\n\n\t/**\n\t * Update axes nodes\n\t * @private\n\t */\n\tupdateAxes() {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\n\t\tObject.keys($$.axesList).forEach(id => {\n\t\t\tconst axesConfig = config[`axis_${id}_axes`];\n\t\t\tconst scale = $$[id].copy();\n\t\t\tconst range = scale.range();\n\n\t\t\t$$.axesList[id].forEach((v, i) => {\n\t\t\t\tconst axisRange = v.scale().range();\n\n\t\t\t\t// adjust range value with the current\n\t\t\t\t// https://github.com/naver/billboard.js/issues/859\n\t\t\t\tif (!range.every((v, i) => v === axisRange[i])) {\n\t\t\t\t\tv.scale().range(range);\n\t\t\t\t}\n\n\t\t\t\tconst className = `${getAxisClassName(id)}-${i + 1}`;\n\t\t\t\tlet g = $$.main.select(`.${className.replace(/\\s/, \".\")}`);\n\n\t\t\t\tif (g.empty()) {\n\t\t\t\t\tg = $$.main.append(\"g\")\n\t\t\t\t\t\t.attr(\"class\", className)\n\t\t\t\t\t\t.style(\"visibility\", config[`axis_${id}_show`] ? \"visible\" : \"hidden\")\n\t\t\t\t\t\t.call(v);\n\t\t\t\t} else {\n\t\t\t\t\taxesConfig[i].domain && scale.domain(axesConfig[i].domain);\n\n\t\t\t\t\t$$.xAxis.helper.transitionise(g)\n\t\t\t\t\t\t.call(v.scale(scale));\n\t\t\t\t}\n\n\t\t\t\tg.attr(\"transform\", $$.getTranslate(id, i + 1));\n\t\t\t});\n\t\t});\n\t}\n\n\t// called from : updateScales() & getMaxTickWidth()\n\tgetAxis(name, scale, outerTick, noTransition, noTickTextRotate) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst isX = /^(x|subX)$/.test(name);\n\t\tconst type = isX ? \"x\" : name;\n\n\t\tconst isCategory = isX && $$.isCategorized();\n\t\tconst orient = $$[`${name}Orient`];\n\t\tconst tickFormat = isX ? $$.xAxisTickFormat : config[`axis_${name}_tick_format`];\n\t\tconst tickTextRotate = noTickTextRotate ? 0 : $$.getAxisTickRotate(type);\n\t\tlet tickValues = isX ? $$.xAxisTickValues : $$[`${name}AxisTickValues`];\n\n\t\tconst axisParams = mergeObj({\n\t\t\touterTick,\n\t\t\tnoTransition,\n\t\t\tconfig,\n\t\t\tname,\n\t\t\ttickTextRotate\n\t\t}, isX && {\n\t\t\tisCategory,\n\t\t\ttickMultiline: config.axis_x_tick_multiline,\n\t\t\ttickWidth: config.axis_x_tick_width,\n\t\t\ttickTitle: isCategory && config.axis_x_tick_tooltip && $$.api.categories(),\n\t\t\torgXScale: $$.x\n\t\t});\n\n\t\tif (!isX) {\n\t\t\taxisParams.tickStepSize = config[`axis_${type}_tick_stepSize`];\n\t\t}\n\n\t\tconst axis = new AxisRenderer(axisParams)\n\t\t\t.scale((isX && $$.zoomScale) || scale)\n\t\t\t.orient(orient);\n\n\t\tif (isX && $$.isTimeSeries() && tickValues && !isFunction(tickValues)) {\n\t\t\ttickValues = tickValues.map(v => $$.parseDate(v));\n\t\t} else if (!isX && $$.isTimeSeriesY()) {\n\t\t\t// https://github.com/d3/d3/blob/master/CHANGES.md#time-intervals-d3-time\n\t\t\taxis.ticks(config.axis_y_tick_time_value);\n\t\t\ttickValues = null;\n\t\t}\n\n\t\ttickValues && axis.tickValues(tickValues);\n\n\t\t// Set tick\n\t\taxis.tickFormat(\n\t\t\ttickFormat || (\n\t\t\t\t!isX && ($$.isStackNormalized() && (x => `${x}%`))\n\t\t\t)\n\t\t);\n\n\t\tif (isCategory) {\n\t\t\taxis.tickCentered(config.axis_x_tick_centered);\n\n\t\t\tif (isEmpty(config.axis_x_tick_culling)) {\n\t\t\t\tconfig.axis_x_tick_culling = false;\n\t\t\t}\n\t\t}\n\n\t\tconst tickCount = config[`axis_${type}_tick_count`];\n\n\t\ttickCount && axis.ticks(tickCount);\n\n\t\treturn axis;\n\t}\n\n\tupdateXAxisTickValues(targets, axis) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst fit = config.axis_x_tick_fit;\n\t\tconst count = config.axis_x_tick_count;\n\t\tlet values;\n\n\t\tif (fit || (count && fit)) {\n\t\t\tvalues = this.generateTickValues(\n\t\t\t\t$$.mapTargetsToUniqueXs(targets),\n\t\t\t\tcount,\n\t\t\t\t$$.isTimeSeries()\n\t\t\t);\n\t\t}\n\n\t\tif (axis) {\n\t\t\taxis.tickValues(values);\n\t\t} else if ($$.xAxis) {\n\t\t\t$$.xAxis.tickValues(values);\n\t\t\t$$.subXAxis.tickValues(values);\n\t\t}\n\n\t\treturn values;\n\t}\n\n\tgetId(id) {\n\t\tconst config = this.owner.config;\n\n\t\treturn id in config.data_axes ? config.data_axes[id] : \"y\";\n\t}\n\n\tgetXAxisTickFormat() {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst tickFormat = config.axis_x_tick_format;\n\t\tconst isTimeSeries = $$.isTimeSeries();\n\t\tconst isCategorized = $$.isCategorized();\n\t\tlet format;\n\n\t\tif (tickFormat) {\n\t\t\tif (isFunction(tickFormat)) {\n\t\t\t\tformat = tickFormat;\n\t\t\t} else if (isTimeSeries) {\n\t\t\t\tformat = date => (date ? $$.axisTimeFormat(tickFormat)(date) : \"\");\n\t\t\t}\n\t\t} else {\n\t\t\tformat = isTimeSeries ? $$.defaultAxisTimeFormat : (\n\t\t\t\tisCategorized ?\n\t\t\t\t\t$$.categoryName : v => (v < 0 ? v.toFixed(0) : v)\n\t\t\t);\n\t\t}\n\n\t\treturn isFunction(format) ? v =>\n\t\t\tformat.apply($$, isCategorized ?\n\t\t\t\t[v, $$.categoryName(v)] : [v]\n\t\t\t) : format;\n\t}\n\n\tgetTickValues(id) {\n\t\tconst $$ = this.owner;\n\t\tconst tickValues = $$.config[`axis_${id}_tick_values`];\n\t\tconst axis = $$[`${id}Axis`];\n\n\t\treturn (isFunction(tickValues) ? tickValues() : tickValues) ||\n\t\t\t(axis ? axis.tickValues() : undefined);\n\t}\n\n\tgetLabelOptionByAxisId(id) {\n\t\treturn this.owner.config[`axis_${id}_label`];\n\t}\n\n\tgetLabelText(id) {\n\t\tconst option = this.getLabelOptionByAxisId(id);\n\n\t\treturn isString(option) ? option : (\n\t\t\toption ? option.text : null\n\t\t);\n\t}\n\n\tsetLabelText(id, text) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst option = this.getLabelOptionByAxisId(id);\n\n\t\tif (isString(option)) {\n\t\t\tconfig[`axis_${id}_label`] = text;\n\t\t} else if (option) {\n\t\t\toption.text = text;\n\t\t}\n\t}\n\n\tgetLabelPosition(id, defaultPosition) {\n\t\tconst isRotated = this.owner.config.axis_rotated;\n\t\tconst option = this.getLabelOptionByAxisId(id);\n\t\tconst position = (isObjectType(option) && option.position) ?\n\t\t\toption.position : defaultPosition[+!isRotated];\n\n\t\tconst has = v => !!~position.indexOf(v);\n\n\t\treturn {\n\t\t\tisInner: has(\"inner\"),\n\t\t\tisOuter: has(\"outer\"),\n\t\t\tisLeft: has(\"left\"),\n\t\t\tisCenter: has(\"center\"),\n\t\t\tisRight: has(\"right\"),\n\t\t\tisTop: has(\"top\"),\n\t\t\tisMiddle: has(\"middle\"),\n\t\t\tisBottom: has(\"bottom\")\n\t\t};\n\t}\n\n\tgetAxisLabelPosition(id) {\n\t\treturn this.getLabelPosition(id, id === \"x\" ? [\"inner-top\", \"inner-right\"] : [\"inner-right\", \"inner-top\"]);\n\t}\n\n\tgetLabelPositionById(id) {\n\t\treturn this.getAxisLabelPosition(id);\n\t}\n\n\txForAxisLabel(id) {\n\t\tconst $$ = this.owner;\n\t\tconst position = this.getAxisLabelPosition(id);\n\t\tlet x = position.isMiddle ? -$$.height / 2 : 0;\n\n\t\tif (isHorizontal($$, id !== \"x\")) {\n\t\t\tx = position.isLeft ? 0 : (\n\t\t\t\tposition.isCenter ? $$.width / 2 : $$.width\n\t\t\t);\n\t\t} else if (position.isBottom) {\n\t\t\tx = -$$.height;\n\t\t}\n\n\t\treturn x;\n\t}\n\n\tdxForAxisLabel(id) {\n\t\tconst $$ = this.owner;\n\t\tconst position = this.getAxisLabelPosition(id);\n\t\tlet dx = position.isBottom ? \"0.5em\" : \"0\";\n\n\t\tif (isHorizontal($$, id !== \"x\")) {\n\t\t\tdx = position.isLeft ? \"0.5em\" : (\n\t\t\t\tposition.isRight ? \"-0.5em\" : \"0\"\n\t\t\t);\n\t\t} else if (position.isTop) {\n\t\t\tdx = \"-0.5em\";\n\t\t}\n\n\t\treturn dx;\n\t}\n\n\ttextAnchorForAxisLabel(id) {\n\t\tconst $$ = this.owner;\n\t\tconst position = this.getAxisLabelPosition(id);\n\t\tlet anchor = position.isMiddle ? \"middle\" : \"end\";\n\n\t\tif (isHorizontal($$, id !== \"x\")) {\n\t\t\tanchor = position.isLeft ? \"start\" : (\n\t\t\t\tposition.isCenter ? \"middle\" : \"end\"\n\t\t\t);\n\t\t} else if (position.isBottom) {\n\t\t\tanchor = \"start\";\n\t\t}\n\n\t\treturn anchor;\n\t}\n\n\tdyForAxisLabel(id) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst isInner = this.getAxisLabelPosition(id).isInner;\n\t\tconst tickRotate = config[`axis_${id}_tick_rotate`] ? $$.getHorizontalAxisHeight(id) : 0;\n\t\tconst maxTickWidth = this.getMaxTickWidth(id);\n\t\tlet dy;\n\n\t\tif (id === \"x\") {\n\t\t\tconst xHeight = config.axis_x_height;\n\n\t\t\tif (isRotated) {\n\t\t\t\tdy = isInner ? \"1.2em\" : -25 - maxTickWidth;\n\t\t\t} else if (isInner) {\n\t\t\t\tdy = \"-0.5em\";\n\t\t\t} else if (xHeight) {\n\t\t\t\tdy = xHeight - 10;\n\t\t\t} else if (tickRotate) {\n\t\t\t\tdy = tickRotate - 10;\n\t\t\t} else {\n\t\t\t\tdy = \"3em\";\n\t\t\t}\n\t\t} else {\n\t\t\tdy = {\n\t\t\t\ty: [\"-0.5em\", 10, \"3em\", \"1.2em\", 10],\n\t\t\t\ty2: [\"1.2em\", -20, \"-2.2em\", \"-0.5em\", 15]\n\t\t\t}[id];\n\n\t\t\tif (isRotated) {\n\t\t\t\tif (isInner) {\n\t\t\t\t\tdy = dy[0];\n\t\t\t\t} else if (tickRotate) {\n\t\t\t\t\tdy = tickRotate * (id === \"y2\" ? -1 : 1) - dy[1];\n\t\t\t\t} else {\n\t\t\t\t\tdy = dy[2];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdy = isInner ?\n\t\t\t\t\tdy[3] : (\n\t\t\t\t\t\tdy[4] + (\n\t\t\t\t\t\t\tconfig[`axis_${id}_inner`] ? 0 : (maxTickWidth + dy[4])\n\t\t\t\t\t\t)\n\t\t\t\t\t) * (id === \"y\" ? -1 : 1);\n\t\t\t}\n\t\t}\n\n\t\treturn dy;\n\t}\n\n\tgetMaxTickWidth(id, withoutRecompute) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst currentTickMax = $$.currentMaxTickWidths[id];\n\t\tlet maxWidth = 0;\n\n\t\tif (withoutRecompute || !config[`axis_${id}_show`] || $$.filterTargetsToShow().length === 0) {\n\t\t\treturn currentTickMax.size;\n\t\t}\n\n\t\tif ($$.svg) {\n\t\t\tconst isYAxis = /^y2?$/.test(id);\n\t\t\tconst targetsToShow = $$.filterTargetsToShow($$.data.targets);\n\t\t\tconst scale = $$[id].copy().domain($$[`get${isYAxis ? \"Y\" : \"X\"}Domain`](targetsToShow, id));\n\t\t\tconst domain = scale.domain();\n\n\t\t\t// do not compute if domain is same\n\t\t\tif (domain[0] === domain[1] ||\n\t\t\t\t(isArray(currentTickMax.domain) && currentTickMax.domain[0] === currentTickMax.domain[1])\n\t\t\t) {\n\t\t\t\treturn currentTickMax.size;\n\t\t\t} else {\n\t\t\t\tcurrentTickMax.domain = domain;\n\t\t\t}\n\n\t\t\tconst axis = this.getAxis(id, scale, false, false, true);\n\t\t\tconst tickCount = config[`axis_${id}_tick_count`];\n\t\t\tconst tickValues = config[`axis_${id}_tick_values`];\n\n\t\t\t// Make to generate the final tick text to be rendered\n\t\t\t// https://github.com/naver/billboard.js/issues/920\n\t\t\t// Do not generate if 'tick values' option is given\n\t\t\t// https://github.com/naver/billboard.js/issues/1251\n\t\t\tif (!tickValues && tickCount) {\n\t\t\t\taxis.tickValues(\n\t\t\t\t\tthis.generateTickValues(\n\t\t\t\t\t\tdomain,\n\t\t\t\t\t\ttickCount,\n\t\t\t\t\t\tisYAxis ? $$.isTimeSeriesY() : $$.isTimeSeries()\n\t\t\t\t\t));\n\t\t\t}\n\n\t\t\t!isYAxis && this.updateXAxisTickValues(targetsToShow, axis);\n\n\t\t\tconst dummy = $$.selectChart.append(\"svg\")\n\t\t\t\t.style(\"visibility\", \"hidden\")\n\t\t\t\t.style(\"position\", \"fixed\")\n\t\t\t\t.style(\"top\", \"0px\")\n\t\t\t\t.style(\"left\", \"0px\");\n\n\t\t\taxis.create(dummy);\n\n\t\t\tdummy.selectAll(\"text\")\n\t\t\t\t.each(function(d, i) {\n\t\t\t\t\tconst currentTextWidth = this.getBoundingClientRect().width;\n\n\t\t\t\t\tmaxWidth = Math.max(maxWidth, currentTextWidth);\n\t\t\t\t\t// cache tick text width for getXAxisTickTextY2Overflow()\n\t\t\t\t\tif (id === \"x\") {\n\t\t\t\t\t\t$$.currentMaxTickWidths.x.ticks[i] = currentTextWidth;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\tdummy.remove();\n\t\t}\n\n\t\tif (maxWidth > 0) {\n\t\t\tcurrentTickMax.size = maxWidth;\n\t\t}\n\n\t\treturn currentTickMax.size;\n\t}\n\n\tgetXAxisTickTextY2Overflow(defaultPadding) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst xAxisTickRotate = $$.getAxisTickRotate(\"x\");\n\t\tconst positiveRotation = xAxisTickRotate > 0 && xAxisTickRotate < 90;\n\n\t\tif (($$.isCategorized() || $$.isTimeSeries()) &&\n\t\t\tconfig.axis_x_tick_fit &&\n\t\t\t!config.axis_x_tick_culling &&\n\t\t\t!config.axis_x_tick_multiline &&\n\t\t\tpositiveRotation\n\t\t) {\n\t\t\tconst widthWithoutCurrentPaddingLeft = $$.currentWidth - $$.getCurrentPaddingLeft();\n\t\t\tconst maxOverflow = this.getXAxisTickMaxOverflow(\n\t\t\t\txAxisTickRotate, widthWithoutCurrentPaddingLeft - defaultPadding\n\t\t\t);\n\t\t\tconst xAxisTickTextY2Overflow = Math.max(0, maxOverflow) +\n\t\t\t\tdefaultPadding; // for display inconsistencies between browsers\n\n\t\t\treturn Math.min(xAxisTickTextY2Overflow, widthWithoutCurrentPaddingLeft / 2);\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\tgetXAxisTickMaxOverflow(xAxisTickRotate, widthWithoutCurrentPaddingLeft) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst isTimeSeries = $$.isTimeSeries();\n\n\t\tconst tickTextWidths = $$.currentMaxTickWidths.x.ticks;\n\t\tconst tickCount = tickTextWidths.length;\n\t\tconst {left, right} = this.x.padding;\n\t\tlet maxOverflow = 0;\n\n\t\tconst remaining = tickCount - (isTimeSeries && config.axis_x_tick_fit ? 0.5 : 0);\n\n\t\tfor (let i = 0; i < tickCount; i++) {\n\t\t\tconst tickIndex = i + 1;\n\t\t\tconst rotatedTickTextWidth = Math.cos(Math.PI * xAxisTickRotate / 180) * tickTextWidths[i];\n\t\t\tconst ticksBeforeTickText = tickIndex - (isTimeSeries ? 1 : 0.5) + left;\n\n\t\t\t// Skip ticks if there are no ticks before them\n\t\t\tif (ticksBeforeTickText <= 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst xAxisLengthWithoutTickTextWidth = widthWithoutCurrentPaddingLeft - rotatedTickTextWidth;\n\t\t\tconst tickLength = xAxisLengthWithoutTickTextWidth / ticksBeforeTickText;\n\t\t\tconst remainingTicks = remaining - tickIndex;\n\n\t\t\tconst paddingRightLength = right * tickLength;\n\t\t\tconst remainingTickWidth = (remainingTicks * tickLength) + paddingRightLength;\n\t\t\tconst overflow = rotatedTickTextWidth - (tickLength / 2) - remainingTickWidth;\n\n\t\t\tmaxOverflow = Math.max(maxOverflow, overflow);\n\t\t}\n\n\t\tlet tickOffset = 0;\n\n\t\tif (!isTimeSeries) {\n\t\t\tconst scale = d3ScaleLinear()\n\t\t\t\t.domain([\n\t\t\t\t\tleft * -1,\n\t\t\t\t\t$$.getXDomainMax($$.data.targets) + 1 + right\n\t\t\t\t])\n\t\t\t\t.range([0, widthWithoutCurrentPaddingLeft - maxOverflow]);\n\n\t\t\ttickOffset = (Math.ceil((scale(1) - scale(0)) / 2));\n\t\t}\n\n\t\treturn maxOverflow + tickOffset;\n\t}\n\n\t/**\n\t * Get x Axis padding\n\t * @param {Number} tickCount Tick count\n\t * @return {Object} Padding object values with 'left' & 'right' key\n\t * @private\n\t */\n\tgetXAxisPadding(tickCount) {\n\t\tconst $$ = this.owner;\n\t\tlet padding = $$.config.axis_x_padding;\n\n\t\tif (isEmpty(padding)) {\n\t\t\tpadding = {left: 0, right: 0};\n\t\t} else {\n\t\t\tpadding.left = padding.left || 0;\n\t\t\tpadding.right = padding.right || 0;\n\t\t}\n\n\t\tif ($$.isTimeSeries()) {\n\t\t\tconst firstX = +$$.getXDomainMin($$.data.targets);\n\t\t\tconst lastX = +$$.getXDomainMax($$.data.targets);\n\t\t\tconst timeDiff = lastX - firstX;\n\n\t\t\tconst range = timeDiff + padding.left + padding.right;\n\t\t\tconst relativeTickWidth = (timeDiff / tickCount) / range;\n\n\t\t\tconst left = padding.left / range / relativeTickWidth || 0;\n\t\t\tconst right = padding.right / range / relativeTickWidth || 0;\n\n\t\t\tpadding = {left, right};\n\t\t}\n\n\t\treturn padding;\n\t}\n\n\tupdateLabels(withTransition) {\n\t\tconst $$ = this.owner;\n\t\tconst labels = {\n\t\t\tx: $$.main.select(`.${CLASS.axisX} .${CLASS.axisXLabel}`),\n\t\t\ty: $$.main.select(`.${CLASS.axisY} .${CLASS.axisYLabel}`),\n\t\t\ty2: $$.main.select(`.${CLASS.axisY2} .${CLASS.axisY2Label}`)\n\t\t};\n\n\t\tObject.keys(labels).filter(id => !labels[id].empty())\n\t\t\t.forEach(v => {\n\t\t\t\tconst node = labels[v];\n\n\t\t\t\t(withTransition ? node.transition() : node)\n\t\t\t\t\t.attr(\"x\", () => this.xForAxisLabel(v))\n\t\t\t\t\t.attr(\"dx\", () => this.dxForAxisLabel(v))\n\t\t\t\t\t.attr(\"dy\", () => this.dyForAxisLabel(v))\n\t\t\t\t\t.text(() => this.getLabelText(v));\n\t\t\t});\n\t}\n\n\tgetPadding(padding, key, defaultValue, domainLength) {\n\t\tconst p = isNumber(padding) ? padding : padding[key];\n\n\t\tif (!isValue(p)) {\n\t\t\treturn defaultValue;\n\t\t}\n\n\t\treturn this.convertPixelsToAxisPadding(p, domainLength);\n\t}\n\n\tconvertPixelsToAxisPadding(pixels, domainLength) {\n\t\tconst $$ = this.owner;\n\t\tconst length = $$.config.axis_rotated ? $$.width : $$.height;\n\n\t\treturn domainLength * (pixels / length);\n\t}\n\n\tgenerateTickValues(values, tickCount, forTimeSeries) {\n\t\tlet tickValues = values;\n\t\tlet start;\n\t\tlet end;\n\t\tlet count;\n\t\tlet interval;\n\t\tlet i;\n\t\tlet tickValue;\n\n\t\tif (tickCount) {\n\t\t\tconst targetCount = isFunction(tickCount) ? tickCount() : tickCount;\n\n\t\t\t// compute ticks according to tickCount\n\t\t\tif (targetCount === 1) {\n\t\t\t\ttickValues = [values[0]];\n\t\t\t} else if (targetCount === 2) {\n\t\t\t\ttickValues = [values[0], values[values.length - 1]];\n\t\t\t} else if (targetCount > 2) {\n\t\t\t\tconst isCategorized = this.owner.isCategorized();\n\n\t\t\t\tcount = targetCount - 2;\n\t\t\t\tstart = values[0];\n\t\t\t\tend = values[values.length - 1];\n\t\t\t\tinterval = (end - start) / (count + 1);\n\n\t\t\t\t// re-construct unique values\n\t\t\t\ttickValues = [start];\n\n\t\t\t\tfor (i = 0; i < count; i++) {\n\t\t\t\t\ttickValue = +start + interval * (i + 1);\n\t\t\t\t\ttickValues.push(\n\t\t\t\t\t\tforTimeSeries ? new Date(tickValue) : (\n\t\t\t\t\t\t\tisCategorized ? Math.round(tickValue) : tickValue\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ttickValues.push(end);\n\t\t\t}\n\t\t}\n\n\t\tif (!forTimeSeries) {\n\t\t\ttickValues = tickValues.sort((a, b) => a - b);\n\t\t}\n\n\t\treturn tickValues;\n\t}\n\n\tgenerateTransitions(duration) {\n\t\tconst $$ = this.owner;\n\t\tconst axes = $$.axes;\n\n\t\tconst [axisX, axisY, axisY2, axisSubX] = [\"x\", \"y\", \"y2\", \"subx\"]\n\t\t\t.map(v => {\n\t\t\t\tlet axis = axes[v];\n\n\t\t\t\tif (axis && duration) {\n\t\t\t\t\taxis = axis.transition().duration(duration);\n\t\t\t\t}\n\n\t\t\t\treturn axis;\n\t\t\t});\n\n\t\treturn {axisX, axisY, axisY2, axisSubX};\n\t}\n\n\tredraw(transitions, isHidden, isInit) {\n\t\tconst $$ = this.owner;\n\t\tconst opacity \t= isHidden ? \"0\" : \"1\";\n\n\t\t[\"x\", \"y\", \"y2\", \"subX\"].forEach(id => {\n\t\t\tconst axis = $$[`${id}Axis`];\n\n\t\t\tif (axis) {\n\t\t\t\tif (!isInit) {\n\t\t\t\t\taxis.config.withoutTransition = !$$.config.transition_duration;\n\t\t\t\t}\n\n\t\t\t\t$$.axes[id.toLowerCase()].style(\"opacity\", opacity);\n\t\t\t\taxis.create(transitions[`axis${capitalize(id)}`]);\n\t\t\t}\n\t\t});\n\n\t\tthis.updateAxes();\n\t}\n\n\t/**\n\t * Redraw axis\n\t * @param {Object} targetsToShow targets data to be shown\n\t * @param {Object} wth\n\t * @param {Ojbect} transitions\n\t * @param {Object} flow\n\t * @private\n\t */\n\tredrawAxis(targetsToShow, wth, transitions, flow, isInit) {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\t\tconst hasZoom = !!$$.zoomScale;\n\t\tlet xDomainForZoom;\n\n\t\tif (!hasZoom && $$.isCategorized() && targetsToShow.length === 0) {\n\t\t\t$$.x.domain([0, $$.axes.x.selectAll(\".tick\").size()]);\n\t\t}\n\n\t\tif ($$.x && targetsToShow.length) {\n\t\t\t!hasZoom &&\n\t\t\t\t$$.updateXDomain(targetsToShow, wth.UpdateXDomain, wth.UpdateOrgXDomain, wth.TrimXDomain);\n\n\t\t\tif (!config.axis_x_tick_values) {\n\t\t\t\tthis.updateXAxisTickValues(targetsToShow);\n\t\t\t}\n\t\t} else if ($$.xAxis) {\n\t\t\t$$.xAxis.tickValues([]);\n\t\t\t$$.subXAxis.tickValues([]);\n\t\t}\n\n\t\tif (config.zoom_rescale && !flow) {\n\t\t\txDomainForZoom = $$.x.orgDomain();\n\t\t}\n\n\t\t[\"y\", \"y2\"].forEach(key => {\n\t\t\tconst axis = $$[key];\n\n\t\t\tif (axis) {\n\t\t\t\tconst tickValues = config[`axis_${key}_tick_values`];\n\t\t\t\tconst tickCount = config[`axis_${key}_tick_count`];\n\n\t\t\t\taxis.domain($$.getYDomain(targetsToShow, key, xDomainForZoom));\n\n\t\t\t\tif (!tickValues && tickCount) {\n\t\t\t\t\tconst domain = axis.domain();\n\n\t\t\t\t\t$$[`${key}Axis`].tickValues(\n\t\t\t\t\t\tthis.generateTickValues(\n\t\t\t\t\t\t\tdomain,\n\t\t\t\t\t\t\tdomain.every(v => v === 0) ? 1 : tickCount,\n\t\t\t\t\t\t\t$$.isTimeSeriesY()\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// axes\n\t\tthis.redraw(transitions, $$.hasArcType(), isInit);\n\n\t\t// Update axis label\n\t\tthis.updateLabels(wth.Transition);\n\n\t\t// show/hide if manual culling needed\n\t\tif ((wth.UpdateXDomain || wth.UpdateXAxis || wth.Y) && targetsToShow.length) {\n\t\t\tthis.setCulling();\n\t\t}\n\n\t\t// Update sub domain\n\t\tif (wth.Y) {\n\t\t\t$$.subY && $$.subY.domain($$.getYDomain(targetsToShow, \"y\"));\n\t\t\t$$.subY2 && $$.subY2.domain($$.getYDomain(targetsToShow, \"y2\"));\n\t\t}\n\t}\n\n\t/**\n\t * Set manual culling\n\t * @private\n\t */\n\tsetCulling() {\n\t\tconst $$ = this.owner;\n\t\tconst config = $$.config;\n\n\t\t[\"subx\", \"x\", \"y\", \"y2\"].forEach(type => {\n\t\t\tconst axis = $$.axes[type];\n\n\t\t\t// subchart x axis should be aligned with x axis culling\n\t\t\tconst id = type === \"subx\" ? \"x\" : type;\n\t\t\tconst toCull = config[`axis_${id}_tick_culling`];\n\n\t\t\tif (axis && toCull) {\n\t\t\t\tconst tickText = axis.selectAll(\".tick text\");\n\t\t\t\tconst tickValues = sortValue(tickText.data());\n\t\t\t\tconst tickSize = tickValues.length;\n\t\t\t\tconst cullingMax = config[`axis_${id}_tick_culling_max`];\n\t\t\t\tlet intervalForCulling;\n\n\t\t\t\tif (tickSize) {\n\t\t\t\t\tfor (let i = 1; i < tickSize; i++) {\n\t\t\t\t\t\tif (tickSize / i < cullingMax) {\n\t\t\t\t\t\t\tintervalForCulling = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttickText.each(function(d) {\n\t\t\t\t\t\tthis.style.display = tickValues.indexOf(d) % intervalForCulling ? \"none\" : \"block\";\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\ttickText.style(\"display\", \"block\");\n\t\t\t\t}\n\n\t\t\t\t// set/unset x_axis_tick_clippath\n\t\t\t\tif (type === \"x\") {\n\t\t\t\t\tconst clipPath = $$.clipXAxisTickMaxWidth ? $$.clipPathForXAxisTickTexts : null;\n\n\t\t\t\t\t$$.svg.selectAll(`.${CLASS.axisX} .tick text`)\n\t\t\t\t\t\t.attr(\"clip-path\", clipPath);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n * @ignore\n */\nimport {\n\ttimeParse as d3TimeParse,\n\ttimeFormat as d3TimeFormat,\n\tutcParse as d3UtcParse,\n\tutcFormat as d3UtcFormat\n} from \"d3-time-format\";\nimport {\n\tselect as d3Select,\n\tselectAll as d3SelectAll\n} from \"d3-selection\";\nimport {transition as d3Transition} from \"d3-transition\";\nimport Axis from \"../axis/Axis\";\nimport CLASS from \"../config/classes\";\nimport {document, window} from \"../internals/browser\";\nimport {notEmpty, asHalfPixel, getOption, isArray, isFunction, isNumber, isObject, isString, isValue, callFn, sortValue} from \"./util\";\n\n/**\n * Internal chart class.\n * - Note: Instantiated internally, not exposed for public.\n * @class ChartInternal\n * @ignore\n * @private\n */\nexport default class ChartInternal {\n\tconstructor(api) {\n\t\tconst $$ = this;\n\n\t\t$$.api = api;\n\t\t$$.config = $$.getOptions();\n\t\t$$.data = {};\n\t\t$$.cache = {};\n\t\t$$.axes = {};\n\t\t$$.rendered = false;\n\t}\n\n\tbeforeInit() {\n\t\tconst $$ = this;\n\n\t\t$$.callPluginHook(\"$beforeInit\");\n\n\t\t// can do something\n\t\tcallFn($$.config.onbeforeinit, $$, $$.api);\n\t}\n\n\tafterInit() {\n\t\tconst $$ = this;\n\n\t\t$$.callPluginHook(\"$afterInit\");\n\n\t\t// can do something\n\t\tcallFn($$.config.onafterinit, $$, $$.api);\n\t}\n\n\tinit() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t$$.initParams();\n\n\t\tconst bindto = {\n\t\t\telement: config.bindto,\n\t\t\tclassname: \"bb\"\n\t\t};\n\n\t\tif (isObject(config.bindto)) {\n\t\t\tbindto.element = config.bindto.element || \"#chart\";\n\t\t\tbindto.classname = config.bindto.classname || bindto.classname;\n\t\t}\n\n\t\t// select bind element\n\t\t$$.selectChart = isFunction(bindto.element.node) ?\n\t\t\tconfig.bindto.element : d3Select(bindto.element || []);\n\n\t\tif ($$.selectChart.empty()) {\n\t\t\t$$.selectChart = d3Select(document.body.appendChild(document.createElement(\"div\")));\n\t\t}\n\n\t\t$$.selectChart.html(\"\").classed(bindto.classname, true);\n\t\t$$.initToRender();\n\t}\n\n\t/**\n\t * Initialize the rendering process\n\t * @param {Boolean} forced Force to render process\n\t * @private\n\t */\n\tinitToRender(forced) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst target = $$.selectChart;\n\t\tconst isHidden = () => target.style(\"display\") === \"none\" || target.style(\"visibility\") === \"hidden\";\n\n\t\tconst isLazy = config.render.lazy || isHidden();\n\t\tconst MutationObserver = window.MutationObserver;\n\n\t\tif (isLazy && MutationObserver && config.render.observe !== false && !forced) {\n\t\t\tnew MutationObserver((mutation, observer) => {\n\t\t\t\tif (!isHidden()) {\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t!$$.rendered && $$.initToRender(true);\n\t\t\t\t}\n\t\t\t}).observe(target.node(), {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: [\"class\", \"style\"]\n\t\t\t});\n\t\t}\n\n\t\tif (!isLazy || forced) {\n\t\t\tconst convertedData = $$.convertData(config, $$.initWithData);\n\n\t\t\tconvertedData && $$.initWithData(convertedData);\n\t\t\t$$.afterInit();\n\t\t}\n\t}\n\n\tinitParams() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\t// datetime to be used for uniqueness\n\t\t$$.datetimeId = `bb-${+new Date()}`;\n\t\t$$.initClip();\n\n\t\t$$.dragStart = null;\n\t\t$$.dragging = false;\n\t\t$$.flowing = false;\n\t\t$$.cancelClick = false;\n\t\t$$.mouseover = false;\n\t\t$$.transiting = false;\n\n\t\t$$.color = $$.generateColor();\n\t\t$$.levelColor = $$.generateLevelColor();\n\t\t$$.point = $$.generatePoint();\n\n\t\t$$.extraLineClasses = $$.generateExtraLineClass();\n\n\t\t$$.dataTimeFormat = config.data_xLocaltime ? d3TimeParse : d3UtcParse;\n\t\t$$.axisTimeFormat = config.axis_x_localtime ? d3TimeFormat : d3UtcFormat;\n\n\t\tconst isDragZoom = $$.config.zoom_enabled && $$.config.zoom_enabled.type === \"drag\";\n\n\t\t$$.defaultAxisTimeFormat = d => {\n\t\t\tconst isZoomed = isDragZoom ? this.zoomScale :\n\t\t\t\tthis.zoomScale && $$.x.orgDomain().toString() !== this.zoomScale.domain().toString();\n\n\t\t\tconst specifier = (d.getMilliseconds() && \".%L\") ||\n\t\t\t\t(d.getSeconds() && \".:%S\") ||\n\t\t\t\t(d.getMinutes() && \"%I:%M\") ||\n\t\t\t\t(d.getHours() && \"%I %p\") ||\n\t\t\t\t(d.getDate() !== 1 && \"%b %d\") ||\n\t\t\t\t(isZoomed && d.getDate() === 1 && \"%b\\'%y\") ||\n\t\t\t\t(d.getMonth() && \"%-m/%-d\") || \"%Y\";\n\n\t\t\treturn $$.axisTimeFormat(specifier)(d);\n\t\t};\n\n\t\t$$.hiddenTargetIds = [];\n\t\t$$.hiddenLegendIds = [];\n\t\t$$.focusedTargetIds = [];\n\t\t$$.defocusedTargetIds = [];\n\n\t\t$$.isLegendRight = config.legend_position === \"right\";\n\t\t$$.isLegendInset = config.legend_position === \"inset\";\n\n\t\t$$.isLegendTop = config.legend_inset_anchor === \"top-left\" ||\n\t\t\tconfig.legend_inset_anchor === \"top-right\";\n\t\t$$.isLegendLeft = config.legend_inset_anchor === \"top-left\" ||\n\t\t\tconfig.legend_inset_anchor === \"bottom-left\";\n\n\t\t$$.legendStep = 0;\n\t\t$$.legendItemWidth = 0;\n\t\t$$.legendItemHeight = 0;\n\n\t\t$$.currentMaxTickWidths = {\n\t\t\tx: {size: 0, ticks: [], domain: \"\"},\n\t\t\ty: {size: 0, domain: \"\"},\n\t\t\ty2: {size: 0, domain: \"\"}\n\t\t};\n\n\t\t$$.rotated_padding_left = 30;\n\t\t$$.rotated_padding_right = isRotated && !config.axis_x_show ? 0 : 30;\n\t\t$$.rotated_padding_top = 5;\n\n\t\t$$.withoutFadeIn = {};\n\t\t$$.inputType = $$.convertInputType();\n\n\t\t$$.axes.subx = d3SelectAll([]); // needs when excluding subchart.js\n\t}\n\n\tinitWithData(data) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t// for arc type, set axes to not be shown\n\t\t// $$.hasArcType() && [\"x\", \"y\", \"y2\"].forEach(id => (config[`axis_${id}_show`] = false));\n\n\t\t$$.axis = new Axis($$);\n\t\tconfig.zoom_enabled && $$.initZoom();\n\n\t\t// Init data as targets\n\t\t$$.data.xs = {};\n\t\t$$.data.targets = $$.convertDataToTargets(data);\n\n\t\tif (config.data_filter) {\n\t\t\t$$.data.targets = $$.data.targets.filter(config.data_filter);\n\t\t}\n\n\t\t// Set targets to hide if needed\n\t\tif (config.data_hide) {\n\t\t\t$$.addHiddenTargetIds(\n\t\t\t\tconfig.data_hide === true ?\n\t\t\t\t\t$$.mapToIds($$.data.targets) : config.data_hide\n\t\t\t);\n\t\t}\n\t\tif (config.legend_hide) {\n\t\t\t$$.addHiddenLegendIds(\n\t\t\t\tconfig.legend_hide === true ?\n\t\t\t\t\t$$.mapToIds($$.data.targets) : config.legend_hide\n\t\t\t);\n\t\t}\n\n\t\t// Init sizes and scales\n\t\t$$.updateSizes();\n\t\t$$.updateScales(true);\n\n\t\t// Set domains for each scale\n\t\tif ($$.x) {\n\t\t\t$$.x.domain(sortValue($$.getXDomain($$.data.targets)));\n\t\t\t$$.subX.domain($$.x.domain());\n\n\t\t\t// Save original x domain for zoom update\n\t\t\t$$.orgXDomain = $$.x.domain();\n\t\t}\n\n\t\tif ($$.y) {\n\t\t\t$$.y.domain($$.getYDomain($$.data.targets, \"y\"));\n\t\t\t$$.subY.domain($$.y.domain());\n\t\t}\n\n\t\tif ($$.y2) {\n\t\t\t$$.y2.domain($$.getYDomain($$.data.targets, \"y2\"));\n\t\t\t$$.subY2 && $$.subY2.domain($$.y2.domain());\n\t\t}\n\n\t\t// -- Basic Elements --\n\t\t$$.svg = $$.selectChart.append(\"svg\")\n\t\t\t.style(\"overflow\", \"hidden\")\n\t\t\t.style(\"display\", \"block\");\n\n\t\tif (config.interaction_enabled && $$.inputType) {\n\t\t\tconst isTouch = $$.inputType === \"touch\";\n\n\t\t\t$$.svg\n\t\t\t\t.on(isTouch ? \"touchstart\" : \"mouseenter\", () => callFn(config.onover, $$, $$.api))\n\t\t\t\t.on(isTouch ? \"touchend\" : \"mouseleave\", () => callFn(config.onout, $$, $$.api));\n\t\t}\n\n\t\tconfig.svg_classname && $$.svg.attr(\"class\", config.svg_classname);\n\n\t\t// Define defs\n\t\t$$.defs = $$.svg.append(\"defs\");\n\n\t\t$$.clipChart = $$.appendClip($$.defs, $$.clipId);\n\t\t$$.clipXAxis = $$.appendClip($$.defs, $$.clipIdForXAxis);\n\t\t$$.clipXAxisTickTexts = $$.appendClip($$.defs, $$.clipIdForXAxisTickTexts);\n\t\t$$.clipYAxis = $$.appendClip($$.defs, $$.clipIdForYAxis);\n\t\t$$.clipGrid = $$.appendClip($$.defs, $$.clipIdForGrid);\n\n\t\t// set color patterns\n\t\tif (isFunction(config.color_tiles) && $$.patterns) {\n\t\t\t$$.patterns.forEach(p => $$.defs.append(() => p.node));\n\t\t}\n\n\t\t$$.updateSvgSize();\n\n\t\t// Bind resize event\n\t\t$$.bindResize();\n\n\t\t// Define regions\n\t\tconst main = $$.svg.append(\"g\").attr(\"transform\", $$.getTranslate(\"main\"));\n\n\t\t$$.main = main;\n\n\t\t// initialize subchart when subchart show option is set\n\t\tconfig.subchart_show && $$.initSubchart();\n\n\t\t$$.initTooltip && $$.initTooltip();\n\t\t$$.initLegend && $$.initLegend();\n\t\t$$.initTitle && $$.initTitle();\n\n\t\t// -- Main Region --\n\n\t\t// text when empty\n\t\tif (config.data_empty_label_text) {\n\t\t\tmain.append(\"text\")\n\t\t\t\t.attr(\"class\", `${CLASS.text} ${CLASS.empty}`)\n\t\t\t\t.attr(\"text-anchor\", \"middle\") // horizontal centering of text at x position in all browsers.\n\t\t\t\t.attr(\"dominant-baseline\", \"middle\"); // vertical centering of text at y position in all browsers, except IE.\n\t\t}\n\n\t\t// Regions\n\t\t$$.initRegion();\n\n\t\t// Add Axis here, when clipPath is 'false'\n\t\t!config.clipPath && $$.axis.init();\n\n\t\t// Define g for chart area\n\t\tmain.append(\"g\").attr(\"class\", CLASS.chart)\n\t\t\t.attr(\"clip-path\", $$.clipPath);\n\n\t\t$$.callPluginHook(\"$init\");\n\n\t\t// Cover whole with rects for events\n\t\t$$.initEventRect();\n\n\t\t// Define g for chart\n\t\t$$.initChartElements();\n\n\t\t// Grids\n\t\t$$.initGrid();\n\n\t\t// if zoom privileged, insert rect to forefront\n\t\t// TODO: is this needed?\n\t\tmain.insert(\"rect\", config.zoom_privileged ? null : `g.${CLASS.regions}`)\n\t\t\t.attr(\"class\", CLASS.zoomRect)\n\t\t\t.attr(\"width\", $$.width)\n\t\t\t.attr(\"height\", $$.height)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.on(\"dblclick.zoom\", null);\n\n\t\t// Add Axis here, when clipPath is 'true'\n\t\tconfig.clipPath && $$.axis.init();\n\n\t\t// Set targets\n\t\t$$.updateTargets($$.data.targets);\n\n\t\t// Draw with targets\n\t\t$$.updateDimension();\n\n\t\t// oninit callback\n\t\tcallFn(config.oninit, $$, $$.api);\n\n\t\t// Set background\n\t\t$$.setBackground();\n\n\t\t$$.redraw({\n\t\t\twithTransition: false,\n\t\t\twithTransform: true,\n\t\t\twithUpdateXDomain: true,\n\t\t\twithUpdateOrgXDomain: true,\n\t\t\twithTransitionForAxis: false,\n\t\t\tinitializing: true\n\t\t});\n\n\t\t// data.onmin/max callback\n\t\tif (config.data_onmin || config.data_onmax) {\n\t\t\tconst minMax = $$.getMinMaxData();\n\n\t\t\tcallFn(config.data_onmin, $$, minMax.min);\n\t\t\tcallFn(config.data_onmax, $$, minMax.max);\n\t\t}\n\n\t\t// export element of the chart\n\t\t$$.api.element = $$.selectChart.node();\n\n\t\t$$.rendered = true;\n\t}\n\n\tinitChartElements() {\n\t\tconst $$ = this;\n\n\t\t[\"Bar\", \"Radar\", \"Line\", \"Bubble\", \"Arc\", \"Gauge\", \"Pie\"].forEach(v => {\n\t\t\t$$[`init${v}`]();\n\t\t});\n\n\t\tnotEmpty($$.config.data_labels) && $$.initText();\n\t}\n\n\tsetChartElements() {\n\t\tconst $$ = this;\n\n\t\t$$.api.$ = {\n\t\t\tchart: $$.selectChart,\n\t\t\tsvg: $$.svg,\n\t\t\tdefs: $$.defs,\n\t\t\tmain: $$.main,\n\t\t\ttooltip: $$.tooltip,\n\t\t\tlegend: $$.legend,\n\t\t\ttitle: $$.title,\n\t\t\tgrid: $$.grid,\n\t\t\tarc: $$.arcs,\n\t\t\tbar: {\n\t\t\t\tbars: $$.mainBar\n\t\t\t},\n\t\t\tline: {\n\t\t\t\tlines: $$.mainLine,\n\t\t\t\tareas: $$.mainArea,\n\t\t\t\tcircles: $$.mainCircle\n\t\t\t},\n\t\t\ttext: {\n\t\t\t\ttexts: $$.mainText\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Set background element/image\n\t * @private\n\t */\n\tsetBackground() {\n\t\tconst $$ = this;\n\t\tconst bg = $$.config.background;\n\n\t\tif (notEmpty(bg)) {\n\t\t\tconst element = $$.svg.select(`.${CLASS[$$.hasArcType() ? \"chart\" : \"regions\"]}`)\n\t\t\t\t.insert(bg.imgUrl ? \"image\" : \"rect\", \":first-child\");\n\n\t\t\tif (bg.imgUrl) {\n\t\t\t\telement.attr(\"href\", bg.imgUrl);\n\t\t\t} else if (bg.color) {\n\t\t\t\telement.style(\"fill\", bg.color);\n\t\t\t}\n\n\t\t\telement\n\t\t\t\t.attr(\"class\", bg.class || null)\n\t\t\t\t.attr(\"width\", \"100%\")\n\t\t\t\t.attr(\"height\", \"100%\");\n\t\t}\n\t}\n\n\tsmoothLines(el, type) {\n\t\tif (type === \"grid\") {\n\t\t\tel.each(function() {\n\t\t\t\tconst g = d3Select(this);\n\n\t\t\t\t[\"x1\", \"x2\", \"y1\", \"y2\"]\n\t\t\t\t\t.forEach(v => g.attr(v, Math.ceil(g.attr(v))));\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Update size values\n\t * @param {Boolean} isInit If is called at initialization\n\t * @private\n\t */\n\tupdateSizes(isInit) {\n\t\tconst $$ = this;\n\n\t\t!isInit && $$.setContainerSize();\n\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst hasArc = $$.hasArcType();\n\n\t\tconst legend = {\n\t\t\twidth: $$.legend ? $$.getLegendWidth() : 0,\n\t\t\theight: $$.legend ? $$.getLegendHeight() : 0\n\t\t};\n\n\t\tconst legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legend.height;\n\t\tconst xAxisHeight = isRotated || hasArc ? 0 : $$.getHorizontalAxisHeight(\"x\");\n\n\t\tconst subchartXAxisHeight = config.subchart_axis_x_show && config.subchart_axis_x_tick_text_show ?\n\t\t\txAxisHeight : 30;\n\t\tconst subchartHeight = config.subchart_show && !hasArc ?\n\t\t\t(config.subchart_size_height + subchartXAxisHeight) : 0;\n\n\t\t// for main\n\t\t$$.margin = isRotated ? {\n\t\t\ttop: $$.getHorizontalAxisHeight(\"y2\") + $$.getCurrentPaddingTop(),\n\t\t\tright: hasArc ? 0 : $$.getCurrentPaddingRight(),\n\t\t\tbottom: $$.getHorizontalAxisHeight(\"y\") + legendHeightForBottom + $$.getCurrentPaddingBottom(),\n\t\t\tleft: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())\n\t\t} : {\n\t\t\ttop: 4 + $$.getCurrentPaddingTop(), // for top tick text\n\t\t\tright: hasArc ? 0 : $$.getCurrentPaddingRight(),\n\t\t\tbottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),\n\t\t\tleft: hasArc ? 0 : $$.getCurrentPaddingLeft()\n\t\t};\n\n\t\t// for subchart\n\t\t$$.margin2 = isRotated ? {\n\t\t\ttop: $$.margin.top,\n\t\t\tright: NaN,\n\t\t\tbottom: 20 + legendHeightForBottom,\n\t\t\tleft: $$.rotated_padding_left\n\t\t} : {\n\t\t\ttop: $$.currentHeight - subchartHeight - legendHeightForBottom,\n\t\t\tright: NaN,\n\t\t\tbottom: subchartXAxisHeight + legendHeightForBottom,\n\t\t\tleft: $$.margin.left\n\t\t};\n\n\t\t// for legend\n\t\t$$.margin3 = {\n\t\t\ttop: 0,\n\t\t\tright: NaN,\n\t\t\tbottom: 0,\n\t\t\tleft: 0\n\t\t};\n\n\t\t$$.updateSizeForLegend && $$.updateSizeForLegend(legend);\n\n\t\t$$.width = $$.currentWidth - $$.margin.left - $$.margin.right;\n\t\t$$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;\n\n\t\tif ($$.width < 0) {\n\t\t\t$$.width = 0;\n\t\t}\n\n\t\tif ($$.height < 0) {\n\t\t\t$$.height = 0;\n\t\t}\n\n\t\t$$.width2 = isRotated ?\n\t\t\t$$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;\n\n\t\t$$.height2 = isRotated ?\n\t\t\t$$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;\n\n\t\tif ($$.width2 < 0) {\n\t\t\t$$.width2 = 0;\n\t\t}\n\n\t\tif ($$.height2 < 0) {\n\t\t\t$$.height2 = 0;\n\t\t}\n\n\t\t// for arc\n\t\t$$.arcWidth = $$.width - ($$.isLegendRight ? legend.width + 10 : 0);\n\t\t$$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);\n\n\t\tif ($$.hasType(\"gauge\") && !config.gauge_fullCircle) {\n\t\t\t$$.arcHeight += $$.height - $$.getGaugeLabelHeight();\n\t\t}\n\n\t\t$$.updateRadius && $$.updateRadius();\n\n\t\tif ($$.isLegendRight && hasArc) {\n\t\t\t$$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;\n\t\t}\n\n\t\t!hasArc && config.axis_x_show && $$.updateXAxisTickClip();\n\t}\n\n\t/**\n\t * Update targeted element with given data\n\t * @param {Object} targets Data object formatted as 'target'\n\t * @private\n\t */\n\tupdateTargets(targets) {\n\t\tconst $$ = this;\n\n\t\t// Text\n\t\t$$.updateTargetsForText(targets);\n\n\t\t// Bar\n\t\t$$.updateTargetsForBar(targets);\n\n\t\t// Line\n\t\t$$.updateTargetsForLine(targets);\n\n\t\t// Arc & Radar\n\t\t$$.hasArcType(targets) && (\n\t\t\t$$.hasType(\"radar\") ?\n\t\t\t\t$$.updateTargetsForRadar(targets) :\n\t\t\t\t$$.updateTargetsForArc(targets)\n\t\t);\n\n\t\t// Sub Chart\n\t\t$$.updateTargetsForSubchart &&\n\t\t\t$$.updateTargetsForSubchart(targets);\n\n\t\t// Fade-in each chart\n\t\t$$.showTargets();\n\t}\n\n\t/**\n\t * Display targeted elements\n\t * @private\n\t */\n\tshowTargets() {\n\t\tconst $$ = this;\n\n\t\t$$.svg.selectAll(`.${CLASS.target}`)\n\t\t\t.filter(d => $$.isTargetToShow(d.id))\n\t\t\t.transition()\n\t\t\t.duration($$.config.transition_duration)\n\t\t\t.style(\"opacity\", \"1\");\n\t}\n\n\tgetWithOption(options) {\n\t\tconst withOptions = {\n\t\t\tY: true,\n\t\t\tSubchart: true,\n\t\t\tTransition: true,\n\t\t\tEventRect: true,\n\t\t\tDimension: true,\n\t\t\tTrimXDomain: true,\n\t\t\tTransform: false,\n\t\t\tUpdateXDomain: false,\n\t\t\tUpdateOrgXDomain: false,\n\t\t\tLegend: false,\n\t\t\tUpdateXAxis: \"UpdateXDomain\",\n\t\t\tTransitionForExit: \"Transition\",\n\t\t\tTransitionForAxis: \"Transition\"\n\t\t};\n\n\t\tObject.keys(withOptions).forEach(key => {\n\t\t\tlet defVal = withOptions[key];\n\n\t\t\tif (isString(defVal)) {\n\t\t\t\tdefVal = withOptions[defVal];\n\t\t\t}\n\n\t\t\twithOptions[key] = getOption(options, `with${key}`, defVal);\n\t\t});\n\n\t\treturn withOptions;\n\t}\n\n\tredraw(options = {}, transitionsValue) {\n\t\tconst $$ = this;\n\t\tconst main = $$.main;\n\t\tconst config = $$.config;\n\t\tconst targetsToShow = $$.filterTargetsToShow($$.data.targets);\n\n\t\tconst initializing = options.initializing;\n\t\tconst flow = options.flow;\n\t\tconst wth = $$.getWithOption(options);\n\t\tconst duration = wth.Transition ? config.transition_duration : 0;\n\t\tconst durationForExit = wth.TransitionForExit ? duration : 0;\n\t\tconst durationForAxis = wth.TransitionForAxis ? duration : 0;\n\t\tconst transitions = transitionsValue || $$.axis.generateTransitions(durationForAxis);\n\n\t\t$$.updateSizes(initializing);\n\n\t\t// update legend and transform each g\n\n\t\tif (wth.Legend && config.legend_show) {\n\t\t\t$$.updateLegend($$.mapToIds($$.data.targets), options, transitions);\n\t\t} else if (wth.Dimension) {\n\t\t\t// need to update dimension (e.g. axis.y.tick.values) because y tick values should change\n\t\t\t// no need to update axis in it because they will be updated in redraw()\n\t\t\t$$.updateDimension(true);\n\t\t}\n\n\t\t// update axis\n\t\t// @TODO: Make 'init' state to be accessible everywhere not passing as argument.\n\t\t$$.axis.redrawAxis(targetsToShow, wth, transitions, flow, initializing);\n\n\t\t// update circleY based on updated parameters\n\t\t$$.updateCircleY();\n\n\t\t// Data empty label positioning and text.\n\t\tconfig.data_empty_label_text && main.select(`text.${CLASS.text}.${CLASS.empty}`)\n\t\t\t.attr(\"x\", $$.width / 2)\n\t\t\t.attr(\"y\", $$.height / 2)\n\t\t\t.text(config.data_empty_label_text)\n\t\t\t.style(\"display\", targetsToShow.length ? \"none\" : null);\n\n\t\t// grid\n\t\t$$.updateGrid(duration);\n\n\t\t// rect for regions\n\t\t$$.updateRegion(duration);\n\n\t\t// bars\n\t\t$$.updateBar(durationForExit);\n\n\t\t// lines, areas and circles\n\t\t$$.updateLine(durationForExit);\n\t\t$$.updateArea(durationForExit);\n\t\t$$.updateCircle();\n\n\t\t// text\n\t\t$$.hasDataLabel() && $$.updateText(durationForExit);\n\n\t\t// title\n\t\t$$.redrawTitle && $$.redrawTitle();\n\n\t\t// arc\n\t\t$$.arcs && $$.redrawArc(duration, durationForExit, wth.Transform);\n\n\t\t// radar\n\t\t$$.radars && $$.redrawRadar(durationForExit);\n\n\t\t// circles for select\n\t\t$$.mainText && main.selectAll(`.${CLASS.selectedCircles}`)\n\t\t\t.filter($$.isBarType.bind($$))\n\t\t\t.selectAll(\"circle\")\n\t\t\t.remove();\n\n\t\t// event rects will redrawn when flow called\n\t\tif (config.interaction_enabled && !flow && wth.EventRect) {\n\t\t\t$$.bindZoomEvent();\n\t\t}\n\n\t\tinitializing && $$.setChartElements();\n\n\t\t$$.generateRedrawList(targetsToShow, flow, duration, wth.Subchart);\n\t\t$$.callPluginHook(\"$redraw\", options, duration);\n\t}\n\n\t/**\n\t * Generate redraw list\n\t * @param {Object} targets targets data to be shown\n\t * @param {Object} flow\n\t * @param {Object} duration\n\t * @param {Boolean} withSubchart whether or not to show subchart\n\t * @private\n\t */\n\tgenerateRedrawList(targets, flow, duration, withSubchart) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst shape = $$.getDrawShape();\n\n\t\t// subchart\n\t\tconfig.subchart_show && $$.redrawSubchart(withSubchart, duration, shape);\n\n\t\t// generate flow\n\t\tconst flowFn = flow && $$.generateFlow({\n\t\t\ttargets,\n\t\t\tflow,\n\t\t\tduration: flow.duration,\n\t\t\tshape,\n\t\t\txv: $$.xv.bind($$)\n\t\t});\n\t\tconst isTransition = (duration || flowFn) && $$.isTabVisible();\n\n\t\t// redraw list\n\t\tconst redrawList = $$.getRedrawList(shape, flow, flowFn, isTransition);\n\n\t\t// callback function after redraw ends\n\t\tconst afterRedraw = flow || config.onrendered ? () => {\n\t\t\tflowFn && flowFn();\n\t\t\tcallFn(config.onrendered, $$, $$.api);\n\t\t} : null;\n\n\t\tif (afterRedraw) {\n\t\t\t// Only use transition when current tab is visible.\n\t\t\tif (isTransition && redrawList.length) {\n\t\t\t\t// Wait for end of transitions for callback\n\t\t\t\tconst waitForDraw = $$.generateWait();\n\n\t\t\t\t// transition should be derived from one transition\n\t\t\t\td3Transition().duration(duration)\n\t\t\t\t\t.each(() => {\n\t\t\t\t\t\tredrawList\n\t\t\t\t\t\t\t.reduce((acc, t1) => acc.concat(t1), [])\n\t\t\t\t\t\t\t.forEach(t => waitForDraw.add(t));\n\t\t\t\t\t})\n\t\t\t\t\t.call(waitForDraw, afterRedraw);\n\t\t\t} else if (!$$.transiting) {\n\t\t\t\tafterRedraw();\n\t\t\t}\n\t\t}\n\n\t\t// update fadein condition\n\t\t$$.mapToIds($$.data.targets).forEach(id => {\n\t\t\t$$.withoutFadeIn[id] = true;\n\t\t});\n\t}\n\n\t/**\n\t * Get the shape draw function\n\t * @return {Object}\n\t * @private\n\t */\n\tgetDrawShape() {\n\t\tconst $$ = this;\n\t\tconst isRotated = $$.config.axis_rotated;\n\t\tconst hasRadar = $$.hasType(\"radar\");\n\t\tconst shape = {type: {}, indices: {}};\n\n\t\t// setup drawer - MEMO: these must be called after axis updated\n\t\tif ($$.hasTypeOf(\"Line\") || $$.hasType(\"bubble\") || $$.hasType(\"scatter\")) {\n\t\t\tconst indices = $$.getShapeIndices($$.isLineType);\n\n\t\t\tshape.indices.line = indices;\n\t\t\tshape.type.line = $$.generateDrawLine ? $$.generateDrawLine(indices, false) : undefined;\n\n\t\t\tif ($$.hasTypeOf(\"Area\")) {\n\t\t\t\tconst indices = $$.getShapeIndices($$.isAreaType);\n\n\t\t\t\tshape.indices.area = indices;\n\t\t\t\tshape.type.area = $$.generateDrawArea ? $$.generateDrawArea(indices, false) : undefined;\n\t\t\t}\n\t\t}\n\n\t\tif ($$.hasType(\"bar\")) {\n\t\t\tconst indices = $$.getShapeIndices($$.isBarType);\n\n\t\t\tshape.indices.bar = indices;\n\t\t\tshape.type.bar = $$.generateDrawBar ? $$.generateDrawBar(indices) : undefined;\n\t\t}\n\n\t\tshape.pos = {\n\t\t\txForText: $$.generateXYForText(shape.indices, true),\n\t\t\tyForText: $$.generateXYForText(shape.indices, false),\n\n\t\t\t// generate circle x/y functions depending on updated params\n\t\t\tcx: (hasRadar ? $$.radarCircleX : (isRotated ? $$.circleY : $$.circleX)).bind($$),\n\t\t\tcy: (hasRadar ? $$.radarCircleY : (isRotated ? $$.circleX : $$.circleY)).bind($$)\n\t\t};\n\n\t\treturn shape;\n\t}\n\n\tgetRedrawList(shape, flow, flowFn, isTransition) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst hasArcType = $$.hasArcType();\n\t\tconst {cx, cy, xForText, yForText} = shape.pos;\n\t\tconst list = [];\n\n\t\tif (!hasArcType) {\n\t\t\tconst {area, bar, line} = shape.type;\n\n\t\t\tif (config.grid_x_lines.length || config.grid_y_lines.length) {\n\t\t\t\tlist.push($$.redrawGrid(isTransition));\n\t\t\t}\n\n\t\t\tif (config.regions.length) {\n\t\t\t\tlist.push($$.redrawRegion(isTransition));\n\t\t\t}\n\n\t\t\tif ($$.hasTypeOf(\"Line\")) {\n\t\t\t\tlist.push($$.redrawLine(line, isTransition));\n\t\t\t\t$$.hasTypeOf(\"Area\") && list.push($$.redrawArea(area, isTransition));\n\t\t\t}\n\n\t\t\t$$.hasType(\"bar\") && list.push($$.redrawBar(bar, isTransition));\n\t\t\t!flow && list.push($$.updategridFocus());\n\t\t}\n\n\t\tif (!hasArcType || $$.hasType(\"radar\")) {\n\t\t\tnotEmpty(config.data_labels) &&\n\t\t\t\tlist.push($$.redrawText(xForText, yForText, flow, isTransition));\n\n\t\t\tlist.push($$.redrawCircle(cx, cy, isTransition, flowFn));\n\t\t}\n\n\t\treturn list;\n\t}\n\n\tupdateAndRedraw(options = {}) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet transitions;\n\n\t\t// same with redraw\n\t\toptions.withTransition = getOption(options, \"withTransition\", true);\n\t\toptions.withTransform = getOption(options, \"withTransform\", false);\n\t\toptions.withLegend = getOption(options, \"withLegend\", false);\n\n\t\t// NOT same with redraw\n\t\toptions.withUpdateXDomain = true;\n\t\toptions.withUpdateOrgXDomain = true;\n\t\toptions.withTransitionForExit = false;\n\t\toptions.withTransitionForTransform = getOption(options, \"withTransitionForTransform\", options.withTransition);\n\n\t\t// MEMO: called in updateLegend in redraw if withLegend\n\t\tif (!(options.withLegend && config.legend_show)) {\n\t\t\ttransitions = $$.axis.generateTransitions(\n\t\t\t\toptions.withTransitionForAxis ? config.transition_duration : 0\n\t\t\t);\n\n\t\t\t// Update scales\n\t\t\t$$.updateScales();\n\t\t\t$$.updateSvgSize();\n\n\t\t\t// Update g positions\n\t\t\t$$.transformAll(options.withTransitionForTransform, transitions);\n\t\t}\n\n\t\t// Draw with new sizes & scales\n\t\t$$.redraw(options, transitions);\n\t}\n\n\tredrawWithoutRescale() {\n\t\tthis.redraw({\n\t\t\twithY: false,\n\t\t\twithSubchart: false,\n\t\t\twithEventRect: false,\n\t\t\twithTransitionForAxis: false\n\t\t});\n\t}\n\n\tisTimeSeries() {\n\t\treturn this.config.axis_x_type === \"timeseries\";\n\t}\n\n\tisCategorized() {\n\t\treturn this.config.axis_x_type.indexOf(\"category\") >= 0 || this.hasType(\"radar\");\n\t}\n\n\tisCustomX() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));\n\t}\n\n\tisTimeSeriesY() {\n\t\treturn this.config.axis_y_type === \"timeseries\";\n\t}\n\n\tgetTranslate(target, index = 0) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst hasGauge = $$.hasType(\"gauge\");\n\t\tlet padding = 0;\n\t\tlet x;\n\t\tlet y;\n\n\t\tif (index && /^(x|y2?)$/.test(target)) {\n\t\t\tpadding = $$.getAxisSize(target) * index;\n\t\t}\n\n\t\tif (target === \"main\") {\n\t\t\tx = asHalfPixel($$.margin.left);\n\t\t\ty = asHalfPixel($$.margin.top);\n\t\t} else if (target === \"context\") {\n\t\t\tx = asHalfPixel($$.margin2.left);\n\t\t\ty = asHalfPixel($$.margin2.top);\n\t\t} else if (target === \"legend\") {\n\t\t\tx = $$.margin3.left;\n\t\t\ty = $$.margin3.top + (hasGauge ? 10 : 0);\n\t\t} else if (target === \"x\") {\n\t\t\tx = isRotated ? -padding : 0;\n\t\t\ty = isRotated ? 0 : $$.height + padding;\n\t\t} else if (target === \"y\") {\n\t\t\tx = isRotated ? 0 : -padding;\n\t\t\ty = isRotated ? $$.height + padding : 0;\n\t\t} else if (target === \"y2\") {\n\t\t\tx = isRotated ? 0 : $$.width + padding;\n\t\t\ty = isRotated ? 1 - padding : 0;\n\t\t} else if (target === \"subx\") {\n\t\t\tx = 0;\n\t\t\ty = isRotated ? 0 : $$.height2;\n\t\t} else if (target === \"arc\") {\n\t\t\tx = $$.arcWidth / 2;\n\t\t\ty = $$.arcHeight / 2;\n\t\t} else if (target === \"radar\") {\n\t\t\tconst [width] = $$.getRadarSize();\n\n\t\t\tx = $$.width / 2 - width;\n\t\t\ty = asHalfPixel($$.margin.top);\n\t\t}\n\n\t\treturn `translate(${x}, ${y})`;\n\t}\n\n\tinitialOpacity(d) {\n\t\treturn this.getBaseValue(d) !== null &&\n\t\t\tthis.withoutFadeIn[d.id] ? \"1\" : \"0\";\n\t}\n\n\tinitialOpacityForCircle(d) {\n\t\treturn this.getBaseValue(d) !== null &&\n\t\t\tthis.withoutFadeIn[d.id] ? this.opacityForCircle(d) : \"0\";\n\t}\n\n\topacityForCircle(d) {\n\t\tconst opacity = this.config.point_show ? \"1\" : \"0\";\n\n\t\treturn isValue(this.getBaseValue(d)) ?\n\t\t\t(this.isBubbleType(d) || this.isScatterType(d) ?\n\t\t\t\t\"0.5\" : opacity) : \"0\";\n\t}\n\n\topacityForText() {\n\t\treturn this.hasDataLabel() ? \"1\" : \"0\";\n\t}\n\n\t/**\n\t * Get the zoom or unzoomed scaled value\n\t * @param {Date|Number|Object} d Data value\n\t * @private\n\t */\n\txx(d) {\n\t\tconst $$ = this;\n\t\tconst fn = $$.config.zoom_enabled && $$.zoomScale ?\n\t\t\t$$.zoomScale : this.x;\n\n\t\treturn d ? fn(isValue(d.x) ? d.x : d) : null;\n\t}\n\n\txv(d) {\n\t\tconst $$ = this;\n\t\tlet value = $$.getBaseValue(d);\n\n\t\tif ($$.isTimeSeries()) {\n\t\t\tvalue = $$.parseDate(value);\n\t\t} else if ($$.isCategorized() && isString(value)) {\n\t\t\tvalue = $$.config.axis_x_categories.indexOf(value);\n\t\t}\n\n\t\treturn Math.ceil($$.x(value));\n\t}\n\n\tyv(d) {\n\t\tconst $$ = this;\n\t\tconst yScale = d.axis && d.axis === \"y2\" ? $$.y2 : $$.y;\n\n\t\treturn Math.ceil(yScale($$.getBaseValue(d)));\n\t}\n\n\tsubxx(d) {\n\t\treturn d ? this.subX(d.x) : null;\n\t}\n\n\ttransformMain(withTransition, transitions) {\n\t\tconst $$ = this;\n\t\tlet xAxis;\n\t\tlet yAxis;\n\t\tlet y2Axis;\n\n\t\tif (transitions && transitions.axisX) {\n\t\t\txAxis = transitions.axisX;\n\t\t} else {\n\t\t\txAxis = $$.main.select(`.${CLASS.axisX}`);\n\n\t\t\tif (withTransition) {\n\t\t\t\txAxis = xAxis.transition();\n\t\t\t}\n\t\t}\n\n\t\tif (transitions && transitions.axisY) {\n\t\t\tyAxis = transitions.axisY;\n\t\t} else {\n\t\t\tyAxis = $$.main.select(`.${CLASS.axisY}`);\n\n\t\t\tif (withTransition) {\n\t\t\t\tyAxis = yAxis.transition();\n\t\t\t}\n\t\t}\n\n\t\tif (transitions && transitions.axisY2) {\n\t\t\ty2Axis = transitions.axisY2;\n\t\t} else {\n\t\t\ty2Axis = $$.main.select(`.${CLASS.axisY2}`);\n\n\t\t\tif (withTransition) {\n\t\t\t\ty2Axis = y2Axis.transition();\n\t\t\t}\n\t\t}\n\n\t\t(withTransition ? $$.main.transition() : $$.main)\n\t\t\t.attr(\"transform\", $$.getTranslate(\"main\"));\n\n\t\txAxis.attr(\"transform\", $$.getTranslate(\"x\"));\n\t\tyAxis.attr(\"transform\", $$.getTranslate(\"y\"));\n\t\ty2Axis.attr(\"transform\", $$.getTranslate(\"y2\"));\n\n\t\t$$.main.select(`.${CLASS.chartArcs}`)\n\t\t\t.attr(\"transform\", $$.getTranslate(\"arc\"));\n\t}\n\n\ttransformAll(withTransition, transitions) {\n\t\tconst $$ = this;\n\n\t\t$$.transformMain(withTransition, transitions);\n\n\t\t$$.config.subchart_show &&\n\t\t\t$$.transformContext(withTransition, transitions);\n\n\t\t$$.legend && $$.transformLegend(withTransition);\n\t}\n\n\tupdateSvgSize() {\n\t\tconst $$ = this;\n\t\tconst brush = $$.svg.select(`.${CLASS.brush} .overlay`);\n\t\tconst brushSize = {width: 0, height: 0};\n\n\t\tif (brush.size()) {\n\t\t\tbrushSize.width = +brush.attr(\"width\");\n\t\t\tbrushSize.height = +brush.attr(\"height\");\n\t\t}\n\n\t\t$$.svg\n\t\t\t.attr(\"width\", $$.currentWidth)\n\t\t\t.attr(\"height\", $$.currentHeight);\n\n\t\t$$.svg.selectAll([`#${$$.clipId}`, `#${$$.clipIdForGrid}`])\n\t\t\t.select(\"rect\")\n\t\t\t.attr(\"width\", $$.width)\n\t\t\t.attr(\"height\", $$.height);\n\n\t\t$$.svg.select(`#${$$.clipIdForXAxis}`)\n\t\t\t.select(\"rect\")\n\t\t\t.attr(\"x\", $$.getXAxisClipX.bind($$))\n\t\t\t.attr(\"y\", $$.getXAxisClipY.bind($$))\n\t\t\t.attr(\"width\", $$.getXAxisClipWidth.bind($$))\n\t\t\t.attr(\"height\", $$.getXAxisClipHeight.bind($$));\n\n\t\t$$.svg.select(`#${$$.clipIdForYAxis}`)\n\t\t\t.select(\"rect\")\n\t\t\t.attr(\"x\", $$.getYAxisClipX.bind($$))\n\t\t\t.attr(\"y\", $$.getYAxisClipY.bind($$))\n\t\t\t.attr(\"width\", $$.getYAxisClipWidth.bind($$))\n\t\t\t.attr(\"height\", $$.getYAxisClipHeight.bind($$));\n\n\t\t$$.svg.select(`#${$$.clipIdForSubchart}`)\n\t\t\t.select(\"rect\")\n\t\t\t.attr(\"width\", $$.width)\n\t\t\t.attr(\"height\", brushSize.height);\n\n\t\t$$.svg.select(`.${CLASS.zoomRect}`)\n\t\t\t.attr(\"width\", $$.width)\n\t\t\t.attr(\"height\", $$.height);\n\t}\n\n\tupdateDimension(withoutAxis) {\n\t\tconst $$ = this;\n\n\t\tif (!withoutAxis) {\n\t\t\tif ($$.xAxis && $$.config.axis_rotated) {\n\t\t\t\t$$.xAxis.create($$.axes.x);\n\t\t\t\t$$.subXAxis.create($$.axes.subx);\n\t\t\t} else {\n\t\t\t\t$$.yAxis && $$.yAxis.create($$.axes.y);\n\t\t\t\t$$.y2Axis && $$.y2Axis.create($$.axes.y2);\n\t\t\t}\n\t\t}\n\n\t\t// pass 'withoutAxis' param to not animate at the init rendering\n\t\t$$.updateScales(withoutAxis);\n\t\t$$.updateSvgSize();\n\t\t$$.transformAll(false);\n\t}\n\n\tbindResize() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst resizeFunction = $$.generateResize();\n\t\tconst list = [];\n\n\t\tlist.push(() => callFn(config.onresize, $$, $$.api));\n\n\t\tif (config.resize_auto) {\n\t\t\tlist.push(() => $$.api.flush(false, true));\n\t\t}\n\n\t\tlist.push(() => callFn(config.onresized, $$, $$.api));\n\n\t\t// add resize functions\n\t\tlist.forEach(v => resizeFunction.add(v));\n\n\t\t// attach resize event\n\t\twindow.addEventListener(\"resize\", $$.resizeFunction = resizeFunction);\n\t}\n\n\tgenerateResize() {\n\t\tconst fn = [];\n\n\t\tfunction callResizeFn() {\n\t\t\t// Delay all resize functions call, to prevent unintended excessive call from resize event\n\t\t\tif (callResizeFn.timeout) {\n\t\t\t\twindow.clearTimeout(callResizeFn.timeout);\n\t\t\t\tcallResizeFn.timeout = null;\n\t\t\t}\n\n\t\t\tcallResizeFn.timeout = window.setTimeout(() => {\n\t\t\t\tfn.forEach(f => f());\n\t\t\t}, 200);\n\t\t}\n\n\t\tcallResizeFn.add = f => fn.push(f);\n\t\tcallResizeFn.remove = f => fn.splice(fn.indexOf(f), 1);\n\n\t\treturn callResizeFn;\n\t}\n\n\tendall(transition, callback) {\n\t\tlet n = 0;\n\n\t\ttransition\n\t\t\t.each(() => ++n)\n\t\t\t.on(\"end\", function(...args) {\n\t\t\t\t!--n && callback.apply(this, ...args);\n\t\t\t});\n\t}\n\n\tgenerateWait() {\n\t\tlet transitionsToWait = [];\n\t\tconst f = function(transition, callback) {\n\t\t\tlet timer;\n\n\t\t\tfunction loop() {\n\t\t\t\tlet done = 0;\n\n\t\t\t\tfor (let i = 0, t; (t = transitionsToWait[i]); i++) {\n\t\t\t\t\tif (t.empty()) {\n\t\t\t\t\t\tdone++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tt.transition();\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tdone++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttimer && clearTimeout(timer);\n\n\t\t\t\tif (done === transitionsToWait.length) {\n\t\t\t\t\tcallback && callback();\n\t\t\t\t} else {\n\t\t\t\t\ttimer = setTimeout(loop, 50);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tloop();\n\t\t};\n\n\t\tf.add = function(transition) {\n\t\t\tisArray(transition) ?\n\t\t\t\t(transitionsToWait = transitionsToWait.concat(transition)) :\n\t\t\t\ttransitionsToWait.push(transition);\n\t\t};\n\n\t\treturn f;\n\t}\n\n\tparseDate(date) {\n\t\tconst $$ = this;\n\t\tlet parsedDate;\n\n\t\tif (date instanceof Date) {\n\t\t\tparsedDate = date;\n\t\t} else if (isString(date)) {\n\t\t\tparsedDate = $$.dataTimeFormat($$.config.data_xFormat)(date);\n\t\t} else if (isNumber(date) && !isNaN(date)) {\n\t\t\tparsedDate = new Date(+date);\n\t\t}\n\n\t\tif (!parsedDate || isNaN(+parsedDate)) {\n\t\t\tconsole && console.error &&\n\t\t\t\tconsole.error(`Failed to parse x '${date}' to Date object`);\n\t\t}\n\n\t\treturn parsedDate;\n\t}\n\n\tisTabVisible() {\n\t\treturn !document.hidden;\n\t}\n\n\tconvertInputType() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet isMobile = false;\n\n\t\t// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#Mobile_Tablet_or_Desktop\n\t\tif (/Mobi/.test(window.navigator.userAgent) && config.interaction_inputType_touch) {\n\t\t\t// Some Edge desktop return true: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/20417074/\n\t\t\tconst hasTouchPoints = window.navigator && \"maxTouchPoints\" in window.navigator && window.navigator.maxTouchPoints > 0;\n\n\t\t\t// Ref: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js\n\t\t\t// On IE11 with IE9 emulation mode, ('ontouchstart' in window) is returning true\n\t\t\tconst hasTouch = (\"ontouchmove\" in window || (window.DocumentTouch && document instanceof window.DocumentTouch));\n\n\t\t\tisMobile = hasTouchPoints || hasTouch;\n\t\t}\n\n\t\tconst hasMouse = config.interaction_inputType_mouse && !isMobile ? (\"onmouseover\" in window) : false;\n\n\t\treturn (hasMouse && \"mouse\") || (isMobile && \"touch\") || null;\n\t}\n\n\t/**\n\t * Call plugin hook\n\t * @param {String} phase The lifecycle phase\n\t * @private\n\t */\n\tcallPluginHook(phase, ...args) {\n\t\tthis.config.plugins.forEach(v => {\n\t\t\tif (phase === \"$beforeInit\") {\n\t\t\t\tv.$$ = this;\n\t\t\t\tthis.api.plugins.push(v);\n\t\t\t}\n\n\t\t\tv[phase](...args);\n\t\t});\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\n\n/**\n * Main chart class.\n * - Note: Instantiated via `bb.generate()`.\n * @class Chart\n * @example\n * var chart = bb.generate({\n * data: {\n * columns: [\n *\t [\"x\", \"2015-11-02\", \"2015-12-01\", \"2016-01-01\", \"2016-02-01\", \"2016-03-01\"],\n * \t [\"count1\", 11, 8, 7, 6, 5 ],\n *\t [\"count2\", 9, 3, 6, 2, 8 ]\n * ]}\n * }\n * @see {@link bb.generate} for the initialization.\n*/\n/**\n * Access instance's primary node elements\n * @member {Object} $\n * @property {Object} $\n * @property {d3.selection} $.chart Wrapper element\n * @property {d3.selection} $.svg Main svg element\n * @property {d3.selection} $.defs Definition element\n * @property {d3.selection} $.main Main grouping element\n * @property {d3.selection} $.tooltip Tooltip element\n * @property {d3.selection} $.legend Legend element\n * @property {d3.selection} $.title Title element\n * @property {d3.selection} $.grid Grid element\n * @property {d3.selection} $.arc Arc element\n * @property {Object} $.bar\n * @property {d3.selection} $.bar.bars Bar elements\n * @property {Object} $.line\n * @property {d3.selection} $.line.lines Line elements\n * @property {d3.selection} $.line.areas Areas elements\n * @property {d3.selection} $.line.circles Data point circle elements\n * @property {Object} $.text\n * @property {d3.selection} $.text.texts Data label text elements\n * @memberof Chart\n * @example\n * var chart = bb.generate({ ... });\n *\n * chart.$.chart; // wrapper element\n * chart.$.line.circles; // all data point circle elements\n */\nexport default class Chart {\n\tconstructor(config) {\n\t\tconst $$ = new ChartInternal(this);\n\n\t\t/**\n\t\t * Plugin instance array\n\t\t * @member {Array} plugins\n\t\t * @memberof Chart\n\t\t * @instance\n \t \t * @example\n\t\t * var chart = bb.generate({\n\t\t * ...\n\t\t * plugins: [\n\t\t * new bb.plugin.stanford({ ... }),\n\t\t * new PluginA()\n\t\t * ]\n\t\t * });\n\t\t *\n\t\t * chart.plugins; // [Stanford, PluginA] - instance array\n\t\t */\n\t\tthis.plugins = [];\n\t\tthis.internal = $$;\n\n\t\t$$.loadConfig(config);\n\t\t$$.beforeInit(config);\n\t\t$$.init();\n\n\t\t// bind \"this\" to nested API\n\t\t(function bindThis(fn, target, argThis) {\n\t\t\tObject.keys(fn).forEach(key => {\n\t\t\t\ttarget[key] = fn[key].bind(argThis);\n\n\t\t\t\tObject.keys(fn[key]).length &&\n\t\t\t\t\tbindThis(fn[key], target[key], argThis);\n\t\t\t});\n\t\t})(Chart.prototype, this, this);\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\n/**\n * Class to set options on generating chart.\n * - It's instantiated internally, not exposed for public.\n * @class Options\n * @see {@link bb.generate} to use these options on generating the chart\n */\nexport default class Options {\n\tconstructor() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * Specify the CSS selector or the element which the chart will be set to. D3 selection object can be specified also.<br>\n\t\t\t * If other chart is set already, it will be replaced with the new one (only one chart can be set in one element).\n\t\t\t * - **NOTE:** In case of element doesn't exist or not specified, will add a `<div>` element to the body.\n\t\t\t * @name bindto\n\t\t\t * @memberof Options\n\t\t\t * @property {String|HTMLElement|d3.selection} bindto=#chart Specify the element where chart will be drawn.\n\t\t\t * @property {String|HTMLElement|d3.selection} bindto.element=#chart Specify the element where chart will be drawn.\n\t\t\t * @property {String} [bindto.classname=bb] Specify the class name of bind element.<br>\n\t\t\t * **NOTE:** When class name isn't `bb`, then you also need to update the default CSS to be rendered correctly.\n\t\t\t * @default #chart\n\t\t\t * @example\n\t\t\t * bindto: \"#myContainer\"\n\t\t\t *\n\t\t\t * // or HTMLElement\n\t\t\t * bindto: document.getElementById(\"myContainer\")\n\t\t\t *\n\t\t\t * // or D3 selection object\n\t\t\t * bindto: d3.select(\"#myContainer\")\n\t\t\t *\n\t\t\t * // or to change default classname\n\t\t\t * bindto: {\n\t\t\t * element: \"#chart\",\n\t\t\t * classname: \"bill-board\" // ex) <div id='chart' class='bill-board'>\n\t\t\t * }\n\t\t\t */\n\t\t\tbindto: \"#chart\",\n\n\t\t\t/**\n\t\t\t * Set chart background.\n\t\t\t * @name background\n\t\t\t * @memberof Options\n\t\t\t * @property {String} background.class Specify the class name for background element.\n\t\t\t * @property {String} background.color Specify the fill color for background element.<br>**NOTE:** Will be ignored if `imgUrl` option is set.\n\t\t\t * @property {String} background.imgUrl Specify the image url string for background.\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.Background)\n\t\t\t * @example\n\t\t\t * background: {\n\t\t\t * class: \"myClass\",\n\t\t\t * color: \"red\",\n\t\t\t *\n\t\t\t * // Set image url for background.\n\t\t\t * // If specified, 'color' option will be ignored.\n\t\t\t * imgUrl: \"https://naver.github.io/billboard.js/img/logo/billboard.js.svg\",\n\t\t\t * }\n\t\t\t */\n\t\t\tbackground: {},\n\n\t\t\t/**\n\t\t\t * Set 'clip-path' attribute for chart element\n\t\t\t * - **NOTE:**\n\t\t\t * > When is false, chart node element is positioned after the axis node in DOM tree hierarchy.\n\t\t\t * > Is to make chart element positioned over axis element.\n\t\t\t * @name clipPath\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.clipPath)\n\t\t\t * @example\n\t\t\t * // don't set 'clip-path' attribute\n\t\t\t * clipPath: false\n\t\t\t */\n\t\t\tclipPath: true,\n\n\t\t\t/**\n\t\t\t * Set svg element's class name\n\t\t\t * @name svg\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {String} [svg.classname] class name for svg element\n\t\t\t * @example\n\t\t\t * svg: {\n * classname: \"test_class\"\n\t\t\t * }\n\t\t\t */\n\t\t\tsvg_classname: undefined,\n\n\t\t\t/**\n\t\t\t * The desired size of the chart element.\n\t\t\t * If value is not specified, the width of the chart will be calculated by the size of the parent element it's appended to.\n\t\t\t * @name size\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number} [size.width] width of the chart element\n\t\t\t * @property {Number} [size.height] height of the chart element\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.ChartSize)\n\t\t\t * @example\n\t\t\t * size: {\n * width: 640,\n * height: 480\n\t\t\t * }\n\t\t\t */\n\t\t\tsize_width: undefined,\n\t\t\tsize_height: undefined,\n\n\t\t\t/**\n\t\t\t * The padding of the chart element.\n\t\t\t * @name padding\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number} [padding.top] padding on the top of chart\n\t\t\t * @property {Number} [padding.right] padding on the right of chart\n\t\t\t * @property {Number} [padding.bottom] padding on the bottom of chart\n\t\t\t * @property {Number} [padding.left] padding on the left of chart\n\t\t\t * @example\n\t\t\t * padding: {\n * top: 20,\n * right: 20,\n * bottom: 20,\n * left: 20\n\t\t\t * }\n\t\t\t */\n\t\t\tpadding_left: undefined,\n\t\t\tpadding_right: undefined,\n\t\t\tpadding_top: undefined,\n\t\t\tpadding_bottom: undefined,\n\n\t\t\t/**\n\t\t\t * Set chart resize options\n\t\t\t * @name resize\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [resize.auto=true] Set chart resize automatically on viewport changes.\n\t\t\t * @example\n\t\t\t * resize: {\n\t\t\t * auto: false\n\t\t\t * }\n\t\t\t */\n\t\t\tresize_auto: true,\n\n\t\t\t/**\n\t\t\t * Set zoom options\n\t\t\t * @name zoom\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [zoom.enabled=false] Enable zooming.\n\t\t\t * @property {String} [zoom.enabled.type='wheel'] Set zoom interaction type.\n\t\t\t * - **Available types:**\n\t\t\t * - wheel\n\t\t\t * - drag\n\t\t\t * @property {Boolean} [zoom.rescale=false] Enable to rescale after zooming.<br>\n\t\t\t * If true set, y domain will be updated according to the zoomed region.\n\t\t\t * @property {Array} [zoom.extent=[1, 10]] Change zoom extent.\n\t\t\t * @property {Number|Date} [zoom.x.min] Set x Axis minimum zoom range\n\t\t\t * @property {Number|Date} [zoom.x.max] Set x Axis maximum zoom range\n\t\t\t * @property {Function} [zoom.onzoomstart=undefined] Set callback that is called when zooming starts.<br>\n\t\t\t * Specified function receives the zoom event.\n\t\t\t * @property {Function} [zoom.onzoom=undefined] Set callback that is called when the chart is zooming.<br>\n\t\t\t * Specified function receives the zoomed domain.\n\t\t\t * @property {Function} [zoom.onzoomend=undefined] Set callback that is called when zooming ends.<br>\n\t\t\t * Specified function receives the zoomed domain.\n\t\t\t * @property {Boolean|Object} [zoom.resetButton=true] Set to display zoom reset button for 'drag' type zoom\n\t\t\t * @property {Function} [zoom.resetButton.onclick] Set callback when clicks the reset button. The callback will receive reset button element reference as argument.\n\t\t\t * @property {String} [zoom.resetButton.text='Reset Zoom'] Text value for zoom reset button.\n\t\t\t * @see [Demo:zoom](https://naver.github.io/billboard.js/demo/#Interaction.Zoom)\n\t\t\t * @see [Demo:drag zoom](https://naver.github.io/billboard.js/demo/#Interaction.DragZoom)\n\t\t\t * @example\n\t\t\t * zoom: {\n\t\t\t * enabled: {\n * type: \"drag\"\n * },\n\t\t\t * rescale: true,\n\t\t\t * extent: [1, 100] // enable more zooming\n\t\t\t * x: {\n\t\t\t * min: -1, // set min range\n\t\t\t * max: 10 // set max range\n\t\t\t * },\n\t\t\t * onzoomstart: function(event) { ... },\n\t\t\t * onzoom: function(domain) { ... },\n\t\t\t * onzoomend: function(domain) { ... },\n\t\t\t *\n\t\t\t * // show reset button when is zoomed-in\n\t\t\t * resetButton: true,\n\t\t\t *\n\t\t\t * resetButton: {\n\t\t\t * // onclick callback when reset button is clicked\n\t\t\t * onclick: function(button) {\n\t\t\t * button; // Reset button element reference\n\t\t\t * ...\n\t\t\t * },\n\t\t\t *\n\t\t\t * // customized text value for reset zoom button\n\t\t\t * text: \"Unzoom\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tzoom_enabled: undefined,\n\t\t\tzoom_extent: undefined,\n\t\t\tzoom_privileged: false,\n\t\t\tzoom_rescale: false,\n\t\t\tzoom_onzoom: undefined,\n\t\t\tzoom_onzoomstart: undefined,\n\t\t\tzoom_onzoomend: undefined,\n\t\t\tzoom_resetButton: true,\n\t\t\tzoom_x_min: undefined,\n\t\t\tzoom_x_max: undefined,\n\n\t\t\t/**\n\t\t\t * Interaction options\n\t\t\t * @name interaction\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [interaction.enabled=true] Indicate if the chart should have interactions.<br>\n\t\t\t * If `false` is set, all of interactions (showing/hiding tooltip, selection, mouse events, etc) will be disabled.\n\t\t\t * @property {Boolean} [interaction.brighten=true] Make brighter for the selected area (ex. 'pie' type data selected area)\n\t\t\t * @property {Boolean} [interaction.inputType.mouse=true] enable or disable mouse interaction\n\t\t\t * @property {Boolean} [interaction.inputType.touch=true] enable or disable touch interaction\n\t\t\t * @property {Boolean|Number} [interaction.inputType.touch.preventDefault=false] enable or disable to call event.preventDefault on touchstart & touchmove event. It's usually used to prevent document scrolling.\n\t\t\t * @see [Demo: touch.preventDefault](https://naver.github.io/billboard.js/demo/#Interaction.PreventScrollOnTouch)\n\t\t\t * @example\n\t\t\t * interaction: {\n * enabled: false,\n * brighten: false,\n * inputType: {\n * mouse: true,\n * touch: false\n *\n * // or declare preventDefault explicitly.\n * // In this case touch inputType is enabled by default\n * touch: {\n * preventDefault: true\n *\n * // or threshold pixel value (pixel moved from touchstart to touchmove)\n * preventDefault: 5\n * }\n * }\n\t\t\t * }\n\t\t\t */\n\t\t\tinteraction_enabled: true,\n\t\t\tinteraction_brighten: true,\n\t\t\tinteraction_inputType_mouse: true,\n\t\t\tinteraction_inputType_touch: {},\n\n\t\t\t/**\n\t\t\t * Set a callback to execute when mouse/touch enters the chart.\n\t\t\t * @name onover\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onover: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonover: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute when mouse/touch leaves the chart.\n\t\t\t * @name onout\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onout: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonout: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute when user resizes the screen.\n\t\t\t * @name onresize\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onresize: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonresize: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute when screen resize finished.\n\t\t\t * @name onresized\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onresized: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonresized: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute before the chart is initialized\n\t\t\t * @name onbeforeinit\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onbeforeinit: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonbeforeinit: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute when the chart is initialized.\n\t\t\t * @name oninit\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * oninit: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\toninit: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback to execute after the chart is initialized\n\t\t\t * @name onafterinit\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onafterinit: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonafterinit: undefined,\n\n\t\t\t/**\n\t\t\t * 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.\n\t\t\t * @name onrendered\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * // @param {Chart} ctx - Instance itself\n\t\t\t * onrendered: function(ctx) {\n\t\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tonrendered: undefined,\n\n\t\t\t/**\n\t\t\t * Set duration of transition (in milliseconds) for chart animation.<br><br>\n\t\t\t * - **NOTE:** If `0 `or `null` set, transition will be skipped. So, this makes initial rendering faster especially in case you have a lot of data.\n\t\t\t * @name transition\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number} [transition.duration=350] duration in milliseconds\n\t\t\t * @example\n\t\t\t * transition: {\n\t\t\t * duration: 500\n\t\t\t * }\n\t\t\t */\n\t\t\ttransition_duration: 350,\n\n\t\t\t/**\n\t\t\t * Specify the key of x values in the data.<br><br>\n\t\t\t * We can show the data with non-index x values by this option. This option is required when the type of x axis is timeseries. If this option is set on category axis, the values of the data on the key will be used for category names.\n\t\t\t * @name data․x\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * data: {\n * x: \"date\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_x: undefined,\n\n\t\t\t/**\n\t\t\t * Specify the keys of the x values for each data.<br><br>\n\t\t\t * This option can be used if we want to show the data that has different x values.\n\t\t\t * @name data․xs\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n * xs: {\n * data1: \"x1\",\n * data2: \"x2\"\n * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_xs: {},\n\n\t\t\t/**\n\t\t\t * Set a format specifier to parse string specifed as x.\n\t\t\t * @name data․xFormat\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default %Y-%m-%d\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * x: \"x\",\n\t\t\t * columns: [\n\t\t\t * [\"x\", \"01012019\", \"02012019\", \"03012019\"],\n\t\t\t * [\"data1\", 30, 200, 100]\n\t\t\t * ],\n\t\t\t * // Format specifier to parse as datetime for given 'x' string value\n\t\t\t * xFormat: \"%m%d%Y\"\n\t\t\t * },\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * type: \"timeseries\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * @see [D3's time specifier](https://github.com/d3/d3-time-format#locale_format)\n\t\t\t */\n\t\t\tdata_xFormat: \"%Y-%m-%d\",\n\n\t\t\t/**\n\t\t\t * Set localtime format to parse x axis.\n\t\t\t * @name data․xLocaltime\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * data: {\n * xLocaltime: false\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_xLocaltime: true,\n\n\t\t\t/**\n\t\t\t * Sort on x axis.\n\t\t\t * @name data․xSort\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * data: {\n * xSort: false\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_xSort: true,\n\n\t\t\t/**\n\t\t\t * Converts data id value\n\t\t\t * @name data․idConverter\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function(id) { return id; }\n\t\t\t * @example\n\t\t\t * data: {\n * idConverter: function(id) {\n * // when id is 'data1', converts to be 'data2'\n * // 'data2' should be given as the initial data value\n * if (id === \"data1\") {\n * return \"data2\";\n * } else {\n * return id;\n * }\n * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_idConverter: id => id,\n\n\t\t\t/**\n\t\t\t * Set custom data name.\n\t\t\t * @name data․names\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataName)\n\t\t\t * @example\n\t\t\t * data: {\n * names: {\n * data1: \"Data Name 1\",\n * data2: \"Data Name 2\"\n * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_names: {},\n\n\t\t\t/**\n\t\t\t * Set custom data class.<br><br>\n\t\t\t * If this option is specified, the element g for the data has an additional class that has the prefix 'bb-target-' (eg. bb-target-additional-data1-class).\n\t\t\t * @name data․classes\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n * classes: {\n * data1: \"additional-data1-class\",\n * data2: \"additional-data2-class\"\n * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_classes: {},\n\n\t\t\t/**\n\t\t\t * Set groups for the data for stacking.\n\t\t\t * @name data․groups\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default []\n\t\t\t * @example\n\t\t\t * data: {\n * groups: [\n * [\"data1\", \"data2\"],\n * [\"data3\"]\n * ]\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_groups: [],\n\n\t\t\t/**\n\t\t\t * Set y axis the data related to. y and y2 can be used.\n\t\t\t * - **NOTE:** If all data is related to one of the axes, the domain of axis without related data will be replaced by the domain from the axis with related data\n\t\t\t * @name data․axes\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * axes: {\n\t\t\t * data1: \"y\",\n\t\t\t * data2: \"y2\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_axes: {},\n\n\t\t\t/**\n\t\t\t * Set chart type at once.<br><br>\n\t\t\t * If this option is specified, the type will be applied to every data. This setting can be overwritten by data.types.<br><br>\n\t\t\t * **Available Values:**\n\t\t\t * - area\n\t\t\t * - area-line-range\n\t\t\t * - area-spline\n\t\t\t * - area-spline-range\n\t\t\t * - area-step\n\t\t\t * - bar\n\t\t\t * - bubble\n\t\t\t * - donut\n\t\t\t * - gauge\n\t\t\t * - line\n\t\t\t * - pie\n\t\t\t * - radar\n\t\t\t * - scatter\n\t\t\t * - spline\n\t\t\t * - step\n\t\t\t * @name data․type\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default line\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * type: \"bar\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_type: undefined,\n\n\t\t\t/**\n\t\t\t * Set chart type for each data.<br>\n\t\t\t * This setting overwrites data.type setting.\n\t\t\t * - **NOTE:** `radar` type can't be combined with other types.\n\t\t\t * @name data․types\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * types: {\n\t\t\t * data1: \"bar\",\n\t\t\t * data2: \"spline\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_types: {},\n\n\t\t\t/**\n\t\t\t * Set labels options\n\t\t\t * @name data․labels\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [data.labels=false] Show or hide labels on each data points\n\t\t\t * @property {Boolean} [data.labels.centered=false] Centerize labels on `bar` shape. (**NOTE:** works only for 'bar' type)\n\t\t\t * @property {Function} [data.labels.format] Set formatter function for data labels.<br>\n\t\t\t * The formatter function receives 4 arguments such as v, id, i, j and it must return a string that will be shown as the label. The arguments are:<br>\n\t\t\t * - `v` is the value of the data point where the label is shown.\n\t\t\t * - `id` is the id of the data where the label is shown.\n\t\t\t * - `i` is the index of the data point where the label is shown.\n\t\t\t * - `j` is the sub index of the data point where the label is shown.<br><br>\n\t\t\t * Formatter function can be defined for each data by specifying as an object and D3 formatter function can be set (ex. d3.format('$'))\n \t\t\t * @property {String|Object} [data.labels.colors] Set label text colors.\n\t\t\t * @property {Object} [data.labels.position] Set each dataset position, relative the original.\n\t\t\t * @property {Number} [data.labels.position.x=0] x coordinate position, relative the original.\n\t\t\t * @property {Number} [data.labels.position.y=0] y coordinate position, relative the original.\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataLabel)\n\t\t\t * @see [Demo: label colors](https://naver.github.io/billboard.js/demo/#Data.DataLabelColors)\n\t\t\t * @see [Demo: label format](https://naver.github.io/billboard.js/demo/#Data.DataLabelFormat)\n\t\t\t * @see [Demo: label overlap](https://naver.github.io/billboard.js/demo/#Data.DataLabelOverlap)\n\t\t\t * @see [Demo: label position](https://naver.github.io/billboard.js/demo/#Data.DataLabelPosition)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * labels: true,\n\t\t\t *\n\t\t\t * // or set specific options\n\t\t\t * labels: {\n\t\t\t * format: function(v, id, i, j) { ... },\n\t\t\t *\n\t\t\t * // it's possible to set for each data\n\t\t\t * format: {\n\t\t\t * data1: function(v, id, i, j) { ... },\n\t\t\t * ...\n\t\t\t * },\n\t\t\t *\n\t\t\t * // align text to center of the 'bar' shape (works only for 'bar' type)\n\t\t\t * centered: true,\n\t\t\t *\n\t\t\t * // apply for all label texts\n\t\t\t * colors: \"red\",\n\t\t\t *\n\t\t\t * // or set different colors per dataset\n\t\t\t * // for not specified dataset, will have the default color value\n\t\t\t * colors: {\n\t\t\t * data1: \"yellow\",\n\t\t\t * data3: \"green\"\n\t\t\t * },\n\t\t\t *\n\t\t\t * // set x, y coordinate position\n\t\t\t * position: {\n\t\t\t * x: -10,\n\t\t\t * y: 10\n\t\t\t * },\n\t\t\t *\n\t\t\t * // or set x, y coordinate position by each dataset\n\t\t\t * position: {\n\t\t\t * data1: {x: 5, y: 5},\n\t\t\t * data2: {x: 10, y: -20}\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_labels: {},\n\t\t\tdata_labels_colors: undefined,\n\t\t\tdata_labels_position: {},\n\n\t\t\t/**\n\t\t\t * This option changes the order of stacking data and pieces of pie/donut.\n\t\t\t * - If `null` specified, it will be the order the data loaded.\n\t\t\t * - If function specified, it will be used as [Array.sort compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)<br><br>\n\t\t\t *\n\t\t\t * **Available Values:**\n\t\t\t * - `desc`: In descending order\n\t\t\t * - `asc`: In ascending order\n\t\t\t * - `null`: It keeps the data load order\n\t\t\t * - `function(data1, data2) { ... }`: Array.sort compareFunction\n\t\t\t * @name data․order\n\t\t\t * @memberof Options\n\t\t\t * @type {String|Function|null}\n\t\t\t * @default desc\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataOrder)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * // in descending order (default)\n\t\t\t * order: \"desc\"\n\t\t\t *\n\t\t\t * // in ascending order\n\t\t\t * order: \"asc\"\n\t\t\t *\n\t\t\t * // keeps data input order\n\t\t\t * order: null\n\t\t\t *\n\t\t\t * // specifying sort function\n\t\t\t * order: function(a, b) {\n\t\t\t * // param data passed format\n\t\t\t * {\n\t\t\t * id: \"data1\", id_org: \"data1\", values: [\n\t\t\t * {x: 5, value: 250, id: \"data1\", index: 5, name: \"data1\"},\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_order: \"desc\",\n\n\t\t\t/**\n\t\t\t * Define regions for each data.<br>\n\t\t\t * The values must be an array for each data and it should include an object that has `start`, `end` and `style`.\n\t\t\t * - The object type should be as:\n\t\t\t * - start {Number}: Start data point number. If not set, the start will be the first data point.\n\t\t\t * - [end] {Number}: End data point number. If not set, the end will be the last data point.\n\t\t\t * - [style.dasharray=\"2 2\"] {Object}: The first number specifies a distance for the filled area, and the second a distance for the unfilled area.\n\t\t\t * - **NOTE:** Currently this option supports only line chart and dashed style. If this option specified, the line will be dashed only in the regions.\n\t\t\t * @name data․regions\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * regions: {\n\t\t\t * data1: [{\n\t\t\t * start: 1,\n\t\t\t * end: 2,\n\t\t\t * style: {\n\t\t\t * dasharray: \"5 2\"\n\t\t\t * }\n\t\t\t * }, {\n\t\t\t * start: 3\n\t\t\t * }],\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_regions: {},\n\n\t\t\t/**\n\t\t\t * Set color converter function.<br><br>\n\t\t\t * This option should a function and the specified function receives color (e.g. '#ff0000') and d that has data parameters like id, value, index, etc. And it must return a string that represents color (e.g. '#00ff00').\n\t\t\t * @name data․color\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataColor)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * color: function(color, d) { ... }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_color: undefined,\n\n\t\t\t/**\n\t\t\t * Set color for each data.\n\t\t\t * @name data․colors\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * colors: {\n\t\t\t * data1: \"#ff0000\",\n\t\t\t * data2: function(d) {\n\t\t\t * return \"#000\";\n\t\t\t * }\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_colors: {},\n\n\t\t\t/**\n\t\t\t * Hide each data when the chart appears.<br><br>\n\t\t\t * If true specified, all of data will be hidden. If multiple ids specified as an array, those will be hidden.\n\t\t\t * @name data․hide\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean|Array}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * // all of data will be hidden\n\t\t\t * hide: true\n\t\t\t *\n\t\t\t * // specified data will be hidden\n\t\t\t * hide: [\"data1\", ...]\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_hide: false,\n\n\t\t\t/**\n\t\t\t * Filter values to be shown\n\t\t\t * The data value is the same as the returned by `.data()`.\n\t\t\t * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter\n\t\t\t * @name data․filter\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * // filter for id value\n\t\t\t * filter: function(v) {\n\t\t\t * // v: [{id: \"data1\", id_org: \"data1\", values: [\n\t\t\t * // {x: 0, value: 130, id: \"data2\", index: 0}, ...]\n\t\t\t * // }, ...]\n\t\t\t * return v.id !== \"data1\";\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_filter: undefined,\n\n\t\t\t/**\n\t\t\t * Set the stacking to be normalized\n\t\t\t * - **NOTE:**\n\t\t\t * - For stacking, '[data.groups](#.data%25E2%2580%25A4groups)' option should be set\n\t\t\t * - y Axis will be set in percentage value (0 ~ 100%)\n\t\t\t * - Must have postive values\n\t\t\t * @name data․stack․normalize\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataStackNormalized)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t * stack: {\n\t\t * normalize: true\n\t\t * }\n\t\t * }\n\t\t\t */\n\t\t\tdata_stack_normalize: false,\n\t\t\t/**\n\t\t\t * Set data selection enabled<br><br>\n\t\t\t * If this option is set true, we can select the data points and get/set its state of selection by API (e.g. select, unselect, selected).\n\t\t\t * @name data․selection․enabled\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataSelection)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * selection: {\n\t\t\t * enabled: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_selection_enabled: false,\n\n\t\t\t/**\n\t\t\t * Set grouped selection enabled.<br><br>\n\t\t\t * If this option set true, multiple data points that have same x value will be selected by one selection.\n\t\t\t * @name data․selection․grouped\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * selection: {\n\t\t\t * grouped: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_selection_grouped: false,\n\n\t\t\t/**\n\t\t\t * Set a callback for each data point to determine if it's selectable or not.<br><br>\n\t\t\t * The callback will receive d as an argument and it has some parameters like id, value, index. This callback should return boolean.\n\t\t\t * @name data․selection․isselectable\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() { return true; }\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * selection: {\n\t\t\t * isselectable: function(d) { ... }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_selection_isselectable: () => true,\n\n\t\t\t/**\n\t\t\t * Set multiple data points selection enabled.<br><br>\n\t\t\t * If this option set true, multile data points can have the selected state at the same time. If false set, only one data point can have the selected state and the others will be unselected when the new data point is selected.\n\t\t\t * @name data․selection․multiple\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * selection: {\n\t\t\t * multiple: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_selection_multiple: true,\n\n\t\t\t/**\n\t\t\t * Enable to select data points by dragging.\n\t\t\t * If this option set true, data points can be selected by dragging.\n\t\t\t * - **NOTE:** If this option set true, scrolling on the chart will be disabled because dragging event will handle the event.\n\t\t\t * @name data․selection․draggable\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * selection: {\n\t\t\t * draggable: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_selection_draggable: false,\n\n\t\t\t/**\n\t\t\t * Set a callback for click event on each data point.<br><br>\n\t\t\t * This callback will be called when each data point clicked and will receive `d` and element as the arguments.\n\t\t\t * - `d` is the data clicked and element is the element clicked.\n\t\t\t * - `element` is the current interacting svg element.\n\t\t\t * - In this callback, `this` will be the Chart object.\n\t\t\t * @name data․onclick\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * onclick: function(d, element) {\n\t\t\t * // d - ex) {x: 4, value: 150, id: \"data1\", index: 4, name: \"data1\"}\n\t\t\t * // element - <circle>\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onclick: () => {},\n\n\t\t\t/**\n\t\t\t * Set a callback for mouse/touch over event on each data point.<br><br>\n\t\t\t * This callback will be called when mouse cursor or via touch moves onto each data point and will receive `d` and `element` as the argument.\n\t\t\t * - `d` is the data where mouse cursor moves onto.\n\t\t\t * - `element` is the current interacting svg element.\n\t\t\t * - In this callback, `this` will be the Chart object.\n\t\t\t * @name data․onover\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * onover: function(d, element) {\n\t\t\t * // d - ex) {x: 4, value: 150, id: \"data1\", index: 4}\n\t\t\t * // element - <circle>\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onover: () => {},\n\n\t\t\t/**\n\t\t\t * Set a callback for mouse/touch out event on each data point.<br><br>\n\t\t\t * This callback will be called when mouse cursor or via touch moves out each data point and will receive `d` as the argument.\n\t\t\t * - `d` is the data where mouse cursor moves out.\n\t\t\t * - `element` is the current interacting svg element.\n\t\t\t * - In this callback, `this` will be the Chart object.\n\t\t\t * @name data․onout\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * onout: function(d, element) {\n\t\t\t * // d - ex) {x: 4, value: 150, id: \"data1\", index: 4}\n\t\t\t * // element - <circle>\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onout: () => {},\n\n\t\t\t/**\n\t\t\t * Set a callback for on data selection.\n\t\t\t * @name data․onselected\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * onselected: function(d, element) {\n\t\t\t * // d - ex) {x: 4, value: 150, id: \"data1\", index: 4, name: \"data1\"}\n\t\t\t * // element - <circle>\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onselected: () => {},\n\n\t\t\t/**\n\t\t\t * Set a callback for on data un-selection.\n\t\t\t * @name data․onunselected\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default function() {}\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * onunselected: function(d, element) {\n\t\t\t * // d - ex) {x: 4, value: 150, id: \"data1\", index: 4, name: \"data1\"}\n\t\t\t * // element - <circle>\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onunselected: () => {},\n\n\t\t\t/**\n\t\t\t * Set a callback for minimum data\n\t\t\t * - **NOTE:** For 'area-line-range' and 'area-spline-range', `mid` data will be taken for the comparison\n\t\t\t * @name data․onmin\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)\n\t\t\t * @example\n\t\t\t * onmin: function(data) {\n\t\t\t * // data - ex) [{x: 3, value: 400, id: \"data1\", index: 3}, ... ]\n\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onmin: undefined,\n\n\t\t\t/**\n\t\t\t * Set a callback for maximum data\n\t\t\t * - **NOTE:** For 'area-line-range' and 'area-spline-range', `mid` data will be taken for the comparison\n\t\t\t * @name data․onmax\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.OnMinMaxCallback)\n\t\t\t * @example\n\t\t\t * onmax: function(data) {\n\t\t\t * // data - ex) [{x: 3, value: 400, id: \"data1\", index: 3}, ... ]\n\t\t * ...\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_onmax: undefined,\n\n\t\t\t/**\n\t\t\t * Load a CSV or JSON file from a URL. NOTE that this will not work if loading via the \"file://\" protocol as the most browsers will block XMLHTTPRequests.\n\t\t\t * @name data․url\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.LoadData)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * url: \"/data/test.csv\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_url: undefined,\n\n\t\t\t/**\n\t\t\t * XHR header value\n\t\t\t * - **NOTE:** Should be used with `data.url` option\n\t\t\t * @name data․headers\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default undefined\n\t\t\t * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * url: \"/data/test.csv\",\n\t\t\t * headers: {\n\t\t\t * \"Content-Type\": \"text/xml\",\n\t\t\t * ...\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_headers: undefined,\n\n\t\t\t/**\n\t\t\t * Parse a JSON object for data. See also data.keys.\n\t\t\t * @name data․json\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default undefined\n\t\t\t * @see [data․keys](#.data%25E2%2580%25A4keys)\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.JSONData)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * json: [\n\t\t\t * {name: \"www.site1.com\", upload: 200, download: 200, total: 400},\n\t\t\t * {name: \"www.site2.com\", upload: 100, download: 300, total: 400},\n\t\t\t * {name: \"www.site3.com\", upload: 300, download: 200, total: 500},\n\t\t\t * {name: \"www.site4.com\", upload: 400, download: 100, total: 500}\n\t\t\t * ],\n\t\t\t * keys: {\n\t\t\t * // x: \"name\", // it's possible to specify 'x' when category axis\n\t\t\t * value: [\"upload\", \"download\"]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_json: undefined,\n\n\t\t\t/**\n\t\t\t * Load data from a multidimensional array, with the first element containing the data names, the following containing related data in that order.\n\t\t\t * @name data․rows\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.RowOrientedData)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * rows: [\n\t\t\t * [\"A\", \"B\", \"C\"],\n\t\t\t * [90, 120, 300],\n\t\t\t * [40, 160, 240],\n\t\t\t * [50, 200, 290],\n\t\t\t * [120, 160, 230],\n\t\t\t * [80, 130, 300],\n\t\t\t * [90, 220, 320]\n\t\t\t * ]\n\t\t\t * }\n\t\t\t *\n\t\t\t * // for 'range' types('area-line-range' or 'area-spline-range'), data should contain:\n\t\t\t * // - an array of [high, mid, low] data following the order\n\t\t\t * // - or an object with 'high', 'mid' and 'low' key value\n\t\t\t * data: {\n\t\t\t * rows: [\n\t\t\t * [\"data1\", \"data2\"],\n\t\t\t * [\n\t\t\t * // or {high:150, mid: 140, low: 110}, 120\n\t\t\t * [150, 140, 110], 120\n\t\t\t * ],\n\t\t\t * [[155, 130, 115], 55],\n\t\t\t * [[160, 135, 120], 60]\n\t\t\t * ],\n\t\t\t * types: {\n\t\t\t * data1: \"area-line-range\",\n\t\t\t * data2: \"line\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t *\n\t\t\t * // for 'bubble' type, data can contain dimension value:\n\t\t\t * // - an array of [y, z] data following the order\n\t\t\t * // - or an object with 'y' and 'z' key value\n\t\t\t * // 'y' is for y axis coordination and 'z' is the bubble radius value\n\t\t\t * data: {\n\t\t\t * rows: [\n\t\t\t * [\"data1\", \"data2\"],\n\t\t\t * [\n\t\t\t * // or {y:10, z: 140}, 120\n\t\t\t * [10, 140], 120\n\t\t\t * ],\n\t\t\t * [[100, 30], 55],\n\t\t\t * [[50, 100], 60]\n\t\t\t * ],\n\t\t\t * types: {\n\t\t\t * data1: \"bubble\",\n\t\t\t * data2: \"line\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_rows: undefined,\n\n\t\t\t/**\n\t\t\t * Load data from a multidimensional array, with each element containing an array consisting of a datum name and associated data values.\n\t\t\t * @name data․columns\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.ColumnOrientedData)\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * columns: [\n\t\t\t * [\"data1\", 30, 20, 50, 40, 60, 50],\n\t\t\t * [\"data2\", 200, 130, 90, 240, 130, 220],\n\t\t\t * [\"data3\", 300, 200, 160, 400, 250, 250]\n\t\t\t * ]\n\t\t\t * }\n\t\t\t *\n\t\t\t * // for 'range' types('area-line-range' or 'area-spline-range'), data should contain:\n\t\t\t * // - an array of [high, mid, low] data following the order\n\t\t\t * // - or an object with 'high', 'mid' and 'low' key value\n\t\t\t * data: {\n\t\t\t * columns: [\n\t\t\t * [\"data1\",\n\t\t\t * [150, 140, 110], // or {high:150, mid: 140, low: 110}\n\t\t\t * [150, 140, 110],\n\t\t\t * [150, 140, 110]\n\t\t\t * ]\n\t\t\t * ],\n\t\t\t * type: \"area-line-range\"\n\t\t\t * }\n\t\t\t *\n\t\t\t * // for 'bubble' type, data can contain dimension value:\n\t\t\t * // - an array of [y, z] data following the order\n\t\t\t * // - or an object with 'y' and 'z' key value\n\t\t\t * // 'y' is for y axis coordination and 'z' is the bubble radius value\n\t\t\t * data: {\n\t\t\t * columns: [\n\t\t\t * [\"data1\",\n\t\t\t * [10, 140], // or {y:10, z: 140}\n\t\t\t * [100, 30],\n\t\t\t * [50, 100]\n\t\t\t * ]\n\t\t\t * ],\n\t\t\t * type: \"bubble\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_columns: undefined,\n\n\t\t\t/**\n\t\t\t * Used if loading JSON via data.url.\n\t\t\t * - **Available Values:**\n\t\t\t * - json\n\t\t\t * - csv\n\t\t\t * - tsv\n\t\t\t * @name data․mimeType\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default csv\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * mimeType: \"json\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_mimeType: \"csv\",\n\n\t\t\t/**\n\t\t\t * Choose which JSON object keys correspond to desired data.\n\t\t\t * - **NOTE:** Only for JSON object given as array.\n\t\t\t * @name data․keys\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * json: [\n\t\t\t * {name: \"www.site1.com\", upload: 200, download: 200, total: 400},\n\t\t\t * {name: \"www.site2.com\", upload: 100, download: 300, total: 400},\n\t\t\t * {name: \"www.site3.com\", upload: 300, download: 200, total: 500},\n\t\t\t * {name: \"www.site4.com\", upload: 400, download: 100, total: 500}\n\t\t\t * ],\n\t\t\t * keys: {\n\t\t\t * // x: \"name\", // it's possible to specify 'x' when category axis\n\t\t\t * value: [\"upload\", \"download\"]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_keys: undefined,\n\n\t\t\t/**\n\t\t\t * Set text label to be displayed when there's no data to show.\n\t\t\t * - ex. Toggling all visible data to not be shown, unloading all current data, etc.\n\t\t\t * @name data․empty․label․text\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default \"\"\n\t\t\t * @example\n\t\t\t * data: {\n\t\t\t * empty: {\n\t\t\t * label: {\n\t\t\t * text: \"No Data\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tdata_empty_label_text: \"\",\n\n\t\t\t/**\n\t\t\t * Set subchart options\n\t\t\t * @name subchart\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [subchart.show=false] Show sub chart on the bottom of the chart.\n\t\t\t * @property {Boolean} [subchart.axis.x.show=true] Show or hide x axis.\n\t\t\t * @property {Boolean} [subchart.axis.x.tick.show=true] Show or hide x axis tick line.\n\t\t\t * @property {Boolean} [subchart.axis.x.tick.text.show=true] Show or hide x axis tick text.\n\t\t\t * @property {Number} [subchart.size.height] Change the height of the subchart.\n\t\t\t * @property {Function} [subchart.onbrush] Set callback for brush event.<br>\n\t\t\t * Specified function receives the current zoomed x domain.\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Interaction.SubChart)\n\t\t\t * @example\n\t\t\t * subchart: {\n\t\t\t * axis: {\n\t\t\t * \tx: {\n\t\t\t * \t show: true,\n\t\t\t * \t tick: {\n\t\t\t * \t show: true,\n\t\t\t * \t text: {\n\t\t\t * \t show: false\n\t\t\t * \t }\n\t\t\t * \t }\n\t\t\t * \t}\n\t\t\t * },\n\t\t\t * show: true,\n\t\t\t * size: {\n\t\t\t * height: 20\n\t\t\t * },\n\t\t\t * onbrush: function(domain) { ... }\n\t\t\t * }\n\t\t\t */\n\t\t\tsubchart_show: false,\n\t\t\tsubchart_size_height: 60,\n\t\t\tsubchart_axis_x_show: true,\n\t\t\tsubchart_axis_x_tick_show: true,\n\t\t\tsubchart_axis_x_tick_text_show: true,\n\t\t\tsubchart_onbrush: () => {},\n\n\t\t\t/**\n\t\t\t * Set color of the data values\n\t\t\t * @name color\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {String|Object|Function} [color.onover] Set the color value for each data point when mouse/touch onover event occurs.\n\t\t\t * @property {Array} [color.pattern=[]] custom color pattern\n\t\t\t * @property {Function} [color.tiles] if defined, allows use svg's patterns to fill data area. It should return an array of [SVGPatternElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGPatternElement).\n\t\t\t * - **NOTE:** The pattern element's id will be defined as `bb-colorize-pattern-$COLOR-VALUE`.<br>\n\t\t\t * ex. When color pattern value is `['red', '#fff']` and defined 2 patterns,then ids for pattern elements are:<br>\n\t\t\t * - `bb-colorize-pattern-red`\n\t\t\t * - `bb-colorize-pattern-fff`\n\t\t\t * @property {Object} [color.threshold] color threshold for gauge and tooltip color\n\t\t\t * @property {String} [color.threshold.unit] If set to `value`, the threshold will be based on the data value. Otherwise it'll be based on equation of the `threshold.max` option value.\n\t\t\t * @property {Array} [color.threshold.values] Threshold values for each steps\n\t\t\t * @property {Number} [color.threshold.max=100] The base value to determine threshold step value condition. When the given value is 15 and max 10, then the value for threshold is `15*100/10`.\n\t\t\t * @example\n\t\t\t * color: {\n\t\t\t * pattern: [\"#1f77b4\", \"#aec7e8\", ...],\n\t\t\t *\n\t\t\t * // Set colors' patterns\n\t\t\t * // it should return an array of SVGPatternElement\n\t\t\t * tiles: function() {\n\t\t\t * var pattern = document.createElementNS(\"http://www.w3.org/2000/svg\", \"pattern\");\n\t\t\t * var g = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n\t\t\t * var circle1 = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n\t\t\t *\n\t\t\t * pattern.setAttribute(\"patternUnits\", \"userSpaceOnUse\");\n\t\t\t * pattern.setAttribute(\"width\", \"32\");\n\t\t\t * pattern.setAttribute(\"height\", \"32\");\n\t\t\t *\n\t\t\t * g.style.fill = \"#000\";\n\t\t\t * g.style.opacity = \"0.2\";\n *\n\t\t\t * circle1.setAttribute(\"cx\", \"3\");\n\t\t\t * circle1.setAttribute(\"cy\", \"3\");\n\t\t\t * circle1.setAttribute(\"r\", \"3\");\n *\n\t\t\t * g.appendChild(circle1);\n\t\t\t * pattern.appendChild(g);\n\t\t\t *\n\t\t\t * return [pattern];\n\t\t\t * },\n\t\t\t *\n\t\t\t * // for threshold usage, pattern values should be set for each steps\n\t\t\t * pattern: [\"grey\", \"green\", \"yellow\", \"orange\", \"red\"],\n\t\t\t * threshold: {\n\t\t\t * unit: \"value\",\n\t\t\t *\n\t\t\t * // when value is 20 => 'green', value is 40 => 'orange' will be set.\n\t\t\t * values: [10, 20, 30, 40, 50],\n\t\t\t *\n\t\t\t * // the equation for max:\n\t\t\t * // - unit == 'value': max => 30\n\t\t\t * // - unit != 'value': max => value*100/30\n\t\t\t * max: 30\n\t\t\t * },\n\t\t\t *\n\t\t\t * // set all data to 'red'\n\t\t\t * onover: \"red\",\n\t\t\t *\n\t\t\t * // set different color for data\n\t\t\t * onover: {\n\t\t\t * data1: \"red\",\n\t\t\t * data2: \"yellow\"\n\t\t\t * },\n\t\t\t *\n\t\t\t * // will pass data object to the callback\n\t\t\t * onover: function(d) {\n\t\t\t * return d.id === \"data1\" ? \"red\" : \"green\";\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tcolor_pattern: [],\n\t\t\tcolor_tiles: undefined,\n\t\t\tcolor_threshold: {},\n\t\t\tcolor_onover: undefined,\n\n\t\t\t/**\n\t\t\t * Legend options\n\t\t\t * @name legend\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [legend.show=true] Show or hide legend.\n\t\t\t * @property {Boolean} [legend.hide=false] Hide legend\n\t\t\t * If true given, all legend will be hidden. If string or array given, only the legend that has the id will be hidden.\n\t\t\t * @property {String|HTMLElement} [legend.contents.bindto=undefined] Set CSS selector or element reference to bind legend items.\n\t\t\t * @property {String|Function} [legend.contents.template=undefined] Set item's template.<br>\n\t\t\t * - If set `string` value, within template the 'color' and 'title' can be replaced using template-like syntax string:\n\t\t\t * - {=COLOR}: data color value\n\t\t\t * - {=TITLE}: data title value\n\t\t\t * - If set `function` value, will pass following arguments to the given function:\n\t\t\t * - title {String}: data's id value\n\t\t\t * - color {String}: color string\n\t\t\t * - data {Array}: data array\n\t\t\t * @property {String} [legend.position=bottom] Change the position of legend.<br>\n\t\t\t * Available values are: `bottom`, `right` and `inset` are supported.\n\t\t\t * @property {Object} [legend.inset={anchor: 'top-left',x: 10,y: 0,step: undefined}] Change inset legend attributes.<br>\n\t\t\t * This option accepts object that has the keys `anchor`, `x`, `y` and `step`.\n\t\t\t * - **anchor** decides the position of the legend:\n\t\t\t * - top-left\n\t\t\t * - top-right\n\t\t\t * - bottom-left\n\t\t\t * - bottom-right\n\t\t\t * - **x** and **y**:\n\t\t\t * - set the position of the legend based on the anchor.\n\t\t\t * - **step**:\n\t\t\t * - defines the max step the legend has (e.g. If 2 set and legend has 3 legend item, the legend 2 columns).\n\t\t\t * @property {Boolean} [legend.equally=false] Set to all items have same width size.\n\t\t\t * @property {Boolean} [legend.padding=0] Set padding value\n\t\t\t * @property {Function} [legend.item.onclick=undefined] Set click event handler to the legend item.\n\t\t\t * @property {Function} [legend.item.onover=undefined] Set mouse/touch over event handler to the legend item.\n\t\t\t * @property {Function} [legend.item.onout=undefined] Set mouse/touch out event handler to the legend item.\n\t\t\t * @property {Number} [legend.item.tile.width=10] Set width of item tile element\n\t\t\t * @property {Number} [legend.item.tile.height=10] Set height of item tile element\n\t\t\t * @property {Boolean} [legend.usePoint=false] Whether to use custom points in legend.\n\t\t\t * @see [Demo: position](https://naver.github.io/billboard.js/demo/#Legend.LegendPosition)\n\t\t\t * @see [Demo: contents.template](https://naver.github.io/billboard.js/demo/#Legend.LegendTemplate1)\n\t\t\t * @see [Demo: usePoint](https://naver.github.io/billboard.js/demo/#Legend.usePoint)\n\t\t\t * @example\n\t\t\t * legend: {\n\t\t\t * show: true,\n\t\t\t * hide: true,\n\t\t\t * //or hide: \"data1\"\n * //or hide: [\"data1\", \"data2\"]\n\t\t\t * contents: {\n\t\t\t * bindto: \"#legend\", // <ul id='legend'></ul>\n\t\t\t *\n\t\t\t * // will be as: <li style='background-color:#1f77b4'>data1</li>\n\t\t\t * template: \"<li style='background-color:{=COLOR}'>{=TITLE}</li>\"\n\t\t\t *\n\t\t\t * // or using function\n\t\t\t * template: function(id, color, data) {\n\t\t\t * // if you want omit some legend, return falsy value\n\t\t\t * if (title !== \"data1\") {\n\t\t\t * return \"<li style='background-color:\"+ color +\">\"+ title +\"</li>\";\n\t\t\t * }\n\t\t\t * }\n\t\t\t * },\n * position: \"bottom\", // bottom, right, inset\n\t\t\t * inset: {\n\t\t\t * anchor: \"top-right\" // top-left, top-right, bottom-left, bottom-right\n\t\t\t * x: 20,\n\t\t\t * y: 10,\n\t\t\t * step: 2\n\t\t\t * },\n * equally: false,\n * padding: 10,\n * item: {\n\t\t\t * onclick: function(id) { ... },\n\t\t\t * onover: function(id) { ... },\n\t\t\t * onout: function(id) { ... },\n\t\t\t *\n\t\t\t * // set tile's size\n\t\t\t * tile: {\n\t\t\t * width: 20,\n\t\t\t * height: 15\n\t\t\t * }\n\t\t\t * },\n\t\t\t * usePoint: true\n\t\t\t * }\n\t\t\t */\n\t\t\tlegend_show: true,\n\t\t\tlegend_hide: false,\n\t\t\tlegend_contents_bindto: undefined,\n\t\t\tlegend_contents_template: undefined,\n\t\t\tlegend_position: \"bottom\",\n\t\t\tlegend_inset_anchor: \"top-left\",\n\t\t\tlegend_inset_x: 10,\n\t\t\tlegend_inset_y: 0,\n\t\t\tlegend_inset_step: undefined,\n\t\t\tlegend_item_onclick: undefined,\n\t\t\tlegend_item_onover: undefined,\n\t\t\tlegend_item_onout: undefined,\n\t\t\tlegend_equally: false,\n\t\t\tlegend_padding: 0,\n\t\t\tlegend_item_tile_width: 10,\n\t\t\tlegend_item_tile_height: 10,\n\t\t\tlegend_usePoint: false,\n\n\t\t\t/**\n\t\t\t * Switch x and y axis position.\n\t\t\t * @name axis․rotated\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * rotated: true\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_rotated: false,\n\n\t\t\t/**\n\t\t\t * Set clip-path attribute for x axis element\n\t\t\t * @name axis․x․clipPath\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo]()\n\t\t\t * @example\n\t\t\t * // don't set 'clip-path' attribute\n\t\t\t * clipPath: false\n\t\t\t */\n\t\t\taxis_x_clipPath: true,\n\n\t\t\t/**\n\t\t\t * Show or hide x axis.\n\t\t\t * @name axis․x․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_show: true,\n\n\t\t\t/**\n\t\t\t * Set type of x axis.<br><br>\n\t\t\t * **Available Values:**\n\t\t\t * - timeseries\n\t\t\t * - category\n\t\t\t * - indexed\n\t\t\t * @name axis․x․type\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default indexed\n\t\t\t * @see [Demo: indexed](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)\n\t\t\t * @see [Demo: timeseries](https://naver.github.io/billboard.js/demo/#Chart.TimeseriesChart)\n\t\t\t * @see [Demo: category](https://naver.github.io/billboard.js/demo/#Data.CategoryData)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * type: \"timeseries\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_type: \"indexed\",\n\n\t\t\t/**\n\t\t\t * Set how to treat the timezone of x values.<br>\n\t\t\t * If true, treat x value as localtime. If false, convert to UTC internally.\n\t\t\t * @name axis․x․localtime\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * localtime: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_localtime: true,\n\n\t\t\t/**\n\t\t\t * Set category names on category axis.\n\t\t\t * This must be an array that includes category names in string. If category names are included in the date by data.x option, this is not required.\n\t\t\t * @name axis․x․categories\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default []\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * categories: [\"Category 1\", \"Category 2\", ...]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_categories: [],\n\n\t\t\t/**\n\t\t\t * centerize ticks on category axis.\n\t\t\t * @name axis․x․tick․centered\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * centered: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_centered: false,\n\n\t\t\t/**\n\t\t\t * A function to format tick value. Format string is also available for timeseries data.\n\t\t\t * @name axis․x․tick․format\n\t\t\t * @memberof Options\n\t\t\t * @type {Function|String}\n\t\t\t * @default undefined\n\t\t\t * @see [D3's time specifier](https://github.com/d3/d3-time-format#locale_format)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * // for timeseries, a 'datetime' object is given as parameter\n\t\t\t * format: function(x) {\n\t\t\t * return x.getFullYear();\n\t\t\t * }\n\t\t\t *\n\t\t\t * // for category, index(Number) and categoryName(String) are given as parameter\n\t\t\t * format: function(index, categoryName) {\n\t\t\t * return categoryName.substr(0, 10);\n\t\t\t * },\n\t\t\t *\n\t\t\t * // for timeseries format specifier\n\t\t\t * format: \"%Y-%m-%d %H:%M:%S\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_format: undefined,\n\n\t\t\t/**\n\t\t\t * Setting for culling ticks.<br><br>\n\t\t\t * If true is set, the ticks will be culled, then only limitted tick text will be shown. This option does not hide the tick lines. If false is set, all of ticks will be shown.<br><br>\n\t\t\t * We can change the number of ticks to be shown by axis.x.tick.culling.max.\n\t\t\t * @name axis․x․tick․culling\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default\n\t\t\t * - true for indexed axis and timeseries axis\n\t\t\t * - false for category axis\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * culling: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_culling: {},\n\n\t\t\t/**\n\t\t\t * The number of tick texts will be adjusted to less than this value.\n\t\t\t * @name axis․x․tick․culling․max\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 10\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * culling: {\n\t\t\t * max: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_culling_max: 10,\n\n\t\t\t/**\n\t\t\t * The number of x axis ticks to show.<br><br>\n\t\t\t * This option hides tick lines together with tick text. If this option is used on timeseries axis, the ticks position will be determined precisely and not nicely positioned (e.g. it will have rough second value).\n\t\t\t * @name axis․x․tick․count\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * count: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_count: undefined,\n\n\t\t\t/**\n\t\t\t * Show or hide x axis tick line.\n\t\t\t * @name axis․x․tick․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_show: true,\n\n\t\t\t/**\n\t\t\t * Show or hide x axis tick text.\n\t\t\t * @name axis․x․tick․text․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * text: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_text_show: true,\n\n\t\t\t/**\n\t\t\t * Set the x Axis tick text's position relatively its original position\n\t\t\t * @name axis․x․tick․text․position\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {x: 0, y:0}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * text: {\n\t\t\t * position: {\n\t\t\t * x: 10,\n\t\t\t * y: 10\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_text_position: {x: 0, y: 0},\n\n\t\t\t/**\n\t\t\t * Fit x axis ticks.\n\t\t\t * - **true**: ticks will be positioned nicely to have same intervals.\n\t\t\t * - **false**: ticks will be positioned according to x value of the data points.\n\t\t\t * @name axis․x․tick․fit\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickFitting)\n\t\t\t * @see [Demo: for timeseries zoom](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickTimeseries)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * fit: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_fit: true,\n\n\t\t\t/**\n\t\t\t * Set the x values of ticks manually.<br><br>\n\t\t\t * If this option is provided, the position of the ticks will be determined based on those values.<br>\n\t\t\t * This option works with `timeseries` data and the x values will be parsed accoding to the type of the value and data.xFormat option.\n\t\t\t * @name axis․x․tick․values\n\t\t\t * @memberof Options\n\t\t\t * @type {Array|Function}\n\t\t\t * @default null\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * values: [1, 2, 4, 8, 16, 32, ...],\n\t\t\t *\n\t\t\t * // an Array value should be returned\n\t\t\t * values: function() {\n\t\t\t * \treturn [ ... ];\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_values: null,\n\n\t\t\t/**\n\t\t\t * Rotate x axis tick text if there is not enough space for 'category' and 'timeseries' type axis.\n\t\t\t * - **NOTE:** The conditions where `autorotate` is enabled are:\n\t\t\t * - axis.x.type='category' or 'timeseries\n\t\t\t * - axis.x.tick.multiline=false\n\t\t\t * - axis.x.tick.culling=false\n\t\t\t * - axis.x.tick.fit=true\n\t\t\t * @name axis․x․tick․autorotate\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickAutorotate)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * rotate: 15,\n\t\t\t * autorotate: true,\n\t\t\t * multiline: false,\n\t\t\t * culling: false,\n\t\t\t * fit: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_autorotate: false,\n\n\t\t\t/**\n\t\t\t * Rotate x axis tick text.\n\t\t\t * - If you set negative value, it will rotate to opposite direction.\n\t\t\t * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `false`.\n\t\t\t * - As long as `axis_x_tick_fit` is set to `true` it will calculate an overflow for the y2 axis and add this value to the right padding.\n\t\t\t * @name axis․x․tick․rotate\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 0\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.RotateXAxisTickText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * rotate: 60\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_rotate: 0,\n\n\t\t\t/**\n\t\t\t * Show x axis outer tick.\n\t\t\t * @name axis․x․tick․outer\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * outer: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_outer: true,\n\n\t\t\t/**\n\t\t\t * Set tick text to be multiline\n\t\t\t * - **NOTE:**\n\t\t\t * > When x tick text contains `\\n`, it's used as line break and 'axis.x.tick.width' option is ignored.\n\t\t\t * @name axis․x․tick․multiline\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.XAxisTickMultiline)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * multiline: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * @example\n\t\t\t * // example of line break with '\\n'\n\t\t\t * // In this case, 'axis.x.tick.width' is ignored\n\t\t\t * data: {\n\t\t\t * x: \"x\",\n\t\t\t * columns: [\n\t\t\t * [\"x\", \"long\\ntext\", \"Another\\nLong\\nText\"],\n\t\t\t * ...\n\t\t\t * ],\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_multiline: true,\n\n\n\t\t\t/**\n\t\t\t * Set tick width\n\t\t\t * - **NOTE:**\n\t\t\t * > When x tick text contains `\\n`, this option is ignored.\n\t\t\t * @name axis․x․tick․width\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default null\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * width: 50\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_width: null,\n\n\t\t\t/**\n\t\t\t * Set to display system tooltip(via 'title' attribute) for tick text\n\t\t\t * - **NOTE:** Only available for category axis type (`axis.x.type='category'`)\n\t\t\t * @name axis․x․tick․tooltip\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * tick: {\n\t\t\t * tooltip: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_tick_tooltip: false,\n\n\t\t\t/**\n\t\t\t * Set max value of x axis range.\n\t\t\t * @name axis․x․max\n\t\t\t * @memberof Options\n\t\t\t * @property {Number} max Set the max value\n\t\t\t * @property {Boolean} [max.fit=false] When specified `max.value` is greater than the bound data value, setting `true` will make x axis max to be fitted to the bound data max value.\n\t\t\t * - **NOTE:** If the bound data max value is greater than the `max.value`, the x axis max will be limited as the given `max.value`.\n\t\t\t * @property {Number} [max.value] Set the max value\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * max: 100,\n\t\t\t *\n\t\t\t * max: {\n\t\t\t * // 'fit=true' will make x axis max to be limited as the bound data value max when 'max.value' is greater.\n\t\t\t * // - when bound data max is '10' and max.value: '100' ==> x axis max will be '10'\n\t\t\t * // - when bound data max is '1000' and max.value: '100' ==> x axis max will be '100'\n\t\t\t * fit: true,\n\t\t\t * value: 100\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_max: undefined,\n\n\t\t\t/**\n\t\t\t * Set min value of x axis range.\n\t\t\t * @name axis․x․min\n\t\t\t * @memberof Options\n\t\t\t * @property {Number} min Set the min value\n\t\t\t * @property {Boolean} [min.fit=false] When specified `min.value` is lower than the bound data value, setting `true` will make x axis min to be fitted to the bound data min value.\n\t\t\t * - **NOTE:** If the bound data min value is lower than the `min.value`, the x axis min will be limited as the given `min.value`.\n\t\t\t * @property {Number} [min.value] Set the min value\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * min: -100,\n\t\t\t *\n\t\t\t * min: {\n\t\t\t * // 'fit=true' will make x axis min to be limited as the bound data value min when 'min.value' is lower.\n\t\t\t * // - when bound data min is '-10' and min.value: '-100' ==> x axis min will be '-10'\n\t\t\t * // - when bound data min is '-1000' and min.value: '-100' ==> x axis min will be '-100'\n\t\t\t * fit: true,\n\t\t\t * value: -100\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_min: undefined,\n\n\t\t\t/**\n\t\t\t * Set padding for x axis.<br><br>\n\t\t\t * If this option is set, the range of x axis will increase/decrease according to the values.\n\t\t\t * If no padding is needed in the rage of x axis, 0 should be set.\n\t\t\t * - **NOTE:**\n\t\t\t * The padding values aren't based on pixels. It differs according axis types<br>\n\t\t\t * - **category:** The unit of tick value\n\t\t\t * ex. the given value `1`, is same as the width of 1 tick width\n\t\t\t * - **timeseries:** Numeric time value\n\t\t\t * ex. the given value `1000*60*60*24`, which is numeric time equivalent of a day, is same as the width of 1 tick width\n\t\t\t * @name axis․x․padding\n\t\t\t * @memberof Options\n\t\t\t * @type {Object|Number}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * padding: {\n\t\t\t * // when axis type is 'category'\n\t\t\t * left: 1, // set left padding width of equivalent value of a tick's width\n\t\t\t * right: 0.5 // set right padding width as half of equivalent value of tick's width\n\t\t\t *\n\t\t\t * // when axis type is 'timeseries'\n\t\t\t * left: 1000*60*60*24, // set left padding width of equivalent value of a day tick's width\n\t\t\t * right: 1000*60*60*12 // set right padding width as half of equivalent value of a day tick's width\n\t\t\t * },\n\t\t\t *\n\t\t\t * // or set both values at once.\n\t\t\t * padding: 10\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_padding: {},\n\n\t\t\t/**\n\t\t\t * Set height of x axis.<br><br>\n\t\t\t * The height of x axis can be set manually by this option. If you need more space for x axis, please use this option for that. The unit is pixel.\n\t\t\t * @name axis․x․height\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * height: 20\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_height: undefined,\n\n\t\t\t/**\n\t\t\t * Set default extent for subchart and zoom. This can be an array or function that returns an array.\n\t\t\t * @name axis․x․extent\n\t\t\t * @memberof Options\n\t\t\t * @type {Array|Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * // extent range as a pixel value\n\t\t\t * extent: [0, 200],\n\t\t\t *\n\t\t\t * // when axis is 'timeseries', parsable datetime string\n\t\t\t * extent: [\"2019-03-01\", \"2019-03-05\"],\n\t\t\t *\n\t\t\t * // return extent value\n\t\t\t * extent: function(domain, scale) {\n\t\t\t * \t var extent = domain.map(function(v) {\n\t\t\t * \t return scale(v);\n\t\t\t * \t });\n\t\t\t *\n\t\t\t * \t // it should return a format of array\n\t\t\t * \t // ex) [0, 584]\n\t\t\t * \t return extent;\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_extent: undefined,\n\n\t\t\t/**\n\t\t\t * Set label on x axis.<br><br>\n\t\t\t * You can set x axis label and change its position by this option.\n\t\t\t * `string` and `object` can be passed and we can change the poisiton by passing object that has position key.<br>\n\t\t\t * Available position differs according to the axis direction (vertical or horizontal).\n\t\t\t * If string set, the position will be the default.\n\t\t\t *\n\t\t\t * - **If it's horizontal axis:**\n\t\t\t * - inner-right [default]\n\t\t\t * - inner-center\n\t\t\t * - inner-left\n\t\t\t * - outer-right\n\t\t\t * - outer-center\n\t\t\t * - outer-left\n\t\t\t * - **If it's vertical axis:**\n\t\t\t * - inner-top [default]\n\t\t\t * - inner-middle\n\t\t\t * - inner-bottom\n\t\t\t * - outer-top\n\t\t\t * - outer-middle\n\t\t\t * - outer-bottom\n\t\t\t * @name axis․x․label\n\t\t\t * @memberof Options\n\t\t\t * @type {String|Object}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * label: \"Your X Axis\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t *\n\t\t\t * axis: {\n\t\t\t * x: {\n\t\t\t * label: {\n\t\t\t * text: \"Your X Axis\",\n\t\t\t * position: \"outer-center\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_label: {},\n\n\t\t\t/**\n\t\t\t * Set additional axes for x Axis.\n\t\t\t * - **NOTE:** Axis' scale is based on x Axis value if domain option isn't set.\n\t\t\t *\n\t\t\t * Each axis object should consist with following options:\n\t\t\t *\n\t\t\t * | Name | Type | Default | Description |\n\t\t\t * | --- | --- | --- | --- |\n\t\t\t * | domain | Array | - | Set the domain value |\n\t\t\t * | tick.outer | Boolean | true | Show outer tick |\n\t\t\t * | tick.format | Function | - | Set formatter for tick text |\n\t\t\t * | tick.count | Number | - | Set the number of y axis ticks |\n\t\t\t * | tick.values | Array | - | Set tick values manually |\n\t\t\t * @name axis․x․axes\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)\n\t\t\t * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)\n\t\t\t * @example\n\t\t\t * x: {\n\t\t\t * axes: [\n\t\t\t * {\n\t\t\t * // if set, will not be correlated with the main x Axis domain value\n \t\t\t * domain: [0, 1000],\n\t\t\t * tick: {\n\t\t\t * outer: false,\n\t\t\t * format: function(x) {\n\t\t\t * return x + \"%\";\n\t\t\t * },\n\t\t\t * count: 2,\n\t\t\t * values: [10, 20, 30]\n\t\t\t * }\n\t\t\t * },\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_x_axes: [],\n\n\t\t\t/**\n\t\t\t * Set clip-path attribute for y axis element\n\t\t\t * - **NOTE**: `clip-path` attribute for y Axis is set only when `axis.y.inner` option is true.\n\t\t\t * @name axis․y․clipPath\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * // don't set 'clip-path' attribute\n\t\t\t * clipPath: false\n\t\t\t */\n\t\t\taxis_y_clipPath: true,\n\n\t\t\t/**\n\t\t\t * Show or hide y axis.\n\t\t\t * @name axis․y․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_show: true,\n\n\t\t\t/**\n\t\t\t * Set type of y axis.<br><br>\n\t\t\t * **Available Values:**\n\t\t\t * - timeseries\n\t\t\t * - category\n\t\t\t * - indexed\n\t\t\t * @name axis․y․type\n\t\t\t * @memberof Options\n\t\t\t * @type {String}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * type: \"timeseries\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_type: undefined,\n\n\t\t\t/**\n\t\t\t * Set max value of y axis.\n\t\t\t * - **NOTE:** Padding will be added based on this value, so if you don't need the padding, please set axis.y.padding to disable it (e.g. axis.y.padding = 0).\n\t\t\t * @name axis․y․max\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * max: 1000\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_max: undefined,\n\n\t\t\t/**\n\t\t\t * Set min value of y axis.\n\t\t\t * - **NOTE:**\n\t\t\t * Padding will be added based on this value, so if you don't need the padding, please set axis.y.padding to disable it (e.g. axis.y.padding = 0).\n\t\t\t * @name axis․y․min\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * min: 1000\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_min: undefined,\n\n\t\t\t/**\n\t\t\t * Change the direction of y axis.<br><br>\n\t\t\t * If true set, the direction will be from the top to the bottom.\n\t\t\t * @name axis․y․inverted\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * inverted: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_inverted: false,\n\n\t\t\t/**\n\t\t\t * Set center value of y axis.\n\t\t\t * @name axis․y․center\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * center: 0\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_center: undefined,\n\n\t\t\t/**\n\t\t\t * Show y axis inside of the chart.\n\t\t\t * @name axis․y․inner\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * inner: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_inner: false,\n\n\t\t\t/**\n\t\t\t * Set label on y axis.<br><br>\n\t\t\t * You can set y axis label and change its position by this option. This option works in the same way as [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label).\n\t\t\t * @name axis․y․label\n\t\t\t * @memberof Options\n\t\t\t * @type {String|Object}\n\t\t\t * @default {}\n\t\t\t * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * label: \"Your Y Axis\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t *\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * label: {\n\t\t\t * text: \"Your Y Axis\",\n\t\t\t * position: \"outer-middle\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_label: {},\n\n\t\t\t/**\n\t\t\t * Set formatter for y axis tick text.<br><br>\n\t\t\t * This option accepts d3.format object as well as a function you define.\n\t\t\t * @name axis․y․tick․format\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * format: function(x) {\n\t\t\t * return x.getFullYear();\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_format: undefined,\n\n\t\t\t/**\n\t\t\t * Setting for culling ticks.<br><br>\n\t\t\t * If true is set, the ticks will be culled, then only limitted tick text will be shown. This option does not hide the tick lines. If false is set, all of ticks will be shown.<br><br>\n\t\t\t * We can change the number of ticks to be shown by axis.y.tick.culling.max.\n\t\t\t * @name axis․y․tick․culling\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * culling: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_culling: false,\n\n\t\t\t/**\n\t\t\t * The number of tick texts will be adjusted to less than this value.\n\t\t\t * @name axis․y․tick․culling․max\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 5\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * culling: {\n\t\t\t * max: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_culling_max: 5,\n\n\t\t\t/**\n\t\t\t * Show y axis outer tick.\n\t\t\t * @name axis․y․tick․outer\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * outer: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_outer: true,\n\n\t\t\t/**\n\t\t\t * Set y axis tick values manually.\n\t\t\t * @name axis․y․tick․values\n\t\t\t * @memberof Options\n\t\t\t * @type {Array|Function}\n\t\t\t * @default null\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * values: [100, 1000, 10000],\n\t\t\t *\n\t\t\t * // an Array value should be returned\n\t\t\t * values: function() {\n\t\t\t * \treturn [ ... ];\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_values: null,\n\n\t\t\t/**\n\t\t\t * Rotate y axis tick text.\n\t\t\t * - If you set negative value, it will rotate to opposite direction.\n\t\t\t * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.\n\t\t\t * @name axis․y․tick․rotate\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 0\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * rotate: 60\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_rotate: 0,\n\n\t\t\t/**\n\t\t\t * Set the number of y axis ticks.<br><br>\n\t\t\t * - **NOTE:** The position of the ticks will be calculated precisely, so the values on the ticks will not be rounded nicely. In the case, axis.y.tick.format or axis.y.tick.values will be helpful.\n\t\t\t * @name axis․y․tick․count\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * count: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_count: undefined,\n\n\t\t\t/**\n\t\t\t * Show or hide y axis tick line.\n\t\t\t * @name axis․y․tick․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_show: true,\n\n\t\t\t/**\n\t\t\t * Set axis tick step(interval) size.\n\t\t\t * - **NOTE:** Will be ignored if `axis.y.tick.count` or `axis.y.tick.values` options are set.\n\t\t\t * @name axis․y․tick․stepSize\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * // tick value will step as indicated interval value.\n\t\t\t * // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]\n\t\t\t * stepSize: 15\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_stepSize: null,\n\n\t\t\t/**\n\t\t\t* Show or hide y axis tick text.\n\t\t\t* @name axis․y․tick․text․show\n\t\t\t* @memberof Options\n\t\t\t* @type {Boolean}\n\t\t\t* @default true\n\t\t\t* @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t* @example\n\t\t\t* axis: {\n\t\t\t* y: {\n\t\t\t* tick: {\n\t\t\t* text: {\n\t\t\t* show: false\n\t\t\t* }\n\t\t\t* }\n\t\t\t* }\n\t\t\t* }\n\t\t\t*/\n\t\t\taxis_y_tick_text_show: true,\n\n\t\t\t/**\n\t\t\t * Set the y Axis tick text's position relatively its original position\n\t\t\t * @name axis․y․tick․text․position\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {x: 0, y:0}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * text: {\n\t\t\t * position: {\n\t\t\t * x: 10,\n\t\t\t * y: 10\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_tick_text_position: {x: 0, y: 0},\n\n\t\t\t/**\n\t\t\t * Set the number of y axis ticks.<br><br>\n\t\t\t * - **NOTE:** The position of the ticks will be calculated precisely, so the values on the ticks will not be rounded nicely. In the case, axis.y.tick.format or axis.y.tick.values will be helpful.\n\t\t\t * @name axis․y․tick․time\n\t\t\t * @memberof Options\n\t\t\t * @private\n\t\t\t * @type {Object}\n\t\t\t * @property {Function} [time.value] D3's time interval function (https://github.com/d3/d3-time#intervals)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * tick: {\n\t\t\t * time: {\n\t\t\t * // ticks at 15-minute intervals\n\t\t\t * // https://github.com/d3/d3-scale/blob/master/README.md#time_ticks\n\t\t\t * value: d3.timeMinute.every(15)\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\t// @TODO: not fully implemented yet\n\t\t\taxis_y_tick_time_value: undefined,\n\n\t\t\t/**\n\t\t\t * Set padding for y axis.<br><br>\n\t\t\t * You can set padding for y axis to create more space on the edge of the axis.\n\t\t\t * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.\n\t\t\t *\n\t\t\t * - **NOTE:**\n\t\t\t * - Given values are translated relative to the y Axis domain value for padding\n\t\t\t * - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.\n\t\t\t * @name axis․y․padding\n\t\t\t * @memberof Options\n\t\t\t * @type {Object|Number}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * padding: {\n\t\t\t * top: 0,\n\t\t\t * bottom: 0\n\t\t\t * },\n\t\t\t *\n\t\t\t * // or set both values at once.\n\t\t\t * padding: 10\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_padding: {},\n\n\t\t\t/**\n\t\t\t * Set default range of y axis.<br><br>\n\t\t\t * This option set the default value for y axis when there is no data on init.\n\t\t\t * @name axis․y․default\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y: {\n\t\t\t * default: [0, 1000]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_default: undefined,\n\n\t\t\t/**\n\t\t\t * Set additional axes for y Axis.\n\t\t\t * - **NOTE:** Axis' scale is based on y Axis value if domain option isn't set.\n\t\t\t *\n\t\t\t * Each axis object should consist with following options:\n\t\t\t *\n\t\t\t * | Name | Type | Default | Description |\n\t\t\t * | --- | --- | --- | --- |\n\t\t\t * | domain | Array | - | Set the domain value |\n\t\t\t * | tick.outer | Boolean | true | Show outer tick |\n\t\t\t * | tick.format | Function | - | Set formatter for tick text |\n\t\t\t * | tick.count | Number | - | Set the number of y axis ticks |\n\t\t\t * | tick.values | Array | - | Set tick values manually |\n\t\t\t * @name axis․y․axes\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)\n\t\t\t * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)\n\t\t\t * @example\n\t\t\t * y: {\n\t\t\t * axes: [\n\t\t\t * {\n\t\t\t * // if set, will not be correlated with the main y Axis domain value\n\t\t\t * domain: [0, 1000],\n\t\t\t * tick: {\n\t\t\t * outer: false,\n\t\t\t * format: function(x) {\n\t\t\t * return x + \"%\";\n\t\t\t * },\n\t\t\t * count: 2,\n\t\t\t * values: [10, 20, 30]\n\t\t\t * }\n\t\t\t * },\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y_axes: [],\n\n\t\t\t/**\n\t\t\t * Show or hide y2 axis.\n\t\t\t * - **NOTE**:\n\t\t\t * - When set to `false` will not generate y2 axis node. In this case, all 'y2' axis related functionality won't work properly.\n\t\t\t * - If need to use 'y2' related options while y2 isn't visible, set the value `true` and control visibility by css display property.\n\t\t\t * @name axis․y2․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * show: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_show: false,\n\n\t\t\t/**\n\t\t\t * Set max value of y2 axis.\n\t\t\t * @name axis․y2․max\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * max: 1000\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_max: undefined,\n\n\t\t\t/**\n\t\t\t * Set min value of y2 axis.\n\t\t\t * @name axis․y2․min\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * min: -1000\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_min: undefined,\n\n\t\t\t/**\n\t\t\t * Change the direction of y2 axis.<br><br>\n\t\t\t * If true set, the direction will be from the top to the bottom.\n\t\t\t * @name axis․y2․inverted\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * inverted: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_inverted: false,\n\n\t\t\t/**\n\t\t\t * Set center value of y2 axis.\n\t\t\t * @name axis․y2․center\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * center: 0\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_center: undefined,\n\n\t\t\t/**\n\t\t\t * Show y2 axis inside of the chart.\n\t\t\t * @name axis․y2․inner\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * inner: true\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_inner: false,\n\n\t\t\t/**\n\t\t\t * Set label on y2 axis.<br><br>\n\t\t\t * You can set y2 axis label and change its position by this option. This option works in the same way as [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label).\n\t\t\t * @name axis․y2․label\n\t\t\t * @memberof Options\n\t\t\t * @type {String|Object}\n\t\t\t * @default {}\n\t\t\t * @see [axis.x.label](#.axis%25E2%2580%25A4x%25E2%2580%25A4label) for position string value.\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * label: \"Your Y2 Axis\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t *\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * label: {\n\t\t\t * text: \"Your Y2 Axis\",\n\t\t\t * position: \"outer-middle\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_label: {},\n\n\t\t\t/**\n\t\t\t * Set formatter for y2 axis tick text.<br><br>\n\t\t\t * This option works in the same way as axis.y.format.\n\t\t\t * @name axis․y2․tick․format\n\t\t\t * @memberof Options\n\t\t\t * @type {Function}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * format: d3.format(\"$,\")\n\t\t\t * //or format: function(d) { return \"$\" + d; }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_format: undefined,\n\n\t\t\t/**\n\t\t\t * Setting for culling ticks.<br><br>\n\t\t\t * If true is set, the ticks will be culled, then only limitted tick text will be shown. This option does not hide the tick lines. If false is set, all of ticks will be shown.<br><br>\n\t\t\t * We can change the number of ticks to be shown by axis.y.tick.culling.max.\n\t\t\t * @name axis․y2․tick․culling\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default false\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * culling: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_culling: false,\n\n\t\t\t/**\n\t\t\t * The number of tick texts will be adjusted to less than this value.\n\t\t\t * @name axis․y2․tick․culling․max\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 5\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * culling: {\n\t\t\t * max: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_culling_max: 5,\n\n\t\t\t/**\n\t\t\t * Show or hide y2 axis outer tick.\n\t\t\t * @name axis․y2․tick․outer\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * outer: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_outer: true,\n\n\t\t\t/**\n\t\t\t * Set y2 axis tick values manually.\n\t\t\t * @name axis․y2․tick․values\n\t\t\t * @memberof Options\n\t\t\t * @type {Array|Function}\n\t\t\t * @default null\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * values: [100, 1000, 10000],\n\t\t\t *\n\t\t\t * // an Array value should be returned\n\t\t\t * values: function() {\n\t\t\t * \treturn [ ... ];\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_values: null,\n\n\t\t\t/**\n\t\t\t * Rotate y2 axis tick text.\n\t\t\t * - If you set negative value, it will rotate to opposite direction.\n\t\t\t * - Applied when [`axis.rotated`](#.axis%25E2%2580%25A4rotated) option is `true`.\n\t\t\t * @name axis․y2․tick․rotate\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default 0\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * rotate: 60\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_rotate: 0,\n\n\t\t\t/**\n\t\t\t * Set the number of y2 axis ticks.\n\t\t\t * - **NOTE:** This works in the same way as axis.y.tick.count.\n\t\t\t * @name axis․y2․tick․count\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * count: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_count: undefined,\n\n\t\t\t/**\n\t\t\t * Show or hide y2 axis tick line.\n\t\t\t * @name axis․y2․tick․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_show: true,\n\n\t\t\t/**\n\t\t\t * Set axis tick step(interval) size.\n\t\t\t * - **NOTE:** Will be ignored if `axis.y2.tick.count` or `axis.y2.tick.values` options are set.\n\t\t\t * @name axis․y2․tick․stepSize\n\t\t\t * @memberof Options\n\t\t\t * @type {Number}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.StepSizeForYAxis)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * // tick value will step as indicated interval value.\n\t\t\t * // ex) 'stepSize=15' ==> [0, 15, 30, 45, 60]\n\t\t\t * stepSize: 15\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_stepSize: null,\n\n\t\t\t/**\n\t\t\t * Show or hide y2 axis tick text.\n\t\t\t * @name axis․y2․tick․text․show\n\t\t\t * @memberof Options\n\t\t\t * @type {Boolean}\n\t\t\t * @default true\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.HideTickLineText)\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * text: {\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_text_show: true,\n\n\t\t\t/**\n\t\t\t * Set the y2 Axis tick text's position relatively its original position\n\t\t\t * @name axis․y2․tick․text․position\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @default {x: 0, y:0}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * tick: {\n\t\t\t * text: {\n\t\t\t * position: {\n\t\t\t * x: 10,\n\t\t\t * y: 10\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_tick_text_position: {x: 0, y: 0},\n\n\t\t\t/**\n\t\t\t * Set padding for y2 axis.<br><br>\n\t\t\t * You can set padding for y2 axis to create more space on the edge of the axis.\n\t\t\t * This option accepts object and it can include top and bottom. top, bottom will be treated as pixels.\n\t\t\t *\n\t\t\t * - **NOTE:**\n\t\t\t * - Given values are translated relative to the y2 Axis domain value for padding\n\t\t\t * - For area and bar type charts, [area.zerobased](#.area) or [bar.zerobased](#.bar) options should be set to 'false` to get padded bottom.\n\t\t\t * @name axis․y2․padding\n\t\t\t * @memberof Options\n\t\t\t * @type {Object|Number}\n\t\t\t * @default {}\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * padding: {\n\t\t\t * top: 100,\n\t\t\t * bottom: 100\n\t\t\t * }\n\t\t\t *\n\t\t\t * // or set both values at once.\n\t\t\t * padding: 10\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_padding: {},\n\n\t\t\t/**\n\t\t\t * Set default range of y2 axis.<br><br>\n\t\t\t * This option set the default value for y2 axis when there is no data on init.\n\t\t\t * @name axis․y2․default\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default undefined\n\t\t\t * @example\n\t\t\t * axis: {\n\t\t\t * y2: {\n\t\t\t * default: [0, 1000]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_default: undefined,\n\n\t\t\t/**\n\t\t\t * Set additional axes for y2 Axis.\n\t\t\t * - **NOTE:** Axis' scale is based on y2 Axis value if domain option isn't set.\n\t\t\t *\n\t\t\t * Each axis object should consist with following options:\n\t\t\t *\n\t\t\t * | Name | Type | Default | Description |\n\t\t\t * | --- | --- | --- | --- |\n\t\t\t * | domain | Array | - | Set the domain value |\n\t\t\t * | tick.outer | Boolean | true | Show outer tick |\n\t\t\t * | tick.format | Function | - | Set formatter for tick text |\n\t\t\t * | tick.count | Number | - | Set the number of y axis ticks |\n\t\t\t * | tick.values | Array | - | Set tick values manually |\n\t\t\t * @name axis․y2․axes\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Axis.MultiAxes)\n\t\t\t * @see [Demo: Domain](https://naver.github.io/billboard.js/demo/#Axis.MultiAxesDomain)\n\t\t\t * @example\n\t\t\t * y2: {\n\t\t\t * axes: [\n\t\t\t * {\n\t\t\t * // if set, will not be correlated with the main y2 Axis domain value\n\t\t\t * domain: [0, 1000],\n\t\t\t * tick: {\n\t\t\t * outer: false,\n\t\t\t * format: function(x) {\n\t\t\t * return x + \"%\";\n\t\t\t * },\n\t\t\t * count: 2,\n\t\t\t * values: [10, 20, 30]\n\t\t\t * }\n\t\t\t * },\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t * }\n\t\t\t */\n\t\t\taxis_y2_axes: [],\n\n\t\t\t/**\n\t\t\t * Set related options\n\t\t\t * @name grid\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [front=false] Set 'grid & focus lines' to be positioned over grid lines and chart elements.\n\t\t\t * @property {Boolean} [x.show=false] Show grids along x axis.\n\t\t\t * @property {Array} [x.lines=[]] Show additional grid lines along x axis.<br>\n\t\t\t * This option accepts array including object that has value, text, position and class. text, position and class are optional. For position, start, middle and end (default) are available.\n\t\t\t * If x axis is category axis, value can be category name. If x axis is timeseries axis, value can be date string, Date object and unixtime integer.\n\t\t\t * @property {Boolean} [y.show=false] Show grids along x axis.\n\t\t\t * @property {Array} [y.lines=[]] Show additional grid lines along y axis.<br>\n\t\t\t * This option accepts array including object that has value, text, position and class.\n\t\t\t * @property {Number} [y.ticks=10] Number of y grids to be shown.\n\t\t\t * @property {Boolean} [focus.edge=false] Show edged focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.\n\t\t\t * @property {Boolean} [focus.show=true] Show grid line when focus.\n\t\t\t * @property {Boolean} [focus.y=false] Show y coordinate focus grid line.<br>**NOTE:** Available when [`tooltip.grouped=false`](#.tooltip) option is set.\n\t\t\t * @property {Boolean} [lines.front=true] Set grid lines to be positioned over chart elements.\n\t\t\t * @default undefined\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Grid.GridLines)\n\t\t\t * @see [Demo: X Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalXGridLines)\n\t\t\t * @see [Demo: Y Grid Lines](https://naver.github.io/billboard.js/demo/#Grid.OptionalYGridLines)\n\t\t\t * @example\n\t\t\t * grid: {\n\t\t\t * x: {\n\t\t\t * show: true,\n\t\t\t * lines: [\n\t\t\t * {value: 2, text: \"Label on 2\"},\n\t\t\t * {value: 5, text: \"Label on 5\", class: \"label-5\"},\n\t\t\t * {value: 6, text: \"Label on 6\", position: \"start\"}\n\t\t\t * ]\n\t\t\t * },\n\t\t\t * y: {\n\t\t\t * show: true,\n\t\t\t * lines: [\n\t\t\t * {value: 100, text: \"Label on 100\"},\n\t\t\t * {value: 200, text: \"Label on 200\", class: \"label-200\"},\n\t\t\t * {value: 300, text: \"Label on 300\", position: 'middle'}\n\t\t\t * ],\n\t\t\t * ticks: 5\n\t\t\t * },\n\t\t\t * front: true,\n\t\t\t * focus: {\n\t\t\t * show: false,\n\t\t\t *\n\t\t\t * // Below options are available when 'tooltip.grouped=false' option is set\n\t\t\t * edge: true,\n\t\t\t * y: true\n\t\t\t * },\n\t\t\t * lines: {\n\t\t\t * front: false\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tgrid_x_show: false,\n\t\t\tgrid_x_type: \"tick\",\n\t\t\tgrid_x_lines: [],\n\t\t\tgrid_y_show: false,\n\t\t\tgrid_y_lines: [],\n\t\t\tgrid_y_ticks: 10,\n\t\t\tgrid_focus_edge: false,\n\t\t\tgrid_focus_show: true,\n\t\t\tgrid_focus_y: false,\n\t\t\tgrid_front: false,\n\t\t\tgrid_lines_front: true,\n\n\t\t\t/**\n\t\t\t * Set point options\n\t\t\t * @name point\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [point.show=true] Whether to show each point in line.\n\t\t\t * @property {Number|Function} [point.r=2.5] The radius size of each point.\n\t\t\t * - **NOTE:** Disabled for 'bubble' type\n\t\t\t * @property {Boolean} [point.focus.expand.enabled=true] Whether to expand each point on focus.\n\t\t\t * @property {Number} [point.focus.expand.r=point.r*1.75] The radius size of each point on focus.\n\t\t\t * - **NOTE:** For 'bubble' type, the default is `bubbleSize*1.15`\n\t\t\t * @property {Number} [point.sensitivity=10] The senstivity value for interaction boundary.\n\t\t\t * @property {Number} [point.select.r=point.r*4] The radius size of each point on selected.\n\t\t\t * @property {String} [point.type=\"circle\"] The type of point to be drawn\n\t\t\t * - **NOTE:**\n\t\t\t * - If chart has 'bubble' type, only circle can be used.\n\t\t\t * - For IE, non circle point expansions are not supported due to lack of transform support.\n\t\t\t * - **Available Values:**\n\t\t\t * - circle\n\t\t\t * - rectangle\n\t\t\t * @property {Array} [point.pattern=[]] The type of point or svg shape as string, to be drawn for each line\n\t\t\t * - **NOTE:**\n\t\t\t * - This is an `experimental` feature and can have some unexpected behaviors.\n\t\t\t * - If chart has 'bubble' type, only circle can be used.\n\t\t\t * - For IE, non circle point expansions are not supported due to lack of transform support.\n\t\t\t * - **Available Values:**\n\t\t\t * - circle\n\t\t\t * - rectangle\n\t\t\t * - svg shape tag interpreted as string<br>\n\t\t\t * (ex. `<polygon points='2.5 0 0 5 5 5'></polygon>`)\n\t\t\t * @see [Demo: point type](https://naver.github.io/billboard.js/demo/#Point.RectanglePoints)\n\t\t\t * @example\n\t\t\t * point: {\n\t\t\t * show: false,\n\t\t\t * r: 5,\n\t\t\t *\n\t\t\t * // or customize the radius\n\t\t\t * r: function(d) {\n\t\t\t * ...\n\t\t\t * return r;\n\t\t\t * },\n\t\t\t *\n\t\t\t * focus: {\n\t\t\t * expand: {\n\t\t\t * enabled: true,\n\t\t\t * r: 1\n\t\t\t * }\n\t\t\t * },\n\t\t\t * select: {\n\t\t\t * r: 3\n\t\t\t * },\n\t\t\t *\n\t\t\t * // having lower value, means how closer to be for interaction\n\t\t\t * sensitivity: 3,\n\t\t\t *\n\t\t\t * // valid values are \"circle\" or \"rectangle\"\n\t\t\t * type: \"rectangle\",\n\t\t\t *\n\t\t\t * // or indicate as pattern\n \t\t\t * pattern: [\n \t\t\t * \"circle\",\n \t\t\t * \"rectangle\",\n \t\t\t * \"<polygon points='0 6 4 0 -4 0'></polygon>\"\n \t\t\t * ],\n\t\t\t * }\n\t\t\t */\n\t\t\tpoint_show: true,\n\t\t\tpoint_r: 2.5,\n\t\t\tpoint_sensitivity: 10,\n\t\t\tpoint_focus_expand_enabled: true,\n\t\t\tpoint_focus_expand_r: undefined,\n\t\t\tpoint_pattern: [],\n\t\t\tpoint_select_r: undefined,\n\t\t\tpoint_type: \"circle\",\n\n\t\t\t/**\n\t\t\t * Set line options\n\t\t\t * @name line\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [line.connectNull=false] Set if null data point will be connected or not.<br>\n\t\t\t * If true set, the region of null data will be connected without any data point. If false set, the region of null data will not be connected and get empty.\n\t\t\t * @property {Array} [line.classes=undefined] If set, used to set a css class on each line.\n\t\t\t * @property {Boolean} [line.step.type=step] Change step type for step chart.<br>\n\t\t\t * **Available values:**\n\t\t\t * - step\n\t\t\t * - step-before\n\t\t\t * - step-after\n\t\t\t * @property {Boolean|Array} [line.point=true] Set to false to not draw points on linecharts. Or pass an array of line ids to draw points for.\n\t\t\t * @property {Boolean} [line.zerobased=false] Set if min or max value will be 0 on line chart.\n\t\t\t * @example\n\t\t\t * line: {\n\t\t\t * connectNull: true,\n\t\t\t * classes: [\n\t\t\t * \"line-class1\",\n\t\t\t * \"line-class2\"\n\t\t\t * ],\n\t\t\t * step: {\n\t\t\t * type: \"step-after\"\n\t\t\t * },\n\t\t\t *\n\t\t\t * // hide all data points ('point.show=false' also has similar effect)\n\t\t\t * point: false,\n\t\t\t *\n\t\t\t * // show data points for only indicated datas\n\t\t\t * point: [\n\t\t\t * \"data1\", \"data3\"\n\t\t\t * ],\n\t\t\t *\n\t\t\t * zerobased: false\n\t\t\t * }\n\t\t\t */\n\t\t\tline_connectNull: false,\n\t\t\tline_step_type: \"step\",\n\t\t\tline_zerobased: false,\n\t\t\tline_classes: undefined,\n\t\t\tline_point: true,\n\n\t\t\t/**\n\t\t\t\t* Set scatter options\n\t\t\t\t* @name scatter\n\t\t\t\t* @memberof Options\n\t\t\t\t* @type {Object}\n\t\t\t\t* @property {Boolean} [scatter.zerobased=false] Set if min or max value will be 0 on scatter chart.\n\t\t\t\t* @example\n\t\t\t\t* scatter: {\n\t\t\t\t* connectNull: true,\n\t\t\t\t* step: {\n\t\t\t\t* type: \"step-after\"\n\t\t\t\t* },\n\t\t\t\t*\n\t\t\t\t* // hide all data points ('point.show=false' also has similar effect)\n\t\t\t\t* point: false,\n\t\t\t\t*\n\t\t\t\t* // show data points for only indicated datas\n\t\t\t\t* point: [\n\t\t\t\t* \"data1\", \"data3\"\n\t\t\t\t* ],\n\t\t\t\t*\n\t\t\t\t* zerobased: false\n\t\t\t\t* }\n\t\t\t\t*/\n\t\t\tscatter_zerobased: false,\n\n\t\t\t/**\n\t\t\t * Set bar options\n\t\t\t * @name bar\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number} [bar.padding=0] The padding pixel value between each bar.\n\t\t\t * @property {Number} [bar.radius] Set the radius of bar edge in pixel.\n\t\t\t * - **NOTE:** Works only for non-stacked bar\n\t\t\t * @property {Number} [bar.radius.ratio] Set the radius ratio of bar edge in relative the bar's width.\n \t\t\t * @property {Number} [bar.sensitivity=2] The senstivity offset value for interaction boundary.\n\t\t\t * @property {Number} [bar.width] Change the width of bar chart.\n\t\t\t * @property {Number} [bar.width.ratio=0.6] Change the width of bar chart by ratio.\n\t\t\t * @property {Number} [bar.width.max] The maximum width value for ratio.\n\t\t\t * @property {Number} [bar.width.dataname] Change the width of bar for indicated dataset only.\n\t\t\t * - **NOTE:**\n\t\t\t * - Works only for non-stacked bar\n\t\t\t * - Bars are centered accoding its total width value\n\t\t\t * @property {Number} [bar.width.dataname.ratio=0.6] Change the width of bar chart by ratio.\n\t\t\t * @property {Number} [bar.width.dataname.max] The maximum width value for ratio.\n\t\t\t * @property {Boolean} [bar.zerobased=true] Set if min or max value will be 0 on bar chart.\n\t\t\t * @see [Demo: bar padding](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarPadding)\n\t\t\t * @see [Demo: bar radius](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarRadius)\n\t\t\t * @see [Demo: bar width](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidth)\n\t\t\t * @see [Demo: bar width variant](https://naver.github.io/billboard.js/demo/#BarChartOptions.BarWidthVariant)\n\t\t\t * @example\n\t\t\t * bar: {\n\t\t\t * padding: 1,\n\t\t\t *\n\t\t\t * // the 'radius' option can be used only for non-stacking bars\n\t\t\t * radius: 10,\n\t\t\t * // or\n\t\t\t * radius: {\n\t\t\t * ratio: 0.5\n\t\t\t * }\n\t\t\t *\n\t\t\t * // will not have offset between each bar elements for interaction\n\t\t\t * sensitivity: 0,\n\t\t\t *\n\t\t\t * width: 10,\n\t\t\t *\n\t\t\t * // or\n\t\t\t * width: {\n\t\t\t * ratio: 0.2,\n\t\t\t * max: 20\n\t\t\t * },\n\t\t\t *\n\t\t\t * // or specify width per dataset\n\t\t\t * width: {\n\t\t\t * data1: 20,\n\t\t\t * data2: {\n\t\t\t * ratio: 0.2,\n\t\t\t * max: 20\n\t\t\t * }\n\t\t\t * },\n\t\t\t *\n\t\t\t * zerobased: false\n\t\t\t * }\n\t\t\t */\n\t\t\tbar_padding: 0,\n\t\t\tbar_radius: undefined,\n\t\t\tbar_radius_ratio: undefined,\n\t\t\tbar_sensitivity: 2,\n\t\t\tbar_width: undefined,\n\t\t\tbar_width_ratio: 0.6,\n\t\t\tbar_width_max: undefined,\n\t\t\tbar_zerobased: true,\n\n\t\t\t/**\n\t\t\t * Set bubble options\n\t\t\t * @name bubble\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number|Function} [bubble.maxR=35] Set the max bubble radius value\n\t\t\t * @property {Boolean} [bubble.zerobased=false] Set if min or max value will be 0 on bubble chart.\n\t\t\t * @example\n\t\t\t * bubble: {\n\t\t\t * // ex) If 100 is the highest value among data bound, the representation bubble of 100 will have radius of 50.\n\t\t\t * // And the lesser will have radius relatively from tha max value.\n\t\t\t * maxR: 50,\n\t\t\t *\n\t\t\t * // or set radius callback\n\t\t\t * maxR: function(d) {\n\t\t\t * // ex. of d param - {x: Fri Oct 06 2017 00:00:00 GMT+0900, value: 80, id: \"data2\", index: 5}\n\t\t\t * ...\n\t\t\t * return Math.sqrt(d.value * 2);\n\t\t\t * },\n\t\t\t * zerobased: false\n\t\t\t * }\n\t\t\t */\n\t\t\tbubble_maxR: 35,\n\t\t\tbubble_zerobased: false,\n\n\t\t\t/**\n\t\t\t * Set area options\n\t\t\t * @name area\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [area.zerobased=true] Set if min or max value will be 0 on area chart.\n\t\t\t * @property {Boolean} [area.above=false] Set background area above the data chart line.\n\t\t\t * @property {Boolean|Object} [area.linearGradient=false] Set the linear gradient on area.<br><br>\n\t\t\t * Or customize by giving below object value:\n\t\t\t * - x {Array}: `x1`, `x2` value\n\t\t\t * - y {Array}: `y1`, `y2` value\n\t\t\t * - stops {Array}: Each item should be having `[offset, stop-color, stop-opacity]` values.\n\t\t\t * @see [MDN's &lt;linearGradient>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient), [&lt;stop>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/stop)\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.AreaChart)\n\t\t\t * @see [Demo: above](https://naver.github.io/billboard.js/demo/#AreaChartOptions.Above)\n\t\t\t * @see [Demo: linearGradient](https://naver.github.io/billboard.js/demo/#AreaChartOptions.LinearGradient)\n\t\t\t * @example\n\t\t\t * area: {\n\t\t\t * zerobased: false,\n\t\t\t * above: true,\n\t\t\t *\n\t\t\t * // will generate follwing linearGradient:\n\t\t\t * // <linearGradient x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n\t\t\t * // <stop offset=\"0\" stop-color=\"$DATA_COLOR\" stop-opacity=\"1\"></stop>\n\t\t\t * // <stop offset=\"1\" stop-color=\"$DATA_COLOR\" stop-opacity=\"0\"></stop>\n\t\t\t * // </linearGradient>\n\t\t\t * linearGradient: true,\n\t\t\t *\n\t\t\t * // Or customized gradient\n\t\t\t * linearGradient: {\n\t\t\t * \tx: [0, 0], // x1, x2 attributes\n\t\t\t * \ty: [0, 0], // y1, y2 attributes\n\t\t\t * \tstops: [\n\t\t\t * \t // offset, stop-color, stop-opacity\n\t\t\t * \t [0, \"#7cb5ec\", 1],\n\t\t\t *\n\t\t\t * \t // setting 'null' for stop-color, will set its original data color\n\t\t\t * \t [0.5, null, 0],\n\t\t\t *\n\t\t\t * \t // setting 'function' for stop-color, will pass data id as argument.\n\t\t\t * \t // It should return color string or null value\n\t\t\t * \t [1, function(id) { return id === \"data1\" ? \"red\" : \"blue\"; }, 0],\n\t\t\t * \t]\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tarea_zerobased: true,\n\t\t\tarea_above: false,\n\t\t\tarea_linearGradient: false,\n\n\t\t\t/**\n\t\t\t * Set pie options\n\t\t\t * @name pie\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [pie.label.show=true] Show or hide label on each pie piece.\n\t\t\t * @property {Function} [pie.label.format] Set formatter for the label on each pie piece.\n\t\t\t * @property {Number} [pie.label.threshold=0.05] Set threshold to show/hide labels.\n\t\t\t * @property {Number|Function} [pie.label.ratio=undefined] Set ratio of labels position.\n\t\t\t * @property {Boolean|Object} [pie.expand=true] Enable or disable expanding pie pieces.\n\t\t\t * @property {Number} [pie.expand.rate=0.98] Set expand rate.\n\t\t\t * @property {Number} [pie.expand.duration=50] Set expand transition time in ms.\n\t\t\t * @property {Number|Object} [pie.innerRadius=0] Sets the inner radius of pie arc.\n\t\t\t * @property {Number} [pie.padAngle=0] Set padding between data.\n\t\t\t * @property {Number} [pie.padding=0] Sets the gap between pie arcs.\n \t\t\t * @property {Number} [donut.startingAngle=0] Set starting angle where data draws.\n\t\t\t * @example\n\t\t\t * pie: {\n\t\t\t * label: {\n\t\t\t * show: false,\n\t\t\t * format: function(value, ratio, id) {\n\t\t\t * return d3.format(\"$\")(value);\n\t\t\t *\n\t\t\t * // to multiline, return with '\\n' character\n\t\t\t * // return value +\"%\\nLine1\\n2Line2\";\n\t\t\t * },\n\t\t\t * threshold: 0.1,\n\t\t\t *\n\t\t\t * // set ratio callback. Should return ratio value\n\t\t\t * ratio: function(d, radius, h) {\n\t\t\t * ...\n\t\t\t * return ratio;\n\t\t\t * },\n\t\t\t * // or set ratio number\n\t\t\t * ratio: 0.5\n\t\t\t * },\n\t\t\t *\n\t\t\t * // disable expand transition for interaction\n\t\t\t * expand: false,\n\t\t\t *\n\t\t\t * expand: {\n\t\t\t * \t// set duration of expand transition to 500ms.\n\t\t\t * duration: 500,\n\t\t\t *\n\t\t\t * \t// set expand area rate\n\t\t\t * rate: 1\n\t\t\t * },\n\t\t\t *\n\t\t\t * innerRadius: 0,\n\t\t\t *\n\t\t\t * // set different innerRadius for each data\n\t\t\t * innerRadius: {\n\t\t\t * \tdata1: 10,\n\t\t\t * \tdata2: 0\n\t\t\t * }\n\t\t\t *\n\t\t\t * padAngle: 0.1,\n\t\t\t * padding: 0,\n\t\t\t * startingAngle: 1\n\t\t\t * }\n\t\t\t */\n\t\t\tpie_label_show: true,\n\t\t\tpie_label_format: undefined,\n\t\t\tpie_label_threshold: 0.05,\n\t\t\tpie_label_ratio: undefined,\n\t\t\tpie_expand: {},\n\t\t\tpie_expand_rate: 0.98,\n\t\t\tpie_expand_duration: 50,\n\t\t\tpie_innerRadius: 0,\n\t\t\tpie_padAngle: 0,\n\t\t\tpie_padding: 0,\n\t\t\tpie_startingAngle: 0,\n\n\t\t\t/**\n\t\t\t * Set plugins\n\t\t\t * @name plugins\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @example\n\t\t\t * plugins: [\n\t\t\t * new bb.plugin.stanford({ ... }),\n\t\t\t * new PluginA(),\n\t\t\t * ...\n\t\t\t * ]\n\t\t\t */\n\t\t\tplugins: [],\n\n\t\t\t/**\n\t\t\t * Set gauge options\n\t\t\t * @name gauge\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [gauge.fullCircle=false] Show full circle as donut. When set to 'true', the max label will not be showed due to start and end points are same location.\n\t\t\t * @property {Boolean} [gauge.label.show=true] Show or hide label on gauge.\n\t\t\t * @property {Function} [gauge.label.format] Set formatter for the label on gauge. Label text can be multilined with `\\n` character.\n\t\t\t * @property {Function} [gauge.label.extents] Set customized min/max label text.\n\t\t\t * @property {Boolean} [gauge.expand=true] Enable or disable expanding gauge.\n \t\t\t * @property {Number} [gauge.expand.rate=0.98] Set expand rate.\n\t\t\t * @property {Number} [gauge.expand.duration=50] Set the expand transition time in milliseconds.\n\t\t\t * @property {Number} [gauge.min=0] Set min value of the gauge.\n\t\t\t * @property {Number} [gauge.max=100] Set max value of the gauge.\n\t\t\t * @property {Number} [gauge.startingAngle=-1 * Math.PI / 2] Set starting angle where data draws.\n\t\t\t * @property {String} [gauge.title=\"\"] Set title of gauge chart. Use `\\n` character to enter line break.\n\t\t\t * @property {String} [gauge.units] Set units of the gauge.\n\t\t\t * @property {Number} [gauge.width] Set width of gauge chart.\n\t\t\t * @property {String} [gauge.type=\"single\"] Set type of gauge to be displayed.<br><br>\n\t\t\t * **Available Values:**\n\t\t\t * - single\n\t\t\t * - multi\n\t\t\t * @property {String} [gauge.arcs.minWidth=5] Set minimal width of gauge arcs until the innerRadius disappears.\n\t\t\t * @example\n\t\t\t * gauge: {\n\t\t\t * fullCircle: false,\n\t\t\t * label: {\n\t\t\t * show: false,\n\t\t\t * format: function(value, ratio) {\n\t\t\t * return value;\n\t\t\t *\n\t\t\t * // to multiline, return with '\\n' character\n\t\t\t * // return value +\"%\\nLine1\\n2Line2\";\n\t\t\t * },\n\t\t\t * extents: function(value, isMax) {\n\t\t \t * return (isMax ? \"Max:\" : \"Min:\") + value;\n\t\t\t * }\n\t\t\t * },\n\t\t\t *\n\t\t\t * // disable expand transition for interaction\n\t\t\t * expand: false,\n\t\t\t *\n\t\t\t * expand: {\n\t\t\t * \t// set duration of expand transition to 500ms.\n\t\t\t * duration: 500,\n\t\t\t *\n\t\t\t * \t// set expand area rate\n\t\t\t * rate: 1\n\t\t\t * },\n\t\t\t *\n\t\t\t * min: -100,\n\t\t\t * max: 200,\n\t\t\t * type: \"single\" // or 'multi'\n\t\t\t * title: \"Title Text\",\n\t\t\t * units: \"%\",\n\t\t\t * width: 10,\n\t\t\t * arcs: {\n\t\t\t * minWidth: 5\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tgauge_fullCircle: false,\n\t\t\tgauge_label_show: true,\n\t\t\tgauge_label_format: undefined,\n\t\t\tgauge_min: 0,\n\t\t\tgauge_max: 100,\n\t\t\tgauge_type: \"single\",\n\t\t\tgauge_startingAngle: -1 * Math.PI / 2,\n\t\t\tgauge_label_extents: undefined,\n\t\t\tgauge_title: \"\",\n\t\t\tgauge_units: undefined,\n\t\t\tgauge_width: undefined,\n\t\t\tgauge_arcs_minWidth: 5,\n\t\t\tgauge_expand: {},\n\t\t\tgauge_expand_rate: 0.98,\n\t\t\tgauge_expand_duration: 50,\n\n\t\t\t/**\n\t\t\t * Set donut options\n\t\t\t * @name donut\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [donut.label.show=true] Show or hide label on each donut piece.\n\t\t\t * @property {Function} [donut.label.format] Set formatter for the label on each donut piece.\n\t\t\t * @property {Number} [donut.label.threshold=0.05] Set threshold to show/hide labels.\n\t\t\t * @property {Number|Function} [donut.label.ratio=undefined] Set ratio of labels position.\n\t\t\t * @property {Boolean} [donut.expand=true] Enable or disable expanding donut pieces.\n\t\t\t * @property {Number} [donut.expand.rate=0.98] Set expand rate.\n\t\t\t * @property {Number} [donut.expand.duration=50] Set expand transition time in ms.\n\t\t\t * @property {Number} [donut.width] Set width of donut chart.\n\t\t\t * @property {String} [donut.title=\"\"] Set title of donut chart. Use `\\n` character to enter line break.\n\t\t\t * @property {Number} [donut.padAngle=0] Set padding between data.\n\t\t\t * @property {Number} [donut.startingAngle=0] Set starting angle where data draws.\n\t\t\t * @example\n\t\t\t * donut: {\n\t\t\t * label: {\n\t\t\t * show: false,\n\t\t\t * format: function(value, ratio, id) {\n\t\t\t * return d3.format(\"$\")(value);\n\t\t\t *\n\t\t\t * // to multiline, return with '\\n' character\n\t\t\t * // return value +\"%\\nLine1\\n2Line2\";\n\t\t\t * },\n\t\t\t * threshold: 0.1,\n\t\t\t *\n\t\t\t * // set ratio callback. Should return ratio value\n\t\t\t * ratio: function(d, radius, h) {\n\t\t\t * \t...\n\t\t\t * \treturn ratio;\n\t\t\t * },\n\t\t\t * // or set ratio number\n\t\t\t * ratio: 0.5\n\t\t\t * },\n\t\t\t *\n\t\t\t * // disable expand transition for interaction\n\t\t\t * expand: false,\n\t\t\t *\n\t\t\t * expand: {\n\t\t\t * \t// set duration of expand transition to 500ms.\n\t\t\t * duration: 500,\n\t\t\t *\n\t\t\t * \t// set expand area rate\n\t\t\t * rate: 1\n\t\t\t * },\n\t\t\t *\n\t\t\t * width: 10,\n\t\t\t * padAngle: 0.2,\n\t\t\t * startingAngle: 1,\n\t\t\t * title: \"Donut Title\"\n\t\t\t *\n\t\t\t * // title with line break\n\t\t\t * title: \"Title1\\nTitle2\"\n\t\t\t * }\n\t\t\t */\n\t\t\tdonut_label_show: true,\n\t\t\tdonut_label_format: undefined,\n\t\t\tdonut_label_threshold: 0.05,\n\t\t\tdonut_label_ratio: undefined,\n\t\t\tdonut_width: undefined,\n\t\t\tdonut_title: \"\",\n\t\t\tdonut_expand: {},\n\t\t\tdonut_expand_rate: 0.98,\n\t\t\tdonut_expand_duration: 50,\n\t\t\tdonut_padAngle: 0,\n\t\t\tdonut_startingAngle: 0,\n\n\t\t\t/**\n\t\t\t * Set spline options\n\t\t\t * - **Available interpolation type values:**\n\t\t\t * - basis (d3.curveBasis)\n\t\t\t * - basis-closed (d3.curveBasisClosed)\n\t\t\t * - basis-open (d3.curveBasisOpen)\n\t\t\t * - bundle (d3.curveBundle)\n\t\t\t * - cardinal (d3.curveCardinal)\n\t\t\t * - cardinal-closed (d3.curveCardinalClosed)\n\t\t\t * - cardinal-open (d3.curveCardinalOpen)\n\t\t\t * - catmull-rom (d3.curveCatmullRom)\n\t\t\t * - catmull-rom-closed (d3.curveCatmullRomClosed)\n\t\t\t * - catmull-rom-open (d3.curveCatmullRomOpen)\n\t\t\t * - monotone-x (d3.curveMonotoneX)\n\t\t\t * - monotone-y (d3.curveMonotoneY)\n\t\t\t * - natural (d3.curveNatural)\n\t\t\t * - linear-closed (d3.curveLinearClosed)\n\t\t\t * - linear (d3.curveLinear)\n\t\t\t * - step (d3.curveStep)\n\t\t\t * - step-after (d3.curveStepAfter)\n\t\t\t * - step-before (d3.curveStepBefore)\n\t\t\t * @name spline\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {String} [spline.interpolation.type=\"cardinal\"]\n\t\t\t * @see [Interpolation (d3 v4)](http://bl.ocks.org/emmasaunders/c25a147970def2b02d8c7c2719dc7502)\n\t\t\t * @example\n\t\t\t * spline: {\n\t\t\t * interpolation: {\n\t\t\t * type: \"cardinal\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tspline_interpolation_type: \"cardinal\",\n\n\t\t\t/**\n\t\t\t * Set radar options\n\t\t\t * - **NOTE:**\n\t\t\t * > When x tick text contains `\\n`, it's used as line break.\n\t\t\t * @name radar\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Number} [radar.axis.max=undefined] The max value of axis. If not given, it'll take the max value from the given data.\n\t\t\t * @property {Boolean} [radar.axis.line.show=true] Show or hide axis line.\n\t\t\t * @property {Number} [radar.axis.text.position.x=0] x coordinate position, relative the original.\n\t\t\t * @property {NUmber} [radar.axis.text.position.y=0] y coordinate position, relative the original.\n\t\t\t * @property {Boolean} [radar.axis.text.show=true] Show or hide axis text.\n\t\t\t * @property {Boolean} [radar.direction.clockwise=false] Set the direction to be drawn.\n\t\t\t * @property {Number} [radar.level.depth=3] Set the level depth.\n\t\t\t * @property {Boolean} [radar.level.show=true] Show or hide level.\n\t\t\t * @property {Function} [radar.level.text.format=(x) => (x % 1 === 0 ? x : x.toFixed(2))] Set format function for the level value.\n\t\t\t * @property {Boolean} [radar.level.text.show=true] Show or hide level text.\n\t\t\t * @property {Number} [radar.size.ratio=0.87] Set size ratio.\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Chart.RadarChart)\n\t\t\t * @see [Demo: radar axis](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxis)\n\t\t\t * @see [Demo: radar level](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarLevel)\n\t\t\t * @see [Demo: radar size](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarSize)\n\t\t\t * @see [Demo: radar axis multiline](https://naver.github.io/billboard.js/demo/#RadarChartOptions.RadarAxisMultiline)\n\t\t\t * @example\n\t\t\t * radar: {\n\t\t\t * axis: {\n\t\t\t * max: 50,\n\t\t\t * line: {\n\t\t\t * show: false\n\t\t\t * },\n\t\t\t * text: {\n\t\t\t * position: {\n\t\t\t * \tx: 0,\n\t\t\t * \ty: 0\n\t\t\t * },\n\t\t\t * show: false\n\t\t\t * }\n\t\t\t * },\n\t\t\t * direction: {\n\t\t\t * clockwise: true\n\t\t\t * },\n\t\t\t * level: {\n\t\t\t * show: false,\n\t\t\t * text: {\n\t\t\t * format: function(x) {\n\t\t\t * return x + \"%\";\n\t\t\t * },\n\t\t\t * show: true\n\t\t\t * }\n\t\t\t * },\n\t\t\t * size: {\n\t\t\t * ratio: 0.7\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\tradar_axis_max: undefined,\n\t\t\tradar_axis_line_show: true,\n\t\t\tradar_axis_text_show: true,\n\t\t\tradar_axis_text_position: {},\n\t\t\tradar_level_depth: 3,\n\t\t\tradar_level_show: true,\n\t\t\tradar_level_text_format: x => (x % 1 === 0 ? x : x.toFixed(2)),\n\t\t\tradar_level_text_show: true,\n\t\t\tradar_size_ratio: 0.87,\n\t\t\tradar_direction_clockwise: false,\n\n\t\t\t/**\n\t\t\t * Control the render timing\n\t\t\t * @name render\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [render.lazy=true] Make to not render at initialization (enabled by default when bind element's visibility is hidden).\n\t\t\t * @property {Boolean} [render.observe=true] Observe bind element's visibility(`display` or `visiblity` inline css property or class value) & render when is visible automatically (for IEs, only works IE11+). When set to **false**, call [`.flush()`](./Chart.html#flush) to render.\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#ChartOptions.LazyRender)\n\t\t\t * @example\n\t\t\t * render: {\n\t\t\t * lazy: true,\n\t\t\t * observe: true\n\t\t\t * }\n\t\t\t *\n\t\t\t * @example\n\t\t\t *\t// <!-- render.lazy will detect visibility defined -->\n\t\t\t * // (a) <div id='chart' class='hide'></div>\n\t\t\t * // (b) <div id='chart' style='display:none'></div>\n\t\t\t *\n\t\t\t * // render.lazy enabled by default when element is hidden\n\t\t\t * var chart = bb.generate({ ... });\n\t\t\t *\n\t\t\t * // chart will be rendered automatically when element's visibility changes\n\t\t\t * // Note: works only for inlined css property or class attribute changes\n\t\t\t * document.getElementById('chart').classList.remove('hide') // (a)\n\t\t\t * document.getElementById('chart').style.display = 'block'; // (b)\n\t\t\t *\n\t\t\t * @example\n\t\t\t *\t// chart won't be rendered and not observing bind element's visiblity changes\n\t\t\t * var chart = bb.generate({\n\t\t\t * render: {\n\t\t\t * lazy: true,\n\t\t\t * observe: false\n\t\t\t * }\n\t\t\t * });\n\t\t\t *\n\t\t\t * // call at any point when you want to render\n\t\t\t * chart.flush();\n\t\t\t */\n\t\t\trender: {},\n\n\t\t\t/**\n\t\t\t * Show rectangles inside the chart.<br><br>\n\t\t\t * This option accepts array including object that has axis, start, end and class.\n\t\t\t * The keys start, end and class are optional.\n\t\t\t * axis must be x, y or y2. start and end should be the value where regions start and end.\n\t\t\t * If not specified, the edge values will be used.\n\t\t\t * If timeseries x axis, date string, Date object and unixtime integer can be used.\n\t\t\t * If class is set, the region element will have it as class.\n\t\t\t * @name regions\n\t\t\t * @memberof Options\n\t\t\t * @type {Array}\n\t\t\t * @default []\n\t\t\t * @example\n\t\t\t * regions: [\n\t\t\t * {\n\t\t\t * axis: \"x\",\n\t\t\t * start: 1,\n\t\t\t * end: 4,\n\t\t\t * class: \"region-1-4\"\n\t\t\t * }\n\t\t\t * ]\n\t\t\t */\n\t\t\tregions: [],\n\n\t\t\t/**\n\t\t\t * Tooltip options\n\t\t\t * @name tooltip\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {Boolean} [tooltip.show=true] Show or hide tooltip.\n\t\t\t * @property {Boolean} [tooltip.doNotHide=false] Make tooltip keep showing not hiding on interaction.\n\t\t\t * @property {Boolean} [tooltip.grouped=true] Set if tooltip is grouped or not for the data points.\n\t\t\t * - **NOTE:** The overlapped data points will be displayed as grouped even if set false.\n\t\t\t * @property {Boolean} [tooltip.linked=false] Set if tooltips on all visible charts with like x points are shown together when one is shown.\n\t\t\t * @property {String} [tooltip.linked.name=\"\"] Groping name for linked tooltip.<br>If specified, linked tooltip will be groped interacting to be worked only with the same name.\n\t\t\t * @property {Function} [tooltip.format.title] Set format for the title of tooltip.<br>\n\t\t\t * Specified function receives x of the data point to show.\n\t\t\t * @property {Function} [tooltip.format.name] Set format for the name of each data in tooltip.<br>\n\t\t\t * Specified function receives name, ratio, id and index of the data point to show. ratio will be undefined if the chart is not donut/pie/gauge.\n\t\t\t * @property {Function} [tooltip.format.value] Set format for the value of each data in tooltip.<br>\n\t\t\t * Specified function receives name, ratio, id and index of the data point to show. ratio will be undefined if the chart is not donut/pie/gauge.\n\t\t\t * If undefined returned, the row of that value will be skipped.\n\t\t\t * @property {Function} [tooltip.position] Set custom position function for the tooltip.<br>\n\t\t\t * This option can be used to modify the tooltip position by returning object that has top and left.\n\t\t\t * @property {Function|Object} [tooltip.contents] Set custom HTML for the tooltip.<br>\n\t\t\t * Specified function receives data, defaultTitleFormat, defaultValueFormat and color of the data point to show. If tooltip.grouped is true, data includes multiple data points.\n\t\t\t * @property {String|HTMLElement} [tooltip.contents.bindto=undefined] Set CSS selector or element reference to bind tooltip.\n\t\t\t * - **NOTE:** When is specified, will not be updating tooltip's position.\n\t\t\t * @property {String} [tooltip.contents.template=undefined] Set tooltip's template.<br><br>\n\t\t\t * Within template, below syntax will be replaced using template-like syntax string:\n\t\t\t * - **{{ ... }}**: the doubly curly brackets indicate loop block for data rows.\n\t\t\t * - **{=CLASS_TOOLTIP}**: default tooltip class name `bb-tooltip`.\n\t\t\t * - **{=CLASS_TOOLTIP_NAME}**: default tooltip data class name (ex. `bb-tooltip-name-data1`)\n\t\t\t * - **{=TITLE}**: title value.\n\t\t\t * - **{=COLOR}**: data color.\n\t\t\t * - **{=VALUE}**: data value.\n\t\t\t * @property {Object} [tooltip.contents.text=undefined] Set additional text content within data loop, using template syntax.\n\t\t\t * - **NOTE:** It should contain `{ key: Array, ... }` value\n\t\t\t * - 'key' name is used as substitution within template as '{=KEY}'\n\t\t\t * - The value array length should match with the data length\n\t\t\t * @property {Boolean} [tooltip.init.show=false] Show tooltip at the initialization.\n\t\t\t * @property {Number} [tooltip.init.x=0] Set x Axis index to be shown at the initialization.\n\t\t\t * @property {Object} [tooltip.init.position={top: \"0px\",left: \"50px\"}] Set the position of tooltip at the initialization.\n\t\t\t * @property {Function} [tooltip.onshow] Set a callback that will be invoked before the tooltip is shown.\n\t\t\t * @property {Function} [tooltip.onhide] Set a callback that will be invoked before the tooltip is hidden.\n\t\t\t * @property {Function} [tooltip.onshown] Set a callback that will be invoked after the tooltip is shown\n\t\t\t * @property {Function} [tooltip.onhidden] Set a callback that will be invoked after the tooltip is hidden.\n\t\t\t * @property {String|Function|null} [tooltip.order=null] Set tooltip data display order.<br><br>\n\t\t\t * **Available Values:**\n\t\t\t * - `desc`: In descending data value order\n\t\t\t * - `asc`: In ascending data value order\n\t\t\t * - `null`: It keeps the data display order<br>\n\t\t\t * **NOTE:** When `data.groups` is set, the order will follow as the stacked graph order.<br>\n\t\t\t * If want to order as data bound, set any value rather than asc, desc or null. (ex. empty string \"\")\n\t\t\t * - `function(data1, data2) { ... }`: [Array.sort compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters)\n\t\t\t * @see [Demo: Hide Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.HideTooltip)\n\t\t\t * @see [Demo: Tooltip Grouping](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipGrouping)\n\t\t\t * @see [Demo: Tooltip Format](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipFormat)\n\t\t\t * @see [Demo: Linked Tooltip](https://naver.github.io/billboard.js/demo/#Tooltip.LinkedTooltips)\n\t\t\t * @see [Demo: Tooltip Template](https://naver.github.io/billboard.js/demo/#Tooltip.TooltipTemplate)\n\t\t\t * @example\n\t\t\t * tooltip: {\n\t\t\t * show: true,\n\t\t\t * doNotHide: true,\n\t\t\t * grouped: false,\n\t\t\t * format: {\n\t\t\t * title: function(x) { return \"Data \" + x; },\n\t\t\t * name: function(name, ratio, id, index) { return name; },\n\t\t\t * value: function(value, ratio, id, index) { return ratio; }\n\t\t\t * },\n\t\t\t * position: function(data, width, height, element) {\n\t\t\t * \t// return with unit or without. If the value is number, is treated as 'px'.\n\t\t\t * \treturn {top: \"10%\", left: 20} // top:10%; left: 20px;\n \t\t\t * },\n \t\t\t * contents: function(d, defaultTitleFormat, defaultValueFormat, color) {\n \t\t\t * return ... // formatted html as you want\n \t\t * },\n\t\t\t *\n\t\t\t * // specify tooltip contents using template\n\t\t\t * // - example of HTML returned:\n\t\t\t * // <ul class=\"bb-tooltip\">\n\t\t\t * // <li class=\"bb-tooltip-name-data1\"><span>250</span><br><span style=\"color:#00c73c\">data1</span></li>\n\t\t\t * // <li class=\"bb-tooltip-name-data2\"><span>50</span><br><span style=\"color:#fa7171\">data2</span></li>\n\t\t\t * // </ul>\n\t\t\t * contents: {\n\t\t\t * \tbindto: \"#tooltip\",\n\t\t\t * \ttemplate: '<ul class={=CLASS_TOOLTIP}>{{' +\n\t\t\t * \t\t\t'<li class=\"{=CLASS_TOOLTIP_NAME}\"><span>{=VALUE}</span><br>' +\n\t\t\t * \t\t\t'<span style=color:{=COLOR}>{=NAME}</span></li>' +\n\t\t\t * \t\t'}}</ul>'\n\t\t\t * }\n\t\t\t *\n\t\t\t * // with additional text value\n\t\t\t * // - example of HTML returned:\n\t\t\t * // <ul class=\"bb-tooltip\">\n\t\t\t * // <li class=\"bb-tooltip-name-data1\"><span>250</span><br>comment1<span style=\"color:#00c73c\">data1</span>text1</li>\n\t\t\t * // <li class=\"bb-tooltip-name-data2\"><span>50</span><br>comment2<span style=\"color:#fa7171\">data2</span>text2</li>\n\t\t\t * // </ul>\n\t\t\t * contents: {\n\t\t\t * \tbindto: \"#tooltip\",\n\t\t\t * \ttext: {\n\t\t\t * \t\t// a) 'key' name is used as substitution within template as '{=KEY}'\n\t\t\t * \t\t// b) the length should match with the data length\n\t\t\t * \t\tVAR1: [\"text1\", \"text2\"],\n\t\t\t * \t\tVAR2: [\"comment1\", \"comment2\"],\n\t\t\t * \t},\n\t\t\t * \ttemplate: '<ul class={=CLASS_TOOLTIP}>{{' +\n\t\t\t * \t\t\t'<li class=\"{=CLASS_TOOLTIP_NAME}\"><span>{=VALUE}</span>{=VAR2}<br>' +\n\t\t\t * \t\t\t'<span style=color:{=COLOR}>{=NAME}</span>{=VAR1}</li>' +\n\t\t\t * \t\t'}}</ul>'\n\t\t\t * }\n \t\t *\n \t\t * // sort tooltip data value display in ascending order\n \t\t * order: \"asc\",\n \t\t *\n\t\t\t * // specifying sort function\n\t\t\t * order: function(a, b) {\n\t\t\t * // param data passed format\n\t\t\t * {x: 5, value: 250, id: \"data1\", index: 5, name: \"data1\"}\n\t\t\t * ...\n\t\t\t * },\n\t\t\t *\n\t\t\t * // show at the initialization\n\t\t\t * init: {\n\t\t\t * show: true,\n\t\t\t * x: 2,\n\t\t\t * position: {\n\t\t\t * top: \"150px\",\n\t\t\t * left: \"250px\"\n\t\t\t * }\n\t\t\t * },\n\t\t\t *\n\t\t\t * // fires prior tooltip is shown\n\t\t\t * onshow: function(ctx, selectedData) {\n\t\t\t * \tctx; // current chart instance\n\t\t\t *\n\t\t\t * \t// current dataset selected\n\t\t\t * \t// ==> [{x: 4, value: 150, id: \"data2\", index: 4, name: \"data2\"}, ...]\n\t\t\t * \tselectedData;\n\t\t\t * },\n\t\t\t *\n\t\t\t * // fires prior tooltip is hidden\n\t\t\t * onhide: function(ctx, selectedData) {\n\t\t\t * \tctx; // current chart instance\n\t\t\t *\n\t\t\t * \t// current dataset selected\n\t\t\t * \t// ==> [{x: 4, value: 150, id: \"data2\", index: 4, name: \"data2\"}, ...]\n\t\t\t * \tselectedData;\n\t\t\t * },\n\t\t\t *\n\t\t\t * // fires after tooltip is shown\n\t\t\t * onshown: function(ctx, selectedData) {\n\t\t\t * \tctx; // current chart instance\n\t\t\t *\n\t\t\t * \t// current dataset selected\n\t\t\t * \t// ==> [{x: 4, value: 150, id: \"data2\", index: 4, name: \"data2\"}, ...]\n\t\t\t * \tselectedData;\n\t\t\t * },\n\t\t\t *\n\t\t\t * // fires after tooltip is hidden\n\t\t\t * onhidden: function(ctx, selectedData) {\n\t\t\t * \tctx; // current chart instance\n\t\t\t *\n\t\t\t * \t// current dataset selected\n\t\t\t * \t// ==> [{x: 4, value: 150, id: \"data2\", index: 4, name: \"data2\"}, ...]\n\t\t\t * \tselectedData;\n\t\t\t * },\n\t\t\t *\n\t\t\t * // Link any tooltips when multiple charts are on the screen where same x coordinates are available\n\t\t\t * // Useful for timeseries correlation\n\t\t\t * linked: true,\n\t\t\t *\n\t\t\t * // Specify name to interact those with the same name only.\n\t\t\t * linked: {\n\t\t\t * name: \"some-group\"\n\t\t\t * }\n\t\t\t * }\n\t\t\t */\n\t\t\ttooltip_show: true,\n\t\t\ttooltip_doNotHide: false,\n\t\t\ttooltip_grouped: true,\n\t\t\ttooltip_format_title: undefined,\n\t\t\ttooltip_format_name: undefined,\n\t\t\ttooltip_format_value: undefined,\n\t\t\ttooltip_position: undefined,\n\t\t\ttooltip_contents: {},\n\t\t\ttooltip_init_show: false,\n\t\t\ttooltip_init_x: 0,\n\t\t\ttooltip_init_position: {\n\t\t\t\ttop: \"0px\",\n\t\t\t\tleft: \"50px\"\n\t\t\t},\n\t\t\ttooltip_linked: false,\n\t\t\ttooltip_linked_name: \"\",\n\t\t\ttooltip_onshow: () => {},\n\t\t\ttooltip_onhide: () => {},\n\t\t\ttooltip_onshown: () => {},\n\t\t\ttooltip_onhidden: () => {},\n\t\t\ttooltip_order: null,\n\n\t\t\t/**\n\t\t\t * Set title options\n\t\t\t * @name title\n\t\t\t * @memberof Options\n\t\t\t * @type {Object}\n\t\t\t * @property {String} [title.text] Title text. If contains `\\n`, it's used as line break allowing multiline title.\n\t\t\t * @property {Number} [title.padding.top=0] Top padding value.\n\t\t\t * @property {Number} [title.padding.right=0] Right padding value.\n\t\t\t * @property {Number} [title.padding.bottom=0] Bottom padding value.\n\t\t\t * @property {Number} [title.padding.left=0] Left padding value.\n\t\t\t * @property {String} [title.position=center] Available values are: 'center', 'right' and 'left'.\n\t\t\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Title.MultilinedTitle)\n\t\t\t * @example\n\t\t\t * title: {\n\t\t\t * text: \"Title Text\",\n\t\t\t *\n\t\t\t * // or Multiline title text\n\t\t\t * text: \"Main title text\\nSub title text\",\n\t\t\t *\n\t\t\t * padding: {\n\t\t\t * top: 10,\n\t\t\t * right: 10,\n\t\t\t * bottom: 10,\n\t\t\t * left: 10\n\t\t\t * },\n\t\t\t * position: \"center\"\n\t\t\t * }\n\t\t\t */\n\t\t\ttitle_text: undefined,\n\t\t\ttitle_padding: {\n\t\t\t\ttop: 0,\n\t\t\t\tright: 0,\n\t\t\t\tbottom: 0,\n\t\t\t\tleft: 0\n\t\t\t},\n\t\t\ttitle_position: \"center\"\n\t\t};\n\t}\n}\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Options from \"./Options\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {isDefined, isObjectType, extend} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tgetOptions() {\n\t\treturn new Options();\n\t},\n\n\t/**\n\t * Load configuration option\n\t * @param {Object} config User's generation config value\n\t * @private\n\t */\n\tloadConfig(config) {\n\t\tconst thisConfig = this.config;\n\t\tlet target;\n\t\tlet keys;\n\t\tlet read;\n\n\t\tconst find = () => {\n\t\t\tconst key = keys.shift();\n\n\t\t\tif (key && target && isObjectType(target) && key in target) {\n\t\t\t\ttarget = target[key];\n\t\t\t\treturn find();\n\t\t\t} else if (!key) {\n\t\t\t\treturn target;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t};\n\n\t\tObject.keys(thisConfig).forEach(key => {\n\t\t\ttarget = config;\n\t\t\tkeys = key.split(\"_\");\n\t\t\tread = find();\n\n\t\t\tif (isDefined(read)) {\n\t\t\t\tthisConfig[key] = read;\n\t\t\t}\n\t\t});\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tscaleTime as d3ScaleTime,\n\tscaleLinear as d3ScaleLinear\n} from \"d3-scale\";\nimport ChartInternal from \"./ChartInternal\";\nimport {extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\tgetScale(min, max, forTimeseries) {\n\t\treturn (forTimeseries ?\n\t\t\td3ScaleTime() : d3ScaleLinear()\n\t\t).range([min, max]);\n\t},\n\n\t/**\n\t * Get x Axis scale function\n\t * @param {Number} min\n\t * @param {Number} max\n\t * @param {Number} domain\n\t * @param {Function} offset The offset getter to be sum\n\t * @return {Function} scale\n\t * @private\n\t */\n\tgetX(min, max, domain, offset) {\n\t\tconst $$ = this;\n\t\tconst scale = $$.zoomScale || $$.getScale(min, max, $$.isTimeSeries());\n\n\t\treturn $$.getCustomizedScale(\n\t\t\tdomain ? scale.domain(domain) : scale,\n\t\t\toffset\n\t\t);\n\t},\n\n\t/**\n\t * Get y Axis scale function\n\t * @param {Number} min\n\t * @param {Number} max\n\t * @param {Number} domain\n\t * @return {Function} scale\n\t * @private\n\t */\n\tgetY(min, max, domain) {\n\t\tconst scale = this.getScale(min, max, this.isTimeSeriesY());\n\n\t\tdomain && scale.domain(domain);\n\n\t\treturn scale;\n\t},\n\n\t/**\n\t * Get customized scale\n\t * @param {d3.scaleLinear|d3.scaleTime} scaleValue\n\t * @param {Function} offsetValue Offset getter to be sum\n\t * @return {} scale\n\t * @private\n\t */\n\tgetCustomizedScale(scaleValue, offsetValue) {\n\t\tconst $$ = this;\n\t\tconst offset = offsetValue || (() => $$.xAxis.tickOffset());\n\t\tconst scale = function(d, raw) {\n\t\t\tconst v = scaleValue(d) + offset();\n\n\t\t\treturn raw ? v : Math.ceil(v);\n\t\t};\n\n\t\t// copy original scale methods\n\t\tfor (const key in scaleValue) {\n\t\t\tscale[key] = scaleValue[key];\n\t\t}\n\n\t\tscale.orgDomain = () => scaleValue.domain();\n\t\tscale.orgScale = () => scaleValue;\n\n\t\t// define custom domain() for categorized axis\n\t\tif ($$.isCategorized()) {\n\t\t\tscale.domain = function(domainValue) {\n\t\t\t\tlet domain = domainValue;\n\n\t\t\t\tif (!arguments.length) {\n\t\t\t\t\tdomain = this.orgDomain();\n\n\t\t\t\t\treturn [domain[0], domain[1] + 1];\n\t\t\t\t}\n\n\t\t\t\tscaleValue.domain(domain);\n\n\t\t\t\treturn scale;\n\t\t\t};\n\t\t}\n\n\t\treturn scale;\n\t},\n\n\tgetYScale(id) {\n\t\treturn this.axis.getId(id) === \"y2\" ? this.y2 : this.y;\n\t},\n\n\tgetSubYScale(id) {\n\t\treturn this.axis.getId(id) === \"y2\" ? this.subY2 : this.subY;\n\t},\n\n\t/**\n\t * Update scale\n\t * @private\n\t * @param {Boolean} isInit - param is given at the init rendering\n\t */\n\tupdateScales(isInit, updateXDomain = true) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\t// update edges\n\t\t$$.xMin = isRotated ? 1 : 0;\n\t\t$$.xMax = isRotated ? $$.height : $$.width;\n\t\t$$.yMin = isRotated ? 0 : $$.height;\n\t\t$$.yMax = isRotated ? $$.width : 1;\n\t\t$$.subXMin = $$.xMin;\n\t\t$$.subXMax = $$.xMax;\n\t\t$$.subYMin = isRotated ? 0 : $$.height2;\n\t\t$$.subYMax = isRotated ? $$.width2 : 1;\n\n\t\t// update scales\n\t\t// x Axis\n\t\tconst xDomain = updateXDomain && $$.x && $$.x.orgDomain();\n\t\tconst xSubDomain = updateXDomain && $$.orgXDomain;\n\n\t\t$$.x = $$.getX($$.xMin, $$.xMax, xDomain, () => $$.xAxis.tickOffset());\n\t\t$$.subX = $$.getX($$.xMin, $$.xMax, xSubDomain, d => (d % 1 ? 0 : $$.subXAxis.tickOffset()));\n\n\t\t$$.xAxisTickFormat = $$.axis.getXAxisTickFormat();\n\t\t$$.xAxisTickValues = $$.axis.getTickValues(\"x\");\n\n\t\t$$.xAxis = $$.axis\n\t\t\t.getAxis(\"x\", $$.x, config.axis_x_tick_outer, isInit);\n\n\t\t$$.subXAxis = $$.axis\n\t\t\t.getAxis(\"subX\", $$.subX, config.axis_x_tick_outer, isInit);\n\n\t\t// y Axis\n\t\t$$.y = $$.getY($$.yMin, $$.yMax, $$.y ? $$.y.domain() : config.axis_y_default);\n\t\t$$.subY = $$.getY($$.subYMin, $$.subYMax, $$.subY ? $$.subY.domain() : config.axis_y_default);\n\n\t\t$$.yAxisTickValues = $$.axis.getTickValues(\"y\");\n\n\t\t$$.yAxis = $$.axis\n\t\t\t.getAxis(\"y\", $$.y, config.axis_y_tick_outer, isInit);\n\n\t\t// y2 Axis\n\t\tif (config.axis_y2_show) {\n\t\t\t$$.y2 = $$.getY($$.yMin, $$.yMax, $$.y2 ? $$.y2.domain() : config.axis_y2_default);\n\t\t\t$$.subY2 = $$.getY($$.subYMin, $$.subYMax,\n\t\t\t\t$$.subY2 ? $$.subY2.domain() : config.axis_y2_default);\n\n\t\t\t$$.y2AxisTickValues = $$.axis.getTickValues(\"y2\");\n\n\t\t\t$$.y2Axis = $$.axis\n\t\t\t\t.getAxis(\"y2\", $$.y2, config.axis_y2_tick_outer, isInit);\n\t\t}\n\n\t\t// update for arc\n\t\t$$.updateArc && $$.updateArc();\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {extend, brushEmpty, getBrushSelection, getMinMax, isDefined, notEmpty, isValue, isObject, isNumber, diffDomain, sortValue} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\tgetYDomainMinMax(targets, type) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isMin = type === \"min\";\n\n\t\tconst dataGroups = config.data_groups;\n\t\tconst ids = $$.mapToIds(targets);\n\t\tconst ys = $$.getValuesAsIdKeyed(targets);\n\n\t\tif (dataGroups.length > 0) {\n\t\t\tconst hasValue = $$[`has${isMin ? \"Negative\" : \"Positive\"}ValueInTargets`](targets);\n\n\t\t\tfor (let j = 0, idsInGroup; (idsInGroup = dataGroups[j]); j++) {\n\t\t\t\t// Determine baseId\n\t\t\t\tidsInGroup = idsInGroup.filter(v => ids.indexOf(v) >= 0);\n\n\t\t\t\tif (idsInGroup.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst baseId = idsInGroup[0];\n\t\t\t\tconst baseAxisId = $$.axis.getId(baseId);\n\n\t\t\t\t// Initialize base value. Set to 0 if not match with the condition\n\t\t\t\tif (hasValue && ys[baseId]) {\n\t\t\t\t\tys[baseId] = ys[baseId].map(v => (\n\t\t\t\t\t\t(isMin ? v < 0 : v > 0) ? v : 0\n\t\t\t\t\t));\n\t\t\t\t}\n\n\t\t\t\tfor (let k = 1, id; (id = idsInGroup[k]); k++) {\n\t\t\t\t\tif (!ys[id]) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst axisId = $$.axis.getId(id);\n\n\t\t\t\t\tys[id].forEach((v, i) => {\n\t\t\t\t\t\tconst val = +v;\n\t\t\t\t\t\tconst meetCondition = isMin ? val > 0 : val < 0;\n\n\t\t\t\t\t\tif (axisId === baseAxisId && !(hasValue && meetCondition)) {\n\t\t\t\t\t\t\tys[baseId][i] += val;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn getMinMax(type, Object.keys(ys).map(key => getMinMax(type, ys[key])));\n\t},\n\n\tgetYDomainMin(targets) {\n\t\treturn this.getYDomainMinMax(targets, \"min\");\n\t},\n\n\tgetYDomainMax(targets) {\n\t\treturn this.getYDomainMinMax(targets, \"max\");\n\t},\n\n\t/**\n\t * Check if hidden targets bound to the given axis id\n\t * @return {Boolean}\n\t * @private\n\t */\n\tisHiddenTargetWithYDomain(id) {\n\t\tconst $$ = this;\n\n\t\treturn $$.hiddenTargetIds\n\t\t\t.some(v => $$.axis.getId(v) === id);\n\t},\n\n\tgetYDomain(targets, axisId, xDomain) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst pfx = `axis_${axisId}`;\n\n\t\tif ($$.isStackNormalized()) {\n\t\t\treturn [0, 100];\n\t\t}\n\n\t\tconst targetsByAxisId = targets.filter(t => $$.axis.getId(t.id) === axisId);\n\t\tconst yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId;\n\n\t\tif (yTargets.length === 0) {\n\t\t\tif ($$.isHiddenTargetWithYDomain(axisId)) {\n\t\t\t\treturn $$[axisId].domain();\n\t\t\t} else {\n\t\t\t\t// use domain of the other axis if target of axisId is none\n\t\t\t\treturn axisId === \"y2\" ?\n\t\t\t\t\t$$.y.domain() :\n\t\t\t\t\t// When all data bounds to y2, y Axis domain is called prior y2.\n\t\t\t\t\t// So, it needs to call to get y2 domain here\n\t\t\t\t\t$$.getYDomain(targets, \"y2\", xDomain);\n\t\t\t}\n\t\t}\n\n\t\tconst yMin = config[`${pfx}_min`];\n\t\tconst yMax = config[`${pfx}_max`];\n\t\tlet yDomainMin = $$.getYDomainMin(yTargets);\n\t\tlet yDomainMax = $$.getYDomainMax(yTargets);\n\n\t\tconst center = config[`${pfx}_center`];\n\t\tlet isZeroBased = [\"area\", \"bar\", \"bubble\", \"line\", \"scatter\"]\n\t\t\t.some(v => $$.hasType(v, yTargets) && config[`${v}_zerobased`]);\n\t\tconst isInverted = config[`${pfx}_inverted`];\n\t\tconst showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated;\n\t\tconst showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;\n\n\t\t// MEMO: avoid inverting domain unexpectedly\n\t\tyDomainMin = isValue(yMin) ? yMin :\n\t\t\t(isValue(yMax) ? (yDomainMin < yMax ? yDomainMin : yMax - 10) : yDomainMin);\n\t\tyDomainMax = isValue(yMax) ? yMax :\n\t\t\t(isValue(yMin) ? (yMin < yDomainMax ? yDomainMax : yMin + 10) : yDomainMax);\n\n\t\tif (isNaN(yDomainMin)) { // set minimum to zero when not number\n\t\t\tyDomainMin = 0;\n\t\t}\n\n\t\tif (isNaN(yDomainMax)) { // set maximum to have same value as yDomainMin\n\t\t\tyDomainMax = yDomainMin;\n\t\t}\n\n\t\tif (yDomainMin === yDomainMax) {\n\t\t\tyDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;\n\t\t}\n\n\t\tconst isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;\n\t\tconst isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;\n\n\t\t// Cancel zerobased if axis_*_min / axis_*_max specified\n\t\tif ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {\n\t\t\tisZeroBased = false;\n\t\t}\n\n\t\t// Bar/Area chart should be 0-based if all positive|negative\n\t\tif (isZeroBased) {\n\t\t\tisAllPositive && (yDomainMin = 0);\n\t\t\tisAllNegative && (yDomainMax = 0);\n\t\t}\n\n\t\tconst domainLength = Math.abs(yDomainMax - yDomainMin);\n\t\tconst padding = {top: domainLength * 0.1, bottom: domainLength * 0.1};\n\n\t\tif (isDefined(center)) {\n\t\t\tconst yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));\n\n\t\t\tyDomainMax = center + yDomainAbs;\n\t\t\tyDomainMin = center - yDomainAbs;\n\t\t}\n\n\t\t// add padding for data label\n\t\tif (showHorizontalDataLabel) {\n\t\t\tconst diff = diffDomain($$.y.range());\n\t\t\tconst ratio = $$.getDataLabelLength(yDomainMin, yDomainMax, \"width\")\n\t\t\t\t.map(v => v / diff);\n\n\t\t\t[\"bottom\", \"top\"].forEach((v, i) => {\n\t\t\t\tpadding[v] += domainLength * (ratio[i] / (1 - ratio[0] - ratio[1]));\n\t\t\t});\n\t\t} else if (showVerticalDataLabel) {\n\t\t\tconst lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, \"height\");\n\n\t\t\t[\"bottom\", \"top\"].forEach((v, i) => {\n\t\t\t\tpadding[v] += $$.axis.convertPixelsToAxisPadding(lengths[i], domainLength);\n\t\t\t});\n\t\t}\n\n\n\t\t// if padding is set, the domain will be updated relative the current domain value\n\t\t// ex) $$.height=300, padding.top=150, domainLength=4 --> domain=6\n\t\tconst p = config[`${pfx}_padding`];\n\n\t\tif (notEmpty(p)) {\n\t\t\t[\"bottom\", \"top\"].forEach(v => {\n\t\t\t\tpadding[v] = $$.axis.getPadding(p, v, padding[v], domainLength);\n\t\t\t});\n\t\t}\n\n\t\t// Bar/Area chart should be 0-based if all positive|negative\n\t\tif (isZeroBased) {\n\t\t\tisAllPositive && (padding.bottom = yDomainMin);\n\t\t\tisAllNegative && (padding.top = -yDomainMax);\n\t\t}\n\n\t\tconst domain = [yDomainMin - padding.bottom, yDomainMax + padding.top];\n\n\t\treturn isInverted ? domain.reverse() : domain;\n\t},\n\n\tgetXDomainMinMax(targets, type) {\n\t\tconst $$ = this;\n\t\tconst configValue = $$.config[`axis_x_${type}`];\n\t\tconst dataValue = getMinMax(type, targets.map(t => getMinMax(type, t.values.map(v => v.x))));\n\t\tlet value = isObject(configValue) ? configValue.value : configValue;\n\n\t\tvalue = isDefined(value) && $$.isTimeSeries() ? $$.parseDate(value) : value;\n\n\t\tif (isObject(configValue) && configValue.fit && (\n\t\t\t(type === \"min\" && value < dataValue) || (type === \"max\" && value > dataValue)\n\t\t)) {\n\t\t\tvalue = undefined;\n\t\t}\n\n\t\treturn isDefined(value) ? value : dataValue;\n\t},\n\n\tgetXDomainMin(targets) {\n\t\treturn this.getXDomainMinMax(targets, \"min\");\n\t},\n\n\tgetXDomainMax(targets) {\n\t\treturn this.getXDomainMinMax(targets, \"max\");\n\t},\n\n\tgetXDomainPadding(domain) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst diff = domain[1] - domain[0];\n\t\tconst xPadding = config.axis_x_padding;\n\t\tlet maxDataCount;\n\t\tlet padding;\n\n\t\tif ($$.isCategorized()) {\n\t\t\tpadding = 0;\n\t\t} else if ($$.hasType(\"bar\")) {\n\t\t\tmaxDataCount = $$.getMaxDataCount();\n\t\t\tpadding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5;\n\t\t} else {\n\t\t\tpadding = diff * 0.01;\n\t\t}\n\n\t\tlet left = padding;\n\t\tlet right = padding;\n\n\t\tif (isObject(xPadding) && notEmpty(xPadding)) {\n\t\t\tleft = isValue(xPadding.left) ? xPadding.left : padding;\n\t\t\tright = isValue(xPadding.right) ? xPadding.right : padding;\n\t\t} else if (isNumber(config.axis_x_padding)) {\n\t\t\tleft = xPadding;\n\t\t\tright = xPadding;\n\t\t}\n\n\t\treturn {left, right};\n\t},\n\n\tgetXDomain(targets) {\n\t\tconst $$ = this;\n\t\tconst xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)];\n\t\tlet [firstX, lastX] = xDomain;\n\t\tconst padding = $$.getXDomainPadding(xDomain);\n\t\tlet min = 0;\n\t\tlet max = 0;\n\n\t\t// show center of x domain if min and max are the same\n\t\tif ((firstX - lastX) === 0 && !$$.isCategorized()) {\n\t\t\tif ($$.isTimeSeries()) {\n\t\t\t\tfirstX = new Date(firstX.getTime() * 0.5);\n\t\t\t\tlastX = new Date(lastX.getTime() * 1.5);\n\t\t\t} else {\n\t\t\t\tfirstX = firstX === 0 ? 1 : (firstX * 0.5);\n\t\t\t\tlastX = lastX === 0 ? -1 : (lastX * 1.5);\n\t\t\t}\n\t\t}\n\n\t\tif (firstX || firstX === 0) {\n\t\t\tmin = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;\n\t\t}\n\n\t\tif (lastX || lastX === 0) {\n\t\t\tmax = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;\n\t\t}\n\n\t\treturn [min, max];\n\t},\n\n\tupdateXDomain(targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst zoomEnabled = config.zoom_enabled;\n\n\t\tif (withUpdateOrgXDomain) {\n\t\t\t$$.x.domain(domain || sortValue($$.getXDomain(targets)));\n\t\t\t$$.orgXDomain = $$.x.domain();\n\n\t\t\tzoomEnabled && $$.zoom.updateScaleExtent();\n\n\t\t\t$$.subX.domain($$.x.domain());\n\t\t\t$$.brush && $$.brush.scale($$.subX);\n\t\t}\n\n\t\tif (withUpdateXDomain) {\n\t\t\tconst domainValue = domain || (!$$.brush || brushEmpty($$)) ?\n\t\t\t\t$$.orgXDomain : getBrushSelection($$).map($$.subX.invert);\n\n\t\t\t$$.x.domain(domainValue);\n\t\t\tzoomEnabled && $$.zoom.updateScaleExtent();\n\t\t}\n\n\t\t// Trim domain when too big by zoom mousemove event\n\t\twithTrim && $$.x.domain($$.trimXDomain($$.x.orgDomain()));\n\n\t\treturn $$.x.domain();\n\t},\n\n\ttrimXDomain(domain) {\n\t\tconst zoomDomain = this.getZoomDomain();\n\t\tconst [min, max] = zoomDomain;\n\n\t\tif (domain[0] <= min) {\n\t\t\tdomain[1] = +domain[1] + (min - domain[0]);\n\t\t\tdomain[0] = min;\n\t\t}\n\n\t\tif (max <= domain[1]) {\n\t\t\tdomain[0] = +domain[0] - (domain[1] - max);\n\t\t\tdomain[1] = max;\n\t\t}\n\n\t\treturn domain;\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {\n\textend,\n\tgetUnique,\n\thasValue,\n\tisArray,\n\tisBoolean,\n\tisDefined,\n\tisFunction,\n\tisNumber,\n\tisObject,\n\tisObjectType,\n\tisString,\n\tisUndefined,\n\tisValue,\n\tnotEmpty,\n\tmergeArray,\n\tsortValue\n} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tisX(key) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst dataKey = config.data_x && key === config.data_x;\n\t\tconst existValue = notEmpty(config.data_xs) && hasValue(config.data_xs, key);\n\n\t\treturn dataKey || existValue;\n\t},\n\n\tisNotX(key) {\n\t\treturn !this.isX(key);\n\t},\n\n\tisStackNormalized() {\n\t\tconst config = this.config;\n\n\t\treturn config.data_stack_normalize && config.data_groups.length;\n\t},\n\n\tisGrouped(id) {\n\t\treturn this.config.data_groups\n\t\t\t.map(v => v.indexOf(id) >= 0)[0];\n\t},\n\n\tgetXKey(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn config.data_x ?\n\t\t\tconfig.data_x : (notEmpty(config.data_xs) ? config.data_xs[id] : null);\n\t},\n\n\tgetXValuesOfXKey(key, targets) {\n\t\tconst $$ = this;\n\t\tconst ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];\n\t\tlet xValues;\n\n\t\tids.forEach(id => {\n\t\t\tif ($$.getXKey(id) === key) {\n\t\t\t\txValues = $$.data.xs[id];\n\t\t\t}\n\t\t});\n\n\t\treturn xValues;\n\t},\n\n\t/**\n\t * Get index number based on given x Axis value\n\t * @param {Date|Number|String} x x Axis to be compared\n\t * @param {Array} basedX x Axis list to be based on\n\t * @return {Number} index number\n\t * @private\n\t */\n\tgetIndexByX(x, basedX) {\n\t\tconst $$ = this;\n\n\t\treturn basedX ?\n\t\t\tbasedX.indexOf(isString(x) ? x : +x) :\n\t\t\t($$.filterByX($$.data.targets, x)[0] || {index: null}).index;\n\t},\n\n\tgetXValue(id, i) {\n\t\tconst $$ = this;\n\n\t\treturn id in $$.data.xs &&\n\t\t\t$$.data.xs[id] &&\n\t\t\tisValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;\n\t},\n\n\tgetOtherTargetXs() {\n\t\tconst $$ = this;\n\t\tconst idsForX = Object.keys($$.data.xs);\n\n\t\treturn idsForX.length ? $$.data.xs[idsForX[0]] : null;\n\t},\n\n\tgetOtherTargetX(index) {\n\t\tconst xs = this.getOtherTargetXs();\n\n\t\treturn xs && index < xs.length ? xs[index] : null;\n\t},\n\n\taddXs(xs) {\n\t\tconst $$ = this;\n\n\t\tObject.keys(xs).forEach(id => {\n\t\t\t$$.config.data_xs[id] = xs[id];\n\t\t});\n\t},\n\n\tisMultipleX() {\n\t\treturn notEmpty(this.config.data_xs) ||\n\t\t\t!this.config.data_xSort ||\n\t\t\tthis.hasType(\"bubble\") ||\n\t\t\tthis.hasType(\"scatter\");\n\t},\n\n\taddName(data) {\n\t\tconst $$ = this;\n\t\tlet name;\n\n\t\tif (data) {\n\t\t\tname = $$.config.data_names[data.id];\n\t\t\tdata.name = name !== undefined ? name : data.id;\n\t\t}\n\n\t\treturn data;\n\t},\n\n\tgetAllValuesOnIndex(index) {\n\t\tconst $$ = this;\n\n\t\treturn $$.filterTargetsToShow($$.data.targets)\n\t\t\t.map(t => $$.addName($$.getValueOnIndex(t.values, index)));\n\t},\n\n\tgetValueOnIndex(values, index) {\n\t\tconst valueOnIndex = values.filter(v => v.index === index);\n\n\t\treturn valueOnIndex.length ? valueOnIndex[0] : null;\n\t},\n\n\tupdateTargetX(targets, x) {\n\t\tconst $$ = this;\n\n\t\ttargets.forEach(t => {\n\t\t\tt.values.forEach((v, i) => {\n\t\t\t\tv.x = $$.generateTargetX(x[i], t.id, i);\n\t\t\t});\n\n\t\t\t$$.data.xs[t.id] = x;\n\t\t});\n\t},\n\n\tupdateTargetXs(targets, xs) {\n\t\tconst $$ = this;\n\n\t\ttargets.forEach(t => {\n\t\t\txs[t.id] && $$.updateTargetX([t], xs[t.id]);\n\t\t});\n\t},\n\n\tgenerateTargetX(rawX, id, index) {\n\t\tconst $$ = this;\n\t\tlet x = $$.isCategorized() ? index : (rawX || index);\n\n\t\tif ($$.isTimeSeries()) {\n\t\t\tx = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));\n\t\t} else if ($$.isCustomX() && !$$.isCategorized()) {\n\t\t\tx = isValue(rawX) ? +rawX : $$.getXValue(id, index);\n\t\t}\n\n\t\treturn x;\n\t},\n\n\tcloneTarget(target) {\n\t\treturn {\n\t\t\tid: target.id,\n\t\t\tid_org: target.id_org,\n\t\t\tvalues: target.values.map(d => ({x: d.x, value: d.value, id: d.id}))\n\t\t};\n\t},\n\n\tupdateXs(values) {\n\t\tif (values.length) {\n\t\t\tthis.xs = values.map(v => v.x);\n\t\t}\n\t},\n\n\tgetPrevX(i) {\n\t\tconst x = this.xs[i - 1];\n\n\t\treturn isDefined(x) ? x : null;\n\t},\n\n\tgetNextX(i) {\n\t\tconst x = this.xs[i + 1];\n\n\t\treturn isDefined(x) ? x : null;\n\t},\n\n\t/**\n\t * Get base value isAreaRangeType\n\t * @param data Data object\n\t * @return {Number}\n\t * @private\n\t */\n\tgetBaseValue(data) {\n\t\tconst $$ = this;\n\t\tlet value = data.value;\n\n\t\t// In case of area-range, data is given as: [low, mid, high] or {low, mid, high}\n\t\t// will take the 'mid' as the base value\n\t\tif (value) {\n\t\t\tif ($$.isAreaRangeType(data)) {\n\t\t\t\tvalue = $$.getAreaRangeData(data, \"mid\");\n\t\t\t} else if ($$.isBubbleZType(data)) {\n\t\t\t\tvalue = $$.getBubbleZData(value, \"y\");\n\t\t\t}\n\t\t}\n\t\treturn value;\n\t},\n\n\t/**\n\t * Get min/max value from the data\n\t * @private\n\t * @param {Array} data array data to be evaluated\n\t * @return {{min: {Number}, max: {Number}}}\n\t */\n\tgetMinMaxValue(data) {\n\t\tconst getBaseValue = this.getBaseValue.bind(this);\n\t\tlet min;\n\t\tlet max;\n\n\t\t(data || this.data.targets.map(t => t.values))\n\t\t\t.forEach((v, i) => {\n\t\t\t\tconst value = v.map(getBaseValue).filter(isNumber);\n\n\t\t\t\tmin = Math.min(i ? min : Infinity, ...value);\n\t\t\t\tmax = Math.max(i ? max : -Infinity, ...value);\n\t\t\t});\n\n\t\treturn {min, max};\n\t},\n\n\t/**\n\t * Get the min/max data\n\t * @private\n\t * @return {{min: Array, max: Array}}\n\t */\n\tgetMinMaxData() {\n\t\tconst $$ = this;\n\t\tconst cacheKey = \"$minMaxData\";\n\t\tlet minMaxData = $$.getCache(cacheKey);\n\n\t\tif (!minMaxData) {\n\t\t\tconst data = $$.data.targets.map(t => t.values);\n\t\t\tconst minMax = $$.getMinMaxValue(data);\n\n\t\t\tlet min = [];\n\t\t\tlet max = [];\n\n\t\t\tdata.forEach(v => {\n\t\t\t\tconst minData = $$.getFilteredDataByValue(v, minMax.min);\n\t\t\t\tconst maxData = $$.getFilteredDataByValue(v, minMax.max);\n\n\t\t\t\tif (minData.length) {\n\t\t\t\t\tmin = min.concat(minData);\n\t\t\t\t}\n\n\t\t\t\tif (maxData.length) {\n\t\t\t\t\tmax = max.concat(maxData);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// update the cached data\n\t\t\t$$.addCache(cacheKey, minMaxData = {min, max});\n\t\t}\n\n\t\treturn minMaxData;\n\t},\n\n\t/**\n\t * Get sum of data per index\n\t * @private\n\t * @return {Array}\n\t */\n\tgetTotalPerIndex() {\n\t\tconst $$ = this;\n\t\tconst cacheKey = \"$totalPerIndex\";\n\t\tlet sum = $$.getCache(cacheKey);\n\n\t\tif ($$.isStackNormalized() && !sum) {\n\t\t\tsum = [];\n\n\t\t\t$$.data.targets.forEach(row => {\n\t\t\t\trow.values.forEach((v, i) => {\n\t\t\t\t\tif (!sum[i]) {\n\t\t\t\t\t\tsum[i] = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tsum[i] += isNumber(v.value) ? v.value : 0;\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\treturn sum;\n\t},\n\n\t/**\n\t * Get total data sum\n\t * @return {Number}\n \t * @private\n\t */\n\tgetTotalDataSum() {\n\t\tconst $$ = this;\n\t\tconst cacheKey = \"$totalDataSum\";\n\t\tlet totalDataSum = $$.getCache(cacheKey);\n\n\t\tif (!totalDataSum) {\n\t\t\tconst total = mergeArray($$.data.targets.map(t => t.values))\n\t\t\t\t.map(v => v.value)\n\t\t\t\t.reduce((p, c) => p + c);\n\n\t\t\t$$.addCache(cacheKey, totalDataSum = total);\n\t\t}\n\n\t\treturn totalDataSum;\n\t},\n\n\t/**\n\t * Get filtered data by value\n\t * @param {Object} data\n\t * @param {Number} value\n\t * @return {Array} filtered array data\n\t * @private\n\t */\n\tgetFilteredDataByValue(data, value) {\n\t\treturn data.filter(t => this.getBaseValue(t) === value);\n\t},\n\n\t/**\n\t * Return the max length of the data\n\t * @return {Number} max data length\n\t * @private\n\t */\n\tgetMaxDataCount() {\n\t\treturn Math.max(...this.data.targets.map(t => t.values.length));\n\t},\n\n\tgetMaxDataCountTarget() {\n\t\tlet target = this.filterTargetsToShow() || [];\n\t\tconst length = target.length;\n\n\t\tif (length > 1) {\n\t\t\ttarget = target.map(t => t.values)\n\t\t\t\t.reduce((a, b) => a.concat(b))\n\t\t\t\t.map(v => v.x);\n\n\t\t\ttarget = sortValue(getUnique(target))\n\t\t\t\t.map((x, index) => ({x, index}));\n\t\t} else if (length) {\n\t\t\ttarget = target[0].values;\n\t\t}\n\n\t\treturn target;\n\t},\n\n\tmapToIds(targets) {\n\t\treturn targets.map(d => d.id);\n\t},\n\n\tmapToTargetIds(ids) {\n\t\tconst $$ = this;\n\n\t\treturn ids ? (isArray(ids) ? ids.concat() : [ids]) : $$.mapToIds($$.data.targets);\n\t},\n\n\thasTarget(targets, id) {\n\t\tconst ids = this.mapToIds(targets);\n\n\t\tfor (let i = 0, val; (val = ids[i]); i++) {\n\t\t\tif (val === id) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tisTargetToShow(targetId) {\n\t\treturn this.hiddenTargetIds.indexOf(targetId) < 0;\n\t},\n\n\tisLegendToShow(targetId) {\n\t\treturn this.hiddenLegendIds.indexOf(targetId) < 0;\n\t},\n\n\tfilterTargetsToShow(targets) {\n\t\tconst $$ = this;\n\n\t\treturn (targets || $$.data.targets).filter(t => $$.isTargetToShow(t.id));\n\t},\n\n\tmapTargetsToUniqueXs(targets) {\n\t\tconst $$ = this;\n\t\tlet xs = [];\n\n\t\tif (targets && targets.length) {\n\t\t\txs = getUnique(\n\t\t\t\tmergeArray(targets.map(t => t.values.map(v => +v.x)))\n\t\t\t);\n\n\t\t\txs = $$.isTimeSeries() ? xs.map(x => new Date(+x)) : xs.map(x => +x);\n\t\t}\n\n\t\treturn sortValue(xs);\n\t},\n\n\taddHiddenTargetIds(targetIds) {\n\t\tthis.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);\n\t},\n\n\tremoveHiddenTargetIds(targetIds) {\n\t\tthis.hiddenTargetIds = this.hiddenTargetIds.filter(id => targetIds.indexOf(id) < 0);\n\t},\n\n\taddHiddenLegendIds(targetIds) {\n\t\tthis.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);\n\t},\n\n\tremoveHiddenLegendIds(targetIds) {\n\t\tthis.hiddenLegendIds = this.hiddenLegendIds.filter(id => targetIds.indexOf(id) < 0);\n\t},\n\n\tgetValuesAsIdKeyed(targets) {\n\t\tconst $$ = this;\n\t\tconst ys = {};\n\t\tconst isMultipleX = $$.isMultipleX();\n\t\tconst xs = isMultipleX ? $$.mapTargetsToUniqueXs(targets)\n\t\t\t.map(v => (isString(v) ? v : +v)) : null;\n\n\t\ttargets.forEach(t => {\n\t\t\tconst data = [];\n\n\t\t\tt.values.forEach(v => {\n\t\t\t\tconst value = v.value;\n\n\t\t\t\tif (isArray(value)) {\n\t\t\t\t\tdata.push(...value);\n\t\t\t\t} else if (isObject(value) && \"high\" in value) {\n\t\t\t\t\tdata.push(...Object.values(value));\n\t\t\t\t} else if ($$.isBubbleZType(v)) {\n\t\t\t\t\tdata.push($$.getBubbleZData(value, \"y\"));\n\t\t\t\t} else {\n\t\t\t\t\tif (isMultipleX) {\n\t\t\t\t\t\tdata[$$.getIndexByX(v.x, xs)] = value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata.push(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tys[t.id] = data;\n\t\t});\n\n\t\treturn ys;\n\t},\n\n\tcheckValueInTargets(targets, checker) {\n\t\tconst ids = Object.keys(targets);\n\t\tlet values;\n\n\t\tfor (let i = 0; i < ids.length; i++) {\n\t\t\tvalues = targets[ids[i]].values;\n\n\t\t\tfor (let j = 0; j < values.length; j++) {\n\t\t\t\tif (checker(values[j].value)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\thasMultiTargets() {\n\t\treturn this.filterTargetsToShow().length > 1;\n\t},\n\n\thasNegativeValueInTargets(targets) {\n\t\treturn this.checkValueInTargets(targets, v => v < 0);\n\t},\n\n\thasPositiveValueInTargets(targets) {\n\t\treturn this.checkValueInTargets(targets, v => v > 0);\n\t},\n\n\t_checkOrder(type) {\n\t\tconst config = this.config;\n\t\tconst order = config.data_order;\n\n\t\treturn isString(order) && order.toLowerCase() === type;\n\t},\n\n\tisOrderDesc() {\n\t\treturn this._checkOrder(\"desc\");\n\t},\n\n\tisOrderAsc() {\n\t\treturn this._checkOrder(\"asc\");\n\t},\n\n\t/**\n\t * Sort targets data\n\t * @param {Array} targetsValue\n\t * @return {Array}\n\t * @private\n\t */\n\torderTargets(targetsValue) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst targets = [...targetsValue];\n\t\tconst orderAsc = $$.isOrderAsc();\n\t\tconst orderDesc = $$.isOrderDesc();\n\n\t\tif (orderAsc || orderDesc) {\n\t\t\ttargets.sort((t1, t2) => {\n\t\t\t\tconst reducer = (p, c) => p + Math.abs(c.value);\n\t\t\t\tconst t1Sum = t1.values.reduce(reducer, 0);\n\t\t\t\tconst t2Sum = t2.values.reduce(reducer, 0);\n\n\t\t\t\treturn orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;\n\t\t\t});\n\t\t} else if (isFunction(config.data_order)) {\n\t\t\ttargets.sort(config.data_order);\n\t\t} // TODO: accept name array for order\n\n\t\treturn targets;\n\t},\n\n\tfilterByX(targets, x) {\n\t\treturn mergeArray(targets.map(t => t.values)).filter(v => v.x - x === 0);\n\t},\n\n\tfilterRemoveNull(data) {\n\t\treturn data.filter(d => isValue(this.getBaseValue(d)));\n\t},\n\n\tfilterByXDomain(targets, xDomain) {\n\t\treturn targets.map(t => ({\n\t\t\tid: t.id,\n\t\t\tid_org: t.id_org,\n\t\t\tvalues: t.values.filter(v => xDomain[0] <= v.x && v.x <= xDomain[1])\n\t\t}));\n\t},\n\n\thasDataLabel() {\n\t\tconst dataLabels = this.config.data_labels;\n\n\t\treturn (isBoolean(dataLabels) && dataLabels) ||\n\t\t\t(isObjectType(dataLabels) && notEmpty(dataLabels));\n\t},\n\n\tgetDataLabelLength(min, max, key) {\n\t\tconst $$ = this;\n\t\tconst lengths = [0, 0];\n\t\tconst paddingCoef = 1.3;\n\n\t\t$$.selectChart.select(\"svg\").selectAll(\".dummy\")\n\t\t\t.data([min, max])\n\t\t\t.enter()\n\t\t\t.append(\"text\")\n\t\t\t.text(d => $$.dataLabelFormat(d.id)(d))\n\t\t\t.each(function(d, i) {\n\t\t\t\tlengths[i] = this.getBoundingClientRect()[key] * paddingCoef;\n\t\t\t})\n\t\t\t.remove();\n\n\t\treturn lengths;\n\t},\n\n\tisNoneArc(d) {\n\t\treturn this.hasTarget(this.data.targets, d.id);\n\t},\n\n\tisArc(d) {\n\t\treturn \"data\" in d && this.hasTarget(this.data.targets, d.data.id);\n\t},\n\n\tfindSameXOfValues(values, index) {\n\t\tconst targetX = values[index].x;\n\t\tconst sames = [];\n\t\tlet i;\n\n\t\tfor (i = index - 1; i >= 0; i--) {\n\t\t\tif (targetX !== values[i].x) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tsames.push(values[i]);\n\t\t}\n\n\t\tfor (i = index; i < values.length; i++) {\n\t\t\tif (targetX !== values[i].x) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tsames.push(values[i]);\n\t\t}\n\n\t\treturn sames;\n\t},\n\n\tfindClosestFromTargets(targets, pos) {\n\t\tconst $$ = this;\n\t\tconst candidates = targets.map(target => $$.findClosest(target.values, pos)); // map to array of closest points of each target\n\n\t\t// decide closest point and return\n\t\treturn $$.findClosest(candidates, pos);\n\t},\n\n\tfindClosest(values, pos) {\n\t\tconst $$ = this;\n\t\tconst data = values.filter(v => v && isValue(v.value));\n\t\tlet minDist = $$.config.point_sensitivity;\n\t\tlet closest;\n\n\t\t// find mouseovering bar\n\t\tdata\n\t\t\t.filter(v => $$.isBarType(v.id))\n\t\t\t.forEach(v => {\n\t\t\t\tconst shape = $$.main.select(`.${CLASS.bars}${$$.getTargetSelectorSuffix(v.id)} .${CLASS.bar}-${v.index}`).node();\n\n\t\t\t\tif (!closest && $$.isWithinBar(shape)) {\n\t\t\t\t\tclosest = v;\n\t\t\t\t}\n\t\t\t});\n\n\t\t// find closest point from non-bar\n\t\tdata\n\t\t\t.filter(v => !$$.isBarType(v.id))\n\t\t\t.forEach(v => {\n\t\t\t\tconst d = $$.dist(v, pos);\n\n\t\t\t\tif (d < minDist) {\n\t\t\t\t\tminDist = d;\n\t\t\t\t\tclosest = v;\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn closest;\n\t},\n\n\tdist(data, pos) {\n\t\tconst $$ = this;\n\t\tconst isRotated = $$.config.axis_rotated;\n\n\t\tconst xIndex = isRotated ? 1 : 0;\n\t\tconst yIndex = isRotated ? 0 : 1;\n\t\tconst y = $$.circleY(data, data.index);\n\t\tconst x = ($$.zoomScale || $$.x)(data.x);\n\n\t\treturn Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));\n\t},\n\n\t/**\n\t * Convert data for step type\n\t * @param {Array} values Object data values\n\t * @return {Array}\n\t * @private\n\t */\n\tconvertValuesToStep(values) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst stepType = config.line_step_type;\n\t\tconst isCategorized = $$.isCategorized();\n\n\t\tconst converted = isArray(values) ? values.concat() : [values];\n\n\t\tif (!isRotated && !isCategorized) {\n\t\t\treturn values;\n\t\t}\n\n\t\t// insert & append cloning first/last value to be fully rendered covering on each gap sides\n\t\tconst id = converted[0].id;\n\n\t\t// insert\n\t\tlet x = converted[0].x - 1;\n\t\tlet value = converted[0].value;\n\n\t\tisCategorized && converted.unshift({x, value, id});\n\n\t\tstepType === \"step-after\" &&\n\t\t\tconverted.unshift({x: x - 1, value, id});\n\n\t\t// append\n\t\tx = converted.length;\n\t\tvalue = converted[x - 1].value;\n\n\t\tisCategorized && converted.push({x, value, id});\n\n\t\tstepType === \"step-before\" &&\n\t\t\tconverted.push({x: x + 1, value, id});\n\n\t\treturn converted;\n\t},\n\n\tconvertValuesToRange(values) {\n\t\tconst converted = isArray(values) ? values.concat() : [values];\n\t\tconst ranges = [];\n\n\t\tconverted.forEach(range => {\n\t\t\tconst {x, id} = range;\n\n\t\t\tranges.push({\n\t\t\t\tx,\n\t\t\t\tid,\n\t\t\t\tvalue: range.value[0]\n\t\t\t});\n\n\t\t\tranges.push({\n\t\t\t\tx,\n\t\t\t\tid,\n\t\t\t\tvalue: range.value[2]\n\t\t\t});\n\t\t});\n\n\t\treturn ranges;\n\t},\n\n\tupdateDataAttributes(name, attrs) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst current = config[`data_${name}`];\n\n\t\tif (isUndefined(attrs)) {\n\t\t\treturn current;\n\t\t}\n\n\t\tObject.keys(attrs).forEach(id => {\n\t\t\tcurrent[id] = attrs[id];\n\t\t});\n\n\t\t$$.redraw({withLegend: true});\n\n\t\treturn current;\n\t},\n\n\tgetAreaRangeData(d, type) {\n\t\tconst value = d.value;\n\n\t\tif (isArray(value)) {\n\t\t\tconst index = [\"high\", \"mid\", \"low\"].indexOf(type);\n\n\t\t\treturn index === -1 ? null : value[index];\n\t\t}\n\n\t\treturn value[type];\n\t},\n\n\t/**\n\t * Get ratio value\n\t * @param {String} type Ratio for given type\n\t * @param {Object} d Data value object\n\t * @param {Boolean} asPercent Convert the return as percent or not\n\t * @return {Number} Ratio value\n\t * @private\n\t */\n\tgetRatio(type, d, asPercent) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst api = $$.api;\n\t\tlet ratio = 0;\n\n\t\tif (d && api.data.shown.call(api).length) {\n\t\t\tconst dataValues = api.data.values.bind(api);\n\n\t\t\tratio = d.ratio || d.value;\n\n\t\t\tif (type === \"arc\") {\n\t\t\t\t// if has padAngle set, calculate rate based on value\n\t\t\t\tif ($$.pie.padAngle()()) {\n\t\t\t\t\tlet total = $$.getTotalDataSum();\n\n\t\t\t\t\tif ($$.hiddenTargetIds.length) {\n\t\t\t\t\t\ttotal -= dataValues($$.hiddenTargetIds).reduce((p, c) => p + c);\n\t\t\t\t\t}\n\n\t\t\t\t\tratio = d.value / total;\n\n\t\t\t\t\t// otherwise, based on the rendered angle value\n\t\t\t\t} else {\n\t\t\t\t\tratio = (d.endAngle - d.startAngle) / (\n\t\t\t\t\t\tMath.PI * ($$.hasType(\"gauge\") && !config.gauge_fullCircle ? 1 : 2)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (type === \"index\") {\n\t\t\t\tlet total = this.getTotalPerIndex();\n\n\t\t\t\tif ($$.hiddenTargetIds.length) {\n\t\t\t\t\tlet hiddenSum = dataValues($$.hiddenTargetIds, false);\n\n\t\t\t\t\tif (hiddenSum.length) {\n\t\t\t\t\t\thiddenSum = hiddenSum\n\t\t\t\t\t\t\t.reduce((acc, curr) => acc.map((v, i) => (isNumber(v) ? v : 0) + curr[i]));\n\n\t\t\t\t\t\ttotal = total.map((v, i) => v - hiddenSum[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\td.ratio = isNumber(d.value) && total && total[d.index] > 0 ?\n\t\t\t\t\td.value / total[d.index] : 0;\n\n\t\t\t\tratio = d.ratio;\n\t\t\t} else if (type === \"radar\") {\n\t\t\t\tratio = (parseFloat(Math.max(d.value, 0)) / $$.maxValue) * config.radar_size_ratio;\n\t\t\t}\n\t\t}\n\n\t\treturn asPercent && ratio ? ratio * 100 : ratio;\n\t},\n\n\t/**\n\t * Sort data index to be aligned with x axis.\n\t * @param {Array} tickValues Tick array values\n\t * @private\n\t */\n\tupdateDataIndexByX(tickValues) {\n\t\tconst $$ = this;\n\n\t\tconst tickValueMap = tickValues.reduce((out, tick, index) => {\n\t\t\tout[Number(tick.x)] = index;\n\t\t\treturn out;\n\t\t}, {});\n\n\t\t$$.data.targets.forEach(t => {\n\t\t\tt.values.forEach((value, valueIndex) => {\n\t\t\t\tlet index = tickValueMap[Number(value.x)];\n\n\t\t\t\tif (index === undefined) {\n\t\t\t\t\tindex = valueIndex;\n\t\t\t\t}\n\t\t\t\tvalue.index = index;\n\t\t\t});\n\t\t});\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tcsvParse as d3CsvParse,\n\ttsvParse as d3TsvParse,\n\tcsvParseRows as d3CsvParseRows,\n\ttsvParseRows as d3TsvParseRows,\n} from \"d3-dsv\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {isUndefined, isDefined, isObject, isValue, notEmpty, extend, isArray, capitalize} from \"../internals/util\";\n\n/**\n * Convert CSV/TSV data\n * @param {Object} parser Parser object\n * @param {Object} xsv Data\n * @private\n * @return {Object}\n */\nconst convertCsvTsvToData = (parser, xsv) => {\n\tconst rows = parser.rows(xsv);\n\tlet d;\n\n\tif (rows.length === 1) {\n\t\td = [{}];\n\n\t\trows[0].forEach(id => {\n\t\t\td[0][id] = null;\n\t\t});\n\t} else {\n\t\td = parser.parse(xsv);\n\t}\n\n\treturn d;\n};\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Convert data according its type\n\t * @param {Object} args data object\n\t * @param {Function} [callback] callback for url(XHR) type loading\n\t * @return {Object}\n\t * @private\n\t */\n\tconvertData(args, callback) {\n\t\tconst $$ = this;\n\t\tlet data;\n\n\t\tif (args.bindto) {\n\t\t\tdata = {};\n\n\t\t\t[\"url\", \"mimeType\", \"headers\", \"keys\", \"json\", \"keys\", \"rows\", \"columns\"]\n\t\t\t\t.forEach(v => {\n\t\t\t\t\tconst key = `data_${v}`;\n\n\t\t\t\t\tif (key in args) {\n\t\t\t\t\t\tdata[v] = args[key];\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t} else {\n\t\t\tdata = args;\n\t\t}\n\n\t\tif (data.url && callback) {\n\t\t\t$$.convertUrlToData(data.url, data.mimeType, data.headers, data.keys, callback);\n\t\t} else if (data.json) {\n\t\t\tdata = $$.convertJsonToData(data.json, data.keys);\n\t\t} else if (data.rows) {\n\t\t\tdata = $$.convertRowsToData(data.rows);\n\t\t} else if (data.columns) {\n\t\t\tdata = $$.convertColumnsToData(data.columns);\n\t\t} else if (args.bindto) {\n\t\t\tthrow Error(\"url or json or rows or columns is required.\");\n\t\t}\n\n\t\treturn isArray(data) && data;\n\t},\n\n\t/**\n\t * Convert URL data\n\t * @param {String} url Remote URL\n\t * @param {String} mimeType MIME type string: json | csv | tsv\n\t * @param {Object} headers Header object\n\t * @param {Object} keys Key object\n\t * @param {Function} done Callback function\n\t * @private\n\t */\n\tconvertUrlToData(url, mimeType = \"csv\", headers, keys, done) {\n\t\tconst req = new XMLHttpRequest();\n\n\t\treq.open(\"GET\", url);\n\n\t\tif (headers) {\n\t\t\tObject.keys(headers).forEach(key => {\n\t\t\t\treq.setRequestHeader(key, headers[key]);\n\t\t\t});\n\t\t}\n\n\t\treq.onreadystatechange = () => {\n\t\t\tif (req.readyState === 4) {\n\t\t\t\tif (req.status === 200) {\n\t\t\t\t\tconst response = req.responseText;\n\n\t\t\t\t\tresponse && done.call(this,\n\t\t\t\t\t\tthis[`convert${capitalize(mimeType)}ToData`](\n\t\t\t\t\t\t\tmimeType === \"json\" ? JSON.parse(response) : response,\n\t\t\t\t\t\t\tkeys\n\t\t\t\t\t\t));\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(`${url}: Something went wrong loading!`);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\treq.send();\n\t},\n\n\tconvertCsvToData(xsv) {\n\t\treturn convertCsvTsvToData({\n\t\t\trows: d3CsvParseRows,\n\t\t\tparse: d3CsvParse\n\t\t}, xsv);\n\t},\n\n\tconvertTsvToData(tsv) {\n\t\treturn convertCsvTsvToData({\n\t\t\trows: d3TsvParseRows,\n\t\t\tparse: d3TsvParse\n\t\t}, tsv);\n\t},\n\n\tconvertJsonToData(json, keysParam) {\n\t\tconst config = this.config;\n\t\tconst newRows = [];\n\t\tlet targetKeys;\n\t\tlet data;\n\n\t\tif (isArray(json)) {\n\t\t\tconst keys = keysParam || config.data_keys;\n\n\t\t\tif (keys.x) {\n\t\t\t\ttargetKeys = keys.value.concat(keys.x);\n\t\t\t\tconfig.data_x = keys.x;\n\t\t\t} else {\n\t\t\t\ttargetKeys = keys.value;\n\t\t\t}\n\n\t\t\tnewRows.push(targetKeys);\n\n\t\t\tjson.forEach(o => {\n\t\t\t\tconst newRow = targetKeys.map(key => {\n\t\t\t\t\t// convert undefined to null because undefined data will be removed in convertDataToTargets()\n\t\t\t\t\tlet v = this.findValueInJson(o, key);\n\n\t\t\t\t\tif (isUndefined(v)) {\n\t\t\t\t\t\tv = null;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn v;\n\t\t\t\t});\n\n\t\t\t\tnewRows.push(newRow);\n\t\t\t});\n\n\t\t\tdata = this.convertRowsToData(newRows);\n\t\t} else {\n\t\t\tObject.keys(json).forEach(key => {\n\t\t\t\tconst tmp = json[key].concat();\n\n\t\t\t\ttmp.unshift(key);\n\t\t\t\tnewRows.push(tmp);\n\t\t\t});\n\n\t\t\tdata = this.convertColumnsToData(newRows);\n\t\t}\n\n\t\treturn data;\n\t},\n\n\tfindValueInJson(object, path) {\n\t\tif (object[path] !== undefined) {\n\t\t\treturn object[path];\n\t\t}\n\n\t\tconst convertedPath = path.replace(/\\[(\\w+)\\]/g, \".$1\"); // convert indexes to properties (replace [] with .)\n\t\tconst pathArray = convertedPath.replace(/^\\./, \"\").split(\".\"); // strip a leading dot\n\t\tlet target = object;\n\n\t\tpathArray.some(k => !(\n\t\t\ttarget = target && k in target ?\n\t\t\t\ttarget[k] : undefined\n\t\t));\n\n\t\treturn target;\n\t},\n\n\tconvertRowsToData(rows) {\n\t\tconst keys = rows[0];\n\t\tconst newRows = [];\n\n\t\trows.forEach((row, i) => {\n\t\t\tif (i > 0) {\n\t\t\t\tconst newRow = {};\n\n\t\t\t\trow.forEach((v, j) => {\n\t\t\t\t\tif (isUndefined(v)) {\n\t\t\t\t\t\tthrow new Error(`Source data is missing a component at (${i}, ${j})!`);\n\t\t\t\t\t}\n\n\t\t\t\t\tnewRow[keys[j]] = v;\n\t\t\t\t});\n\n\t\t\t\tnewRows.push(newRow);\n\t\t\t}\n\t\t});\n\n\t\treturn newRows;\n\t},\n\n\tconvertColumnsToData(columns) {\n\t\tconst newRows = [];\n\n\t\tcolumns.forEach((col, i) => {\n\t\t\tconst key = col[0];\n\n\t\t\tcol.forEach((v, j) => {\n\t\t\t\tif (j > 0) {\n\t\t\t\t\tif (isUndefined(newRows[j - 1])) {\n\t\t\t\t\t\tnewRows[j - 1] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isUndefined(v)) {\n\t\t\t\t\t\tthrow new Error(`Source data is missing a component at (${i}, ${j})!`);\n\t\t\t\t\t}\n\n\t\t\t\t\tnewRows[j - 1][key] = v;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\treturn newRows;\n\t},\n\n\tconvertDataToTargets(data, appendXs) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isTimeSeries = $$.isTimeSeries();\n\n\t\tconst dataKeys = Object.keys(data[0] || {});\n\t\tconst ids = dataKeys.length ? dataKeys.filter($$.isNotX, $$) : [];\n\t\tconst xs = dataKeys.length ? dataKeys.filter($$.isX, $$) : [];\n\n\t\tlet xsData;\n\n\t\t// save x for update data by load when custom x and bb.x API\n\t\tids.forEach(id => {\n\t\t\tconst xKey = this.getXKey(id);\n\n\t\t\tif (this.isCustomX() || isTimeSeries) {\n\t\t\t\t// if included in input data\n\t\t\t\tif (xs.indexOf(xKey) >= 0) {\n\t\t\t\t\txsData = ((appendXs && $$.data.xs[id]) || [])\n\t\t\t\t\t\t.concat(\n\t\t\t\t\t\t\tdata.map(d => d[xKey])\n\t\t\t\t\t\t\t\t.filter(isValue)\n\t\t\t\t\t\t\t\t.map((rawX, i) => $$.generateTargetX(rawX, id, i))\n\t\t\t\t\t\t);\n\t\t\t\t} else if (config.data_x) {\n\t\t\t\t\t// if not included in input data, find from preloaded data of other id's x\n\t\t\t\t\txsData = this.getOtherTargetXs();\n\t\t\t\t} else if (notEmpty(config.data_xs)) {\n\t\t\t\t\t// if not included in input data, find from preloaded data\n\t\t\t\t\txsData = $$.getXValuesOfXKey(xKey, $$.data.targets);\n\t\t\t\t}\n\t\t\t\t// MEMO: if no x included, use same x of current will be used\n\t\t\t} else {\n\t\t\t\txsData = data.map((d, i) => i);\n\t\t\t}\n\n\t\t\txsData && (this.data.xs[id] = xsData);\n\t\t});\n\n\t\t// check x is defined\n\t\tids.forEach(id => {\n\t\t\tif (!this.data.xs[id]) {\n\t\t\t\tthrow new Error(`x is not defined for id = \"${id}\".`);\n\t\t\t}\n\t\t});\n\n\t\t// convert to target\n\t\tconst targets = ids.map((id, index) => {\n\t\t\tconst convertedId = config.data_idConverter(id);\n\t\t\tconst xKey = $$.getXKey(id);\n\t\t\tconst isCategorized = $$.isCustomX() && $$.isCategorized();\n\t\t\tconst hasCategory = isCategorized && data.map(v => v.x)\n\t\t\t\t.every(v => config.axis_x_categories.indexOf(v) > -1);\n\n\t\t\treturn {\n\t\t\t\tid: convertedId,\n\t\t\t\tid_org: id,\n\t\t\t\tvalues: data.map((d, i) => {\n\t\t\t\t\tconst rawX = d[xKey];\n\t\t\t\t\tlet value = d[id];\n\t\t\t\t\tlet x;\n\n\t\t\t\t\tvalue = value !== null && !isNaN(value) && !isObject(value) ?\n\t\t\t\t\t\t+value : (isArray(value) || isObject(value) ? value : null);\n\n\t\t\t\t\t// use x as categories if custom x and categorized\n\t\t\t\t\tif (isCategorized && index === 0 && !isUndefined(rawX)) {\n\t\t\t\t\t\tif (!hasCategory && index === 0 && i === 0) {\n\t\t\t\t\t\t\tconfig.axis_x_categories = [];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tx = config.axis_x_categories.indexOf(rawX);\n\n\t\t\t\t\t\tif (x === -1) {\n\t\t\t\t\t\t\tx = config.axis_x_categories.length;\n\t\t\t\t\t\t\tconfig.axis_x_categories.push(rawX);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tx = $$.generateTargetX(rawX, id, i);\n\t\t\t\t\t}\n\n\t\t\t\t\t// mark as x = undefined if value is undefined and filter to remove after mapped\n\t\t\t\t\tif (isUndefined(value) || $$.data.xs[id].length <= i) {\n\t\t\t\t\t\tx = undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {x, value, id: convertedId};\n\t\t\t\t}).filter(v => isDefined(v.x))\n\t\t\t};\n\t\t});\n\n\t\t// finish targets\n\t\ttargets.forEach(t => {\n\t\t\t// sort values by its x\n\t\t\tif (config.data_xSort) {\n\t\t\t\tt.values = t.values.sort((v1, v2) => {\n\t\t\t\t\tconst x1 = v1.x || v1.x === 0 ? v1.x : Infinity;\n\t\t\t\t\tconst x2 = v2.x || v2.x === 0 ? v2.x : Infinity;\n\n\t\t\t\t\treturn x1 - x2;\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// indexing each value\n\t\t\tt.values.forEach((v, i) => (v.index = i));\n\n\t\t\t// this needs to be sorted because its index and value.index is identical\n\t\t\t$$.data.xs[t.id].sort((v1, v2) => v1 - v2);\n\t\t});\n\n\t\t// cache information about values\n\t\t$$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);\n\t\t$$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);\n\n\t\t// set target types\n\t\tif (config.data_type) {\n\t\t\t$$.setTargetType($$.mapToIds(targets)\n\t\t\t\t.filter(id => !(id in config.data_types)), config.data_type);\n\t\t}\n\n\t\t// cache as original id keyed\n\t\ttargets.forEach(d => $$.addCache(d.id_org, d, true));\n\n\t\treturn targets;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {extend} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tload(rawTargets, args) {\n\t\tconst $$ = this;\n\t\tlet targets = rawTargets;\n\n\t\tif (targets) {\n\t\t\t// filter loading targets if needed\n\t\t\tif (args.filter) {\n\t\t\t\ttargets = targets.filter(args.filter);\n\t\t\t}\n\n\t\t\t// set type if args.types || args.type specified\n\t\t\tif (args.type || args.types) {\n\t\t\t\ttargets.forEach(t => {\n\t\t\t\t\tconst type = (args.types && args.types[t.id]) || args.type;\n\n\t\t\t\t\t$$.setTargetType(t.id, type);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Update/Add data\n\t\t\t$$.data.targets.forEach(d => {\n\t\t\t\tfor (let i = 0; i < targets.length; i++) {\n\t\t\t\t\tif (d.id === targets[i].id) {\n\t\t\t\t\t\td.values = targets[i].values;\n\t\t\t\t\t\ttargets.splice(i, 1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t$$.data.targets = $$.data.targets.concat(targets); // add remained\n\t\t}\n\n\t\t// Set targets\n\t\t$$.updateTargets($$.data.targets);\n\n\t\t// Redraw with new targets\n\t\t$$.redraw({\n\t\t\twithUpdateOrgXDomain: true,\n\t\t\twithUpdateXDomain: true,\n\t\t\twithLegend: true\n\t\t});\n\n\t\targs.done && args.done();\n\t},\n\n\tloadFromArgs(args) {\n\t\tconst $$ = this;\n\n\t\t// prevent load when chart is already destroyed\n\t\tif (!$$.config) {\n\t\t\treturn;\n\t\t}\n\n\t\t// reset internally cached data\n\t\t$$.resetCache();\n\n\t\tconst data = args.data || $$.convertData(args, d => $$.load($$.convertDataToTargets(d), args));\n\n\t\tdata && $$.load($$.convertDataToTargets(data), args);\n\t},\n\n\tunload(rawTargetIds, customDoneCb) {\n\t\tconst $$ = this;\n\t\tlet done = customDoneCb;\n\t\tlet targetIds = rawTargetIds;\n\n\t\t// reset internally cached data\n\t\t$$.resetCache();\n\n\t\tif (!done) {\n\t\t\tdone = () => {};\n\t\t}\n\n\t\t// filter existing target\n\t\ttargetIds = targetIds.filter(id => $$.hasTarget($$.data.targets, id));\n\n\t\t// If no target, call done and return\n\t\tif (!targetIds || targetIds.length === 0) {\n\t\t\tdone();\n\t\t\treturn;\n\t\t}\n\n\t\t$$.svg.selectAll(targetIds.map(id => $$.selectorTarget(id)))\n\t\t\t.transition()\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove()\n\t\t\t.call($$.endall, done);\n\n\t\ttargetIds.forEach(id => {\n\t\t\t// Reset fadein for future load\n\t\t\t$$.withoutFadeIn[id] = false;\n\t\t\t// Remove target's elements\n\t\t\tif ($$.legend) {\n\t\t\t\t$$.legend.selectAll(`.${CLASS.legendItem}${$$.getTargetSelectorSuffix(id)}`).remove();\n\t\t\t}\n\t\t\t// Remove target\n\t\t\t$$.data.targets = $$.data.targets.filter(t => t.id !== id);\n\t\t});\n\t}\n});\n\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Category Name\n\t * @private\n\t * @param {Number} index\n\t * @returns {String} gategory Name\n\t */\n\tcategoryName(i) {\n\t\tconst config = this.config;\n\n\t\treturn i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tmouse as d3Mouse,\n\tselect as d3Select,\n\tevent as d3Event\n} from \"d3-selection\";\nimport {drag as d3Drag} from \"d3-drag\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {document} from \"../internals/browser\";\nimport CLASS from \"../config/classes\";\nimport {emulateEvent, extend, isBoolean, isNumber, isObject} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initialize the area that detects the event.\n\t * Add a container for the zone that detects the event.\n\t * @private\n\t */\n\tinitEventRect() {\n\t\tconst $$ = this;\n\n\t\t$$.main.select(`.${CLASS.chart}`)\n\t\t\t.append(\"g\")\n\t\t\t.attr(\"class\", CLASS.eventRects)\n\t\t\t.style(\"fill-opacity\", \"0\");\n\t},\n\n\t/**\n\t * Redraws the area that detects the event.\n\t * @private\n\t */\n\tredrawEventRect() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isMultipleX = $$.isMultipleX();\n\t\tlet eventRectUpdate;\n\n\t\tconst zoomEnabled = config.zoom_enabled;\n\t\tconst eventRects = $$.main.select(`.${CLASS.eventRects}`)\n\t\t\t.style(\"cursor\", zoomEnabled && zoomEnabled.type !== \"drag\" ? (\n\t\t\t\tconfig.axis_rotated ? \"ns-resize\" : \"ew-resize\"\n\t\t\t) : null)\n\t\t\t.classed(CLASS.eventRectsMultiple, isMultipleX)\n\t\t\t.classed(CLASS.eventRectsSingle, !isMultipleX);\n\n\t\t// clear old rects\n\t\teventRects.selectAll(`.${CLASS.eventRect}`).remove();\n\n\t\t// open as public constiable\n\t\t$$.eventRect = eventRects.selectAll(`.${CLASS.eventRect}`);\n\n\t\tif (isMultipleX) {\n\t\t\teventRectUpdate = $$.eventRect.data([0]);\n\t\t\t// update\n\t\t\t// enter: only one rect will be added\n\t\t\t// exit: not needed because always only one rect exists\n\t\t\teventRectUpdate = $$.generateEventRectsForMultipleXs(eventRectUpdate.enter())\n\t\t\t\t.merge(eventRectUpdate);\n\t\t} else {\n\t\t\t// Set data and update $$.eventRect\n\t\t\tconst xAxisTickValues = $$.getMaxDataCountTarget();\n\n\t\t\t// update data's index value to be alinged with the x Axis\n\t\t\t$$.updateDataIndexByX(xAxisTickValues);\n\t\t\t$$.updateXs(xAxisTickValues);\n\t\t\t$$.updatePointClass(true);\n\n\t\t\teventRects.datum(xAxisTickValues);\n\n\t\t\t$$.eventRect = eventRects.selectAll(`.${CLASS.eventRect}`);\n\t\t\teventRectUpdate = $$.eventRect.data(d => d);\n\n\t\t\t// exit\n\t\t\teventRectUpdate.exit().remove();\n\n\t\t\t// update\n\t\t\teventRectUpdate = $$.generateEventRectsForSingleX(eventRectUpdate.enter())\n\t\t\t\t.merge(eventRectUpdate);\n\t\t}\n\n\t\t$$.eventRect = eventRectUpdate;\n\t\t$$.updateEventRect(eventRectUpdate);\n\n\t\tif ($$.inputType === \"touch\" && !$$.svg.on(\"touchstart.eventRect\") && !$$.hasArcType()) {\n\t\t\t$$.bindTouchOnEventRect(isMultipleX);\n\t\t}\n\t},\n\n\tbindTouchOnEventRect(isMultipleX) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst getEventRect = () => {\n\t\t\tconst touch = d3Event.changedTouches[0];\n\n\t\t\treturn d3Select(document.elementFromPoint(touch.clientX, touch.clientY));\n\t\t};\n\n\t\tconst getIndex = eventRect => {\n\t\t\tlet index = eventRect && eventRect.attr(\"class\") && eventRect.attr(\"class\")\n\t\t\t\t.replace(new RegExp(`(${CLASS.eventRect}-?|s)`, \"g\"), \"\") * 1;\n\n\t\t\tif (isNaN(index) || index === null) {\n\t\t\t\tindex = -1;\n\t\t\t}\n\n\t\t\treturn index;\n\t\t};\n\n\t\tconst selectRect = context => {\n\t\t\tif (isMultipleX) {\n\t\t\t\t$$.selectRectForMultipleXs(context);\n\t\t\t} else {\n\t\t\t\tconst eventRect = getEventRect();\n\t\t\t\tconst index = getIndex(eventRect);\n\n\t\t\t\t$$.callOverOutForTouch(index);\n\n\t\t\t\tindex === -1 ?\n\t\t\t\t\t$$.unselectRect() :\n\t\t\t\t\t$$.selectRectForSingle(context, eventRect, index);\n\t\t\t}\n\t\t};\n\n\t\t// call event.preventDefault()\n\t\t// according 'interaction.inputType.touch.preventDefault' option\n\t\tconst preventDefault = config.interaction_inputType_touch.preventDefault;\n\t\tconst isPrevented = (isBoolean(preventDefault) && preventDefault) || false;\n\t\tconst preventThreshold = (!isNaN(preventDefault) && preventDefault) || null;\n\t\tlet startPx;\n\n\t\tconst preventEvent = event => {\n\t\t\tconst eventType = event.type;\n\t\t\tconst touch = event.changedTouches[0];\n\t\t\tconst currentXY = touch[`client${config.axis_rotated ? \"Y\" : \"X\"}`];\n\n\t\t\t// prevent document scrolling\n\t\t\tif (eventType === \"touchstart\") {\n\t\t\t\tif (isPrevented) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t} else if (preventThreshold !== null) {\n\t\t\t\t\tstartPx = currentXY;\n\t\t\t\t}\n\t\t\t} else if (eventType === \"touchmove\") {\n\t\t\t\tif (isPrevented || startPx === true || (\n\t\t\t\t\tpreventThreshold !== null && Math.abs(startPx - currentXY) >= preventThreshold\n\t\t\t\t)) {\n\t\t\t\t\t// once prevented, keep prevented during whole 'touchmove' context\n\t\t\t\t\tstartPx = true;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// bind touch events\n\t\t$$.svg\n\t\t\t.on(\"touchstart.eventRect touchmove.eventRect\", function() {\n\t\t\t\tconst eventRect = getEventRect();\n\t\t\t\tconst event = d3Event;\n\n\t\t\t\tif (!eventRect.empty() && eventRect.classed(CLASS.eventRect)) {\n\t\t\t\t\t// if touch points are > 1, means doing zooming interaction. In this case do not execute tooltip codes.\n\t\t\t\t\tif ($$.dragging || $$.flowing || $$.hasArcType() || event.touches.length > 1) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tpreventEvent(event);\n\t\t\t\t\tselectRect(this);\n\t\t\t\t} else {\n\t\t\t\t\t$$.unselectRect();\n\t\t\t\t\t$$.callOverOutForTouch();\n\t\t\t\t}\n\t\t\t}, true)\n\t\t\t.on(\"touchend.eventRect\", () => {\n\t\t\t\tconst eventRect = getEventRect();\n\n\t\t\t\tif (!eventRect.empty() && eventRect.classed(CLASS.eventRect)) {\n\t\t\t\t\tif ($$.hasArcType() || !$$.toggleShape || $$.cancelClick) {\n\t\t\t\t\t\t$$.cancelClick && ($$.cancelClick = false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, true);\n\t},\n\n\t/**\n\t * Updates the location and size of the eventRect.\n\t * @private\n\t * @param {Object} d3.select(CLASS.eventRects) object.\n\t */\n\tupdateEventRect(eventRectUpdate) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst xScale = $$.zoomScale || $$.x;\n\t\tconst eventRectData = eventRectUpdate || $$.eventRect.data(); // set update selection if null\n\t\tconst isRotated = config.axis_rotated;\n\t\tlet x;\n\t\tlet y;\n\t\tlet w;\n\t\tlet h;\n\n\t\tif ($$.isMultipleX()) {\n\t\t\t// TODO: rotated not supported yet\n\t\t\tx = 0;\n\t\t\ty = 0;\n\t\t\tw = $$.width;\n\t\t\th = $$.height;\n\t\t} else {\n\t\t\tlet rectW;\n\t\t\tlet rectX;\n\n\t\t\tif ($$.isCategorized()) {\n\t\t\t\trectW = $$.getEventRectWidth();\n\t\t\t\trectX = d => xScale(d.x) - (rectW / 2);\n\t\t\t} else {\n\t\t\t\tconst getPrevNextX = d => {\n\t\t\t\t\tconst index = d.index;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tprev: $$.getPrevX(index),\n\t\t\t\t\t\tnext: $$.getNextX(index)\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\trectW = d => {\n\t\t\t\t\tconst x = getPrevNextX(d);\n\n\t\t\t\t\t// if there this is a single data point make the eventRect full width (or height)\n\t\t\t\t\tif (x.prev === null && x.next === null) {\n\t\t\t\t\t\treturn isRotated ? $$.height : $$.width;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (x.prev === null) {\n\t\t\t\t\t\tx.prev = xScale.domain()[0];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (x.next === null) {\n\t\t\t\t\t\tx.next = xScale.domain()[1];\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Math.max(0, (xScale(x.next) - xScale(x.prev)) / 2);\n\t\t\t\t};\n\n\t\t\t\trectX = d => {\n\t\t\t\t\tconst x = getPrevNextX(d);\n\t\t\t\t\tconst thisX = d.x;\n\n\t\t\t\t\t// if there this is a single data point position the eventRect at 0\n\t\t\t\t\tif (x.prev === null && x.next === null) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (x.prev === null) {\n\t\t\t\t\t\tx.prev = xScale.domain()[0];\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (xScale(thisX) + xScale(x.prev)) / 2;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tx = isRotated ? 0 : rectX;\n\t\t\ty = isRotated ? rectX : 0;\n\t\t\tw = isRotated ? $$.width : rectW;\n\t\t\th = isRotated ? rectW : $$.height;\n\t\t}\n\n\t\teventRectData.attr(\"class\", $$.classEvent.bind($$))\n\t\t\t.attr(\"x\", x)\n\t\t\t.attr(\"y\", y)\n\t\t\t.attr(\"width\", w)\n\t\t\t.attr(\"height\", h);\n\t},\n\n\tselectRectForSingle(context, eventRect, index) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isSelectionEnabled = config.data_selection_enabled;\n\t\tconst isSelectionGrouped = config.data_selection_grouped;\n\t\tconst isTooltipGrouped = config.tooltip_grouped;\n\t\tconst selectedData = $$.getAllValuesOnIndex(index);\n\n\t\tif (isTooltipGrouped) {\n\t\t\t$$.showTooltip(selectedData, context);\n\t\t\t$$.showGridFocus(selectedData);\n\n\t\t\tif (!isSelectionEnabled || isSelectionGrouped) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t$$.main.selectAll(`.${CLASS.shape}-${index}`)\n\t\t\t.each(function() {\n\t\t\t\td3Select(this).classed(CLASS.EXPANDED, true);\n\n\t\t\t\tif (isSelectionEnabled) {\n\t\t\t\t\teventRect.style(\"cursor\", isSelectionGrouped ? \"pointer\" : null);\n\t\t\t\t}\n\n\t\t\t\tif (!isTooltipGrouped) {\n\t\t\t\t\t$$.hideGridFocus();\n\t\t\t\t\t$$.hideTooltip();\n\n\t\t\t\t\t!isSelectionGrouped && $$.expandCirclesBars(index);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.filter(function(d) {\n\t\t\t\treturn $$.isWithinShape(this, d);\n\t\t\t})\n\t\t\t.call(selected => {\n\t\t\t\tconst d = selected.data();\n\n\t\t\t\tif (isSelectionEnabled && (isSelectionGrouped || config.data_selection_isselectable(d))) {\n\t\t\t\t\teventRect.style(\"cursor\", \"pointer\");\n\t\t\t\t}\n\n\t\t\t\tif (!isTooltipGrouped) {\n\t\t\t\t\t$$.showTooltip(d, context);\n\t\t\t\t\t$$.showGridFocus(d);\n\n\t\t\t\t\t$$.unexpandCircles();\n\t\t\t\t\tselected.each(d => $$.expandCirclesBars(index, d.id));\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\texpandCirclesBars(index, id, reset) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconfig.point_focus_expand_enabled &&\n\t\t\t$$.expandCircles(index, id, reset);\n\n\t\t$$.expandBars(index, id, reset);\n\t},\n\n\tselectRectForMultipleXs(context) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst targetsToShow = $$.filterTargetsToShow($$.data.targets);\n\n\t\t// do nothing when dragging\n\t\tif ($$.dragging || $$.hasArcType(targetsToShow)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mouse = d3Mouse(context);\n\t\tconst closest = $$.findClosestFromTargets(targetsToShow, mouse);\n\n\t\tif ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {\n\t\t\tconfig.data_onout.call($$.api, $$.mouseover);\n\t\t\t$$.mouseover = undefined;\n\t\t}\n\n\t\tif (!closest) {\n\t\t\t$$.unselectRect();\n\t\t\treturn;\n\t\t}\n\n\t\tconst sameXData = (\n\t\t\t$$.isBubbleType(closest) || $$.isScatterType(closest) || !config.tooltip_grouped\n\t\t) ? [closest] : $$.filterByX(targetsToShow, closest.x);\n\n\t\t// show tooltip when cursor is close to some point\n\t\tconst selectedData = sameXData.map(d => $$.addName(d));\n\n\t\t$$.showTooltip(selectedData, context);\n\n\t\t// expand points\n\t\t$$.expandCirclesBars(closest.index, closest.id, true);\n\n\t\t// Show xgrid focus line\n\t\t$$.showGridFocus(selectedData);\n\n\t\t// Show cursor as pointer if point is close to mouse position\n\t\tif ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {\n\t\t\t$$.svg.select(`.${CLASS.eventRect}`).style(\"cursor\", \"pointer\");\n\n\t\t\tif (!$$.mouseover) {\n\t\t\t\tconfig.data_onover.call($$.api, closest);\n\t\t\t\t$$.mouseover = closest;\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Unselect EventRect.\n\t * @private\n\t */\n\tunselectRect() {\n\t\tconst $$ = this;\n\n\t\t$$.svg.select(`.${CLASS.eventRect}`).style(\"cursor\", null);\n\t\t$$.hideGridFocus();\n\t\t$$.hideTooltip();\n\t\t$$._handleLinkedCharts(false);\n\t\t$$.unexpandCircles();\n\t\t$$.unexpandBars();\n\t},\n\n\t/**\n\t * Handle data.onover/out callback options\n\t * @param {Boolean} isOver\n\t * @param {Number|Object} d\n\t * @private\n\t */\n\tsetOverOut(isOver, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isArc = isObject(d);\n\n\t\t// Call event handler\n\t\tif (isArc || d !== -1) {\n\t\t\tlet callback = config[isOver ? \"data_onover\" : \"data_onout\"].bind($$.api);\n\n\t\t\tconfig.color_onover && $$.setOverColor(isOver, d, isArc);\n\n\t\t\tif (isArc) {\n\t\t\t\tcallback(d, $$.main.select(`.${CLASS.arc}${$$.getTargetSelectorSuffix(d.id)}`).node());\n\t\t\t} else if (!config.tooltip_grouped) {\n\t\t\t\tconst callee = $$.setOverOut;\n\t\t\t\tlet last = callee.last || [];\n\n\t\t\t\tconst shape = $$.main.selectAll(`.${CLASS.shape}-${d}`)\n\t\t\t\t\t.filter(function(d) {\n\t\t\t\t\t\treturn $$.isWithinShape(this, d);\n\t\t\t\t\t});\n\n\t\t\t\tshape\n\t\t\t\t\t.each(function(d) {\n\t\t\t\t\t\tif (last.length === 0 || last.every(v => v !== this)) {\n\t\t\t\t\t\t\tcallback(d, this);\n\t\t\t\t\t\t\tlast.push(this);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\tif (last.length > 0 && shape.empty()) {\n\t\t\t\t\tcallback = config.data_onout.bind($$.api);\n\n\t\t\t\t\tlast.forEach(v => callback(d3Select(v).datum(), v));\n\t\t\t\t\tlast = [];\n\t\t\t\t}\n\n\t\t\t\tcallee.last = last;\n\t\t\t} else {\n\t\t\t\tisOver && $$.expandCirclesBars(d, null, true);\n\n\t\t\t\t!$$.isMultipleX() && $$.main.selectAll(`.${CLASS.shape}-${d}`)\n\t\t\t\t\t.each(function(d) {\n\t\t\t\t\t\tcallback(d, this);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Call data.onover/out callback for touch event\n\t * @param {Number|Object} d target index or data object for Arc type\n\t * @private\n\t */\n\tcallOverOutForTouch(d) {\n\t\tconst $$ = this;\n\t\tconst callee = $$.callOverOutForTouch;\n\t\tconst last = callee.last;\n\n\t\tif (isObject(d) && last ? d.id !== last.id : (d !== last)) {\n\t\t\t(last || isNumber(last)) && $$.setOverOut(false, last);\n\t\t\t(d || isNumber(d)) && $$.setOverOut(true, d);\n\n\t\t\tcallee.last = d;\n\t\t}\n\t},\n\n\t/**\n\t * Return draggable selection function\n\t * @return {Function}\n\t * @private\n\t */\n\tgetDraggableSelection() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn config.interaction_enabled && config.data_selection_draggable && $$.drag ?\n\t\t\td3Drag()\n\t\t\t\t.on(\"drag\", function() { $$.drag(d3Mouse(this)); })\n\t\t\t\t.on(\"start\", function() { $$.dragstart(d3Mouse(this)); })\n\t\t\t\t.on(\"end\", () => { $$.dragend(); }) : () => {};\n\t},\n\n\t/**\n\t * Create eventRect for each data on the x-axis.\n\t * Register touch and drag events.\n\t * @private\n\t * @param {Object} d3.select(CLASS.eventRects) object.\n\t * @returns {Object} d3.select(CLASS.eventRects) object.\n\t */\n\tgenerateEventRectsForSingleX(eventRectEnter) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst rect = eventRectEnter.append(\"rect\")\n\t\t\t.attr(\"class\", $$.classEvent.bind($$))\n\t\t\t.style(\"cursor\", config.data_selection_enabled && config.data_selection_grouped ? \"pointer\" : null)\n\t\t\t.on(\"click\", function(d) {\n\t\t\t\t$$.clickHandlerForSingleX.bind(this)(d, $$);\n\t\t\t})\n\t\t\t.call($$.getDraggableSelection());\n\n\t\tif ($$.inputType === \"mouse\") {\n\t\t\trect\n\t\t\t\t.on(\"mouseover\", d => {\n\t\t\t\t\t// do nothing while dragging/flowing\n\t\t\t\t\tif ($$.dragging || $$.flowing || $$.hasArcType()) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$$.config.tooltip_grouped && $$.setOverOut(true, d.index);\n\t\t\t\t})\n\t\t\t\t.on(\"mousemove\", function(d) {\n\t\t\t\t\t// do nothing while dragging/flowing\n\t\t\t\t\tif ($$.dragging || $$.flowing || $$.hasArcType()) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet index = d.index;\n\t\t\t\t\tconst eventRect = $$.svg.select(`.${CLASS.eventRect}-${index}`);\n\n\t\t\t\t\tif ($$.isStepType(d) &&\n\t\t\t\t\t\t$$.config.line_step_type === \"step-after\" &&\n\t\t\t\t\t\td3Mouse(this)[0] < $$.x($$.getXValue(d.id, index))\n\t\t\t\t\t) {\n\t\t\t\t\t\tindex -= 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tindex === -1 ?\n\t\t\t\t\t\t$$.unselectRect() : $$.selectRectForSingle(this, eventRect, index);\n\n\t\t\t\t\t// As of individual data point(or <path>) element can't bind mouseover/out event\n\t\t\t\t\t// to determine current interacting element, so use 'mousemove' event instead.\n\t\t\t\t\tif (!$$.config.tooltip_grouped) {\n\t\t\t\t\t\t$$.setOverOut(index !== -1, d.index);\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.on(\"mouseout\", d => {\n\t\t\t\t\t// chart is destroyed\n\t\t\t\t\tif (!$$.config || $$.hasArcType()) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$$.unselectRect();\n\t\t\t\t\t$$.setOverOut(false, d.index);\n\t\t\t\t});\n\t\t}\n\n\t\treturn rect;\n\t},\n\n\tclickHandlerForSingleX(d, ctx) {\n\t\tconst $$ = ctx;\n\t\tconst config = $$.config;\n\n\t\tif ($$.hasArcType() || !$$.toggleShape || $$.cancelClick) {\n\t\t\t$$.cancelClick && ($$.cancelClick = false);\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst index = d.index;\n\n\t\t$$.main.selectAll(`.${CLASS.shape}-${index}`)\n\t\t\t.each(function(d2) {\n\t\t\t\tif (config.data_selection_grouped || $$.isWithinShape(this, d2)) {\n\t\t\t\t\t$$.toggleShape(this, d2, index);\n\t\t\t\t\tconfig.data_onclick.call($$.api, d2, this);\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\t/**\n\t * Create an eventRect,\n\t * Register touch and drag events.\n\t * @private\n\t * @param {Object} d3.select(CLASS.eventRects) object.\n\t * @returns {Object} d3.select(CLASS.eventRects) object.\n\t */\n\tgenerateEventRectsForMultipleXs(eventRectEnter) {\n\t\tconst $$ = this;\n\n\t\tconst rect = eventRectEnter\n\t\t\t.append(\"rect\")\n\t\t\t.attr(\"x\", 0)\n\t\t\t.attr(\"y\", 0)\n\t\t\t.attr(\"width\", $$.width)\n\t\t\t.attr(\"height\", $$.height)\n\t\t\t.attr(\"class\", CLASS.eventRect)\n\t\t\t.on(\"click\", function() {\n\t\t\t\t$$.clickHandlerForMultipleXS.bind(this)($$);\n\t\t\t})\n\t\t\t.call($$.getDraggableSelection());\n\n\t\tif ($$.inputType === \"mouse\") {\n\t\t\trect\n\t\t\t\t.on(\"mouseover mousemove\", function() {\n\t\t\t\t\t$$.selectRectForMultipleXs(this);\n\t\t\t\t})\n\t\t\t\t.on(\"mouseout\", () => {\n\t\t\t\t\t// chart is destroyed\n\t\t\t\t\tif (!$$.config || $$.hasArcType()) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t$$.unselectRect();\n\t\t\t\t});\n\t\t}\n\n\t\treturn rect;\n\t},\n\n\tclickHandlerForMultipleXS(ctx) {\n\t\tconst $$ = ctx;\n\t\tconst config = $$.config;\n\t\tconst targetsToShow = $$.filterTargetsToShow($$.data.targets);\n\n\t\tif ($$.hasArcType(targetsToShow)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mouse = d3Mouse(this);\n\t\tconst closest = $$.findClosestFromTargets(targetsToShow, mouse);\n\n\t\tif (!closest) {\n\t\t\treturn;\n\t\t}\n\n\t\t// select if selection enabled\n\t\tif ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {\n\t\t\t$$.main.selectAll(`.${CLASS.shapes}${$$.getTargetSelectorSuffix(closest.id)}`)\n\t\t\t\t.selectAll(`.${CLASS.shape}-${closest.index}`)\n\t\t\t\t.each(function() {\n\t\t\t\t\tif (config.data_selection_grouped || $$.isWithinShape(this, closest)) {\n\t\t\t\t\t\t$$.toggleShape(this, closest, closest.index);\n\t\t\t\t\t\tconfig.data_onclick.call($$.api, closest, this);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * Dispatch a mouse event.\n\t * @private\n\t * @param {String} type event type\n\t * @param {Number} index Index of eventRect\n\t * @param {Array} mouse x and y coordinate value\n\t */\n\tdispatchEvent(type, index, mouse) {\n\t\tconst $$ = this;\n\t\tconst isMultipleX = $$.isMultipleX();\n\t\tconst selector = `.${isMultipleX ? CLASS.eventRect : `${CLASS.eventRect}-${index}`}`;\n\t\tconst eventRect = $$.main.select(selector).node();\n\t\tconst {width, left, top} = eventRect.getBoundingClientRect();\n\t\tconst x = left + (mouse ? mouse[0] : 0) + (\n\t\t\tisMultipleX || $$.config.axis_rotated ? 0 : (width / 2)\n\t\t);\n\t\tconst y = top + (mouse ? mouse[1] : 0);\n\t\tconst params = {\n\t\t\tscreenX: x,\n\t\t\tscreenY: y,\n\t\t\tclientX: x,\n\t\t\tclientY: y\n\t\t};\n\n\t\temulateEvent[/^(mouse|click)/.test(type) ? \"mouse\" : \"touch\"](eventRect, type, params);\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {document} from \"./browser\";\nimport CLASS from \"../config/classes\";\nimport {isValue, ceil10, extend, capitalize} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Update container size\n\t * @private\n\t */\n\tsetContainerSize() {\n\t\tconst $$ = this;\n\n\t\t$$.currentWidth = $$.getCurrentWidth();\n\t\t$$.currentHeight = $$.getCurrentHeight();\n\t},\n\n\tgetCurrentWidth() {\n\t\tconst $$ = this;\n\n\t\treturn $$.config.size_width || $$.getParentWidth();\n\t},\n\n\tgetCurrentHeight() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst h = config.size_height || $$.getParentHeight();\n\n\t\treturn h > 0 ? h : 320 / ($$.hasType(\"gauge\") && !config.gauge_fullCircle ? 2 : 1);\n\t},\n\n\t/**\n\t * Get Axis size according its position\n\t * @param {String} id Axis id value - x, y or y2\n\t * @return {number} size Axis size value\n\t * @private\n\t */\n\tgetAxisSize(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\treturn (isRotated && id === \"x\") || (!isRotated && /y2?/.test(id)) ?\n\t\t\t$$.getAxisWidthByAxisId(id, true) :\n\t\t\t$$.getHorizontalAxisHeight(id);\n\t},\n\n\tgetCurrentPaddingTop() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst axesLen = config.axis_y2_axes.length;\n\n\t\tlet padding = isValue(config.padding_top) ?\n\t\t\tconfig.padding_top : 0;\n\n\t\tif ($$.title && $$.title.node()) {\n\t\t\tpadding += $$.getTitlePadding();\n\t\t}\n\n\t\tif (axesLen && config.axis_rotated) {\n\t\t\tpadding += $$.getHorizontalAxisHeight(\"y2\") * axesLen;\n\t\t}\n\n\t\treturn padding;\n\t},\n\n\tgetCurrentPaddingBottom() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst axisId = config.axis_rotated ? \"y\" : \"x\";\n\t\tconst axesLen = config[`axis_${axisId}_axes`].length;\n\t\tconst padding = isValue(config.padding_bottom) ?\n\t\t\tconfig.padding_bottom : 0;\n\n\t\treturn padding + (\n\t\t\taxesLen ? $$.getHorizontalAxisHeight(axisId) * axesLen : 0\n\t\t);\n\t},\n\n\tgetCurrentPaddingLeft(withoutRecompute) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst axisId = isRotated ? \"x\" : \"y\";\n\t\tconst axesLen = config[`axis_${axisId}_axes`].length;\n\t\tconst axisWidth = $$.getAxisWidthByAxisId(axisId, withoutRecompute);\n\t\tlet padding;\n\n\t\tif (isValue(config.padding_left)) {\n\t\t\tpadding = config.padding_left;\n\t\t} else if (isRotated) {\n\t\t\tpadding = !config.axis_x_show ?\n\t\t\t\t1 : Math.max(ceil10(axisWidth), 40);\n\t\t} else if (!config.axis_y_show || config.axis_y_inner) { // && !config.axis_rotated\n\t\t\tpadding = $$.axis.getAxisLabelPosition(\"y\").isOuter ? 30 : 1;\n\t\t} else {\n\t\t\tpadding = ceil10(axisWidth);\n\t\t}\n\n\t\treturn padding + (axisWidth * axesLen);\n\t},\n\n\tgetCurrentPaddingRight(withoutTickTextOverflow = false) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst defaultPadding = 10;\n\t\tconst legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;\n\t\tconst axesLen = config.axis_y2_axes.length;\n\t\tconst axisWidth = $$.getAxisWidthByAxisId(\"y2\");\n\t\tconst xAxisTickTextOverflow = withoutTickTextOverflow ?\n\t\t\t0 : $$.axis.getXAxisTickTextY2Overflow(defaultPadding);\n\t\tlet padding;\n\n\t\tif (isValue(config.padding_right)) {\n\t\t\tpadding = config.padding_right + 1; // 1 is needed not to hide tick line\n\t\t} else if (config.axis_rotated) {\n\t\t\tpadding = defaultPadding + legendWidthOnRight;\n\t\t} else if (!config.axis_y2_show || config.axis_y2_inner) { // && !config.axis_rotated\n\t\t\tpadding = Math.max(\n\t\t\t\t2 + legendWidthOnRight + ($$.axis.getAxisLabelPosition(\"y2\").isOuter ? 20 : 0),\n\t\t\t\txAxisTickTextOverflow\n\t\t\t);\n\t\t} else {\n\t\t\tpadding = Math.max(ceil10(axisWidth) + legendWidthOnRight, xAxisTickTextOverflow);\n\t\t}\n\n\t\treturn padding + (axisWidth * axesLen);\n\t},\n\n\t/**\n\t * Get the parent rect element's size\n\t * @param {String} key property/attribute name\n\t * @private\n\t */\n\tgetParentRectValue(key) {\n\t\tconst offsetName = `offset${capitalize(key)}`;\n\t\tlet parent = this.selectChart.node();\n\t\tlet v;\n\n\t\twhile (!v && parent && parent.tagName !== \"BODY\") {\n\t\t\ttry {\n\t\t\t\tv = parent.getBoundingClientRect()[key];\n\t\t\t} catch (e) {\n\t\t\t\tif (offsetName in parent) {\n\t\t\t\t\t// In IE in certain cases getBoundingClientRect\n\t\t\t\t\t// will cause an \"unspecified error\"\n\t\t\t\t\tv = parent[offsetName];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tparent = parent.parentNode;\n\t\t}\n\n\t\tif (key === \"width\") {\n\t\t\t// Sometimes element's width value is incorrect(ex. flex container)\n\t\t\t// In this case, use body's offsetWidth instead.\n\t\t\tconst bodyWidth = document.body.offsetWidth;\n\n\t\t\tv > bodyWidth && (v = bodyWidth);\n\t\t}\n\n\t\treturn v;\n\t},\n\n\tgetParentWidth() {\n\t\treturn this.getParentRectValue(\"width\");\n\t},\n\n\tgetParentHeight() {\n\t\tconst h = this.selectChart.style(\"height\");\n\n\t\treturn h.indexOf(\"px\") > 0 ? parseInt(h, 10) : 0;\n\t},\n\n\tgetSvgLeft(withoutRecompute) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner);\n\t\tconst leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY;\n\t\tconst leftAxis = $$.main.select(`.${leftAxisClass}`).node();\n\t\tconst svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {right: 0};\n\t\tconst chartRect = $$.selectChart.node().getBoundingClientRect();\n\t\tconst hasArc = $$.hasArcType();\n\t\tconst svgLeft = svgRect.right - chartRect.left -\n\t\t\t(hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));\n\n\t\treturn svgLeft > 0 ? svgLeft : 0;\n\t},\n\n\tgetAxisWidthByAxisId(id, withoutRecompute) {\n\t\tconst $$ = this;\n\t\tconst position = $$.axis.getLabelPositionById(id);\n\n\t\treturn $$.axis.getMaxTickWidth(id, withoutRecompute) +\n\t\t\t(position.isInner ? 20 : 40);\n\t},\n\n\tgetHorizontalAxisHeight(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tlet h = 30;\n\n\t\tif (id === \"x\" && !config.axis_x_show) {\n\t\t\treturn 8;\n\t\t}\n\n\t\tif (id === \"x\" && config.axis_x_height) {\n\t\t\treturn config.axis_x_height;\n\t\t}\n\n\t\tif (id === \"y\" && !config.axis_y_show) {\n\t\t\treturn config.legend_show &&\n\t\t\t\t!$$.isLegendRight &&\n\t\t\t\t!$$.isLegendInset ? 10 : 1;\n\t\t}\n\n\t\tif (id === \"y2\" && !config.axis_y2_show) {\n\t\t\treturn $$.rotated_padding_top;\n\t\t}\n\n\t\t// const rotate = config[`axis_${id}_tick_rotate`];\n\t\tconst rotate = $$.getAxisTickRotate(id);\n\n\t\t// Calculate x/y axis height when tick rotated\n\t\tif (\n\t\t\t((id === \"x\" && !isRotated) || (/y2?/.test(id) && isRotated)) && rotate\n\t\t) {\n\t\t\th = 30 +\n\t\t\t\t$$.axis.getMaxTickWidth(id) *\n\t\t\t\tMath.cos(Math.PI * (90 - rotate) / 180);\n\n\t\t\tif (!config.axis_x_tick_multiline && $$.currentHeight) {\n\t\t\t\tif (h > $$.currentHeight / 2) {\n\t\t\t\t\th = $$.currentHeight / 2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn h +\n\t\t\t($$.axis.getLabelPositionById(id).isInner ? 0 : 10) +\n\t\t\t(id === \"y2\" && !isRotated ? -10 : 0);\n\t},\n\n\tgetEventRectWidth() {\n\t\treturn Math.max(0, this.xAxis.tickInterval());\n\t},\n\n\t/**\n\t * Get axis tick test rotate value\n\t * @param {String} id\n\t * @return {Number} rotate value\n\t * @private\n\t */\n\tgetAxisTickRotate(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet rotate = config[`axis_${id}_tick_rotate`];\n\n\t\tif (id === \"x\") {\n\t\t\tconst isCategorized = $$.isCategorized();\n\t\t\tconst isTimeSeries = $$.isTimeSeries();\n\t\t\tconst allowedXAxisTypes = isCategorized || isTimeSeries;\n\t\t\tlet tickCount = 0;\n\n\t\t\tif (config.axis_x_tick_fit && allowedXAxisTypes) {\n\t\t\t\t$$.axis.x = {\n\t\t\t\t\tpadding: {left: 0, right: 0},\n\t\t\t\t\ttickCount: 0\n\t\t\t\t};\n\n\t\t\t\ttickCount = $$.currentMaxTickWidths.x.ticks.length + (isTimeSeries ? -1 : 1);\n\n\t\t\t\tif (tickCount !== $$.axis.x.tickCount) {\n\t\t\t\t\t$$.axis.x.padding = $$.axis.getXAxisPadding(tickCount);\n\t\t\t\t}\n\n\t\t\t\t$$.axis.x.tickCount = tickCount;\n\t\t\t}\n\n\t\t\tif ($$.svg &&\n\t\t\t\tconfig.axis_x_tick_fit &&\n\t\t\t\t!config.axis_x_tick_multiline &&\n\t\t\t\t!config.axis_x_tick_culling &&\n\t\t\t\tconfig.axis_x_tick_autorotate &&\n\t\t\t\tallowedXAxisTypes\n\t\t\t) {\n\t\t\t\trotate = $$.needToRotateXAxisTickTexts() ?\n\t\t\t\t\tconfig.axis_x_tick_rotate : 0;\n\t\t\t}\n\t\t}\n\n\t\treturn rotate;\n\t},\n\n\t/**\n\t * Check weather axis tick text needs to be rotated\n\t * @private\n\t */\n\tneedToRotateXAxisTickTexts() {\n\t\tconst $$ = this;\n\t\tconst xAxisLength = $$.currentWidth -\n\t\t\t$$.getCurrentPaddingLeft(false) - $$.getCurrentPaddingRight(true);\n\t\tconst tickCountWithPadding = $$.axis.x.tickCount +\n\t\t\t$$.axis.x.padding.left + $$.axis.x.padding.right;\n\n\t\tconst maxTickWidth = $$.axis.getMaxTickWidth(\"x\");\n\t\tconst tickLength = (xAxisLength / tickCountWithPadding) || 0;\n\n\t\treturn maxTickWidth > tickLength;\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tcurveStepBefore as d3CurveStepBefore,\n\tcurveStepAfter as d3CurveStepAfter,\n\tcurveBasisClosed as d3CurveBasisClosed,\n\tcurveBasisOpen as d3CurveBasisOpen,\n\tcurveBasis as d3CurveBasis,\n\tcurveBundle as d3CurveBundle,\n\tcurveCardinalClosed as d3CurveCardinalClosed,\n\tcurveCardinalOpen as d3CurveCardinalOpen,\n\tcurveCardinal as d3CurveCardinal,\n\tcurveCatmullRomClosed as d3CurveCatmullRomClosed,\n\tcurveCatmullRomOpen as d3CurveCatmullRomOpen,\n\tcurveCatmullRom as d3CurveCatmullRom,\n\tcurveLinearClosed as d3CurveLinearClosed,\n\tcurveLinear as d3CurveLinear,\n\tcurveMonotoneX as d3CurveMonotoneX,\n\tcurveMonotoneY as d3CurveMonotoneY,\n\tcurveNatural as d3CurveNatural,\n\tcurveStep as d3CurveStep\n} from \"d3-shape\";\nimport {select as d3Select} from \"d3-selection\";\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {extend, getUnique, isObjectType, isNumber, isUndefined, notEmpty} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tgetShapeIndices(typeFilter) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst xs = config.data_xs;\n\t\tconst hasXs = notEmpty(xs);\n\t\tconst indices = {};\n\t\tlet i = hasXs ? {} : 0;\n\n\t\tif (hasXs) {\n\t\t\tgetUnique(Object.keys(xs).map(v => xs[v]))\n\t\t\t\t.forEach(v => {\n\t\t\t\t\ti[v] = 0;\n\t\t\t\t\tindices[v] = {};\n\t\t\t\t});\n\t\t}\n\n\t\t$$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))\n\t\t\t.forEach(d => {\n\t\t\t\tconst xKey = d.id in xs ? xs[d.id] : \"\";\n\t\t\t\tconst ind = xKey ? indices[xKey] : indices;\n\n\t\t\t\tfor (let j = 0, groups; (groups = config.data_groups[j]); j++) {\n\t\t\t\t\tif (groups.indexOf(d.id) < 0) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (let k = 0, row; (row = groups[k]); k++) {\n\t\t\t\t\t\tif (row in ind) {\n\t\t\t\t\t\t\tind[d.id] = ind[row];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isUndefined(ind[d.id])) {\n\t\t\t\t\tind[d.id] = xKey ? i[xKey]++ : i++;\n\t\t\t\t\tind.__max__ = (xKey ? i[xKey] : i) - 1;\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn indices;\n\t},\n\n\t/**\n\t * Get indices value based on data ID value\n\t * @param {Object} indices Indices object\n\t * @param {String} id Data id value\n\t * @return {Object} Indices object\n\t * @private\n\t */\n\tgetIndices(indices, id) {\n\t\tconst xs = this.config.data_xs;\n\n\t\treturn notEmpty(xs) ?\n\t\t\tindices[xs[id]] : indices;\n\t},\n\n\t/**\n\t * Get indices max number\n\t * @param {Object} indices Indices object\n\t * @return {Number} Max number\n\t * @private\n\t */\n\tgetIndicesMax(indices) {\n\t\treturn notEmpty(this.config.data_xs) ?\n\t\t\t// if is multiple xs, return total sum of xs' __max__ value\n\t\t\tObject.keys(indices)\n\t\t\t\t.map(v => indices[v].__max__ || 0)\n\t\t\t\t.reduce((acc, curr) => acc + curr) : indices.__max__;\n\t},\n\n\tgetShapeX(offset, indices, isSub) {\n\t\tconst $$ = this;\n\t\tconst scale = isSub ? $$.subX : ($$.zoomScale || $$.x);\n\t\tconst barPadding = $$.config.bar_padding;\n\t\tconst sum = (p, c) => p + c;\n\t\tconst halfWidth = isObjectType(offset) && offset.total.length ? offset.total.reduce(sum) / 2 : 0;\n\n\t\treturn d => {\n\t\t\tconst ind = $$.getIndices(indices, d.id);\n\t\t\tconst index = d.id in ind ? ind[d.id] : 0;\n\t\t\tconst targetsNum = (ind.__max__ || 0) + 1;\n\t\t\tlet x = 0;\n\n\t\t\tif (notEmpty(d.x)) {\n\t\t\t\tconst xPos = scale(d.x);\n\n\t\t\t\tif (halfWidth) {\n\t\t\t\t\tx = xPos - (offset[d.id] || offset.width) +\n\t\t\t\t\t\toffset.total.slice(0, index + 1).reduce(sum) -\n\t\t\t\t\t\thalfWidth;\n\t\t\t\t} else {\n\t\t\t\t\tx = xPos - (isNumber(offset) ? offset : offset.width) * (targetsNum / 2 - index);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// adjust x position for bar.padding optionq\n\t\t\tif (offset && x && targetsNum > 1 && barPadding) {\n\t\t\t\tif (index) {\n\t\t\t\t\tx += barPadding * index;\n\t\t\t\t}\n\n\t\t\t\tif (targetsNum > 2) {\n\t\t\t\t\tx -= (targetsNum - 1) * barPadding / 2;\n\t\t\t\t} else if (targetsNum === 2) {\n\t\t\t\t\tx -= barPadding / 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn x;\n\t\t};\n\t},\n\n\tgetShapeY(isSub) {\n\t\tconst $$ = this;\n\t\tconst isStackNormalized = $$.isStackNormalized();\n\n\t\treturn d => {\n\t\t\tconst value = isStackNormalized ? $$.getRatio(\"index\", d, true) : (\n\t\t\t\t$$.isBubbleZType(d) ? $$.getBubbleZData(d.value, \"y\") : d.value\n\t\t\t);\n\n\t\t\treturn (isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id))(value);\n\t\t};\n\t},\n\n\t/**\n\t * Get Shape's offset data\n\t * @param {function(Object): boolean} typeFilter\n\t * @return {{shapeOffsetTargets: ShapeOffsetTarget[], indexMapByTargetId: object}}\n\t * @private\n\t */\n\tgetShapeOffsetData(typeFilter) {\n\t\tconst $$ = this;\n\t\tconst targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)));\n\t\tconst shapeOffsetTargets = targets.map(target => {\n\t\t\tlet rowValues = target.values;\n\n\t\t\tif ($$.isStepType(target)) {\n\t\t\t\trowValues = $$.convertValuesToStep(rowValues);\n\t\t\t}\n\t\t\tconst rowValueMapByXValue = rowValues.reduce((out, value) => {\n\t\t\t\tout[Number(value.x)] = value;\n\t\t\t\treturn out;\n\t\t\t}, {});\n\n\t\t\tlet values;\n\n\t\t\tif ($$.isStackNormalized()) {\n\t\t\t\tvalues = rowValues.map(v => $$.getRatio(\"index\", v, true));\n\t\t\t} else {\n\t\t\t\tvalues = rowValues.map(({value}) => value);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tid: target.id,\n\t\t\t\trowValues,\n\t\t\t\trowValueMapByXValue,\n\t\t\t\tvalues,\n\t\t\t};\n\t\t});\n\t\tconst indexMapByTargetId = targets.reduce((out, {id}, index) => {\n\t\t\tout[id] = index;\n\t\t\treturn out;\n\t\t}, {});\n\n\t\treturn {indexMapByTargetId, shapeOffsetTargets};\n\t},\n\n\tgetShapeOffset(typeFilter, indices, isSub) {\n\t\tconst $$ = this;\n\t\tconst {shapeOffsetTargets, indexMapByTargetId} = $$.getShapeOffsetData(typeFilter);\n\n\t\treturn (d, idx) => {\n\t\t\tconst ind = $$.getIndices(indices, d.id);\n\t\t\tconst scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);\n\t\t\tconst y0 = scale(0);\n\t\t\tconst dataXAsNumber = Number(d.x);\n\t\t\tlet offset = y0;\n\n\t\t\tshapeOffsetTargets\n\t\t\t\t.forEach(t => {\n\t\t\t\t\tconst rowValues = t.rowValues;\n\t\t\t\t\tconst values = t.values;\n\n\t\t\t\t\tif (t.id === d.id || ind[t.id] !== ind[d.id]) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (indexMapByTargetId[t.id] < indexMapByTargetId[d.id]) {\n\t\t\t\t\t\tlet rowValue = rowValues[idx];\n\n\t\t\t\t\t\t// check if the x values line up\n\t\t\t\t\t\tif (!rowValue || Number(rowValue.x) !== dataXAsNumber) {\n\t\t\t\t\t\t\trowValue = t.rowValueMapByXValue[dataXAsNumber];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (rowValue && rowValue.value * d.value >= 0) {\n\t\t\t\t\t\t\toffset += scale(values[rowValue.index]) - y0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\treturn offset;\n\t\t};\n\t},\n\n\tisWithinShape(that, d) {\n\t\tconst $$ = this;\n\t\tconst shape = d3Select(that);\n\t\tlet isWithin;\n\n\t\tif (!$$.isTargetToShow(d.id)) {\n\t\t\tisWithin = false;\n\t\t} else if ($$.hasValidPointType(that.nodeName)) {\n\t\t\tisWithin = $$.isStepType(d) ?\n\t\t\t\t$$.isWithinStep(that, $$.getYScale(d.id)(d.value)) :\n\t\t\t\t$$.isWithinCircle(that, $$.isBubbleType(d) ? $$.pointSelectR(d) * 1.5 : 0);\n\t\t} else if (that.nodeName === \"path\") {\n\t\t\tisWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true;\n\t\t}\n\n\t\treturn isWithin;\n\t},\n\n\tgetInterpolate(d) {\n\t\tconst $$ = this;\n\t\tconst interpolation = $$.getInterpolateType(d);\n\n\t\treturn {\n\t\t\t\"basis\": d3CurveBasis,\n\t\t\t\"basis-closed\": d3CurveBasisClosed,\n\t\t\t\"basis-open\": d3CurveBasisOpen,\n\t\t\t\"bundle\": d3CurveBundle,\n\t\t\t\"cardinal\": d3CurveCardinal,\n\t\t\t\"cardinal-closed\": d3CurveCardinalClosed,\n\t\t\t\"cardinal-open\": d3CurveCardinalOpen,\n\t\t\t\"catmull-rom\": d3CurveCatmullRom,\n\t\t\t\"catmull-rom-closed\": d3CurveCatmullRomClosed,\n\t\t\t\"catmull-rom-open\": d3CurveCatmullRomOpen,\n\t\t\t\"monotone-x\": d3CurveMonotoneX,\n\t\t\t\"monotone-y\": d3CurveMonotoneY,\n\t\t\t\"natural\": d3CurveNatural,\n\t\t\t\"linear-closed\": d3CurveLinearClosed,\n\t\t\t\"linear\": d3CurveLinear,\n\t\t\t\"step\": d3CurveStep,\n\t\t\t\"step-after\": d3CurveStepAfter,\n\t\t\t\"step-before\": d3CurveStepBefore\n\t\t}[interpolation];\n\t},\n\n\tgetInterpolateType(d) {\n\t\tconst $$ = this;\n\t\tconst type = $$.config.spline_interpolation_type;\n\t\tconst interpolation = $$.isInterpolationType(type) ? type : \"cardinal\";\n\n\t\treturn $$.isSplineType(d) ?\n\t\t\tinterpolation : (\n\t\t\t\t$$.isStepType(d) ?\n\t\t\t\t\t$$.config.line_step_type : \"linear\"\n\t\t\t);\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tevent as d3Event\n} from \"d3-selection\";\nimport {\n\tarc as d3Arc,\n\tpie as d3Pie\n} from \"d3-shape\";\nimport {interpolate as d3Interpolate} from \"d3-interpolate\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {document} from \"../internals/browser\";\nimport CLASS from \"../config/classes\";\nimport {callFn, extend, isFunction, isNumber, isUndefined, setTextValue} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tinitPie() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst dataType = config.data_type;\n\t\tconst padding = config.pie_padding;\n\t\tconst startingAngle = config[`${dataType}_startingAngle`] || 0;\n\t\tconst padAngle = (\n\t\t\t$$.hasType(\"pie\") && padding ? padding * 0.01 :\n\t\t\t\tconfig[`${dataType}_padAngle`]\n\t\t) || 0;\n\n\t\t$$.pie = d3Pie()\n\t\t\t.startAngle(startingAngle)\n\t\t\t.endAngle(startingAngle + (2 * Math.PI))\n\t\t\t.padAngle(padAngle)\n\t\t\t.sortValues(\n\t\t\t\t$$.isOrderAsc() || $$.isOrderDesc() ?\n\t\t\t\t\t(a, b) => ($$.isOrderAsc() ? a - b : b - a) : null\n\t\t\t)\n\t\t\t.value(d => d.values.reduce((a, b) => a + b.value, 0));\n\t},\n\n\tupdateRadius() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst radius = config.pie_innerRadius;\n\t\tconst padding = config.pie_padding;\n\t\tconst w = config.gauge_width || config.donut_width;\n\t\tconst gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length *\n\t\t\tconfig.gauge_arcs_minWidth;\n\n\t\t$$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2 * ($$.hasMultiArcGauge() ? 0.85 : 1);\n\t\t$$.radius = $$.radiusExpanded * 0.95;\n\t\t$$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;\n\t\t$$.gaugeArcWidth = w || (\n\t\t\tgaugeArcWidth <= $$.radius - $$.innerRadius ?\n\t\t\t\t$$.radius - $$.innerRadius :\n\t\t\t\t(gaugeArcWidth <= $$.radius ? gaugeArcWidth : $$.radius)\n\t\t);\n\n\t\tconst innerRadius = radius || (\n\t\t\tpadding ? padding * ($$.innerRadiusRatio + 0.1) : 0\n\t\t);\n\n\t\t// NOTE: innerRadius can be an object by user setting, only for 'pie' type\n\t\t$$.innerRadius = $$.hasType(\"donut\") || $$.hasType(\"gauge\") ?\n\t\t\t$$.radius * $$.innerRadiusRatio : innerRadius;\n\t},\n\n\tgetInnerRadius(d) {\n\t\tconst $$ = this;\n\t\tlet radius = $$.innerRadius;\n\n\t\tif (!isNumber(radius) && d) {\n\t\t\tradius = radius[d.data.id] || 0;\n\t\t}\n\n\t\treturn radius;\n\t},\n\n\tupdateArc() {\n\t\tconst $$ = this;\n\n\t\t$$.svgArc = $$.getSvgArc();\n\t\t$$.svgArcExpanded = $$.getSvgArcExpanded();\n\t},\n\n\tupdateAngle(dValue) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet pie = $$.pie;\n\t\tlet d = dValue;\n\t\tlet found = false;\n\n\t\tif (!config) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst radius = Math.PI * (config.gauge_fullCircle ? 2 : 1);\n\t\tconst gStart = config.gauge_startingAngle;\n\n\t\tif (d.data && $$.isGaugeType(d.data) && !$$.hasMultiArcGauge()) {\n\t\t\tconst totalSum = $$.getTotalDataSum();\n\n\t\t\t// if gauge_max less than totalSum, make totalSum to max value\n\t\t\tif (totalSum > config.gauge_max) {\n\t\t\t\tconfig.gauge_max = totalSum;\n\t\t\t}\n\n\t\t\tconst gEnd = radius * (totalSum / (config.gauge_max - config.gauge_min));\n\n\t\t\tpie = pie\n\t\t\t\t.startAngle(gStart)\n\t\t\t\t.endAngle(gEnd + gStart);\n\t\t}\n\n\t\tpie($$.filterTargetsToShow())\n\t\t\t.forEach((t, i) => {\n\t\t\t\tif (!found && t.data.id === d.data.id) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\td = t;\n\t\t\t\t\td.index = i;\n\t\t\t\t}\n\t\t\t});\n\n\t\tif (isNaN(d.startAngle)) {\n\t\t\td.startAngle = 0;\n\t\t}\n\n\t\tif (isNaN(d.endAngle)) {\n\t\t\td.endAngle = d.startAngle;\n\t\t}\n\n\t\tif (d.data && $$.hasMultiArcGauge()) {\n\t\t\tconst maxValue = $$.getMinMaxData().max[0].value;\n\n\t\t\t// if gauge_max less than maxValue, make maxValue to max value\n\t\t\tif (maxValue > config.gauge_max) {\n\t\t\t\tconfig.gauge_max = maxValue;\n\t\t\t}\n\n\t\t\tconst gMin = config.gauge_min;\n\t\t\tconst gMax = config.gauge_max;\n\t\t\tconst gTic = radius / (gMax - gMin);\n\t\t\tconst gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);\n\n\t\t\td.startAngle = gStart;\n\t\t\td.endAngle = gStart + gTic * gValue;\n\t\t}\n\n\t\treturn found ? d : null;\n\t},\n\n\tgetSvgArc() {\n\t\tconst $$ = this;\n\t\tconst ir = $$.getInnerRadius();\n\t\tconst singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length;\n\t\tconst hasMultiArcGauge = $$.hasMultiArcGauge();\n\n\t\tlet arc = d3Arc()\n\t\t\t.outerRadius(d => (hasMultiArcGauge ? ($$.radius - singleArcWidth * d.index) : $$.radius))\n\t\t\t.innerRadius(d => (hasMultiArcGauge ?\n\t\t\t\t$$.radius - singleArcWidth * (d.index + 1) :\n\t\t\t\tisNumber(ir) ? ir : 0));\n\n\t\tconst newArc = function(d, withoutUpdate) {\n\t\t\tlet path = \"M 0 0\";\n\n\t\t\tif (d.value || d.data) {\n\t\t\t\tif (!isNumber(ir)) {\n\t\t\t\t\tarc = arc.innerRadius($$.getInnerRadius(d));\n\t\t\t\t}\n\n\t\t\t\tconst updated = !withoutUpdate && $$.updateAngle(d);\n\n\t\t\t\tif (withoutUpdate) {\n\t\t\t\t\tpath = arc(d);\n\t\t\t\t} else if (updated) {\n\t\t\t\t\tpath = arc(updated);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn path;\n\t\t};\n\n\t\t// TODO: extends all function\n\t\tnewArc.centroid = arc.centroid;\n\n\t\treturn newArc;\n\t},\n\n\tgetSvgArcExpanded(rate) {\n\t\tconst $$ = this;\n\t\tconst newRate = rate || 1;\n\t\tconst singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length;\n\t\tconst hasMultiArcGauge = $$.hasMultiArcGauge();\n\t\tconst expandWidth = Math.min($$.radiusExpanded * newRate - $$.radius,\n\t\t\tsingleArcWidth * 0.8 - (1 - newRate) * 100\n\t\t);\n\n\t\tconst arc = d3Arc()\n\t\t\t.outerRadius(d => (hasMultiArcGauge ?\n\t\t\t\t$$.radius - singleArcWidth * d.index + expandWidth :\n\t\t\t\t$$.radiusExpanded * newRate)\n\t\t\t)\n\t\t\t.innerRadius(d => (hasMultiArcGauge ?\n\t\t\t\t$$.radius - singleArcWidth * (d.index + 1) : $$.innerRadius));\n\n\t\treturn function(d) {\n\t\t\tconst updated = $$.updateAngle(d);\n\n\t\t\tif (updated) {\n\t\t\t\treturn (\n\t\t\t\t\thasMultiArcGauge ? arc : arc.innerRadius($$.getInnerRadius(d))\n\t\t\t\t)(updated);\n\t\t\t} else {\n\t\t\t\treturn \"M 0 0\";\n\t\t\t}\n\t\t};\n\t},\n\n\tgetArc(d, withoutUpdate, force) {\n\t\treturn force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : \"M 0 0\";\n\t},\n\n\ttransformForArcLabel(d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst updated = $$.updateAngle(d);\n\t\tlet translate = \"\";\n\n\t\tif (updated) {\n\t\t\tif ($$.hasMultiArcGauge()) {\n\t\t\t\tconst y1 = Math.sin(updated.endAngle - Math.PI / 2);\n\n\t\t\t\tconst x = Math.cos(updated.endAngle - Math.PI / 2) * ($$.radiusExpanded + 25);\n\t\t\t\tconst y = y1 * ($$.radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;\n\n\t\t\t\ttranslate = `translate(${x},${y})`;\n\t\t\t} else if (!$$.hasType(\"gauge\") || $$.data.targets.length > 1) {\n\t\t\t\tconst c = this.svgArc.centroid(updated);\n\t\t\t\tconst x = isNaN(c[0]) ? 0 : c[0];\n\t\t\t\tconst y = isNaN(c[1]) ? 0 : c[1];\n\t\t\t\tconst h = Math.sqrt(x * x + y * y);\n\n\t\t\t\tlet ratio = ($$.hasType(\"donut\") && config.donut_label_ratio) ||\n\t\t\t\t\t($$.hasType(\"pie\") && config.pie_label_ratio);\n\n\t\t\t\tif (ratio) {\n\t\t\t\t\tratio = isFunction(ratio) ? ratio(d, $$.radius, h) : ratio;\n\t\t\t\t} else {\n\t\t\t\t\tratio = $$.radius && (\n\t\t\t\t\t\th ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ttranslate = `translate(${x * ratio},${y * ratio})`;\n\t\t\t}\n\t\t}\n\n\t\treturn translate;\n\t},\n\n\tconvertToArcData(d) {\n\t\treturn this.addName({\n\t\t\tid: d.data.id,\n\t\t\tvalue: d.value,\n\t\t\tratio: this.getRatio(\"arc\", d),\n\t\t\tindex: d.index,\n\t\t});\n\t},\n\n\ttextForArcLabel(selection) {\n\t\tconst $$ = this;\n\n\t\tif ($$.shouldShowArcLabel()) {\n\t\t\tselection.each(function(d) {\n\t\t\t\tconst node = d3Select(this);\n\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\tconst value = updated ? updated.value : d.value;\n\t\t\t\tconst ratio = $$.getRatio(\"arc\", updated);\n\t\t\t\tconst id = d.data.id;\n\t\t\t\tconst hasGauge = $$.hasType(\"gauge\");\n\t\t\t\tconst isUnderThreshold = !(\n\t\t\t\t\t!hasGauge && !$$.meetsArcLabelThreshold(ratio)\n\t\t\t\t);\n\n\t\t\t\tif (isUnderThreshold) {\n\t\t\t\t\tconst text = (\n\t\t\t\t\t\t$$.getArcLabelFormat() || $$.defaultArcValueFormat\n\t\t\t\t\t)(value, ratio, id).toString();\n\n\t\t\t\t\tsetTextValue(node, text, [-1, 1], hasGauge);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\ttextForGaugeMinMax(value, isMax) {\n\t\tconst format = this.getGaugeLabelExtents();\n\n\t\treturn format ? format(value, isMax) : value;\n\t},\n\n\texpandArc(targetIds) {\n\t\tconst $$ = this;\n\n\t\t// MEMO: avoid to cancel transition\n\t\tif ($$.transiting) {\n\t\t\tconst interval = setInterval(() => {\n\t\t\t\tif (!$$.transiting) {\n\t\t\t\t\tclearInterval(interval);\n\n\t\t\t\t\t$$.legend.selectAll(`.${CLASS.legendItemFocused}`).size() > 0 &&\n\t\t\t\t\t\t$$.expandArc(targetIds);\n\t\t\t\t}\n\t\t\t}, 10);\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst newTargetIds = $$.mapToTargetIds(targetIds);\n\n\t\t$$.svg.selectAll($$.selectorTargets(newTargetIds, `.${CLASS.chartArc}`))\n\t\t\t.each(function(d) {\n\t\t\t\tif (!$$.shouldExpand(d.data.id)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst expandDuration = $$.getExpandConfig(d.data.id, \"duration\");\n\t\t\t\tconst svgArcExpandedSub = $$.getSvgArcExpanded($$.getExpandConfig(d.data.id, \"rate\"));\n\n\t\t\t\td3Select(this).selectAll(\"path\")\n\t\t\t\t\t.transition()\n\t\t\t\t\t.duration(expandDuration)\n\t\t\t\t\t.attr(\"d\", $$.svgArcExpanded)\n\t\t\t\t\t.transition()\n\t\t\t\t\t.duration(expandDuration * 2)\n\t\t\t\t\t.attr(\"d\", svgArcExpandedSub);\n\t\t\t});\n\t},\n\n\tunexpandArc(targetIds) {\n\t\tconst $$ = this;\n\n\t\tif ($$.transiting) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst newTargetIds = $$.mapToTargetIds(targetIds);\n\n\t\t$$.svg.selectAll($$.selectorTargets(newTargetIds, `.${CLASS.chartArc}`))\n\t\t\t.selectAll(\"path\")\n\t\t\t.transition()\n\t\t\t.duration(d => $$.getExpandConfig(d.data.id, \"duration\"))\n\t\t\t.attr(\"d\", $$.svgArc);\n\n\t\t$$.svg.selectAll(`${CLASS.arc}`)\n\t\t\t.style(\"opacity\", \"1\");\n\t},\n\n\t/**\n\t * Get expand config value\n\t * @param {String} id data ID\n\t * @param {String} key config key: 'duration | rate'\n\t * @return {Number}\n\t * @private\n\t */\n\tgetExpandConfig(id, key) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst def = {\n\t\t\tduration: 50,\n\t\t\trate: 0.98\n\t\t};\n\t\tlet type;\n\n\t\tif ($$.isDonutType(id)) {\n\t\t\ttype = \"donut\";\n\t\t} else if ($$.isGaugeType(id)) {\n\t\t\ttype = \"gauge\";\n\t\t} else if ($$.isPieType(id)) {\n\t\t\ttype = \"pie\";\n\t\t}\n\n\t\treturn type ? config[`${type}_expand_${key}`] : def[key];\n\t},\n\n\tshouldExpand(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn ($$.isDonutType(id) && config.donut_expand) ||\n\t\t\t($$.isGaugeType(id) && config.gauge_expand) ||\n\t\t\t($$.isPieType(id) && config.pie_expand);\n\t},\n\n\tshouldShowArcLabel() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn [\"pie\", \"donut\", \"gauge\"]\n\t\t\t.some(v => $$.hasType(v) && config[`${v}_label_show`]);\n\t},\n\n\tmeetsArcLabelThreshold(ratio) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst threshold = $$.hasType(\"donut\") ? config.donut_label_threshold : config.pie_label_threshold;\n\n\t\treturn ratio >= threshold;\n\t},\n\n\tgetArcLabelFormat() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet format = config.pie_label_format;\n\n\t\tif ($$.hasType(\"gauge\")) {\n\t\t\tformat = config.gauge_label_format;\n\t\t} else if ($$.hasType(\"donut\")) {\n\t\t\tformat = config.donut_label_format;\n\t\t}\n\n\t\treturn format;\n\t},\n\n\tgetGaugeLabelExtents() {\n\t\tconst config = this.config;\n\n\t\treturn config.gauge_label_extents;\n\t},\n\n\tgetArcTitle() {\n\t\tconst $$ = this;\n\t\tconst type = ($$.hasType(\"donut\") && \"donut\") || ($$.hasType(\"gauge\") && \"gauge\");\n\n\t\treturn type ? $$.config[`${type}_title`] : \"\";\n\t},\n\n\tupdateTargetsForArc(targets) {\n\t\tconst $$ = this;\n\t\tconst main = $$.main;\n\t\tconst hasGauge = $$.hasType(\"gauge\");\n\t\tconst classChartArc = $$.classChartArc.bind($$);\n\t\tconst classArcs = $$.classArcs.bind($$);\n\t\tconst classFocus = $$.classFocus.bind($$);\n\t\tconst mainPieUpdate = main.select(`.${CLASS.chartArcs}`)\n\t\t\t.selectAll(`.${CLASS.chartArc}`)\n\t\t\t.data($$.pie(targets))\n\t\t\t.attr(\"class\", d => classChartArc(d) + classFocus(d.data));\n\n\t\tconst mainPieEnter = mainPieUpdate.enter().append(\"g\")\n\t\t\t.attr(\"class\", classChartArc);\n\n\t\tmainPieEnter.append(\"g\")\n\t\t\t.attr(\"class\", classArcs)\n\t\t\t.merge(mainPieUpdate);\n\n\t\tmainPieEnter.append(\"text\")\n\t\t\t.attr(\"dy\", hasGauge && !$$.hasMultiTargets() ? \"-.1em\" : \".35em\")\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.style(\"text-anchor\", \"middle\")\n\t\t\t.style(\"pointer-events\", \"none\");\n\t\t// MEMO: can not keep same color..., but not bad to update color in redraw\n\t\t// mainPieUpdate.exit().remove();\n\t},\n\n\tinitArc() {\n\t\tconst $$ = this;\n\n\t\t$$.arcs = $$.main.select(`.${CLASS.chart}`)\n\t\t\t.append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartArcs)\n\t\t\t.attr(\"transform\", $$.getTranslate(\"arc\"));\n\n\t\t$$.setArcTitle();\n\t},\n\n\t/**\n\t * Set arc title text\n\t * @private\n\t */\n\tsetArcTitle() {\n\t\tconst $$ = this;\n\t\tconst title = $$.getArcTitle();\n\t\tconst hasGauge = $$.hasType(\"gauge\");\n\n\t\tif (title) {\n\t\t\tconst text = $$.arcs.append(\"text\")\n\t\t\t\t.attr(\"class\", CLASS[hasGauge ? \"chartArcsGaugeTitle\" : \"chartArcsTitle\"])\n\t\t\t\t.style(\"text-anchor\", \"middle\");\n\n\t\t\tif (hasGauge) {\n\t\t\t\ttext\n\t\t\t\t\t.attr(\"dy\", \"-0.3em\")\n\t\t\t\t\t.style(\"font-size\", \"27px\");\n\t\t\t}\n\n\t\t\tsetTextValue(text, title, hasGauge ? undefined : [-0.6, 1.35], true);\n\t\t}\n\t},\n\n\tredrawArc(duration, durationForExit, withTransform) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst main = $$.main;\n\t\tconst hasInteraction = config.interaction_enabled;\n\n\t\tlet mainArc = main.selectAll(`.${CLASS.arcs}`)\n\t\t\t.selectAll(`.${CLASS.arc}`)\n\t\t\t.data($$.arcData.bind($$));\n\n\t\tmainArc.exit().transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\tmainArc = mainArc.enter().append(\"path\")\n\t\t\t.attr(\"class\", $$.classArc.bind($$))\n\t\t\t.style(\"fill\", d => $$.color(d.data))\n\t\t\t.style(\"cursor\", d => (hasInteraction && config.data_selection_isselectable(d) ? \"pointer\" : null))\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.each(function(d) {\n\t\t\t\tif ($$.isGaugeType(d.data)) {\n\t\t\t\t\td.startAngle = config.gauge_startingAngle;\n\t\t\t\t\td.endAngle = config.gauge_startingAngle;\n\t\t\t\t}\n\n\t\t\t\tthis._current = d;\n\t\t\t})\n\t\t\t.merge(mainArc);\n\n\t\t$$.hasMultiArcGauge() && $$.redrawMultiArcGauge();\n\n\t\tmainArc\n\t\t\t.attr(\"transform\", d => (!$$.isGaugeType(d.data) && withTransform ? \"scale(0)\" : \"\"))\n\t\t\t.style(\"opacity\", function(d) {\n\t\t\t\treturn d === this._current ? \"0\" : \"1\";\n\t\t\t})\n\t\t\t.each(() => {\n\t\t\t\t$$.transiting = true;\n\t\t\t})\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.attrTween(\"d\", function(d) {\n\t\t\t\tconst updated = $$.updateAngle(d);\n\n\t\t\t\tif (!updated) {\n\t\t\t\t\treturn () => \"M 0 0\";\n\t\t\t\t}\n\n\t\t\t\tif (isNaN(this._current.startAngle)) {\n\t\t\t\t\tthis._current.startAngle = 0;\n\t\t\t\t}\n\n\t\t\t\tif (isNaN(this._current.endAngle)) {\n\t\t\t\t\tthis._current.endAngle = this._current.startAngle;\n\t\t\t\t}\n\n\t\t\t\tconst interpolate = d3Interpolate(this._current, updated);\n\n\t\t\t\tthis._current = interpolate(0);\n\n\t\t\t\treturn function(t) {\n\t\t\t\t\tconst interpolated = interpolate(t);\n\n\t\t\t\t\tinterpolated.data = d.data; // data.id will be updated by interporator\n\t\t\t\t\treturn $$.getArc(interpolated, true);\n\t\t\t\t};\n\t\t\t})\n\t\t\t.attr(\"transform\", withTransform ? \"scale(1)\" : \"\")\n\t\t\t.style(\"fill\", d => {\n\t\t\t\tlet color;\n\n\t\t\t\tif ($$.levelColor) {\n\t\t\t\t\tcolor = $$.levelColor(d.data.values[0].value);\n\n\t\t\t\t\t// update data's color\n\t\t\t\t\tconfig.data_colors[d.data.id] = color;\n\t\t\t\t} else {\n\t\t\t\t\tcolor = $$.color(d.data.id);\n\t\t\t\t}\n\n\t\t\t\treturn color;\n\t\t\t})\n\t\t\t// Where gauge reading color would receive customization.\n\t\t\t.style(\"opacity\", \"1\")\n\t\t\t.call($$.endall, function() {\n\t\t\t\tif ($$.levelColor) {\n\t\t\t\t\tconst path = d3Select(this);\n\t\t\t\t\tconst d = path.datum();\n\n\t\t\t\t\t$$.updateLegendItemColor(d.data.id, path.style(\"fill\"));\n\t\t\t\t}\n\n\t\t\t\t$$.transiting = false;\n\t\t\t\tcallFn(config.onrendered, $$, $$.api);\n\t\t\t});\n\n\t\t// bind arc events\n\t\thasInteraction && $$.bindArcEvent(mainArc);\n\n\t\t$$.redrawArcText(duration);\n\t},\n\n\tredrawMultiArcGauge() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst arcLabelLines = $$.main.selectAll(`.${CLASS.arcs}`)\n\t\t\t.selectAll(`.${CLASS.arcLabelLine}`)\n\t\t\t.data($$.arcData.bind($$));\n\n\t\tconst mainArcLabelLine = arcLabelLines.enter()\n\t\t\t.append(\"rect\")\n\t\t\t.attr(\"class\", d => `${CLASS.arcLabelLine} ${CLASS.target} ${CLASS.target}-${d.data.id}`)\n\t\t\t.merge(arcLabelLines);\n\n\t\tmainArcLabelLine\n\t\t\t.style(\"fill\", d => ($$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data)))\n\t\t\t.style(\"display\", config.gauge_label_show ? \"\" : \"none\")\n\t\t\t.each(function(d) {\n\t\t\t\tlet lineLength = 0;\n\t\t\t\tconst lineThickness = 2;\n\t\t\t\tlet x = 0;\n\t\t\t\tlet y = 0;\n\t\t\t\tlet transform = \"\";\n\n\t\t\t\tif ($$.hiddenTargetIds.indexOf(d.data.id) < 0) {\n\t\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\t\tconst innerLineLength = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length *\n\t\t\t\t\t\t(updated.index + 1);\n\t\t\t\t\tconst lineAngle = updated.endAngle - Math.PI / 2;\n\t\t\t\t\tconst arcInnerRadius = $$.radius - innerLineLength;\n\t\t\t\t\tconst linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : (1 / arcInnerRadius));\n\n\t\t\t\t\tlineLength = $$.radiusExpanded - $$.radius + innerLineLength;\n\t\t\t\t\tx = Math.cos(linePositioningAngle) * arcInnerRadius;\n\t\t\t\t\ty = Math.sin(linePositioningAngle) * arcInnerRadius;\n\t\t\t\t\ttransform = `rotate(${lineAngle * 180 / Math.PI}, ${x}, ${y})`;\n\t\t\t\t}\n\n\t\t\t\td3Select(this)\n\t\t\t\t\t.attr(\"x\", x)\n\t\t\t\t\t.attr(\"y\", y)\n\t\t\t\t\t.attr(\"width\", lineLength)\n\t\t\t\t\t.attr(\"height\", lineThickness)\n\t\t\t\t\t.attr(\"transform\", transform)\n\t\t\t\t\t.style(\"stroke-dasharray\", `0, ${lineLength + lineThickness}, 0`);\n\t\t\t});\n\t},\n\n\tbindArcEvent(arc) {\n\t\tconst $$ = this;\n\t\tconst isTouch = $$.inputType === \"touch\";\n\t\tconst isMouse = $$.inputType === \"mouse\";\n\n\t\tfunction selectArc(_this, arcData, id) {\n\t\t\t// transitions\n\t\t\t$$.expandArc(id);\n\t\t\t$$.api.focus(id);\n\t\t\t$$.toggleFocusLegend(id, true);\n\t\t\t$$.showTooltip([arcData], _this);\n\t\t}\n\n\t\tfunction unselectArc(arcData) {\n\t\t\tconst id = (arcData && arcData.id) || undefined;\n\n\t\t\t$$.unexpandArc(id);\n\t\t\t$$.api.revert();\n\t\t\t$$.revertLegend();\n\t\t\t$$.hideTooltip();\n\t\t}\n\n\t\tarc\n\t\t\t.on(\"click\", function(d, i) {\n\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\tlet arcData;\n\n\t\t\t\tif (updated) {\n\t\t\t\t\tarcData = $$.convertToArcData(updated);\n\n\t\t\t\t\t$$.toggleShape && $$.toggleShape(this, arcData, i);\n\t\t\t\t\t$$.config.data_onclick.call($$.api, arcData, this);\n\t\t\t\t}\n\t\t\t});\n\n\t\t// mouse events\n\t\tif (isMouse) {\n\t\t\tarc\n\t\t\t\t.on(\"mouseover\", function(d) {\n\t\t\t\t\tif ($$.transiting) { // skip while transiting\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\t\tconst arcData = updated ? $$.convertToArcData(updated) : null;\n\t\t\t\t\tconst id = (arcData && arcData.id) || undefined;\n\n\t\t\t\t\tselectArc(this, arcData, id);\n\t\t\t\t\t$$.setOverOut(true, arcData);\n\t\t\t\t})\n\t\t\t\t.on(\"mouseout\", d => {\n\t\t\t\t\tif ($$.transiting) { // skip while transiting\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\t\tconst arcData = updated ? $$.convertToArcData(updated) : null;\n\n\t\t\t\t\tunselectArc();\n\t\t\t\t\t$$.setOverOut(false, arcData);\n\t\t\t\t})\n\t\t\t\t.on(\"mousemove\", function(d) {\n\t\t\t\t\tconst updated = $$.updateAngle(d);\n\t\t\t\t\tconst arcData = updated ? $$.convertToArcData(updated) : null;\n\n\t\t\t\t\t$$.showTooltip([arcData], this);\n\t\t\t\t});\n\t\t}\n\n\t\t// touch events\n\t\tif (isTouch && $$.hasArcType() && !$$.radars) {\n\t\t\tconst getEventArc = () => {\n\t\t\t\tconst touch = d3Event.changedTouches[0];\n\t\t\t\tconst eventArc = d3Select(document.elementFromPoint(touch.clientX, touch.clientY));\n\n\t\t\t\treturn eventArc;\n\t\t\t};\n\n\t\t\tconst handler = function() {\n\t\t\t\tif ($$.transiting) { // skip while transiting\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst eventArc = getEventArc();\n\t\t\t\tconst datum = eventArc.datum();\n\t\t\t\tconst updated = (datum && datum.data && datum.data.id) ? $$.updateAngle(datum) : null;\n\t\t\t\tconst arcData = updated ? $$.convertToArcData(updated) : null;\n\t\t\t\tconst id = (arcData && arcData.id) || undefined;\n\n\t\t\t\t$$.callOverOutForTouch(arcData);\n\n\t\t\t\tisUndefined(id) ?\n\t\t\t\t\tunselectArc() : selectArc(this, arcData, id);\n\t\t\t};\n\n\t\t\t$$.svg\n\t\t\t\t.on(\"touchstart\", handler)\n\t\t\t\t.on(\"touchmove\", handler);\n\t\t}\n\t},\n\n\tredrawArcText(duration) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst main = $$.main;\n\t\tconst hasGauge = $$.hasType(\"gauge\");\n\t\tconst hasMultiArcGauge = $$.hasMultiArcGauge();\n\t\tlet text;\n\n\t\t// for gauge type, update text when has no title & multi data\n\t\tif (!(hasGauge && $$.data.targets.length === 1 && config.gauge_title)) {\n\t\t\ttext = main.selectAll(`.${CLASS.chartArc}`)\n\t\t\t\t.select(\"text\")\n\t\t\t\t.style(\"opacity\", \"0\")\n\t\t\t\t.attr(\"class\", d => ($$.isGaugeType(d.data) ? CLASS.gaugeValue : null))\n\t\t\t\t.call($$.textForArcLabel.bind($$))\n\t\t\t\t.attr(\"transform\", $$.transformForArcLabel.bind($$))\n\t\t\t\t.style(\"font-size\", d => (\n\t\t\t\t\t$$.isGaugeType(d.data) && $$.data.targets.length === 1 && !hasMultiArcGauge ?\n\t\t\t\t\t\t`${Math.round($$.radius / 5)}px` : null\n\t\t\t\t))\n\t\t\t\t.transition()\n\t\t\t\t.duration(duration)\n\t\t\t\t.style(\"opacity\", d => ($$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? \"1\" : \"0\"));\n\n\t\t\thasMultiArcGauge && text.attr(\"dy\", \"-.1em\");\n\t\t}\n\n\t\tmain.select(`.${CLASS.chartArcsTitle}`)\n\t\t\t.style(\"opacity\", $$.hasType(\"donut\") || hasGauge ? \"1\" : \"0\");\n\n\t\tif (hasGauge) {\n\t\t\tconst isFullCircle = config.gauge_fullCircle;\n\t\t\tconst startAngle = -1 * Math.PI / 2;\n\t\t\tconst endAngle = (isFullCircle ? -4 : -1) * startAngle;\n\n\t\t\tisFullCircle && text && text.attr(\"dy\", `${Math.round($$.radius / 14)}`);\n\n\t\t\tlet backgroundArc = $$.arcs.select(\n\t\t\t\t`${hasMultiArcGauge ? \"g\" : \"\"}.${CLASS.chartArcsBackground}`\n\t\t\t);\n\n\t\t\tif (hasMultiArcGauge) {\n\t\t\t\tlet index = 0;\n\n\t\t\t\tbackgroundArc = backgroundArc\n\t\t\t\t\t.selectAll(`path.${CLASS.chartArcsBackground}`)\n\t\t\t\t\t.data($$.data.targets);\n\n\t\t\t\tbackgroundArc.enter()\n\t\t\t\t\t.append(\"path\")\n\t\t\t\t\t.attr(\"class\", (d, i) => `${CLASS.chartArcsBackground} ${CLASS.chartArcsBackground}-${i}`)\n\t\t\t\t\t.merge(backgroundArc)\n\t\t\t\t\t.attr(\"d\", d1 => {\n\t\t\t\t\t\tif ($$.hiddenTargetIds.indexOf(d1.id) >= 0) {\n\t\t\t\t\t\t\treturn \"M 0 0\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst d = {\n\t\t\t\t\t\t\tdata: [{value: config.gauge_max}],\n\t\t\t\t\t\t\tstartAngle,\n\t\t\t\t\t\t\tendAngle,\n\t\t\t\t\t\t\tindex: index++\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\treturn $$.getArc(d, true, true);\n\t\t\t\t\t});\n\n\t\t\t\tbackgroundArc.exit().remove();\n\t\t\t} else {\n\t\t\t\tbackgroundArc.attr(\"d\", () => {\n\t\t\t\t\tconst d = {\n\t\t\t\t\t\tdata: [{value: config.gauge_max}],\n\t\t\t\t\t\tstartAngle,\n\t\t\t\t\t\tendAngle\n\t\t\t\t\t};\n\n\t\t\t\t\treturn $$.getArc(d, true, true);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t$$.arcs.select(`.${CLASS.chartArcsGaugeUnit}`)\n\t\t\t\t.attr(\"dy\", \".75em\")\n\t\t\t\t.text(config.gauge_label_show ? config.gauge_units : \"\");\n\n\t\t\tif (config.gauge_label_show) {\n\t\t\t\t$$.arcs.select(`.${CLASS.chartArcsGaugeMin}`)\n\t\t\t\t\t.attr(\"dx\", `${-1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (isFullCircle ? 1 : 2)))}px`)\n\t\t\t\t\t.attr(\"dy\", \"1.2em\")\n\t\t\t\t\t.text($$.textForGaugeMinMax(config.gauge_min, false));\n\n\t\t\t\t// show max text when isn't fullCircle\n\t\t\t\t!isFullCircle && $$.arcs.select(`.${CLASS.chartArcsGaugeMax}`)\n\t\t\t\t\t.attr(\"dx\", `${$$.innerRadius + (($$.radius - $$.innerRadius) / 2)}px`)\n\t\t\t\t\t.attr(\"dy\", \"1.2em\")\n\t\t\t\t\t.text($$.textForGaugeMinMax(config.gauge_max, true));\n\t\t\t}\n\t\t}\n\t},\n\n\tinitGauge() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst arcs = $$.arcs;\n\t\tconst appendText = className => {\n\t\t\tarcs.append(\"text\")\n\t\t\t\t.attr(\"class\", className)\n\t\t\t\t.style(\"text-anchor\", \"middle\")\n\t\t\t\t.style(\"pointer-events\", \"none\");\n\t\t};\n\n\t\tif ($$.hasType(\"gauge\")) {\n\t\t\tarcs.append($$.hasMultiArcGauge() ? \"g\" : \"path\")\n\t\t\t\t.attr(\"class\", CLASS.chartArcsBackground);\n\n\t\t\tconfig.gauge_units && appendText(CLASS.chartArcsGaugeUnit);\n\n\t\t\tif (config.gauge_label_show) {\n\t\t\t\tappendText(CLASS.chartArcsGaugeMin);\n\t\t\t\t!config.gauge_fullCircle && appendText(CLASS.chartArcsGaugeMax);\n\t\t\t}\n\t\t}\n\t},\n\n\tgetGaugeLabelHeight() {\n\t\treturn this.config.gauge_label_show ? 20 : 0;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {mouse as d3Mouse} from \"d3-selection\";\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {extend, getRandom, getRectSegList, isNumber, isObjectType, isValue} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tinitBar() {\n\t\tconst $$ = this;\n\n\t\t$$.main.select(`.${CLASS.chart}`).append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartBars);\n\t},\n\n\tupdateTargetsForBar(targets) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst classChartBar = $$.classChartBar.bind($$);\n\t\tconst classBars = $$.classBars.bind($$);\n\t\tconst classFocus = $$.classFocus.bind($$);\n\t\tconst mainBarUpdate = $$.main.select(`.${CLASS.chartBars}`)\n\t\t\t.selectAll(`.${CLASS.chartBar}`)\n\t\t\t.data(targets)\n\t\t\t.attr(\"class\", d => classChartBar(d) + classFocus(d));\n\t\tconst mainBarEnter = mainBarUpdate.enter().append(\"g\")\n\t\t\t.attr(\"class\", classChartBar)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.style(\"pointer-events\", \"none\");\n\n\t\t// Bars for each data\n\t\tmainBarEnter.append(\"g\")\n\t\t\t.attr(\"class\", classBars)\n\t\t\t.style(\"cursor\", d => (config.data_selection_isselectable(d) ? \"pointer\" : null));\n\t},\n\n\tupdateBar(durationForExit) {\n\t\tconst $$ = this;\n\t\tconst barData = $$.barData.bind($$);\n\t\tconst classBar = $$.classBar.bind($$);\n\t\tconst initialOpacity = $$.initialOpacity.bind($$);\n\n\t\t$$.mainBar = $$.main.selectAll(`.${CLASS.bars}`).selectAll(`.${CLASS.bar}`)\n\t\t\t.data(barData);\n\n\t\t$$.mainBar.exit().transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.mainBar = $$.mainBar.enter().append(\"path\")\n\t\t\t.attr(\"class\", classBar)\n\t\t\t.style(\"fill\", $$.color)\n\t\t\t.merge($$.mainBar)\n\t\t\t.style(\"opacity\", initialOpacity);\n\t},\n\n\tredrawBar(drawBar, withTransition) {\n\t\treturn [\n\t\t\t(withTransition ? this.mainBar.transition(getRandom()) : this.mainBar)\n\t\t\t\t.attr(\"d\", drawBar)\n\t\t\t\t.style(\"fill\", this.color)\n\t\t\t\t.style(\"opacity\", \"1\")\n\t\t];\n\t},\n\n\tgetBarW(axis, barTargetsNum) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst maxDataCount = $$.getMaxDataCount();\n\t\tconst isGrouped = config.data_groups.length;\n\t\tconst tickInterval = ($$.zoomScale || $$) && !$$.isCategorized() ?\n\t\t\t$$.xx($$.subX.domain()[1]) / maxDataCount : axis.tickInterval(maxDataCount);\n\t\tlet result;\n\n\t\tconst getWidth = id => {\n\t\t\tconst width = id ? config.bar_width[id] : config.bar_width;\n\t\t\tconst ratio = id ? width.ratio : config.bar_width_ratio;\n\t\t\tconst max = id ? width.max : config.bar_width_max;\n\t\t\tconst w = isNumber(width) ?\n\t\t\t\twidth : barTargetsNum ? (tickInterval * ratio) / barTargetsNum : 0;\n\n\t\t\treturn max && w > max ? max : w;\n\t\t};\n\n\t\tresult = getWidth();\n\n\t\tif (!isGrouped && isObjectType(config.bar_width)) {\n\t\t\tresult = {width: result, total: []};\n\n\t\t\t$$.filterTargetsToShow($$.data.targets).forEach(v => {\n\t\t\t\tif (config.bar_width[v.id]) {\n\t\t\t\t\tresult[v.id] = getWidth(v.id);\n\t\t\t\t\tresult.total.push(result[v.id] || result.width);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn result;\n\t},\n\n\tgetBars(i, id) {\n\t\tconst $$ = this;\n\t\tconst suffix = (isValue(i) ? `-${i}` : ``);\n\n\t\treturn (id ? $$.main\n\t\t\t.selectAll(`.${CLASS.bars}${$$.getTargetSelectorSuffix(id)}`) : $$.main)\n\t\t\t.selectAll(`.${CLASS.bar}${suffix}`);\n\t},\n\n\texpandBars(i, id, reset) {\n\t\tconst $$ = this;\n\n\t\treset && $$.unexpandBars();\n\t\t$$.getBars(i, id).classed(CLASS.EXPANDED, true);\n\t},\n\n\tunexpandBars(i) {\n\t\tthis.getBars(i).classed(CLASS.EXPANDED, false);\n\t},\n\n\tgenerateDrawBar(barIndices, isSub) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst getPoints = $$.generateGetBarPoints(barIndices, isSub);\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst isGrouped = config.data_groups.length;\n\t\tconst barRadius = config.bar_radius;\n\t\tconst barRadiusRatio = config.bar_radius_ratio;\n\n\t\t// get the bar radius\n\t\tconst getRadius = isNumber(barRadius) && barRadius > 0 ?\n\t\t\t() => barRadius : (\n\t\t\t\tisNumber(barRadiusRatio) ? w => w * barRadiusRatio : null\n\t\t\t);\n\n\t\treturn (d, i) => {\n\t\t\t// 4 points that make a bar\n\t\t\tconst points = getPoints(d, i);\n\n\t\t\t// switch points if axis is rotated, not applicable for sub chart\n\t\t\tconst indexX = +isRotated;\n\t\t\tconst indexY = +!indexX;\n\n\t\t\tconst isNegative = d.value < 0;\n\t\t\tconst pathRadius = [\"\", \"\"];\n\t\t\tlet radius = 0;\n\n\t\t\tif (getRadius && !isGrouped) {\n\t\t\t\tconst index = isRotated ? indexY : indexX;\n\t\t\t\tconst barW = points[2][index] - points[0][index];\n\n\t\t\t\tradius = getRadius(barW);\n\n\t\t\t\tconst arc = `a${radius},${radius} ${isNegative ? `1 0 0` : `0 0 1`} `;\n\n\t\t\t\tpathRadius[+!isRotated] = `${arc}${radius},${radius}`;\n\t\t\t\tpathRadius[+isRotated] = `${arc}${[-radius, radius][isRotated ? \"sort\" : \"reverse\"]()}`;\n\n\t\t\t\tisNegative && pathRadius.reverse();\n\t\t\t}\n\n\t\t\t// path string data shouldn't be containing new line chars\n\t\t\t// https://github.com/naver/billboard.js/issues/530\n\t\t\tconst path = isRotated ?\n\t\t\t\t`H${points[1][indexX] - radius} ${pathRadius[0]}V${points[2][indexY] - radius} ${pathRadius[1]}H${points[3][indexX]}` :\n\t\t\t\t`V${points[1][indexY] + (isNegative ? -radius : radius)} ${pathRadius[0]}H${points[2][indexX] - radius} ${pathRadius[1]}V${points[3][indexY]}`;\n\n\t\t\treturn `M${points[0][indexX]},${points[0][indexY]}${path}z`;\n\t\t};\n\t},\n\n\tgenerateGetBarPoints(barIndices, isSub) {\n\t\tconst $$ = this;\n\t\tconst axis = isSub ? $$.subXAxis : $$.xAxis;\n\t\tconst barTargetsNum = $$.getIndicesMax(barIndices) + 1;\n\t\tconst barW = $$.getBarW(axis, barTargetsNum);\n\t\tconst barX = $$.getShapeX(barW, barIndices, !!isSub);\n\t\tconst barY = $$.getShapeY(!!isSub);\n\t\tconst barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub);\n\t\tconst yScale = isSub ? $$.getSubYScale : $$.getYScale;\n\n\t\treturn (d, i) => {\n\t\t\tconst y0 = yScale.call($$, d.id)(0);\n\t\t\tconst offset = barOffset(d, i) || y0; // offset is for stacked bar chart\n\t\t\tconst width = isNumber(barW) ? barW : barW[d.id] || barW.width;\n\t\t\tconst posX = barX(d);\n\t\t\tlet posY = barY(d);\n\n\t\t\t// fix posY not to overflow opposite quadrant\n\t\t\tif ($$.config.axis_rotated && (\n\t\t\t\t(d.value > 0 && posY < y0) || (d.value < 0 && y0 < posY)\n\t\t\t)) {\n\t\t\t\tposY = y0;\n\t\t\t}\n\n\t\t\tposY -= (y0 - offset);\n\n\t\t\t// 4 points that make a bar\n\t\t\treturn [\n\t\t\t\t[posX, offset],\n\t\t\t\t[posX, posY],\n\t\t\t\t[posX + width, posY],\n\t\t\t\t[posX + width, offset]\n\t\t\t];\n\t\t};\n\t},\n\n\tisWithinBar(that) {\n\t\tconst mouse = d3Mouse(that);\n\t\tconst list = getRectSegList(that);\n\t\tconst [seg0, seg1] = list;\n\t\tconst x = Math.min(seg0.x, seg1.x);\n\t\tconst y = Math.min(seg0.y, seg1.y);\n\t\tconst offset = this.config.bar_sensitivity;\n\t\tconst {width, height} = that.getBBox();\n\t\tconst sx = x - offset;\n\t\tconst ex = x + width + offset;\n\t\tconst sy = y + height + offset;\n\t\tconst ey = y - offset;\n\n\t\treturn sx < mouse[0] &&\n\t\t\tmouse[0] < ex &&\n\t\t\tey < mouse[1] &&\n\t\t\tmouse[1] < sy;\n\t}\n});\n\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {extend, getMinMax, isArray, isFunction, isNumber, isObject} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initializer\n\t * @private\n\t */\n\tinitBubble() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif ($$.hasType(\"bubble\")) {\n\t\t\tconfig.point_show = true;\n\t\t\tconfig.point_type = \"circle\";\n\t\t\tconfig.point_sensitivity = 25;\n\t\t}\n\t},\n\n\t/**\n\t * Get user agent's computed value for the total length of the path in user units\n\t * https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength\n\t * @return {Number}\n\t * @private\n\t */\n\tgetBaseLength() {\n\t\tconst $$ = this;\n\t\tconst cacheKey = \"$baseLength\";\n\t\tlet baseLength = $$.getCache(cacheKey);\n\n\t\tif (!baseLength) {\n\t\t\t$$.addCache(cacheKey, baseLength = getMinMax(\"min\", [\n\t\t\t\t$$.axes.x.select(\"path\").node()\n\t\t\t\t\t.getTotalLength(),\n\t\t\t\t$$.axes.y.select(\"path\").node()\n\t\t\t\t\t.getTotalLength()\n\t\t\t]));\n\t\t}\n\n\t\treturn baseLength;\n\t},\n\n\t/**\n\t * Get the radius value for bubble circle\n\t * @param {Object} d\n\t * @return {Number}\n\t * @private\n \t */\n\tgetBubbleR(d) {\n\t\tconst $$ = this;\n\t\tlet maxR = $$.config.bubble_maxR;\n\n\t\tif (isFunction(maxR)) {\n\t\t\tmaxR = maxR(d);\n\t\t} else if (!isNumber(maxR)) {\n\t\t\tmaxR = ($$.getBaseLength() / ($$.getMaxDataCount() * 2)) + 12;\n\t\t}\n\n\t\tconst max = getMinMax(\"max\", $$.getMinMaxData().max.map(d => (\n\t\t\t$$.isBubbleZType(d) ?\n\t\t\t\t$$.getBubbleZData(d.value, \"y\") : (\n\t\t\t\t\tisObject(d.value) ? d.value.mid : d.value\n\t\t\t\t)\n\t\t)));\n\t\tconst maxArea = maxR * maxR * Math.PI;\n\t\tconst area = ($$.isBubbleZType(d) ? $$.getBubbleZData(d.value, \"z\") : d.value) * (maxArea / max);\n\n\t\treturn Math.sqrt(area / Math.PI);\n\t},\n\n\t/**\n\t * Get bubble dimension data\n\t * @param {Object|Array} d data value\n\t * @param {String} type - y or z\n\t * @return {Number}\n\t * @private\n\t */\n\tgetBubbleZData(d, type) {\n\t\treturn isObject(d) ? d[type] : d[type === \"y\" ? 0 : 1];\n\t},\n\n\t/**\n\t * Determine if bubble has dimension data\n\t * @param {Object|array} d data value\n\t * @return {Boolean}\n\t * @private\n\t */\n\tisBubbleZType(d) {\n\t\tconst $$ = this;\n\n\t\treturn $$.isBubbleType(d) && (\n\t\t\t(isObject(d.value) && (\"z\" in d.value || \"y\" in d.value)) ||\n\t\t\t(isArray(d.value) && d.value.length === 2)\n\t\t);\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tarea as d3Area,\n\tline as d3Line\n} from \"d3-shape\";\nimport {\n\tmouse as d3Mouse,\n\tselect as d3Select\n} from \"d3-selection\";\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {extend, getRandom, isArray, isDefined, isFunction, isUndefined, isValue} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\tinitLine() {\n\t\tconst $$ = this;\n\n\t\t$$.main.select(`.${CLASS.chart}`).append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartLines);\n\t},\n\n\tupdateTargetsForLine(targets) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst classChartLine = $$.classChartLine.bind($$);\n\t\tconst classLines = $$.classLines.bind($$);\n\t\tconst classAreas = $$.classAreas.bind($$);\n\t\tconst classCircles = $$.classCircles.bind($$);\n\t\tconst classFocus = $$.classFocus.bind($$);\n\n\t\tconst mainLineUpdate = $$.main.select(`.${CLASS.chartLines}`)\n\t\t\t.selectAll(`.${CLASS.chartLine}`)\n\t\t\t.data(targets)\n\t\t\t.attr(\"class\", d => classChartLine(d) + classFocus(d));\n\n\t\tconst mainLineEnter = mainLineUpdate.enter().append(\"g\")\n\t\t\t.attr(\"class\", classChartLine)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.style(\"pointer-events\", \"none\");\n\n\t\t// Lines for each data\n\t\tmainLineEnter.append(\"g\")\n\t\t\t.attr(\"class\", classLines);\n\n\t\t// Areas\n\t\tmainLineEnter.append(\"g\")\n\t\t\t.attr(\"class\", classAreas);\n\n\t\tif (config.point_show) {\n\t\t\t// Circles for each data point on lines\n\t\t\tconfig.data_selection_enabled && mainLineEnter.append(\"g\")\n\t\t\t\t.attr(\"class\", d => $$.generateClass(CLASS.selectedCircles, d.id));\n\n\t\t\tmainLineEnter.append(\"g\")\n\t\t\t\t.attr(\"class\", classCircles)\n\t\t\t\t.style(\"cursor\", d => (config.data_selection_isselectable(d) ? \"pointer\" : null));\n\t\t}\n\n\t\t// Update date for selected circles\n\t\ttargets.forEach(t => {\n\t\t\t$$.main.selectAll(`.${CLASS.selectedCircles}${$$.getTargetSelectorSuffix(t.id)}`)\n\t\t\t\t.selectAll(`${CLASS.selectedCircle}`)\n\t\t\t\t.each(d => {\n\t\t\t\t\td.value = t.values[d.index].value;\n\t\t\t\t});\n\t\t});\n\n\t\t// MEMO: can not keep same color...\n\t\t// mainLineUpdate.exit().remove();\n\t},\n\n\tupdateLine(durationForExit) {\n\t\tconst $$ = this;\n\n\t\t$$.mainLine = $$.main\n\t\t\t.selectAll(`.${CLASS.lines}`)\n\t\t\t.selectAll(`.${CLASS.line}`)\n\t\t\t.data($$.lineData.bind($$));\n\n\t\t$$.mainLine.exit().transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.mainLine = $$.mainLine.enter()\n\t\t\t.append(\"path\")\n\t\t\t.attr(\"class\", d => `${$$.classLine.bind($$)(d)} ${$$.extraLineClasses(d) || \"\"}`)\n\t\t\t.style(\"stroke\", $$.color)\n\t\t\t.merge($$.mainLine)\n\t\t\t.style(\"opacity\", $$.initialOpacity.bind($$))\n\t\t\t.style(\"shape-rendering\", d => ($$.isStepType(d) ? \"crispEdges\" : \"\"))\n\t\t\t.attr(\"transform\", null);\n\t},\n\n\tredrawLine(drawLine, withTransition) {\n\t\treturn [\n\t\t\t(withTransition ? this.mainLine.transition(getRandom()) : this.mainLine)\n\t\t\t\t.attr(\"d\", drawLine)\n\t\t\t\t.style(\"stroke\", this.color)\n\t\t\t\t.style(\"opacity\", \"1\")\n\t\t];\n\t},\n\n\t/**\n\t * Get the curve interpolate\n\t * @param {Array} d Data object\n\t * @return {Function}\n\t * @private\n\t */\n\tgetCurve(d) {\n\t\tconst $$ = this;\n\t\tconst isRotatedStepType = $$.config.axis_rotated && $$.isStepType(d);\n\n\t\t// when is step & rotated, should be computed in different way\n\t\t// https://github.com/naver/billboard.js/issues/471\n\t\treturn isRotatedStepType ? context => {\n\t\t\tconst step = $$.getInterpolate(d)(context);\n\n\t\t\t// keep the original method\n\t\t\tstep.orgPoint = step.point;\n\n\t\t\t// to get rotated path data\n\t\t\tstep.pointRotated = function(x, y) {\n\t\t\t\tthis._point === 1 && (this._point = 2);\n\n\t\t\t\tconst y1 = this._y * (1 - this._t) + y * this._t;\n\n\t\t\t\tthis._context.lineTo(this._x, y1);\n\t\t\t\tthis._context.lineTo(x, y1);\n\n\t\t\t\tthis._x = x;\n\t\t\t\tthis._y = y;\n\t\t\t};\n\n\t\t\tstep.point = function(x, y) {\n\t\t\t\tthis._point === 0 ? this.orgPoint(x, y) : this.pointRotated(x, y);\n\t\t\t};\n\n\t\t\treturn step;\n\t\t} : $$.getInterpolate(d);\n\t},\n\n\tgenerateDrawLine(lineIndices, isSub) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst lineConnectNull = config.line_connectNull;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\tconst getPoints = $$.generateGetLinePoints(lineIndices, isSub);\n\t\tconst yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale;\n\n\t\tconst xValue = d => (isSub ? $$.subxx : $$.xx).call($$, d);\n\t\tconst yValue = (d, i) => ($$.isGrouped(d.id) ?\n\t\t\tgetPoints(d, i)[0][1] :\n\t\t\tyScaleGetter.call($$, d.id)($$.getBaseValue(d))\n\t\t);\n\n\t\tlet line = d3Line();\n\n\t\tline = isRotated ?\n\t\t\tline.x(yValue).y(xValue) : line.x(xValue).y(yValue);\n\n\t\tif (!lineConnectNull) {\n\t\t\tline = line.defined(d => $$.getBaseValue(d) !== null);\n\t\t}\n\n\t\tconst x = isSub ? $$.subX : $$.x;\n\n\t\treturn d => {\n\t\t\tconst y = yScaleGetter.call($$, d.id);\n\t\t\tlet values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;\n\t\t\tlet x0 = 0;\n\t\t\tlet y0 = 0;\n\t\t\tlet path;\n\n\t\t\tif ($$.isLineType(d)) {\n\t\t\t\tconst regions = config.data_regions[d.id];\n\n\t\t\t\tif (regions) {\n\t\t\t\t\tpath = $$.lineWithRegions(values, x, y, regions);\n\t\t\t\t} else {\n\t\t\t\t\tif ($$.isStepType(d)) {\n\t\t\t\t\t\tvalues = $$.convertValuesToStep(values);\n\t\t\t\t\t}\n\n\t\t\t\t\tpath = line.curve($$.getCurve(d))(values);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (values[0]) {\n\t\t\t\t\tx0 = x(values[0].x);\n\t\t\t\t\ty0 = y(values[0].value);\n\t\t\t\t}\n\n\t\t\t\tpath = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;\n\t\t\t}\n\n\t\t\treturn path || \"M 0 0\";\n\t\t};\n\t},\n\n\tgenerateGetLinePoints(lineIndices, isSubValue) { // partial duplication of generateGetBarPoints\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isSub = !!isSubValue;\n\t\tconst x = $$.getShapeX(0, lineIndices, isSub);\n\t\tconst y = $$.getShapeY(isSub);\n\t\tconst lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, isSub);\n\t\tconst yScale = isSub ? $$.getSubYScale : $$.getYScale;\n\n\t\treturn (d, i) => {\n\t\t\tconst y0 = yScale.call($$, d.id)(0);\n\t\t\tconst offset = lineOffset(d, i) || y0; // offset is for stacked area chart\n\t\t\tconst posX = x(d);\n\t\t\tlet posY = y(d);\n\n\t\t\t// fix posY not to overflow opposite quadrant\n\t\t\tif (config.axis_rotated && (\n\t\t\t\t(d.value > 0 && posY < y0) || (d.value < 0 && y0 < posY)\n\t\t\t)) {\n\t\t\t\tposY = y0;\n\t\t\t}\n\n\t\t\t// 1 point that marks the line position\n\t\t\tconst point = [posX, posY - (y0 - offset)];\n\n\t\t\treturn [\n\t\t\t\tpoint,\n\t\t\t\tpoint, // from here and below, needed for compatibility\n\t\t\t\tpoint,\n\t\t\t\tpoint\n\t\t\t];\n\t\t};\n\t},\n\n\tlineWithRegions(d, x, y, _regions) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst isTimeSeries = $$.isTimeSeries();\n\t\tconst xOffset = $$.isCategorized() ? 0.5 : 0;\n\t\tconst regions = [];\n\t\tconst dasharray = \"2 2\"; // default value\n\n\t\tlet xp;\n\t\tlet yp;\n\t\tlet diff;\n\t\tlet diffx2;\n\n\t\t// check weather data is within region\n\t\tconst isWithinRegions = (withinX, withinRegions) => {\n\t\t\tfor (let i = 0, reg; (reg = withinRegions[i]); i++) {\n\t\t\t\tif (reg.start < withinX && withinX <= reg.end) {\n\t\t\t\t\treturn reg.style;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t};\n\n\t\t// Check start/end of regions\n\t\tif (isDefined(_regions)) {\n\t\t\tconst getValue = (v, def) => (\n\t\t\t\tisUndefined(v) ? def : (isTimeSeries ? $$.parseDate(v) : v)\n\t\t\t);\n\n\t\t\tfor (let i = 0, reg; (reg = _regions[i]); i++) {\n\t\t\t\tconst start = getValue(reg.start, d[0].x);\n\t\t\t\tconst end = getValue(reg.end, d[d.length - 1].x);\n\t\t\t\tconst style = reg.style || {dasharray};\n\n\t\t\t\tregions[i] = {start, end, style};\n\t\t\t}\n\t\t}\n\n\t\t// Set scales\n\t\tconst xValue = isRotated ? dt => y(dt.value) : dt => x(dt.x);\n\t\tconst yValue = isRotated ? dt => x(dt.x) : dt => y(dt.value);\n\n\t\t// Define svg generator function for region\n\t\tconst generateM = points => `M${points[0][0]},${points[0][1]}L${points[1][0]},${points[1][1]}`;\n\n\t\tconst sWithRegion = isTimeSeries ? (d0, d1, k, timeseriesDiff) => {\n\t\t\tconst x0 = d0.x.getTime();\n\t\t\tconst xDiff = d1.x - d0.x;\n\t\t\tconst xv0 = new Date(x0 + xDiff * k);\n\t\t\tconst xv1 = new Date(x0 + xDiff * (k + timeseriesDiff));\n\n\t\t\tconst points = isRotated ?\n\t\t\t\t[[y(yp(k)), x(xv0)], [y(yp(k + diff)), x(xv1)]] :\n\t\t\t\t[[x(xv0), y(yp(k))], [x(xv1), y(yp(k + diff))]];\n\n\t\t\treturn generateM(points);\n\t\t} : (d0, d1, k, otherDiff) => {\n\t\t\tconst points = isRotated ?\n\t\t\t\t[[y(yp(k), true), x(xp(k))], [y(yp(k + otherDiff), true), x(xp(k + otherDiff))]] :\n\t\t\t\t[[x(xp(k), true), y(yp(k))], [x(xp(k + otherDiff), true), y(yp(k + otherDiff))]];\n\n\t\t\treturn generateM(points);\n\t\t};\n\n\t\t// Generate\n\t\tlet path = \"\";\n\n\t\tfor (let i = 0, data; (data = d[i]); i++) {\n\t\t\tconst prevData = d[i - 1];\n\t\t\tconst hasPrevData = prevData && isValue(prevData.value);\n\t\t\tlet style = isWithinRegions(data.x, regions);\n\n\t\t\t// https://github.com/naver/billboard.js/issues/1172\n\t\t\tif (!isValue(data.value)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Draw as normal\n\t\t\tif (isUndefined(regions) || !style || !hasPrevData) {\n\t\t\t\tpath += `${i && hasPrevData ? \"L\" : \"M\"}${xValue(data)},${yValue(data)}`;\n\t\t\t} else if (hasPrevData) {\n\t\t\t\ttry {\n\t\t\t\t\tstyle = style.dasharray.split(\" \");\n\t\t\t\t} catch (e) {\n\t\t\t\t\tstyle = dasharray.split(\" \");\n\t\t\t\t}\n\n\t\t\t\t// Draw with region // TODO: Fix for horizotal charts\n\t\t\t\txp = $$.getScale(prevData.x + xOffset, data.x + xOffset, isTimeSeries);\n\t\t\t\typ = $$.getScale(prevData.value, data.value);\n\n\t\t\t\tconst dx = x(data.x) - x(prevData.x);\n\t\t\t\tconst dy = y(data.value) - y(prevData.value);\n\t\t\t\tconst dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n\n\t\t\t\tdiff = style[0] / dd;\n\t\t\t\tdiffx2 = diff * style[1];\n\n\t\t\t\tfor (let j = diff; j <= 1; j += diffx2) {\n\t\t\t\t\tpath += sWithRegion(prevData, data, j, diff);\n\n\t\t\t\t\t// to make sure correct line drawing\n\t\t\t\t\tif (j + diffx2 >= 1) {\n\t\t\t\t\t\tpath += sWithRegion(prevData, data, 1, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn path;\n\t},\n\n\tupdateAreaGradient() {\n\t\tconst $$ = this;\n\n\t\t$$.data.targets.forEach(d => {\n\t\t\tconst id = `${$$.datetimeId}-areaGradient${$$.getTargetSelectorSuffix(d.id)}`;\n\n\t\t\tif ($$.isAreaType(d) && $$.defs.select(`#${id}`).empty()) {\n\t\t\t\tconst color = $$.color(d);\n\t\t\t\tconst {\n\t\t\t\t\tx = [0, 0],\n\t\t\t\t\ty = [0, 1],\n\t\t\t\t\tstops = [[0, color, 1], [1, color, 0]]\n\t\t\t\t} = $$.config.area_linearGradient;\n\n\t\t\t\tconst linearGradient = $$.defs.append(\"linearGradient\")\n\t\t\t\t\t.attr(\"id\", `${id}`)\n\t\t\t\t\t.attr(\"x1\", x[0])\n\t\t\t\t\t.attr(\"x2\", x[1])\n\t\t\t\t\t.attr(\"y1\", y[0])\n\t\t\t\t\t.attr(\"y2\", y[1]);\n\n\t\t\t\tstops.forEach(v => {\n\t\t\t\t\tconst stopColor = isFunction(v[1]) ? v[1](d.id) : v[1];\n\n\t\t\t\t\tlinearGradient.append(\"stop\")\n\t\t\t\t\t\t.attr(\"offset\", v[0])\n\t\t\t\t\t\t.attr(\"stop-color\", stopColor || color)\n\t\t\t\t\t\t.attr(\"stop-opacity\", v[2]);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t},\n\n\tupdateAreaColor(d) {\n\t\tconst $$ = this;\n\n\t\treturn $$.config.area_linearGradient ?\n\t\t\t`url(#${$$.datetimeId}-areaGradient${$$.getTargetSelectorSuffix(d.id)})` :\n\t\t\t$$.color(d);\n\t},\n\n\tupdateArea(durationForExit) {\n\t\tconst $$ = this;\n\n\t\t$$.config.area_linearGradient && $$.updateAreaGradient();\n\n\t\t$$.mainArea = $$.main.selectAll(`.${CLASS.areas}`)\n\t\t\t.selectAll(`.${CLASS.area}`)\n\t\t\t.data($$.lineData.bind($$));\n\n\t\t$$.mainArea.exit().transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.mainArea = $$.mainArea.enter().append(\"path\")\n\t\t\t.attr(\"class\", $$.classArea.bind($$))\n\t\t\t.style(\"fill\", $$.updateAreaColor.bind($$))\n\t\t\t.style(\"opacity\", function() {\n\t\t\t\t$$.orgAreaOpacity = d3Select(this).style(\"opacity\");\n\t\t\t\treturn \"0\";\n\t\t\t})\n\t\t\t.merge($$.mainArea);\n\n\t\t$$.mainArea\n\t\t\t.style(\"opacity\", $$.orgAreaOpacity);\n\t},\n\n\tredrawArea(drawArea, withTransition) {\n\t\tconst $$ = this;\n\n\t\treturn [\n\t\t\t(withTransition ? $$.mainArea.transition(getRandom()) : $$.mainArea)\n\t\t\t\t.attr(\"d\", drawArea)\n\t\t\t\t.style(\"fill\", $$.updateAreaColor.bind($$))\n\t\t\t\t.style(\"opacity\", d => String($$.isAreaRangeType(d) ? $$.orgAreaOpacity / 1.75 : $$.orgAreaOpacity))\n\t\t];\n\t},\n\n\t/**\n\t * Generate area path data\n\t * @param areaIndices\n\t * @param isSub\n\t * @return {function(*=): (*|string)}\n\t * @private\n\t */\n\tgenerateDrawArea(areaIndices, isSub) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst lineConnectNull = config.line_connectNull;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\tconst getPoints = $$.generateGetAreaPoints(areaIndices, isSub);\n\t\tconst yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale;\n\n\t\tconst xValue = d => (isSub ? $$.subxx : $$.xx).call($$, d);\n\t\tconst value0 = (d, i) => ($$.isGrouped(d.id) ?\n\t\t\tgetPoints(d, i)[0][1] :\n\t\t\tyScaleGetter.call($$, d.id)(\n\t\t\t\t$$.isAreaRangeType(d) ?\n\t\t\t\t\t$$.getAreaRangeData(d, \"high\") : 0\n\t\t\t));\n\t\tconst value1 = (d, i) => ($$.isGrouped(d.id) ?\n\t\t\tgetPoints(d, i)[1][1] :\n\t\t\tyScaleGetter.call($$, d.id)(\n\t\t\t\t$$.isAreaRangeType(d) ?\n\t\t\t\t\t$$.getAreaRangeData(d, \"low\") : d.value\n\t\t\t));\n\n\t\treturn d => {\n\t\t\tlet values = lineConnectNull ? $$.filterRemoveNull(d.values) : d.values;\n\t\t\tlet x0 = 0;\n\t\t\tlet y0 = 0;\n\t\t\tlet path;\n\n\t\t\tif ($$.isAreaType(d)) {\n\t\t\t\tlet area = d3Area();\n\n\t\t\t\tarea = isRotated ?\n\t\t\t\t\tarea.y(xValue)\n\t\t\t\t\t\t.x0(value0)\n\t\t\t\t\t\t.x1(value1) :\n\t\t\t\t\tarea.x(xValue)\n\t\t\t\t\t\t.y0(config.area_above ? 0 : value0)\n\t\t\t\t\t\t.y1(value1);\n\n\t\t\t\tif (!lineConnectNull) {\n\t\t\t\t\tarea = area.defined(d => $$.getBaseValue(d) !== null);\n\t\t\t\t}\n\n\t\t\t\tif ($$.isStepType(d)) {\n\t\t\t\t\tvalues = $$.convertValuesToStep(values);\n\t\t\t\t}\n\n\t\t\t\tpath = area.curve($$.getCurve(d))(values);\n\t\t\t} else {\n\t\t\t\tif (values[0]) {\n\t\t\t\t\tx0 = $$.x(values[0].x);\n\t\t\t\t\ty0 = $$.getYScale(d.id)(values[0].value);\n\t\t\t\t}\n\n\t\t\t\tpath = isRotated ? `M ${y0} ${x0}` : `M ${x0} ${y0}`;\n\t\t\t}\n\n\t\t\treturn path || \"M 0 0\";\n\t\t};\n\t},\n\n\tgenerateGetAreaPoints(areaIndices, isSub) {\n\t\t// partial duplication of generateGetBarPoints\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst x = $$.getShapeX(0, areaIndices, !!isSub);\n\t\tconst y = $$.getShapeY(!!isSub);\n\t\tconst areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub);\n\t\tconst yScale = isSub ? $$.getSubYScale : $$.getYScale;\n\n\t\treturn function(d, i) {\n\t\t\tconst y0 = yScale.call($$, d.id)(0);\n\t\t\tconst offset = areaOffset(d, i) || y0; // offset is for stacked area chart\n\t\t\tconst posX = x(d);\n\t\t\tlet posY = y(d);\n\n\t\t\t// fix posY not to overflow opposite quadrant\n\t\t\tif (config.axis_rotated && (\n\t\t\t\t(d.value > 0 && posY < y0) || (d.value < 0 && y0 < posY)\n\t\t\t)) {\n\t\t\t\tposY = y0;\n\t\t\t}\n\n\t\t\t// 1 point that marks the area position\n\t\t\treturn [\n\t\t\t\t[posX, offset],\n\t\t\t\t[posX, posY - (y0 - offset)],\n\t\t\t\t[posX, posY - (y0 - offset)], // needed for compatibility\n\t\t\t\t[posX, offset] // needed for compatibility\n\t\t\t];\n\t\t};\n\t},\n\n\tupdateCircle() {\n\t\tconst $$ = this;\n\n\t\tif (!$$.config.point_show) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.mainCircle = $$.main.selectAll(`.${CLASS.circles}`).selectAll(`.${CLASS.circle}`)\n\t\t\t.data(d => !$$.isBarType(d) && (\n\t\t\t\t!$$.isLineType(d) || $$.shouldDrawPointsForLine(d)\n\t\t\t) && $$.labelishData(d));\n\n\t\t$$.mainCircle.exit().remove();\n\n\t\tconst fn = $$.point(\"create\", this, $$.pointR.bind($$), $$.color);\n\n\t\t$$.mainCircle = $$.mainCircle.enter()\n\t\t\t.append(fn)\n\t\t\t.merge($$.mainCircle)\n\t\t\t.style(\"stroke\", $$.color)\n\t\t\t.style(\"opacity\", $$.initialOpacityForCircle.bind($$));\n\t},\n\n\tredrawCircle(cx, cy, withTransition, flow) {\n\t\tconst $$ = this;\n\t\tconst selectedCircles = $$.main.selectAll(`.${CLASS.selectedCircle}`);\n\n\t\tif (!$$.config.point_show) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst mainCircles = [];\n\n\t\t$$.mainCircle.each(function(d) {\n\t\t\tconst fn = $$.point(\"update\", $$, cx, cy, $$.opacityForCircle.bind($$), $$.color, withTransition, flow, selectedCircles).bind(this);\n\t\t\tconst result = fn(d);\n\n\t\t\tmainCircles.push(result);\n\t\t});\n\n\t\tconst posAttr = $$.isCirclePoint() ? \"c\" : \"\";\n\n\t\treturn [\n\t\t\tmainCircles,\n\t\t\tselectedCircles\n\t\t\t\t.attr(`${posAttr}x`, cx)\n\t\t\t\t.attr(`${posAttr}y`, cy)\n\t\t];\n\t},\n\n\tcircleX(d) {\n\t\tconst $$ = this;\n\t\tconst hasValue = isValue(d.x);\n\n\t\treturn $$.config.zoom_enabled && $$.zoomScale ?\n\t\t\t(hasValue ? $$.zoomScale(d.x) : null) :\n\t\t\t(hasValue ? $$.x(d.x) : null);\n\t},\n\n\tupdateCircleY() {\n\t\tconst $$ = this;\n\t\tconst getPoints = $$.generateGetLinePoints($$.getShapeIndices($$.isLineType), false);\n\n\t\t$$.circleY = (d, i) => {\n\t\t\tconst id = d.id;\n\n\t\t\treturn $$.isGrouped(id) ?\n\t\t\t\tgetPoints(d, i)[0][1] :\n\t\t\t\t$$.getYScale(id)($$.getBaseValue(d));\n\t\t};\n\t},\n\n\tgetCircles(i, id) {\n\t\tconst $$ = this;\n\t\tconst suffix = (isValue(i) ? `-${i}` : ``);\n\n\t\treturn (id ? $$.main.selectAll(`.${CLASS.circles}${$$.getTargetSelectorSuffix(id)}`) : $$.main)\n\t\t\t.selectAll(`.${CLASS.circle}${suffix}`);\n\t},\n\n\texpandCircles(i, id, reset) {\n\t\tconst $$ = this;\n\t\tconst r = $$.pointExpandedR.bind($$);\n\n\t\treset && $$.unexpandCircles();\n\n\t\tconst circles = $$.getCircles(i, id).classed(CLASS.EXPANDED, true);\n\t\tconst scale = r(circles) / $$.config.point_r;\n\t\tconst ratio = 1 - scale;\n\n\t\tif ($$.isCirclePoint()) {\n\t\t\tcircles.attr(\"r\", r);\n\t\t} else {\n\t\t\t// transform must be applied to each node individually\n\t\t\tcircles.each(function() {\n\t\t\t\tconst point = d3Select(this);\n\n\t\t\t\tif (this.tagName === \"circle\") {\n\t\t\t\t\tpoint.attr(\"r\", r);\n\t\t\t\t} else {\n\t\t\t\t\tconst {width, height} = this.getBBox();\n\t\t\t\t\tconst x = ratio * (+point.attr(\"x\") + width / 2);\n\t\t\t\t\tconst y = ratio * (+point.attr(\"y\") + height / 2);\n\n\t\t\t\t\tpoint.attr(\"transform\", `translate(${x} ${y}) scale(${scale})`);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\tunexpandCircles(i) {\n\t\tconst $$ = this;\n\t\tconst r = $$.pointR.bind($$);\n\n\t\tconst circles = $$.getCircles(i)\n\t\t\t.filter(function() {\n\t\t\t\treturn d3Select(this).classed(CLASS.EXPANDED);\n\t\t\t})\n\t\t\t.classed(CLASS.EXPANDED, false);\n\n\t\tcircles.attr(\"r\", r);\n\n\t\t!$$.isCirclePoint() &&\n\t\t\tcircles.attr(\"transform\", `scale(${r(circles) / $$.config.point_r})`);\n\t},\n\n\tpointR(d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst pointR = config.point_r;\n\t\tlet r = pointR;\n\n\t\tif ($$.isStepType(d)) {\n\t\t\tr = 0;\n\t\t} else if ($$.isBubbleType(d)) {\n\t\t\tr = $$.getBubbleR(d);\n\t\t} else if (isFunction(pointR)) {\n\t\t\tr = pointR(d);\n\t\t}\n\n\t\treturn r;\n\t},\n\n\tpointExpandedR(d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst scale = $$.isBubbleType(d) ? 1.15 : 1.75;\n\n\t\treturn config.point_focus_expand_enabled ?\n\t\t\t(config.point_focus_expand_r || $$.pointR(d) * scale) : $$.pointR(d);\n\t},\n\n\tpointSelectR(d) {\n\t\tconst $$ = this;\n\t\tconst selectR = $$.config.point_select_r;\n\n\t\treturn isFunction(selectR) ?\n\t\t\tselectR(d) : (selectR || $$.pointR(d) * 4);\n\t},\n\n\tisWithinCircle(node, r) {\n\t\tconst mouse = d3Mouse(node);\n\t\tconst element = d3Select(node);\n\t\tconst prefix = this.isCirclePoint() ? \"c\" : \"\";\n\n\t\tlet cx = +element.attr(`${prefix}x`);\n\t\tlet cy = +element.attr(`${prefix}y`);\n\n\t\t// if node don't have cx/y or x/y attribute value\n\t\tif (!(cx || cy) && node.nodeType === 1) {\n\t\t\tconst {x, y} = node.getBBox ? node.getBBox() : node.getBoundingClientRect();\n\n\t\t\tcx = x;\n\t\t\tcy = y;\n\t\t}\n\n\t\treturn Math.sqrt(\n\t\t\tMath.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)\n\t\t) < (r || this.config.point_sensitivity);\n\t},\n\n\tisWithinStep(that, y) {\n\t\treturn Math.abs(y - d3Mouse(that)[1]) < 30;\n\t},\n\n\tshouldDrawPointsForLine(d) {\n\t\tconst linePoint = this.config.line_point;\n\n\t\treturn linePoint === true ||\n\t\t\t(isArray(linePoint) && linePoint.indexOf(d.id) !== -1);\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tnamespaces as d3Namespaces,\n\tselect as d3Select\n} from \"d3-selection\";\nimport CLASS from \"../config/classes\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {document} from \"../internals/browser\";\nimport {getRandom, isFunction, isObject, isObjectType, toArray, extend, notEmpty} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\thasValidPointType(type) {\n\t\treturn /^(circle|rect(angle)?|polygon|ellipse|use)$/i.test(type || this.config.point_type);\n\t},\n\n\thasValidPointDrawMethods(type) {\n\t\tconst pointType = type || this.config.point_type;\n\n\t\treturn isObjectType(pointType) &&\n\t\t\tisFunction(pointType.create) && isFunction(pointType.update);\n\t},\n\n\tinsertPointInfoDefs(point, id) {\n\t\tconst $$ = this;\n\t\tconst copyAttr = (from, target) => {\n\t\t\tconst attribs = from.attributes;\n\n\t\t\tfor (let i = 0, name; (name = attribs[i]); i++) {\n\t\t\t\tname = name.name;\n\t\t\t\ttarget.setAttribute(name, from.getAttribute(name));\n\t\t\t}\n\t\t};\n\n\t\tconst doc = new DOMParser().parseFromString(point, \"image/svg+xml\");\n\t\tconst node = doc.documentElement;\n\t\tconst clone = document.createElementNS(d3Namespaces.svg, node.nodeName.toLowerCase());\n\n\t\tclone.id = id;\n\t\tclone.style.fill = \"inherit\";\n\t\tclone.style.stroke = \"inherit\";\n\n\t\tcopyAttr(node, clone);\n\n\t\tif (node.childNodes && node.childNodes.length) {\n\t\t\tconst parent = d3Select(clone);\n\n\t\t\tif (\"innerHTML\" in clone) {\n\t\t\t\tparent.html(node.innerHTML);\n\t\t\t} else {\n\t\t\t\ttoArray(node.childNodes).forEach(v => {\n\t\t\t\t\tcopyAttr(v, parent.append(v.tagName).node());\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t$$.defs.node().appendChild(clone);\n\t},\n\n\tpointFromDefs(id) {\n\t\treturn this.defs.select(`#${id}`);\n\t},\n\n\tupdatePointClass(d) {\n\t\tconst $$ = this;\n\t\tlet pointClass = false;\n\n\t\tif (isObject(d) || $$.mainCircle) {\n\t\t\tpointClass = d === true ?\n\t\t\t\t$$.mainCircle.each(function(d) {\n\t\t\t\t\tlet className = $$.classCircle.bind($$)(d);\n\n\t\t\t\t\tif (this.getAttribute(\"class\").indexOf(CLASS.EXPANDED) > -1) {\n\t\t\t\t\t\tclassName += ` ${CLASS.EXPANDED}`;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.setAttribute(\"class\", className);\n\t\t\t\t}) : $$.classCircle(d);\n\t\t}\n\n\t\treturn pointClass;\n\t},\n\n\tgeneratePoint() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst ids = [];\n\t\tconst pattern = notEmpty(config.point_pattern) ? config.point_pattern : [config.point_type];\n\n\t\treturn function(method, context, ...args) {\n\t\t\treturn function(d) {\n\t\t\t\tconst id = d.id || (d.data && d.data.id) || d;\n\t\t\t\tconst element = d3Select(this);\n\n\t\t\t\tids.indexOf(id) < 0 && ids.push(id);\n\n\t\t\t\tlet point = pattern[ids.indexOf(id) % pattern.length];\n\n\t\t\t\tif ($$.hasValidPointType(point)) {\n\t\t\t\t\tpoint = $$[point];\n\t\t\t\t} else if (!$$.hasValidPointDrawMethods(point)) {\n\t\t\t\t\tconst pointId = `${$$.datetimeId}-point-${id}`;\n\t\t\t\t\tconst pointFromDefs = $$.pointFromDefs(pointId);\n\n\t\t\t\t\tif (pointFromDefs.size() < 1) {\n\t\t\t\t\t\t$$.insertPointInfoDefs(point, pointId);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (method === \"create\") {\n\t\t\t\t\t\treturn $$.custom.create.bind(context)(element, pointId, ...args);\n\t\t\t\t\t} else if (method === \"update\") {\n\t\t\t\t\t\treturn $$.custom.update.bind(context)(element, ...args);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn point[method].bind(context)(element, ...args);\n\t\t\t};\n\t\t};\n\t},\n\n\tgetTransitionName() {\n\t\treturn getRandom();\n\t},\n\n\tcustom: {\n\t\tcreate(element, id, sizeFn, fillStyleFn) {\n\t\t\treturn element.append(\"use\")\n\t\t\t\t.attr(\"xlink:href\", `#${id}`)\n\t\t\t\t.attr(\"class\", this.updatePointClass.bind(this))\n\t\t\t\t.style(\"fill\", fillStyleFn)\n\t\t\t\t.node();\n\t\t},\n\n\t\tupdate(element, xPosFn, yPosFn, opacityStyleFn, fillStyleFn,\n\t\t\twithTransition, flow, selectedCircles) {\n\t\t\tconst $$ = this;\n\t\t\tconst {width, height} = element.node().getBBox();\n\n\t\t\tconst xPosFn2 = d => xPosFn(d) - width / 2;\n\t\t\tconst yPosFn2 = d => yPosFn(d) - height / 2;\n\t\t\tlet mainCircles = element;\n\n\t\t\tif (withTransition) {\n\t\t\t\tconst transitionName = $$.getTransitionName();\n\n\t\t\t\tflow && mainCircles.attr(\"x\", xPosFn2);\n\n\t\t\t\tmainCircles = mainCircles.transition(transitionName);\n\t\t\t\tselectedCircles.transition($$.getTransitionName());\n\t\t\t}\n\n\t\t\treturn mainCircles\n\t\t\t\t.attr(\"x\", xPosFn2)\n\t\t\t\t.attr(\"y\", yPosFn2)\n\t\t\t\t.style(\"opacity\", opacityStyleFn)\n\t\t\t\t.style(\"fill\", fillStyleFn);\n\t\t}\n\t},\n\n\t// 'circle' data point\n\tcircle: {\n\t\tcreate(element, sizeFn, fillStyleFn) {\n\t\t\treturn element.append(\"circle\")\n\t\t\t\t.attr(\"class\", this.updatePointClass.bind(this))\n\t\t\t\t.attr(\"r\", sizeFn)\n\t\t\t\t.style(\"fill\", fillStyleFn)\n\t\t\t\t.node();\n\t\t},\n\n\t\tupdate(element, xPosFn, yPosFn, opacityStyleFn, fillStyleFn,\n\t\t\twithTransition, flow, selectedCircles) {\n\t\t\tconst $$ = this;\n\t\t\tlet mainCircles = element;\n\n\t\t\t// when '.load()' called, bubble size should be updated\n\t\t\tif ($$.hasType(\"bubble\")) {\n\t\t\t\tmainCircles.attr(\"r\", $$.pointR.bind($$));\n\t\t\t}\n\n\t\t\tif (withTransition) {\n\t\t\t\tconst transitionName = $$.getTransitionName();\n\n\t\t\t\tflow && mainCircles.attr(\"cx\", xPosFn);\n\n\t\t\t\tif (mainCircles.attr(\"cx\")) {\n\t\t\t\t\tmainCircles = mainCircles.transition(transitionName);\n\t\t\t\t}\n\n\t\t\t\tselectedCircles.transition($$.getTransitionName());\n\t\t\t}\n\n\t\t\treturn mainCircles\n\t\t\t\t.attr(\"cx\", xPosFn)\n\t\t\t\t.attr(\"cy\", yPosFn)\n\t\t\t\t.style(\"opacity\", opacityStyleFn)\n\t\t\t\t.style(\"fill\", fillStyleFn);\n\t\t}\n\t},\n\n\t// 'rectangle' data point\n\trectangle: {\n\t\tcreate(element, sizeFn, fillStyleFn) {\n\t\t\tconst rectSizeFn = d => sizeFn(d) * 2.0;\n\n\t\t\treturn element.append(\"rect\")\n\t\t\t\t.attr(\"class\", this.updatePointClass.bind(this))\n\t\t\t\t.attr(\"width\", rectSizeFn)\n\t\t\t\t.attr(\"height\", rectSizeFn)\n\t\t\t\t.style(\"fill\", fillStyleFn)\n\t\t\t\t.node();\n\t\t},\n\n\t\tupdate(element, xPosFn, yPosFn, opacityStyleFn, fillStyleFn,\n\t\t\twithTransition, flow, selectedCircles) {\n\t\t\tconst $$ = this;\n\t\t\tconst r = $$.config.point_r;\n\t\t\tconst rectXPosFn = d => xPosFn(d) - r;\n\t\t\tconst rectYPosFn = d => yPosFn(d) - r;\n\n\t\t\tlet mainCircles = element;\n\n\t\t\tif (withTransition) {\n\t\t\t\tconst transitionName = $$.getTransitionName();\n\n\t\t\t\tflow && mainCircles.attr(\"x\", rectXPosFn);\n\n\t\t\t\tmainCircles = mainCircles.transition(transitionName);\n\t\t\t\tselectedCircles.transition($$.getTransitionName());\n\t\t\t}\n\n\t\t\treturn mainCircles\n\t\t\t\t.attr(\"x\", rectXPosFn)\n\t\t\t\t.attr(\"y\", rectYPosFn)\n\t\t\t\t.style(\"opacity\", opacityStyleFn)\n\t\t\t\t.style(\"fill\", fillStyleFn);\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tevent as d3Event\n} from \"d3-selection\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend, getMinMax, getRange, isDefined, isEmpty, isNumber, isUndefined, setTextValue, toArray} from \"../internals/util\";\n\n/**\n * Get the position value\n * @param {Boolean} isClockwise If the direction is clockwise\n * @param {String} type Coordinate type 'x' or 'y'\n * @param {Number} edge Number of edge\n * @param {Number} pos The indexed position\n * @param {Number} range\n * @param {Number} ratio\n * @return {number}\n * @private\n */\nfunction getPosition(isClockwise, type, edge, pos, range, ratio) {\n\tconst index = isClockwise && pos > 0 ? edge - pos : pos;\n\tconst r = 2 * Math.PI;\n\tconst func = type === \"x\" ? Math.sin : Math.cos;\n\n\treturn range * (1 - ratio * func(index * r / edge));\n}\n\n// cache key\nconst cacheKey = \"$radarPoints\";\n\nextend(ChartInternal.prototype, {\n\tinitRadar() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif ($$.hasType(\"radar\")) {\n\t\t\t$$.radars = $$.main.select(`.${CLASS.chart}`).append(\"g\")\n\t\t\t\t.attr(\"class\", CLASS.chartRadars);\n\n\t\t\t// level\n\t\t\t$$.radars.levels = $$.radars.append(\"g\")\n\t\t\t\t.attr(\"class\", CLASS.levels);\n\n\t\t\t// axis\n\t\t\t$$.radars.axes = $$.radars.append(\"g\")\n\t\t\t\t.attr(\"class\", CLASS.axis);\n\n\t\t\t// shapes\n\t\t\t$$.radars.shapes = $$.radars.append(\"g\")\n\t\t\t\t.attr(\"class\", CLASS.shapes);\n\n\t\t\t$$.maxValue = config.radar_axis_max || $$.getMinMaxData().max[0].value;\n\t\t}\n\t},\n\n\tgetRadarSize() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst padding = config.axis_x_categories.length < 4 ? -20 : 10;\n\t\tconst size = (Math.min($$.arcWidth, $$.arcHeight) - padding) / 2;\n\n\t\treturn [size, size];\n\t},\n\n\tupdateTargetsForRadar(targets) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif (isEmpty(config.axis_x_categories)) {\n\t\t\tconfig.axis_x_categories = getRange(0, getMinMax(\"max\", targets.map(v => v.values.length)));\n\t\t}\n\n\t\t$$.generateRadarPoints();\n\t},\n\n\tgetRadarPosition(type, index, range, ratio) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst [width, height] = $$.getRadarSize();\n\t\tconst edge = config.axis_x_categories.length;\n\t\tconst isClockwise = config.radar_direction_clockwise;\n\n\t\tconst pos = toArray(type).map(v => getPosition(\n\t\t\tisClockwise,\n\t\t\tv,\n\t\t\tedge,\n\t\t\tindex,\n\t\t\tisDefined(range) ? range : (type === \"x\" ? width : height),\n\t\t\tisNumber(ratio) ? ratio : config.radar_size_ratio\n\t\t));\n\n\t\treturn pos.length === 1 ? pos[0] : pos;\n\t},\n\n\t/**\n\t * Generate data points\n\t * @private\n\t */\n\tgenerateRadarPoints() {\n\t\tconst $$ = this;\n\t\tconst targets = $$.data.targets;\n\n\t\tconst [width, height] = $$.getRadarSize();\n\t\tconst points = $$.getCache(cacheKey) || {};\n\t\tconst size = points._size;\n\n\t\t// recalculate position only when the previous dimension has been changed\n\t\tif (!size || (size.width !== width && size.height !== height)) {\n\t\t\ttargets.forEach(d => {\n\t\t\t\tpoints[d.id] = d.values.map((v, i) => (\n\t\t\t\t\t$$.getRadarPosition([\"x\", \"y\"], i, undefined, $$.getRatio(\"radar\", v))\n\t\t\t\t));\n\t\t\t});\n\n\t\t\tpoints._size = {width, height};\n\t\t\t$$.addCache(cacheKey, points);\n\t\t}\n\t},\n\n\tredrawRadar(durationForExit) {\n\t\tconst $$ = this;\n\t\tconst translate = $$.getTranslate(\"radar\");\n\n\t\t// Adjust radar, circles and texts' position\n\t\tif (translate) {\n\t\t\t$$.radars.attr(\"transform\", translate);\n\t\t\t$$.main.selectAll(`.${CLASS.circles}`).attr(\"transform\", translate);\n\t\t\t$$.main.select(`.${CLASS.chartTexts}`).attr(\"transform\", translate);\n\n\t\t\t$$.generateRadarPoints();\n\t\t\t$$.updateRadarLevel();\n\t\t\t$$.updateRadarAxes();\n\t\t\t$$.updateRadarShape(durationForExit);\n\t\t}\n\t},\n\n\tgenerateGetRadarPoints() {\n\t\tconst $$ = this;\n\t\tconst points = $$.getCache(cacheKey);\n\n\t\treturn (d, i) => {\n\t\t\tconst point = points[d.id][i];\n\n\t\t\treturn [\n\t\t\t\tpoint,\n\t\t\t\tpoint,\n\t\t\t\tpoint,\n\t\t\t\tpoint\n\t\t\t];\n\t\t};\n\t},\n\n\tupdateRadarLevel() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst [width, height] = $$.getRadarSize();\n\t\tconst depth = config.radar_level_depth;\n\t\tconst edge = config.axis_x_categories.length;\n\t\tconst showText = config.radar_level_text_show;\n\n\t\tconst radarLevels = $$.radars.levels;\n\t\tconst levelData = getRange(0, depth);\n\n\t\tconst radius = config.radar_size_ratio * Math.min(width, height);\n\t\tconst levelRatio = levelData.map(l => radius * ((l + 1) / depth));\n\t\tconst levelTextFormat = config.radar_level_text_format;\n\n\t\t// Generate points\n\t\tconst points = levelData.map(v => {\n\t\t\tconst range = levelRatio[v];\n\t\t\tconst pos = getRange(0, edge).map(i => (\n\t\t\t\t$$.getRadarPosition([\"x\", \"y\"], i, range, 1)).join(\",\")\n\t\t\t);\n\n\t\t\treturn pos.join(\" \");\n\t\t});\n\n\t\tconst level = radarLevels\n\t\t\t.selectAll(`.${CLASS.level}`)\n\t\t\t.data(levelData);\n\n\t\tlevel.exit().remove();\n\n\t\tconst levelEnter = level.enter().append(\"g\")\n\t\t\t.attr(\"class\", (d, i) => `${CLASS.level} ${CLASS.level}-${i}`);\n\n\t\tlevelEnter.append(\"polygon\")\n\t\t\t.style(\"visibility\", config.radar_level_show ? null : \"hidden\");\n\n\t\tif (showText) {\n\t\t\tif (radarLevels.select(\"text\").empty()) {\n\t\t\t\tradarLevels\n\t\t\t\t\t.append(\"text\")\n\t\t\t\t\t.attr(\"dx\", \"-.5em\")\n\t\t\t\t\t.attr(\"dy\", \"-.7em\")\n\t\t\t\t\t.style(\"text-anchor\", \"end\")\n\t\t\t\t\t.text(() => levelTextFormat(0));\n\t\t\t}\n\n\t\t\tlevelEnter.append(\"text\")\n\t\t\t\t.attr(\"dx\", \"-.5em\")\n\t\t\t\t.style(\"text-anchor\", \"end\")\n\t\t\t\t.text(d => levelTextFormat(\n\t\t\t\t\t$$.maxValue / levelData.length * (d + 1)\n\t\t\t\t));\n\t\t}\n\n\t\tlevelEnter\n\t\t\t.merge(level)\n\t\t\t.attr(\"transform\", d => `translate(${width - levelRatio[d]}, ${height - levelRatio[d]})`)\n\t\t\t.selectAll(\"polygon\")\n\t\t\t.attr(\"points\", d => points[d]);\n\n\t\t// update level text position\n\t\tif (showText) {\n\t\t\tradarLevels.selectAll(\"text\")\n\t\t\t\t.attr(\"x\", d => (isUndefined(d) ? width : points[d].split(\",\")[0]))\n\t\t\t\t.attr(\"y\", d => (isUndefined(d) ? height : 0));\n\t\t}\n\t},\n\n\tupdateRadarAxes() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst [width, height] = $$.getRadarSize();\n\t\tconst categories = config.axis_x_categories;\n\n\t\tlet axis = $$.radars.axes.selectAll(\"g\")\n\t\t\t.data(categories);\n\n\t\taxis.exit().remove();\n\n\t\tconst axisEnter = axis.enter().append(\"g\")\n\t\t\t.attr(\"class\", (d, i) => `${CLASS.axis}-${i}`);\n\n\t\tconfig.radar_axis_line_show && axisEnter.append(\"line\");\n\t\tconfig.radar_axis_text_show && axisEnter.append(\"text\");\n\n\t\taxis = axisEnter.merge(axis);\n\n\t\t// axis line\n\t\tif (config.radar_axis_line_show) {\n\t\t\taxis.select(\"line\")\n\t\t\t\t.attr(\"x1\", width)\n\t\t\t\t.attr(\"y1\", height)\n\t\t\t\t.attr(\"x2\", (d, i) => $$.getRadarPosition(\"x\", i))\n\t\t\t\t.attr(\"y2\", (d, i) => $$.getRadarPosition(\"y\", i));\n\t\t}\n\n\t\t// axis text\n\t\tif (config.radar_axis_text_show) {\n\t\t\tconst {x = 0, y = 0} = config.radar_axis_text_position;\n\n\t\t\taxis.select(\"text\")\n\t\t\t\t.style(\"text-anchor\", \"middle\")\n\t\t\t\t.attr(\"dy\", \".5em\")\n\t\t\t\t.call(selection => {\n\t\t\t\t\tselection.each(function(d) {\n\t\t\t\t\t\tsetTextValue(d3Select(this), String(d), [-0.6, 1.2]);\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.datum((d, i) => ({index: i}))\n\t\t\t\t.attr(\"transform\", function(d) {\n\t\t\t\t\tif (isUndefined(this.width)) {\n\t\t\t\t\t\t// cache evaluated axis text width\n\t\t\t\t\t\tthis.width = this.getBoundingClientRect().width / 2;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet posX = $$.getRadarPosition(\"x\", d.index, undefined, 1);\n\t\t\t\t\tlet posY = Math.round($$.getRadarPosition(\"y\", d.index, undefined, 1));\n\n\t\t\t\t\tif (posX > width) {\n\t\t\t\t\t\tposX += this.width + x;\n\t\t\t\t\t} else if (Math.round(posX) < width) {\n\t\t\t\t\t\tposX -= this.width + x;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (posY > height) {\n\t\t\t\t\t\t// update vertical centered edge axis text dy position\n\t\t\t\t\t\tif (posY / 2 === height && this.firstChild.tagName === \"tspan\") {\n\t\t\t\t\t\t\tthis.firstChild.setAttribute(\"dy\", \"0em\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tposY += y;\n\t\t\t\t\t} else if (posY < height) {\n\t\t\t\t\t\tposY -= y;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `translate(${posX} ${posY})`;\n\t\t\t\t});\n\t\t}\n\n\t\t$$.bindEvent();\n\t},\n\n\tbindEvent() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif (config.interaction_enabled) {\n\t\t\tconst isMouse = $$.inputType === \"mouse\";\n\t\t\tconst getIndex = () => {\n\t\t\t\tlet target = d3Event.target;\n\n\t\t\t\t// in case of multilined axis text\n\t\t\t\tif (/tspan/i.test(target.tagName)) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\n\t\t\t\tconst d = d3Select(target).datum();\n\n\t\t\t\treturn d && Object.keys(d).length === 1 ? d.index : undefined;\n\t\t\t};\n\t\t\tconst hide = () => {\n\t\t\t\tconst index = getIndex();\n\t\t\t\tconst noIndex = isUndefined(index);\n\n\t\t\t\tif (isMouse || noIndex) {\n\t\t\t\t\tthis.hideTooltip();\n\t\t\t\t\tthis.unexpandCircles();\n\n\t\t\t\t\tif (isMouse) {\n\t\t\t\t\t\t$$.setOverOut(false, index);\n\t\t\t\t\t} else if (noIndex) {\n\t\t\t\t\t\t$$.callOverOutForTouch();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t$$.radars.select(`.${CLASS.axis}`)\n\t\t\t\t.on(isMouse ? \"mouseover \" : \"touchstart\", () => {\n\t\t\t\t\tif ($$.transiting) { // skip while transiting\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst index = getIndex();\n\n\t\t\t\t\t$$.selectRectForSingle($$.svg.node(), null, index);\n\t\t\t\t\tisMouse ? $$.setOverOut(true, index) : $$.callOverOutForTouch(index);\n\t\t\t\t})\n\t\t\t\t.on(\"mouseout\", isMouse ? hide : null);\n\n\t\t\tif (!isMouse) {\n\t\t\t\t$$.svg.on(\"touchstart\", hide);\n\t\t\t}\n\t\t}\n\t},\n\n\tupdateRadarShape(durationForExit) {\n\t\tconst $$ = this;\n\t\tconst targets = $$.data.targets;\n\t\tconst points = $$.getCache(cacheKey);\n\n\t\tconst areas = $$.radars.shapes\n\t\t\t.selectAll(\"polygon\")\n\t\t\t.data(targets);\n\n\t\tconst areasEnter = areas.enter().append(\"g\")\n\t\t\t.attr(\"class\", $$.classChartRadar.bind($$));\n\n\t\tareas.exit().transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.remove();\n\n\t\tareasEnter\n\t\t\t.append(\"polygon\")\n\t\t\t.merge(areas)\n\t\t\t.style(\"fill\", $$.color)\n\t\t\t.style(\"stroke\", $$.color)\n\t\t\t.attr(\"points\", d => points[d.id].join(\" \"));\n\t},\n\n\t/**\n\t * Get data point x coordinate\n\t * @param {Object} d Data object\n\t * @return {Number}\n\t * @private\n\t */\n\tradarCircleX(d) {\n\t\treturn this.getCache(cacheKey)[d.id][d.index][0];\n\t},\n\n\t/**\n\t * Get data point y coordinate\n\t * @param {Object} d Data object\n\t * @return {Number}\n\t * @private\n\t */\n\tradarCircleY(d) {\n\t\treturn this.getCache(cacheKey)[d.id][d.index][1];\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tselectAll as d3SelectAll\n} from \"d3-selection\";\nimport ChartInternal from \"./ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {capitalize, extend, getBoundingRect, getRandom, isNumber, isObject, isString, getTranslation} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initializes the text\n\t * @private\n\t */\n\tinitText() {\n\t\tconst $$ = this;\n\n\t\t$$.main.select(`.${CLASS.chart}`).append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartTexts);\n\n\t\t$$.mainText = d3SelectAll([]);\n\t},\n\n\t/**\n\t * Update chartText\n\t * @private\n\t * @param {Object} $$.data.targets\n\t */\n\tupdateTargetsForText(targets) {\n\t\tconst $$ = this;\n\t\tconst classChartText = $$.classChartText.bind($$);\n\t\tconst classTexts = $$.classTexts.bind($$);\n\t\tconst classFocus = $$.classFocus.bind($$);\n\t\tconst mainTextUpdate = $$.main.select(`.${CLASS.chartTexts}`).selectAll(`.${CLASS.chartText}`)\n\t\t\t.data(targets)\n\t\t\t.attr(\"class\", d => classChartText(d) + classFocus(d));\n\n\t\tconst mainTextEnter = mainTextUpdate.enter().append(\"g\")\n\t\t\t.attr(\"class\", classChartText)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.style(\"pointer-events\", \"none\");\n\n\t\tmainTextEnter.append(\"g\")\n\t\t\t.attr(\"class\", classTexts);\n\t},\n\n\t/**\n\t * Update text\n\t * @private\n\t * @param {Number} Fade-out transition duration\n\t */\n\tupdateText(durationForExit) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst dataFn = $$.labelishData.bind($$);\n\t\tconst classText = $$.classText.bind($$);\n\n\t\t$$.mainText = $$.main.selectAll(`.${CLASS.texts}`).selectAll(`.${CLASS.text}`)\n\t\t\t.data(d => (this.isRadarType(d) ? d.values : dataFn(d)));\n\n\t\t$$.mainText.exit()\n\t\t\t.transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"fill-opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.mainText = $$.mainText.enter()\n\t\t\t.append(\"text\")\n\t\t\t.merge($$.mainText)\n\t\t\t.attr(\"class\", classText)\n\t\t\t.attr(\"text-anchor\", d => (config.axis_rotated ? (d.value < 0 ? \"end\" : \"start\") : \"middle\"))\n\t\t\t.style(\"fill\", $$.updateTextColor.bind($$))\n\t\t\t.style(\"fill-opacity\", \"0\")\n\t\t\t.text((d, i, j) => {\n\t\t\t\tconst value = $$.isBubbleZType(d) ? $$.getBubbleZData(d.value, \"z\") : d.value;\n\n\t\t\t\treturn $$.dataLabelFormat(d.id)(value, d.id, i, j);\n\t\t\t});\n\t},\n\n\tupdateTextColor(d) {\n\t\tconst $$ = this;\n\t\tconst labelColors = $$.config.data_labels_colors;\n\t\tlet color;\n\n\t\tif (isString(labelColors)) {\n\t\t\tcolor = labelColors;\n\t\t} else if (isObject(labelColors)) {\n\t\t\tcolor = labelColors[d.id];\n\t\t}\n\n\t\treturn color || $$.color(d);\n\t},\n\n\t/**\n\t * Redraw chartText\n\t * @param {Function} x Positioning function for x\n\t * @param {Function} y Positioning function for y\n\t * @param {Boolean} forFlow\n\t * @param {Boolean} withTransition transition is enabled\n\t * @private\n\t */\n\tredrawText(x, y, forFlow, withTransition) {\n\t\tconst $$ = this;\n\t\tconst t = getRandom();\n\t\tconst opacityForText = forFlow ? 0 : $$.opacityForText.bind($$);\n\n\t\treturn [\n\t\t\t$$.mainText.each(function(d, i) {\n\t\t\t\tconst text = d3Select(this);\n\n\t\t\t\t// do not apply transition for newly added text elements\n\t\t\t\t(withTransition && text.attr(\"x\") ? text.transition(t) : text)\n\t\t\t\t\t.attr(\"x\", x.bind(this)(d, i))\n\t\t\t\t\t.attr(\"y\", y.bind(this)(d, i))\n\t\t\t\t\t.style(\"fill\", $$.updateTextColor.bind($$))\n\t\t\t\t\t.style(\"fill-opacity\", opacityForText);\n\t\t\t})\n\t\t];\n\t},\n\n\t/**\n\t * Gets the getBoundingClientRect value of the element\n\t * @private\n\t * @param {HTMLElement|d3.selection} element\n\t * @param {String} className\n\t * @returns {Object} value of element.getBoundingClientRect()\n\t */\n\tgetTextRect(element, className) {\n\t\tconst $$ = this;\n\t\tlet base = (element.node ? element.node() : element);\n\n\t\tif (!/text/i.test(base.tagName)) {\n\t\t\tbase = base.querySelector(\"text\");\n\t\t}\n\n\t\tconst text = base.textContent;\n\t\tconst cacheKey = `$${text.replace(/\\W/g, \"_\")}`;\n\t\tlet rect = $$.getCache(cacheKey);\n\n\t\tif (!rect) {\n\t\t\t$$.svg.append(\"text\")\n\t\t\t\t.style(\"visibility\", \"hidden\")\n\t\t\t\t.style(\"font\", d3Select(base).style(\"font\"))\n\t\t\t\t.classed(className, true)\n\t\t\t\t.text(text)\n\t\t\t\t.call(v => {\n\t\t\t\t\trect = getBoundingRect(v.node());\n\t\t\t\t})\n\t\t\t\t.remove();\n\n\t\t\t$$.addCache(cacheKey, rect);\n\t\t}\n\n\t\treturn rect;\n\t},\n\n\t/**\n\t * Gets the x or y coordinate of the text\n\t * @param {Object} indices Indices values\n\t * @param {Boolean} forX whether or not to x\n\t * @returns {Number} coordinates\n\t * @private\n\t */\n\tgenerateXYForText(indices, forX) {\n\t\tconst $$ = this;\n\t\tconst types = Object.keys(indices);\n\t\tconst points = {};\n\t\tconst getter = forX ? $$.getXForText : $$.getYForText;\n\n\t\t$$.hasType(\"radar\") && types.push(\"radar\");\n\n\t\ttypes.forEach(v => {\n\t\t\tpoints[v] = $$[`generateGet${capitalize(v)}Points`](indices[v], false);\n\t\t});\n\n\t\treturn function(d, i) {\n\t\t\tconst type = ($$.isAreaType(d) && \"area\") ||\n\t\t\t\t($$.isBarType(d) && \"bar\") ||\n\t\t\t\t($$.isRadarType(d) && \"radar\") || \"line\";\n\n\t\t\treturn getter.call($$, points[type](d, i), d, this);\n\t\t};\n\t},\n\n\t/**\n\t * Get centerized text position for bar type data.label.text\n\t * @private\n\t * @param {Object} d Data object\n\t * @param {Array} points Data points position\n\t * @param {HTMLElement} textElement Data label text element\n\t * @returns {Number} Position value\n\t */\n\tgetCenteredTextPos(d, points, textElement) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\tif (config.data_labels.centered && $$.isBarType(d)) {\n\t\t\tconst rect = getBoundingRect(textElement);\n\t\t\tconst isPositive = d.value >= 0;\n\n\t\t\tif (isRotated) {\n\t\t\t\tconst w = (\n\t\t\t\t\tisPositive ?\n\t\t\t\t\t\tpoints[1][1] - points[0][1] :\n\t\t\t\t\t\tpoints[0][1] - points[1][1]\n\t\t\t\t) / 2 + (rect.width / 2);\n\n\t\t\t\treturn isPositive ? -w - 3 : w + 2;\n\t\t\t} else {\n\t\t\t\tconst h = (\n\t\t\t\t\tisPositive ?\n\t\t\t\t\t\tpoints[0][1] - points[1][1] :\n\t\t\t\t\t\tpoints[1][1] - points[0][1]\n\t\t\t\t) / 2 + (rect.height / 2);\n\n\t\t\t\treturn isPositive ? h : -h - 2;\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t},\n\n\t/**\n\t * Get data.labels.position value\n\t * @param {String} id Data id value\n\t * @param {String} type x | y\n\t * @return {Number} Position value\n\t * @private\n\t */\n\tgetTextPos(id, type) {\n\t\tconst pos = this.config.data_labels_position;\n\n\t\treturn (id in pos ? pos[id] : pos)[type] || 0;\n\t},\n\n\t/**\n\t * Gets the x coordinate of the text\n\t * @private\n\t * @param {Object} points\n\t * @param {Object} data\n\t * @param {HTMLElement} element\n\t * @returns {Number} x coordinate\n\t */\n\tgetXForText(points, d, textElement) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tlet xPos;\n\t\tlet padding;\n\n\t\tif (isRotated) {\n\t\t\tpadding = $$.isBarType(d) ? 4 : 6;\n\t\t\txPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);\n\t\t} else {\n\t\t\txPos = $$.hasType(\"bar\") ? (points[2][0] + points[0][0]) / 2 : points[0][0];\n\t\t}\n\t\t// show labels regardless of the domain if value is null\n\t\tif (d.value === null) {\n\t\t\tif (xPos > $$.width) {\n\t\t\t\tconst {width} = getBoundingRect(textElement);\n\n\t\t\t\txPos = $$.width - width;\n\t\t\t} else if (xPos < 0) {\n\t\t\t\txPos = 4;\n\t\t\t}\n\t\t}\n\n\t\tif (isRotated) {\n\t\t\txPos += $$.getCenteredTextPos(d, points, textElement);\n\t\t}\n\n\t\treturn xPos + $$.getTextPos(d.id, \"x\");\n\t},\n\n\t/**\n\t * Gets the y coordinate of the text\n\t * @private\n\t * @param {Object} points\n\t * @param {Object} data\n\t * @param {HTMLElement} element\n\t * @returns {Number} y coordinate\n\t */\n\tgetYForText(points, d, textElement) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst r = config.point_r;\n\t\tconst rect = getBoundingRect(textElement);\n\t\tlet baseY = 3;\n\t\tlet yPos;\n\n\t\tif (isRotated) {\n\t\t\tyPos = (points[0][0] + points[2][0] + rect.height * 0.6) / 2;\n\t\t} else {\n\t\t\tyPos = points[2][1];\n\n\t\t\tif (isNumber(r) && r > 5 && ($$.isLineType(d) || $$.isScatterType(d))) {\n\t\t\t\tbaseY += config.point_r / 2.3;\n\t\t\t}\n\n\t\t\tif (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue && $$.hasNegativeValue)) {\n\t\t\t\tyPos += rect.height + ($$.isBarType(d) ? -baseY : baseY);\n\t\t\t} else {\n\t\t\t\tlet diff = -baseY * 2;\n\n\t\t\t\tif ($$.isBarType(d)) {\n\t\t\t\t\tdiff = -baseY;\n\t\t\t\t} else if ($$.isBubbleType(d)) {\n\t\t\t\t\tdiff = baseY;\n\t\t\t\t}\n\n\t\t\t\tyPos += diff;\n\t\t\t}\n\t\t}\n\n\t\t// show labels regardless of the domain if value is null\n\t\tif (d.value === null && !isRotated) {\n\t\t\tconst boxHeight = rect.height;\n\n\t\t\tif (yPos < boxHeight) {\n\t\t\t\tyPos = boxHeight;\n\t\t\t} else if (yPos > this.height) {\n\t\t\t\tyPos = this.height - 4;\n\t\t\t}\n\t\t}\n\n\t\tif (!isRotated) {\n\t\t\tyPos += $$.getCenteredTextPos(d, points, textElement);\n\t\t}\n\n\t\treturn yPos + $$.getTextPos(d.id, \"y\");\n\t},\n\n\t/**\n\t * Calculate if two or more text nodes are overlapping\n\t * Mark overlapping text nodes with \"text-overlapping\" class\n\t * @private\n\t * @param {number} id\n\t * @param {ChartInternal} $$\n\t * @param {string} selector\n\t */\n\tmarkOverlapped(id, $$, selector) {\n\t\tconst textNodes = $$.arcs.selectAll(selector);\n\t\tconst filteredTextNodes = textNodes.filter(node => node.data.id !== id);\n\t\tconst textNode = textNodes.filter(node => node.data.id === id);\n\t\tconst translate = getTranslation(textNode.node());\n\n\t\t// Calculates the length of the hypotenuse\n\t\tconst calcHypo = (x, y) => Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));\n\n\t\ttextNode.node() && filteredTextNodes.each(function() {\n\t\t\tconst coordinate = getTranslation(this);\n\t\t\tconst filteredTextNode = d3Select(this);\n\t\t\tconst nodeForWidth = calcHypo(translate.e, translate.f) > calcHypo(coordinate.e, coordinate.f) ?\n\t\t\t\ttextNode : filteredTextNode;\n\n\t\t\tconst overlapsX = Math.ceil(Math.abs(translate.e - coordinate.e)) <\n\t\t\t\tMath.ceil(nodeForWidth.node().getComputedTextLength());\n\t\t\tconst overlapsY = Math.ceil(Math.abs(translate.f - coordinate.f)) <\n\t\t\t\tparseInt(textNode.style(\"font-size\"), 0);\n\n\t\t\tfilteredTextNode.classed(CLASS.TextOverlapping, overlapsX && overlapsY);\n\t\t});\n\t},\n\n\t/**\n\t * Calculate if two or more text nodes are overlapping\n\t * Remove \"text-overlapping\" class on selected text nodes\n\t * @private\n\t * @param {ChartInternal} $$\n\t * @param {string} selector\n\t */\n\tundoMarkOverlapped($$, selector) {\n\t\t$$.arcs.selectAll(selector)\n\t\t\t.each(function() {\n\t\t\t\td3SelectAll([this, this.previousSibling])\n\t\t\t\t\t.classed(CLASS.TextOverlapping, false);\n\t\t\t});\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {isString, isArray, extend} from \"./util\";\n\n// defined chart types as category\nconst TYPES = {\n\tArea: [\"area\", \"area-spline\", \"area-spline-range\", \"area-line-range\", \"area-step\"],\n\tAreaRange: [\"area-spline-range\", \"area-line-range\"],\n\tArc: [\"pie\", \"donut\", \"gauge\", \"radar\"],\n\tLine: [\"line\", \"spline\", \"area\", \"area-spline\", \"area-spline-range\", \"area-line-range\", \"step\", \"area-step\"],\n\tStep: [\"step\", \"area-step\"],\n\tSpline: [\"spline\", \"area-spline\", \"area-spline-range\"]\n};\n\nextend(ChartInternal.prototype, {\n\tsetTargetType(targetIds, type) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t$$.mapToTargetIds(targetIds).forEach(id => {\n\t\t\t$$.withoutFadeIn[id] = (type === config.data_types[id]);\n\t\t\tconfig.data_types[id] = type;\n\t\t});\n\n\t\tif (!targetIds) {\n\t\t\tconfig.data_type = type;\n\t\t}\n\t},\n\n\thasType(type, targetsValue) {\n\t\tconst $$ = this;\n\t\tconst types = $$.config.data_types;\n\t\tconst targets = targetsValue || $$.data.targets;\n\t\tlet has = false;\n\n\t\tif (targets && targets.length) {\n\t\t\ttargets.forEach(target => {\n\t\t\t\tconst t = types[target.id];\n\n\t\t\t\tif ((t && t.indexOf(type) >= 0) || (!t && type === \"line\")) {\n\t\t\t\t\thas = true;\n\t\t\t\t}\n\t\t\t});\n\t\t} else if (Object.keys(types).length) {\n\t\t\tObject.keys(types).forEach(id => {\n\t\t\t\tif (types[id] === type) {\n\t\t\t\t\thas = true;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\thas = $$.config.data_type === type;\n\t\t}\n\n\t\treturn has;\n\t},\n\n\t/**\n\t * Check if contains given chart types\n\t * @param {String} type Type key\n\t * @param {Object} targets\n\t * @param {Array} exclude Excluded types\n\t * @return {boolean}\n\t * @private\n\t */\n\thasTypeOf(type, targets, exclude = []) {\n\t\treturn !TYPES[type]\n\t\t\t.filter(v => exclude.indexOf(v) === -1)\n\t\t\t.every(v => !this.hasType(v, targets));\n\t},\n\n\t/**\n\t * Check if given data is certain chart type\n\t * @param {Object} d Data object\n\t * @param {String} type chart type\n\t * @return {Boolean}\n\t * @private\n\t */\n\tisTypeOf(d, type) {\n\t\tconst id = isString(d) ? d : d.id;\n\t\tconst dataType = this.config.data_types[id];\n\n\t\treturn isArray(type) ?\n\t\t\ttype.indexOf(dataType) >= 0 : dataType === type;\n\t},\n\n\t/**\n\t * Check if contains arc types chart\n\t * @param {Object} targets\n\t * @param {Array} exclude Excluded types\n\t * @return {boolean}\n\t * @private\n\t */\n\thasArcType(targets, exclude) {\n\t\treturn this.hasTypeOf(\"Arc\", targets, exclude);\n\t},\n\n\thasMultiArcGauge() {\n\t\treturn this.hasType(\"gauge\") && this.config.gauge_type === \"multi\";\n\t},\n\n\tisLineType(d) {\n\t\tconst id = isString(d) ? d : d.id;\n\n\t\treturn !this.config.data_types[id] ||\n\t\t\tthis.isTypeOf(id, TYPES.Line);\n\t},\n\n\tisStepType(d) {\n\t\treturn this.isTypeOf(d, TYPES.Step);\n\t},\n\n\tisSplineType(d) {\n\t\treturn this.isTypeOf(d, TYPES.Spline);\n\t},\n\n\tisAreaType(d) {\n\t\treturn this.isTypeOf(d, TYPES.Area);\n\t},\n\n\tisAreaRangeType(d) {\n\t\treturn this.isTypeOf(d, TYPES.AreaRange);\n\t},\n\n\tisBarType(d) {\n\t\treturn this.isTypeOf(d, \"bar\");\n\t},\n\n\tisBubbleType(d) {\n\t\treturn this.isTypeOf(d, \"bubble\");\n\t},\n\n\tisScatterType(d) {\n\t\treturn this.isTypeOf(d, \"scatter\");\n\t},\n\n\tisPieType(d) {\n\t\treturn this.isTypeOf(d, \"pie\");\n\t},\n\n\tisGaugeType(d) {\n\t\treturn this.isTypeOf(d, \"gauge\");\n\t},\n\n\tisDonutType(d) {\n\t\treturn this.isTypeOf(d, \"donut\");\n\t},\n\n\tisRadarType(d) {\n\t\treturn this.isTypeOf(d, \"radar\");\n\t},\n\n\tisArcType(d) {\n\t\treturn this.isPieType(d) ||\n\t\t\tthis.isDonutType(d) ||\n\t\t\tthis.isGaugeType(d) ||\n\t\t\tthis.isRadarType(d);\n\t},\n\n\t// determine if is 'circle' data point\n\tisCirclePoint() {\n\t\tconst config = this.config;\n\t\tconst pattern = config.point_pattern;\n\n\t\treturn config.point_type === \"circle\" &&\n\t\t\t(!pattern || (isArray(pattern) && pattern.length === 0));\n\t},\n\n\tlineData(d) {\n\t\treturn this.isLineType(d) ? [d] : [];\n\t},\n\n\tarcData(d) {\n\t\treturn this.isArcType(d.data) ? [d] : [];\n\t},\n\n\tbarData(d) {\n\t\treturn this.isBarType(d) ? d.values : [];\n\t},\n\n\t/**\n\t * Get data adapt for data label showing\n\t * @param {Object} d Data object\n\t * @return {Array}\n\t * @private\n\t */\n\tlabelishData(d) {\n\t\treturn this.isBarType(d) ||\n\t\t\tthis.isLineType(d) ||\n\t\t\tthis.isScatterType(d) ||\n\t\t\tthis.isBubbleType(d) ||\n\t\t\tthis.isRadarType(d) ? d.values : [];\n\t},\n\n\tbarLineBubbleData(d) {\n\t\treturn this.isBarType(d) || this.isLineType(d) || this.isBubbleType(d) ?\n\t\t\td.values : [];\n\t},\n\n\t// https://github.com/d3/d3-shape#curves\n\tisInterpolationType(type) {\n\t\treturn [\n\t\t\t\"basis\",\n\t\t\t\"basis-closed\",\n\t\t\t\"basis-open\",\n\t\t\t\"bundle\",\n\t\t\t\"cardinal\",\n\t\t\t\"cardinal-closed\",\n\t\t\t\"cardinal-open\",\n\t\t\t\"catmull-rom\",\n\t\t\t\"catmull-rom-closed\",\n\t\t\t\"catmull-rom-open\",\n\t\t\t\"linear\",\n\t\t\t\"linear-closed\",\n\t\t\t\"monotone-x\",\n\t\t\t\"monotone-y\",\n\t\t\t\"natural\"\n\t\t].indexOf(type) >= 0;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tselectAll as d3SelectAll\n} from \"d3-selection\";\nimport ChartInternal from \"./ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend, isArray, isValue} from \"./util\";\n\n// Grid position and text anchor helpers\nconst getGridTextAnchor = d => isValue(d.position) || \"end\";\nconst getGridTextDx = d => (d.position === \"start\" ? 4 : (d.position === \"middle\" ? 0 : -4));\nconst getGridTextX = (isX, width, height) => d => {\n\tlet x = isX ? 0 : width;\n\n\tif (d.position === \"start\") {\n\t\tx = isX ? -height : 0;\n\t} else if (d.position === \"middle\") {\n\t\tx = (isX ? -height : width) / 2;\n\t}\n\n\treturn x;\n};\n\nextend(ChartInternal.prototype, {\n\tinitGrid() {\n\t\tconst $$ = this;\n\n\t\t$$.xgrid = d3SelectAll([]);\n\n\t\t$$.initGridLines();\n\t\t$$.initFocusGrid();\n\t},\n\n\tinitGridLines() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif (config.grid_x_lines.length || config.grid_y_lines.length) {\n\t\t\t$$.gridLines = $$.main.insert(\"g\", `.${CLASS.chart}${config.grid_lines_front ? \" + *\" : \"\"}`)\n\t\t\t\t.attr(\"clip-path\", $$.clipPathForGrid)\n\t\t\t\t.attr(\"class\", `${CLASS.grid} ${CLASS.gridLines}`);\n\n\t\t\t$$.gridLines.append(\"g\").attr(\"class\", CLASS.xgridLines);\n\t\t\t$$.gridLines.append(\"g\").attr(\"class\", CLASS.ygridLines);\n\n\t\t\t$$.xgridLines = d3SelectAll([]);\n\t\t}\n\t},\n\n\tupdateXGrid(withoutUpdate) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst xgridData = $$.generateGridData(config.grid_x_type, $$.x);\n\t\tconst tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;\n\t\tconst pos = d => (($$.zoomScale || $$.x)(d) + tickOffset) * (isRotated ? -1 : 1);\n\n\t\t$$.xgridAttr = isRotated ? {\n\t\t\t\"x1\": 0,\n\t\t\t\"x2\": $$.width,\n\t\t\t\"y1\": pos,\n\t\t\t\"y2\": pos,\n\t\t} : {\n\t\t\t\"x1\": pos,\n\t\t\t\"x2\": pos,\n\t\t\t\"y1\": 0,\n\t\t\t\"y2\": $$.height,\n\t\t};\n\n\t\t$$.xgrid = $$.main.select(`.${CLASS.xgrids}`)\n\t\t\t.selectAll(`.${CLASS.xgrid}`)\n\t\t\t.data(xgridData);\n\n\t\t$$.xgrid.exit().remove();\n\n\t\t$$.xgrid = $$.xgrid.enter()\n\t\t\t.append(\"line\")\n\t\t\t.attr(\"class\", CLASS.xgrid)\n\t\t\t.merge($$.xgrid);\n\n\t\tif (!withoutUpdate) {\n\t\t\t$$.xgrid.each(function() {\n\t\t\t\tconst grid = d3Select(this);\n\n\t\t\t\tObject.keys($$.xgridAttr).forEach(id => {\n\t\t\t\t\tgrid.attr(id, $$.xgridAttr[id])\n\t\t\t\t\t\t.style(\"opacity\", () => (\n\t\t\t\t\t\t\tgrid.attr(isRotated ? \"y1\" : \"x1\") === (isRotated ? $$.height : 0) ?\n\t\t\t\t\t\t\t\t\"0\" : \"1\"\n\t\t\t\t\t\t));\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t},\n\n\tupdateYGrid() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);\n\t\tconst pos = d => Math.ceil($$.y(d));\n\n\t\t$$.ygrid = $$.main.select(`.${CLASS.ygrids}`)\n\t\t\t.selectAll(`.${CLASS.ygrid}`)\n\t\t\t.data(gridValues);\n\n\t\t$$.ygrid.exit().remove();\n\n\t\t$$.ygrid = $$.ygrid\n\t\t\t.enter()\n\t\t\t.append(\"line\")\n\t\t\t.attr(\"class\", CLASS.ygrid)\n\t\t\t.merge($$.ygrid);\n\n\t\t$$.ygrid.attr(\"x1\", isRotated ? pos : 0)\n\t\t\t.attr(\"x2\", isRotated ? pos : $$.width)\n\t\t\t.attr(\"y1\", isRotated ? 0 : pos)\n\t\t\t.attr(\"y2\", isRotated ? $$.height : pos);\n\n\t\t$$.smoothLines($$.ygrid, \"grid\");\n\t},\n\n\tupdateGrid(duration) {\n\t\tconst $$ = this;\n\n\t\t!$$.gridLines && $$.initGridLines();\n\n\t\t// hide if arc type\n\t\t$$.grid.style(\"visibility\", $$.hasArcType() ? \"hidden\" : \"visible\");\n\n\t\t$$.hideGridFocus();\n\t\t$$.updateXGridLines(duration);\n\t\t$$.updateYGridLines(duration);\n\t},\n\n\t/**\n\t * Update X Grid lines\n\t * @param {Number} duration\n\t * @private\n\t */\n\tupdateXGridLines(duration) {\n\t\tconst $$ = this;\n\t\tconst main = $$.main;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\tconfig.grid_x_show && $$.updateXGrid();\n\n\t\t$$.xgridLines = main.select(`.${CLASS.xgridLines}`)\n\t\t\t.selectAll(`.${CLASS.xgridLine}`)\n\t\t\t.data(config.grid_x_lines);\n\n\t\t// exit\n\t\t$$.xgridLines.exit().transition()\n\t\t\t.duration(duration)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t// enter\n\t\tconst xgridLine = $$.xgridLines.enter().append(\"g\");\n\n\t\txgridLine.append(\"line\")\n\t\t\t.style(\"opacity\", \"0\");\n\n\t\txgridLine.append(\"text\")\n\t\t\t.attr(\"transform\", isRotated ? \"\" : \"rotate(-90)\")\n\t\t\t.attr(\"dy\", -5)\n\t\t\t.style(\"opacity\", \"0\");\n\n\t\t$$.xgridLines = xgridLine.merge($$.xgridLines);\n\n\t\t$$.xgridLines\n\t\t\t.attr(\"class\", d => `${CLASS.xgridLine} ${d.class || \"\"}`.trim())\n\t\t\t.select(\"text\")\n\t\t\t.attr(\"text-anchor\", getGridTextAnchor)\n\t\t\t.attr(\"dx\", getGridTextDx)\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.text(d => d.text)\n\t\t\t.transition()\n\t\t\t.style(\"opacity\", \"1\");\n\t},\n\n\t/**\n\t * Update Y Grid lines\n\t * @param {Number} duration\n\t * @private\n\t */\n\tupdateYGridLines(duration) {\n\t\tconst $$ = this;\n\t\tconst main = $$.main;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\tconfig.grid_y_show && $$.updateYGrid();\n\n\t\t$$.ygridLines = main.select(`.${CLASS.ygridLines}`)\n\t\t\t.selectAll(`.${CLASS.ygridLine}`)\n\t\t\t.data(config.grid_y_lines);\n\n\t\t// exit\n\t\t$$.ygridLines.exit()\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t// enter\n\t\tconst ygridLine = $$.ygridLines.enter().append(\"g\");\n\n\t\tygridLine.append(\"line\")\n\t\t\t.style(\"opacity\", \"0\");\n\n\t\tygridLine.append(\"text\")\n\t\t\t.attr(\"transform\", isRotated ? \"rotate(-90)\" : \"\")\n\t\t\t.style(\"opacity\", \"0\");\n\n\t\t$$.ygridLines = ygridLine.merge($$.ygridLines);\n\n\t\t// update\n\t\tconst yv = $$.yv.bind($$);\n\n\t\t$$.ygridLines\n\t\t\t.attr(\"class\", d => `${CLASS.ygridLine} ${d.class || \"\"}`.trim())\n\t\t\t.select(\"line\")\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.attr(\"x1\", isRotated ? yv : 0)\n\t\t\t.attr(\"x2\", isRotated ? yv : $$.width)\n\t\t\t.attr(\"y1\", isRotated ? 0 : yv)\n\t\t\t.attr(\"y2\", isRotated ? $$.height : yv)\n\t\t\t.transition()\n\t\t\t.style(\"opacity\", \"1\");\n\n\t\t$$.ygridLines.select(\"text\")\n\t\t\t.attr(\"text-anchor\", getGridTextAnchor)\n\t\t\t.attr(\"dx\", getGridTextDx)\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.attr(\"dy\", -5)\n\t\t\t.attr(\"x\", getGridTextX(isRotated, $$.width, $$.height))\n\t\t\t.attr(\"y\", yv)\n\t\t\t.text(d => d.text)\n\t\t\t.transition()\n\t\t\t.style(\"opacity\", \"1\");\n\t},\n\n\tredrawGrid(withTransition) {\n\t\tconst $$ = this;\n\t\tconst isRotated = $$.config.axis_rotated;\n\t\tconst xv = $$.xv.bind($$);\n\n\t\tlet lines = $$.xgridLines.select(\"line\");\n\t\tlet texts = $$.xgridLines.select(\"text\");\n\n\t\tlines = (withTransition ? lines.transition() : lines)\n\t\t\t.attr(\"x1\", isRotated ? 0 : xv)\n\t\t\t.attr(\"x2\", isRotated ? $$.width : xv)\n\t\t\t.attr(\"y1\", isRotated ? xv : 0)\n\t\t\t.attr(\"y2\", isRotated ? xv : $$.height);\n\n\t\ttexts = (withTransition ? texts.transition() : texts)\n\t\t\t.attr(\"x\", getGridTextX(!isRotated, $$.width, $$.height))\n\t\t\t.attr(\"y\", xv)\n\t\t\t.text(d => d.text);\n\n\t\treturn [\n\t\t\t(withTransition ? lines.transition() : lines).style(\"opacity\", \"1\"),\n\t\t\t(withTransition ? texts.transition() : texts).style(\"opacity\", \"1\")\n\t\t];\n\t},\n\n\tinitFocusGrid() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isFront = config.grid_front;\n\t\tconst className = `.${CLASS[isFront && $$.gridLines ? \"gridLines\" : \"chart\"]}${isFront ? \" + *\" : \"\"}`;\n\n\t\t$$.grid = $$.main.insert(\"g\", className)\n\t\t\t.attr(\"clip-path\", $$.clipPathForGrid)\n\t\t\t.attr(\"class\", CLASS.grid);\n\n\t\tconfig.grid_x_show &&\n\t\t\t$$.grid.append(\"g\").attr(\"class\", CLASS.xgrids);\n\n\t\tconfig.grid_y_show &&\n\t\t\t$$.grid.append(\"g\").attr(\"class\", CLASS.ygrids);\n\n\t\tif (config.grid_focus_show) {\n\t\t\t$$.grid.append(\"g\")\n\t\t\t\t.attr(\"class\", CLASS.xgridFocus)\n\t\t\t\t.append(\"line\")\n\t\t\t\t.attr(\"class\", CLASS.xgridFocus);\n\n\t\t\t// to show xy focus grid line, should be 'tooltip.grouped=false'\n\t\t\tif (config.grid_focus_y && !config.tooltip_grouped) {\n\t\t\t\t$$.grid.append(\"g\")\n\t\t\t\t\t.attr(\"class\", CLASS.ygridFocus)\n\t\t\t\t\t.append(\"line\")\n\t\t\t\t\t.attr(\"class\", CLASS.ygridFocus);\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Show grid focus line\n\t * @param {Array} selectedData\n\t * @private\n\t */\n\tshowGridFocus(selectedData) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst dataToShow = selectedData.filter(d => d && isValue($$.getBaseValue(d)));\n\n\t\t// Hide when bubble/scatter/stanford plot exists\n\t\tif (!config.tooltip_show || dataToShow.length === 0 || $$.hasType(\"bubble\") || $$.hasArcType()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst focusEl = $$.main.selectAll(`line.${CLASS.xgridFocus}, line.${CLASS.ygridFocus}`);\n\t\tconst isEdge = config.grid_focus_edge && !config.tooltip_grouped;\n\t\tconst xx = $$.xx.bind($$);\n\n\t\tfocusEl\n\t\t\t.style(\"visibility\", \"visible\")\n\t\t\t.data(dataToShow.concat(dataToShow))\n\t\t\t.each(function(d) {\n\t\t\t\tconst el = d3Select(this);\n\t\t\t\tconst pos = {\n\t\t\t\t\tx: xx(d),\n\t\t\t\t\ty: $$.getYScale(d.id)(d.value)\n\t\t\t\t};\n\t\t\t\tlet xy;\n\n\t\t\t\tif (el.classed(CLASS.xgridFocus)) {\n\t\t\t\t\t// will contain 'x1, y1, x2, y2' order\n\t\t\t\t\txy = isRotated ?\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tnull, // x1\n\t\t\t\t\t\t\tpos.x, // y1\n\t\t\t\t\t\t\tisEdge ? pos.y : $$.width, // x2\n\t\t\t\t\t\t\tpos.x // y2\n\t\t\t\t\t\t] : [\n\t\t\t\t\t\t\tpos.x,\n\t\t\t\t\t\t\tisEdge ? pos.y : null,\n\t\t\t\t\t\t\tpos.x,\n\t\t\t\t\t\t\t$$.height\n\t\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tconst isY2 = $$.axis.getId(d.id) === \"y2\";\n\n\t\t\t\t\txy = isRotated ?\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tpos.y, // x1\n\t\t\t\t\t\t\tisEdge && !isY2 ? pos.x : null, // y1\n\t\t\t\t\t\t\tpos.y, // x2\n\t\t\t\t\t\t\tisEdge && isY2 ? pos.x : $$.height // y2\n\t\t\t\t\t\t] : [\n\t\t\t\t\t\t\tisEdge && isY2 ? pos.x : null,\n\t\t\t\t\t\t\tpos.y,\n\t\t\t\t\t\t\tisEdge && !isY2 ? pos.x : $$.width,\n\t\t\t\t\t\t\tpos.y\n\t\t\t\t\t\t];\n\t\t\t\t}\n\n\t\t\t\t[\"x1\", \"y1\", \"x2\", \"y2\"]\n\t\t\t\t\t.forEach((v, i) => el.attr(v, xy[i]));\n\t\t\t});\n\n\t\t$$.smoothLines(focusEl, \"grid\");\n\t},\n\n\thideGridFocus() {\n\t\tconst $$ = this;\n\n\t\t$$.inputType === \"mouse\" && $$.main.selectAll(`line.${CLASS.xgridFocus}, line.${CLASS.ygridFocus}`)\n\t\t\t.style(\"visibility\", \"hidden\");\n\t},\n\n\tupdategridFocus() {\n\t\tconst $$ = this;\n\n\t\tif ($$.inputType === \"touch\") {\n\t\t\tconst d = $$.grid.select(`line.${CLASS.xgridFocus}`).datum();\n\n\t\t\td && $$.showGridFocus([d]);\n\t\t} else {\n\t\t\tconst isRotated = $$.config.axis_rotated;\n\n\t\t\t$$.main.select(`line.${CLASS.xgridFocus}`)\n\t\t\t\t.attr(\"x1\", isRotated ? 0 : -10)\n\t\t\t\t.attr(\"x2\", isRotated ? $$.width : -10)\n\t\t\t\t.attr(\"y1\", isRotated ? -10 : 0)\n\t\t\t\t.attr(\"y2\", isRotated ? -10 : $$.height);\n\t\t}\n\t},\n\n\tgenerateGridData(type, scale) {\n\t\tconst $$ = this;\n\t\tconst tickNum = $$.main.select(`.${CLASS.axisX}`)\n\t\t\t.selectAll(\".tick\")\n\t\t\t.size();\n\t\tlet gridData = [];\n\n\t\tif (type === \"year\") {\n\t\t\tconst xDomain = $$.getXDomain();\n\t\t\tconst firstYear = xDomain[0].getFullYear();\n\t\t\tconst lastYear = xDomain[1].getFullYear();\n\n\t\t\tfor (let i = firstYear; i <= lastYear; i++) {\n\t\t\t\tgridData.push(new Date(`${i}-01-01 00:00:00`));\n\t\t\t}\n\t\t} else {\n\t\t\tgridData = scale.ticks(10);\n\n\t\t\tif (gridData.length > tickNum) { // use only int\n\t\t\t\tgridData = gridData.filter(d => String(d).indexOf(\".\") < 0);\n\t\t\t}\n\t\t}\n\n\t\treturn gridData;\n\t},\n\n\tgetGridFilterToRemove(params) {\n\t\treturn params ? line => {\n\t\t\tlet found = false;\n\n\t\t\t(isArray(params) ? params.concat() : [params]).forEach(param => {\n\t\t\t\tif (((\"value\" in param && line.value === param.value) || (\"class\" in param && line.class === param.class))) {\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn found;\n\t\t} : () => true;\n\t},\n\n\tremoveGridLines(params, forX) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst toRemove = $$.getGridFilterToRemove(params);\n\t\tconst toShow = line => !toRemove(line);\n\t\tconst classLines = forX ? CLASS.xgridLines : CLASS.ygridLines;\n\t\tconst classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;\n\n\t\t$$.main.select(`.${classLines}`)\n\t\t\t.selectAll(`.${classLine}`)\n\t\t\t.filter(toRemove)\n\t\t\t.transition()\n\t\t\t.duration(config.transition_duration)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\tconst gridLines = `grid_${forX ? \"x\" : \"y\"}_lines`;\n\n\t\tconfig[gridLines] = config[gridLines].filter(toShow);\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tmouse as d3Mouse\n} from \"d3-selection\";\nimport ChartInternal from \"./ChartInternal\";\nimport {document} from \"./browser\";\nimport CLASS from \"../config/classes\";\nimport {extend, isFunction, isObject, isString, isValue, callFn, sanitise, tplProcess, isUndefined} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initializes the tooltip\n\t * @private\n\t */\n\tinitTooltip() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst bindto = config.tooltip_contents.bindto;\n\n\t\t$$.tooltip = d3Select(bindto);\n\n\t\tif ($$.tooltip.empty()) {\n\t\t\t$$.tooltip = $$.selectChart\n\t\t\t\t.style(\"position\", \"relative\")\n\t\t\t\t.append(\"div\")\n\t\t\t\t.attr(\"class\", CLASS.tooltipContainer)\n\t\t\t\t.style(\"position\", \"absolute\")\n\t\t\t\t.style(\"pointer-events\", \"none\")\n\t\t\t\t.style(\"display\", \"none\");\n\t\t}\n\n\t\t// Show tooltip if needed\n\t\tif (config.tooltip_init_show) {\n\t\t\tif ($$.isTimeSeries() && isString(config.tooltip_init_x)) {\n\t\t\t\tconst targets = $$.data.targets[0];\n\t\t\t\tlet i;\n\t\t\t\tlet val;\n\n\t\t\t\tconfig.tooltip_init_x = $$.parseDate(config.tooltip_init_x);\n\n\t\t\t\tfor (i = 0; (val = targets.values[i]); i++) {\n\t\t\t\t\tif ((val.x - config.tooltip_init_x) === 0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconfig.tooltip_init_x = i;\n\t\t\t}\n\n\t\t\t$$.tooltip.html($$.getTooltipHTML(\n\t\t\t\t$$.data.targets.map(d => $$.addName(d.values[config.tooltip_init_x])),\n\t\t\t\t$$.axis.getXAxisTickFormat(),\n\t\t\t\t$$.getYFormat($$.hasArcType(null, [\"radar\"])),\n\t\t\t\t$$.color\n\t\t\t));\n\n\t\t\tif (!bindto) {\n\t\t\t\t$$.tooltip.style(\"top\", config.tooltip_init_position.top)\n\t\t\t\t\t.style(\"left\", config.tooltip_init_position.left)\n\t\t\t\t\t.style(\"display\", \"block\");\n\t\t\t}\n\t\t}\n\n\t\t$$.bindTooltipResizePos();\n\t},\n\n\t/**\n\t * Get the tooltip HTML string\n\t * @param {...any} args\n\t * @private\n\t * @return {String} Formatted HTML string\n\t */\n\tgetTooltipHTML(...args) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn isFunction(config.tooltip_contents) ?\n\t\t\tconfig.tooltip_contents.call($$, ...args) : $$.getTooltipContent(...args);\n\t},\n\n\t/**\n\t * Returns the tooltip content(HTML string)\n\t * @param {Object} d data\n\t * @param {Function} defaultTitleFormat Default title format\n\t * @param {Function} defaultValueFormat Default format for each data value in the tooltip.\n\t * @param {Function} color Color function\n\t * @returns {String} html\n\t * @private\n\t */\n\tgetTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst titleFormat = config.tooltip_format_title || defaultTitleFormat;\n\t\tconst nameFormat = config.tooltip_format_name || (name => name);\n\t\tconst valueFormat = config.tooltip_format_value || ($$.isStackNormalized() ? ((v, ratio) => `${(ratio * 100).toFixed(2)}%`) : defaultValueFormat);\n\t\tconst order = config.tooltip_order;\n\t\tconst getRowValue = row => ($$.isBubbleZType(row) ? $$.getBubbleZData(row.value, \"z\") : $$.getBaseValue(row));\n\t\tconst getBgColor = $$.levelColor ? row => $$.levelColor(row.value) : row => color(row);\n\t\tconst contents = config.tooltip_contents;\n\t\tconst tplStr = contents.template;\n\t\tconst targetIds = $$.mapToTargetIds();\n\n\t\tif (order === null && config.data_groups.length) {\n\t\t\t// for stacked data, order should aligned with the visually displayed data\n\t\t\tconst ids = $$.orderTargets($$.data.targets)\n\t\t\t\t.map(i2 => i2.id)\n\t\t\t\t.reverse();\n\n\t\t\td.sort((a, b) => {\n\t\t\t\tlet v1 = a ? a.value : null;\n\t\t\t\tlet v2 = b ? b.value : null;\n\n\t\t\t\tif (v1 > 0 && v2 > 0) {\n\t\t\t\t\tv1 = a.id ? ids.indexOf(a.id) : null;\n\t\t\t\t\tv2 = b.id ? ids.indexOf(b.id) : null;\n\t\t\t\t}\n\n\t\t\t\treturn v1 - v2;\n\t\t\t});\n\t\t} else if (/^(asc|desc)$/.test(order)) {\n\t\t\tconst isAscending = order === \"asc\";\n\n\t\t\td.sort((a, b) => {\n\t\t\t\tconst v1 = a ? getRowValue(a) : null;\n\t\t\t\tconst v2 = b ? getRowValue(b) : null;\n\n\t\t\t\treturn isAscending ? v1 - v2 : v2 - v1;\n\t\t\t});\n\t\t} else if (isFunction(order)) {\n\t\t\td.sort(order);\n\t\t}\n\n\t\tconst tpl = $$.getTooltipContentTemplate(tplStr);\n\t\tconst len = d.length;\n\t\tlet text;\n\t\tlet row;\n\t\tlet param;\n\t\tlet value;\n\t\tlet i;\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\trow = d[i];\n\n\t\t\tif (!row || !(getRowValue(row) || getRowValue(row) === 0)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isUndefined(text)) {\n\t\t\t\tconst title = sanitise(titleFormat ? titleFormat(row.x) : row.x);\n\n\t\t\t\ttext = tplProcess(tpl[0], {\n\t\t\t\t\tCLASS_TOOLTIP: CLASS.tooltip,\n\t\t\t\t\tTITLE: isValue(title) ? (\n\t\t\t\t\t\ttplStr ? title : `<tr><th colspan=\"2\">${title}</th></tr>`\n\t\t\t\t\t) : \"\"\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tparam = [row.ratio, row.id, row.index, d];\n\t\t\tvalue = sanitise(valueFormat(getRowValue(row), ...param));\n\n\t\t\tif ($$.isAreaRangeType(row)) {\n\t\t\t\tconst [high, low] = [\"high\", \"low\"].map(v => sanitise(\n\t\t\t\t\tvalueFormat($$.getAreaRangeData(row, v), ...param)\n\t\t\t\t));\n\n\t\t\t\tvalue = `<b>Mid:</b> ${value} <b>High:</b> ${high} <b>Low:</b> ${low}`;\n\t\t\t}\n\n\t\t\tif (value !== undefined) {\n\t\t\t\t// Skip elements when their name is set to null\n\t\t\t\tif (row.name === null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst name = sanitise(nameFormat(row.name, ...param));\n\t\t\t\tconst color = getBgColor(row);\n\t\t\t\tconst contentValue = {\n\t\t\t\t\tCLASS_TOOLTIP_NAME: CLASS.tooltipName + $$.getTargetSelectorSuffix(row.id),\n\t\t\t\t\tCOLOR: (tplStr || !$$.patterns) ? color : `<svg><rect style=\"fill:${color}\" width=\"10\" height=\"10\"></rect></svg>`,\n\t\t\t\t\tNAME: name,\n\t\t\t\t\tVALUE: value\n\t\t\t\t};\n\n\t\t\t\tif (tplStr && isObject(contents.text)) {\n\t\t\t\t\tconst index = targetIds.indexOf(row.id);\n\n\t\t\t\t\tObject.keys(contents.text).forEach(key => {\n\t\t\t\t\t\tcontentValue[key] = contents.text[key][index];\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\ttext += tplProcess(tpl[1], contentValue);\n\t\t\t}\n\t\t}\n\n\t\treturn `${text}</table>`;\n\t},\n\n\t/**\n\t * Get the content template string\n\t * @param {String} tplStr\n\t * @return {String} Template string\n\t * @private\n\t */\n\tgetTooltipContentTemplate(tplStr) {\n\t\treturn (tplStr || `<table class=\"{=CLASS_TOOLTIP}\"><tbody>\n\t\t\t\t{=TITLE}\n\t\t\t\t{{<tr class=\"{=CLASS_TOOLTIP_NAME}\">\n\t\t\t\t\t<td class=\"name\">${this.patterns ? `{=COLOR}` : `<span style=\"background-color:{=COLOR}\"></span>`}{=NAME}</td>\n\t\t\t\t\t<td class=\"value\">{=VALUE}</td>\n\t\t\t\t</tr>}}\n\t\t\t</tbody></table>`)\n\t\t\t.replace(/(\\r?\\n|\\t)/g, \"\")\n\t\t\t.split(/{{(.*)}}/);\n\t},\n\n\t/**\n\t * Returns the position of the tooltip\n\t * @param {Object} dataToShow data\n\t * @param {String} tWidth Width value of tooltip element\n\t * @param {String} tHeight Height value of tooltip element\n\t * @param {HTMLElement} element\n\t * @returns {Object} top, left value\n\t * @private\n\t */\n\ttooltipPosition(dataToShow, tWidth, tHeight, element) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst hasGauge = $$.hasType(\"gauge\") && !config.gauge_fullCircle;\n\t\tconst svgLeft = $$.getSvgLeft(true);\n\t\tlet [left, top] = d3Mouse(element);\n\t\tlet chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight(true);\n\t\tconst chartLeft = $$.getCurrentPaddingLeft(true);\n\t\tconst size = 20;\n\n\t\ttop += size;\n\n\t\t// Determine tooltip position\n\t\tif ($$.hasArcType()) {\n\t\t\tconst raw = $$.inputType === \"touch\" || $$.hasType(\"radar\");\n\n\t\t\tif (!raw) {\n\t\t\t\ttop += hasGauge ? $$.height : $$.height / 2;\n\t\t\t\tleft += ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2;\n\t\t\t}\n\t\t} else {\n\t\t\tconst dataScale = $$.x(dataToShow[0].x);\n\n\t\t\tif (config.axis_rotated) {\n\t\t\t\ttop = dataScale + size;\n\t\t\t\tleft += svgLeft + 100;\n\t\t\t\tchartRight -= svgLeft;\n\t\t\t} else {\n\t\t\t\ttop -= 5;\n\t\t\t\tleft = svgLeft + chartLeft + size + ($$.zoomScale ? left : dataScale);\n\t\t\t}\n\t\t}\n\n\t\t// when tooltip left + tWidth > chart's width\n\t\tif ((left + tWidth + 15) > chartRight) {\n\t\t\tleft -= (svgLeft + tWidth + chartLeft);\n\t\t}\n\n\t\tif (top + tHeight > $$.currentHeight) {\n\t\t\ttop -= hasGauge ? tHeight * 3 : tHeight + 30;\n\t\t}\n\n\t\tif (top < 0) {\n\t\t\ttop = 0;\n\t\t}\n\n\t\treturn {top, left};\n\t},\n\n\t/**\n\t * Show the tooltip\n\t * @private\n\t * @param {Object} selectedData\n\t * @param {HTMLElement} element\n\t */\n\tshowTooltip(selectedData, element) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst bindto = config.tooltip_contents.bindto;\n\t\tconst forArc = $$.hasArcType(null, [\"radar\"]);\n\t\tconst dataToShow = selectedData.filter(d => d && isValue($$.getBaseValue(d)));\n\n\t\tif (dataToShow.length === 0 || !config.tooltip_show) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet datum = $$.tooltip.datum();\n\t\tlet {width = 0, height = 0} = datum || {};\n\t\tconst dataStr = JSON.stringify(selectedData);\n\n\t\tif (!datum || datum.current !== dataStr) {\n\t\t\tconst index = selectedData.concat().sort()[0].index;\n\n\t\t\tcallFn(config.tooltip_onshow, $$, $$.api, selectedData);\n\n\t\t\t// set tooltip content\n\t\t\t$$.tooltip\n\t\t\t\t.html($$.getTooltipHTML(\n\t\t\t\t\tselectedData,\n\t\t\t\t\t$$.axis.getXAxisTickFormat(),\n\t\t\t\t\t$$.getYFormat(forArc),\n\t\t\t\t\t$$.color\n\t\t\t\t))\n\t\t\t\t.style(\"display\", null)\n\t\t\t\t.style(\"visibility\", null) // for IE9\n\t\t\t\t.datum(datum = {\n\t\t\t\t\tindex,\n\t\t\t\t\tcurrent: dataStr,\n\t\t\t\t\twidth: width = $$.tooltip.property(\"offsetWidth\"),\n\t\t\t\t\theight: height = $$.tooltip.property(\"offsetHeight\")\n\t\t\t\t});\n\n\t\t\tcallFn(config.tooltip_onshown, $$, $$.api, selectedData);\n\t\t\t$$._handleLinkedCharts(true, index);\n\t\t}\n\n\t\tif (!bindto) {\n\t\t\tconst fnPos = config.tooltip_position || $$.tooltipPosition;\n\n\t\t\t// Get tooltip dimensions\n\t\t\tconst pos = fnPos.call(this, dataToShow, width, height, element);\n\n\t\t\t[\"top\", \"left\"].forEach(v => {\n\t\t\t\tconst value = pos[v];\n\n\t\t\t\t$$.tooltip.style(v, `${value}px`);\n\n\t\t\t\t// Remember left pos in percentage to be used on resize call\n\t\t\t\tif (v === \"left\" && !datum.xPosInPercent) {\n\t\t\t\t\tdatum.xPosInPercent = value / $$.currentWidth * 100;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * Adjust tooltip position on resize event\n\t * @private\n\t */\n\tbindTooltipResizePos() {\n\t\tconst $$ = this;\n\t\tconst {resizeFunction, tooltip} = $$;\n\n\t\tresizeFunction.add(() => {\n\t\t\tif (tooltip.style(\"display\") === \"block\") {\n\t\t\t\tconst {currentWidth} = $$;\n\t\t\t\tconst {width, xPosInPercent} = tooltip.datum();\n\t\t\t\tlet value = currentWidth / 100 * xPosInPercent;\n\t\t\t\tconst diff = currentWidth - (value + width);\n\n\t\t\t\t// if tooltip size overs current viewport size\n\t\t\t\tif (diff < 0) {\n\t\t\t\t\tvalue += diff;\n\t\t\t\t}\n\n\t\t\t\ttooltip.style(\"left\", `${value}px`);\n\t\t\t}\n\t\t});\n\t},\n\n\t/**\n\t * Hide the tooltip\n\t * @param {Boolean} force Force to hide\n\t * @private\n\t */\n\thideTooltip(force) {\n\t\tconst $$ = this;\n\t\tconst {api, config, tooltip} = $$;\n\n\t\tif (tooltip.style(\"display\") !== \"none\" && (!config.tooltip_doNotHide || force)) {\n\t\t\tconst selectedData = JSON.parse(this.tooltip.datum().current);\n\n\t\t\tcallFn(config.tooltip_onhide, $$, api, selectedData);\n\n\t\t\t// hide tooltip\n\t\t\ttooltip\n\t\t\t\t.style(\"display\", \"none\")\n\t\t\t\t.style(\"visibility\", \"hidden\") // for IE9\n\t\t\t\t.datum(null);\n\n\t\t\tcallFn(config.tooltip_onhidden, $$, api, selectedData);\n\t\t}\n\t},\n\n\t/**\n\t * Toggle display for linked chart instances\n\t * @param {Boolean} show true: show, false: hide\n\t * @param {Number} index x Axis index\n\t * @private\n\t */\n\t_handleLinkedCharts(show, index) {\n\t\tconst $$ = this;\n\n\t\tif ($$.config.tooltip_linked) {\n\t\t\tconst linkedName = $$.config.tooltip_linked_name;\n\n\t\t\t($$.api.internal.charts || []).forEach(c => {\n\t\t\t\tif (c !== $$.api) {\n\t\t\t\t\tconst config = c.internal.config;\n\t\t\t\t\tconst isLinked = config.tooltip_linked;\n\t\t\t\t\tconst name = config.tooltip_linked_name;\n\t\t\t\t\tconst isInDom = document.body.contains(c.element);\n\n\t\t\t\t\tif (isLinked && linkedName === name && isInDom) {\n\t\t\t\t\t\tconst data = c.internal.tooltip.data()[0];\n\t\t\t\t\t\tconst isNotSameIndex = index !== (data && data.index);\n\n\t\t\t\t\t\t// prevent throwing error for non-paired linked indexes\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (show && isNotSameIndex) {\n\t\t\t\t\t\t\t\tc.tooltip.show({index});\n\t\t\t\t\t\t\t} else if (!show) {\n\t\t\t\t\t\t\t\tc.tooltip.hide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tevent as d3Event,\n\tnamespaces as d3Namespaces\n} from \"d3-selection\";\nimport ChartInternal from \"./ChartInternal\";\nimport {document} from \"./browser\";\nimport CLASS from \"../config/classes\";\nimport {extend, callFn, isDefined, getOption, isEmpty, isFunction, notEmpty, tplProcess} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initialize the legend.\n\t * @private\n\t */\n\tinitLegend() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t$$.legendItemTextBox = {};\n\t\t$$.legendHasRendered = false;\n\t\t$$.legend = $$.svg.append(\"g\");\n\n\t\tif (config.legend_show) {\n\t\t\t$$.legend.attr(\"transform\", $$.getTranslate(\"legend\"));\n\n\t\t\t// MEMO: call here to update legend box and translate for all\n\t\t\t// MEMO: translate will be updated by this, so transform not needed in updateLegend()\n\t\t\t$$.updateLegend();\n\t\t} else {\n\t\t\t$$.legend.style(\"visibility\", \"hidden\");\n\t\t\t$$.hiddenLegendIds = $$.mapToIds($$.data.targets);\n\t\t}\n\t},\n\n\t/**\n\t * Update legend element\n\t * @param {Array} targetIds ID's of target\n\t * @param {Object} options withTransform : Whether to use the transform property / withTransitionForTransform: Whether transition is used when using the transform property / withTransition : whether or not to transition.\n\t * @param {Object} transitions Return value of the generateTransitions\n\t * @private\n\t */\n\tupdateLegend(targetIds, options, transitions) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst optionz = options || {\n\t\t\twithTransform: false,\n\t\t\twithTransitionForTransform: false,\n\t\t\twithTransition: false\n\t\t};\n\n\t\toptionz.withTransition = getOption(optionz, \"withTransition\", true);\n\t\toptionz.withTransitionForTransform = getOption(optionz, \"withTransitionForTransform\", true);\n\n\t\tif (config.legend_contents_bindto && config.legend_contents_template) {\n\t\t\t$$.updateLegendTemplate();\n\t\t} else {\n\t\t\t$$.updateLegendElement(\n\t\t\t\ttargetIds || $$.mapToIds($$.data.targets),\n\t\t\t\toptionz,\n\t\t\t\ttransitions\n\t\t\t);\n\t\t}\n\n\t\t// toggle legend state\n\t\t$$.legend.selectAll(`.${CLASS.legendItem}`)\n\t\t\t.classed(CLASS.legendItemHidden, id => !$$.isTargetToShow(id));\n\n\t\t// Update size and scale\n\t\t$$.updateScales(false, !$$.zoomScale);\n\t\t$$.updateSvgSize();\n\n\t\t// Update g positions\n\t\t$$.transformAll(optionz.withTransitionForTransform, transitions);\n\n\t\t$$.legendHasRendered = true;\n\t},\n\n\t/**\n\t * Update legend using template option\n\t * @private\n\t */\n\tupdateLegendTemplate() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst wrapper = d3Select(config.legend_contents_bindto);\n\t\tconst template = config.legend_contents_template;\n\n\t\tif (!wrapper.empty()) {\n\t\t\tconst targets = $$.mapToIds($$.data.targets);\n\t\t\tconst ids = [];\n\t\t\tlet html = \"\";\n\n\t\t\ttargets.forEach(v => {\n\t\t\t\tconst content = isFunction(template) ?\n\t\t\t\t\ttemplate.call($$, v, $$.color(v), $$.api.data(v)[0].values) :\n\t\t\t\t\ttplProcess(template, {\n\t\t\t\t\t\tCOLOR: $$.color(v),\n\t\t\t\t\t\tTITLE: v\n\t\t\t\t\t});\n\n\t\t\t\tif (content) {\n\t\t\t\t\tids.push(v);\n\t\t\t\t\thtml += content;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst legendItem = wrapper.html(html)\n\t\t\t\t.selectAll(function() { return this.childNodes; })\n\t\t\t\t.data(ids);\n\n\t\t\t$$.setLegendItem(legendItem);\n\n\t\t\t$$.legend = wrapper;\n\t\t}\n\t},\n\n\t/**\n\t * Update the size of the legend.\n\t * @private\n\t * @param {Obejct} size S\n\t */\n\tupdateSizeForLegend(size) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst {width, height} = size;\n\n\t\tconst insetLegendPosition = {\n\t\t\ttop: $$.isLegendTop ?\n\t\t\t\t$$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 :\n\t\t\t\t$$.currentHeight - height - $$.getCurrentPaddingBottom() - config.legend_inset_y,\n\t\t\tleft: $$.isLegendLeft ?\n\t\t\t\t$$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 :\n\t\t\t\t$$.currentWidth - width - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5\n\t\t};\n\n\t\t$$.margin3 = {\n\t\t\ttop: $$.isLegendRight ?\n\t\t\t\t0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - height,\n\t\t\tright: NaN,\n\t\t\tbottom: 0,\n\t\t\tleft: $$.isLegendRight ?\n\t\t\t\t$$.currentWidth - width : $$.isLegendInset ? insetLegendPosition.left : 0\n\t\t};\n\t},\n\n\t/**\n\t * Transform Legend\n\t * @private\n\t * @param {Boolean} whether or not to transition.\n\t */\n\ttransformLegend(withTransition) {\n\t\tconst $$ = this;\n\n\t\t(withTransition ? $$.legend.transition() : $$.legend)\n\t\t\t.attr(\"transform\", $$.getTranslate(\"legend\"));\n\t},\n\n\t/**\n\t * Update the legend step\n\t * @private\n\t * @param {Number} step\n\t */\n\tupdateLegendStep(step) {\n\t\tthis.legendStep = step;\n\t},\n\n\t/**\n\t * Update legend item width\n\t * @private\n\t * @param {Number} width\n\t */\n\tupdateLegendItemWidth(w) {\n\t\tthis.legendItemWidth = w;\n\t},\n\n\t/**\n\t * Update legend item height\n\t * @private\n\t * @param {Number} height\n\t */\n\tupdateLegendItemHeight(h) {\n\t\tthis.legendItemHeight = h;\n\t},\n\n\t/**\n\t * Update legend item color\n\t * @private\n\t * @param {String} id Corresponding data ID value\n\t * @param {String} color Color value\n\t */\n\tupdateLegendItemColor(id, color) {\n\t\tthis.legend.select(`.${CLASS.legendItem}-${id} line`)\n\t\t\t.style(\"stroke\", color);\n\t},\n\n\t/**\n\t * Get the width of the legend\n\t * @private\n\t * @return {Number} width\n\t */\n\tgetLegendWidth() {\n\t\tconst $$ = this;\n\n\t\treturn $$.config.legend_show ? (\n\t\t\t$$.isLegendRight || $$.isLegendInset ?\n\t\t\t\t$$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth\n\t\t) : 0;\n\t},\n\n\t/**\n\t * Get the height of the legend\n\t * @return {Number} height\n\t * @private\n\t */\n\tgetLegendHeight() {\n\t\tconst $$ = this;\n\n\t\treturn $$.config.legend_show ? (\n\t\t\t$$.isLegendRight ?\n\t\t\t\t$$.currentHeight : Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1)\n\t\t) : 0;\n\t},\n\n\t/**\n\t * Get the opacity of the legend\n\t * @private\n\t * @param {Object} d3.Select\n\t * @returns {Number} opacity\n\t */\n\topacityForLegend(legendItem) {\n\t\treturn legendItem.classed(CLASS.legendItemHidden) ? null : \"1\";\n\t},\n\n\t/**\n\t * Get the opacity of the legend that is unfocused\n\t * @private\n\t * @param {Object} legendItem, d3.Select\n\t * @returns {Number} opacity\n\t */\n\topacityForUnfocusedLegend(legendItem) {\n\t\treturn legendItem.classed(CLASS.legendItemHidden) ? null : \"0.3\";\n\t},\n\n\t/**\n\t * Toggles the focus of the legend\n\t * @private\n\t * @param {Array} ID's of target\n\t * @param {Boolean} whether or not to focus.\n\t */\n\ttoggleFocusLegend(targetIds, focus) {\n\t\tconst $$ = this;\n\t\tconst targetIdz = $$.mapToTargetIds(targetIds);\n\n\t\t$$.legend.selectAll(`.${CLASS.legendItem}`)\n\t\t\t.filter(id => targetIdz.indexOf(id) >= 0)\n\t\t\t.classed(CLASS.legendItemFocused, focus)\n\t\t\t.transition()\n\t\t\t.duration(100)\n\t\t\t.style(\"opacity\", function() {\n\t\t\t\treturn (focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend)\n\t\t\t\t\t.call($$, d3Select(this));\n\t\t\t});\n\t},\n\n\t/**\n\t * Revert the legend to its default state\n\t * @private\n\t */\n\trevertLegend() {\n\t\tconst $$ = this;\n\n\t\t$$.legend.selectAll(`.${CLASS.legendItem}`)\n\t\t\t.classed(CLASS.legendItemFocused, false)\n\t\t\t.transition()\n\t\t\t.duration(100)\n\t\t\t.style(\"opacity\", function() {\n\t\t\t\treturn $$.opacityForLegend(d3Select(this));\n\t\t\t});\n\t},\n\n\t/**\n\t * Shows the legend\n\t * @private\n\t * @param {Array} ID's of target\n\t */\n\tshowLegend(targetIds) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif (!config.legend_show) {\n\t\t\tconfig.legend_show = true;\n\t\t\t$$.legend.style(\"visibility\", \"visible\");\n\n\t\t\t!$$.legendHasRendered && $$.updateLegend();\n\t\t}\n\t\t$$.removeHiddenLegendIds(targetIds);\n\n\t\t$$.legend.selectAll($$.selectorLegends(targetIds))\n\t\t\t.style(\"visibility\", \"visible\")\n\t\t\t.transition()\n\t\t\t.style(\"opacity\", function() {\n\t\t\t\treturn $$.opacityForLegend(d3Select(this));\n\t\t\t});\n\t},\n\n\t/**\n\t * Hide the legend\n\t * @private\n\t * @param {Array} ID's of target\n\t */\n\thideLegend(targetIds) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif (config.legend_show && isEmpty(targetIds)) {\n\t\t\tconfig.legend_show = false;\n\t\t\t$$.legend.style(\"visibility\", \"hidden\");\n\t\t}\n\n\t\t$$.addHiddenLegendIds(targetIds);\n\t\t$$.legend.selectAll($$.selectorLegends(targetIds))\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.style(\"visibility\", \"hidden\");\n\t},\n\n\t/**\n\t * Clear the LegendItemTextBox cache.\n\t * @private\n\t */\n\tclearLegendItemTextBoxCache() {\n\t\tthis.legendItemTextBox = {};\n\t},\n\n\t/**\n\t * Set legend item style & bind events\n\t * @private\n\t * @param {d3.selection} item\n\t */\n\tsetLegendItem(item) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isTouch = $$.inputType === \"touch\";\n\t\tconst hasGauge = $$.hasType(\"gauge\");\n\n\t\titem\n\t\t\t.attr(\"class\", function(id) {\n\t\t\t\tconst node = d3Select(this);\n\t\t\t\tconst itemClass = (!node.empty() && node.attr(\"class\")) || \"\";\n\n\t\t\t\treturn itemClass + $$.generateClass(CLASS.legendItem, id);\n\t\t\t})\n\t\t\t.style(\"visibility\", id => ($$.isLegendToShow(id) ? \"visible\" : \"hidden\"))\n\t\t\t.style(\"cursor\", \"pointer\")\n\t\t\t.on(\"click\", id => {\n\t\t\t\tif (!callFn(config.legend_item_onclick, $$, id)) {\n\t\t\t\t\tif (d3Event.altKey) {\n\t\t\t\t\t\t$$.api.hide();\n\t\t\t\t\t\t$$.api.show(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$$.api.toggle(id);\n\t\t\t\t\t\t!isTouch && $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tisTouch && $$.hideTooltip();\n\t\t\t});\n\n\t\tif (!isTouch) {\n\t\t\titem\n\t\t\t\t.on(\"mouseout\", function(id) {\n\t\t\t\t\tif (!callFn(config.legend_item_onout, $$, id)) {\n\t\t\t\t\t\td3Select(this).classed(CLASS.legendItemFocused, false);\n\n\t\t\t\t\t\tif (hasGauge) {\n\t\t\t\t\t\t\t$$.undoMarkOverlapped($$, `.${CLASS.gaugeValue}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$$.api.revert();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.on(\"mouseover\", function(id) {\n\t\t\t\t\tif (!callFn(config.legend_item_onover, $$, id)) {\n\t\t\t\t\t\td3Select(this).classed(CLASS.legendItemFocused, true);\n\n\t\t\t\t\t\tif (hasGauge) {\n\t\t\t\t\t\t\t$$.markOverlapped(id, $$, `.${CLASS.gaugeValue}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!$$.transiting && $$.isTargetToShow(id)) {\n\t\t\t\t\t\t\t$$.api.focus(id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}\n\t},\n\n\t/**\n\t * Update the legend\n\t * @param {Array} targetIds ID's of target\n\t * @param {Object} options withTransform : Whether to use the transform property / withTransitionForTransform: Whether transition is used when using the transform property / withTransition : whether or not to transition.\n \t * @private\n\t */\n\tupdateLegendElement(targetIds, options) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst paddingTop = 4;\n\t\tconst paddingRight = 10;\n\t\tconst posMin = 10;\n\t\tconst tileWidth = config.legend_item_tile_width + 5;\n\t\tlet maxWidth = 0;\n\t\tlet maxHeight = 0;\n\t\tlet xForLegend;\n\t\tlet yForLegend;\n\t\tlet totalLength = 0;\n\t\tconst offsets = {};\n\t\tconst widths = {};\n\t\tconst heights = {};\n\t\tconst margins = [0];\n\t\tconst steps = {};\n\t\tlet step = 0;\n\t\tlet background;\n\t\tconst isLegendRightOrInset = $$.isLegendRight || $$.isLegendInset;\n\n\t\t// Skip elements when their name is set to null\n\t\tconst targetIdz = targetIds\n\t\t\t.filter(id => !isDefined(config.data_names[id]) || config.data_names[id] !== null);\n\n\t\tconst withTransition = options.withTransition;\n\n\t\tconst getTextBox = function(textElement, id) {\n\t\t\tif (!$$.legendItemTextBox[id]) {\n\t\t\t\t$$.legendItemTextBox[id] =\n\t\t\t\t\t$$.getTextRect(textElement, CLASS.legendItem);\n\t\t\t}\n\n\t\t\treturn $$.legendItemTextBox[id];\n\t\t};\n\n\t\tconst updatePositions = function(textElement, id, index) {\n\t\t\tconst reset = index === 0;\n\t\t\tconst isLast = index === targetIdz.length - 1;\n\t\t\tconst box = getTextBox(textElement, id);\n\t\t\tconst itemWidth = box.width + tileWidth +\n\t\t\t\t(isLast && !isLegendRightOrInset ? 0 : paddingRight) + config.legend_padding;\n\t\t\tconst itemHeight = box.height + paddingTop;\n\t\t\tconst itemLength = isLegendRightOrInset ? itemHeight : itemWidth;\n\t\t\tconst areaLength = isLegendRightOrInset ? $$.getLegendHeight() : $$.getLegendWidth();\n\t\t\tlet margin;\n\n\t\t\t// MEMO: care about condifion of step, totalLength\n\t\t\tconst updateValues = function(id2, withoutStep) {\n\t\t\t\tif (!withoutStep) {\n\t\t\t\t\tmargin = (areaLength - totalLength - itemLength) / 2;\n\n\t\t\t\t\tif (margin < posMin) {\n\t\t\t\t\t\tmargin = (areaLength - itemLength) / 2;\n\t\t\t\t\t\ttotalLength = 0;\n\t\t\t\t\t\tstep++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tsteps[id2] = step;\n\t\t\t\tmargins[step] = $$.isLegendInset ? 10 : margin;\n\t\t\t\toffsets[id2] = totalLength;\n\t\t\t\ttotalLength += itemLength;\n\t\t\t};\n\n\t\t\tif (reset) {\n\t\t\t\ttotalLength = 0;\n\t\t\t\tstep = 0;\n\t\t\t\tmaxWidth = 0;\n\t\t\t\tmaxHeight = 0;\n\t\t\t}\n\n\t\t\tif (config.legend_show && !$$.isLegendToShow(id)) {\n\t\t\t\twidths[id] = 0;\n\t\t\t\theights[id] = 0;\n\t\t\t\tsteps[id] = 0;\n\t\t\t\toffsets[id] = 0;\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twidths[id] = itemWidth;\n\t\t\theights[id] = itemHeight;\n\n\t\t\tif (!maxWidth || itemWidth >= maxWidth) {\n\t\t\t\tmaxWidth = itemWidth;\n\t\t\t}\n\n\t\t\tif (!maxHeight || itemHeight >= maxHeight) {\n\t\t\t\tmaxHeight = itemHeight;\n\t\t\t}\n\n\t\t\tconst maxLength = isLegendRightOrInset ? maxHeight : maxWidth;\n\n\t\t\tif (config.legend_equally) {\n\t\t\t\tObject.keys(widths).forEach(id2 => (widths[id2] = maxWidth));\n\t\t\t\tObject.keys(heights).forEach(id2 => (heights[id2] = maxHeight));\n\t\t\t\tmargin = (areaLength - maxLength * targetIdz.length) / 2;\n\n\t\t\t\tif (margin < posMin) {\n\t\t\t\t\ttotalLength = 0;\n\t\t\t\t\tstep = 0;\n\t\t\t\t\ttargetIdz.forEach(id2 => updateValues(id2));\n\t\t\t\t} else {\n\t\t\t\t\tupdateValues(id, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tupdateValues(id);\n\t\t\t}\n\t\t};\n\n\t\tif ($$.isLegendInset) {\n\t\t\tstep = config.legend_inset_step ? config.legend_inset_step : targetIdz.length;\n\t\t\t$$.updateLegendStep(step);\n\t\t}\n\n\t\tif ($$.isLegendRight) {\n\t\t\txForLegend = id => maxWidth * steps[id];\n\t\t\tyForLegend = id => margins[steps[id]] + offsets[id];\n\t\t} else if ($$.isLegendInset) {\n\t\t\txForLegend = id => maxWidth * steps[id] + 10;\n\t\t\tyForLegend = id => margins[steps[id]] + offsets[id];\n\t\t} else {\n\t\t\txForLegend = id => margins[steps[id]] + offsets[id];\n\t\t\tyForLegend = id => maxHeight * steps[id];\n\t\t}\n\n\t\tconst xForLegendText = (id, i) => xForLegend(id, i) + 4 + config.legend_item_tile_width;\n\t\tconst xForLegendRect = (id, i) => xForLegend(id, i);\n\t\tconst x1ForLegendTile = (id, i) => xForLegend(id, i) - 2;\n\t\tconst x2ForLegendTile = (id, i) => xForLegend(id, i) - 2 + config.legend_item_tile_width;\n\n\t\tconst yForLegendText = (id, i) => yForLegend(id, i) + 9;\n\t\tconst yForLegendRect = (id, i) => yForLegend(id, i) - 5;\n\t\tconst yForLegendTile = (id, i) => yForLegend(id, i) + 4;\n\n\t\tconst pos = -200;\n\n\t\t// Define g for legend area\n\t\tconst l = $$.legend.selectAll(`.${CLASS.legendItem}`)\n\t\t\t.data(targetIdz)\n\t\t\t.enter()\n\t\t\t.append(\"g\");\n\n\t\t$$.setLegendItem(l);\n\n\t\tl.append(\"text\")\n\t\t\t.text(id => (isDefined(config.data_names[id]) ? config.data_names[id] : id))\n\t\t\t.each(function(id, i) {\n\t\t\t\tupdatePositions(this, id, i);\n\t\t\t})\n\t\t\t.style(\"pointer-events\", \"none\")\n\t\t\t.attr(\"x\", isLegendRightOrInset ? xForLegendText : pos)\n\t\t\t.attr(\"y\", isLegendRightOrInset ? pos : yForLegendText);\n\n\t\tl.append(\"rect\")\n\t\t\t.attr(\"class\", CLASS.legendItemEvent)\n\t\t\t.style(\"fill-opacity\", \"0\")\n\t\t\t.attr(\"x\", isLegendRightOrInset ? xForLegendRect : pos)\n\t\t\t.attr(\"y\", isLegendRightOrInset ? pos : yForLegendRect);\n\n\t\tconst usePoint = $$.config.legend_usePoint;\n\n\t\tif (usePoint) {\n\t\t\tconst ids = [];\n\n\t\t\tl.append(d => {\n\t\t\t\tconst pattern = notEmpty(config.point_pattern) ?\n\t\t\t\t\tconfig.point_pattern : [config.point_type];\n\n\t\t\t\tids.indexOf(d) === -1 && ids.push(d);\n\n\t\t\t\tlet point = pattern[ids.indexOf(d) % pattern.length];\n\n\t\t\t\tif (point === \"rectangle\") {\n\t\t\t\t\tpoint = \"rect\";\n\t\t\t\t}\n\n\t\t\t\treturn document.createElementNS(d3Namespaces.svg, $$.hasValidPointType(point) ? point : \"use\");\n\t\t\t})\n\t\t\t\t.attr(\"class\", CLASS.legendItemPoint)\n\t\t\t\t.style(\"fill\", d => $$.color(d))\n\t\t\t\t.style(\"pointer-events\", \"none\")\n\t\t\t\t.attr(\"href\", (data, idx, selection) => {\n\t\t\t\t\tconst node = selection[idx];\n\t\t\t\t\tconst nodeName = node.nodeName.toLowerCase();\n\n\t\t\t\t\treturn nodeName === \"use\" ? `#${$$.datetimeId}-point-${data}` : undefined;\n\t\t\t\t});\n\t\t} else {\n\t\t\tl.append(\"line\")\n\t\t\t\t.attr(\"class\", CLASS.legendItemTile)\n\t\t\t\t.style(\"stroke\", $$.color)\n\t\t\t\t.style(\"pointer-events\", \"none\")\n\t\t\t\t.attr(\"x1\", isLegendRightOrInset ? x1ForLegendTile : pos)\n\t\t\t\t.attr(\"y1\", isLegendRightOrInset ? pos : yForLegendTile)\n\t\t\t\t.attr(\"x2\", isLegendRightOrInset ? x2ForLegendTile : pos)\n\t\t\t\t.attr(\"y2\", isLegendRightOrInset ? pos : yForLegendTile)\n\t\t\t\t.attr(\"stroke-width\", config.legend_item_tile_height);\n\t\t}\n\n\t\t// Set background for inset legend\n\t\tbackground = $$.legend.select(`.${CLASS.legendBackground} rect`);\n\n\t\tif ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {\n\t\t\tbackground = $$.legend.insert(\"g\", `.${CLASS.legendItem}`)\n\t\t\t\t.attr(\"class\", CLASS.legendBackground)\n\t\t\t\t.append(\"rect\");\n\t\t}\n\n\t\tconst texts = $$.legend.selectAll(\"text\")\n\t\t\t.data(targetIdz)\n\t\t\t.text(id => (isDefined(config.data_names[id]) ? config.data_names[id] : id)) // MEMO: needed for update\n\t\t\t.each(function(id, i) {\n\t\t\t\tupdatePositions(this, id, i);\n\t\t\t});\n\n\t\t(withTransition ? texts.transition() : texts)\n\t\t\t.attr(\"x\", xForLegendText)\n\t\t\t.attr(\"y\", yForLegendText);\n\n\t\tconst rects = $$.legend.selectAll(`rect.${CLASS.legendItemEvent}`)\n\t\t\t.data(targetIdz);\n\n\t\t(withTransition ? rects.transition() : rects)\n\t\t\t.attr(\"width\", id => widths[id])\n\t\t\t.attr(\"height\", id => heights[id])\n\t\t\t.attr(\"x\", xForLegendRect)\n\t\t\t.attr(\"y\", yForLegendRect);\n\n\n\t\tif (usePoint) {\n\t\t\tconst tiles = $$.legend.selectAll(`.${CLASS.legendItemPoint}`)\n\t\t\t\t.data(targetIdz);\n\n\t\t\t(withTransition ? tiles.transition() : tiles)\n\t\t\t\t.each(function() {\n\t\t\t\t\tconst nodeName = this.nodeName.toLowerCase();\n\t\t\t\t\tconst pointR = $$.config.point_r;\n\t\t\t\t\tlet x = \"x\";\n\t\t\t\t\tlet y = \"y\";\n\t\t\t\t\tlet xOffset = 2;\n\t\t\t\t\tlet yOffset = 2.5;\n\t\t\t\t\tlet radius;\n\t\t\t\t\tlet width;\n\t\t\t\t\tlet height;\n\n\t\t\t\t\tif (nodeName === \"circle\") {\n\t\t\t\t\t\tconst size = pointR * 0.2;\n\n\t\t\t\t\t\tx = \"cx\";\n\t\t\t\t\t\ty = \"cy\";\n\t\t\t\t\t\tradius = pointR + size;\n\t\t\t\t\t\txOffset = pointR * 2;\n\t\t\t\t\t\tyOffset = -size;\n\t\t\t\t\t} else if (nodeName === \"rect\") {\n\t\t\t\t\t\tconst size = pointR * 2.5;\n\n\t\t\t\t\t\twidth = size;\n\t\t\t\t\t\theight = size;\n\t\t\t\t\t\tyOffset = 3;\n\t\t\t\t\t}\n\n\t\t\t\t\td3Select(this)\n\t\t\t\t\t\t.attr(x, d => x1ForLegendTile(d) + xOffset)\n\t\t\t\t\t\t.attr(y, d => yForLegendTile(d) - yOffset)\n\t\t\t\t\t\t.attr(\"r\", radius)\n\t\t\t\t\t\t.attr(\"width\", width)\n\t\t\t\t\t\t.attr(\"height\", height);\n\t\t\t\t});\n\t\t} else {\n\t\t\tconst tiles = $$.legend.selectAll(`line.${CLASS.legendItemTile}`)\n\t\t\t\t.data(targetIdz);\n\n\t\t\t(withTransition ? tiles.transition() : tiles)\n\t\t\t\t.style(\"stroke\", $$.levelColor ? id => $$.levelColor($$.cache[id].values[0].value) : $$.color)\n\t\t\t\t.attr(\"x1\", x1ForLegendTile)\n\t\t\t\t.attr(\"y1\", yForLegendTile)\n\t\t\t\t.attr(\"x2\", x2ForLegendTile)\n\t\t\t\t.attr(\"y2\", yForLegendTile);\n\t\t}\n\n\t\tif (background) {\n\t\t\t(withTransition ? background.transition() : background)\n\t\t\t\t.attr(\"height\", $$.getLegendHeight() - 12)\n\t\t\t\t.attr(\"width\", maxWidth * (step + 1) + 10);\n\t\t}\n\n\t\t// Update all to reflect change of legend\n\t\t$$.updateLegendItemWidth(maxWidth);\n\t\t$$.updateLegendItemHeight(maxHeight);\n\t\t$$.updateLegendStep(step);\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {extend, isNumber, setTextValue} from \"./util\";\nimport CLASS from \"../config/classes\";\n\n/**\n * Get the text position\n * @param {String} pos right, left or center\n * @param {Number} width chart width\n * @return {String|Number} text-anchor value or position in pixel\n * @private\n */\nconst getTextPos = (pos = \"left\", width) => {\n\tlet position;\n\tconst isNum = isNumber(width);\n\n\tif (pos.indexOf(\"center\") > -1) {\n\t\tposition = isNum ? width / 2 : \"middle\";\n\t} else if (pos.indexOf(\"right\") > -1) {\n\t\tposition = isNum ? width : \"end\";\n\t} else {\n\t\tposition = isNum ? 0 : \"start\";\n\t}\n\n\treturn position;\n};\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initializes the title\n\t * @private\n\t */\n\tinitTitle() {\n\t\tconst $$ = this;\n\n\t\tif ($$.config.title_text) {\n\t\t\t$$.title = $$.svg.append(\"g\");\n\n\t\t\tconst text = $$.title\n\t\t\t\t.append(\"text\")\n\t\t\t\t.style(\"text-anchor\", getTextPos($$.config.title_position))\n\t\t\t\t.attr(\"class\", CLASS.title);\n\n\t\t\tsetTextValue(text, $$.config.title_text, [0.3, 1.5]);\n\t\t}\n\t},\n\n\t/**\n\t * Redraw title\n\t * @private\n\t */\n\tredrawTitle() {\n\t\tconst $$ = this;\n\n\t\tif ($$.title) {\n\t\t\tconst y = $$.yForTitle.call($$);\n\n\t\t\tif (/g/i.test($$.title.node().tagName)) {\n\t\t\t\t$$.title.attr(\"transform\", `translate(${getTextPos($$.config.title_position, $$.currentWidth)}, ${y})`);\n\t\t\t} else {\n\t\t\t\t$$.title.attr(\"x\", $$.xForTitle.call($$)).attr(\"y\", y);\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Returns the x attribute value of the title\n\t * @private\n\t * @returns {Number} x attribute value\n\t */\n\txForTitle() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst position = config.title_position || \"left\";\n\t\tconst textRectWidth = $$.getTextRect($$.title, CLASS.title).width;\n\t\tlet x;\n\n\t\tif (/(right|center)/.test(position)) {\n\t\t\tx = $$.currentWidth - textRectWidth;\n\n\t\t\tif (position.indexOf(\"right\") >= 0) {\n\t\t\t\tx = $$.currentWidth - textRectWidth - config.title_padding.right;\n\t\t\t} else if (position.indexOf(\"center\") >= 0) {\n\t\t\t\tx = ($$.currentWidth - textRectWidth) / 2;\n\t\t\t}\n\t\t} else { // left\n\t\t\tx = (config.title_padding.left || 0);\n\t\t}\n\n\t\treturn x;\n\t},\n\n\t/**\n\t * Returns the y attribute value of the title\n\t * @private\n\t * @returns {Number} y attribute value\n\t */\n\tyForTitle() {\n\t\tconst $$ = this;\n\n\t\treturn ($$.config.title_padding.top || 0) +\n\t\t\t$$.getTextRect($$.title, CLASS.title).height;\n\t},\n\n\t/**\n\t * Get title padding\n\t * @private\n\t * @returns {Number} padding value\n\t */\n\tgetTitlePadding() {\n\t\tconst $$ = this;\n\n\t\treturn $$.yForTitle() + ($$.config.title_padding.bottom || 0);\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {document, window} from \"../internals/browser\";\nimport {extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\tinitClip() {\n\t\tconst $$ = this;\n\n\t\t// MEMO: clipId needs to be unique because it conflicts when multiple charts exist\n\t\t$$.clipId = `${$$.datetimeId}-clip`;\n\n\t\t$$.clipIdForXAxis = `${$$.clipId}-xaxis`;\n\t\t$$.clipIdForYAxis = `${$$.clipId}-yaxis`;\n\t\t$$.clipIdForGrid = `${$$.clipId}-grid`;\n\n\t\t// Define 'clip-path' attribute values\n\t\t$$.clipPath = $$.getClipPath($$.clipId);\n\t\t$$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis);\n\t\t$$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);\n\t\t$$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid);\n\t},\n\n\tgetClipPath(id) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif ((!config.clipPath && /-clip$/.test(id)) ||\n\t\t\t(!config.axis_x_clipPath && /-clip-xaxis$/.test(id)) ||\n\t\t\t(!config.axis_y_clipPath && /-clip-yaxis$/.test(id))) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst isIE9 = window.navigator ?\n\t\t\twindow.navigator.appVersion\n\t\t\t\t.toLowerCase().indexOf(\"msie 9.\") >= 0 : false;\n\n\t\treturn `url(${(isIE9 ? \"\" : document.URL.split(\"#\")[0])}#${id})`;\n\t},\n\n\tappendClip(parent, id) {\n\t\treturn parent.append(\"clipPath\")\n\t\t\t.attr(\"id\", id)\n\t\t\t.append(\"rect\");\n\t},\n\n\tgetAxisClipX(forHorizontal) {\n\t\t// axis line width + padding for left\n\t\tconst left = Math.max(30, this.margin.left);\n\n\t\treturn forHorizontal ? -(1 + left) : -(left - 1);\n\t},\n\n\tgetAxisClipY(forHorizontal) {\n\t\treturn forHorizontal ? -20 : -this.margin.top;\n\t},\n\n\tgetXAxisClipX() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipX(!$$.config.axis_rotated);\n\t},\n\n\tgetXAxisClipY() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipY(!$$.config.axis_rotated);\n\t},\n\n\tgetYAxisClipX() {\n\t\tconst $$ = this;\n\n\t\treturn $$.config.axis_y_inner ?\n\t\t\t-1 : $$.getAxisClipX($$.config.axis_rotated);\n\t},\n\n\tgetYAxisClipY() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipY($$.config.axis_rotated);\n\t},\n\n\tgetAxisClipWidth(forHorizontal) {\n\t\tconst $$ = this;\n\t\tconst left = Math.max(30, $$.margin.left);\n\t\tconst right = Math.max(30, $$.margin.right);\n\n\t\t// width + axis line width + padding for left/right\n\t\treturn forHorizontal ?\n\t\t\t$$.width + 2 + left + right : $$.margin.left + 20;\n\t},\n\n\tgetAxisClipHeight(forHorizontal) {\n\t\t// less than 20 is not enough to show the axis label 'outer' without legend\n\t\treturn (forHorizontal ? this.margin.bottom : (this.margin.top + this.height)) + 20;\n\t},\n\n\tgetXAxisClipWidth() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipWidth(!$$.config.axis_rotated);\n\t},\n\n\tgetXAxisClipHeight() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipHeight(!$$.config.axis_rotated);\n\t},\n\n\tgetYAxisClipWidth() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);\n\t},\n\n\tgetYAxisClipHeight() {\n\t\tconst $$ = this;\n\n\t\treturn $$.getAxisClipHeight($$.config.axis_rotated);\n\t},\n\n\tupdateXAxisTickClip() {\n\t\tconst $$ = this;\n\t\tconst newXAxisHeight = $$.getHorizontalAxisHeight(\"x\");\n\n\t\t$$.clipIdForXAxisTickTexts = `${$$.clipId}-xaxisticktexts`;\n\t\t$$.clipPathForXAxisTickTexts = $$.getClipPath($$.clipIdForXAxisTickTexts);\n\n\t\tif (!$$.config.axis_x_tick_multiline &&\n\t\t\t$$.getAxisTickRotate(\"x\") &&\n\t\t\tnewXAxisHeight !== $$.xAxisHeight\n\t\t) {\n\t\t\t$$.setXAxisTickClipWidth();\n\t\t\t$$.setXAxisTickTextClipPathWidth();\n\t\t}\n\n\t\t$$.xAxisHeight = newXAxisHeight;\n\t},\n\n\tsetXAxisTickClipWidth() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst xAxisTickRotate = $$.getAxisTickRotate(\"x\");\n\n\t\tif (!config.axis_x_tick_multiline && xAxisTickRotate) {\n\t\t\tconst sinRotation = Math.sin(Math.PI / 180 * Math.abs(xAxisTickRotate));\n\n\t\t\t$$.xAxisTickClipPathMaxWidth = ($$.getHorizontalAxisHeight(\"x\") - 20) / sinRotation;\n\t\t} else {\n\t\t\t$$.xAxisTickClipPathMaxWidth = null;\n\t\t}\n\t},\n\n\tsetXAxisTickTextClipPathWidth() {\n\t\tconst $$ = this;\n\n\t\tif ($$.svg) {\n\t\t\t$$.svg.select(`#${$$.clipIdForXAxisTickTexts} rect`)\n\t\t\t\t.attr(\"width\", $$.xAxisTickClipPathMaxWidth)\n\t\t\t\t.attr(\"height\", 30);\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\"; // selection\nimport ChartInternal from \"./ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {isValue, extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\tinitRegion() {\n\t\tconst $$ = this;\n\n\t\t$$.region = $$.main.append(\"g\")\n\t\t\t.attr(\"clip-path\", $$.clipPath)\n\t\t\t.attr(\"class\", CLASS.regions);\n\t},\n\n\tupdateRegion(duration) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t// hide if arc type\n\t\t$$.region.style(\"visibility\", $$.hasArcType() ? \"hidden\" : \"visible\");\n\n\t\t// select <g> element\n\t\t$$.mainRegion = $$.main.select(`.${CLASS.regions}`)\n\t\t\t.selectAll(`.${CLASS.region}`)\n\t\t\t.data(config.regions);\n\n\t\t$$.mainRegion.exit()\n\t\t\t.transition()\n\t\t\t.duration(duration)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.mainRegion = $$.mainRegion.enter()\n\t\t\t.append(\"g\")\n\t\t\t.merge($$.mainRegion)\n\t\t\t.attr(\"class\", $$.classRegion.bind($$));\n\n\t\t$$.mainRegion\n\t\t\t.append(\"rect\")\n\t\t\t.style(\"fill-opacity\", \"0\");\n\t},\n\n\tredrawRegion(withTransition) {\n\t\tconst $$ = this;\n\t\tlet regions = $$.mainRegion.select(\"rect\");\n\n\t\tregions = (withTransition ? regions.transition() : regions)\n\t\t\t.attr(\"x\", $$.regionX.bind($$))\n\t\t\t.attr(\"y\", $$.regionY.bind($$))\n\t\t\t.attr(\"width\", $$.regionWidth.bind($$))\n\t\t\t.attr(\"height\", $$.regionHeight.bind($$));\n\n\t\treturn [\n\t\t\t(withTransition ? regions.transition() : regions)\n\t\t\t\t.style(\"fill-opacity\", d => (isValue(d.opacity) ? d.opacity : \"0.1\"))\n\t\t\t\t.on(\"end\", function() {\n\t\t\t\t\t// remove unnecessary rect after transition\n\t\t\t\t\td3Select(this.parentNode)\n\t\t\t\t\t\t.selectAll(\"rect:not([x])\")\n\t\t\t\t\t\t.remove();\n\t\t\t\t})\n\t\t];\n\t},\n\n\tgetRegionXY(type, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst isX = type === \"x\";\n\t\tlet key = \"start\";\n\t\tlet scale;\n\t\tlet pos = 0;\n\n\t\tif (d.axis === \"y\" || d.axis === \"y2\") {\n\t\t\tif (!isX) {\n\t\t\t\tkey = \"end\";\n\t\t\t}\n\n\t\t\tif ((isX ? isRotated : !isRotated) && key in d) {\n\t\t\t\tscale = $$[d.axis];\n\t\t\t\tpos = scale(d[key]);\n\t\t\t}\n\t\t} else if ((isX ? !isRotated : isRotated) && key in d) {\n\t\t\tscale = $$.zoomScale || $$.x;\n\t\t\tpos = scale($$.isTimeSeries() ? $$.parseDate(d[key]) : d[key]);\n\t\t}\n\n\t\treturn pos;\n\t},\n\n\tregionX(d) {\n\t\treturn this.getRegionXY(\"x\", d);\n\t},\n\n\tregionY(d) {\n\t\treturn this.getRegionXY(\"y\", d);\n\t},\n\n\tgetRegionSize(type, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst isWidth = type === \"width\";\n\t\tconst start = $$[isWidth ? \"regionX\" : \"regionY\"](d);\n\t\tlet scale;\n\t\tlet key = \"end\";\n\t\tlet end = $$[type];\n\n\t\tif (d.axis === \"y\" || d.axis === \"y2\") {\n\t\t\tif (!isWidth) {\n\t\t\t\tkey = \"start\";\n\t\t\t}\n\n\t\t\tif ((isWidth ? isRotated : !isRotated) && key in d) {\n\t\t\t\tscale = $$[d.axis];\n\t\t\t\tend = scale(d[key]);\n\t\t\t}\n\t\t} else if ((isWidth ? !isRotated : isRotated) && key in d) {\n\t\t\tscale = $$.zoomScale || $$.x;\n\t\t\tend = scale($$.isTimeSeries() ? $$.parseDate(d[key]) : d[key]);\n\t\t}\n\n\t\treturn end < start ? 0 : end - start;\n\t},\n\n\tregionWidth(d) {\n\t\treturn this.getRegionSize(\"width\", d);\n\t},\n\n\tregionHeight(d) {\n\t\treturn this.getRegionSize(\"height\", d);\n\t},\n\n\tisRegionOnX(d) {\n\t\treturn !d.axis || d.axis === \"x\";\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend, getPathBox} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Called when dragging.\n\t * Data points can be selected.\n\t * @private\n\t * @param {Object} mouse Object\n\t */\n\tdrag(mouse) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst main = $$.main;\n\n\t\tif ($$.hasArcType() ||\n\t\t\t!config.data_selection_enabled || // do nothing if not selectable\n\t\t\t(config.zoom_enabled && !$$.zoom.altDomain) || // skip if zoomable because of conflict drag behavior\n\t\t\t!config.data_selection_multiple // skip when single selection because drag is used for multiple selection\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst [sx, sy] = $$.dragStart;\n\t\tconst [mx, my] = mouse;\n\n\t\tconst minX = Math.min(sx, mx);\n\t\tconst maxX = Math.max(sx, mx);\n\t\tconst minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);\n\t\tconst maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);\n\n\t\tmain.select(`.${CLASS.dragarea}`)\n\t\t\t.attr(\"x\", minX)\n\t\t\t.attr(\"y\", minY)\n\t\t\t.attr(\"width\", maxX - minX)\n\t\t\t.attr(\"height\", maxY - minY);\n\n\t\t// TODO: binary search when multiple xs\n\t\tmain.selectAll(`.${CLASS.shapes}`)\n\t\t\t.selectAll(`.${CLASS.shape}`)\n\t\t\t.filter(d => config.data_selection_isselectable(d))\n\t\t\t.each(function(d, i) {\n\t\t\t\tconst shape = d3Select(this);\n\t\t\t\tconst isSelected = shape.classed(CLASS.SELECTED);\n\t\t\t\tconst isIncluded = shape.classed(CLASS.INCLUDED);\n\t\t\t\tlet toggle;\n\t\t\t\tlet isWithin = false;\n\n\t\t\t\tif (shape.classed(CLASS.circle)) {\n\t\t\t\t\tconst x = shape.attr(\"cx\") * 1;\n\t\t\t\t\tconst y = shape.attr(\"cy\") * 1;\n\n\t\t\t\t\ttoggle = $$.togglePoint;\n\t\t\t\t\tisWithin = minX < x && x < maxX && minY < y && y < maxY;\n\t\t\t\t} else if (shape.classed(CLASS.bar)) {\n\t\t\t\t\tconst {x, y, width, height} = getPathBox(this);\n\n\t\t\t\t\ttoggle = $$.togglePath;\n\t\t\t\t\tisWithin = !(maxX < x || x + width < minX) && !(maxY < y || y + height < minY);\n\t\t\t\t} else {\n\t\t\t\t\t// line/area selection not supported yet\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (isWithin ^ isIncluded) {\n\t\t\t\t\tshape.classed(CLASS.INCLUDED, !isIncluded);\n\t\t\t\t\t// TODO: included/unincluded callback here\n\t\t\t\t\tshape.classed(CLASS.SELECTED, !isSelected);\n\t\t\t\t\ttoggle.call($$, !isSelected, shape, d, i);\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\t/**\n\t * Called when the drag starts.\n\t * Adds and Shows the drag area.\n\t * @private\n\t * @param {Object} mouse Object\n\t */\n\tdragstart(mouse) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif ($$.hasArcType() || !config.data_selection_enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.dragStart = mouse;\n\n\t\t$$.main.select(`.${CLASS.chart}`)\n\t\t\t.append(\"rect\")\n\t\t\t.attr(\"class\", CLASS.dragarea)\n\t\t\t.style(\"opacity\", \"0.1\");\n\n\t\t$$.setDragStatus(true);\n\t},\n\n\t/**\n\t * Called when the drag finishes.\n\t * Removes the drag area.\n\t * @private\n\t */\n\tdragend() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tif ($$.hasArcType() || !config.data_selection_enabled) { // do nothing if not selectable\n\t\t\treturn;\n\t\t}\n\n\t\t$$.main.select(`.${CLASS.dragarea}`)\n\t\t\t.transition()\n\t\t\t.duration(100)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.main.selectAll(`.${CLASS.shape}`)\n\t\t\t.classed(CLASS.INCLUDED, false);\n\n\t\t$$.setDragStatus(false);\n\t},\n\n\tsetDragStatus(isDragging) {\n\t\tthis.dragging = isDragging;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\";\nimport {rgb as d3Rgb} from \"d3-color\";\nimport ChartInternal from \"./ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend, callFn} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Select a point\n\t * @private\n\t * @param {Object} target point\n\t * @param {Object} data\n\t * @param {Number} index\n\t */\n\tselectPoint(target, d, i) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tconst cx = (isRotated ? $$.circleY : $$.circleX).bind($$);\n\t\tconst cy = (isRotated ? $$.circleX : $$.circleY).bind($$);\n\t\tconst r = $$.pointSelectR.bind($$);\n\n\t\tcallFn(config.data_onselected, $$.api, d, target.node());\n\n\t\t// add selected-circle on low layer g\n\t\t$$.main.select(`.${CLASS.selectedCircles}${$$.getTargetSelectorSuffix(d.id)}`)\n\t\t\t.selectAll(`.${CLASS.selectedCircle}-${i}`)\n\t\t\t.data([d])\n\t\t\t.enter()\n\t\t\t.append(\"circle\")\n\t\t\t.attr(\"class\", () => $$.generateClass(CLASS.selectedCircle, i))\n\t\t\t.attr(\"cx\", cx)\n\t\t\t.attr(\"cy\", cy)\n\t\t\t.attr(\"stroke\", $$.color)\n\t\t\t.attr(\"r\", d2 => $$.pointSelectR(d2) * 1.4)\n\t\t\t.transition()\n\t\t\t.duration(100)\n\t\t\t.attr(\"r\", r);\n\t},\n\n\t/**\n\t * Unelect a point\n\t * @private\n\t * @param {Object} target point\n\t * @param {Object} data\n\t * @param {Number} index\n\t */\n\tunselectPoint(target, d, i) {\n\t\tconst $$ = this;\n\n\t\tcallFn($$.config.data_onunselected, $$.api, d, target.node());\n\n\t\t// remove selected-circle from low layer g\n\t\t$$.main.select(`.${CLASS.selectedCircles}${$$.getTargetSelectorSuffix(d.id)}`)\n\t\t\t.selectAll(`.${CLASS.selectedCircle}-${i}`)\n\t\t\t.transition()\n\t\t\t.duration(100)\n\t\t\t.attr(\"r\", 0)\n\t\t\t.remove();\n\t},\n\n\t/**\n\t * Toggles the selection of points\n\t * @private\n\t * @param {Boolean} whether or not to select.\n\t * @param {Object} target point\n\t * @param {Object} data\n\t * @param {Number} index\n\t */\n\ttogglePoint(selected, target, d, i) {\n\t\tconst method = `${selected ? \"\" : \"un\"}selectPoint`;\n\n\t\tthis[method](target, d, i);\n\t},\n\n\t/**\n\t * Select a path\n\t * @private\n\t * @param {Object} target path\n\t * @param {Object} data\n\t */\n\tselectPath(target, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tcallFn(config.data_onselected, $$, d, target.node());\n\n\t\tif (config.interaction_brighten) {\n\t\t\ttarget.transition().duration(100)\n\t\t\t\t.style(\"fill\", () => d3Rgb($$.color(d)).brighter(0.75));\n\t\t}\n\t},\n\n\t/**\n\t * Unelect a path\n\t * @private\n\t * @param {Object} target path\n\t * @param {Object} data\n\t */\n\tunselectPath(target, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tcallFn(config.data_onunselected, $$, d, target.node());\n\n\t\tif (config.interaction_brighten) {\n\t\t\ttarget.transition().duration(100)\n\t\t\t\t.style(\"fill\", () => $$.color(d));\n\t\t}\n\t},\n\n\t/**\n\t * Toggles the selection of lines\n\t * @private\n\t * @param {Boolean} whether or not to select.\n\t * @param {Object} target shape\n\t * @param {Object} data\n\t * @param {Number} index\n\t */\n\ttogglePath(selected, target, d, i) {\n\t\tthis[\n\t\t\t`${selected ? \"\" : \"un\"}selectPath`\n\t\t](target, d, i);\n\t},\n\n\t/**\n\t * Returns the toggle method of the target\n\t * @private\n\t * @param {Object} target shape\n\t * @param {Object} data\n\t * @returns {Function} toggle method\n\t */\n\tgetToggle(that, d) {\n\t\tconst $$ = this;\n\n\t\treturn that.nodeName === \"path\" ?\n\t\t\t$$.togglePath : (\n\t\t\t\t$$.isStepType(d) ?\n\t\t\t\t\t() => {} : // circle is hidden in step chart, so treat as within the click area\n\t\t\t\t\t$$.togglePoint\n\t\t\t);\n\t},\n\n\t/**\n\t * Toggles the selection of shapes\n\t * @private\n\t * @param {Object} target shape\n\t * @param {Object} data\n\t * @param {Number} index\n\t */\n\ttoggleShape(that, d, i) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst shape = d3Select(that);\n\t\tconst isSelected = shape.classed(CLASS.SELECTED);\n\t\tconst toggle = $$.getToggle(that, d).bind($$);\n\t\tlet toggledShape;\n\n\t\tif (config.data_selection_enabled && config.data_selection_isselectable(d)) {\n\t\t\tif (!config.data_selection_multiple) {\n\t\t\t\tlet selector = `.${CLASS.shapes}`;\n\n\t\t\t\tif (config.data_selection_grouped) {\n\t\t\t\t\tselector += $$.getTargetSelectorSuffix(d.id);\n\t\t\t\t}\n\n\t\t\t\t$$.main.selectAll(selector)\n\t\t\t\t\t.selectAll(`.${CLASS.shape}`)\n\t\t\t\t\t.each(function(d, i) {\n\t\t\t\t\t\tconst shape = d3Select(this);\n\n\t\t\t\t\t\tif (shape.classed(CLASS.SELECTED)) {\n\t\t\t\t\t\t\ttoggledShape = shape;\n\t\t\t\t\t\t\ttoggle(false, shape.classed(CLASS.SELECTED, false), d, i);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!toggledShape || toggledShape.node() !== shape.node()) {\n\t\t\t\tshape.classed(CLASS.SELECTED, !isSelected);\n\t\t\t\ttoggle(!isSelected, shape, d, i);\n\t\t\t}\n\t\t}\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tselect as d3Select,\n\tevent as d3Event\n} from \"d3-selection\";\nimport {\n\tbrushX as d3BrushX,\n\tbrushY as d3BrushY,\n\tbrushSelection as d3BrushSelection\n} from \"d3-brush\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend, brushEmpty, capitalize, isArray, isFunction, getRandom} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initialize the brush.\n\t * @private\n\t */\n\tinitBrush() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\n\t\t// set the brush\n\t\t$$.brush = isRotated ? d3BrushY() : d3BrushX();\n\n\t\t// set \"brush\" event\n\t\tconst brushHandler = () => {\n\t\t\t$$.redrawForBrush();\n\t\t};\n\t\tconst getBrushSize = () => {\n\t\t\tconst brush = $$.svg.select(`.${CLASS.brush} .overlay`);\n\t\t\tconst brushSize = {width: 0, height: 0};\n\n\t\t\tif (brush.size()) {\n\t\t\t\tbrushSize.width = +brush.attr(\"width\");\n\t\t\t\tbrushSize.height = +brush.attr(\"height\");\n\t\t\t}\n\n\t\t\treturn brushSize[isRotated ? \"width\" : \"height\"];\n\t\t};\n\n\t\tlet lastDomain;\n\t\tlet timeout;\n\n\t\t$$.brush\n\t\t\t.on(\"start\", () => {\n\t\t\t\t$$.inputType === \"touch\" && $$.hideTooltip();\n\t\t\t\tbrushHandler();\n\t\t\t})\n\t\t\t.on(\"brush\", brushHandler)\n\t\t\t.on(\"end\", () => {\n\t\t\t\tlastDomain = $$.x.orgDomain();\n\t\t\t});\n\n\t\t$$.brush.updateResize = function() {\n\t\t\ttimeout && clearTimeout(timeout);\n\t\t\ttimeout = setTimeout(() => {\n\t\t\t\tconst selection = this.getSelection();\n\n\t\t\t\tlastDomain && d3BrushSelection(selection.node()) &&\n\t\t\t\t\tthis.move(selection, lastDomain.map($$.subX.orgScale()));\n\t\t\t}, 0);\n\t\t};\n\n\t\t$$.brush.update = function() {\n\t\t\tconst extent = this.extent()();\n\n\t\t\tif (extent[1].filter(v => isNaN(v)).length === 0) {\n\t\t\t\t$$.context && $$.context.select(`.${CLASS.brush}`).call(this);\n\t\t\t}\n\n\t\t\treturn this;\n\t\t};\n\n\t\t// set the brush extent\n\t\t$$.brush.scale = function(scale) {\n\t\t\tconst h = config.subchart_size_height || getBrushSize();\n\t\t\tlet extent = $$.getExtent();\n\n\t\t\tif (!extent && scale.range) {\n\t\t\t\textent = [[0, 0], [scale.range()[1], h]];\n\t\t\t} else if (isArray(extent)) {\n\t\t\t\textent = extent.map((v, i) => [v, i > 0 ? h : i]);\n\t\t\t}\n\n\t\t\t// [[x0, y0], [x1, y1]], where [x0, y0] is the top-left corner and [x1, y1] is the bottom-right corner\n\t\t\tisRotated && extent[1].reverse();\n\t\t\tthis.extent(extent);\n\n\t\t\t// when extent updates, brush selection also be re-applied\n\t\t\t// https://github.com/d3/d3/issues/2918\n\t\t\tthis.update();\n\t\t};\n\n\t\t$$.brush.getSelection = () => (\n\t\t\t$$.context ? $$.context.select(`.${CLASS.brush}`) : d3Select([])\n\t\t);\n\t},\n\n\t/**\n\t * Initialize the subchart.\n\t * @private\n\t */\n\tinitSubchart() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst visibility = config.subchart_show ? \"visible\" : \"hidden\";\n\t\tconst clipId = `${$$.clipId}-subchart`;\n\t\tconst clipPath = $$.getClipPath(clipId);\n\n\t\t$$.clipIdForSubchart = clipId;\n\t\t$$.appendClip($$.defs, clipId);\n\t\t$$.initBrush();\n\n\t\t$$.context = $$.svg.append(\"g\").attr(\"transform\", $$.getTranslate(\"context\"));\n\n\t\tconst context = $$.context;\n\n\t\tcontext.style(\"visibility\", visibility);\n\n\t\t// Define g for chart area\n\t\tcontext.append(\"g\")\n\t\t\t.attr(\"clip-path\", clipPath)\n\t\t\t.attr(\"class\", CLASS.chart);\n\n\t\t// Define g for bar chart area\n\t\t$$.hasType(\"bar\") && context.select(`.${CLASS.chart}`)\n\t\t\t.append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartBars);\n\n\t\t// Define g for line chart area\n\t\tcontext.select(`.${CLASS.chart}`)\n\t\t\t.append(\"g\")\n\t\t\t.attr(\"class\", CLASS.chartLines);\n\n\t\t// Add extent rect for Brush\n\t\tcontext.append(\"g\")\n\t\t\t.attr(\"clip-path\", clipPath)\n\t\t\t.attr(\"class\", CLASS.brush)\n\t\t\t.call($$.brush);\n\n\t\t// ATTENTION: This must be called AFTER chart added\n\t\t// Add Axis\n\t\t$$.axes.subx = context.append(\"g\")\n\t\t\t.attr(\"class\", CLASS.axisX)\n\t\t\t.attr(\"transform\", $$.getTranslate(\"subx\"))\n\t\t\t.attr(\"clip-path\", config.axis_rotated ? \"\" : $$.clipPathForXAxis)\n\t\t\t.style(\"visibility\", config.subchart_axis_x_show ? visibility : \"hidden\");\n\t},\n\n\t/**\n\t * Update sub chart\n\t * @private\n\t * @param {Object} $$.data.targets\n\t */\n\tupdateTargetsForSubchart(targets) {\n\t\tconst $$ = this;\n\t\tconst context = $$.context;\n\t\tconst config = $$.config;\n\t\tconst classChartBar = $$.classChartBar.bind($$);\n\t\tconst classBars = $$.classBars.bind($$);\n\t\tconst classChartLine = $$.classChartLine.bind($$);\n\t\tconst classLines = $$.classLines.bind($$);\n\t\tconst classAreas = $$.classAreas.bind($$);\n\n\t\tif (config.subchart_show) {\n\t\t\t// -- Bar --//\n\t\t\tconst contextBarUpdate = context.select(`.${CLASS.chartBars}`)\n\t\t\t\t.selectAll(`.${CLASS.chartBar}`)\n\t\t\t\t.data(targets)\n\t\t\t\t.attr(\"class\", classChartBar);\n\t\t\tconst contextBarEnter = contextBarUpdate.enter()\n\t\t\t\t.append(\"g\")\n\t\t\t\t.style(\"opacity\", \"0\")\n\t\t\t\t.attr(\"class\", classChartBar)\n\t\t\t\t.merge(contextBarUpdate);\n\n\t\t\t// Bars for each data\n\t\t\tcontextBarEnter.append(\"g\")\n\t\t\t\t.attr(\"class\", classBars);\n\n\t\t\t// -- Line --//\n\t\t\tconst contextLineUpdate = context.select(`.${CLASS.chartLines}`)\n\t\t\t\t.selectAll(`.${CLASS.chartLine}`)\n\t\t\t\t.data(targets)\n\t\t\t\t.attr(\"class\", classChartLine);\n\t\t\tconst contextLineEnter = contextLineUpdate.enter().append(\"g\")\n\t\t\t\t.style(\"opacity\", \"0\")\n\t\t\t\t.attr(\"class\", classChartLine)\n\t\t\t\t.merge(contextLineUpdate);\n\n\t\t\t// Lines for each data\n\t\t\tcontextLineEnter.append(\"g\")\n\t\t\t\t.attr(\"class\", classLines);\n\n\t\t\t// Area\n\t\t\t$$.hasType(\"area\") && contextLineEnter.append(\"g\")\n\t\t\t\t.attr(\"class\", classAreas);\n\n\t\t\t// -- Brush --//\n\t\t\tcontext.selectAll(`.${CLASS.brush} rect`)\n\t\t\t\t.attr(config.axis_rotated ? \"width\" : \"height\", config.axis_rotated ? $$.width2 : $$.height2);\n\t\t}\n\t},\n\n\t/**\n\t * Update the bar of the sub chart\n\t * @private\n\t * @param {Object} durationForExit\n\t */\n\tupdateBarForSubchart(durationForExit) {\n\t\tconst $$ = this;\n\n\t\t$$.contextBar = $$.context.selectAll(`.${CLASS.bars}`).selectAll(`.${CLASS.bar}`)\n\t\t\t.data($$.barData.bind($$));\n\n\t\t$$.contextBar\n\t\t\t.exit()\n\t\t\t.transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.contextBar = $$.contextBar\n\t\t\t.enter()\n\t\t\t.append(\"path\")\n\t\t\t.attr(\"class\", $$.classBar.bind($$))\n\t\t\t.style(\"stroke\", \"none\")\n\t\t\t.style(\"fill\", $$.color)\n\t\t\t.merge($$.contextBar)\n\t\t\t.style(\"opacity\", $$.initialOpacity.bind($$));\n\t},\n\n\t/**\n\t * Redraw the bar of the subchart\n\t * @private\n\t * @param {String} path in subchart bar\n\t * @param {Boolean} whether or not to transition.\n\t * @param {Number} transition duration\n\t */\n\tredrawBarForSubchart(drawBarOnSub, withTransition, duration) {\n\t\tconst contextBar = withTransition ?\n\t\t\tthis.contextBar.transition(getRandom()).duration(duration) :\n\t\t\tthis.contextBar;\n\n\t\tcontextBar.attr(\"d\", drawBarOnSub)\n\t\t\t.style(\"opacity\", \"1\");\n\t},\n\n\t/**\n\t * Update the line of the sub chart\n\t * @private\n\t * @param {Number} Fade-out transition duration\n\t */\n\tupdateLineForSubchart(durationForExit) {\n\t\tconst $$ = this;\n\n\t\t$$.contextLine = $$.context.selectAll(`.${CLASS.lines}`)\n\t\t\t.selectAll(`.${CLASS.line}`)\n\t\t\t.data($$.lineData.bind($$));\n\n\t\t$$.contextLine\n\t\t\t.exit()\n\t\t\t.transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.contextLine = $$.contextLine\n\t\t\t.enter()\n\t\t\t.append(\"path\")\n\t\t\t.attr(\"class\", $$.classLine.bind($$))\n\t\t\t.style(\"stroke\", $$.color)\n\t\t\t.merge($$.contextLine)\n\t\t\t.style(\"opacity\", $$.initialOpacity.bind($$));\n\t},\n\n\t/**\n\t * Redraw the line of the subchart\n\t * @private\n\t * @param {String} path in subchart line\n\t * @param {Boolean} whether or not to transition\n\t * @param {Number} transition duration\n\t */\n\tredrawLineForSubchart(drawLineOnSub, withTransition, duration) {\n\t\tconst contextLine = withTransition ?\n\t\t\tthis.contextLine.transition(getRandom()).duration(duration) :\n\t\t\tthis.contextLine;\n\n\t\tcontextLine.attr(\"d\", drawLineOnSub)\n\t\t\t.style(\"opacity\", \"1\");\n\t},\n\n\t/**\n\t * Update the area of the sub chart\n\t * @private\n\t * @param {Number} Fade-out transition duration\n\t */\n\tupdateAreaForSubchart(durationForExit) {\n\t\tconst $$ = this;\n\n\t\t$$.contextArea = $$.context.selectAll(`.${CLASS.areas}`)\n\t\t\t.selectAll(`.${CLASS.area}`)\n\t\t\t.data($$.lineData.bind($$));\n\n\t\t$$.contextArea\n\t\t\t.exit()\n\t\t\t.transition()\n\t\t\t.duration(durationForExit)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\t$$.contextArea = $$.contextArea\n\t\t\t.enter()\n\t\t\t.append(\"path\")\n\t\t\t.attr(\"class\", $$.classArea.bind($$))\n\t\t\t.style(\"fill\", $$.color)\n\t\t\t.style(\"opacity\", function() {\n\t\t\t\t$$.orgAreaOpacity = d3Select(this).style(\"opacity\");\n\t\t\t\treturn \"0\";\n\t\t\t})\n\t\t\t.merge($$.contextArea)\n\t\t\t.style(\"opacity\", \"0\");\n\t},\n\t/**\n\t * Redraw the area of the subchart\n\t * @private\n\t * @param {String} path in subchart line\n\t * @param {Boolean} whether or not to transition\n\t * @param {Number} transition duration\n\t */\n\tredrawAreaForSubchart(drawAreaOnSub, withTransition, duration) {\n\t\tconst contextArea = withTransition ?\n\t\t\tthis.contextArea.transition(getRandom()).duration(duration) :\n\t\t\tthis.contextArea;\n\n\t\tcontextArea.attr(\"d\", drawAreaOnSub)\n\t\t\t.style(\"fill\", this.color)\n\t\t\t.style(\"opacity\", this.orgAreaOpacity);\n\t},\n\n\t/**\n\t * Redraw subchart.\n\t * @private\n\t * @param {Boolean} withSubchart whether or not to show subchart\n\t * @param {Number} duration duration\n\t * @param {Object} shape Shape's info\n\t */\n\tredrawSubchart(withSubchart, duration, shape) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\t$$.context.style(\"visibility\", config.subchart_show ? \"visible\" : \"hidden\");\n\n\t\t// subchart\n\t\tif (config.subchart_show) {\n\t\t\t// reflect main chart to extent on subchart if zoomed\n\t\t\tif (d3Event && d3Event.type === \"zoom\") {\n\t\t\t\t$$.brush.update();\n\t\t\t}\n\n\t\t\t// update subchart elements if needed\n\t\t\tif (withSubchart) {\n\t\t\t\t// extent rect\n\t\t\t\t!brushEmpty($$) && $$.brush.update();\n\n\t\t\t\tObject.keys(shape.type).forEach(v => {\n\t\t\t\t\tconst name = capitalize(v);\n\t\t\t\t\tconst draw = $$[`generateDraw${name}`](shape.indices[v], true);\n\n\t\t\t\t\t$$[`update${name}ForSubchart`](duration);\n\t\t\t\t\t$$[`redraw${name}ForSubchart`](draw, duration, duration);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Redraw the brush.\n\t * @private\n\t */\n\tredrawForBrush() {\n\t\tconst $$ = this;\n\n\t\t$$.redraw({\n\t\t\twithTransition: false,\n\t\t\twithY: $$.config.zoom_rescale,\n\t\t\twithSubchart: false,\n\t\t\twithUpdateXDomain: true,\n\t\t\twithDimension: false\n\t\t});\n\n\t\t$$.config.subchart_onbrush.call($$.api, $$.x.orgDomain());\n\t},\n\n\t/**\n\t * Transform context\n\t * @private\n\t * @param {Boolean} indicates transition is enabled\n\t * @param {Object} The return value of the generateTransitions method of Axis.\n\t */\n\ttransformContext(withTransition, transitions) {\n\t\tconst $$ = this;\n\t\tlet subXAxis;\n\n\t\tif (transitions && transitions.axisSubX) {\n\t\t\tsubXAxis = transitions.axisSubX;\n\t\t} else {\n\t\t\tsubXAxis = $$.context.select(`.${CLASS.axisX}`);\n\t\t\tif (withTransition) { subXAxis = subXAxis.transition(); }\n\t\t}\n\n\t\t$$.context.attr(\"transform\", $$.getTranslate(\"context\"));\n\t\tsubXAxis.attr(\"transform\", $$.getTranslate(\"subx\"));\n\t},\n\n\t/**\n\t * Get extent value\n\t * @private\n\t * @returns {Array} default extent\n\t */\n\tgetExtent() {\n\t\tconst $$ = this;\n\t\tlet extent = $$.config.axis_x_extent;\n\n\t\tif (extent) {\n\t\t\tif (isFunction(extent)) {\n\t\t\t\textent = extent($$.getXDomain($$.data.targets), $$.subX);\n\t\t\t} else if ($$.isTimeSeries() && extent.every(isNaN)) {\n\t\t\t\textent = extent.map(v => $$.subX($$.parseDate(v)));\n\t\t\t}\n\t\t}\n\n\t\treturn extent;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {\n\tmouse as d3Mouse,\n\tevent as d3Event,\n\tselect as d3Select\n} from \"d3-selection\";\nimport {drag as d3Drag} from \"d3-drag\";\nimport {zoom as d3Zoom} from \"d3-zoom\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {document} from \"../internals/browser\";\nimport CLASS from \"../config/classes\";\nimport {extend, callFn, diffDomain, getMinMax, isDefined, isFunction} from \"../internals/util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Initialize zoom.\n\t * @private\n\t */\n\tinitZoom() {\n\t\tconst $$ = this;\n\n\t\t$$.zoomScale = null;\n\n\t\t$$.generateZoom();\n\t\t$$.initZoomBehaviour();\n\t},\n\n\t/**\n\t * Bind zoom event\n\t * @param {Boolean} bind Weather bind or unbound\n\t * @private\n\t */\n\tbindZoomEvent(bind = true) {\n\t\tconst $$ = this;\n\t\tconst zoomEnabled = $$.config.zoom_enabled;\n\n\t\t$$.redrawEventRect();\n\n\t\tconst eventRects = $$.main.select(`.${CLASS.eventRects}`);\n\n\t\tif (zoomEnabled && bind) {\n\t\t\t// Do not bind zoom event when subchart is shown\n\t\t\t!$$.config.subchart_show &&\n\t\t\t\t$$.bindZoomOnEventRect(eventRects, zoomEnabled.type);\n\t\t} else if (bind === false) {\n\t\t\t$$.api.unzoom();\n\n\t\t\teventRects\n\t\t\t\t.on(\".zoom\", null)\n\t\t\t\t.on(\".drag\", null);\n\t\t}\n\t},\n\n\t/**\n\t * Generate zoom\n\t * @private\n\t */\n\tgenerateZoom() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\tconst zoom = d3Zoom().duration(0)\n\t\t\t.on(\"start\", $$.onZoomStart.bind($$))\n\t\t\t.on(\"zoom\", $$.onZoom.bind($$))\n\t\t\t.on(\"end\", $$.onZoomEnd.bind($$));\n\n\t\t// get zoom extent\n\t\tzoom.orgScaleExtent = () => {\n\t\t\tconst extent = config.zoom_extent || [1, 10];\n\n\t\t\treturn [extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1])];\n\t\t};\n\n\t\tzoom.updateScaleExtent = function() {\n\t\t\tconst ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.getZoomDomain());\n\t\t\tconst extent = this.orgScaleExtent();\n\n\t\t\tthis.scaleExtent([extent[0] * ratio, extent[1] * ratio]);\n\n\t\t\treturn this;\n\t\t};\n\n\t\t/**\n\t\t * Update scale according zoom transform value\n\t\t * @param {Object} transform\n\t\t * @private\n\t\t */\n\t\tzoom.updateTransformScale = transform => {\n\t\t\t// in case of resize, update range of orgXScale\n\t\t\t$$.orgXScale && $$.orgXScale.range($$.x.range());\n\n\t\t\t// rescale from the original scale\n\t\t\tconst newScale = transform[\n\t\t\t\tconfig.axis_rotated ? \"rescaleY\" : \"rescaleX\"\n\t\t\t]($$.orgXScale || $$.x);\n\n\t\t\tconst domain = $$.trimXDomain(newScale.domain());\n\t\t\tconst rescale = config.zoom_rescale;\n\n\t\t\tnewScale.domain(domain, $$.orgXDomain);\n\n\t\t\t$$.zoomScale = $$.getCustomizedScale(newScale);\n\t\t\t$$.xAxis.scale($$.zoomScale);\n\n\t\t\tif (rescale) {\n\t\t\t\t// copy current initial x scale in case of rescale option is used\n\t\t\t\t!$$.orgXScale && ($$.orgXScale = $$.x.copy());\n\t\t\t\t$$.x.domain(domain);\n\t\t\t}\n\t\t};\n\n\t\t$$.zoom = zoom;\n\t},\n\n\t/**\n\t * 'start' event listener\n\t * @private\n\t */\n\tonZoomStart() {\n\t\tconst $$ = this;\n\t\tconst event = d3Event.sourceEvent;\n\n\t\tif (!event) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.zoom.startEvent = event;\n\t\tcallFn($$.config.zoom_onzoomstart, $$.api, event);\n\t},\n\n\t/**\n\t * 'zoom' event listener\n\t * @private\n\t */\n\tonZoom() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst event = d3Event;\n\t\tconst sourceEvent = event.sourceEvent;\n\n\t\tif (\n\t\t\t!config.zoom_enabled ||\n\t\t\t!event.sourceEvent ||\n\t\t\t$$.filterTargetsToShow($$.data.targets).length === 0 ||\n\t\t\t(!$$.zoomScale && sourceEvent.type.indexOf(\"touch\") > -1 && sourceEvent.touches.length === 1)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isMousemove = sourceEvent.type === \"mousemove\";\n\t\tconst isZoomOut = sourceEvent.wheelDelta < 0;\n\t\tconst transform = event.transform;\n\n\t\tif (!isMousemove && isZoomOut && $$.x.domain().every((v, i) => v !== $$.orgXDomain[i])) {\n\t\t\t$$.x.domain($$.orgXDomain);\n\t\t}\n\n\t\t$$.zoom.updateTransformScale(transform);\n\n\t\tif ($$.isCategorized() && $$.x.orgDomain()[0] === $$.orgXDomain[0]) {\n\t\t\t$$.x.domain([$$.orgXDomain[0] - 1e-10, $$.x.orgDomain()[1]]);\n\t\t}\n\n\t\t$$.redraw({\n\t\t\twithTransition: false,\n\t\t\twithY: config.zoom_rescale,\n\t\t\twithSubchart: false,\n\t\t\twithEventRect: false,\n\t\t\twithDimension: false\n\t\t});\n\n\t\t$$.cancelClick = isMousemove;\n\t\tcallFn(config.zoom_onzoom, $$.api, $$.zoomScale.domain());\n\t},\n\n\t/**\n\t * 'end' event listener\n\t * @private\n\t */\n\tonZoomEnd() {\n\t\tconst $$ = this;\n\t\tlet startEvent = $$.zoom.startEvent;\n\t\tlet event = d3Event && d3Event.sourceEvent;\n\n\t\tif ((startEvent && startEvent.type.indexOf(\"touch\") > -1)) {\n\t\t\tstartEvent = startEvent.changedTouches[0];\n\t\t\tevent = event.changedTouches[0];\n\t\t}\n\n\t\t// if click, do nothing. otherwise, click interaction will be canceled.\n\t\tif (!startEvent ||\n\t\t\t(event && startEvent.clientX === event.clientX && startEvent.clientY === event.clientY)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.redrawEventRect();\n\t\t$$.updateZoom();\n\n\t\tcallFn($$.config.zoom_onzoomend, $$.api, $$[$$.zoomScale ? \"zoomScale\" : \"subX\"].domain());\n\t},\n\n\t/**\n\t * Get zoom domain\n\t * @returns {Array} zoom domain\n \t * @private\n\t */\n\tgetZoomDomain() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tlet [min, max] = $$.orgXDomain;\n\n\t\tif (isDefined(config.zoom_x_min)) {\n\t\t\tmin = getMinMax(\"min\", [min, config.zoom_x_min]);\n\t\t}\n\n\t\tif (isDefined(config.zoom_x_max)) {\n\t\t\tmax = getMinMax(\"max\", [max, config.zoom_x_max]);\n\t\t}\n\n\t\treturn [min, max];\n\t},\n\n\t/**\n\t * Update zoom\n\t * @param {Boolean} force Force unzoom\n\t * @private\n\t */\n\tupdateZoom(force) {\n\t\tconst $$ = this;\n\n\t\tif ($$.zoomScale) {\n\t\t\tconst zoomDomain = $$.zoomScale.domain();\n\t\t\tconst xDomain = $$.subX.domain();\n\t\t\tconst delta = 0.015; // arbitrary value\n\n\t\t\tconst isfullyShown = (zoomDomain[0] <= xDomain[0] || (zoomDomain[0] - delta) <= xDomain[0]) &&\n\t\t\t\t(xDomain[1] <= zoomDomain[1] || xDomain[1] <= (zoomDomain[1] - delta));\n\n\t\t\t// check if the zoomed chart is fully shown, then reset scale when zoom is out as initial\n\t\t\tif (force || isfullyShown) {\n\t\t\t\t$$.xAxis.scale($$.subX);\n\t\t\t\t$$.x.domain($$.subX.orgDomain());\n\t\t\t\t$$.zoomScale = null;\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Attach zoom event on <rect>\n\t * @private\n\t */\n\tbindZoomOnEventRect(eventRects, type) {\n\t\tconst $$ = this;\n\t\tconst behaviour = type === \"drag\" ? $$.zoomBehaviour : $$.zoom;\n\n\t\teventRects\n\t\t\t.call(behaviour)\n\t\t\t.on(\"dblclick.zoom\", null);\n\t},\n\n\t/**\n\t * Initialize the drag behaviour used for zooming.\n\t * @private\n\t */\n\tinitZoomBehaviour() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst isRotated = config.axis_rotated;\n\t\tlet start = 0;\n\t\tlet end = 0;\n\t\tlet zoomRect = null;\n\n\t\tconst prop = {\n\t\t\taxis: isRotated ? \"y\" : \"x\",\n\t\t\tattr: isRotated ? \"height\" : \"width\",\n\t\t\tindex: isRotated ? 1 : 0\n\t\t};\n\n\t\t$$.zoomBehaviour = d3Drag()\n\t\t\t.clickDistance(4)\n\t\t\t.on(\"start\", function() {\n\t\t\t\t$$.setDragStatus(true);\n\n\t\t\t\tif (!zoomRect) {\n\t\t\t\t\tzoomRect = $$.main.append(\"rect\")\n\t\t\t\t\t\t.attr(\"clip-path\", $$.clipPath)\n\t\t\t\t\t\t.attr(\"class\", CLASS.zoomBrush)\n\t\t\t\t\t\t.attr(\"width\", isRotated ? $$.width : 0)\n\t\t\t\t\t\t.attr(\"height\", isRotated ? 0 : $$.height);\n\t\t\t\t}\n\n\t\t\t\tstart = d3Mouse(this)[prop.index];\n\t\t\t\tend = start;\n\n\t\t\t\tzoomRect\n\t\t\t\t\t.attr(prop.axis, start)\n\t\t\t\t\t.attr(prop.attr, 0);\n\n\t\t\t\t$$.onZoomStart();\n\t\t\t})\n\t\t\t.on(\"drag\", function() {\n\t\t\t\tend = d3Mouse(this)[prop.index];\n\n\t\t\t\tzoomRect\n\t\t\t\t\t.attr(prop.axis, Math.min(start, end))\n\t\t\t\t\t.attr(prop.attr, Math.abs(end - start));\n\t\t\t})\n\t\t\t.on(\"end\", function(d) {\n\t\t\t\tconst scale = $$.zoomScale || $$.x;\n\n\t\t\t\t$$.setDragStatus(false);\n\n\t\t\t\tzoomRect\n\t\t\t\t\t.attr(prop.axis, 0)\n\t\t\t\t\t.attr(prop.attr, 0);\n\n\t\t\t\tif (start > end) {\n\t\t\t\t\t[start, end] = [end, start];\n\t\t\t\t}\n\n\t\t\t\tif (start < 0) {\n\t\t\t\t\tend += Math.abs(start);\n\t\t\t\t\tstart = 0;\n\t\t\t\t}\n\n\t\t\t\tif (start !== end) {\n\t\t\t\t\t$$.api.zoom([start, end].map(v => scale.invert(v)));\n\t\t\t\t\t$$.onZoomEnd();\n\t\t\t\t} else {\n\t\t\t\t\tif ($$.isMultipleX()) {\n\t\t\t\t\t\t$$.clickHandlerForMultipleXS.bind(this)($$);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst event = d3Event.sourceEvent || d3Event;\n\t\t\t\t\t\tconst [x, y] = \"clientX\" in event ? [event.clientX, event.clientY] : [event.x, event.y];\n\t\t\t\t\t\tconst target = document.elementFromPoint(x, y);\n\n\t\t\t\t\t\t$$.clickHandlerForSingleX.bind(target)(d3Select(target).datum(), $$);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\tsetZoomResetButton() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst resetButton = config.zoom_resetButton;\n\n\t\tif (resetButton && config.zoom_enabled.type === \"drag\") {\n\t\t\tif (!$$.zoom.resetBtn) {\n\t\t\t\t$$.zoom.resetBtn = $$.selectChart.append(\"div\")\n\t\t\t\t\t.classed(CLASS.button, true)\n\t\t\t\t\t.append(\"span\")\n\t\t\t\t\t.on(\"click\", function() {\n\t\t\t\t\t\tisFunction(resetButton.onclick) && resetButton.onclick(this);\n\t\t\t\t\t\t$$.api.unzoom.call($$);\n\t\t\t\t\t})\n\t\t\t\t\t.classed(CLASS.buttonZoomReset, true)\n\t\t\t\t\t.text(resetButton.text || \"Reset Zoom\");\n\t\t\t} else {\n\t\t\t\t$$.zoom.resetBtn.style(\"display\", null);\n\t\t\t}\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\";\nimport {scaleOrdinal as d3ScaleOrdinal} from \"d3-scale\";\nimport ChartInternal from \"./ChartInternal\";\nimport {document, window} from \"./browser\";\nimport CLASS from \"../config/classes\";\nimport {notEmpty, extend, isFunction, isObject, isString} from \"./util\";\n\n/**\n * Set pattern's background color\n * (it adds a <rect> element to simulate bg-color)\n * @param {SVGPatternElement} pattern SVG pattern element\n * @param {String} color Color string\n * @param {String} id ID to be set\n * @return {{id: string, node: SVGPatternElement}}\n * @private\n */\nconst colorizePattern = (pattern, color, id) => {\n\tconst node = d3Select(pattern.cloneNode(true));\n\n\tnode\n\t\t.attr(\"id\", id)\n\t\t.insert(\"rect\", \":first-child\")\n\t\t.attr(\"width\", node.attr(\"width\"))\n\t\t.attr(\"height\", node.attr(\"height\"))\n\t\t.style(\"fill\", color);\n\n\treturn {\n\t\tid,\n\t\tnode: node.node()\n\t};\n};\n\n// Replacement of d3.schemeCategory10.\n// Contained differently depend on d3 version: v4(d3-scale), v5(d3-scale-chromatic)\nconst schemeCategory10 = [\"#1f77b4\", \"#ff7f0e\", \"#2ca02c\", \"#d62728\", \"#9467bd\", \"#8c564b\", \"#e377c2\", \"#7f7f7f\", \"#bcbd22\", \"#17becf\"];\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Get color pattern from CSS file\n\t * CSS should be defined as: background-image: url(\"#00c73c;#fa7171; ...\");\n\t * @return {Array}\n\t * @private\n\t */\n\tgetColorFromCss() {\n\t\tconst cacheKey = \"__colorPattern__\";\n\t\tconst body = document.body;\n\t\tlet pattern = body[cacheKey];\n\n\t\tif (!pattern) {\n\t\t\tconst delimiter = \";\";\n\t\t\tconst span = document.createElement(\"span\");\n\n\t\t\tspan.className = CLASS.colorPattern;\n\t\t\tspan.style.display = \"none\";\n\t\t\tbody.appendChild(span);\n\n\t\t\tconst content = window.getComputedStyle(span).backgroundImage;\n\n\t\t\tspan.parentNode.removeChild(span);\n\n\t\t\tif (content.indexOf(delimiter) > -1) {\n\t\t\t\tpattern = content\n\t\t\t\t\t.replace(/url[^#]*|[\"'()]|(\\s|%20)/g, \"\")\n\t\t\t\t\t.split(delimiter)\n\t\t\t\t\t.map(v => v.trim().replace(/[\\\"'\\s]/g, \"\"))\n\t\t\t\t\t.filter(Boolean);\n\n\t\t\t\tbody[cacheKey] = pattern;\n\t\t\t}\n\t\t}\n\n\t\treturn pattern;\n\t},\n\n\tgenerateColor() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst colors = config.data_colors;\n\t\tconst callback = config.data_color;\n\t\tconst ids = [];\n\n\t\tlet pattern = notEmpty(config.color_pattern) ? config.color_pattern :\n\t\t\td3ScaleOrdinal($$.getColorFromCss() || schemeCategory10).range();\n\n\t\tconst originalColorPattern = pattern;\n\n\t\tif (isFunction(config.color_tiles)) {\n\t\t\tconst tiles = config.color_tiles();\n\n\t\t\t// Add background color to patterns\n\t\t\tconst colorizedPatterns = pattern.map((p, index) => {\n\t\t\t\tconst color = p.replace(/[#\\(\\)\\s,]/g, \"\");\n\t\t\t\tconst id = `${$$.datetimeId}-pattern-${color}-${index}`;\n\n\t\t\t\treturn colorizePattern(tiles[index % tiles.length], p, id);\n\t\t\t});\n\n\t\t\tpattern = colorizedPatterns.map(p => `url(#${p.id})`);\n\t\t\t$$.patterns = colorizedPatterns;\n\t\t}\n\n\t\treturn function(d) {\n\t\t\tconst id = d.id || (d.data && d.data.id) || d;\n\t\t\tconst isLine = $$.isTypeOf(id, [\"line\", \"spline\", \"step\"]) || !$$.config.data_types[id];\n\t\t\tlet color;\n\n\t\t\t// if callback function is provided\n\t\t\tif (isFunction(colors[id])) {\n\t\t\t\tcolor = colors[id](d);\n\n\t\t\t// if specified, choose that color\n\t\t\t} else if (colors[id]) {\n\t\t\t\tcolor = colors[id];\n\n\t\t\t// if not specified, choose from pattern\n\t\t\t} else {\n\t\t\t\tif (ids.indexOf(id) < 0) {\n\t\t\t\t\tids.push(id);\n\t\t\t\t}\n\n\t\t\t\tcolor = isLine ? originalColorPattern[ids.indexOf(id) % originalColorPattern.length] :\n\t\t\t\t\tpattern[ids.indexOf(id) % pattern.length];\n\n\t\t\t\tcolors[id] = color;\n\t\t\t}\n\n\t\t\treturn isFunction(callback) ?\n\t\t\t\tcallback(color, d) : color;\n\t\t};\n\t},\n\n\tgenerateLevelColor() {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst colors = config.color_pattern;\n\t\tconst threshold = config.color_threshold;\n\t\tconst asValue = threshold.unit === \"value\";\n\t\tconst max = threshold.max || 100;\n\t\tconst values = threshold.values &&\n\t\t\tthreshold.values.length ? threshold.values : [];\n\n\t\treturn notEmpty(threshold) ? function(value) {\n\t\t\tconst v = asValue ? value : (value * 100 / max);\n\t\t\tlet color = colors[colors.length - 1];\n\n\t\t\tfor (let i = 0, l = values.length; i < l; i++) {\n\t\t\t\tif (v <= values[i]) {\n\t\t\t\t\tcolor = colors[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn color;\n\t\t} : null;\n\t},\n\n\t/**\n\t * Set the data over color.\n\t * When is out, will restore in its previous color value\n\t * @param {Boolean} isOver true: set overed color, false: restore\n\t * @param {Number|Object} d target index or data object for Arc type\n\t * @private\n\t */\n\tsetOverColor(isOver, d) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\t\tconst onover = config.color_onover;\n\t\tlet color = isOver ? onover : $$.color;\n\n\t\tif (isObject(color)) {\n\t\t\tcolor = ({id}) => (id in onover ? onover[id] : $$.color(id));\n\t\t} else if (isString(color)) {\n\t\t\tcolor = () => onover;\n\t\t}\n\n\t\t// when is Arc type\n\t\tif (isObject(d)) {\n\t\t\t$$.main.selectAll(`.${CLASS.arc}${$$.getTargetSelectorSuffix(d.id)}`)\n\t\t\t\t.style(\"fill\", color(d));\n\t\t} else {\n\t\t\t$$.main.selectAll(`.${CLASS.shape}-${d}`)\n\t\t\t\t.style(\"fill\", color);\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {isValue, isFunction, isObjectType, extend} from \"./util\";\n\nconst getFormat = ($$, typeValue, v) => {\n\tconst config = $$.config;\n\tconst type = `axis_${typeValue}_tick_format`;\n\tconst format = config[type] ?\n\t\tconfig[type] : $$.defaultValueFormat;\n\n\treturn format(v);\n};\n\nextend(ChartInternal.prototype, {\n\tgetYFormat(forArc) {\n\t\tconst $$ = this;\n\t\tlet formatForY = $$.yFormat;\n\t\tlet formatForY2 = $$.y2Format;\n\n\t\tif (forArc && !$$.hasType(\"gauge\")) {\n\t\t\tformatForY = $$.defaultArcValueFormat;\n\t\t\tformatForY2 = $$.defaultArcValueFormat;\n\t\t}\n\n\t\treturn function(v, ratio, id) {\n\t\t\tconst format = $$.axis.getId(id) === \"y2\" ?\n\t\t\t\tformatForY2 : formatForY;\n\n\t\t\treturn format.call($$, v, ratio);\n\t\t};\n\t},\n\n\tyFormat(v) {\n\t\treturn getFormat(this, \"y\", v);\n\t},\n\n\ty2Format(v) {\n\t\treturn getFormat(this, \"y2\", v);\n\t},\n\n\tdefaultValueFormat(v) {\n\t\treturn isValue(v) ? +v : \"\";\n\t},\n\n\tdefaultArcValueFormat(v, ratio) {\n\t\treturn `${(ratio * 100).toFixed(1)}%`;\n\t},\n\n\tdataLabelFormat(targetId) {\n\t\tconst $$ = this;\n\t\tconst dataLabels = $$.config.data_labels;\n\t\tconst defaultFormat = v => (isValue(v) ? +v : \"\");\n\t\tlet format = defaultFormat;\n\n\t\t// find format according to axis id\n\t\tif (isFunction(dataLabels.format)) {\n\t\t\tformat = dataLabels.format;\n\t\t} else if (isObjectType(dataLabels.format)) {\n\t\t\tif (dataLabels.format[targetId]) {\n\t\t\t\tformat = dataLabels.format[targetId] === true ?\n\t\t\t\t\tdefaultFormat : dataLabels.format[targetId];\n\t\t\t} else {\n\t\t\t\tformat = () => \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn format;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport {toArray, extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Add cache\n\t * @param {String} key\n\t * @param {*} value\n\t * @param {Boolean} isDataType\n\t * @private\n\t */\n\taddCache(key, value, isDataType = false) {\n\t\tthis.cache[key] = isDataType ? this.cloneTarget(value) : value;\n\t},\n\n\t/**\n\t * Remove cache\n\t * @param {String|Array} key\n\t * @private\n\t */\n\tremoveCache(key) {\n\t\ttoArray(key).forEach(v => delete this.cache[v]);\n\t},\n\n\t/**\n\t * Get cahce\n\t * @param {String|Array} key\n\t * @param {Boolean} isDataType\n\t * @return {*}\n\t * @private\n\t */\n\tgetCache(key, isDataType = false) {\n\t\tif (isDataType) {\n\t\t\tconst targets = [];\n\n\t\t\tfor (let i = 0, id; (id = key[i]); i++) {\n\t\t\t\tif (id in this.cache) {\n\t\t\t\t\ttargets.push(this.cloneTarget(this.cache[id]));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn targets;\n\t\t} else {\n\t\t\treturn this.cache[key] || null;\n\t\t}\n\t},\n\n\t/**\n\t * reset cached data\n\t * @param {Boolean} all true: reset all data, false: reset only '$' prefixed key data\n\t * @private\n \t */\n\tresetCache(all) {\n\t\tconst $$ = this;\n\n\t\tfor (const x in $$.cache) {\n\t\t\t// reset the prefixed '$' key(which is internal use data) only.\n\t\t\tif (all || /^\\$/.test(x)) {\n\t\t\t\t$$.cache[x] = null;\n\t\t\t}\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport ChartInternal from \"./ChartInternal\";\nimport CLASS from \"../config/classes\";\nimport {extend} from \"./util\";\n\nextend(ChartInternal.prototype, {\n\tgenerateClass(prefix, targetId) {\n\t\treturn ` ${prefix} ${prefix + this.getTargetSelectorSuffix(targetId)}`;\n\t},\n\n\tclassText(d) {\n\t\treturn this.generateClass(CLASS.text, d.index);\n\t},\n\n\tclassTexts(d) {\n\t\treturn this.generateClass(CLASS.texts, d.id);\n\t},\n\n\tclassShape(d) {\n\t\treturn this.generateClass(CLASS.shape, d.index);\n\t},\n\n\tclassShapes(d) {\n\t\treturn this.generateClass(CLASS.shapes, d.id);\n\t},\n\n\tgenerateExtraLineClass() {\n\t\tconst $$ = this;\n\t\tconst classes = $$.config.line_classes || [];\n\t\tconst ids = [];\n\n\t\treturn function(d) {\n\t\t\tconst id = d.id || (d.data && d.data.id) || d;\n\n\t\t\tif (ids.indexOf(id) < 0) {\n\t\t\t\tids.push(id);\n\t\t\t}\n\n\t\t\treturn classes[ids.indexOf(id) % classes.length];\n\t\t};\n\t},\n\n\tclassLine(d) {\n\t\treturn this.classShape(d) + this.generateClass(CLASS.line, d.id);\n\t},\n\n\tclassLines(d) {\n\t\treturn this.classShapes(d) + this.generateClass(CLASS.lines, d.id);\n\t},\n\n\tclassCircle(d) {\n\t\treturn this.classShape(d) + this.generateClass(CLASS.circle, d.index);\n\t},\n\n\tclassCircles(d) {\n\t\treturn this.classShapes(d) + this.generateClass(CLASS.circles, d.id);\n\t},\n\n\tclassBar(d) {\n\t\treturn this.classShape(d) + this.generateClass(CLASS.bar, d.index);\n\t},\n\n\tclassBars(d) {\n\t\treturn this.classShapes(d) + this.generateClass(CLASS.bars, d.id);\n\t},\n\n\tclassArc(d) {\n\t\treturn this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);\n\t},\n\n\tclassArcs(d) {\n\t\treturn this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);\n\t},\n\n\tclassArea(d) {\n\t\treturn this.classShape(d) + this.generateClass(CLASS.area, d.id);\n\t},\n\n\tclassAreas(d) {\n\t\treturn this.classShapes(d) + this.generateClass(CLASS.areas, d.id);\n\t},\n\n\tclassRegion(d, i) {\n\t\treturn `${this.generateClass(CLASS.region, i)} ${\"class\" in d ? d.class : \"\"}`;\n\t},\n\n\tclassEvent(d) {\n\t\treturn this.generateClass(CLASS.eventRect, d.index);\n\t},\n\n\tclassTarget(id) {\n\t\tconst additionalClassSuffix = this.config.data_classes[id];\n\t\tlet additionalClass = \"\";\n\n\t\tif (additionalClassSuffix) {\n\t\t\tadditionalClass = ` ${CLASS.target}-${additionalClassSuffix}`;\n\t\t}\n\n\t\treturn this.generateClass(CLASS.target, id) + additionalClass;\n\t},\n\n\tclassFocus(d) {\n\t\treturn this.classFocused(d) + this.classDefocused(d);\n\t},\n\n\tclassFocused(d) {\n\t\treturn ` ${this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : \"\"}`;\n\t},\n\n\tclassDefocused(d) {\n\t\treturn ` ${this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : \"\"}`;\n\t},\n\n\tclassChartText(d) {\n\t\treturn CLASS.chartText + this.classTarget(d.id);\n\t},\n\n\tclassChartLine(d) {\n\t\treturn CLASS.chartLine + this.classTarget(d.id);\n\t},\n\n\tclassChartBar(d) {\n\t\treturn CLASS.chartBar + this.classTarget(d.id);\n\t},\n\n\tclassChartArc(d) {\n\t\treturn CLASS.chartArc + this.classTarget(d.data.id);\n\t},\n\n\tclassChartRadar(d) {\n\t\treturn CLASS.chartRadar + this.classTarget(d.id);\n\t},\n\n\tgetTargetSelectorSuffix(targetId) {\n\t\treturn targetId || targetId === 0 ?\n\t\t\t`-${targetId}`.replace(/[\\s?!@#$%^&*()_=+,.<>'\":;\\[\\]\\/|~`{}\\\\]/g, \"-\") : \"\";\n\t},\n\n\tselectorTarget(id, prefix) {\n\t\treturn `${prefix || \"\"}.${CLASS.target + this.getTargetSelectorSuffix(id)}`;\n\t},\n\n\tselectorTargets(idsValue, prefix) {\n\t\tconst $$ = this;\n\t\tconst ids = idsValue || [];\n\n\t\treturn ids.length ?\n\t\t\tids.map(id => $$.selectorTarget(id, prefix)) : null;\n\t},\n\n\tselectorLegend(id) {\n\t\treturn `.${CLASS.legendItem + this.getTargetSelectorSuffix(id)}`;\n\t},\n\n\tselectorLegends(ids) {\n\t\tconst $$ = this;\n\n\t\treturn ids && ids.length ?\n\t\t\tids.map(id => $$.selectorLegend(id)) : null;\n\t},\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\";\nimport Chart from \"../internals/Chart\";\nimport CLASS from \"../config/classes\";\nimport {extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * This API highlights specified targets and fade out the others.<br><br>\n\t * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be highlighted.\n\t * @method focus\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} targetIdsValue Target ids to be highlighted.\n\t * @example\n\t * // data1 will be highlighted and the others will be faded out\n\t * chart.focus(\"data1\");\n\t *\n\t * // data1 and data2 will be highlighted and the others will be faded out\n\t * chart.focus([\"data1\", \"data2\"]);\n\t *\n\t * // all targets will be highlighted\n\t * chart.focus();\n\t */\n\tfocus(targetIdsValue) {\n\t\tconst $$ = this.internal;\n\t\tconst targetIds = $$.mapToTargetIds(targetIdsValue);\n\t\tconst candidates = $$.svg.selectAll(\n\t\t\t$$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))\n\t\t);\n\n\t\tthis.revert();\n\t\tthis.defocus();\n\n\t\tcandidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);\n\n\t\tif ($$.hasArcType()) {\n\t\t\t$$.expandArc(targetIds);\n\n\t\t\t$$.hasType(\"gauge\") &&\n\t\t\t\t$$.markOverlapped(targetIdsValue, $$, `.${CLASS.gaugeValue}`);\n\t\t}\n\n\t\t$$.toggleFocusLegend(targetIds, true);\n\n\t\t$$.focusedTargetIds = targetIds;\n\t\t$$.defocusedTargetIds = $$.defocusedTargetIds.filter(id => targetIds.indexOf(id) < 0);\n\t},\n\n\t/**\n\t * This API fades out specified targets and reverts the others.<br><br>\n\t * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be faded out.\n\t * @method defocus\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} Target ids to be faded out.\n\t * @example\n\t * // data1 will be faded out and the others will be reverted.\n\t * chart.defocus(\"data1\");\n\t *\n\t * // data1 and data2 will be faded out and the others will be reverted.\n\t * chart.defocus([\"data1\", \"data2\"]);\n\t *\n\t * // all targets will be faded out.\n\t * chart.defocus();\n\t */\n\tdefocus(targetIdsValue) {\n\t\tconst $$ = this.internal;\n\t\tconst targetIds = $$.mapToTargetIds(targetIdsValue);\n\t\tconst candidates = $$.svg.selectAll(\n\t\t\t$$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))\n\t\t);\n\n\t\tcandidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);\n\n\t\tif ($$.hasArcType()) {\n\t\t\t$$.unexpandArc(targetIds);\n\n\t\t\t$$.hasType(\"gauge\") &&\n\t\t\t\t$$.undoMarkOverlapped($$, `.${CLASS.gaugeValue}`);\n\t\t}\n\n\t\t$$.toggleFocusLegend(targetIds, false);\n\n\t\t$$.focusedTargetIds = $$.focusedTargetIds.filter(id => targetIds.indexOf(id) < 0);\n\t\t$$.defocusedTargetIds = targetIds;\n\t},\n\n\t/**\n\t * This API reverts specified targets.<br><br>\n\t * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be reverted.\n\t * @method revert\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} Target ids to be reverted\n\t * @example\n\t * // data1 will be reverted.\n\t * chart.revert(\"data1\");\n\t *\n\t * // data1 and data2 will be reverted.\n\t * chart.revert([\"data1\", \"data2\"]);\n\t *\n\t * // all targets will be reverted.\n\t * chart.revert();\n\t */\n\trevert(targetIdsValue) {\n\t\tconst $$ = this.internal;\n\t\tconst targetIds = $$.mapToTargetIds(targetIdsValue);\n\t\tconst candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets\n\n\t\tcandidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);\n\t\t$$.hasArcType() && $$.unexpandArc(targetIds);\n\n\t\tif ($$.config.legend_show) {\n\t\t\t$$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));\n\t\t\t$$.legend.selectAll($$.selectorLegends(targetIds))\n\t\t\t\t.filter(function() {\n\t\t\t\t\treturn d3Select(this).classed(CLASS.legendItemFocused);\n\t\t\t\t})\n\t\t\t\t.classed(CLASS.legendItemFocused, false);\n\t\t}\n\n\t\t$$.focusedTargetIds = [];\n\t\t$$.defocusedTargetIds = [];\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Show/Hide data series\n\t * @private\n\t */\n\t_showHide(show, targetIdsValue, options) {\n\t\tconst $$ = this.internal;\n\t\tconst targetIds = $$.mapToTargetIds(targetIdsValue);\n\n\t\t$$[`${show ? \"remove\" : \"add\"}HiddenTargetIds`](targetIds);\n\t\tconst targets = $$.svg.selectAll($$.selectorTargets(targetIds));\n\t\tconst opacity = show ? \"1\" : \"0\";\n\n\t\ttargets.transition()\n\t\t\t.style(\"opacity\", opacity, \"important\")\n\t\t\t.call($$.endall, () => {\n\t\t\t\ttargets.style(\"opacity\", null).style(\"opacity\", opacity);\n\t\t\t});\n\n\t\toptions.withLegend && $$[`${show ? \"show\" : \"hide\"}Legend`](targetIds);\n\n\t\t$$.redraw({\n\t\t\twithUpdateOrgXDomain: true,\n\t\t\twithUpdateXDomain: true,\n\t\t\twithLegend: true\n\t\t});\n\t},\n\n\t/**\n\t * Show data series on chart\n\t * @method show\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} [targetIdsValue=all] The target id value.\n\t * @param {Object} [options] The object can consist with following members:<br>\n\t *\n\t * | Key | Type | default | Description |\n\t * | --- | --- | --- | --- |\n\t * | withLegend | Boolean | false | whether or not display legend |\n\t *\n\t * @example\n\t * // show 'data1'\n\t * chart.show(\"data1\");\n\t *\n\t * // show 'data1' and 'data3'\n\t * chart.show([\"data1\", \"data3\"]);\n\t */\n\tshow(targetIdsValue, options = {}) {\n\t\tthis._showHide(true, targetIdsValue, options);\n\t},\n\n\t/**\n\t * Hide data series from chart\n\t * @method hide\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} [targetIdsValue=all] The target id value.\n\t * @param {Object} [options] The object can consist with following members:<br>\n\t *\n\t * | Key | Type | default | Description |\n\t * | --- | --- | --- | --- |\n\t * | withLegend | Boolean | false | whether or not display legend |\n\t *\n\t * @example\n\t * // hide 'data1'\n\t * chart.hide(\"data1\");\n\t *\n\t * // hide 'data1' and 'data3'\n\t * chart.hide([\"data1\", \"data3\"]);\n\t */\n\thide(targetIdsValue, options = {}) {\n\t\tthis._showHide(false, targetIdsValue, options);\n\t},\n\n\t/**\n\t * Toggle data series on chart. When target data is hidden, it will show. If is shown, it will hide in vice versa.\n\t * @method toggle\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} [targetIdsValue=all] The target id value.\n\t * @param {Object} [options] The object can consist with following members:<br>\n\t *\n\t * | Key | Type | default | Description |\n\t * | --- | --- | --- | --- |\n\t * | withLegend | Boolean | false | whether or not display legend |\n\t *\n\t * @example\n\t * // toggle 'data1'\n\t * chart.toggle(\"data1\");\n\t *\n\t * // toggle 'data1' and 'data3'\n\t * chart.toggle([\"data1\", \"data3\"]);\n\t */\n\ttoggle(targetIds, options = {}) {\n\t\tconst $$ = this.internal;\n\t\tconst targets = {show: [], hide: []};\n\n\t\t// sort show & hide target ids\n\t\t$$.mapToTargetIds(targetIds)\n\t\t\t.forEach(id => targets[$$.isTargetToShow(id) ? \"hide\" : \"show\"].push(id));\n\n\t\t// perform show & hide task separately\n\t\t// https://github.com/naver/billboard.js/issues/454\n\t\ttargets.show.length && this.show(targets.show, options);\n\t\ttargets.hide.length && setTimeout(() => this.hide(targets.hide, options), 0);\n\t}\n});\n\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {zoomIdentity as d3ZoomIdentity, zoomTransform as d3ZoomTransform} from \"d3-zoom\";\nimport Chart from \"../internals/Chart\";\nimport CLASS from \"../config/classes\";\nimport {callFn, extend, getMinMax, isDefined, isObject, isString} from \"../internals/util\";\n\n/**\n * Check if the given domain is within zoom range\n * @param {Array} domain\n * @return {Boolean}\n * @private\n */\nconst withinRange = (domain, range) => {\n\tconst [min, max] = range;\n\n\treturn domain.every((v, i) => (\n\t\ti === 0 ? (v >= min) : (v <= max)\n\t));\n};\n\n/**\n * Zoom by giving x domain.\n * - **NOTE:**\n * - For `wheel` type zoom, the minimum zoom range will be set as the given domain. To get the initial state, [.unzoom()](#unzoom) should be called.\n * - To be used [zoom.enabled](Options.html#.zoom) option should be set as `truthy`.\n * @method zoom\n * @instance\n * @memberof Chart\n * @param {Array} domainValue If domain is given, the chart will be zoomed to the given domain. If no argument is given, the current zoomed domain will be returned.\n * @return {Array} domain value in array\n * @example\n * // Zoom to specified domain\n * chart.zoom([10, 20]);\n *\n * // Get the current zoomed domain\n * chart.zoom();\n */\nconst zoom = function(domainValue) {\n\tconst $$ = this.internal;\n\tlet domain = domainValue;\n\tlet resultDomain;\n\n\tif ($$.config.zoom_enabled && domain && withinRange(domain, $$.getZoomDomain())) {\n\t\tconst isTimeSeries = $$.isTimeSeries();\n\n\t\tif (isTimeSeries) {\n\t\t\tdomain = domain.map(x => $$.parseDate(x));\n\t\t}\n\n\t\tif ($$.config.subchart_show) {\n\t\t\tconst xScale = $$.zoomScale || $$.x;\n\n\t\t\t$$.brush.getSelection().call($$.brush.move, [xScale(domain[0]), xScale(domain[1])]);\n\t\t\tresultDomain = domain;\n\t\t} else {\n\t\t\t$$.x.domain(domain);\n\t\t\t$$.zoomScale = $$.x;\n\t\t\t$$.xAxis.scale($$.zoomScale);\n\n\t\t\tresultDomain = $$.zoomScale.orgDomain();\n\t\t}\n\n\t\t$$.redraw({\n\t\t\twithTransition: true,\n\t\t\twithY: $$.config.zoom_rescale,\n\t\t\twithDimension: false\n\t\t});\n\n\t\t$$.setZoomResetButton();\n\t\tcallFn($$.config.zoom_onzoom, $$.api, resultDomain);\n\t} else {\n\t\tresultDomain = $$.zoomScale ?\n\t\t\t$$.zoomScale.domain() : $$.x.orgDomain();\n\t}\n\n\treturn resultDomain;\n};\n\nextend(zoom, {\n\t/**\n\t * Enable and disable zooming.\n\t * @method zoom․enable\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Boolean} enabled Possible string values are \"wheel\" or \"drag\". If enabled is true, \"wheel\" will be used. If false is given, zooming will be disabled.<br>When set to false, the current zooming status will be reset.\n\t * @example\n\t * // Enable zooming using the mouse wheel\n\t * chart.zoom.enable(true);\n\t * // Or\n\t * chart.zoom.enable(\"wheel\");\n\t *\n\t * // Enable zooming by dragging\n\t * chart.zoom.enable(\"drag\");\n\t *\n\t * // Disable zooming\n\t * chart.zoom.enable(false);\n\t */\n\tenable: function(enabled = \"wheel\") {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\t\tlet enableType = enabled;\n\n\t\tif (enabled) {\n\t\t\tenableType = isString(enabled) && /^(drag|wheel)$/.test(enabled) ?\n\t\t\t\t{type: enabled} : enabled;\n\t\t}\n\n\t\tconfig.zoom_enabled = enableType;\n\n\t\tif (!$$.zoom) {\n\t\t\t$$.initZoom();\n\t\t\t$$.bindZoomEvent();\n\t\t} else if (enabled === false) {\n\t\t\t$$.bindZoomEvent(false);\n\t\t}\n\n\t\t$$.updateAndRedraw();\n\t},\n\n\t/**\n\t * Set or get x Axis maximum zoom range value\n\t * @method zoom․max\n\t * @instance\n\t * @memberof Chart\n\t * @param {Number} [max] maximum value to set for zoom\n\t * @return {Number} zoom max value\n\t * @example\n\t * // Set maximum range value\n\t * chart.zoom.max(20);\n\t */\n\tmax: function(max) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (max === 0 || max) {\n\t\t\tconfig.zoom_x_max = getMinMax(\"max\", [$$.orgXDomain[1], max]);\n\t\t}\n\n\t\treturn config.zoom_x_max;\n\t},\n\n\t/**\n\t * Set or get x Axis minimum zoom range value\n\t * @method zoom․min\n\t * @instance\n\t * @memberof Chart\n\t * @param {Number} [min] minimum value to set for zoom\n\t * @return {Number} zoom min value\n\t * @example\n\t * // Set minimum range value\n\t * chart.zoom.min(-1);\n\t */\n\tmin: function(min) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (min === 0 || min) {\n\t\t\tconfig.zoom_x_min = getMinMax(\"min\", [$$.orgXDomain[0], min]);\n\t\t}\n\n\t\treturn config.zoom_x_min;\n\t},\n\n\t/**\n\t * Set zoom range\n\t * @method zoom․range\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} [range]\n\t * @return {Object} zoom range value\n\t * {\n\t * min: 0,\n\t * max: 100\n\t * }\n\t * @example\n\t * chart.zoom.range({\n\t * min: 10,\n\t * max: 100\n\t * });\n\t */\n\trange: function(range) {\n\t\tconst zoom = this.zoom;\n\n\t\tif (isObject(range)) {\n\t\t\tconst {min, max} = range;\n\n\t\t\tisDefined(min) && zoom.min(min);\n\t\t\tisDefined(max) && zoom.max(max);\n\t\t}\n\n\t\treturn {\n\t\t\tmin: zoom.min(),\n\t\t\tmax: zoom.max()\n\t\t};\n\t}\n});\n\nextend(Chart.prototype, {\n\tzoom,\n\n\t/**\n\t * Unzoom zoomed area\n\t * @method unzoom\n\t * @instance\n\t * @memberof Chart\n\t * @example\n\t * chart.unzoom();\n\t */\n\tunzoom() {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif ($$.zoomScale) {\n\t\t\tconfig.subchart_show ?\n\t\t\t\t$$.brush.getSelection().call($$.brush.move, null) :\n\t\t\t\t$$.zoom.updateTransformScale(d3ZoomIdentity);\n\n\t\t\t$$.updateZoom(true);\n\t\t\t$$.zoom.resetBtn && $$.zoom.resetBtn.style(\"display\", \"none\");\n\n\t\t\t// reset transform\n\t\t\tconst eventRects = $$.main.select(`.${CLASS.eventRects}`);\n\n\t\t\tif (d3ZoomTransform(eventRects.node()) !== d3ZoomIdentity) {\n\t\t\t\t$$.zoom.transform(eventRects, d3ZoomIdentity);\n\t\t\t}\n\n\t\t\t$$.redraw({\n\t\t\t\twithTransition: true,\n\t\t\t\twithUpdateXDomain: true,\n\t\t\t\twithUpdateOrgXDomain: true,\n\t\t\t\twithY: config.zoom_rescale\n\t\t\t});\n\t\t}\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend, isString, isArray} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Load data to the chart.<br><br>\n\t * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be toggles.\n\t * - <b>Note:</b>\n\t * - unload should be used if some data needs to be unloaded simultaneously.\n\t * If you call unload API soon after/before load instead of unload param, chart will not be rendered properly because of cancel of animation.<br>\n\t * - done will be called after data loaded, but it's not after rendering.\n\t * It's because rendering will finish after some transition and there is some time lag between loading and rendering\n\t * @method load\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} args The object can consist with following members:<br>\n\t *\n\t * | Key | Description |\n\t * | --- | --- |\n\t * | - url<br>- json<br>- rows<br>- columns | The data will be loaded. If data that has the same target id is given, the chart will be updated. Otherwise, new target will be added |\n\t * | data | Data objects to be loaded. Checkout the example. |\n\t * | names | Same as data.names() |\n\t * | xs | Same as data.xs option |\n\t * | classes | The classes specified by data.classes will be updated. classes must be Object that has target id as keys. |\n\t * | categories | The categories specified by axis.x.categories or data.x will be updated. categories must be Array. |\n\t * | axes | The axes specified by data.axes will be updated. axes must be Object that has target id as keys. |\n\t * | colors | The colors specified by data.colors will be updated. colors must be Object that has target id as keys. |\n\t * | headers | Set request header if loading via `data.url`.<br>@see [data․headers](Options.html#.data%25E2%2580%25A4headers) |\n\t * | keys | Choose which JSON objects keys correspond to desired data.<br>**NOTE:** Only for JSON object given as array.<br>@see [data․keys](Options.html#.data%25E2%2580%25A4keys) |\n\t * | mimeType | Set 'json' if loading JSON via url.<br>@see [data․mimeType](Options.html#.data%25E2%2580%25A4mimeType) |\n\t * | - type<br>- types | The type of targets will be updated. type must be String and types must be Object. |\n\t * | unload | Specify the data will be unloaded before loading new data. If true given, all of data will be unloaded. If target ids given as String or Array, specified targets will be unloaded. If absent or false given, unload will not occur. |\n\t * | done | The specified function will be called after data loaded.|\n\t * @see [Demo](https://naver.github.io/billboard.js/demo/#Data.DataFromURL)\n\t * @example\n\t * // Load data1 and unload data2 and data3\n\t * chart.load({\n\t * columns: [\n\t * [\"data1\", 100, 200, 150, ...],\n\t * ...\n\t * ],\n\t * unload: [\"data2\", \"data3\"],\n\t * url: \"...\",\n\t * done: function() { ... }\n\t * });\n\t * @example\n\t * // myAPI.json\n\t * // {\n\t * // \"data1\": [220, 240, 270, 250, 280],\n\t * // \"data2\": [180, 150, 300, 70, 120]\n\t * // }\n\t *\n\t * chart.load({\n\t * url: './data/myAPI.json',\n\t * mimeType: \"json\",\n\t *\n\t * // set request header if is needed\n\t * headers: {\n\t * \"Content-Type\": \"text/json\"\n\t * }\n\t * });\n\t * @example\n\t * chart.load({\n\t * data: [\n\t * // equivalent as: columns: [[\"data1\", 30, 200, 100]]\n\t * {\"data1\": 30}, {\"data1\": 200}, {\"data1\": 100}\n\t *\n\t * // or\n\t * // equivalent as: columns: [[\"data1\", 10, 20], [\"data2\", 13, 30]]\n\t * // {\"data1\": 10, \"data2\": 13}, {\"data1\": 20, \"data2\": 30}}\n\t * ]\n\t * });\n\t * @example\n\t * chart.load({\n\t * json: [\n\t * {name: \"www.site1.com\", upload: 800, download: 500, total: 400},\n\t * ],\n\t * keys: {\n\t * x: \"name\",\n\t * value: [\"upload\", \"download\"]\n\t * }\n\t * });\n\t */\n\tload(args) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\t// update xs if specified\n\t\targs.xs && $$.addXs(args.xs);\n\n\t\t// update names if exists\n\t\t\"names\" in args && this.data.names(args.names);\n\n\t\t// update classes if exists\n\t\t\"classes\" in args && Object.keys(args.classes).forEach(id => {\n\t\t\tconfig.data_classes[id] = args.classes[id];\n\t\t});\n\n\t\t// update categories if exists\n\t\tif (\"categories\" in args && $$.isCategorized()) {\n\t\t\tconfig.axis_x_categories = args.categories;\n\t\t}\n\n\t\t// update axes if exists\n\t\t\"axes\" in args && Object.keys(args.axes).forEach(id => {\n\t\t\tconfig.data_axes[id] = args.axes[id];\n\t\t});\n\n\t\t// update colors if exists\n\t\t\"colors\" in args && Object.keys(args.colors).forEach(id => {\n\t\t\tconfig.data_colors[id] = args.colors[id];\n\t\t});\n\n\t\t// unload if needed\n\t\tif (\"unload\" in args && args.unload !== false) {\n\t\t\t// TODO: do not unload if target will load (included in url/rows/columns)\n\t\t\t$$.unload($$.mapToTargetIds(args.unload === true ? null : args.unload), () =>\n\t\t\t\t$$.loadFromArgs(args)\n\t\t\t);\n\t\t} else {\n\t\t\t$$.loadFromArgs(args);\n\t\t}\n\t},\n\n\t/**\n\t * Unload data to the chart.<br><br>\n\t * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be toggles.\n\t * - <b>Note:</b>\n\t * If you call load API soon after/before unload, unload param of load should be used. Otherwise chart will not be rendered properly because of cancel of animation.<br>\n\t * `done` will be called after data loaded, but it's not after rendering. It's because rendering will finish after some transition and there is some time lag between loading and rendering.\n\t * @method unload\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} args\n\t * | key | Type | Description |\n\t * | --- | --- | --- |\n\t * | ids | String &vert; Array | Target id data to be unloaded. If not given, all data will be unloaded. |\n\t * | done | Fuction | Callback after data is unloaded. |\n\t * @example\n\t * // Unload data2 and data3\n\t * chart.unload({\n\t * ids: [\"data2\", \"data3\"],\n\t * done: function() {\n\t * // called after the unloaded\n\t * }\n\t * });\n\t */\n\tunload(argsValue) {\n\t\tconst $$ = this.internal;\n\t\tlet args = argsValue || {};\n\n\t\tif (isArray(args)) {\n\t\t\targs = {ids: args};\n\t\t} else if (isString(args)) {\n\t\t\targs = {ids: [args]};\n\t\t}\n\n\t\tconst ids = $$.mapToTargetIds(args.ids);\n\n\t\t$$.unload(ids, () => {\n\t\t\t$$.redraw({\n\t\t\t\twithUpdateOrgXDomain: true,\n\t\t\t\twithUpdateXDomain: true,\n\t\t\t\twithLegend: true\n\t\t\t});\n\n\t\t\t$$.removeCache(ids);\n\t\t\targs.done && args.done();\n\t\t});\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {selectAll as d3SelectAll} from \"d3-selection\";\nimport {easeLinear as d3EaseLinear} from \"d3-ease\";\nimport {transition as d3Transition} from \"d3-transition\";\nimport Chart from \"../internals/Chart\";\nimport ChartInternal from \"../internals/ChartInternal\";\nimport {isDefined, isValue, diffDomain, extend} from \"../internals/util\";\nimport CLASS from \"../config/classes\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Flow data to the chart.<br><br>\n\t * By this API, you can append new data points to the chart.\n\t * @method flow\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} args The object can consist with following members:<br>\n\t *\n\t * | Key | Type | Description |\n\t * | --- | --- | --- |\n\t * | json | Object | Data as JSON format (@see [data․json](Options.html#.data%25E2%2580%25A4json)) |\n\t * | rows | Array | Data in array as row format (@see [data․rows](Options.html#.data%25E2%2580%25A4json)) |\n\t * | columns | Array | Data in array as column format (@see [data․columns](Options.html#.data%25E2%2580%25A4columns)) |\n\t * | to | String | The lower x edge will move to that point. If not given, the lower x edge will move by the number of given data points |\n\t * | length | Number | The lower x edge will move by the number of this argument |\n\t * | duration | Number | The duration of the transition will be specified value. If not given, transition.duration will be used as default |\n\t * | done | Function | The specified function will be called when flow ends |\n\t *\n\t * - **NOTE:**\n\t * - If json, rows and columns given, the data will be loaded.\n\t * - If data that has the same target id is given, the chart will be appended.\n\t * - Otherwise, new target will be added. One of these is required when calling.\n\t * - If json specified, keys is required as well as data.json.\n\t * \t - If tab isn't visible(by evaluating `document.hidden`), will not be executed to prevent unnecessary work.\n\t * @example\n\t * // 2 data points will be apprended to the tail and popped from the head.\n\t * // After that, 4 data points will be appended and no data points will be poppoed.\n\t * chart.flow({\n\t * columns: [\n\t * [\"x\", \"2018-01-11\", \"2018-01-21\"],\n\t * [\"data1\", 500, 200],\n\t * [\"data2\", 100, 300],\n\t * [\"data3\", 200, 120]\n\t * ],\n\t * to: \"2013-01-11\",\n\t * done: function () {\n\t * chart.flow({\n\t * columns: [\n\t * [\"x\", \"2018-02-11\", \"2018-02-12\", \"2018-02-13\", \"2018-02-14\"],\n\t * [\"data1\", 200, 300, 100, 250],\n\t * [\"data2\", 100, 90, 40, 120],\n\t * [\"data3\", 100, 100, 300, 500]\n\t * ],\n\t * length: 2,\n * duration: 1500\n\t * });\n\t * }\n\t * });\n\t */\n\tflow(args) {\n\t\tconst $$ = this.internal;\n\t\tlet data;\n\t\tlet domain;\n\t\tlet length = 0;\n\t\tlet tail = 0;\n\t\tlet diff;\n\t\tlet to;\n\n\t\tif (args.json || args.rows || args.columns) {\n\t\t\tdata = $$.convertData(args);\n\t\t}\n\n\t\tif (!data || !$$.isTabVisible()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst notfoundIds = [];\n\t\tconst orgDataCount = $$.getMaxDataCount();\n\t\tconst targets = $$.convertDataToTargets(data, true);\n\n\t\t// Update/Add data\n\t\t$$.data.targets.forEach(t => {\n\t\t\tlet found = false;\n\n\t\t\tfor (let i = 0; i < targets.length; i++) {\n\t\t\t\tif (t.id === targets[i].id) {\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\tif (t.values[t.values.length - 1]) {\n\t\t\t\t\t\ttail = t.values[t.values.length - 1].index + 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tlength = targets[i].values.length;\n\n\t\t\t\t\tfor (let j = 0; j < length; j++) {\n\t\t\t\t\t\ttargets[i].values[j].index = tail + j;\n\n\t\t\t\t\t\tif (!$$.isTimeSeries()) {\n\t\t\t\t\t\t\ttargets[i].values[j].x = tail + j;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tt.values = t.values.concat(targets[i].values);\n\t\t\t\t\ttargets.splice(i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t!found && notfoundIds.push(t.id);\n\t\t});\n\n\t\t// Append null for not found targets\n\t\t$$.data.targets.forEach(t => {\n\t\t\tfor (let i = 0; i < notfoundIds.length; i++) {\n\t\t\t\tif (t.id === notfoundIds[i]) {\n\t\t\t\t\ttail = t.values[t.values.length - 1].index + 1;\n\n\t\t\t\t\tfor (let j = 0; j < length; j++) {\n\t\t\t\t\t\tt.values.push({\n\t\t\t\t\t\t\tid: t.id,\n\t\t\t\t\t\t\tindex: tail + j,\n\t\t\t\t\t\t\tx: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,\n\t\t\t\t\t\t\tvalue: null\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// Generate null values for new target\n\t\tif ($$.data.targets.length) {\n\t\t\ttargets.forEach(t => {\n\t\t\t\tconst missing = [];\n\n\t\t\t\tfor (let i = $$.data.targets[0].values[0].index; i < tail; i++) {\n\t\t\t\t\tmissing.push({\n\t\t\t\t\t\tid: t.id,\n\t\t\t\t\t\tindex: i,\n\t\t\t\t\t\tx: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,\n\t\t\t\t\t\tvalue: null\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tt.values.forEach(v => {\n\t\t\t\t\tv.index += tail;\n\n\t\t\t\t\tif (!$$.isTimeSeries()) {\n\t\t\t\t\t\tv.x += tail;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tt.values = missing.concat(t.values);\n\t\t\t});\n\t\t}\n\n\t\t$$.data.targets = $$.data.targets.concat(targets); // add remained\n\n\t\t// check data count because behavior needs to change when it\"s only one\n\t\t// const dataCount = $$.getMaxDataCount();\n\t\tconst baseTarget = $$.data.targets[0];\n\t\tconst baseValue = baseTarget.values[0];\n\n\t\t// Update length to flow if needed\n\t\tif (isDefined(args.to)) {\n\t\t\tlength = 0;\n\t\t\tto = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;\n\n\t\t\tbaseTarget.values.forEach(v => {\n\t\t\t\tv.x < to && length++;\n\t\t\t});\n\t\t} else if (isDefined(args.length)) {\n\t\t\tlength = args.length;\n\t\t}\n\n\t\t// If only one data, update the domain to flow from left edge of the chart\n\t\tif (!orgDataCount) {\n\t\t\tif ($$.isTimeSeries()) {\n\t\t\t\tdiff = baseTarget.values.length > 1 ?\n\t\t\t\t\tbaseTarget.values[baseTarget.values.length - 1].x - baseValue.x :\n\t\t\t\t\tbaseValue.x - $$.getXDomain($$.data.targets)[0];\n\t\t\t} else {\n\t\t\t\tdiff = 1;\n\t\t\t}\n\n\t\t\tdomain = [baseValue.x - diff, baseValue.x];\n\t\t} else if (orgDataCount === 1 && $$.isTimeSeries()) {\n\t\t\tdiff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;\n\t\t\tdomain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];\n\t\t}\n\n\t\tdomain && $$.updateXDomain(null, true, true, false, domain);\n\n\t\t// Set targets\n\t\t$$.updateTargets($$.data.targets);\n\n\t\t// Redraw with new targets\n\t\t$$.redraw({\n\t\t\tflow: {\n\t\t\t\tindex: baseValue.index,\n\t\t\t\tlength: length,\n\t\t\t\tduration: isValue(args.duration) ? args.duration : $$.config.transition_duration,\n\t\t\t\tdone: args.done,\n\t\t\t\torgDataCount: orgDataCount,\n\t\t\t},\n\t\t\twithLegend: true,\n\t\t\twithTransition: orgDataCount > 1,\n\t\t\twithTrimXDomain: false,\n\t\t\twithUpdateXAxis: true\n\t\t});\n\t}\n});\n\nextend(ChartInternal.prototype, {\n\t/**\n\t * Generate flow\n\t * @memberof ChartInternal\n\t * @private\n\t * @param {Object} args\n\t * @return {Function}\n\t */\n\tgenerateFlow(args) {\n\t\tconst $$ = this;\n\t\tconst config = $$.config;\n\n\t\treturn function() {\n\t\t\tconst targets = args.targets;\n\t\t\tconst flow = args.flow;\n\n\t\t\tconst {bar: drawBar, line: drawLine, area: drawArea} = args.shape.type;\n\t\t\tconst {cx, cy, xForText, yForText} = args.shape.pos;\n\t\t\tconst xv = args.xv;\n\t\t\tconst duration = args.duration;\n\n\t\t\tlet translateX;\n\t\t\tlet scaleX = 1;\n\t\t\tconst flowIndex = flow.index;\n\t\t\tconst flowLength = flow.length;\n\t\t\tlet flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex);\n\t\t\tlet flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength);\n\t\t\tconst orgDomain = $$.x.domain();\n\t\t\tconst durationForFlow = flow.duration || duration;\n\t\t\tconst done = flow.done || function() {};\n\t\t\tconst wait = $$.generateWait();\n\n\t\t\tconst xgrid = $$.xgrid || d3SelectAll([]);\n\t\t\tconst xgridLines = $$.xgridLines || d3SelectAll([]);\n\t\t\tconst mainRegion = $$.mainRegion || d3SelectAll([]);\n\t\t\tconst mainText = $$.mainText || d3SelectAll([]);\n\t\t\tconst mainBar = $$.mainBar || d3SelectAll([]);\n\t\t\tconst mainLine = $$.mainLine || d3SelectAll([]);\n\t\t\tconst mainArea = $$.mainArea || d3SelectAll([]);\n\t\t\tconst mainCircle = $$.mainCircle || d3SelectAll([]);\n\n\t\t\t// set flag\n\t\t\t$$.flowing = true;\n\n\t\t\t// remove head data after rendered\n\t\t\t$$.data.targets.forEach(d => {\n\t\t\t\td.values.splice(0, flowLength);\n\t\t\t});\n\n\t\t\t// update x domain to generate axis elements for flow\n\t\t\tconst domain = $$.updateXDomain(targets, true, true);\n\n\t\t\t// update elements related to x scale\n\t\t\tif ($$.updateXGrid) { $$.updateXGrid(true); }\n\n\t\t\t// generate transform to flow\n\t\t\tif (!flow.orgDataCount) { // if empty\n\t\t\t\tif ($$.data.targets[0].values.length !== 1) {\n\t\t\t\t\ttranslateX = $$.x(orgDomain[0]) - $$.x(domain[0]);\n\t\t\t\t} else {\n\t\t\t\t\tif ($$.isTimeSeries()) {\n\t\t\t\t\t\tflowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);\n\t\t\t\t\t\tflowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);\n\t\t\t\t\t\ttranslateX = $$.x(flowStart.x) - $$.x(flowEnd.x);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttranslateX = diffDomain(domain) / 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {\n\t\t\t\ttranslateX = $$.x(orgDomain[0]) - $$.x(domain[0]);\n\t\t\t} else {\n\t\t\t\tif ($$.isTimeSeries()) {\n\t\t\t\t\ttranslateX = ($$.x(orgDomain[0]) - $$.x(domain[0]));\n\t\t\t\t} else {\n\t\t\t\t\ttranslateX = ($$.x(flowStart.x) - $$.x(flowEnd.x));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tscaleX = (diffDomain(orgDomain) / diffDomain(domain));\n\t\t\tconst transform = `translate(${translateX},0) scale(${scaleX},1)`;\n\n\t\t\t$$.hideGridFocus();\n\n\t\t\tconst gt = d3Transition().ease(d3EaseLinear)\n\t\t\t\t.duration(durationForFlow);\n\n\t\t\twait.add([\n\t\t\t\t$$.axes.x\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.call(g => $$.xAxis.setTransition(gt).create(g)),\n\n\t\t\t\tmainBar\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\tmainLine\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\tmainArea\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\tmainCircle\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\tmainText\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\tmainRegion\n\t\t\t\t\t.filter($$.isRegionOnX)\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\txgrid\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\n\t\t\t\txgridLines\n\t\t\t\t\t.transition(gt)\n\t\t\t\t\t.attr(\"transform\", transform),\n\t\t\t]);\n\n\t\t\tgt.call(wait, () => {\n\t\t\t\tconst isRotated = config.axis_rotated;\n\n\t\t\t\t// remove flowed elements\n\t\t\t\tif (flowLength) {\n\t\t\t\t\tconst target = {\n\t\t\t\t\t\tshapes: [],\n\t\t\t\t\t\ttexts: [],\n\t\t\t\t\t\teventRects: []\n\t\t\t\t\t};\n\n\t\t\t\t\tfor (let i = 0; i < flowLength; i++) {\n\t\t\t\t\t\ttarget.shapes.push(`.${CLASS.shape}-${i}`);\n\t\t\t\t\t\ttarget.texts.push(`.${CLASS.text}-${i}`);\n\t\t\t\t\t\ttarget.eventRects.push(`.${CLASS.eventRect}-${i}`);\n\t\t\t\t\t}\n\n\t\t\t\t\t[\"shapes\", \"texts\", \"eventRects\"].forEach(v => {\n\t\t\t\t\t\t$$.svg.selectAll(`.${CLASS[v]}`)\n\t\t\t\t\t\t\t.selectAll(target[v])\n\t\t\t\t\t\t\t.remove();\n\t\t\t\t\t});\n\n\t\t\t\t\t$$.svg.select(`.${CLASS.xgrid}`)\n\t\t\t\t\t\t.remove();\n\t\t\t\t}\n\n\t\t\t\t// draw again for removing flowed elements and reverting attr\n\t\t\t\txgrid.size() && xgrid\n\t\t\t\t\t.attr(\"transform\", null)\n\t\t\t\t\t.attr($$.xgridAttr);\n\n\t\t\t\txgridLines\n\t\t\t\t\t.attr(\"transform\", null);\n\n\t\t\t\txgridLines.select(\"line\")\n\t\t\t\t\t.attr(\"x1\", isRotated ? 0 : xv)\n\t\t\t\t\t.attr(\"x2\", isRotated ? $$.width : xv);\n\n\t\t\t\txgridLines.select(\"text\")\n\t\t\t\t\t.attr(\"x\", isRotated ? $$.width : 0)\n\t\t\t\t\t.attr(\"y\", xv);\n\n\t\t\t\tmainBar\n\t\t\t\t\t.attr(\"transform\", null)\n\t\t\t\t\t.attr(\"d\", drawBar);\n\n\t\t\t\tmainLine\n\t\t\t\t\t.attr(\"transform\", null)\n\t\t\t\t\t.attr(\"d\", drawLine);\n\n\t\t\t\tmainArea\n\t\t\t\t\t.attr(\"transform\", null)\n\t\t\t\t\t.attr(\"d\", drawArea);\n\n\t\t\t\tmainCircle\n\t\t\t\t\t.attr(\"transform\", null);\n\n\t\t\t\tif ($$.isCirclePoint()) {\n\t\t\t\t\tmainCircle\n\t\t\t\t\t\t.attr(\"cx\", cx)\n\t\t\t\t\t\t.attr(\"cy\", cy);\n\t\t\t\t} else {\n\t\t\t\t\tconst xFunc = d => cx(d) - config.point_r;\n\t\t\t\t\tconst yFunc = d => cy(d) - config.point_r;\n\n\t\t\t\t\tmainCircle\n\t\t\t\t\t\t.attr(\"x\", xFunc)\n\t\t\t\t\t\t.attr(\"y\", yFunc)\n\t\t\t\t\t\t.attr(\"cx\", cx) // when pattern is used, it possibly contain 'circle' also.\n\t\t\t\t\t\t.attr(\"cy\", cy);\n\t\t\t\t}\n\n\t\t\t\tmainText\n\t\t\t\t\t.attr(\"transform\", null)\n\t\t\t\t\t.attr(\"x\", xForText)\n\t\t\t\t\t.attr(\"y\", yForText)\n\t\t\t\t\t.style(\"fill-opacity\", $$.opacityForText.bind($$));\n\n\t\t\t\tmainRegion\n\t\t\t\t\t.attr(\"transform\", null);\n\n\t\t\t\tmainRegion.select(\"rect\").filter($$.isRegionOnX)\n\t\t\t\t\t.attr(\"x\", $$.regionX.bind($$))\n\t\t\t\t\t.attr(\"width\", $$.regionWidth.bind($$));\n\n\t\t\t\tconfig.interaction_enabled && $$.redrawEventRect();\n\n\t\t\t\t// callback for end of flow\n\t\t\t\tdone();\n\n\t\t\t\t$$.flowing = false;\n\t\t\t});\n\t\t};\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {select as d3Select} from \"d3-selection\";\nimport Chart from \"../internals/Chart\";\nimport {isDefined, extend} from \"../internals/util\";\nimport CLASS from \"../config/classes\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Get selected data points.<br><br>\n\t * By this API, you can get selected data points information. To use this API, data.selection.enabled needs to be set true.\n\t * @method selected\n\t * @instance\n\t * @memberof Chart\n\t * @param {String} [targetId] You can filter the result by giving target id that you want to get. If not given, all of data points will be returned.\n\t * @return {Array} dataPoint Array of the data points.<br>ex.) `[{x: 1, value: 200, id: \"data1\", index: 1, name: \"data1\"}, ...]`\n\t * @example\n\t * // all selected data points will be returned.\n\t * chart.selected();\n\t * // --> ex.) [{x: 1, value: 200, id: \"data1\", index: 1, name: \"data1\"}, ... ]\n\t *\n\t * // all selected data points of data1 will be returned.\n\t * chart.selected(\"data1\");\n\t */\n\tselected(targetId) {\n\t\tconst $$ = this.internal;\n\t\tconst dataPoint = [];\n\n\t\t$$.main.selectAll(`.${CLASS.shapes + $$.getTargetSelectorSuffix(targetId)}`)\n\t\t\t.selectAll(`.${CLASS.shape}`)\n\t\t\t.filter(function() {\n\t\t\t\treturn d3Select(this).classed(CLASS.SELECTED);\n\t\t\t})\n\t\t\t.each(d => dataPoint.push(d));\n\n\t\treturn dataPoint;\n\t},\n\n\t/**\n\t * Set data points to be selected. (`[data.selection.enabled](Options.html#.data%25E2%2580%25A4selection%25E2%2580%25A4enabled) option should be set true to use this method)`\n\t * @method select\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} [ids] id value to get selected.\n\t * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.\n\t * @param {Boolean} [resetOther] Unselect already selected.\n\t * @example\n\t * // select all data points\n\t * chart.select();\n\t *\n\t * // select all from 'data2'\n\t * chart.select(\"data2\");\n\t *\n\t * // select all from 'data1' and 'data2'\n\t * chart.select([\"data1\", \"data2\"]);\n\t *\n\t * // select from 'data1', indices 2 and unselect others selected\n\t * chart.select(\"data1\", [2], true);\n\t *\n\t * // select from 'data1', indices 0, 3 and 5\n\t * chart.select(\"data1\", [0, 3, 5]);\n\t */\n\tselect(ids, indices, resetOther) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (!config.data_selection_enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.main.selectAll(`.${CLASS.shapes}`)\n\t\t\t.selectAll(`.${CLASS.shape}`)\n\t\t\t.each(function(d, i) {\n\t\t\t\tconst shape = d3Select(this);\n\t\t\t\tconst id = d.data ? d.data.id : d.id;\n\t\t\t\tconst toggle = $$.getToggle(this, d).bind($$);\n\t\t\t\tconst isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0;\n\t\t\t\tconst isTargetIndex = !indices || indices.indexOf(i) >= 0;\n\t\t\t\tconst isSelected = shape.classed(CLASS.SELECTED);\n\n\t\t\t\t// line/area selection not supported yet\n\t\t\t\tif (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (isTargetId && isTargetIndex) {\n\t\t\t\t\tif (config.data_selection_isselectable(d) && !isSelected) {\n\t\t\t\t\t\ttoggle(true, shape.classed(CLASS.SELECTED, true), d, i);\n\t\t\t\t\t}\n\t\t\t\t} else if (isDefined(resetOther) && resetOther && isSelected) {\n\t\t\t\t\ttoggle(false, shape.classed(CLASS.SELECTED, false), d, i);\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\t/**\n\t * Set data points to be un-selected.\n\t * @method unselect\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} [ids] id value to be unselected.\n\t * @param {Array} [indices] The index array of data points. If falsy value given, will select all data points.\n\t * @example\n\t * // unselect all data points\n\t * chart.unselect();\n\t *\n\t * // unselect all from 'data1'\n\t * chart.unselect(\"data1\");\n\t *\n\t * // unselect from 'data1', indices 2\n\t * chart.unselect(\"data1\", [2]);\n\t */\n\tunselect(ids, indices) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (!config.data_selection_enabled) {\n\t\t\treturn;\n\t\t}\n\n\t\t$$.main.selectAll(`.${CLASS.shapes}`)\n\t\t\t.selectAll(`.${CLASS.shape}`)\n\t\t\t.each(function(d, i) {\n\t\t\t\tconst shape = d3Select(this);\n\t\t\t\tconst id = d.data ? d.data.id : d.id;\n\t\t\t\tconst toggle = $$.getToggle(this, d).bind($$);\n\t\t\t\tconst isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0;\n\t\t\t\tconst isTargetIndex = !indices || indices.indexOf(i) >= 0;\n\t\t\t\tconst isSelected = shape.classed(CLASS.SELECTED);\n\n\t\t\t\t// line/area selection not supported yet\n\t\t\t\tif (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (isTargetId && isTargetIndex && config.data_selection_isselectable(d) && isSelected) {\n\t\t\t\t\ttoggle(false, shape.classed(CLASS.SELECTED, false), d, i);\n\t\t\t\t}\n\t\t\t});\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\n/**\n * Change the type of the chart.\n * @private\n * @param {String|Array} targetIds\n * @param {String} type\n * @param {Object} optionsForRedraw\n */\nfunction transformTo(targetIds, type, optionsForRedraw) {\n\tconst $$ = this;\n\tconst options = optionsForRedraw || {withTransitionForAxis: !$$.hasArcType()};\n\n\toptions.withTransitionForTransform = false;\n\t$$.transiting = false;\n\n\t$$.setTargetType(targetIds, type);\n\t$$.updateTargets($$.data.targets); // this is needed when transforming to arc\n\t$$.updateAndRedraw(options);\n}\n\nextend(Chart.prototype, {\n\t/**\n\t * Change the type of the chart.\n\t * @method transform\n\t * @instance\n\t * @memberof Chart\n\t * @param {String} type Specify the type to be transformed. The types listed in data.type can be used.\n\t * @param {String|Array} targetIds Specify targets to be transformed. If not given, all targets will be the candidate.\n\t * @example\n\t * // all targets will be bar chart.\n\t * chart.transform(\"bar\");\n\t *\n\t * // only data1 will be bar chart.\n\t * chart.transform(\"bar\", \"data1\");\n\t *\n\t * // only data1 and data2 will be bar chart.\n\t * chart.transform(\"bar\", [\"data1\", \"data2\"]);\n\t */\n\ttransform(type, targetIds) {\n\t\tconst $$ = this.internal;\n\t\tconst options = [\"pie\", \"donut\"]\n\t\t\t.indexOf(type) >= 0 ? {withTransform: true} : null;\n\n\t\ttransformTo.bind($$)(targetIds, type, options);\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {isUndefined, extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Update groups for the targets.\n\t * @method groups\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array} groups This argument needs to be an Array that includes one or more Array that includes target ids to be grouped.\n\t * @return {Array} Grouped data names array\n\t * @example\n\t * // data1 and data2 will be a new group.\n\t * chart.groups([\n\t * [\"data1\", \"data2\"]\n\t * ]);\n\t */\n\tgroups(groups) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (isUndefined(groups)) {\n\t\t\treturn config.data_groups;\n\t\t}\n\n\t\tconfig.data_groups = groups;\n\t\t$$.redraw();\n\n\t\treturn config.data_groups;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\n/**\n * Update x grid lines.\n * @method xgrids\n * @instance\n * @memberof Chart\n * @param {Array} grids X grid lines will be replaced with this argument. The format of this argument is the same as grid.x.lines.\n * @example\n * // Show 2 x grid lines\n * chart.xgrids([\n * {value: 1, text: \"Label 1\"},\n * {value: 4, text: \"Label 4\"}\n * ]);\n */\nconst xgrids = function(grids) {\n\tconst $$ = this.internal;\n\tconst config = $$.config;\n\n\tif (!grids) {\n\t\treturn config.grid_x_lines;\n\t}\n\n\tconfig.grid_x_lines = grids;\n\t$$.redrawWithoutRescale();\n\n\treturn config.grid_x_lines;\n};\n\nextend(xgrids, {\n\t/**\n\t * Add x grid lines.<br>\n\t * This API adds new x grid lines instead of replacing like xgrids.\n\t * @method xgrids․add\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array|Object} grids New x grid lines will be added. The format of this argument is the same as grid.x.lines and it's possible to give an Object if only one line will be added.\n\t * @example\n\t * // Add a new x grid line\n\t * chart.xgrids.add(\n\t * {value: 4, text: \"Label 4\"}\n\t * );\n\t *\n\t * // Add new x grid lines\n\t * chart.xgrids.add([\n\t * {value: 2, text: \"Label 2\"},\n\t * {value: 4, text: \"Label 4\"}\n\t * ]);\n\t */\n\tadd: function(grids) {\n\t\treturn this.xgrids(\n\t\t\tthis.internal.config.grid_x_lines\n\t\t\t\t.concat(grids || [])\n\t\t);\n\t},\n\n\t/**\n\t * Remove x grid lines.<br>\n\t * This API removes x grid lines.\n\t * @method xgrids․remove\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} params This argument should include value or class. If value is given, the x grid lines that have specified x value will be removed. If class is given, the x grid lines that have specified class will be removed. If args is not given, all of x grid lines will be removed.\n\t * @example\n\t * // x grid line on x = 2 will be removed\n\t * chart.xgrids.remove({value: 2});\n\t *\n\t * // x grid lines that have 'grid-A' will be removed\n\t * chart.xgrids.remove({\n\t * class: \"grid-A\"\n\t * });\n\t *\n\t * // all of x grid lines will be removed\n\t * chart.xgrids.remove();\n\t */\n\tremove: function(params) { // TODO: multiple\n\t\tthis.internal.removeGridLines(params, true);\n\t}\n});\n\n\n/**\n * Update y grid lines.\n * @method ygrids\n * @instance\n * @memberof Chart\n * @param {Array} grids Y grid lines will be replaced with this argument. The format of this argument is the same as grid.y.lines.\n * @example\n * // Show 2 y grid lines\n * chart.ygrids([\n * {value: 100, text: \"Label 1\"},\n * {value: 400, text: \"Label 4\"}\n * ]);\n */\nconst ygrids = function(grids) {\n\tconst $$ = this.internal;\n\tconst config = $$.config;\n\n\tif (!grids) {\n\t\treturn config.grid_y_lines;\n\t}\n\n\tconfig.grid_y_lines = grids;\n\t$$.redrawWithoutRescale();\n\n\treturn config.grid_y_lines;\n};\n\nextend(ygrids, {\n\t/**\n\t * Add y grid lines.<br>\n\t * This API adds new y grid lines instead of replacing like ygrids.\n\t * @method ygrids․add\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array|Object} grids New y grid lines will be added. The format of this argument is the same as grid.y.lines and it's possible to give an Object if only one line will be added.\n\t * @example\n\t * // Add a new x grid line\n\t * chart.ygrids.add(\n\t * {value: 400, text: \"Label 4\"}\n\t * );\n\t *\n\t * // Add new x grid lines\n\t * chart.ygrids.add([\n\t * {value: 200, text: \"Label 2\"},\n\t * {value: 400, text: \"Label 4\"}\n\t * ]);\n\t */\n\tadd: function(grids) {\n\t\treturn this.ygrids(\n\t\t\tthis.internal.config.grid_y_lines\n\t\t\t\t.concat(grids || [])\n\t\t);\n\t},\n\n\t/**\n\t * Remove y grid lines.<br>\n\t * This API removes x grid lines.\n\t * @method ygrids․remove\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} params This argument should include value or class. If value is given, the y grid lines that have specified y value will be removed. If class is given, the y grid lines that have specified class will be removed. If args is not given, all of y grid lines will be removed.\n\t * @example\n\t * // y grid line on y = 200 will be removed\n\t * chart.ygrids.remove({value: 200});\n\t *\n\t * // y grid lines that have 'grid-A' will be removed\n\t * chart.ygrids.remove({\n\t * class: \"grid-A\"\n\t * });\n\t *\n\t * // all of y grid lines will be removed\n\t * chart.ygrids.remove();\n\t */\n\tremove: function(params) { // TODO: multiple\n\t\tthis.internal.removeGridLines(params, false);\n\t}\n});\n\nextend(Chart.prototype, {\n\txgrids,\n\tygrids\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport CLASS from \"../config/classes\";\nimport {getOption, extend} from \"../internals/util\";\n\n/**\n * Update regions.\n * @method regions\n * @instance\n * @memberof Chart\n * @param {Array} regions Regions will be replaced with this argument. The format of this argument is the same as regions.\n * @return {Array} regions\n * @example\n * // Show 2 regions\n * chart.regions([\n * {axis: \"x\", start: 5, class: \"regionX\"},\n * {axis: \"y\", end: 50, class: \"regionY\"}\n * ]);\n */\nconst regions = function(regions) {\n\tconst $$ = this.internal;\n\tconst config = $$.config;\n\n\tif (!regions) {\n\t\treturn config.regions;\n\t}\n\n\tconfig.regions = regions;\n\t$$.redrawWithoutRescale();\n\n\treturn regions;\n};\n\nextend(regions, {\n\t/**\n\t * Add new region.<br><br>\n\t * This API adds new region instead of replacing like regions.\n\t * @method regions․add\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array|Object} regions New region will be added. The format of this argument is the same as regions and it's possible to give an Object if only one region will be added.\n\t * @return {Array} regions\n\t * @example\n\t * // Add a new region\n\t * chart.regions.add(\n\t * {axis: \"x\", start: 5, class: \"regionX\"}\n\t * );\n\t *\n\t * // Add new regions\n\t * chart.regions.add([\n\t * {axis: \"x\", start: 5, class: \"regionX\"},\n\t * {axis: \"y\", end: 50, class: \"regionY\"}\n\t *]);\n\t */\n\tadd: function(regions) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (!regions) {\n\t\t\treturn config.regions;\n\t\t}\n\n\t\tconfig.regions = config.regions.concat(regions);\n\t\t$$.redrawWithoutRescale();\n\n\t\treturn config.regions;\n\t},\n\n\t/**\n\t * Remove regions.<br><br>\n\t * This API removes regions.\n\t * @method regions․remove\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} regions This argument should include classes. If classes is given, the regions that have one of the specified classes will be removed. If args is not given, all of regions will be removed.\n\t * @return {Array} regions Removed regions\n\t * @example\n\t * // regions that have 'region-A' or 'region-B' will be removed.\n\t * chart.regions.remove({\n\t * classes: [\n\t * \"region-A\", \"region-B\"\n\t * ]\n\t * });\n\t *\n\t * // all of regions will be removed.\n\t * chart.regions.remove();\n\t */\n\tremove: function(optionsValue) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tconst options = optionsValue || {};\n\t\tconst duration = getOption(options, \"duration\", config.transition_duration);\n\t\tconst classes = getOption(options, \"classes\", [CLASS.region]);\n\t\tlet regions = $$.main.select(`.${CLASS.regions}`)\n\t\t\t.selectAll(classes.map(c => `.${c}`));\n\n\t\t(duration ? regions.transition().duration(duration) : regions)\n\t\t\t.style(\"opacity\", \"0\")\n\t\t\t.remove();\n\n\t\tregions = config.regions;\n\n\t\tif (Object.keys(options).length) {\n\t\t\tregions = regions.filter(region => {\n\t\t\t\tlet found = false;\n\n\t\t\t\tif (!region.class) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tregion.class.split(\" \").forEach(c => {\n\t\t\t\t\tif (classes.indexOf(c) >= 0) {\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn !found;\n\t\t\t});\n\n\t\t\tconfig.regions = regions;\n\t\t} else {\n\t\t\tconfig.regions = [];\n\t\t}\n\n\t\treturn regions;\n\t}\n});\n\nextend(Chart.prototype, {regions});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend, isUndefined, isArray} from \"../internals/util\";\n\n/**\n * Get data loaded in the chart.\n * @method data\n * @instance\n * @memberof Chart\n * @param {String|Array} targetIds If this argument is given, this API returns the specified target data. If this argument is not given, all of data will be returned.\n * @return {Array} Data objects\n * @example\n * // Get only data1 data\n * chart.data(\"data1\");\n * // --> [{id: \"data1\", id_org: \"data1\", values: Array(6)}, ...]\n *\n * // Get data1 and data2 data\n * chart.data([\"data1\", \"data2\"]);\n *\n * // Get all data\n * chart.data();\n */\nconst data = function(targetIds) {\n\tconst targets = this.internal.data.targets;\n\n\tif (!isUndefined(targetIds)) {\n\t\tconst ids = isArray(targetIds) ? targetIds : [targetIds];\n\n\t\treturn targets.filter(t => ids.some(v => v === t.id));\n\t}\n\n\treturn targets;\n};\n\nextend(data, {\n\t/**\n\t * Get data shown in the chart.\n\t * @method data․shown\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} targetIds If this argument is given, this API filters the data with specified target ids. If this argument is not given, all shown data will be returned.\n\t * @return {Array} Data objects\n\t * @example\n\t * // Get shown data by filtering to include only data1 data\n\t * chart.data.shown(\"data1\");\n\t * // --> [{id: \"data1\", id_org: \"data1\", values: Array(6)}, ...]\n\t *\n\t * // Get shown data by filtering to include data1 and data2 data\n\t * chart.data.shown([\"data1\", \"data2\"]);\n\t *\n\t * // Get all shown data\n\t * chart.data.shown();\n\t */\n\tshown: function(targetIds) {\n\t\treturn this.internal.filterTargetsToShow(this.data(targetIds));\n\t},\n\n\t/**\n\t * Get values of the data loaded in the chart.\n\t * @method data․values\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} targetIds This API returns the values of specified target. If this argument is not given, null will be retruned\n\t * @return {Array} Data values\n\t * @example\n\t * // Get data1 values\n\t * chart.data.values(\"data1\");\n\t * // --> [10, 20, 30, 40]\n\t */\n\tvalues: function(targetId, flat = true) {\n\t\tlet values = null;\n\n\t\tif (targetId) {\n\t\t\tconst targets = this.data(targetId);\n\n\t\t\tif (targets && isArray(targets)) {\n\t\t\t\tvalues = [];\n\n\t\t\t\ttargets.forEach(v => {\n\t\t\t\t\tconst dataValue = v.values.map(d => d.value);\n\n\t\t\t\t\tflat ? (values = values.concat(dataValue)) : values.push(dataValue);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn values;\n\t},\n\n\t/**\n\t * Get and set names of the data loaded in the chart.\n\t * @method data․names\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} names If this argument is given, the names of data will be updated. If not given, the current names will be returned. The format of this argument is the same as\n\t * @return {Object} Corresponding names according its key value, if specified names values.\n\t * @example\n\t * // Get current names\n\t * chart.data.names();\n\t * // --> {data1: \"test1\", data2: \"test2\"}\n\t *\n\t * // Update names\n\t * chart.data.names({\n\t * data1: \"New Name 1\",\n\t * data2: \"New Name 2\"\n\t *});\n\t */\n\tnames: function(names) {\n\t\tthis.internal.clearLegendItemTextBoxCache();\n\n\t\treturn this.internal.updateDataAttributes(\"names\", names);\n\t},\n\n\t/**\n\t * Get and set colors of the data loaded in the chart.\n\t * @method data․colors\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} colors If this argument is given, the colors of data will be updated. If not given, the current colors will be returned. The format of this argument is the same as [data.colors](./Options.html#.data%25E2%2580%25A4colors).\n\t * @return {Object} Corresponding data color value according its key value.\n\t * @example\n\t * // Get current colors\n\t * chart.data.colors();\n\t * // --> {data1: \"#00c73c\", data2: \"#fa7171\"}\n\t *\n\t * // Update colors\n\t * chart.data.colors({\n\t * data1: \"#FFFFFF\",\n\t * data2: \"#000000\"\n\t * });\n\t */\n\tcolors: function(colors) {\n\t\treturn this.internal.updateDataAttributes(\"colors\", colors);\n\t},\n\n\t/**\n\t * Get and set axes of the data loaded in the chart.\n\t * - **NOTE:** If all data is related to one of the axes, the domain of axis without related data will be replaced by the domain from the axis with related data\n\t * @method data․axes\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} axes If this argument is given, the axes of data will be updated. If not given, the current axes will be returned. The format of this argument is the same as\n\t * @return {Object} Corresponding axes value for data, if specified axes value.\n\t * @example\n\t * // Get current axes\n\t * chart.data.axes();\n\t * // --> {data1: \"y\"}\n\t *\n\t * // Update axes\n\t * chart.data.axes({\n\t * data1: \"y\",\n\t * data2: \"y2\"\n\t * });\n\t */\n\taxes: function(axes) {\n\t\treturn this.internal.updateDataAttributes(\"axes\", axes);\n\t},\n\n\t/**\n\t * Get the minimum data value bound to the chart\n\t * @method data․min\n\t * @instance\n\t * @memberof Chart\n\t * @return {Array} Data objects\n\t * @example\n\t * // Get current axes\n\t * chart.data.min();\n\t * // --> [{x: 0, value: 30, id: \"data1\", index: 0}, ...]\n\t */\n\tmin: function() {\n\t\treturn this.internal.getMinMaxData().min;\n\t},\n\n\t/**\n\t * Get the maximum data value bound to the chart\n\t * @method data․max\n\t * @instance\n\t * @memberof Chart\n\t * @return {Array} Data objects\n\t * @example\n\t * // Get current axes\n\t * chart.data.max();\n\t * // --> [{x: 3, value: 400, id: \"data1\", index: 3}, ...]\n\t */\n\tmax: function() {\n\t\treturn this.internal.getMinMaxData().max;\n\t}\n});\n\nextend(Chart.prototype, {data});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Set specified category name on category axis.\n\t * @method category\n\t * @instance\n\t * @memberof Chart\n\t * @param {Number} i index of category to be changed\n\t * @param {String} category category value to be changed\n\t * @example\n\t * chart.category(2, \"Category 3\");\n\t */\n\tcategory(i, category) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (arguments.length > 1) {\n\t\t\tconfig.axis_x_categories[i] = category;\n\t\t\t$$.redraw();\n\t\t}\n\n\t\treturn config.axis_x_categories[i];\n\t},\n\n\t/**\n\t * Set category names on category axis.\n\t * @method categories\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array} categories This must be an array that includes category names in string. If category names are included in the date by data.x option, this is not required.\n\t * @example\n\t * chart.categories([\n\t * \"Category 1\", \"Category 2\", ...\n\t * ]);\n\t */\n\tcategories(categories) {\n\t\tconst $$ = this.internal;\n\t\tconst config = $$.config;\n\n\t\tif (!arguments.length) {\n\t\t\treturn config.axis_x_categories;\n\t\t}\n\n\t\tconfig.axis_x_categories = categories;\n\t\t$$.redraw();\n\n\t\treturn config.axis_x_categories;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Get the color\n\t * @method color\n\t * @instance\n\t * @memberof Chart\n\t * @param {String} id id to get the color\n\t * @example\n\t * chart.color(\"data1\");\n\t */\n\tcolor(id) {\n\t\treturn this.internal.color(id); // more patterns\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {isArray, isObject, extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Get and set x values for the chart.\n\t * @method x\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array} x If x is given, x values of every target will be updated. If no argument is given, current x values will be returned as an Object whose keys are the target ids.\n\t * @return {Object} xs\n\t * @example\n\t * // Get current x values\n\t * chart.x();\n\t *\n\t * // Update x values for all targets\n\t * chart.x([100, 200, 300, 400, ...]);\n\t */\n\tx(x) {\n\t\tconst $$ = this.internal;\n\t\tconst isCategorized = $$.isCustomX() && $$.isCategorized();\n\n\t\tif (isArray(x)) {\n\t\t\tif (isCategorized) {\n\t\t\t\t$$.api.categories(x);\n\t\t\t} else {\n\t\t\t\t$$.updateTargetX($$.data.targets, x);\n\n\t\t\t\t$$.redraw({\n\t\t\t\t\twithUpdateOrgXDomain: true,\n\t\t\t\t\twithUpdateXDomain: true\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn isCategorized ? $$.api.categories() : $$.data.xs;\n\t},\n\n\t/**\n\t * Get and set x values for the chart.\n\t * @method xs\n\t * @instance\n\t * @memberof Chart\n\t * @param {Array} xs If xs is given, specified target's x values will be updated. If no argument is given, current x values will be returned as an Object whose keys are the target ids.\n\t * @return {Object} xs\n\t * @example\n\t * // Get current x values\n\t * chart.xs();\n\t *\n\t * // Update x values for all targets\n\t * chart.xs({\n\t * data1: [10, 20, 30, 40, ...],\n\t * data2: [100, 200, 300, 400, ...]\n\t * });\n\t */\n\txs(xs) {\n\t\tconst $$ = this.internal;\n\n\t\tif (isObject(xs)) {\n\t\t\t$$.updateTargetXs($$.data.targets, xs);\n\n\t\t\t$$.redraw({\n\t\t\t\twithUpdateOrgXDomain: true,\n\t\t\t\twithUpdateXDomain: true\n\t\t\t});\n\t\t}\n\n\t\treturn $$.data.xs;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {isValue, isDefined, isObjectType, extend} from \"../internals/util\";\n\n/**\n * Set the min/max value\n * @param {Chart} $$\n * @param {String} type\n * @param {Object} value\n * @return {undefined}\n * @private\n */\nconst setMinMax = ($$, type, value) => {\n\tconst config = $$.config;\n\tconst axisX = `axis_x_${type}`;\n\tconst axisY = `axis_y_${type}`;\n\tconst axisY2 = `axis_y2_${type}`;\n\n\tif (isDefined(value)) {\n\t\tif (isObjectType(value)) {\n\t\t\tisValue(value.x) && (config[axisX] = value.x);\n\t\t\tisValue(value.y) && (config[axisY] = value.y);\n\t\t\tisValue(value.y2) && (config[axisY2] = value.y2);\n\t\t} else {\n\t\t\tconfig[axisY] = value;\n\t\t\tconfig[axisY2] = value;\n\t\t}\n\n\t\t$$.redraw({\n\t\t\twithUpdateOrgXDomain: true,\n\t\t\twithUpdateXDomain: true\n\t\t});\n\t}\n\n\treturn undefined;\n};\n\n/**\n * Get the min/max value\n * @param {Chart} $$\n * @param {String} type\n * @return {{x, y, y2}}\n * @private\n */\nconst getMinMax = ($$, type) => {\n\tconst config = $$.config;\n\n\treturn {\n\t\tx: config[`axis_x_${type}`],\n\t\ty: config[`axis_y_${type}`],\n\t\ty2: config[`axis_y2_${type}`]\n\t};\n};\n\n/**\n * Define axis\n * @ignore\n */\nconst axis = extend(() => {}, {\n\t/**\n\t * Get and set axis labels.\n\t * @method axis․labels\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} labels specified axis' label to be updated.\n\t * @example\n\t * // Update axis' label\n\t * chart.axis.labels({\n\t * x: \"New X Axis Label\",\n\t * y: \"New Y Axis Label\"\n\t * });\n\t */\n\tlabels: function(labels) {\n\t\tconst $$ = this.internal;\n\n\t\tif (arguments.length) {\n\t\t\tObject.keys(labels).forEach(axisId => {\n\t\t\t\t$$.axis.setLabelText(axisId, labels[axisId]);\n\t\t\t});\n\n\t\t\t$$.axis.updateLabels();\n\t\t}\n\t},\n\n\t/**\n\t * Get and set axis min value.\n\t * @method axis․min\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} min If min is given, specified axis' min value will be updated.<br>\n\t * If no argument is given, the min values set on generating option for each axis will be returned.\n\t * If not set any min values on generation, it will return `undefined`.\n\t * @example\n\t * // Update axis' min\n\t * chart.axis.min({\n\t * x: -10,\n\t * y: 1000,\n\t * y2: 100\n\t * });\n\t */\n\tmin: function(min) {\n\t\tconst $$ = this.internal;\n\n\t\treturn arguments.length ?\n\t\t\tsetMinMax($$, \"min\", min) :\n\t\t\tgetMinMax($$, \"min\");\n\t},\n\n\t/**\n\t * Get and set axis max value.\n\t * @method axis․max\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} max If max is given, specified axis' max value will be updated.<br>\n\t * If no argument is given, the max values set on generating option for each axis will be returned.\n\t * If not set any max values on generation, it will return `undefined`.\n\t * @example\n\t * // Update axis' label\n\t * chart.axis.max({\n\t * x: 100,\n\t * y: 1000,\n\t * y2: 10000\n\t * });\n\t */\n\tmax: function(max) {\n\t\tconst $$ = this.internal;\n\n\t\treturn arguments.length ?\n\t\t\tsetMinMax($$, \"max\", max) :\n\t\t\tgetMinMax($$, \"max\");\n\t},\n\n\t/**\n\t * Get and set axis min and max value.\n\t * @method axis․range\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} range If range is given, specified axis' min and max value will be updated. If no argument is given, the current min and max values for each axis will be returned.\n\t * @example\n\t * // Update axis' label\n\t * chart.axis.range({\n\t * min: {\n\t * x: -10,\n\t * y: -1000,\n\t * y2: -10000\n\t * },\n\t * max: {\n\t * x: 100,\n\t * y: 1000,\n\t * y2: 10000\n\t * },\n\t * });\n\t */\n\trange: function(range) {\n\t\tconst axis = this.axis;\n\n\t\tif (arguments.length) {\n\t\t\tisDefined(range.max) && axis.max(range.max);\n\t\t\tisDefined(range.min) && axis.min(range.min);\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmax: axis.max(),\n\t\t\t\tmin: axis.min()\n\t\t\t};\n\t\t}\n\n\t\treturn undefined;\n\t}\n});\n\nextend(Chart.prototype, {axis});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {extend} from \"../internals/util\";\n\n/**\n * Define legend\n * @ignore\n */\nconst legend = extend(() => {}, {\n\t/**\n\t * Show legend for each target.\n\t * @method legend․show\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} targetIds\n\t * - If targetIds is given, specified target's legend will be shown.\n\t * - If only one target is the candidate, String can be passed.\n\t * - If no argument is given, all of target's legend will be shown.\n\t * @example\n\t * // Show legend for data1.\n\t * chart.legend.show(\"data1\");\n\t *\n\t * // Show legend for data1 and data2.\n\t * chart.legend.show([\"data1\", \"data2\"]);\n\t *\n\t * // Show all legend.\n\t * chart.legend.show();\n\t */\n\tshow: function(targetIds) {\n\t\tconst $$ = this.internal;\n\n\t\t$$.showLegend($$.mapToTargetIds(targetIds));\n\t\t$$.updateAndRedraw({withLegend: true});\n\t},\n\n\t/**\n\t * Hide legend for each target.\n\t * @method legend․hide\n\t * @instance\n\t * @memberof Chart\n\t * @param {String|Array} targetIds\n\t * - If targetIds is given, specified target's legend will be hidden.\n\t * - If only one target is the candidate, String can be passed.\n\t * - If no argument is given, all of target's legend will be hidden.\n\t * @example\n\t * // Hide legend for data1.\n\t * chart.legend.hide(\"data1\");\n\t *\n\t * // Hide legend for data1 and data2.\n\t * chart.legend.hide([\"data1\", \"data2\"]);\n\t *\n\t * // Hide all legend.\n\t * chart.legend.hide();\n\t */\n\thide: function(targetIds) {\n\t\tconst $$ = this.internal;\n\n\t\t$$.hideLegend($$.mapToTargetIds(targetIds));\n\t\t$$.updateAndRedraw({withLegend: true});\n\t}\n});\n\nextend(Chart.prototype, {legend});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {window} from \"../internals/browser\";\nimport {notEmpty, isDefined, extend} from \"../internals/util\";\n\nextend(Chart.prototype, {\n\t/**\n\t * Resize the chart.\n\t * @method resize\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} size This argument should include width and height in pixels.\n\t * @example\n\t * // Resize to 640x480\n\t * chart.resize({\n\t * width: 640,\n\t * height: 480\n\t * });\n\t */\n\tresize(size) {\n\t\tconst $$ = this.internal;\n\t\tconst {config} = $$;\n\n\t\tif ($$.rendered) {\n\t\t\tconfig.size_width = size ? size.width : null;\n\t\t\tconfig.size_height = size ? size.height : null;\n\n\t\t\tthis.flush(false, true);\n\t\t\t$$.resizeFunction();\n\t\t}\n\t},\n\n\t/**\n\t * Force to redraw.\n\t * @method flush\n\t * @instance\n\t * @memberof Chart\n\t * @param {Boolean} [soft] For soft redraw.\n\t * @example\n\t * chart.flush();\n\t *\n\t * // for soft redraw\n\t * chart.flush(true);\n\t */\n\tflush(soft, _isFromResize) {\n\t\tconst $$ = this.internal;\n\n\n\t\tif ($$.rendered) {\n\t\t\t// reset possible zoom scale when is called from resize event\n\t\t\tif (_isFromResize) {\n\t\t\t\t$$.brush && $$.brush.updateResize();\n\t\t\t} else {\n\t\t\t\t// re-update config info\n\t\t\t\t$$.axis && $$.axis.setOrient();\n\t\t\t}\n\n\t\t\t$$.zoomScale = null;\n\n\t\t\tsoft ? $$.redraw({\n\t\t\t\twithTransform: true,\n\t\t\t\twithUpdateXDomain: true,\n\t\t\t\twithUpdateOrgXDomain: true,\n\t\t\t\twithLegend: true\n\t\t\t}) : $$.updateAndRedraw({\n\t\t\t\twithLegend: true,\n\t\t\t\twithTransition: false,\n\t\t\t\twithTransitionForTransform: false,\n\t\t\t});\n\t\t} else {\n\t\t\t$$.initToRender(true);\n\t\t}\n\t},\n\n\t/**\n\t * Reset the chart object and remove element and events completely.\n\t * @method destroy\n\t * @instance\n\t * @memberof Chart\n\t * @example\n\t * chart.destroy();\n\t */\n\tdestroy() {\n\t\tconst $$ = this.internal;\n\n\t\tif (notEmpty($$)) {\n\t\t\t$$.callPluginHook(\"$willDestroy\");\n\t\t\t$$.charts.splice($$.charts.indexOf(this), 1);\n\n\t\t\t// clear timers && pending transition\n\t\t\t$$.svg.select(\"*\").interrupt();\n\t\t\t$$.generateResize.timeout && window.clearTimeout($$.generateResize.timeout);\n\n\t\t\twindow.removeEventListener(\"resize\", $$.resizeFunction);\n\t\t\t$$.selectChart.classed(\"bb\", false).html(\"\");\n\n\t\t\t// releasing references\n\t\t\tObject.keys(this).forEach(key => {\n\t\t\t\tkey === \"internal\" && Object.keys($$).forEach(k => {\n\t\t\t\t\t$$[k] = null;\n\t\t\t\t});\n\n\t\t\t\tthis[key] = null;\n\t\t\t\tdelete this[key];\n\t\t\t});\n\t\t}\n\n\t\treturn null;\n\t},\n\n\t/**\n\t * Get or set single config option value.\n\t * @method config\n\t * @instance\n\t * @memberof Chart\n\t * @param {String} name The option key name.\n\t * @param {*} [value] The value accepted for indicated option.\n\t * @param {Boolean} [redraw] Set to redraw with the new option changes.\n\t * - **NOTE:** Doesn't guarantee work in all circumstances. It can be applied for limited options only.\n\t * @example\n\t * // Getter\n\t * chart.config(\"gauge.max\");\n\t *\n\t * // Setter\n\t * chart.config(\"gauge.max\", 100);\n\t *\n\t * // Setter & redraw with the new option\n\t * chart.config(\"gauge.max\", 100, true);\n\t */\n\tconfig(name, value, redraw) {\n\t\tconst $$ = this.internal;\n\t\tconst key = name && name.replace(/\\./g, \"_\");\n\t\tlet res;\n\n\t\tif (key in $$.config) {\n\t\t\tif (isDefined(value)) {\n\t\t\t\t$$.config[key] = value;\n\t\t\t\tres = value;\n\n\t\t\t\tredraw && this.flush();\n\t\t\t} else {\n\t\t\t\tres = $$.config[key];\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport Chart from \"../internals/Chart\";\nimport {isValue, isDefined, extend} from \"../internals/util\";\n\n/**\n * Define tooltip\n * @ignore\n */\nconst tooltip = extend(() => {}, {\n\t/**\n\t * Show tooltip\n\t * @method tooltip․show\n\t * @instance\n\t * @memberof Chart\n\t * @param {Object} args The object can consist with following members:<br>\n\t *\n\t * | Key | Type | Description |\n\t * | --- | --- | --- |\n\t * | index | Number | Determine focus by index |\n\t * | x | Number &vert; Date | Determine focus by x Axis index |\n\t * | mouse | Array | Determine x and y coordinate value relative the targeted '.bb-event-rect' x Axis.<br>It should be used along with `data`, `index` or `x` value. The default value is set as `[0,0]` |\n\t * | data | Object | When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is used or [tooltip.grouped](Options.html#.tooltip) set to 'false', `should be used giving this param`.<br><br>**Key:**<br>- x {Number &verbar; Date}: x Axis value<br>- index {Number}: x Axis index (useless for data.xs)<br>- id {String}: data id<br>- value {Number}: The corresponding value for tooltip. |\n\t *\n\t * @example\n\t * // show the 2nd x Axis coordinate tooltip\n\t * chart.tooltip.show({\n\t * index: 1\n\t * });\n\t *\n\t * // show tooltip for the 3rd x Axis in x:50 and y:100 coordinate of '.bb-event-rect' of the x Axis.\n\t * chart.tooltip.show({\n\t * x: 2,\n\t * mouse: [50, 100]\n\t * });\n\t *\n\t * // show tooltip for timeseries x axis\n\t * chart.tooltip.show({\n\t * x: new Date(\"2018-01-02 00:00\")\n\t * });\n\t *\n\t * // when data.xs is used\n\t * chart.tooltip.show({\n\t * data: {\n\t * x: 3, // x Axis value\n\t * id: \"data1\", // data id\n\t * value: 500 // data value\n\t * }\n\t * });\n\t *\n\t * // when data.xs isn't used, but tooltip.grouped=false is set\n\t * chart.tooltip.show({\n\t * data: {\n\t * index: 3, // or 'x' key value\n\t * id: \"data1\", // data id\n\t * value: 500 // data value\n\t * }\n\t * });\n\t */\n\tshow: function(args = {}) {\n\t\tconst $$ = this.internal;\n\t\tlet index;\n\t\tlet mouse;\n\n\t\t// determine mouse position on the chart\n\t\tif (args.mouse) {\n\t\t\tmouse = args.mouse;\n\t\t}\n\n\t\t// determine focus data\n\t\tif (args.data) {\n\t\t\tconst y = $$.getYScale(args.data.id)(args.data.value);\n\n\t\t\tif ($$.isMultipleX()) {\n\t\t\t\t// if multiple xs, target point will be determined by mouse\n\t\t\t\tmouse = [$$.x(args.data.x), y];\n\t\t\t} else {\n\t\t\t\tif (!$$.config.tooltip_grouped) {\n\t\t\t\t\tmouse = [0, y];\n\t\t\t\t}\n\n\t\t\t\tindex = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x);\n\t\t\t}\n\t\t} else if (isDefined(args.x)) {\n\t\t\tindex = $$.getIndexByX(args.x);\n\t\t} else if (isDefined(args.index)) {\n\t\t\tindex = args.index;\n\t\t}\n\n\t\t// emulate events to show\n\t\t($$.inputType === \"mouse\" ?\n\t\t\t[\"mouseover\", \"mousemove\"] : [\"touchstart\"]\n\t\t).forEach(eventName => {\n\t\t\t$$.dispatchEvent(eventName, index, mouse);\n\t\t});\n\t},\n\n\t/**\n\t * Hide tooltip\n\t * @method tooltip․hide\n\t * @instance\n\t * @memberof Chart\n\t */\n\thide: function() {\n\t\tconst $$ = this.internal;\n\n\t\t// reset last touch point index\n\t\t$$.inputType === \"touch\" && $$.callOverOutForTouch();\n\n\t\t$$.hideTooltip(true);\n\t\t$$.hideGridFocus();\n\t\t$$.unexpandCircles();\n\t\t$$.unexpandBars();\n\t}\n});\n\nextend(Chart.prototype, {tooltip});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard.js project is licensed under the MIT license\n */\nimport {namespaces as d3Namespaces} from \"d3-selection\";\nimport Chart from \"../internals/Chart\";\nimport {document} from \"../internals/browser\";\nimport {extend, isFunction, toArray, getCssRules} from \"../internals/util\";\n\n/**\n * Encode to base64\n * @param {String} str\n * @return {String}\n * @private\n * @see https://developer.mozilla.org/ko/docs/Web/API/WindowBase64/Base64_encoding_and_decoding\n */\nconst b64EncodeUnicode = str => btoa(\n\tencodeURIComponent(str)\n\t\t.replace(/%([0-9A-F]{2})/g, (match, p) => String.fromCharCode(`0x${p}`))\n);\n\n/**\n * Convert svg node to data url\n * @param {HTMLElement} node\n * @return {String}\n * @private\n */\nconst nodeToSvgDataUrl = (node, size) => {\n\tconst serializer = new XMLSerializer();\n\tconst clone = node.cloneNode(true);\n\tconst cssText = getCssRules(toArray(document.styleSheets))\n\t\t.filter(r => r.cssText)\n\t\t.map(r => r.cssText);\n\n\tclone.setAttribute(\"xmlns\", d3Namespaces.xhtml);\n\n\tconst nodeXml = serializer.serializeToString(clone);\n\n\t// escape css for XML\n\tconst style = document.createElement(\"style\");\n\n\tstyle.appendChild(document.createTextNode(cssText.join(\"\\n\")));\n\n\tconst styleXml = serializer.serializeToString(style);\n\n\t// foreignObject not supported in IE11 and below\n\t// https://msdn.microsoft.com/en-us/library/hh834675(v=vs.85).aspx\n\tconst dataStr = `<svg xmlns=\"${d3Namespaces.svg}\" width=\"${size.width}\" height=\"${size.height}\">\n\t\t\t<foreignObject width=\"100%\" height=\"100%\">\n\t\t\t\t${styleXml}\n\t\t\t\t${nodeXml.replace(/(url\\()[^#]+/g, \"$1\")}\n\t\t\t</foreignObject></svg>`\n\t\t.replace(\"/\\n/g\", \"%0A\");\n\n\treturn `data:image/svg+xml;base64,${b64EncodeUnicode(dataStr)}`;\n};\n\nextend(Chart.prototype, {\n\t/**\n\t * Export chart as an image.\n\t * - **NOTE:**\n\t * - IE11 and below not work properly due to the lack of the feature(<a href=\"https://msdn.microsoft.com/en-us/library/hh834675(v=vs.85).aspx\">foreignObject</a>) support\n\t * - The basic CSS file(ex. billboard.css) should be at same domain as API call context to get correct styled export image.\n\t * @method export\n\t * @instance\n\t * @memberof Chart\n\t * @param {String} [mimeType=image/png] The desired output image format. (ex. 'image/png' for png, 'image/jpeg' for jpeg format)\n\t * @param {Function} [callback] The callback to be invoked when export is ready.\n\t * @return {String} dataURI\n\t * @example\n\t * chart.export();\n\t * // --> \"data:image/svg+xml;base64,PHN...\"\n\t *\n\t * // Initialize the download automatically\n\t * chart.export(\"image/png\", dataUrl => {\n\t * const link = document.createElement(\"a\");\n\t *\n\t * link.download = `${Date.now()}.png`;\n\t * link.href = dataUrl;\n\t * link.innerHTML = \"Download chart as image\";\n\t *\n\t * document.body.appendChild(link);\n\t * });\n\t */\n\texport(mimeType, callback) {\n\t\tconst $$ = this.internal;\n\t\tconst size = {width: $$.currentWidth, height: $$.currentHeight};\n\t\tconst svgDataUrl = nodeToSvgDataUrl(this.element, size);\n\n\t\tif (isFunction(callback)) {\n\t\t\tconst img = new Image();\n\n\t\t\timg.crosssOrigin = \"Anonymous\";\n\t\t\timg.onload = () => {\n\t\t\t\tconst canvas = document.createElement(\"canvas\");\n\t\t\t\tconst ctx = canvas.getContext(\"2d\");\n\n\t\t\t\tcanvas.width = size.width;\n\t\t\t\tcanvas.height = size.height;\n\t\t\t\tctx.drawImage(img, 0, 0);\n\n\t\t\t\tcallback(canvas.toDataURL(mimeType));\n\t\t\t};\n\n\t\t\timg.src = svgDataUrl;\n\t\t}\n\n\t\treturn svgDataUrl;\n\t}\n});\n","/**\n * Copyright (c) 2017 ~ present NAVER Corp.\n * billboard project is licensed under the MIT license\n */\nimport Chart from \"./internals/Chart\";\nimport ChartInternal from \"./internals/ChartInternal\";\nimport Axis from \"./axis/Axis\";\nimport {isObject, mergeObj} from \"./internals/util\";\n\nimport \"./config/config\";\nimport \"./internals/scale\";\nimport \"./internals/domain\";\nimport \"./data/data\";\nimport \"./data/data.convert\";\nimport \"./data/data.load\";\nimport \"./internals/category\";\nimport \"./interactions/interaction\";\nimport \"./internals/size\";\nimport \"./shape/shape\";\nimport \"./shape/arc\";\nimport \"./shape/bar\";\nimport \"./shape/bubble\";\nimport \"./shape/line\";\nimport \"./shape/point\";\nimport \"./shape/radar\";\nimport \"./internals/text\";\nimport \"./internals/type\";\nimport \"./internals/grid\";\nimport \"./internals/tooltip\";\nimport \"./internals/legend\";\nimport \"./internals/title\";\nimport \"./internals/clip\";\nimport \"./internals/region\";\nimport \"./interactions/drag\";\nimport \"./internals/selection\";\nimport \"./interactions/subchart\";\nimport \"./interactions/zoom\";\nimport \"./internals/color\";\nimport \"./internals/format\";\nimport \"./internals/cache\";\nimport \"./internals/class\";\nimport \"./api/api.focus\";\nimport \"./api/api.show\";\nimport \"./api/api.zoom\";\nimport \"./api/api.load\";\nimport \"./api/api.flow\";\nimport \"./api/api.selection\";\nimport \"./api/api.transform\";\nimport \"./api/api.group\";\nimport \"./api/api.grid\";\nimport \"./api/api.region\";\nimport \"./api/api.data\";\nimport \"./api/api.category\";\nimport \"./api/api.color\";\nimport \"./api/api.x\";\nimport \"./api/api.axis\";\nimport \"./api/api.legend\";\nimport \"./api/api.chart\";\nimport \"./api/api.tooltip\";\nimport \"./api/api.export\";\n\nlet defaults = {};\n\n/**\n * @namespace bb\n * @version 1.12.1\n */\nconst bb = {\n\t/**\n\t * Version information\n\t * @property {String} version version\n\t * @example\n\t * bb.version; // \"1.0.0\"\n\t * @memberof bb\n\t */\n\tversion: \"1.12.1\",\n\n\t/**\n\t * Generate chart\n\t * @param {Options} options chart options\n\t * @memberof bb\n\t * @return {Chart}\n\t * @see {@link Options} for different generation options\n\t * @see {@link Chart} for different methods API\n\t * @example\n\t * <!-- chart holder -->\n\t * <div id=\"LineChart\"></div>\n\t * @example\n\t * // generate chart with options\n\t * var chart = bb.generate({\n\t * \"bindto\": \"#LineChart\"\n\t * \"data\": {\n\t * \"columns\": [\n\t * [\"data1\", 30, 200, 100, 400, 150, 250],\n\t * [\"data2\", 50, 20, 10, 40, 15, 25]\n\t * ]\n\t * }\n\t * });\n\t *\n\t * // call some API\n\t * // ex) get the data of 'data1'\n\t * chart.data(\"data1\");\n\t */\n\tgenerate(config) {\n\t\tconst options = mergeObj({}, defaults, config);\n\t\tconst inst = new Chart(options);\n\n\t\tinst.internal.charts = this.instance;\n\t\tthis.instance.push(inst);\n\n\t\treturn inst;\n\t},\n\n\t/**\n\t * Set or get global default options.\n\t * - **NOTE:**\n\t * - The options values settings are valid within page context only.\n\t * - If is called multiple times, will override the last value.\n\t * @param {Options} options chart options\n\t * @memberof bb\n\t * @return {Options}\n\t * @see {@link Options}\n\t * @example\n\t * // Set same option value as for `.generate()`\n\t * bb.defaults({\n\t * data: {\n\t * type: \"bar\"\n\t * }\n\t * });\n\t *\n\t * bb.defaults(); // {data:{type: \"bar\"}}\n\t *\n\t * // data.type defaults to 'bar'\n\t * var chart = bb.generate({ ... });\n\t */\n\tdefaults(options) {\n\t\tif (isObject(options)) {\n\t\t\tdefaults = options;\n\t\t}\n\n\t\treturn defaults;\n\t},\n\n\t/**\n\t * An array containing instance created\n\t * @property {Array} instance instance array\n\t * @example\n\t * // generate charts\n\t * var chart1 = bb.generate(...);\n\t * var chart2 = bb.generate(...);\n\t *\n\t * bb.instance; // [ chart1, chart2, ... ]\n\t * @memberof bb\n\t */\n\tinstance: [],\n\n\t/**\n\t * Namespace for plugins\n\t * @property {Object} plugin plugin namespace\n\t * @example\n\t * // Stanford diagram plugin\n\t * bb.plugin.stanford;\n\t * @memberof bb\n\t */\n\tplugin: {},\n\n\t/**\n\t * Internal chart object\n\t * @private\n\t */\n\tchart: {\n\t\tfn: Chart.prototype,\n\t\tinternal: {\n\t\t\tfn: ChartInternal.prototype,\n\t\t\taxis: {\n\t\t\t\tfn: Axis.prototype\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport {bb};\nexport default bb;\n"],"mappings":";;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AClFA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;ACdA;;;;;AAIA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA9FA;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;AACA;AACA;;ACFA;AACA;AACA;;ACFA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACdA;;;;;AAIA;;;;;;AAKA;AACA;AACA;AAAA;AAAA;AACA;AACA;AACA;AAGA;AAFA;AACA;AACA;;;;;;ACjBA;;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAMA;AAAA;AAAA;AAQA;AAAA;AAAA;AAQA;AAAA;AAAA;AAEA;AAAA;AAAA;AAIA;AACA;AAIA;AAFA;AAAA;AAGA;AASA;AAAA;AACA;AAGA;AACA;AAQA;AAAA;AAAA;AAUA;AAAA;AAAA;AACA;AAOA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAKA;AAGA;AAIA;AACA;AACA;AACA;AAGA;AACA;;;;;;;AADA;AAAA;AAAA;AAAA;AAAA;AACA;AASA;AACA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAJA;AAMA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAKA;AACA;AAAA;AAAA;AAAA;AADA;AAGA;AAGA;AAAA;AAAA;AAAA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A;AACA;AACA;AACA;AAEA;;;;;;;;AAOA;AAAA;AAEA;AAAA;AAFA;AAWA;AAAA;AAAA;AAAA;AAIA;AAAA;AACA;AAAA;AAEA;AAPA;AAAA;AACA;AAaA;AAdA;AAAA;AAmBA;AACA;AAOA;AACA;AAlCA;;;;;;;;AAoCA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;AADA;AA2BA;AAAA;AAEA;AAAA;AAAA;AAFA;AACA;AAIA;AACA;AAEA;AACA;AAAA;AAIA;AAKA;AAGA;AACA;AACA;AACA;AAnDA;;ACzDA;;;;AAIA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAMA;AACA;;;;;;;AAOA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA;AAAA;AAAA;AAOA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;AAsBA;AAKA;AACA;AACA;AACA;;;;;;;;;;;AAWA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AADA;AAFA;AAFA;AAvGA;AAJA;;;;;AAsHA;AACA;;;;A","sourceRoot":""}
\No newline at end of file