{"version":3,"file":null,"sources":["src/axis/c3.axis.js","src/axis/axis.js","src/axis/index.js","src/internals/class.js","src/internals/util.js","src/internals/arc.js","src/internals/cache.js","src/internals/category.js","src/internals/clip.js","src/internals/color.js","src/internals/config.js","src/internals/data.convert.js","src/internals/data.js","src/internals/data.load.js","src/internals/domain.js","src/internals/drag.js","src/internals/flow.js","src/internals/format.js","src/internals/grid.js","src/internals/interaction.js","src/internals/legend.js","src/internals/region.js","src/internals/scale.js","src/internals/selection.js","src/internals/shape.bar.js","src/internals/shape.js","src/internals/shape.line.js","src/internals/size.js","src/internals/subchart.js","src/internals/text.js","src/internals/title.js","src/internals/tooltip.js","src/internals/transform.js","src/internals/type.js","src/internals/ua.js","src/internals/zoom.js","src/internals/index.js","src/chart/api.axis.js","src/chart/api.category.js","src/chart/api.chart.js","src/chart/api.color.js","src/chart/api.data.js","src/chart/api.flow.js","src/chart/api.focus.js","src/chart/api.grid.js","src/chart/api.group.js","src/chart/api.legend.js","src/chart/api.load.js","src/chart/api.region.js","src/chart/api.selection.js","src/chart/api.show.js","src/chart/api.tooltip.js","src/chart/api.transform.js","src/chart/api.x.js","src/chart/api.zoom.js","src/chart/index.js","src/rollup.entry.js"],"sourcesContent":["import d3 from 'd3';\n\nlet tickTextCharSize;\nfunction c3_axis(params) {\n let scale = d3.scale.linear();\n let orient = 'bottom';\n const innerTickSize = 6;\n const tickPadding = 3;\n let tickValues = null;\n let tickFormat;\n let tickArguments;\n\n let tickOffset = 0;\n let tickCulling = true;\n let tickCentered;\n\n params = params || {};\n\n const outerTickSize = params.withOuterTick ? 6 : 0;\n\n function axisX(selection, x) {\n selection.attr('transform', d => 'translate(' + Math.ceil(x(d) + tickOffset) + ', 0)');\n }\n function axisY(selection, y) {\n selection.attr('transform', d => 'translate(0,' + Math.ceil(y(d)) + ')');\n }\n function scaleExtent(domain) {\n const start = domain[0];\n const stop = domain[domain.length - 1];\n return start < stop ? [start, stop] : [stop, start];\n }\n function generateTicks(scale) { // eslint-disable-line no-shadow\n let i;\n const ticks = [];\n if (scale.ticks) {\n return scale.ticks.apply(scale, tickArguments);\n }\n const domain = scale.domain();\n for (i = Math.ceil(domain[0]); i < domain[1]; i++) {\n ticks.push(i);\n }\n if (ticks.length > 0 && ticks[0] > 0) {\n ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));\n }\n return ticks;\n }\n function copyScale() {\n const newScale = scale.copy();\n let domain;\n if (params.isCategory) {\n domain = scale.domain();\n newScale.domain([domain[0], domain[1] - 1]);\n }\n return newScale;\n }\n function textFormatted(v) {\n const formatted = tickFormat ? tickFormat(v) : v;\n return typeof formatted !== 'undefined' ? formatted : '';\n }\n function getSizeFor1Char(tick) {\n if (tickTextCharSize) {\n return tickTextCharSize;\n }\n const size = {\n h: 11.5,\n w: 5.5,\n };\n tick.select('text').text(textFormatted).each(function (d) {\n let box = this.getBoundingClientRect(),\n text = textFormatted(d),\n h = box.height,\n w = text ? (box.width / text.length) : undefined;\n if (h && w) {\n size.h = h;\n size.w = w;\n }\n }).text('');\n tickTextCharSize = size;\n return size;\n }\n function transitionise(selection) {\n return params.withoutTransition ? selection : d3.transition(selection);\n }\n function axis(g) {\n g.each(function () {\n const g = axis.g = d3.select(this);\n\n let scale0 = this.__chart__ || scale,\n scale1 = this.__chart__ = copyScale();\n\n let ticks = tickValues || generateTicks(scale1),\n tick = g.selectAll('.tick').data(ticks, scale1),\n tickEnter = tick.enter().insert('g', '.domain').attr('class', 'tick').style('opacity', 1e-6),\n // MEMO: No exit transition. The reason is this transition affects max tick width\n // calculation because old tick will be included in the ticks.\n tickExit = tick.exit().remove(),\n tickUpdate = transitionise(tick).style('opacity', 1),\n tickTransform,\n tickX,\n tickY;\n\n let range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()),\n path = g.selectAll('.domain').data([0]),\n pathUpdate = (path.enter().append('path').attr('class', 'domain'), transitionise(path));\n tickEnter.append('line');\n tickEnter.append('text');\n\n let lineEnter = tickEnter.select('line'),\n lineUpdate = tickUpdate.select('line'),\n textEnter = tickEnter.select('text'),\n textUpdate = tickUpdate.select('text');\n\n if (params.isCategory) {\n tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);\n tickX = tickCentered ? 0 : tickOffset;\n tickY = tickCentered ? tickOffset : 0;\n } else {\n tickOffset = tickX = 0;\n }\n\n let text,\n tspan,\n sizeFor1Char = getSizeFor1Char(g.select('.tick')),\n counts = [];\n\n let tickLength = Math.max(innerTickSize, 0) + tickPadding,\n isVertical = orient === 'left' || orient === 'right';\n\n // this should be called only when category axis\n function splitTickText(d, maxWidth) {\n let tickText = textFormatted(d),\n subtext,\n spaceIndex,\n textWidth,\n splitted = [];\n\n if (Object.prototype.toString.call(tickText) === '[object Array]') {\n return tickText;\n }\n\n if (!maxWidth || maxWidth <= 0) {\n maxWidth = isVertical ? 95 :\n params.isCategory ?\n (Math.ceil(scale1(ticks[1]) - scale1(ticks[0])) - 12) : 110;\n }\n\n function split(splitted, text) {\n spaceIndex = undefined;\n for (let i = 1; i < text.length; i++) {\n if (text.charAt(i) === ' ') {\n spaceIndex = i;\n }\n subtext = text.substr(0, i + 1);\n textWidth = sizeFor1Char.w * subtext.length;\n // if text width gets over tick width, split by space index or crrent index\n if (maxWidth < textWidth) {\n return split(\n splitted.concat(text.substr(0, spaceIndex || i)),\n text.slice(spaceIndex ? spaceIndex + 1 : i)\n );\n }\n }\n return splitted.concat(text);\n }\n\n return split(splitted, tickText + '');\n }\n\n function tspanDy(d, i) {\n let dy = sizeFor1Char.h;\n if (i === 0) {\n if (orient === 'left' || orient === 'right') {\n dy = -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3);\n } else {\n dy = '.71em';\n }\n }\n return dy;\n }\n\n function tickSize(d) {\n const tickPosition = scale(d) + (tickCentered ? 0 : tickOffset);\n return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;\n }\n\n text = tick.select('text');\n tspan = text.selectAll('tspan')\n .data((d, i) => {\n const splitted = params.tickMultiline ?\n splitTickText(d, params.tickWidth) :\n [].concat(textFormatted(d));\n counts[i] = splitted.length;\n return splitted.map(s => ({ index: i, splitted: s }));\n });\n tspan.enter().append('tspan');\n tspan.exit().remove();\n tspan.text(d => d.splitted);\n\n const rotate = params.tickTextRotate;\n\n function textAnchorForText(rotate) {\n if (!rotate) {\n return 'middle';\n }\n return rotate > 0 ? 'start' : 'end';\n }\n function textTransform(rotate) {\n if (!rotate) {\n return '';\n }\n return 'rotate(' + rotate + ')';\n }\n function dxForText(rotate) {\n if (!rotate) {\n return 0;\n }\n return 8 * Math.sin(Math.PI * (rotate / 180));\n }\n function yForText(rotate) {\n if (!rotate) {\n return tickLength;\n }\n return 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1);\n }\n\n switch (orient) {\n case 'bottom':\n {\n tickTransform = axisX;\n lineEnter.attr('y2', innerTickSize);\n textEnter.attr('y', tickLength);\n lineUpdate.attr('x1', tickX).attr('x2', tickX).attr('y2', tickSize);\n textUpdate.attr('x', 0).attr('y', yForText(rotate))\n .style('text-anchor', textAnchorForText(rotate))\n .attr('transform', textTransform(rotate));\n tspan.attr('x', 0).attr('dy', tspanDy).attr('dx', dxForText(rotate));\n pathUpdate.attr('d', 'M' + range[0] + ',' + outerTickSize + 'V0H' + range[1] + 'V' + outerTickSize);\n break;\n }\n case 'top':\n {\n // TODO: rotated tick text\n tickTransform = axisX;\n lineEnter.attr('y2', -innerTickSize);\n textEnter.attr('y', -tickLength);\n lineUpdate.attr('x2', 0).attr('y2', -innerTickSize);\n textUpdate.attr('x', 0).attr('y', -tickLength);\n text.style('text-anchor', 'middle');\n tspan.attr('x', 0).attr('dy', '0em');\n pathUpdate.attr('d', 'M' + range[0] + ',' + -outerTickSize + 'V0H' + range[1] + 'V' + -outerTickSize);\n break;\n }\n case 'left':\n {\n tickTransform = axisY;\n lineEnter.attr('x2', -innerTickSize);\n textEnter.attr('x', -tickLength);\n lineUpdate.attr('x2', -innerTickSize).attr('y1', tickY).attr('y2', tickY);\n textUpdate.attr('x', -tickLength).attr('y', tickOffset);\n text.style('text-anchor', 'end');\n tspan.attr('x', -tickLength).attr('dy', tspanDy);\n pathUpdate.attr('d', 'M' + -outerTickSize + ',' + range[0] + 'H0V' + range[1] + 'H' + -outerTickSize);\n break;\n }\n case 'right':\n {\n tickTransform = axisY;\n lineEnter.attr('x2', innerTickSize);\n textEnter.attr('x', tickLength);\n lineUpdate.attr('x2', innerTickSize).attr('y2', 0);\n textUpdate.attr('x', tickLength).attr('y', 0);\n text.style('text-anchor', 'start');\n tspan.attr('x', tickLength).attr('dy', tspanDy);\n pathUpdate.attr('d', 'M' + outerTickSize + ',' + range[0] + 'H0V' + range[1] + 'H' + outerTickSize);\n break;\n }\n default:\n break;\n }\n if (scale1.rangeBand) {\n let x = scale1,\n dx = x.rangeBand() / 2;\n scale0 = scale1 = function (d) {\n return x(d) + dx;\n };\n } else if (scale0.rangeBand) {\n scale0 = scale1;\n } else {\n tickExit.call(tickTransform, scale1);\n }\n tickEnter.call(tickTransform, scale0);\n tickUpdate.call(tickTransform, scale1);\n });\n }\n axis.scale = function (x) {\n if (!arguments.length) { return scale; }\n scale = x;\n return axis;\n };\n axis.orient = function (x) {\n if (!arguments.length) { return orient; }\n orient = x in { top: 1, right: 1, bottom: 1, left: 1 } ? x + '' : 'bottom';\n return axis;\n };\n axis.tickFormat = function (format) {\n if (!arguments.length) { return tickFormat; }\n tickFormat = format;\n return axis;\n };\n axis.tickCentered = function (isCentered) {\n if (!arguments.length) { return tickCentered; }\n tickCentered = isCentered;\n return axis;\n };\n axis.tickOffset = function () {\n return tickOffset;\n };\n axis.tickInterval = function () {\n let interval,\n length;\n if (params.isCategory) {\n interval = tickOffset * 2;\n } else {\n length = axis.g.select('path.domain').node().getTotalLength() - outerTickSize * 2;\n interval = length / axis.g.selectAll('line').size();\n }\n return interval === Infinity ? 0 : interval;\n };\n axis.ticks = function (...args) {\n if (!arguments.length) { return tickArguments; }\n tickArguments = args;\n return axis;\n };\n axis.tickCulling = function (culling) {\n if (!arguments.length) { return tickCulling; }\n tickCulling = culling;\n return axis;\n };\n axis.tickValues = function (x) {\n if (typeof x === 'function') {\n tickValues = function () {\n return x(scale.domain());\n };\n } else {\n if (!arguments.length) { return tickValues; }\n tickValues = x;\n }\n return axis;\n };\n return axis;\n}\n\nexport default c3_axis;\n","import * as d3 from 'd3';\n\nimport {\n CLASS,\n isValue,\n isFunction,\n isString,\n isEmpty,\n} from '../internals/index';\n\nimport { inherit, API } from './index';\nimport c3_axis from './c3.axis';\n\nfunction Axis(owner) {\n API.call(this, owner);\n}\n\ninherit(API, Axis);\n\nAxis.prototype.init = function init() {\n const $$ = this.owner;\n const config = $$.config;\n const main = $$.main;\n $$.axes.x = main.append('g')\n .attr('class', CLASS.axis + ' ' + CLASS.axisX)\n .attr('clip-path', $$.clipPathForXAxis)\n .attr('transform', $$.getTranslate('x'))\n .style('visibility', config.axis_x_show ? 'visible' : 'hidden');\n $$.axes.x.append('text')\n .attr('class', CLASS.axisXLabel)\n .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')\n .style('text-anchor', this.textAnchorForXAxisLabel.bind(this));\n $$.axes.y = main.append('g')\n .attr('class', CLASS.axis + ' ' + CLASS.axisY)\n .attr('clip-path', config.axis_y_inner ? '' : $$.clipPathForYAxis)\n .attr('transform', $$.getTranslate('y'))\n .style('visibility', config.axis_y_show ? 'visible' : 'hidden');\n $$.axes.y.append('text')\n .attr('class', CLASS.axisYLabel)\n .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')\n .style('text-anchor', this.textAnchorForYAxisLabel.bind(this));\n\n $$.axes.y2 = main.append('g')\n .attr('class', CLASS.axis + ' ' + CLASS.axisY2)\n // clip-path?\n .attr('transform', $$.getTranslate('y2'))\n .style('visibility', config.axis_y2_show ? 'visible' : 'hidden');\n $$.axes.y2.append('text')\n .attr('class', CLASS.axisY2Label)\n .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')\n .style('text-anchor', this.textAnchorForY2AxisLabel.bind(this));\n};\nAxis.prototype.getXAxis = function getXAxis(\n scale,\n orient,\n tickFormat,\n tickValues,\n withOuterTick,\n withoutTransition,\n withoutRotateTickText) {\n const $$ = this.owner;\n const config = $$.config;\n const axisParams = {\n isCategory: $$.isCategorized(),\n withOuterTick,\n tickMultiline: config.axis_x_tick_multiline,\n tickWidth: config.axis_x_tick_width,\n tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,\n withoutTransition,\n };\n const axis = c3_axis(axisParams).scale(scale).orient(orient);\n\n if ($$.isTimeSeries() && tickValues && typeof tickValues !== 'function') {\n tickValues = tickValues.map(v => $$.parseDate(v));\n }\n\n // Set tick\n axis.tickFormat(tickFormat).tickValues(tickValues);\n if ($$.isCategorized()) {\n axis.tickCentered(config.axis_x_tick_centered);\n if (isEmpty(config.axis_x_tick_culling)) {\n config.axis_x_tick_culling = false;\n }\n }\n\n return axis;\n};\nAxis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {\n const $$ = this.owner;\n const config = $$.config;\n let tickValues;\n if (config.axis_x_tick_fit || config.axis_x_tick_count) {\n tickValues = this.generateTickValues(\n $$.mapTargetsToUniqueXs(targets),\n config.axis_x_tick_count,\n $$.isTimeSeries()\n );\n }\n if (axis) {\n axis.tickValues(tickValues);\n } else {\n $$.xAxis.tickValues(tickValues);\n $$.subXAxis.tickValues(tickValues);\n }\n return tickValues;\n};\nAxis.prototype.getYAxis = function getYAxis(scale,\n orient,\n tickFormat,\n tickValues,\n withOuterTick,\n withoutTransition,\n withoutRotateTickText) {\n const $$ = this.owner;\n const config = $$.config;\n const axisParams = {\n withOuterTick,\n withoutTransition,\n tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate,\n };\n const axis = c3_axis(axisParams).scale(scale).orient(orient).tickFormat(tickFormat);\n if ($$.isTimeSeriesY()) {\n axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);\n } else {\n axis.tickValues(tickValues);\n }\n return axis;\n};\nAxis.prototype.getId = function getId(id) {\n const config = this.owner.config;\n return id in config.data_axes ? config.data_axes[id] : 'y';\n};\nAxis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {\n const $$ = this.owner;\n const config = $$.config;\n let format = $$.isTimeSeries() ? // eslint-disable-line no-nested-ternary\n $$.defaultAxisTimeFormat :\n $$.isCategorized() ?\n $$.categoryName :\n function (v) { return v < 0 ? v.toFixed(0) : v; };\n if (config.axis_x_tick_format) {\n if (isFunction(config.axis_x_tick_format)) {\n format = config.axis_x_tick_format;\n } else if ($$.isTimeSeries()) {\n format = function (date) {\n return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : '';\n };\n }\n }\n return isFunction(format) ? function (v) { return format.call($$, v); } : format;\n};\nAxis.prototype.getTickValues = function getTickValues(tickValues, axis) {\n return tickValues ? tickValues : // eslint-disable-line no-nested-ternary,no-unneeded-ternary\n axis ? axis.tickValues() : undefined;\n};\nAxis.prototype.getXAxisTickValues = function getXAxisTickValues() {\n return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);\n};\nAxis.prototype.getYAxisTickValues = function getYAxisTickValues() {\n return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);\n};\nAxis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {\n return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);\n};\nAxis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {\n const $$ = this.owner;\n const config = $$.config;\n let option;\n if (axisId === 'y') {\n option = config.axis_y_label;\n } else if (axisId === 'y2') {\n option = config.axis_y2_label;\n } else if (axisId === 'x') {\n option = config.axis_x_label;\n }\n return option;\n};\nAxis.prototype.getLabelText = function getLabelText(axisId) {\n const option = this.getLabelOptionByAxisId(axisId);\n return isString(option) ? option : option ? option.text : null; // eslint-disable-line no-nested-ternary,max-len\n};\nAxis.prototype.setLabelText = function setLabelText(axisId, text) {\n const $$ = this.owner;\n const config = $$.config;\n const option = this.getLabelOptionByAxisId(axisId);\n if (isString(option)) {\n if (axisId === 'y') {\n config.axis_y_label = text;\n } else if (axisId === 'y2') {\n config.axis_y2_label = text;\n } else if (axisId === 'x') {\n config.axis_x_label = text;\n }\n } else if (option) {\n option.text = text;\n }\n};\nAxis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {\n const option = this.getLabelOptionByAxisId(axisId);\n const position = (option && typeof option === 'object' && option.position) ? option.position : defaultPosition;\n return {\n isInner: position.indexOf('inner') >= 0,\n isOuter: position.indexOf('outer') >= 0,\n isLeft: position.indexOf('left') >= 0,\n isCenter: position.indexOf('center') >= 0,\n isRight: position.indexOf('right') >= 0,\n isTop: position.indexOf('top') >= 0,\n isMiddle: position.indexOf('middle') >= 0,\n isBottom: position.indexOf('bottom') >= 0,\n };\n};\nAxis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {\n return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');\n};\nAxis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {\n return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');\n};\nAxis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {\n return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');\n};\nAxis.prototype.getLabelPositionById = function getLabelPositionById(id) {\n return id === 'y2' ? this.getY2AxisLabelPosition() :\n id === 'y' ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();\n};\nAxis.prototype.textForXAxisLabel = function textForXAxisLabel() {\n return this.getLabelText('x');\n};\nAxis.prototype.textForYAxisLabel = function textForYAxisLabel() {\n return this.getLabelText('y');\n};\nAxis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {\n return this.getLabelText('y2');\n};\nAxis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {\n const $$ = this.owner;\n if (forHorizontal) {\n return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;\n } else {\n return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;\n }\n};\nAxis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {\n if (forHorizontal) {\n return position.isLeft ? '0.5em' : position.isRight ? '-0.5em' : '0';\n } else {\n return position.isTop ? '-0.5em' : position.isBottom ? '0.5em' : '0';\n }\n};\nAxis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {\n if (forHorizontal) {\n return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';\n } else {\n return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';\n }\n};\nAxis.prototype.xForXAxisLabel = function xForXAxisLabel() {\n return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());\n};\nAxis.prototype.xForYAxisLabel = function xForYAxisLabel() {\n return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());\n};\nAxis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {\n return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());\n};\nAxis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {\n return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());\n};\nAxis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {\n return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());\n};\nAxis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {\n return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());\n};\nAxis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {\n const $$ = this.owner;\n const config = $$.config;\n const position = this.getXAxisLabelPosition();\n if (config.axis_rotated) {\n return position.isInner ? '1.2em' : -25 - this.getMaxTickWidth('x');\n } else {\n return position.isInner ? '-0.5em' : config.axis_x_height ? config.axis_x_height - 10 : '3em';\n }\n};\nAxis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {\n const $$ = this.owner;\n const position = this.getYAxisLabelPosition();\n if ($$.config.axis_rotated) {\n return position.isInner ? '-0.5em' : '3em';\n } else {\n return position.isInner ? '1.2em' : -10 - ($$.config.axis_y_inner ? 0 : (this.getMaxTickWidth('y') + 10));\n }\n};\nAxis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {\n const $$ = this.owner;\n const position = this.getY2AxisLabelPosition();\n if ($$.config.axis_rotated) {\n return position.isInner ? '1.2em' : '-2.2em';\n } else {\n return position.isInner ? '-0.5em' : 15 + ($$.config.axis_y2_inner ? 0 : (this.getMaxTickWidth('y2') + 15));\n }\n};\nAxis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {\n const $$ = this.owner;\n return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());\n};\nAxis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {\n const $$ = this.owner;\n return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());\n};\nAxis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {\n const $$ = this.owner;\n return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());\n};\nAxis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {\n const $$ = this.owner;\n const config = $$.config;\n let maxWidth = 0;\n let targetsToShow;\n let scale;\n let axis;\n let dummy;\n let svg;\n if (withoutRecompute && $$.currentMaxTickWidths[id]) {\n return $$.currentMaxTickWidths[id];\n }\n if ($$.svg) {\n targetsToShow = $$.filterTargetsToShow($$.data.targets);\n if (id === 'y') {\n scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));\n axis = this.getYAxis(\n scale,\n $$.yOrient,\n config.axis_y_tick_format,\n $$.yAxisTickValues,\n false,\n true,\n true\n );\n } else if (id === 'y2') {\n scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));\n axis = this.getYAxis(\n scale,\n $$.y2Orient,\n config.axis_y2_tick_format,\n $$.y2AxisTickValues,\n false,\n true,\n true\n );\n } else {\n scale = $$.x.copy().domain($$.getXDomain(targetsToShow));\n axis = this.getXAxis(\n scale,\n $$.xOrient,\n $$.xAxisTickFormat,\n $$.xAxisTickValues,\n false,\n true,\n true\n );\n this.updateXAxisTickValues(targetsToShow, axis);\n }\n dummy = $$.d3.select('body').append('div').classed('c3', true);\n svg = dummy.append('svg')\n .style('visibility', 'hidden')\n .style('position', 'fixed')\n .style('top', 0)\n .style('left', 0);\n svg.append('g').call(axis).each(function () {\n $$.d3.select(this).selectAll('text').each(function () {\n const box = this.getBoundingClientRect();\n if (maxWidth < box.width) { maxWidth = box.width; }\n });\n dummy.remove();\n });\n }\n $$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;\n return $$.currentMaxTickWidths[id];\n};\n\nAxis.prototype.updateLabels = function updateLabels(withTransition) {\n const $$ = this.owner;\n const axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel);\n const axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel);\n const axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);\n (withTransition ? axisXLabel.transition() : axisXLabel)\n .attr('x', this.xForXAxisLabel.bind(this))\n .attr('dx', this.dxForXAxisLabel.bind(this))\n .attr('dy', this.dyForXAxisLabel.bind(this))\n .text(this.textForXAxisLabel.bind(this));\n (withTransition ? axisYLabel.transition() : axisYLabel)\n .attr('x', this.xForYAxisLabel.bind(this))\n .attr('dx', this.dxForYAxisLabel.bind(this))\n .attr('dy', this.dyForYAxisLabel.bind(this))\n .text(this.textForYAxisLabel.bind(this));\n (withTransition ? axisY2Label.transition() : axisY2Label)\n .attr('x', this.xForY2AxisLabel.bind(this))\n .attr('dx', this.dxForY2AxisLabel.bind(this))\n .attr('dy', this.dyForY2AxisLabel.bind(this))\n .text(this.textForY2AxisLabel.bind(this));\n};\nAxis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {\n const p = typeof padding === 'number' ? padding : padding[key];\n if (!isValue(p)) {\n return defaultValue;\n }\n if (padding.unit === 'ratio') {\n return padding[key] * domainLength;\n }\n // assume padding is pixels if unit is not specified\n return this.convertPixelsToAxisPadding(p, domainLength);\n};\nAxis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) { // eslint-disable-line max-len\n const $$ = this.owner;\n const length = $$.config.axis_rotated ? $$.width : $$.height;\n return domainLength * (pixels / length);\n};\nAxis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {\n let tickValues = values;\n let targetCount;\n let start;\n let end;\n let count;\n let interval;\n let i;\n let tickValue;\n if (tickCount) {\n targetCount = isFunction(tickCount) ? tickCount() : tickCount;\n // compute ticks according to tickCount\n if (targetCount === 1) {\n tickValues = [values[0]];\n } else if (targetCount === 2) {\n tickValues = [values[0], values[values.length - 1]];\n } else if (targetCount > 2) {\n count = targetCount - 2;\n start = values[0];\n end = values[values.length - 1];\n interval = (end - start) / (count + 1);\n // re-construct unique values\n tickValues = [start];\n for (i = 0; i < count; i++) {\n tickValue = +start + interval * (i + 1);\n tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);\n }\n tickValues.push(end);\n }\n }\n if (!forTimeSeries) { tickValues = tickValues.sort((a, b) => a - b); }\n return tickValues;\n};\nAxis.prototype.generateTransitions = function generateTransitions(duration) {\n let $$ = this.owner;\n let axes = $$.axes;\n return {\n axisX: duration ? axes.x.transition().duration(duration) : axes.x,\n axisY: duration ? axes.y.transition().duration(duration) : axes.y,\n axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,\n axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx,\n };\n};\nAxis.prototype.redraw = function redraw(transitions, isHidden) {\n const $$ = this.owner;\n $$.axes.x.style('opacity', isHidden ? 0 : 1);\n $$.axes.y.style('opacity', isHidden ? 0 : 1);\n $$.axes.y2.style('opacity', isHidden ? 0 : 1);\n $$.axes.subx.style('opacity', isHidden ? 0 : 1);\n transitions.axisX.call($$.xAxis);\n transitions.axisY.call($$.yAxis);\n transitions.axisY2.call($$.y2Axis);\n transitions.axisSubX.call($$.subXAxis);\n};\n\nexport default Axis;\n","// import {\n// CLASS,\n// isValue,\n// isFunction,\n// isString,\n// isUndefined,\n// isDefined,\n// ceil10,\n// asHalfPixel,\n// diffDomain,\n// isEmpty,\n// notEmpty,\n// getOption,\n// hasValue,\n// sanitise,\n// getPathBox,\n// ChartInternal } from '../chartinternal';\n\nimport Axis from './axis';\n\nfunction API(owner) {\n this.owner = owner;\n}\n\n/* eslint-disable */\nfunction inherit(base, derived) {\n if (Object.create) {\n derived.prototype = Object.create(base.prototype);\n } else {\n const f = function f() {};\n f.prototype = base.prototype;\n derived.prototype = new f();\n }\n\n derived.prototype.constructor = derived;\n\n return derived;\n}\n/* eslint-enable */\n\nexport { API, inherit, Axis };\n","const CLASS = {\n target: 'c3-target',\n chart: 'c3-chart',\n chartLine: 'c3-chart-line',\n chartLines: 'c3-chart-lines',\n chartBar: 'c3-chart-bar',\n chartBars: 'c3-chart-bars',\n chartText: 'c3-chart-text',\n chartTexts: 'c3-chart-texts',\n chartArc: 'c3-chart-arc',\n chartArcs: 'c3-chart-arcs',\n chartArcsTitle: 'c3-chart-arcs-title',\n chartArcsBackground: 'c3-chart-arcs-background',\n chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',\n chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',\n chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',\n selectedCircle: 'c3-selected-circle',\n selectedCircles: 'c3-selected-circles',\n eventRect: 'c3-event-rect',\n eventRects: 'c3-event-rects',\n eventRectsSingle: 'c3-event-rects-single',\n eventRectsMultiple: 'c3-event-rects-multiple',\n zoomRect: 'c3-zoom-rect',\n brush: 'c3-brush',\n focused: 'c3-focused',\n defocused: 'c3-defocused',\n region: 'c3-region',\n regions: 'c3-regions',\n title: 'c3-title',\n tooltipContainer: 'c3-tooltip-container',\n tooltip: 'c3-tooltip',\n tooltipName: 'c3-tooltip-name',\n shape: 'c3-shape',\n shapes: 'c3-shapes',\n line: 'c3-line',\n lines: 'c3-lines',\n bar: 'c3-bar',\n bars: 'c3-bars',\n circle: 'c3-circle',\n circles: 'c3-circles',\n arc: 'c3-arc',\n arcs: 'c3-arcs',\n area: 'c3-area',\n areas: 'c3-areas',\n empty: 'c3-empty',\n text: 'c3-text',\n texts: 'c3-texts',\n gaugeValue: 'c3-gauge-value',\n grid: 'c3-grid',\n gridLines: 'c3-grid-lines',\n xgrid: 'c3-xgrid',\n xgrids: 'c3-xgrids',\n xgridLine: 'c3-xgrid-line',\n xgridLines: 'c3-xgrid-lines',\n xgridFocus: 'c3-xgrid-focus',\n ygrid: 'c3-ygrid',\n ygrids: 'c3-ygrids',\n ygridLine: 'c3-ygrid-line',\n ygridLines: 'c3-ygrid-lines',\n axis: 'c3-axis',\n axisX: 'c3-axis-x',\n axisXLabel: 'c3-axis-x-label',\n axisY: 'c3-axis-y',\n axisYLabel: 'c3-axis-y-label',\n axisY2: 'c3-axis-y2',\n axisY2Label: 'c3-axis-y2-label',\n legendBackground: 'c3-legend-background',\n legendItem: 'c3-legend-item',\n legendItemEvent: 'c3-legend-item-event',\n legendItemTile: 'c3-legend-item-tile',\n legendItemHidden: 'c3-legend-item-hidden',\n legendItemFocused: 'c3-legend-item-focused',\n dragarea: 'c3-dragarea',\n EXPANDED: '_expanded_',\n SELECTED: '_selected_',\n INCLUDED: '_included_',\n};\nconst generateClass = function (prefix, targetId) {\n return ' ' + prefix + ' ' + prefix + this.getTargetSelectorSuffix(targetId);\n};\nconst classText = function (d) {\n return this.generateClass(CLASS.text, d.index);\n};\nconst classTexts = function (d) {\n return this.generateClass(CLASS.texts, d.id);\n};\nconst classShape = function (d) {\n return this.generateClass(CLASS.shape, d.index);\n};\nconst classShapes = function (d) {\n return this.generateClass(CLASS.shapes, d.id);\n};\nconst classLine = function (d) {\n return this.classShape(d) + this.generateClass(CLASS.line, d.id);\n};\nconst classLines = function (d) {\n return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);\n};\nconst classCircle = function (d) {\n return this.classShape(d) + this.generateClass(CLASS.circle, d.index);\n};\nconst classCircles = function (d) {\n return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);\n};\nconst classBar = function (d) {\n return this.classShape(d) + this.generateClass(CLASS.bar, d.index);\n};\nconst classBars = function (d) {\n return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);\n};\nconst classArc = function (d) {\n return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);\n};\nconst classArcs = function (d) {\n return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);\n};\nconst classArea = function (d) {\n return this.classShape(d) + this.generateClass(CLASS.area, d.id);\n};\nconst classAreas = function (d) {\n return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);\n};\nconst classRegion = function (d, i) {\n return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d.class : '');\n};\nconst classEvent = function (d) {\n return this.generateClass(CLASS.eventRect, d.index);\n};\nconst classTarget = function (id) {\n const $$ = this;\n let additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';\n if (additionalClassSuffix) {\n additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;\n }\n return $$.generateClass(CLASS.target, id) + additionalClass;\n};\nconst classFocus = function (d) {\n return this.classFocused(d) + this.classDefocused(d);\n};\nconst classFocused = function (d) {\n return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');\n};\nconst classDefocused = function (d) {\n return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');\n};\nconst classChartText = function (d) {\n return CLASS.chartText + this.classTarget(d.id);\n};\nconst classChartLine = function (d) {\n return CLASS.chartLine + this.classTarget(d.id);\n};\nconst classChartBar = function (d) {\n return CLASS.chartBar + this.classTarget(d.id);\n};\nconst classChartArc = function (d) {\n return CLASS.chartArc + this.classTarget(d.data.id);\n};\nconst getTargetSelectorSuffix = function (targetId) {\n return targetId || targetId === 0 ? ('-' + targetId).replace(/[\\s?!@#$%^&*()_=+,.<>'\":;\\[\\]\\/|~`{}\\\\]/g, '-') : '';\n};\nconst selectorTarget = function (id, prefix) {\n return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);\n};\nconst selectorTargets = function (ids, prefix) {\n const $$ = this;\n ids = ids || [];\n return ids.length ? ids.map((id) => { return $$.selectorTarget(id, prefix); }) : null;\n};\nconst selectorLegend = function (id) {\n return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);\n};\nconst selectorLegends = function (ids) {\n const $$ = this;\n return ids && ids.length ? ids.map((id) => { return $$.selectorLegend(id); }) : null;\n};\n\nexport {\n CLASS,\n generateClass,\n classText,\n classTexts,\n classShape,\n classShapes,\n classLine,\n classLines,\n classCircle,\n classCircles,\n classBar,\n classBars,\n classArc,\n classArcs,\n classArea,\n classAreas,\n classRegion,\n classEvent,\n classTarget,\n classFocus,\n classFocused,\n classDefocused,\n classChartText,\n classChartLine,\n classChartBar,\n classChartArc,\n getTargetSelectorSuffix,\n selectorTarget,\n selectorTargets,\n selectorLegend,\n selectorLegends,\n};\n","const isValue = function (v) {\n return v || v === 0;\n },\n isFunction = function (o) {\n return typeof o === 'function';\n },\n isString = function (o) {\n return typeof o === 'string';\n },\n isUndefined = function (v) {\n return typeof v === 'undefined';\n },\n isDefined = function (v) {\n return typeof v !== 'undefined';\n },\n ceil10 = function (v) {\n return Math.ceil(v / 10) * 10;\n },\n asHalfPixel = function (n) {\n return Math.ceil(n) + 0.5;\n },\n diffDomain = function (d) {\n return d[1] - d[0];\n },\n isEmpty = function (o) {\n return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);\n },\n notEmpty = function (o) {\n isEmpty(o);\n },\n getOption = function (options, key, defaultValue) {\n return isDefined(options[key]) ? options[key] : defaultValue;\n },\n hasValue = function (dict, value) {\n let found = false;\n Object.keys(dict).forEach((key) => {\n if (dict[key] === value) { found = true; }\n });\n return found;\n },\n sanitise = function (str) {\n return typeof str === 'string' ? str.replace(//g, '>') : str;\n },\n getPathBox = function (path) {\n let box = path.getBoundingClientRect(),\n items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],\n minX = items[0].x, minY = Math.min(items[0].y, items[1].y);\n\n return { x: minX, y: minY, width: box.width, height: box.height };\n };\n\nexport {\n isValue,\n isFunction,\n isString,\n isUndefined,\n isDefined,\n ceil10,\n asHalfPixel,\n diffDomain,\n isEmpty,\n notEmpty,\n getOption,\n hasValue,\n sanitise,\n getPathBox,\n};\n","import { CLASS } from './class';\nimport { isFunction } from './util';\n\nconst initPie = function () {\n let $$ = this, d3 = $$.d3, config = $$.config;\n $$.pie = d3.layout.pie().value((d) => {\n return d.values.reduce((a, b) => { return a + b.value; }, 0);\n });\n if (!config.data_order) {\n $$.pie.sort(null);\n }\n};\n\nconst updateRadius = function () {\n let $$ = this, config = $$.config,\n w = config.gauge_width || config.donut_width;\n $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;\n $$.radius = $$.radiusExpanded * 0.95;\n $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;\n $$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;\n};\n\nconst updateArc = function () {\n const $$ = this;\n $$.svgArc = $$.getSvgArc();\n $$.svgArcExpanded = $$.getSvgArcExpanded();\n $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);\n};\n\nconst updateAngle = function (d) {\n let $$ = this, config = $$.config,\n found = false, index = 0,\n gMin, gMax, gTic, gValue;\n\n if (!config) {\n return null;\n }\n\n $$.pie($$.filterTargetsToShow($$.data.targets)).forEach((t) => {\n if (!found && t.data.id === d.data.id) {\n found = true;\n d = t;\n d.index = index;\n }\n index++;\n });\n if (isNaN(d.startAngle)) {\n d.startAngle = 0;\n }\n if (isNaN(d.endAngle)) {\n d.endAngle = d.startAngle;\n }\n if ($$.isGaugeType(d.data)) {\n gMin = config.gauge_min;\n gMax = config.gauge_max;\n gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);\n gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);\n d.startAngle = config.gauge_startingAngle;\n d.endAngle = d.startAngle + gTic * gValue;\n }\n return found ? d : null;\n};\n\nconst getSvgArc = function () {\n let $$ = this,\n arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius),\n newArc = function (d, withoutUpdate) {\n let updated;\n if (withoutUpdate) { return arc(d); } // for interpolate\n updated = $$.updateAngle(d);\n return updated ? arc(updated) : 'M 0 0';\n };\n // TODO: extends all function\n newArc.centroid = arc.centroid;\n return newArc;\n};\n\nconst getSvgArcExpanded = function (rate) {\n let $$ = this,\n arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius);\n return function (d) {\n const updated = $$.updateAngle(d);\n return updated ? arc(updated) : 'M 0 0';\n };\n};\n\nconst getArc = function (d, withoutUpdate, force) {\n return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : 'M 0 0';\n};\n\n\nconst transformForArcLabel = function (d) {\n let $$ = this, config = $$.config,\n updated = $$.updateAngle(d), c, x, y, h, ratio, translate = '';\n if (updated && !$$.hasType('gauge')) {\n c = this.svgArc.centroid(updated);\n x = isNaN(c[0]) ? 0 : c[0];\n y = isNaN(c[1]) ? 0 : c[1];\n h = Math.sqrt(x * x + y * y);\n if ($$.hasType('donut') && config.donut_label_ratio) {\n ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio;\n } else if ($$.hasType('pie') && config.pie_label_ratio) {\n ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio;\n } else {\n ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;\n }\n translate = 'translate(' + (x * ratio) + ',' + (y * ratio) + ')';\n }\n return translate;\n};\n\nconst getArcRatio = function (d) {\n let $$ = this,\n config = $$.config,\n whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);\n return d ? (d.endAngle - d.startAngle) / whole : null;\n};\n\nconst convertToArcData = function (d) {\n return this.addName({\n id: d.data.id,\n value: d.value,\n ratio: this.getArcRatio(d),\n index: d.index,\n });\n};\n\nconst textForArcLabel = function (d) {\n let $$ = this,\n updated, value, ratio, id, format;\n if (!$$.shouldShowArcLabel()) { return ''; }\n updated = $$.updateAngle(d);\n value = updated ? updated.value : null;\n ratio = $$.getArcRatio(updated);\n id = d.data.id;\n if (!$$.hasType('gauge') && !$$.meetsArcLabelThreshold(ratio)) { return ''; }\n format = $$.getArcLabelFormat();\n return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);\n};\n\nconst expandArc = function (targetIds) {\n let $$ = this, interval;\n\n // MEMO: avoid to cancel transition\n if ($$.transiting) {\n interval = window.setInterval(() => {\n if (!$$.transiting) {\n window.clearInterval(interval);\n if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {\n $$.expandArc(targetIds);\n }\n }\n }, 10);\n return;\n }\n\n targetIds = $$.mapToTargetIds(targetIds);\n\n $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).each(function (d) {\n if (!$$.shouldExpand(d.data.id)) { return; }\n $$.d3.select(this).selectAll('path')\n .transition().duration($$.expandDuration(d.data.id))\n .attr('d', $$.svgArcExpanded)\n .transition().duration($$.expandDuration(d.data.id) * 2)\n .attr('d', $$.svgArcExpandedSub)\n .each((d) => {\n if ($$.isDonutType(d.data)) {\n // callback here\n }\n });\n });\n};\n\nconst unexpandArc = function (targetIds) {\n const $$ = this;\n\n if ($$.transiting) { return; }\n\n targetIds = $$.mapToTargetIds(targetIds);\n\n $$.svg.selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc)).selectAll('path')\n .transition().duration((d) => {\n return $$.expandDuration(d.data.id);\n })\n .attr('d', $$.svgArc);\n $$.svg.selectAll('.' + CLASS.arc)\n .style('opacity', 1);\n};\n\nconst expandDuration = function (id) {\n let $$ = this, config = $$.config;\n\n if ($$.isDonutType(id)) {\n return config.donut_expand_duration;\n } else if ($$.isGaugeType(id)) {\n return config.gauge_expand_duration;\n } else if ($$.isPieType(id)) {\n return config.pie_expand_duration;\n } else {\n return 50;\n }\n};\n\nconst shouldExpand = function (id) {\n let $$ = this, config = $$.config;\n return ($$.isDonutType(id) && config.donut_expand) ||\n ($$.isGaugeType(id) && config.gauge_expand) ||\n ($$.isPieType(id) && config.pie_expand);\n};\n\nconst shouldShowArcLabel = function () {\n let $$ = this, config = $$.config, shouldShow = true;\n if ($$.hasType('donut')) {\n shouldShow = config.donut_label_show;\n } else if ($$.hasType('pie')) {\n shouldShow = config.pie_label_show;\n }\n // when gauge, always true\n return shouldShow;\n};\n\nconst meetsArcLabelThreshold = function (ratio) {\n let $$ = this, config = $$.config,\n threshold = $$.hasType('donut') ? config.donut_label_threshold : config.pie_label_threshold;\n return ratio >= threshold;\n};\n\nconst getArcLabelFormat = function () {\n let $$ = this, config = $$.config,\n format = config.pie_label_format;\n if ($$.hasType('gauge')) {\n format = config.gauge_label_format;\n } else if ($$.hasType('donut')) {\n format = config.donut_label_format;\n }\n return format;\n};\n\nconst getArcTitle = function () {\n const $$ = this;\n return $$.hasType('donut') ? $$.config.donut_title : '';\n};\n\nconst updateTargetsForArc = function (targets) {\n let $$ = this, main = $$.main,\n mainPieUpdate, mainPieEnter,\n classChartArc = $$.classChartArc.bind($$),\n classArcs = $$.classArcs.bind($$),\n classFocus = $$.classFocus.bind($$);\n mainPieUpdate = main.select('.' + CLASS.chartArcs).selectAll('.' + CLASS.chartArc)\n .data($$.pie(targets))\n .attr('class', (d) => { return classChartArc(d) + classFocus(d.data); });\n mainPieEnter = mainPieUpdate.enter().append('g')\n .attr('class', classChartArc);\n mainPieEnter.append('g')\n .attr('class', classArcs);\n mainPieEnter.append('text')\n .attr('dy', $$.hasType('gauge') ? '-.1em' : '.35em')\n .style('opacity', 0)\n .style('text-anchor', 'middle')\n .style('pointer-events', 'none');\n // MEMO: can not keep same color..., but not bad to update color in redraw\n // mainPieUpdate.exit().remove();\n};\n\nconst initArc = function () {\n const $$ = this;\n $$.arcs = $$.main.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartArcs)\n .attr('transform', $$.getTranslate('arc'));\n $$.arcs.append('text')\n .attr('class', CLASS.chartArcsTitle)\n .style('text-anchor', 'middle')\n .text($$.getArcTitle());\n};\n\nconst redrawArc = function (duration, durationForExit, withTransform) {\n let $$ = this, d3 = $$.d3, config = $$.config, main = $$.main,\n mainArc;\n mainArc = main.selectAll('.' + CLASS.arcs).selectAll('.' + CLASS.arc)\n .data($$.arcData.bind($$));\n mainArc.enter().append('path')\n .attr('class', $$.classArc.bind($$))\n .style('fill', (d) => { return $$.color(d.data); })\n .style('cursor', (d) => { return config.interaction_enabled && config.data_selection_isselectable(d) ? 'pointer' : null; })\n .style('opacity', 0)\n .each(function (d) {\n if ($$.isGaugeType(d.data)) {\n d.startAngle = d.endAngle = config.gauge_startingAngle;\n }\n this._current = d;\n });\n mainArc\n .attr('transform', (d) => { return !$$.isGaugeType(d.data) && withTransform ? 'scale(0)' : ''; })\n .style('opacity', function (d) { return d === this._current ? 0 : 1; })\n .on('mouseover', config.interaction_enabled ? function (d) {\n let updated, arcData;\n if ($$.transiting) { // skip while transiting\n return;\n }\n updated = $$.updateAngle(d);\n if (updated) {\n arcData = $$.convertToArcData(updated);\n // transitions\n $$.expandArc(updated.data.id);\n $$.api.focus(updated.data.id);\n $$.toggleFocusLegend(updated.data.id, true);\n $$.config.data_onmouseover(arcData, this);\n }\n } : null)\n .on('mousemove', config.interaction_enabled ? function (d) {\n let updated = $$.updateAngle(d), arcData, selectedData;\n if (updated) {\n arcData = $$.convertToArcData(updated),\n selectedData = [arcData];\n $$.showTooltip(selectedData, this);\n }\n } : null)\n .on('mouseout', config.interaction_enabled ? function (d) {\n let updated, arcData;\n if ($$.transiting) { // skip while transiting\n return;\n }\n updated = $$.updateAngle(d);\n if (updated) {\n arcData = $$.convertToArcData(updated);\n // transitions\n $$.unexpandArc(updated.data.id);\n $$.api.revert();\n $$.revertLegend();\n $$.hideTooltip();\n $$.config.data_onmouseout(arcData, this);\n }\n } : null)\n .on('click', config.interaction_enabled ? function (d, i) {\n let updated = $$.updateAngle(d), arcData;\n if (updated) {\n arcData = $$.convertToArcData(updated);\n if ($$.toggleShape) {\n $$.toggleShape(this, arcData, i);\n }\n $$.config.data_onclick.call($$.api, arcData, this);\n }\n } : null)\n .each(() => { $$.transiting = true; })\n .transition().duration(duration)\n .attrTween('d', function (d) {\n let updated = $$.updateAngle(d), interpolate;\n if (!updated) {\n return function () { return 'M 0 0'; };\n }\n // if (this._current === d) {\n // this._current = {\n // startAngle: Math.PI*2,\n // endAngle: Math.PI*2,\n // };\n // }\n if (isNaN(this._current.startAngle)) {\n this._current.startAngle = 0;\n }\n if (isNaN(this._current.endAngle)) {\n this._current.endAngle = this._current.startAngle;\n }\n interpolate = d3.interpolate(this._current, updated);\n this._current = interpolate(0);\n return function (t) {\n const interpolated = interpolate(t);\n interpolated.data = d.data; // data.id will be updated by interporator\n return $$.getArc(interpolated, true);\n };\n })\n .attr('transform', withTransform ? 'scale(1)' : '')\n .style('fill', (d) => {\n return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);\n }) // Where gauge reading color would receive customization.\n .style('opacity', 1)\n .call($$.endall, () => {\n $$.transiting = false;\n });\n mainArc.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n main.selectAll('.' + CLASS.chartArc).select('text')\n .style('opacity', 0)\n .attr('class', (d) => { return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''; })\n .text($$.textForArcLabel.bind($$))\n .attr('transform', $$.transformForArcLabel.bind($$))\n .style('font-size', (d) => { return $$.isGaugeType(d.data) ? Math.round($$.radius / 5) + 'px' : ''; })\n .transition().duration(duration)\n .style('opacity', (d) => { return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0; });\n main.select('.' + CLASS.chartArcsTitle)\n .style('opacity', $$.hasType('donut') || $$.hasType('gauge') ? 1 : 0);\n\n if ($$.hasType('gauge')) {\n $$.arcs.select('.' + CLASS.chartArcsBackground)\n .attr('d', () => {\n const d = {\n data: [{ value: config.gauge_max }],\n startAngle: config.gauge_startingAngle,\n endAngle: -1 * config.gauge_startingAngle,\n };\n return $$.getArc(d, true, true);\n });\n $$.arcs.select('.' + CLASS.chartArcsGaugeUnit)\n .attr('dy', '.75em')\n .text(config.gauge_label_show ? config.gauge_units : '');\n $$.arcs.select('.' + CLASS.chartArcsGaugeMin)\n .attr('dx', -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + 'px')\n .attr('dy', '1.2em')\n .text(config.gauge_label_show ? config.gauge_min : '');\n $$.arcs.select('.' + CLASS.chartArcsGaugeMax)\n .attr('dx', $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + 'px')\n .attr('dy', '1.2em')\n .text(config.gauge_label_show ? config.gauge_max : '');\n }\n};\nconst initGauge = function () {\n const arcs = this.arcs;\n if (this.hasType('gauge')) {\n arcs.append('path')\n .attr('class', CLASS.chartArcsBackground);\n arcs.append('text')\n .attr('class', CLASS.chartArcsGaugeUnit)\n .style('text-anchor', 'middle')\n .style('pointer-events', 'none');\n arcs.append('text')\n .attr('class', CLASS.chartArcsGaugeMin)\n .style('text-anchor', 'middle')\n .style('pointer-events', 'none');\n arcs.append('text')\n .attr('class', CLASS.chartArcsGaugeMax)\n .style('text-anchor', 'middle')\n .style('pointer-events', 'none');\n }\n};\nconst getGaugeLabelHeight = function () {\n return this.config.gauge_label_show ? 20 : 0;\n};\n\nexport {\n initPie,\n updateRadius,\n updateArc,\n updateAngle,\n getSvgArc,\n getSvgArcExpanded,\n getArc,\n transformForArcLabel,\n getArcRatio,\n convertToArcData,\n textForArcLabel,\n expandArc,\n unexpandArc,\n expandDuration,\n shouldExpand,\n shouldShowArcLabel,\n meetsArcLabelThreshold,\n getArcLabelFormat,\n getArcTitle,\n updateTargetsForArc,\n initArc,\n redrawArc,\n initGauge,\n getGaugeLabelHeight,\n};\n","const hasCaches = function (ids) {\n for (let i = 0; i < ids.length; i++) {\n if (!(ids[i] in this.cache)) { return false; }\n }\n return true;\n};\n\nconst addCache = function (id, target) {\n this.cache[id] = this.cloneTarget(target);\n};\n\nconst getCaches = function (ids) {\n let targets = [], i;\n for (i = 0; i < ids.length; i++) {\n if (ids[i] in this.cache) { targets.push(this.cloneTarget(this.cache[ids[i]])); }\n }\n return targets;\n};\n\nexport {\n hasCaches,\n addCache,\n getCaches,\n};\n","const categoryName = function (i) {\n const config = this.config;\n return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;\n};\n\nexport { categoryName };\n","const getClipPath = function (id) {\n const isIE9 = window.navigator.appVersion.toLowerCase().indexOf('msie 9.') >= 0;\n return 'url(' + (isIE9 ? '' : document.URL.split('#')[0]) + '#' + id + ')';\n};\nconst appendClip = function (parent, id) {\n return parent.append('clipPath').attr('id', id).append('rect');\n};\nconst getAxisClipX = function (forHorizontal) {\n // axis line width + padding for left\n const left = Math.max(30, this.margin.left);\n return forHorizontal ? -(1 + left) : -(left - 1);\n};\nconst getAxisClipY = function (forHorizontal) {\n return forHorizontal ? -20 : -this.margin.top;\n};\nconst getXAxisClipX = function () {\n const $$ = this;\n return $$.getAxisClipX(!$$.config.axis_rotated);\n};\nconst getXAxisClipY = function () {\n const $$ = this;\n return $$.getAxisClipY(!$$.config.axis_rotated);\n};\nconst getYAxisClipX = function () {\n const $$ = this;\n return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);\n};\nconst getYAxisClipY = function () {\n const $$ = this;\n return $$.getAxisClipY($$.config.axis_rotated);\n};\nconst getAxisClipWidth = function (forHorizontal) {\n let $$ = this,\n left = Math.max(30, $$.margin.left),\n right = Math.max(30, $$.margin.right);\n // width + axis line width + padding for left/right\n return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;\n};\nconst getAxisClipHeight = function (forHorizontal) {\n // less than 20 is not enough to show the axis label 'outer' without legend\n return (forHorizontal ? this.margin.bottom : (this.margin.top + this.height)) + 20;\n};\nconst getXAxisClipWidth = function () {\n const $$ = this;\n return $$.getAxisClipWidth(!$$.config.axis_rotated);\n};\nconst getXAxisClipHeight = function () {\n const $$ = this;\n return $$.getAxisClipHeight(!$$.config.axis_rotated);\n};\nconst getYAxisClipWidth = function () {\n const $$ = this;\n return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);\n};\nconst getYAxisClipHeight = function () {\n const $$ = this;\n return $$.getAxisClipHeight($$.config.axis_rotated);\n};\n\nexport {\n getClipPath,\n appendClip,\n getAxisClipX,\n getAxisClipY,\n getXAxisClipX,\n getXAxisClipY,\n getYAxisClipX,\n getYAxisClipY,\n getAxisClipWidth,\n getAxisClipHeight,\n getXAxisClipWidth,\n getXAxisClipHeight,\n getYAxisClipWidth,\n getYAxisClipHeight,\n};\n","import {\n notEmpty,\n} from './util';\n\nconst generateColor = function () {\n let $$ = this, config = $$.config, d3 = $$.d3,\n colors = config.data_colors,\n pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(),\n callback = config.data_color,\n ids = [];\n\n return function (d) {\n let id = d.id || (d.data && d.data.id) || d, color;\n\n // if callback function is provided\n if (colors[id] instanceof Function) {\n color = colors[id](d);\n }\n // if specified, choose that color\n else if (colors[id]) {\n color = colors[id];\n }\n // if not specified, choose from pattern\n else {\n if (ids.indexOf(id) < 0) { ids.push(id); }\n color = pattern[ids.indexOf(id) % pattern.length];\n colors[id] = color;\n }\n return callback instanceof Function ? callback(color, d) : color;\n };\n};\nconst generateLevelColor = function () {\n let $$ = this, config = $$.config,\n colors = config.color_pattern,\n threshold = config.color_threshold,\n asValue = threshold.unit === 'value',\n values = threshold.values && threshold.values.length ? threshold.values : [],\n max = threshold.max || 100;\n return notEmpty(config.color_threshold) ? function (value) {\n let i, v, color = colors[colors.length - 1];\n for (i = 0; i < values.length; i++) {\n v = asValue ? value : (value * 100 / max);\n if (v < values[i]) {\n color = colors[i];\n break;\n }\n }\n return color;\n } : null;\n};\n\nexport {\n generateColor,\n generateLevelColor\n};\n","import { isDefined } from './util';\n\nconst getDefaultConfig = function () {\n const config = {\n bindto: '#chart',\n svg_classname: undefined,\n size_width: undefined,\n size_height: undefined,\n padding_left: undefined,\n padding_right: undefined,\n padding_top: undefined,\n padding_bottom: undefined,\n resize_auto: true,\n zoom_enabled: false,\n zoom_extent: undefined,\n zoom_privileged: false,\n zoom_rescale: false,\n zoom_onzoom() {},\n zoom_onzoomstart() {},\n zoom_onzoomend() {},\n zoom_x_min: undefined,\n zoom_x_max: undefined,\n interaction_brighten: true,\n interaction_enabled: true,\n onmouseover() {},\n onmouseout() {},\n onresize() {},\n onresized() {},\n oninit() {},\n onrendered() {},\n transition_duration: 350,\n data_x: undefined,\n data_xs: {},\n data_xFormat: '%Y-%m-%d',\n data_xLocaltime: true,\n data_xSort: true,\n data_idConverter(id) { return id; },\n data_names: {},\n data_classes: {},\n data_groups: [],\n data_axes: {},\n data_type: undefined,\n data_types: {},\n data_labels: {},\n data_order: 'desc',\n data_regions: {},\n data_color: undefined,\n data_colors: {},\n data_hide: false,\n data_filter: undefined,\n data_selection_enabled: false,\n data_selection_grouped: false,\n data_selection_isselectable() { return true; },\n data_selection_multiple: true,\n data_selection_draggable: false,\n data_onclick() {},\n data_onmouseover() {},\n data_onmouseout() {},\n data_onselected() {},\n data_onunselected() {},\n data_url: undefined,\n data_headers: undefined,\n data_json: undefined,\n data_rows: undefined,\n data_columns: undefined,\n data_mimeType: undefined,\n data_keys: undefined,\n // configuration for no plot-able data supplied.\n data_empty_label_text: '',\n // subchart\n subchart_show: false,\n subchart_size_height: 60,\n subchart_axis_x_show: true,\n subchart_onbrush() {},\n // color\n color_pattern: [],\n color_threshold: {},\n // legend\n legend_show: true,\n legend_hide: false,\n legend_position: 'bottom',\n legend_inset_anchor: 'top-left',\n legend_inset_x: 10,\n legend_inset_y: 0,\n legend_inset_step: undefined,\n legend_item_onclick: undefined,\n legend_item_onmouseover: undefined,\n legend_item_onmouseout: undefined,\n legend_equally: false,\n legend_padding: 0,\n legend_item_tile_width: 10,\n legend_item_tile_height: 10,\n // axis\n axis_rotated: false,\n axis_x_show: true,\n axis_x_type: 'indexed',\n axis_x_localtime: true,\n axis_x_categories: [],\n axis_x_tick_centered: false,\n axis_x_tick_format: undefined,\n axis_x_tick_culling: {},\n axis_x_tick_culling_max: 10,\n axis_x_tick_count: undefined,\n axis_x_tick_fit: true,\n axis_x_tick_values: null,\n axis_x_tick_rotate: 0,\n axis_x_tick_outer: true,\n axis_x_tick_multiline: true,\n axis_x_tick_width: null,\n axis_x_max: undefined,\n axis_x_min: undefined,\n axis_x_padding: {},\n axis_x_height: undefined,\n axis_x_extent: undefined,\n axis_x_label: {},\n axis_y_show: true,\n axis_y_type: undefined,\n axis_y_max: undefined,\n axis_y_min: undefined,\n axis_y_inverted: false,\n axis_y_center: undefined,\n axis_y_inner: undefined,\n axis_y_label: {},\n axis_y_tick_format: undefined,\n axis_y_tick_outer: true,\n axis_y_tick_values: null,\n axis_y_tick_rotate: 0,\n axis_y_tick_count: undefined,\n axis_y_tick_time_value: undefined,\n axis_y_tick_time_interval: undefined,\n axis_y_padding: {},\n axis_y_default: undefined,\n axis_y2_show: false,\n axis_y2_max: undefined,\n axis_y2_min: undefined,\n axis_y2_inverted: false,\n axis_y2_center: undefined,\n axis_y2_inner: undefined,\n axis_y2_label: {},\n axis_y2_tick_format: undefined,\n axis_y2_tick_outer: true,\n axis_y2_tick_values: null,\n axis_y2_tick_count: undefined,\n axis_y2_padding: {},\n axis_y2_default: undefined,\n // grid\n grid_x_show: false,\n grid_x_type: 'tick',\n grid_x_lines: [],\n grid_y_show: false,\n // not used\n // grid_y_type: 'tick',\n grid_y_lines: [],\n grid_y_ticks: 10,\n grid_focus_show: true,\n grid_lines_front: true,\n // point - point of each data\n point_show: true,\n point_r: 2.5,\n point_sensitivity: 10,\n point_focus_expand_enabled: true,\n point_focus_expand_r: undefined,\n point_select_r: undefined,\n // line\n line_connectNull: false,\n line_step_type: 'step',\n // bar\n bar_width: undefined,\n bar_width_ratio: 0.6,\n bar_width_max: undefined,\n bar_zerobased: true,\n // area\n area_zerobased: true,\n area_above: false,\n // pie\n pie_label_show: true,\n pie_label_format: undefined,\n pie_label_threshold: 0.05,\n pie_label_ratio: undefined,\n pie_expand: {},\n pie_expand_duration: 50,\n // gauge\n gauge_fullCircle: false,\n gauge_label_show: true,\n gauge_label_format: undefined,\n gauge_min: 0,\n gauge_max: 100,\n gauge_startingAngle: -1 * Math.PI / 2,\n gauge_units: undefined,\n gauge_width: undefined,\n gauge_expand: {},\n gauge_expand_duration: 50,\n // donut\n donut_label_show: true,\n donut_label_format: undefined,\n donut_label_threshold: 0.05,\n donut_label_ratio: undefined,\n donut_width: undefined,\n donut_title: '',\n donut_expand: {},\n donut_expand_duration: 50,\n // spline\n spline_interpolation_type: 'cardinal',\n // region - region to change style\n regions: [],\n // tooltip - show when mouseover on each data\n tooltip_show: true,\n tooltip_grouped: true,\n tooltip_format_title: undefined,\n tooltip_format_name: undefined,\n tooltip_format_value: undefined,\n tooltip_position: undefined,\n tooltip_contents(d, defaultTitleFormat, defaultValueFormat, color) {\n return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : '';\n },\n tooltip_init_show: false,\n tooltip_init_x: 0,\n tooltip_init_position: { top: '0px', left: '50px' },\n tooltip_onshow() {},\n tooltip_onhide() {},\n // title\n title_text: undefined,\n title_padding: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n },\n title_position: 'top-center',\n // TouchEvent configuration\n touch_tap_radius: 20, // touch movement must be less than this to be a 'tap'\n touch_tap_delay: 500, //clicks are suppressed for this many ms after a tap\n };\n\n Object.keys(this.additionalConfig).forEach(function (key) {\n config[key] = this.additionalConfig[key];\n }, this);\n\n return config;\n};\nconst additionalConfig = {};\n\nconst loadConfig = function (config) {\n let this_config = this.config, target, keys, read;\n function find() {\n const key = keys.shift();\n// console.log(\"key =>\", key, \", target =>\", target);\n if (key && target && typeof target === 'object' && key in target) {\n target = target[key];\n return find();\n }\n else if (!key) {\n return target;\n }\n else {\n return undefined;\n }\n }\n Object.keys(this_config).forEach((key) => {\n target = config;\n keys = key.split('_');\n read = find();\n// console.log(\"CONFIG : \", key, read);\n if (isDefined(read)) {\n this_config[key] = read;\n }\n });\n};\n\nexport {\n getDefaultConfig,\n additionalConfig,\n loadConfig,\n};\n","import {\n isUndefined,\n isValue,\n notEmpty,\n isDefined,\n} from './util';\n\nconst convertUrlToData = function (url, mimeType, headers, keys, done) {\n let $$ = this, type = mimeType ? mimeType : 'csv';\n const req = $$.d3.xhr(url);\n if (headers) {\n Object.keys(headers).forEach((header) => {\n req.header(header, headers[header]);\n });\n }\n req.get((error, data) => {\n let d;\n if (!data) {\n throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');\n }\n if (type === 'json') {\n d = $$.convertJsonToData(JSON.parse(data.response), keys);\n } else if (type === 'tsv') {\n d = $$.convertTsvToData(data.response);\n } else {\n d = $$.convertCsvToData(data.response);\n }\n done.call($$, d);\n });\n};\nconst convertXsvToData = function (xsv, parser) {\n let rows = parser.parseRows(xsv), d;\n if (rows.length === 1) {\n d = [{}];\n rows[0].forEach((id) => {\n d[0][id] = null;\n });\n } else {\n d = parser.parse(xsv);\n }\n return d;\n};\nconst convertCsvToData = function (csv) {\n return this.convertXsvToData(csv, this.d3.csv);\n};\nconst convertTsvToData = function (tsv) {\n return this.convertXsvToData(tsv, this.d3.tsv);\n};\nconst convertJsonToData = function (json, keys) {\n let $$ = this,\n new_rows = [], targetKeys, data;\n if (keys) { // when keys specified, json would be an array that includes objects\n if (keys.x) {\n targetKeys = keys.value.concat(keys.x);\n $$.config.data_x = keys.x;\n } else {\n targetKeys = keys.value;\n }\n new_rows.push(targetKeys);\n json.forEach((o) => {\n const new_row = [];\n targetKeys.forEach((key) => {\n // convert undefined to null because undefined data will be removed in convertDataToTargets()\n let v = $$.findValueInJson(o, key);\n if (isUndefined(v)) {\n v = null;\n }\n new_row.push(v);\n });\n new_rows.push(new_row);\n });\n data = $$.convertRowsToData(new_rows);\n } else {\n Object.keys(json).forEach((key) => {\n new_rows.push([key].concat(json[key]));\n });\n data = $$.convertColumnsToData(new_rows);\n }\n return data;\n};\nconst findValueInJson = function (object, path) {\n path = path.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties (replace [] with .)\n path = path.replace(/^\\./, ''); // strip a leading dot\n const pathArray = path.split('.');\n for (let i = 0; i < pathArray.length; ++i) {\n const k = pathArray[i];\n if (k in object) {\n object = object[k];\n } else {\n return;\n }\n }\n return object;\n};\nconst convertRowsToData = function (rows) {\n let keys = rows[0], new_row = {}, new_rows = [], i, j;\n for (i = 1; i < rows.length; i++) {\n new_row = {};\n for (j = 0; j < rows[i].length; j++) {\n if (isUndefined(rows[i][j])) {\n throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');\n }\n new_row[keys[j]] = rows[i][j];\n }\n new_rows.push(new_row);\n }\n return new_rows;\n};\nconst convertColumnsToData = function (columns) {\n let new_rows = [], i, j, key;\n for (i = 0; i < columns.length; i++) {\n key = columns[i][0];\n for (j = 1; j < columns[i].length; j++) {\n if (isUndefined(new_rows[j - 1])) {\n new_rows[j - 1] = {};\n }\n if (isUndefined(columns[i][j])) {\n throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');\n }\n new_rows[j - 1][key] = columns[i][j];\n }\n }\n return new_rows;\n};\nconst convertDataToTargets = function (data, appendXs) {\n let $$ = this, config = $$.config,\n ids = $$.d3.keys(data[0]).filter($$.isNotX, $$),\n xs = $$.d3.keys(data[0]).filter($$.isX, $$),\n targets;\n\n // save x for update data by load when custom x and c3.x API\n ids.forEach((id) => {\n const xKey = $$.getXKey(id);\n\n if ($$.isCustomX() || $$.isTimeSeries()) {\n // if included in input data\n if (xs.indexOf(xKey) >= 0) {\n $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat(\n data.map((d) => { return d[xKey]; })\n .filter(isValue)\n .map((rawX, i) => { return $$.generateTargetX(rawX, id, i); })\n );\n }\n // if not included in input data, find from preloaded data of other id's x\n else if (config.data_x) {\n $$.data.xs[id] = $$.getOtherTargetXs();\n }\n // if not included in input data, find from preloaded data\n else if (notEmpty(config.data_xs)) {\n $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);\n }\n // MEMO: if no x included, use same x of current will be used\n } else {\n $$.data.xs[id] = data.map((d, i) => { return i; });\n }\n });\n\n\n // check x is defined\n ids.forEach((id) => {\n if (!$$.data.xs[id]) {\n throw new Error('x is not defined for id = \"' + id + '\".');\n }\n });\n\n // convert to target\n targets = ids.map((id, index) => {\n const convertedId = config.data_idConverter(id);\n return {\n id: convertedId,\n id_org: id,\n values: data.map((d, i) => {\n let xKey = $$.getXKey(id), rawX = d[xKey],\n value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x;\n // use x as categories if custom x and categorized\n if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) {\n if (index === 0 && i === 0) {\n config.axis_x_categories = [];\n }\n x = config.axis_x_categories.indexOf(rawX);\n if (x === -1) {\n x = config.axis_x_categories.length;\n config.axis_x_categories.push(rawX);\n }\n } else {\n x = $$.generateTargetX(rawX, id, i);\n }\n // mark as x = undefined if value is undefined and filter to remove after mapped\n if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {\n x = undefined;\n }\n return { x, value, id: convertedId };\n }).filter((v) => { return isDefined(v.x); }),\n };\n });\n\n // finish targets\n targets.forEach((t) => {\n let i;\n // sort values by its x\n if (config.data_xSort) {\n t.values = t.values.sort((v1, v2) => {\n let x1 = v1.x || v1.x === 0 ? v1.x : Infinity,\n x2 = v2.x || v2.x === 0 ? v2.x : Infinity;\n return x1 - x2;\n });\n }\n // indexing each value\n i = 0;\n t.values.forEach((v) => {\n v.index = i++;\n });\n // this needs to be sorted because its index and value.index is identical\n $$.data.xs[t.id].sort((v1, v2) => {\n return v1 - v2;\n });\n });\n\n // cache information about values\n $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);\n $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);\n\n // set target types\n if (config.data_type) {\n $$.setTargetType($$.mapToIds(targets).filter((id) => { return !(id in config.data_types); }), config.data_type);\n }\n\n // cache as original id keyed\n targets.forEach((d) => {\n $$.addCache(d.id_org, d);\n });\n\n return targets;\n};\n\nexport {\n convertUrlToData,\n convertXsvToData,\n convertCsvToData,\n convertTsvToData,\n convertJsonToData,\n findValueInJson,\n convertRowsToData,\n convertColumnsToData,\n convertDataToTargets,\n};\n","import {\n notEmpty,\n hasValue,\n isValue,\n isFunction,\n} from './util';\n\nimport { CLASS } from './class';\n\nconst isX = function (key) {\n let $$ = this, config = $$.config;\n return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));\n};\nconst isNotX = function (key) {\n return !this.isX(key);\n};\nconst getXKey = function (id) {\n let $$ = this, config = $$.config;\n return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;\n};\nconst getXValuesOfXKey = function (key, targets) {\n let $$ = this,\n xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];\n ids.forEach((id) => {\n if ($$.getXKey(id) === key) {\n xValues = $$.data.xs[id];\n }\n });\n return xValues;\n};\nconst getIndexByX = function (x) {\n let $$ = this,\n data = $$.filterByX($$.data.targets, x);\n return data.length ? data[0].index : null;\n};\nconst getXValue = function (id, i) {\n const $$ = this;\n return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;\n};\nconst getOtherTargetXs = function () {\n let $$ = this,\n idsForX = Object.keys($$.data.xs);\n return idsForX.length ? $$.data.xs[idsForX[0]] : null;\n};\nconst getOtherTargetX = function (index) {\n const xs = this.getOtherTargetXs();\n return xs && index < xs.length ? xs[index] : null;\n};\nconst addXs = function (xs) {\n const $$ = this;\n Object.keys(xs).forEach((id) => {\n $$.config.data_xs[id] = xs[id];\n });\n};\nconst hasMultipleX = function (xs) {\n return this.d3.set(Object.keys(xs).map((id) => { return xs[id]; })).size() > 1;\n};\nconst isMultipleX = function () {\n return notEmpty(this.config.data_xs) || !this.config.data_xSort || this.hasType('scatter');\n};\nconst addName = function (data) {\n let $$ = this, name;\n if (data) {\n name = $$.config.data_names[data.id];\n data.name = name !== undefined ? name : data.id;\n }\n return data;\n};\nconst getValueOnIndex = function (values, index) {\n const valueOnIndex = values.filter((v) => { return v.index === index; });\n return valueOnIndex.length ? valueOnIndex[0] : null;\n};\nconst updateTargetX = function (targets, x) {\n const $$ = this;\n targets.forEach((t) => {\n t.values.forEach((v, i) => {\n v.x = $$.generateTargetX(x[i], t.id, i);\n });\n $$.data.xs[t.id] = x;\n });\n};\nconst updateTargetXs = function (targets, xs) {\n const $$ = this;\n targets.forEach((t) => {\n if (xs[t.id]) {\n $$.updateTargetX([t], xs[t.id]);\n }\n });\n};\nconst generateTargetX = function (rawX, id, index) {\n let $$ = this, x;\n if ($$.isTimeSeries()) {\n x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));\n }\n else if ($$.isCustomX() && !$$.isCategorized()) {\n x = isValue(rawX) ? +rawX : $$.getXValue(id, index);\n }\n else {\n x = index;\n }\n return x;\n};\nconst cloneTarget = function (target) {\n return {\n id: target.id,\n id_org: target.id_org,\n values: target.values.map((d) => {\n return { x: d.x, value: d.value, id: d.id };\n }),\n };\n};\nconst updateXs = function () {\n const $$ = this;\n if ($$.data.targets.length) {\n $$.xs = [];\n $$.data.targets[0].values.forEach((v) => {\n $$.xs[v.index] = v.x;\n });\n }\n};\nconst getPrevX = function (i) {\n const x = this.xs[i - 1];\n return typeof x !== 'undefined' ? x : null;\n};\nconst getNextX = function (i) {\n const x = this.xs[i + 1];\n return typeof x !== 'undefined' ? x : null;\n};\nconst getMaxDataCount = function () {\n const $$ = this;\n return $$.d3.max($$.data.targets, (t) => { return t.values.length; });\n};\nconst getMaxDataCountTarget = function (targets) {\n let length = targets.length, max = 0, maxTarget;\n if (length > 1) {\n targets.forEach((t) => {\n if (t.values.length > max) {\n maxTarget = t;\n max = t.values.length;\n }\n });\n } else {\n maxTarget = length ? targets[0] : null;\n }\n return maxTarget;\n};\nconst getEdgeX = function (targets) {\n const $$ = this;\n return !targets.length ? [0, 0] : [\n $$.d3.min(targets, (t) => { return t.values[0].x; }),\n $$.d3.max(targets, (t) => { return t.values[t.values.length - 1].x; }),\n ];\n};\nconst mapToIds = function (targets) {\n return targets.map((d) => { return d.id; });\n};\nconst mapToTargetIds = function (ids) {\n const $$ = this;\n return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);\n};\nconst hasTarget = function (targets, id) {\n let ids = this.mapToIds(targets), i;\n for (i = 0; i < ids.length; i++) {\n if (ids[i] === id) {\n return true;\n }\n }\n return false;\n};\nconst isTargetToShow = function (targetId) {\n return this.hiddenTargetIds.indexOf(targetId) < 0;\n};\nconst isLegendToShow = function (targetId) {\n return this.hiddenLegendIds.indexOf(targetId) < 0;\n};\nconst filterTargetsToShow = function (targets) {\n const $$ = this;\n return targets.filter((t) => { return $$.isTargetToShow(t.id); });\n};\nconst mapTargetsToUniqueXs = function (targets) {\n const $$ = this;\n let xs = $$.d3.set($$.d3.merge(targets.map((t) => { return t.values.map((v) => { return +v.x; }); }))).values();\n xs = $$.isTimeSeries() ? xs.map((x) => { return new Date(+x); }) : xs.map((x) => { return +x; });\n return xs.sort((a, b) => { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; });\n};\nconst addHiddenTargetIds = function (targetIds) {\n this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);\n};\nconst removeHiddenTargetIds = function (targetIds) {\n this.hiddenTargetIds = this.hiddenTargetIds.filter((id) => { return targetIds.indexOf(id) < 0; });\n};\nconst addHiddenLegendIds = function (targetIds) {\n this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);\n};\nconst removeHiddenLegendIds = function (targetIds) {\n this.hiddenLegendIds = this.hiddenLegendIds.filter((id) => { return targetIds.indexOf(id) < 0; });\n};\nconst getValuesAsIdKeyed = function (targets) {\n const ys = {};\n targets.forEach((t) => {\n ys[t.id] = [];\n t.values.forEach((v) => {\n ys[t.id].push(v.value);\n });\n });\n return ys;\n};\nconst checkValueInTargets = function (targets, checker) {\n let ids = Object.keys(targets), i, j, values;\n for (i = 0; i < ids.length; i++) {\n values = targets[ids[i]].values;\n for (j = 0; j < values.length; j++) {\n if (checker(values[j].value)) {\n return true;\n }\n }\n }\n return false;\n};\nconst hasNegativeValueInTargets = function (targets) {\n return this.checkValueInTargets(targets, (v) => { return v < 0; });\n};\nconst hasPositiveValueInTargets = function (targets) {\n return this.checkValueInTargets(targets, (v) => { return v > 0; });\n};\nconst isOrderDesc = function () {\n const config = this.config;\n return typeof (config.data_order) === 'string' && config.data_order.toLowerCase() === 'desc';\n};\nconst isOrderAsc = function () {\n const config = this.config;\n return typeof (config.data_order) === 'string' && config.data_order.toLowerCase() === 'asc';\n};\nconst orderTargets = function (targets) {\n let $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();\n if (orderAsc || orderDesc) {\n targets.sort((t1, t2) => {\n const reducer = function (p, c) { return p + Math.abs(c.value); };\n let t1Sum = t1.values.reduce(reducer, 0),\n t2Sum = t2.values.reduce(reducer, 0);\n return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;\n });\n } else if (isFunction(config.data_order)) {\n targets.sort(config.data_order);\n } // TODO: accept name array for order\n return targets;\n};\nconst filterByX = function (targets, x) {\n return this.d3.merge(targets.map((t) => { return t.values; })).filter((v) => { return v.x - x === 0; });\n};\nconst filterRemoveNull = function (data) {\n return data.filter((d) => { return isValue(d.value); });\n};\nconst filterByXDomain = function (targets, xDomain) {\n return targets.map((t) => {\n return {\n id: t.id,\n id_org: t.id_org,\n values: t.values.filter((v) => {\n return xDomain[0] <= v.x && v.x <= xDomain[1];\n }),\n };\n });\n};\nconst hasDataLabel = function () {\n const config = this.config;\n if (typeof config.data_labels === 'boolean' && config.data_labels) {\n return true;\n } else if (typeof config.data_labels === 'object' && notEmpty(config.data_labels)) {\n return true;\n }\n return false;\n};\nconst getDataLabelLength = function (min, max, key) {\n let $$ = this,\n lengths = [0, 0], paddingCoef = 1.3;\n $$.selectChart.select('svg').selectAll('.dummy')\n .data([min, max])\n .enter().append('text')\n .text((d) => { return $$.dataLabelFormat(d.id)(d); })\n .each(function (d, i) {\n lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;\n })\n .remove();\n return lengths;\n};\nconst isNoneArc = function (d) {\n return this.hasTarget(this.data.targets, d.id);\n};\nconst isArc = function (d) {\n return 'data' in d && this.hasTarget(this.data.targets, d.data.id);\n};\nconst findSameXOfValues = function (values, index) {\n let i, targetX = values[index].x, sames = [];\n for (i = index - 1; i >= 0; i--) {\n if (targetX !== values[i].x) { break; }\n sames.push(values[i]);\n }\n for (i = index; i < values.length; i++) {\n if (targetX !== values[i].x) { break; }\n sames.push(values[i]);\n }\n return sames;\n};\n\nconst findClosestFromTargets = function (targets, pos) {\n let $$ = this, candidates;\n\n // map to array of closest points of each target\n candidates = targets.map((target) => {\n return $$.findClosest(target.values, pos);\n });\n\n // decide closest point and return\n return $$.findClosest(candidates, pos);\n};\nconst findClosest = function (values, pos) {\n let $$ = this, minDist = $$.config.point_sensitivity, closest;\n\n // find mouseovering bar\n values.filter((v) => { return v && $$.isBarType(v.id); }).forEach((v) => {\n const shape = $$.main.select('.' + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + ' .' + CLASS.bar + '-' + v.index).node();\n if (!closest && $$.isWithinBar(shape)) {\n closest = v;\n }\n });\n\n // find closest point from non-bar\n values.filter((v) => { return v && !$$.isBarType(v.id); }).forEach((v) => {\n const d = $$.dist(v, pos);\n if (d < minDist) {\n minDist = d;\n closest = v;\n }\n });\n\n return closest;\n};\nconst dist = function (data, pos) {\n let $$ = this, config = $$.config,\n xIndex = config.axis_rotated ? 1 : 0,\n yIndex = config.axis_rotated ? 0 : 1,\n y = $$.circleY(data, data.index),\n x = $$.x(data.x);\n return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));\n};\nconst convertValuesToStep = function (values) {\n let converted = [].concat(values), i;\n\n if (!this.isCategorized()) {\n return values;\n }\n\n for (i = values.length + 1; 0 < i; i--) {\n converted[i] = converted[i - 1];\n }\n\n converted[0] = {\n x: converted[0].x - 1,\n value: converted[0].value,\n id: converted[0].id,\n };\n converted[values.length + 1] = {\n x: converted[values.length].x + 1,\n value: converted[values.length].value,\n id: converted[values.length].id,\n };\n\n return converted;\n};\nconst updateDataAttributes = function (name, attrs) {\n let $$ = this, config = $$.config, current = config['data_' + name];\n if (typeof attrs === 'undefined') { return current; }\n Object.keys(attrs).forEach((id) => {\n current[id] = attrs[id];\n });\n $$.redraw({ withLegend: true });\n return current;\n};\n\nexport {\n isX,\n isNotX,\n getXKey,\n getXValuesOfXKey,\n getIndexByX,\n getXValue,\n getOtherTargetXs,\n getOtherTargetX,\n addXs,\n hasMultipleX,\n isMultipleX,\n addName,\n getValueOnIndex,\n updateTargetX,\n updateTargetXs,\n generateTargetX,\n cloneTarget,\n updateXs,\n getPrevX,\n getNextX,\n getMaxDataCount,\n getMaxDataCountTarget,\n getEdgeX,\n mapToIds,\n mapToTargetIds,\n hasTarget,\n isTargetToShow,\n isLegendToShow,\n filterTargetsToShow,\n mapTargetsToUniqueXs,\n addHiddenTargetIds,\n removeHiddenTargetIds,\n addHiddenLegendIds,\n removeHiddenLegendIds,\n getValuesAsIdKeyed,\n checkValueInTargets,\n hasNegativeValueInTargets,\n hasPositiveValueInTargets,\n isOrderDesc,\n isOrderAsc,\n orderTargets,\n filterByX,\n filterRemoveNull,\n filterByXDomain,\n hasDataLabel,\n getDataLabelLength,\n isNoneArc,\n isArc,\n findSameXOfValues,\n findClosestFromTargets,\n findClosest,\n dist,\n convertValuesToStep,\n updateDataAttributes,\n};\n","import { CLASS } from './class';\n\nconst load = function (targets, args) {\n const $$ = this;\n if (targets) {\n // filter loading targets if needed\n if (args.filter) {\n targets = targets.filter(args.filter);\n }\n // set type if args.types || args.type specified\n if (args.type || args.types) {\n targets.forEach((t) => {\n const type = args.types && args.types[t.id] ? args.types[t.id] : args.type;\n $$.setTargetType(t.id, type);\n });\n }\n // Update/Add data\n $$.data.targets.forEach((d) => {\n for (let i = 0; i < targets.length; i++) {\n if (d.id === targets[i].id) {\n d.values = targets[i].values;\n targets.splice(i, 1);\n break;\n }\n }\n });\n $$.data.targets = $$.data.targets.concat(targets); // add remained\n }\n\n // Set targets\n $$.updateTargets($$.data.targets);\n\n // Redraw with new targets\n $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true, withLegend: true });\n\n if (args.done) { args.done(); }\n};\nconst loadFromArgs = function (args) {\n const $$ = this;\n if (args.data) {\n $$.load($$.convertDataToTargets(args.data), args);\n }\n else if (args.url) {\n $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, (data) => {\n $$.load($$.convertDataToTargets(data), args);\n });\n }\n else if (args.json) {\n $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);\n }\n else if (args.rows) {\n $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);\n }\n else if (args.columns) {\n $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);\n }\n else {\n $$.load(null, args);\n }\n};\nconst unload = function (targetIds, done) {\n const $$ = this;\n if (!done) {\n done = function () {};\n }\n // filter existing target\n targetIds = targetIds.filter((id) => { return $$.hasTarget($$.data.targets, id); });\n // If no target, call done and return\n if (!targetIds || targetIds.length === 0) {\n done();\n return;\n }\n $$.svg.selectAll(targetIds.map((id) => { return $$.selectorTarget(id); }))\n .transition()\n .style('opacity', 0)\n .remove()\n .call($$.endall, done);\n targetIds.forEach((id) => {\n // Reset fadein for future load\n $$.withoutFadeIn[id] = false;\n // Remove target's elements\n if ($$.legend) {\n $$.legend.selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();\n }\n // Remove target\n $$.data.targets = $$.data.targets.filter((t) => {\n return t.id !== id;\n });\n });\n};\n\nexport {\n load,\n loadFromArgs,\n unload,\n};\n","import {\n isValue,\n diffDomain,\n notEmpty,\n isDefined,\n} from './util';\n\nconst getYDomainMin = function (targets) {\n let $$ = this, config = $$.config,\n ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),\n j, k, baseId, idsInGroup, id, hasNegativeValue;\n if (config.data_groups.length > 0) {\n hasNegativeValue = $$.hasNegativeValueInTargets(targets);\n for (j = 0; j < config.data_groups.length; j++) {\n // Determine baseId\n idsInGroup = config.data_groups[j].filter((id) => { return ids.indexOf(id) >= 0; });\n if (idsInGroup.length === 0) { continue; }\n baseId = idsInGroup[0];\n // Consider negative values\n if (hasNegativeValue && ys[baseId]) {\n ys[baseId].forEach((v, i) => {\n ys[baseId][i] = v < 0 ? v : 0;\n });\n }\n // Compute min\n for (k = 1; k < idsInGroup.length; k++) {\n id = idsInGroup[k];\n if (!ys[id]) { continue; }\n ys[id].forEach((v, i) => {\n if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {\n ys[baseId][i] += +v;\n }\n });\n }\n }\n }\n return $$.d3.min(Object.keys(ys).map((key) => { return $$.d3.min(ys[key]); }));\n};\nconst getYDomainMax = function (targets) {\n let $$ = this, config = $$.config,\n ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),\n j, k, baseId, idsInGroup, id, hasPositiveValue;\n if (config.data_groups.length > 0) {\n hasPositiveValue = $$.hasPositiveValueInTargets(targets);\n for (j = 0; j < config.data_groups.length; j++) {\n // Determine baseId\n idsInGroup = config.data_groups[j].filter((id) => { return ids.indexOf(id) >= 0; });\n if (idsInGroup.length === 0) { continue; }\n baseId = idsInGroup[0];\n // Consider positive values\n if (hasPositiveValue && ys[baseId]) {\n ys[baseId].forEach((v, i) => {\n ys[baseId][i] = v > 0 ? v : 0;\n });\n }\n // Compute max\n for (k = 1; k < idsInGroup.length; k++) {\n id = idsInGroup[k];\n if (!ys[id]) { continue; }\n ys[id].forEach((v, i) => {\n if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {\n ys[baseId][i] += +v;\n }\n });\n }\n }\n }\n return $$.d3.max(Object.keys(ys).map((key) => { return $$.d3.max(ys[key]); }));\n};\nconst getYDomain = function (targets, axisId, xDomain) {\n let $$ = this, config = $$.config,\n targetsByAxisId = targets.filter((t) => { return $$.axis.getId(t.id) === axisId; }),\n yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId,\n yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,\n yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,\n yDomainMin = $$.getYDomainMin(yTargets),\n yDomainMax = $$.getYDomainMax(yTargets),\n domain, domainLength, padding, padding_top, padding_bottom,\n center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,\n yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative,\n isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) || ($$.hasType('area', yTargets) && config.area_zerobased),\n isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted,\n showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,\n showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;\n\n // MEMO: avoid inverting domain unexpectedly\n yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? (yDomainMin < yMax ? yDomainMin : yMax - 10) : yDomainMin;\n yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? (yMin < yDomainMax ? yDomainMax : yMin + 10) : yDomainMax;\n\n if (yTargets.length === 0) { // use current domain if target of axisId is none\n return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();\n }\n if (isNaN(yDomainMin)) { // set minimum to zero when not number\n yDomainMin = 0;\n }\n if (isNaN(yDomainMax)) { // set maximum to have same value as yDomainMin\n yDomainMax = yDomainMin;\n }\n if (yDomainMin === yDomainMax) {\n yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;\n }\n isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;\n isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;\n\n // Cancel zerobased if axis_*_min / axis_*_max specified\n if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {\n isZeroBased = false;\n }\n\n // Bar/Area chart should be 0-based if all positive|negative\n if (isZeroBased) {\n if (isAllPositive) { yDomainMin = 0; }\n if (isAllNegative) { yDomainMax = 0; }\n }\n\n domainLength = Math.abs(yDomainMax - yDomainMin);\n padding = padding_top = padding_bottom = domainLength * 0.1;\n\n if (typeof center !== 'undefined') {\n yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));\n yDomainMax = center + yDomainAbs;\n yDomainMin = center - yDomainAbs;\n }\n // add padding for data label\n if (showHorizontalDataLabel) {\n lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');\n diff = diffDomain($$.y.range());\n ratio = [lengths[0] / diff, lengths[1] / diff];\n padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));\n padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));\n } else if (showVerticalDataLabel) {\n lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');\n padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength);\n padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength);\n }\n if (axisId === 'y' && notEmpty(config.axis_y_padding)) {\n padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);\n padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);\n }\n if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {\n padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);\n padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);\n }\n // Bar/Area chart should be 0-based if all positive|negative\n if (isZeroBased) {\n if (isAllPositive) { padding_bottom = yDomainMin; }\n if (isAllNegative) { padding_top = -yDomainMax; }\n }\n domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];\n return isInverted ? domain.reverse() : domain;\n};\nconst getXDomainMin = function (targets) {\n let $$ = this, config = $$.config;\n return isDefined(config.axis_x_min) ?\n ($$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min) :\n $$.d3.min(targets, (t) => { return $$.d3.min(t.values, (v) => { return v.x; }); });\n};\nconst getXDomainMax = function (targets) {\n let $$ = this, config = $$.config;\n return isDefined(config.axis_x_max) ?\n ($$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max) :\n $$.d3.max(targets, (t) => { return $$.d3.max(t.values, (v) => { return v.x; }); });\n};\nconst getXDomainPadding = function (domain) {\n let $$ = this, config = $$.config,\n diff = domain[1] - domain[0],\n maxDataCount, padding, paddingLeft, paddingRight;\n if ($$.isCategorized()) {\n padding = 0;\n } else if ($$.hasType('bar')) {\n maxDataCount = $$.getMaxDataCount();\n padding = maxDataCount > 1 ? (diff / (maxDataCount - 1)) / 2 : 0.5;\n } else {\n padding = diff * 0.01;\n }\n if (typeof config.axis_x_padding === 'object' && notEmpty(config.axis_x_padding)) {\n paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;\n paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;\n } else if (typeof config.axis_x_padding === 'number') {\n paddingLeft = paddingRight = config.axis_x_padding;\n } else {\n paddingLeft = paddingRight = padding;\n }\n return { left: paddingLeft, right: paddingRight };\n};\nconst getXDomain = function (targets) {\n let $$ = this,\n xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],\n firstX = xDomain[0], lastX = xDomain[1],\n padding = $$.getXDomainPadding(xDomain),\n min = 0, max = 0;\n // show center of x domain if min and max are the same\n if ((firstX - lastX) === 0 && !$$.isCategorized()) {\n if ($$.isTimeSeries()) {\n firstX = new Date(firstX.getTime() * 0.5);\n lastX = new Date(lastX.getTime() * 1.5);\n } else {\n firstX = firstX === 0 ? 1 : (firstX * 0.5);\n lastX = lastX === 0 ? -1 : (lastX * 1.5);\n }\n }\n if (firstX || firstX === 0) {\n min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;\n }\n if (lastX || lastX === 0) {\n max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;\n }\n return [min, max];\n};\nconst updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {\n let $$ = this, config = $$.config;\n\n if (withUpdateOrgXDomain) {\n $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));\n $$.orgXDomain = $$.x.domain();\n if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }\n $$.subX.domain($$.x.domain());\n if ($$.brush) { $$.brush.scale($$.subX); }\n }\n if (withUpdateXDomain) {\n $$.x.domain(domain ? domain : (!$$.brush || $$.brush.empty()) ? $$.orgXDomain : $$.brush.extent());\n if (config.zoom_enabled) { $$.zoom.scale($$.x).updateScaleExtent(); }\n }\n\n // Trim domain when too big by zoom mousemove event\n if (withTrim) { $$.x.domain($$.trimXDomain($$.x.orgDomain())); }\n\n return $$.x.domain();\n};\nconst trimXDomain = function (domain) {\n let zoomDomain = this.getZoomDomain(),\n min = zoomDomain[0], max = zoomDomain[1];\n if (domain[0] <= min) {\n domain[1] = +domain[1] + (min - domain[0]);\n domain[0] = min;\n }\n if (max <= domain[1]) {\n domain[0] = +domain[0] - (domain[1] - max);\n domain[1] = max;\n }\n return domain;\n};\n\nexport {\n getYDomainMin,\n getYDomainMax,\n getYDomain,\n getXDomainMin,\n getXDomainMax,\n getXDomainPadding,\n getXDomain,\n updateXDomain,\n trimXDomain,\n};\n","import { CLASS } from './class';\nimport { getPathBox } from './util';\n\nconst drag = function (mouse) {\n let $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;\n let sx, sy, mx, my, minX, maxX, minY, maxY;\n\n if ($$.hasArcType()) { return; }\n if (!config.data_selection_enabled) { return; } // do nothing if not selectable\n if (config.zoom_enabled && !$$.zoom.altDomain) { return; } // skip if zoomable because of conflict drag dehavior\n if (!config.data_selection_multiple) { return; } // skip when single selection because drag is used for multiple selection\n\n sx = $$.dragStart[0];\n sy = $$.dragStart[1];\n mx = mouse[0];\n my = mouse[1];\n minX = Math.min(sx, mx);\n maxX = Math.max(sx, mx);\n minY = (config.data_selection_grouped) ? $$.margin.top : Math.min(sy, my);\n maxY = (config.data_selection_grouped) ? $$.height : Math.max(sy, my);\n\n main.select('.' + CLASS.dragarea)\n .attr('x', minX)\n .attr('y', minY)\n .attr('width', maxX - minX)\n .attr('height', maxY - minY);\n // TODO: binary search when multiple xs\n main.selectAll('.' + CLASS.shapes).selectAll('.' + CLASS.shape)\n .filter((d) => { return config.data_selection_isselectable(d); })\n .each(function (d, i) {\n let shape = d3.select(this),\n isSelected = shape.classed(CLASS.SELECTED),\n isIncluded = shape.classed(CLASS.INCLUDED),\n _x, _y, _w, _h, toggle, isWithin = false, box;\n if (shape.classed(CLASS.circle)) {\n _x = shape.attr('cx') * 1;\n _y = shape.attr('cy') * 1;\n toggle = $$.togglePoint;\n isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;\n }\n else if (shape.classed(CLASS.bar)) {\n box = getPathBox(this);\n _x = box.x;\n _y = box.y;\n _w = box.width;\n _h = box.height;\n toggle = $$.togglePath;\n isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);\n } else {\n // line/area selection not supported yet\n return;\n }\n if (isWithin ^ isIncluded) {\n shape.classed(CLASS.INCLUDED, !isIncluded);\n // TODO: included/unincluded callback here\n shape.classed(CLASS.SELECTED, !isSelected);\n toggle.call($$, !isSelected, shape, d, i);\n }\n });\n};\n\nconst dragstart = function (mouse) {\n let $$ = this, config = $$.config;\n if ($$.hasArcType()) { return; }\n if (!config.data_selection_enabled) { return; } // do nothing if not selectable\n $$.dragStart = mouse;\n $$.main.select('.' + CLASS.chart).append('rect')\n .attr('class', CLASS.dragarea)\n .style('opacity', 0.1);\n $$.dragging = true;\n};\n\nconst dragend = function () {\n let $$ = this, config = $$.config;\n if ($$.hasArcType()) { return; }\n if (!config.data_selection_enabled) { return; } // do nothing if not selectable\n $$.main.select('.' + CLASS.dragarea)\n .transition().duration(100)\n .style('opacity', 0)\n .remove();\n $$.main.selectAll('.' + CLASS.shape)\n .classed(CLASS.INCLUDED, false);\n $$.dragging = false;\n};\n\nexport {\n drag,\n dragstart,\n dragend,\n};\n","import {\n diffDomain,\n} from './util';\n\nimport { CLASS } from './class';\n\nconst generateFlow = function (args) {\n let $$ = this,\n config = $$.config,\n d3 = $$.d3;\n\n return function () {\n let targets = args.targets,\n flow = args.flow,\n drawBar = args.drawBar,\n drawLine = args.drawLine,\n drawArea = args.drawArea,\n cx = args.cx,\n cy = args.cy,\n xv = args.xv,\n xForText = args.xForText,\n yForText = args.yForText,\n duration = args.duration;\n\n let translateX, scaleX = 1,\n transform,\n flowIndex = flow.index,\n flowLength = flow.length,\n flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),\n flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength),\n orgDomain = $$.x.domain(),\n domain,\n durationForFlow = flow.duration || duration,\n done = flow.done || function () {},\n wait = $$.generateWait();\n\n let xgrid = $$.xgrid || d3.selectAll([]),\n xgridLines = $$.xgridLines || d3.selectAll([]),\n mainRegion = $$.mainRegion || d3.selectAll([]),\n mainText = $$.mainText || d3.selectAll([]),\n mainBar = $$.mainBar || d3.selectAll([]),\n mainLine = $$.mainLine || d3.selectAll([]),\n mainArea = $$.mainArea || d3.selectAll([]),\n mainCircle = $$.mainCircle || d3.selectAll([]);\n\n // set flag\n $$.flowing = true;\n\n // remove head data after rendered\n $$.data.targets.forEach((d) => {\n d.values.splice(0, flowLength);\n });\n\n // update x domain to generate axis elements for flow\n domain = $$.updateXDomain(targets, true, true);\n // update elements related to x scale\n if ($$.updateXGrid) { $$.updateXGrid(true); }\n\n // generate transform to flow\n if (!flow.orgDataCount) { // if empty\n if ($$.data.targets[0].values.length !== 1) {\n translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);\n } else {\n if ($$.isTimeSeries()) {\n flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);\n flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);\n translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);\n } else {\n translateX = diffDomain(domain) / 2;\n }\n }\n } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {\n translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);\n } else {\n if ($$.isTimeSeries()) {\n translateX = ($$.x(orgDomain[0]) - $$.x(domain[0]));\n } else {\n translateX = ($$.x(flowStart.x) - $$.x(flowEnd.x));\n }\n }\n scaleX = (diffDomain(orgDomain) / diffDomain(domain));\n transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';\n\n $$.hideXGridFocus();\n\n d3.transition().ease('linear').duration(durationForFlow).each(() => {\n wait.add($$.axes.x.transition().call($$.xAxis));\n wait.add(mainBar.transition().attr('transform', transform));\n wait.add(mainLine.transition().attr('transform', transform));\n wait.add(mainArea.transition().attr('transform', transform));\n wait.add(mainCircle.transition().attr('transform', transform));\n wait.add(mainText.transition().attr('transform', transform));\n wait.add(mainRegion.filter($$.isRegionOnX).transition().attr('transform', transform));\n wait.add(xgrid.transition().attr('transform', transform));\n wait.add(xgridLines.transition().attr('transform', transform));\n })\n .call(wait, () => {\n let i, shapes = [],\n texts = [],\n eventRects = [];\n\n // remove flowed elements\n if (flowLength) {\n for (i = 0; i < flowLength; i++) {\n shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));\n texts.push('.' + CLASS.text + '-' + (flowIndex + i));\n eventRects.push('.' + CLASS.eventRect + '-' + (flowIndex + i));\n }\n $$.svg.selectAll('.' + CLASS.shapes).selectAll(shapes).remove();\n $$.svg.selectAll('.' + CLASS.texts).selectAll(texts).remove();\n $$.svg.selectAll('.' + CLASS.eventRects).selectAll(eventRects).remove();\n $$.svg.select('.' + CLASS.xgrid).remove();\n }\n\n // draw again for removing flowed elements and reverting attr\n xgrid\n .attr('transform', null)\n .attr($$.xgridAttr);\n xgridLines\n .attr('transform', null);\n xgridLines.select('line')\n .attr('x1', config.axis_rotated ? 0 : xv)\n .attr('x2', config.axis_rotated ? $$.width : xv);\n xgridLines.select('text')\n .attr('x', config.axis_rotated ? $$.width : 0)\n .attr('y', xv);\n mainBar\n .attr('transform', null)\n .attr('d', drawBar);\n mainLine\n .attr('transform', null)\n .attr('d', drawLine);\n mainArea\n .attr('transform', null)\n .attr('d', drawArea);\n mainCircle\n .attr('transform', null)\n .attr('cx', cx)\n .attr('cy', cy);\n mainText\n .attr('transform', null)\n .attr('x', xForText)\n .attr('y', yForText)\n .style('fill-opacity', $$.opacityForText.bind($$));\n mainRegion\n .attr('transform', null);\n mainRegion.select('rect').filter($$.isRegionOnX)\n .attr('x', $$.regionX.bind($$))\n .attr('width', $$.regionWidth.bind($$));\n\n if (config.interaction_enabled) {\n $$.redrawEventRect();\n }\n\n // callback for end of flow\n done();\n\n $$.flowing = false;\n });\n };\n};\n\nexport { generateFlow };\n","import { isValue } from './util';\n\nconst getYFormat = function (forArc) {\n let $$ = this,\n formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,\n formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;\n return function (v, ratio, id) {\n const format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;\n return format.call($$, v, ratio);\n };\n};\nconst yFormat = function (v) {\n let $$ = this, config = $$.config,\n format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;\n return format(v);\n};\nconst y2Format = function (v) {\n let $$ = this, config = $$.config,\n format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;\n return format(v);\n};\nconst defaultValueFormat = function (v) {\n return isValue(v) ? +v : '';\n};\nconst defaultArcValueFormat = function (v, ratio) {\n return (ratio * 100).toFixed(1) + '%';\n};\nconst dataLabelFormat = function (targetId) {\n let $$ = this, data_labels = $$.config.data_labels,\n format, defaultFormat = function (v) { return isValue(v) ? +v : ''; };\n // find format according to axis id\n if (typeof data_labels.format === 'function') {\n format = data_labels.format;\n } else if (typeof data_labels.format === 'object') {\n if (data_labels.format[targetId]) {\n format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId];\n } else {\n format = function () { return ''; };\n }\n } else {\n format = defaultFormat;\n }\n return format;\n};\n\nexport {\n getYFormat,\n yFormat,\n y2Format,\n defaultValueFormat,\n defaultArcValueFormat,\n dataLabelFormat,\n};\n","import { CLASS } from './class';\nimport { isValue } from './util';\n\nconst initGrid = function () {\n let $$ = this, config = $$.config, d3 = $$.d3;\n $$.grid = $$.main.append('g')\n .attr('clip-path', $$.clipPathForGrid)\n .attr('class', CLASS.grid);\n if (config.grid_x_show) {\n $$.grid.append('g').attr('class', CLASS.xgrids);\n }\n if (config.grid_y_show) {\n $$.grid.append('g').attr('class', CLASS.ygrids);\n }\n if (config.grid_focus_show) {\n $$.grid.append('g')\n .attr('class', CLASS.xgridFocus)\n .append('line')\n .attr('class', CLASS.xgridFocus);\n }\n $$.xgrid = d3.selectAll([]);\n if (!config.grid_lines_front) { $$.initGridLines(); }\n};\nconst initGridLines = function () {\n let $$ = this, d3 = $$.d3;\n $$.gridLines = $$.main.append('g')\n .attr('clip-path', $$.clipPathForGrid)\n .attr('class', CLASS.grid + ' ' + CLASS.gridLines);\n $$.gridLines.append('g').attr('class', CLASS.xgridLines);\n $$.gridLines.append('g').attr('class', CLASS.ygridLines);\n $$.xgridLines = d3.selectAll([]);\n};\nconst updateXGrid = function (withoutUpdate) {\n let $$ = this, config = $$.config, d3 = $$.d3,\n xgridData = $$.generateGridData(config.grid_x_type, $$.x),\n tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;\n\n $$.xgridAttr = config.axis_rotated ? {\n 'x1': 0,\n 'x2': $$.width,\n 'y1': function (d) { return $$.x(d) - tickOffset; },\n 'y2': function (d) { return $$.x(d) - tickOffset; },\n } : {\n 'x1': function (d) { return $$.x(d) + tickOffset; },\n 'x2': function (d) { return $$.x(d) + tickOffset; },\n 'y1': 0,\n 'y2': $$.height,\n };\n\n $$.xgrid = $$.main.select('.' + CLASS.xgrids).selectAll('.' + CLASS.xgrid)\n .data(xgridData);\n $$.xgrid.enter().append('line').attr('class', CLASS.xgrid);\n if (!withoutUpdate) {\n $$.xgrid.attr($$.xgridAttr)\n .style('opacity', function () { return +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1') === (config.axis_rotated ? $$.height : 0) ? 0 : 1; });\n }\n $$.xgrid.exit().remove();\n};\n\nconst updateYGrid = function () {\n let $$ = this, config = $$.config,\n gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);\n $$.ygrid = $$.main.select('.' + CLASS.ygrids).selectAll('.' + CLASS.ygrid)\n .data(gridValues);\n $$.ygrid.enter().append('line')\n .attr('class', CLASS.ygrid);\n $$.ygrid.attr('x1', config.axis_rotated ? $$.y : 0)\n .attr('x2', config.axis_rotated ? $$.y : $$.width)\n .attr('y1', config.axis_rotated ? 0 : $$.y)\n .attr('y2', config.axis_rotated ? $$.height : $$.y);\n $$.ygrid.exit().remove();\n $$.smoothLines($$.ygrid, 'grid');\n};\n\nconst gridTextAnchor = function (d) {\n return d.position ? d.position : 'end';\n};\nconst gridTextDx = function (d) {\n return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;\n};\nconst xGridTextX = function (d) {\n return d.position === 'start' ? -this.height : d.position === 'middle' ? -this.height / 2 : 0;\n};\nconst yGridTextX = function (d) {\n return d.position === 'start' ? 0 : d.position === 'middle' ? this.width / 2 : this.width;\n};\nconst updateGrid = function (duration) {\n let $$ = this, main = $$.main, config = $$.config,\n xgridLine, ygridLine, yv;\n\n // hide if arc type\n $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');\n\n main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');\n if (config.grid_x_show) {\n $$.updateXGrid();\n }\n $$.xgridLines = main.select('.' + CLASS.xgridLines).selectAll('.' + CLASS.xgridLine)\n .data(config.grid_x_lines);\n // enter\n xgridLine = $$.xgridLines.enter().append('g')\n .attr('class', (d) => { return CLASS.xgridLine + (d.class ? ' ' + d.class : ''); });\n xgridLine.append('line')\n .style('opacity', 0);\n xgridLine.append('text')\n .attr('text-anchor', $$.gridTextAnchor)\n .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')\n .attr('dx', $$.gridTextDx)\n .attr('dy', -5)\n .style('opacity', 0);\n // udpate\n // done in d3.transition() of the end of this function\n // exit\n $$.xgridLines.exit().transition().duration(duration)\n .style('opacity', 0)\n .remove();\n\n // Y-Grid\n if (config.grid_y_show) {\n $$.updateYGrid();\n }\n $$.ygridLines = main.select('.' + CLASS.ygridLines).selectAll('.' + CLASS.ygridLine)\n .data(config.grid_y_lines);\n // enter\n ygridLine = $$.ygridLines.enter().append('g')\n .attr('class', (d) => { return CLASS.ygridLine + (d.class ? ' ' + d.class : ''); });\n ygridLine.append('line')\n .style('opacity', 0);\n ygridLine.append('text')\n .attr('text-anchor', $$.gridTextAnchor)\n .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')\n .attr('dx', $$.gridTextDx)\n .attr('dy', -5)\n .style('opacity', 0);\n // update\n yv = $$.yv.bind($$);\n $$.ygridLines.select('line')\n .transition().duration(duration)\n .attr('x1', config.axis_rotated ? yv : 0)\n .attr('x2', config.axis_rotated ? yv : $$.width)\n .attr('y1', config.axis_rotated ? 0 : yv)\n .attr('y2', config.axis_rotated ? $$.height : yv)\n .style('opacity', 1);\n $$.ygridLines.select('text')\n .transition().duration(duration)\n .attr('x', config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$))\n .attr('y', yv)\n .text((d) => { return d.text; })\n .style('opacity', 1);\n // exit\n $$.ygridLines.exit().transition().duration(duration)\n .style('opacity', 0)\n .remove();\n};\nconst redrawGrid = function (withTransition) {\n let $$ = this, config = $$.config, xv = $$.xv.bind($$),\n lines = $$.xgridLines.select('line'),\n texts = $$.xgridLines.select('text');\n return [\n (withTransition ? lines.transition() : lines)\n .attr('x1', config.axis_rotated ? 0 : xv)\n .attr('x2', config.axis_rotated ? $$.width : xv)\n .attr('y1', config.axis_rotated ? xv : 0)\n .attr('y2', config.axis_rotated ? xv : $$.height)\n .style('opacity', 1),\n (withTransition ? texts.transition() : texts)\n .attr('x', config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$))\n .attr('y', xv)\n .text((d) => { return d.text; })\n .style('opacity', 1),\n ];\n};\nconst showXGridFocus = function (selectedData) {\n let $$ = this, config = $$.config,\n dataToShow = selectedData.filter((d) => { return d && isValue(d.value); }),\n focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),\n xx = $$.xx.bind($$);\n if (!config.tooltip_show) { return; }\n // Hide when scatter plot exists\n if ($$.hasType('scatter') || $$.hasArcType()) { return; }\n focusEl\n .style('visibility', 'visible')\n .data([dataToShow[0]])\n .attr(config.axis_rotated ? 'y1' : 'x1', xx)\n .attr(config.axis_rotated ? 'y2' : 'x2', xx);\n $$.smoothLines(focusEl, 'grid');\n};\nconst hideXGridFocus = function () {\n this.main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');\n};\nconst updateXgridFocus = function () {\n let $$ = this, config = $$.config;\n $$.main.select('line.' + CLASS.xgridFocus)\n .attr('x1', config.axis_rotated ? 0 : -10)\n .attr('x2', config.axis_rotated ? $$.width : -10)\n .attr('y1', config.axis_rotated ? -10 : 0)\n .attr('y2', config.axis_rotated ? -10 : $$.height);\n};\nconst generateGridData = function (type, scale) {\n let $$ = this,\n gridData = [], xDomain, firstYear, lastYear, i,\n tickNum = $$.main.select('.' + CLASS.axisX).selectAll('.tick').size();\n if (type === 'year') {\n xDomain = $$.getXDomain();\n firstYear = xDomain[0].getFullYear();\n lastYear = xDomain[1].getFullYear();\n for (i = firstYear; i <= lastYear; i++) {\n gridData.push(new Date(i + '-01-01 00:00:00'));\n }\n } else {\n gridData = scale.ticks(10);\n if (gridData.length > tickNum) { // use only int\n gridData = gridData.filter((d) => { return ('' + d).indexOf('.') < 0; });\n }\n }\n return gridData;\n};\nconst getGridFilterToRemove = function (params) {\n return params ? function (line) {\n let found = false;\n [].concat(params).forEach((param) => {\n if ((('value' in param && line.value === param.value) || ('class' in param && line.class === param.class))) {\n found = true;\n }\n });\n return found;\n } : function () { return true; };\n};\nconst removeGridLines = function (params, forX) {\n let $$ = this, config = $$.config,\n toRemove = $$.getGridFilterToRemove(params),\n toShow = function (line) { return !toRemove(line); },\n classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,\n classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;\n $$.main.select('.' + classLines).selectAll('.' + classLine).filter(toRemove)\n .transition().duration(config.transition_duration)\n .style('opacity', 0).remove();\n if (forX) {\n config.grid_x_lines = config.grid_x_lines.filter(toShow);\n } else {\n config.grid_y_lines = config.grid_y_lines.filter(toShow);\n }\n};\n\nexport {\n initGrid,\n initGridLines,\n updateXGrid,\n updateYGrid,\n gridTextAnchor,\n gridTextDx,\n xGridTextX,\n yGridTextX,\n updateGrid,\n redrawGrid,\n showXGridFocus,\n hideXGridFocus,\n updateXgridFocus,\n generateGridData,\n getGridFilterToRemove,\n removeGridLines,\n};\n","import { CLASS } from './class';\n\nconst initEventRect = function () {\n const $$ = this;\n $$.main.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.eventRects)\n .style('fill-opacity', 0);\n};\nconst redrawEventRect = function () {\n let $$ = this, config = $$.config,\n eventRectUpdate, maxDataCountTarget,\n isMultipleX = $$.isMultipleX();\n\n // rects for mouseover\n const eventRects = $$.main.select('.' + CLASS.eventRects)\n .style('cursor', config.zoom_enabled ? config.axis_rotated ? 'ns-resize' : 'ew-resize' : null)\n .classed(CLASS.eventRectsMultiple, isMultipleX)\n .classed(CLASS.eventRectsSingle, !isMultipleX);\n\n // clear old rects\n eventRects.selectAll('.' + CLASS.eventRect).remove();\n\n // open as public variable\n $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);\n\n if (isMultipleX) {\n eventRectUpdate = $$.eventRect.data([0]);\n // enter : only one rect will be added\n $$.generateEventRectsForMultipleXs(eventRectUpdate.enter());\n // update\n $$.updateEventRect(eventRectUpdate);\n // exit : not needed because always only one rect exists\n }\n else {\n // Set data and update $$.eventRect\n maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);\n eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);\n $$.eventRect = eventRects.selectAll('.' + CLASS.eventRect);\n eventRectUpdate = $$.eventRect.data((d) => { return d; });\n // enter\n $$.generateEventRectsForSingleX(eventRectUpdate.enter());\n // update\n $$.updateEventRect(eventRectUpdate);\n // exit\n eventRectUpdate.exit().remove();\n }\n};\nconst updateEventRect = function (eventRectUpdate) {\n let $$ = this, config = $$.config,\n x, y, w, h, rectW, rectX;\n\n // set update selection if null\n eventRectUpdate = eventRectUpdate || $$.eventRect.data((d) => { return d; });\n\n if ($$.isMultipleX()) {\n // TODO: rotated not supported yet\n x = 0;\n y = 0;\n w = $$.width;\n h = $$.height;\n }\n else {\n if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {\n // update index for x that is used by prevX and nextX\n $$.updateXs();\n\n rectW = function (d) {\n let prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index);\n\n // if there this is a single data point make the eventRect full width (or height)\n if (prevX === null && nextX === null) {\n return config.axis_rotated ? $$.height : $$.width;\n }\n\n if (prevX === null) { prevX = $$.x.domain()[0]; }\n if (nextX === null) { nextX = $$.x.domain()[1]; }\n\n return Math.max(0, ($$.x(nextX) - $$.x(prevX)) / 2);\n };\n rectX = function (d) {\n let prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index),\n thisX = $$.data.xs[d.id][d.index];\n\n // if there this is a single data point position the eventRect at 0\n if (prevX === null && nextX === null) {\n return 0;\n }\n\n if (prevX === null) { prevX = $$.x.domain()[0]; }\n\n return ($$.x(thisX) + $$.x(prevX)) / 2;\n };\n } else {\n rectW = $$.getEventRectWidth();\n rectX = function (d) {\n return $$.x(d.x) - (rectW / 2);\n };\n }\n x = config.axis_rotated ? 0 : rectX;\n y = config.axis_rotated ? rectX : 0;\n w = config.axis_rotated ? $$.width : rectW;\n h = config.axis_rotated ? rectW : $$.height;\n }\n\n eventRectUpdate\n .attr('class', $$.classEvent.bind($$))\n .attr('x', x)\n .attr('y', y)\n .attr('width', w)\n .attr('height', h);\n};\nconst generateEventRectsForSingleX = function (eventRectEnter) {\n let $$ = this, d3 = $$.d3, config = $$.config,\n tap = false, tapX;\n\n function click(shape, d) {\n let index = d.index;\n if ($$.hasArcType() || !$$.toggleShape) { return; }\n if ($$.cancelClick) {\n $$.cancelClick = false;\n return;\n }\n if ($$.isStepType(d) && config.line_step_type === 'step-after' && d3.mouse(shape)[0] < $$.x($$.getXValue(d.id, index))) {\n index -= 1;\n }\n $$.main.selectAll('.' + CLASS.shape + '-' + index).each(function (d) {\n if (config.data_selection_grouped || $$.isWithinShape(this, d)) {\n $$.toggleShape(this, d, index);\n $$.config.data_onclick.call($$.api, d, this);\n }\n });\n }\n\n eventRectEnter.append('rect')\n .attr('class', $$.classEvent.bind($$))\n .style('cursor', config.data_selection_enabled && config.data_selection_grouped ? 'pointer' : null)\n .on('mouseover', (d) => {\n const index = d.index;\n\n if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing\n if ($$.hasArcType()) { return; }\n\n // Expand shapes for selection\n if (config.point_focus_expand_enabled) { $$.expandCircles(index, null, true); }\n $$.expandBars(index, null, true);\n\n // Call event handler\n $$.main.selectAll('.' + CLASS.shape + '-' + index).each((d) => {\n config.data_onmouseover.call($$.api, d);\n });\n })\n .on('mouseout', (d) => {\n const index = d.index;\n if (!$$.config) { return; } // chart is destroyed\n if ($$.hasArcType()) { return; }\n $$.hideXGridFocus();\n $$.hideTooltip();\n // Undo expanded shapes\n $$.unexpandCircles();\n $$.unexpandBars();\n // Call event handler\n $$.main.selectAll('.' + CLASS.shape + '-' + index).each((d) => {\n config.data_onmouseout.call($$.api, d);\n });\n })\n .on('mousemove', function (d) {\n let selectedData, index = d.index,\n eventRect = $$.svg.select('.' + CLASS.eventRect + '-' + index);\n\n if ($$.dragging || $$.flowing) { return; } // do nothing while dragging/flowing\n if ($$.hasArcType()) { return; }\n\n if ($$.isStepType(d) && $$.config.line_step_type === 'step-after' && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {\n index -= 1;\n }\n\n // Show tooltip\n selectedData = $$.filterTargetsToShow($$.data.targets).map((t) => {\n return $$.addName($$.getValueOnIndex(t.values, index));\n });\n\n if (config.tooltip_grouped) {\n $$.showTooltip(selectedData, this);\n $$.showXGridFocus(selectedData);\n }\n\n if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) {\n return;\n }\n\n $$.main.selectAll('.' + CLASS.shape + '-' + index)\n .each(function () {\n d3.select(this).classed(CLASS.EXPANDED, true);\n if (config.data_selection_enabled) {\n eventRect.style('cursor', config.data_selection_grouped ? 'pointer' : null);\n }\n if (!config.tooltip_grouped) {\n $$.hideXGridFocus();\n $$.hideTooltip();\n if (!config.data_selection_grouped) {\n $$.unexpandCircles(index);\n $$.unexpandBars(index);\n }\n }\n })\n .filter(function (d) {\n return $$.isWithinShape(this, d);\n })\n .each(function (d) {\n if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) {\n eventRect.style('cursor', 'pointer');\n }\n if (!config.tooltip_grouped) {\n $$.showTooltip([d], this);\n $$.showXGridFocus([d]);\n if (config.point_focus_expand_enabled) { $$.expandCircles(index, d.id, true); }\n $$.expandBars(index, d.id, true);\n }\n });\n })\n .on('click', function (d) {\n // click event was simulated via a 'tap' touch event, cancel regular click\n if (tap) {\n return;\n }\n\n click(this, d);\n })\n .on('touchstart', (d) => {\n // store current X selection for comparison during touch end event\n tapX = d.x;\n })\n .on('touchend', function (d) {\n const finalX = d.x;\n\n // If end is not the same as the start, event doesn't count as a tap\n if (tapX !== finalX) {\n return;\n }\n\n\n click(this, d);\n\n // indictate tap event fired to prevent click;\n tap = true;\n setTimeout(() => { tap = false; }, config.touch_tap_delay);\n })\n\n .call(\n config.data_selection_draggable && $$.drag ? (\n d3.behavior.drag().origin(Object)\n .on('drag', function () { $$.drag(d3.mouse(this)); })\n .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })\n .on('dragend', () => { $$.dragend(); })\n ) : () => {}\n );\n};\n\nconst generateEventRectsForMultipleXs = function (eventRectEnter) {\n let $$ = this, d3 = $$.d3, config = $$.config,\n tap = false, tapX, tapY;\n\n function mouseout() {\n $$.svg.select('.' + CLASS.eventRect).style('cursor', null);\n $$.hideXGridFocus();\n $$.hideTooltip();\n $$.unexpandCircles();\n $$.unexpandBars();\n }\n\n function click(shape) {\n const targetsToShow = $$.filterTargetsToShow($$.data.targets);\n let mouse, closest;\n if ($$.hasArcType(targetsToShow)) { return; }\n\n mouse = d3.mouse(shape);\n closest = $$.findClosestFromTargets(targetsToShow, mouse);\n if (!closest) { return; }\n // select if selection enabled\n if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {\n $$.main.selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll('.' + CLASS.shape + '-' + closest.index).each(function () {\n if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {\n $$.toggleShape(this, closest, closest.index);\n $$.config.data_onclick.call($$.api, closest, this);\n }\n });\n }\n }\n\n eventRectEnter.append('rect')\n .attr('x', 0)\n .attr('y', 0)\n .attr('width', $$.width)\n .attr('height', $$.height)\n .attr('class', CLASS.eventRect)\n .on('mouseout', () => {\n if (!$$.config) { return; } // chart is destroyed\n if ($$.hasArcType()) { return; }\n mouseout();\n })\n .on('mousemove', function () {\n const targetsToShow = $$.filterTargetsToShow($$.data.targets);\n let mouse, closest, sameXData, selectedData;\n\n if ($$.dragging) { return; } // do nothing when dragging\n if ($$.hasArcType(targetsToShow)) { return; }\n\n mouse = d3.mouse(this);\n closest = $$.findClosestFromTargets(targetsToShow, mouse);\n\n if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {\n config.data_onmouseout.call($$.api, $$.mouseover);\n $$.mouseover = undefined;\n }\n\n if (!closest) {\n mouseout();\n return;\n }\n\n if ($$.isScatterType(closest) || !config.tooltip_grouped) {\n sameXData = [closest];\n } else {\n sameXData = $$.filterByX(targetsToShow, closest.x);\n }\n\n // show tooltip when cursor is close to some point\n selectedData = sameXData.map((d) => {\n return $$.addName(d);\n });\n $$.showTooltip(selectedData, this);\n\n // expand points\n if (config.point_focus_expand_enabled) {\n $$.expandCircles(closest.index, closest.id, true);\n }\n $$.expandBars(closest.index, closest.id, true);\n\n // Show xgrid focus line\n $$.showXGridFocus(selectedData);\n\n // Show cursor as pointer if point is close to mouse position\n if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < config.point_sensitivity) {\n $$.svg.select('.' + CLASS.eventRect).style('cursor', 'pointer');\n if (!$$.mouseover) {\n config.data_onmouseover.call($$.api, closest);\n $$.mouseover = closest;\n }\n }\n })\n .on('click', function () {\n // click event was simulated via a 'tap' touch event, cancel regular click\n if (tap) {\n return;\n }\n\n click(this);\n })\n .on('touchstart', function () {\n const mouse = d3.mouse(this);\n // store starting coordinates for distance comparision during touch end event\n tapX = mouse[0];\n tapY = mouse[1];\n })\n .on('touchend', function () {\n let mouse = d3.mouse(this),\n x = mouse[0],\n y = mouse[1];\n\n // If end is too far from start, event doesn't count as a tap\n if (Math.abs(x - tapX) > config.touch_tap_radius || Math.abs(y - tapY) > config.touch_tap_radius) {\n return;\n }\n\n click(this);\n\n // indictate tap event fired to prevent click;\n tap = true;\n setTimeout(() => { tap = false; }, config.touch_tap_delay);\n })\n .call(\n config.data_selection_draggable && $$.drag ? (\n d3.behavior.drag().origin(Object)\n .on('drag', function () { $$.drag(d3.mouse(this)); })\n .on('dragstart', function () { $$.dragstart(d3.mouse(this)); })\n .on('dragend', () => { $$.dragend(); })\n ) : () => {}\n );\n};\nconst dispatchEvent = function (type, index, mouse) {\n let $$ = this,\n selector = '.' + CLASS.eventRect + (!$$.isMultipleX() ? '-' + index : ''),\n eventRect = $$.main.select(selector).node(),\n box = eventRect.getBoundingClientRect(),\n x = box.left + (mouse ? mouse[0] : 0),\n y = box.top + (mouse ? mouse[1] : 0),\n event = document.createEvent('MouseEvents');\n\n event.initMouseEvent(type, true, true, window, 0, x, y, x, y,\n false, false, false, false, 0, null);\n eventRect.dispatchEvent(event);\n};\n\nexport {\n initEventRect,\n redrawEventRect,\n updateEventRect,\n generateEventRectsForSingleX,\n generateEventRectsForMultipleXs,\n dispatchEvent,\n};\n","import { CLASS } from './class';\nimport {\n isEmpty,\n isDefined,\n getOption,\n} from './util';\n\nconst initLegend = function () {\n const $$ = this;\n $$.legendItemTextBox = {};\n $$.legendHasRendered = false;\n $$.legend = $$.svg.append('g').attr('transform', $$.getTranslate('legend'));\n if (!$$.config.legend_show) {\n $$.legend.style('visibility', 'hidden');\n $$.hiddenLegendIds = $$.mapToIds($$.data.targets);\n return;\n }\n // MEMO: call here to update legend box and tranlate for all\n // MEMO: translate will be upated by this, so transform not needed in updateLegend()\n $$.updateLegendWithDefaults();\n};\nconst updateLegendWithDefaults = function () {\n const $$ = this;\n $$.updateLegend($$.mapToIds($$.data.targets), { withTransform: false, withTransitionForTransform: false, withTransition: false });\n};\nconst updateSizeForLegend = function (legendHeight, legendWidth) {\n let $$ = this, config = $$.config, insetLegendPosition = {\n top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,\n left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + 0.5,\n };\n\n $$.margin3 = {\n top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,\n right: NaN,\n bottom: 0,\n left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0,\n };\n};\nconst transformLegend = function (withTransition) {\n const $$ = this;\n (withTransition ? $$.legend.transition() : $$.legend).attr('transform', $$.getTranslate('legend'));\n};\nconst updateLegendStep = function (step) {\n this.legendStep = step;\n};\nconst updateLegendItemWidth = function (w) {\n this.legendItemWidth = w;\n};\nconst updateLegendItemHeight = function (h) {\n this.legendItemHeight = h;\n};\nconst getLegendWidth = function () {\n const $$ = this;\n return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;\n};\nconst getLegendHeight = function () {\n let $$ = this, h = 0;\n if ($$.config.legend_show) {\n if ($$.isLegendRight) {\n h = $$.currentHeight;\n } else {\n h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);\n }\n }\n return h;\n};\nconst opacityForLegend = function (legendItem) {\n return legendItem.classed(CLASS.legendItemHidden) ? null : 1;\n};\nconst opacityForUnfocusedLegend = function (legendItem) {\n return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;\n};\nconst toggleFocusLegend = function (targetIds, focus) {\n const $$ = this;\n targetIds = $$.mapToTargetIds(targetIds);\n $$.legend.selectAll('.' + CLASS.legendItem)\n .filter((id) => { return targetIds.indexOf(id) >= 0; })\n .classed(CLASS.legendItemFocused, focus)\n .transition().duration(100)\n .style('opacity', function () {\n const opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;\n return opacity.call($$, $$.d3.select(this));\n });\n};\nconst revertLegend = function () {\n let $$ = this, d3 = $$.d3;\n $$.legend.selectAll('.' + CLASS.legendItem)\n .classed(CLASS.legendItemFocused, false)\n .transition().duration(100)\n .style('opacity', function () { return $$.opacityForLegend(d3.select(this)); });\n};\nconst showLegend = function (targetIds) {\n let $$ = this, config = $$.config;\n if (!config.legend_show) {\n config.legend_show = true;\n $$.legend.style('visibility', 'visible');\n if (!$$.legendHasRendered) {\n $$.updateLegendWithDefaults();\n }\n }\n $$.removeHiddenLegendIds(targetIds);\n $$.legend.selectAll($$.selectorLegends(targetIds))\n .style('visibility', 'visible')\n .transition()\n .style('opacity', function () { return $$.opacityForLegend($$.d3.select(this)); });\n};\nconst hideLegend = function (targetIds) {\n let $$ = this, config = $$.config;\n if (config.legend_show && isEmpty(targetIds)) {\n config.legend_show = false;\n $$.legend.style('visibility', 'hidden');\n }\n $$.addHiddenLegendIds(targetIds);\n $$.legend.selectAll($$.selectorLegends(targetIds))\n .style('opacity', 0)\n .style('visibility', 'hidden');\n};\nconst clearLegendItemTextBoxCache = function () {\n this.legendItemTextBox = {};\n};\nconst updateLegend = function (targetIds, options, transitions) {\n let $$ = this, config = $$.config;\n let xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;\n let paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5;\n let l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;\n let withTransition, withTransitionForTransform;\n let texts, rects, tiles, background;\n\n // Skip elements when their name is set to null\n targetIds = targetIds.filter((id) => {\n return !isDefined(config.data_names[id]) || config.data_names[id] !== null;\n });\n\n options = options || {};\n withTransition = getOption(options, 'withTransition', true);\n withTransitionForTransform = getOption(options, 'withTransitionForTransform', true);\n\n function getTextBox(textElement, id) {\n if (!$$.legendItemTextBox[id]) {\n $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);\n }\n return $$.legendItemTextBox[id];\n }\n\n function updatePositions(textElement, id, index) {\n let reset = index === 0, isLast = index === targetIds.length - 1,\n box = getTextBox(textElement, id),\n itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) + config.legend_padding,\n itemHeight = box.height + paddingTop,\n itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,\n areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(),\n margin, maxLength;\n\n // MEMO: care about condifion of step, totalLength\n function updateValues(id, withoutStep) {\n if (!withoutStep) {\n margin = (areaLength - totalLength - itemLength) / 2;\n if (margin < posMin) {\n margin = (areaLength - itemLength) / 2;\n totalLength = 0;\n step++;\n }\n }\n steps[id] = step;\n margins[step] = $$.isLegendInset ? 10 : margin;\n offsets[id] = totalLength;\n totalLength += itemLength;\n }\n\n if (reset) {\n totalLength = 0;\n step = 0;\n maxWidth = 0;\n maxHeight = 0;\n }\n\n if (config.legend_show && !$$.isLegendToShow(id)) {\n widths[id] = heights[id] = steps[id] = offsets[id] = 0;\n return;\n }\n\n widths[id] = itemWidth;\n heights[id] = itemHeight;\n\n if (!maxWidth || itemWidth >= maxWidth) { maxWidth = itemWidth; }\n if (!maxHeight || itemHeight >= maxHeight) { maxHeight = itemHeight; }\n maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;\n\n if (config.legend_equally) {\n Object.keys(widths).forEach((id) => { widths[id] = maxWidth; });\n Object.keys(heights).forEach((id) => { heights[id] = maxHeight; });\n margin = (areaLength - maxLength * targetIds.length) / 2;\n if (margin < posMin) {\n totalLength = 0;\n step = 0;\n targetIds.forEach((id) => { updateValues(id); });\n }\n else {\n updateValues(id, true);\n }\n } else {\n updateValues(id);\n }\n }\n\n if ($$.isLegendInset) {\n step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;\n $$.updateLegendStep(step);\n }\n\n if ($$.isLegendRight) {\n xForLegend = function (id) { return maxWidth * steps[id]; };\n yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };\n } else if ($$.isLegendInset) {\n xForLegend = function (id) { return maxWidth * steps[id] + 10; };\n yForLegend = function (id) { return margins[steps[id]] + offsets[id]; };\n } else {\n xForLegend = function (id) { return margins[steps[id]] + offsets[id]; };\n yForLegend = function (id) { return maxHeight * steps[id]; };\n }\n xForLegendText = function (id, i) { return xForLegend(id, i) + 4 + config.legend_item_tile_width; };\n yForLegendText = function (id, i) { return yForLegend(id, i) + 9; };\n xForLegendRect = function (id, i) { return xForLegend(id, i); };\n yForLegendRect = function (id, i) { return yForLegend(id, i) - 5; };\n x1ForLegendTile = function (id, i) { return xForLegend(id, i) - 2; };\n x2ForLegendTile = function (id, i) { return xForLegend(id, i) - 2 + config.legend_item_tile_width; };\n yForLegendTile = function (id, i) { return yForLegend(id, i) + 4; };\n\n // Define g for legend area\n l = $$.legend.selectAll('.' + CLASS.legendItem)\n .data(targetIds)\n .enter().append('g')\n .attr('class', (id) => { return $$.generateClass(CLASS.legendItem, id); })\n .style('visibility', (id) => { return $$.isLegendToShow(id) ? 'visible' : 'hidden'; })\n .style('cursor', 'pointer')\n .on('click', (id) => {\n if (config.legend_item_onclick) {\n config.legend_item_onclick.call($$, id);\n } else {\n if ($$.d3.event.altKey) {\n $$.api.hide();\n $$.api.show(id);\n } else {\n $$.api.toggle(id);\n $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();\n }\n }\n })\n .on('mouseover', function (id) {\n if (config.legend_item_onmouseover) {\n config.legend_item_onmouseover.call($$, id);\n }\n else {\n $$.d3.select(this).classed(CLASS.legendItemFocused, true);\n if (!$$.transiting && $$.isTargetToShow(id)) {\n $$.api.focus(id);\n }\n }\n })\n .on('mouseout', function (id) {\n if (config.legend_item_onmouseout) {\n config.legend_item_onmouseout.call($$, id);\n }\n else {\n $$.d3.select(this).classed(CLASS.legendItemFocused, false);\n $$.api.revert();\n }\n });\n l.append('text')\n .text((id) => { return isDefined(config.data_names[id]) ? config.data_names[id] : id; })\n .each(function (id, i) { updatePositions(this, id, i); })\n .style('pointer-events', 'none')\n .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)\n .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);\n l.append('rect')\n .attr('class', CLASS.legendItemEvent)\n .style('fill-opacity', 0)\n .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)\n .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);\n l.append('line')\n .attr('class', CLASS.legendItemTile)\n .style('stroke', $$.color)\n .style('pointer-events', 'none')\n .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)\n .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)\n .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)\n .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)\n .attr('stroke-width', config.legend_item_tile_height);\n\n // Set background for inset legend\n background = $$.legend.select('.' + CLASS.legendBackground + ' rect');\n if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {\n background = $$.legend.insert('g', '.' + CLASS.legendItem)\n .attr('class', CLASS.legendBackground)\n .append('rect');\n }\n\n texts = $$.legend.selectAll('text')\n .data(targetIds)\n .text((id) => { return isDefined(config.data_names[id]) ? config.data_names[id] : id; }) // MEMO: needed for update\n .each(function (id, i) { updatePositions(this, id, i); });\n (withTransition ? texts.transition() : texts)\n .attr('x', xForLegendText)\n .attr('y', yForLegendText);\n\n rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent)\n .data(targetIds);\n (withTransition ? rects.transition() : rects)\n .attr('width', (id) => { return widths[id]; })\n .attr('height', (id) => { return heights[id]; })\n .attr('x', xForLegendRect)\n .attr('y', yForLegendRect);\n\n tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile)\n .data(targetIds);\n (withTransition ? tiles.transition() : tiles)\n .style('stroke', $$.color)\n .attr('x1', x1ForLegendTile)\n .attr('y1', yForLegendTile)\n .attr('x2', x2ForLegendTile)\n .attr('y2', yForLegendTile);\n\n if (background) {\n (withTransition ? background.transition() : background)\n .attr('height', $$.getLegendHeight() - 12)\n .attr('width', maxWidth * (step + 1) + 10);\n }\n\n // toggle legend state\n $$.legend.selectAll('.' + CLASS.legendItem)\n .classed(CLASS.legendItemHidden, (id) => { return !$$.isTargetToShow(id); });\n\n // Update all to reflect change of legend\n $$.updateLegendItemWidth(maxWidth);\n $$.updateLegendItemHeight(maxHeight);\n $$.updateLegendStep(step);\n // Update size and scale\n $$.updateSizes();\n $$.updateScales();\n $$.updateSvgSize();\n // Update g positions\n $$.transformAll(withTransitionForTransform, transitions);\n $$.legendHasRendered = true;\n};\n\nexport {\n initLegend,\n updateLegendWithDefaults,\n updateSizeForLegend,\n transformLegend,\n updateLegendStep,\n updateLegendItemWidth,\n updateLegendItemHeight,\n getLegendWidth,\n getLegendHeight,\n opacityForLegend,\n opacityForUnfocusedLegend,\n toggleFocusLegend,\n revertLegend,\n showLegend,\n hideLegend,\n clearLegendItemTextBoxCache,\n updateLegend,\n};\n","import { CLASS } from './class';\nimport { isValue } from './util';\n\nconst initRegion = function () {\n const $$ = this;\n $$.region = $$.main.append('g')\n .attr('clip-path', $$.clipPath)\n .attr('class', CLASS.regions);\n};\nconst updateRegion = function (duration) {\n let $$ = this, config = $$.config;\n\n // hide if arc type\n $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');\n\n $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)\n .data(config.regions);\n $$.mainRegion.enter().append('g')\n .append('rect')\n .style('fill-opacity', 0);\n $$.mainRegion\n .attr('class', $$.classRegion.bind($$));\n $$.mainRegion.exit().transition().duration(duration)\n .style('opacity', 0)\n .remove();\n};\nconst redrawRegion = function (withTransition) {\n let $$ = this,\n regions = $$.mainRegion.selectAll('rect').each(function () {\n // data is binded to g and it's not transferred to rect (child node) automatically,\n // then data of each rect has to be updated manually.\n // TODO: there should be more efficient way to solve this?\n const parentData = $$.d3.select(this.parentNode).datum();\n $$.d3.select(this).datum(parentData);\n }),\n x = $$.regionX.bind($$),\n y = $$.regionY.bind($$),\n w = $$.regionWidth.bind($$),\n h = $$.regionHeight.bind($$);\n return [\n (withTransition ? regions.transition() : regions)\n .attr('x', x)\n .attr('y', y)\n .attr('width', w)\n .attr('height', h)\n .style('fill-opacity', (d) => { return isValue(d.opacity) ? d.opacity : 0.1; }),\n ];\n};\nconst regionX = function (d) {\n let $$ = this, config = $$.config,\n xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;\n if (d.axis === 'y' || d.axis === 'y2') {\n xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;\n } else {\n xPos = config.axis_rotated ? 0 : ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0);\n }\n return xPos;\n};\nconst regionY = function (d) {\n let $$ = this, config = $$.config,\n yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;\n if (d.axis === 'y' || d.axis === 'y2') {\n yPos = config.axis_rotated ? 0 : ('end' in d ? yScale(d.end) : 0);\n } else {\n yPos = config.axis_rotated ? ('start' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0) : 0;\n }\n return yPos;\n};\nconst regionWidth = function (d) {\n let $$ = this, config = $$.config,\n start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;\n if (d.axis === 'y' || d.axis === 'y2') {\n end = config.axis_rotated ? ('end' in d ? yScale(d.end) : $$.width) : $$.width;\n } else {\n end = config.axis_rotated ? $$.width : ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width);\n }\n return end < start ? 0 : end - start;\n};\nconst regionHeight = function (d) {\n let $$ = this, config = $$.config,\n start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;\n if (d.axis === 'y' || d.axis === 'y2') {\n end = config.axis_rotated ? $$.height : ('start' in d ? yScale(d.start) : $$.height);\n } else {\n end = config.axis_rotated ? ('end' in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height) : $$.height;\n }\n return end < start ? 0 : end - start;\n};\nconst isRegionOnX = function (d) {\n return !d.axis || d.axis === 'x';\n};\n\nexport {\n initRegion,\n updateRegion,\n redrawRegion,\n regionX,\n regionY,\n regionWidth,\n regionHeight,\n isRegionOnX,\n};\n","const getScale = function (min, max, forTimeseries) {\n return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]);\n};\nconst getX = function (min, max, domain, offset) {\n let $$ = this,\n scale = $$.getScale(min, max, $$.isTimeSeries()),\n _scale = domain ? scale.domain(domain) : scale, key;\n // Define customized scale if categorized axis\n if ($$.isCategorized()) {\n offset = offset || function () { return 0; };\n scale = function (d, raw) {\n const v = _scale(d) + offset(d);\n return raw ? v : Math.ceil(v);\n };\n } else {\n scale = function (d, raw) {\n const v = _scale(d);\n return raw ? v : Math.ceil(v);\n };\n }\n // define functions\n for (key in _scale) {\n scale[key] = _scale[key];\n }\n scale.orgDomain = function () {\n return _scale.domain();\n };\n // define custom domain() for categorized axis\n if ($$.isCategorized()) {\n scale.domain = function (domain) {\n if (!arguments.length) {\n domain = this.orgDomain();\n return [domain[0], domain[1] + 1];\n }\n _scale.domain(domain);\n return scale;\n };\n }\n return scale;\n};\nconst getY = function (min, max, domain) {\n const scale = this.getScale(min, max, this.isTimeSeriesY());\n if (domain) { scale.domain(domain); }\n return scale;\n};\nconst getYScale = function (id) {\n return this.axis.getId(id) === 'y2' ? this.y2 : this.y;\n};\nconst getSubYScale = function (id) {\n return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;\n};\nconst updateScales = function () {\n let $$ = this, config = $$.config,\n forInit = !$$.x;\n // update edges\n $$.xMin = config.axis_rotated ? 1 : 0;\n $$.xMax = config.axis_rotated ? $$.height : $$.width;\n $$.yMin = config.axis_rotated ? 0 : $$.height;\n $$.yMax = config.axis_rotated ? $$.width : 1;\n $$.subXMin = $$.xMin;\n $$.subXMax = $$.xMax;\n $$.subYMin = config.axis_rotated ? 0 : $$.height2;\n $$.subYMax = config.axis_rotated ? $$.width2 : 1;\n // update scales\n $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), () => { return $$.xAxis.tickOffset(); });\n $$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain());\n $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain());\n $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, (d) => { return d % 1 ? 0 : $$.subXAxis.tickOffset(); });\n $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain());\n $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain());\n // update axes\n $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();\n $$.xAxisTickValues = $$.axis.getXAxisTickValues();\n $$.yAxisTickValues = $$.axis.getYAxisTickValues();\n $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();\n\n $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);\n $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);\n $$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer);\n $$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer);\n\n // Set initialized scales to brush and zoom\n if (!forInit) {\n if ($$.brush) { $$.brush.scale($$.subX); }\n if (config.zoom_enabled) { $$.zoom.scale($$.x); }\n }\n // update for arc\n if ($$.updateArc) { $$.updateArc(); }\n};\n\nexport {\n getScale,\n getX,\n getY,\n getYScale,\n getSubYScale,\n updateScales,\n};\n","import { CLASS } from './class';\n\nconst selectPoint = function (target, d, i) {\n let $$ = this, config = $$.config,\n cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),\n cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),\n r = $$.pointSelectR.bind($$);\n config.data_onselected.call($$.api, d, target.node());\n // add selected-circle on low layer g\n $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)\n .data([d])\n .enter().append('circle')\n .attr('class', () => { return $$.generateClass(CLASS.selectedCircle, i); })\n .attr('cx', cx)\n .attr('cy', cy)\n .attr('stroke', () => { return $$.color(d); })\n .attr('r', (d) => { return $$.pointSelectR(d) * 1.4; })\n .transition().duration(100)\n .attr('r', r);\n};\nconst unselectPoint = function (target, d, i) {\n const $$ = this;\n $$.config.data_onunselected.call($$.api, d, target.node());\n // remove selected-circle from low layer g\n $$.main.select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll('.' + CLASS.selectedCircle + '-' + i)\n .transition().duration(100).attr('r', 0)\n .remove();\n};\nconst togglePoint = function (selected, target, d, i) {\n selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);\n};\nconst selectPath = function (target, d) {\n const $$ = this;\n $$.config.data_onselected.call($$, d, target.node());\n if ($$.config.interaction_brighten) {\n target.transition().duration(100)\n .style('fill', () => { return $$.d3.rgb($$.color(d)).brighter(0.75); });\n }\n};\nconst unselectPath = function (target, d) {\n const $$ = this;\n $$.config.data_onunselected.call($$, d, target.node());\n if ($$.config.interaction_brighten) {\n target.transition().duration(100)\n .style('fill', () => { return $$.color(d); });\n }\n};\nconst togglePath = function (selected, target, d, i) {\n selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);\n};\nconst getToggle = function (that, d) {\n let $$ = this, toggle;\n if (that.nodeName === 'circle') {\n if ($$.isStepType(d)) {\n // circle is hidden in step chart, so treat as within the click area\n toggle = function () {}; // TODO: how to select step chart?\n } else {\n toggle = $$.togglePoint;\n }\n }\n else if (that.nodeName === 'path') {\n toggle = $$.togglePath;\n }\n return toggle;\n};\nconst toggleShape = function (that, d, i) {\n let $$ = this, d3 = $$.d3, config = $$.config,\n shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED),\n toggle = $$.getToggle(that, d).bind($$);\n\n if (config.data_selection_enabled && config.data_selection_isselectable(d)) {\n if (!config.data_selection_multiple) {\n $$.main.selectAll('.' + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : '')).selectAll('.' + CLASS.shape).each(function (d, i) {\n const shape = d3.select(this);\n if (shape.classed(CLASS.SELECTED)) { toggle(false, shape.classed(CLASS.SELECTED, false), d, i); }\n });\n }\n shape.classed(CLASS.SELECTED, !isSelected);\n toggle(!isSelected, shape, d, i);\n }\n};\n\nexport {\n selectPoint,\n unselectPoint,\n togglePoint,\n selectPath,\n unselectPath,\n togglePath,\n getToggle,\n toggleShape,\n};\n","import { CLASS } from './class';\nimport { isValue } from './util';\n\nconst initBar = function () {\n const $$ = this;\n $$.main.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartBars);\n};\nconst updateTargetsForBar = function (targets) {\n let $$ = this, config = $$.config,\n mainBarUpdate, mainBarEnter,\n classChartBar = $$.classChartBar.bind($$),\n classBars = $$.classBars.bind($$),\n classFocus = $$.classFocus.bind($$);\n mainBarUpdate = $$.main.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)\n .data(targets)\n .attr('class', (d) => { return classChartBar(d) + classFocus(d); });\n mainBarEnter = mainBarUpdate.enter().append('g')\n .attr('class', classChartBar)\n .style('opacity', 0)\n .style('pointer-events', 'none');\n // Bars for each data\n mainBarEnter.append('g')\n .attr('class', classBars)\n .style('cursor', (d) => { return config.data_selection_isselectable(d) ? 'pointer' : null; });\n};\nconst updateBar = function (durationForExit) {\n let $$ = this,\n barData = $$.barData.bind($$),\n classBar = $$.classBar.bind($$),\n initialOpacity = $$.initialOpacity.bind($$),\n color = function (d) { return $$.color(d.id); };\n $$.mainBar = $$.main.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)\n .data(barData);\n $$.mainBar.enter().append('path')\n .attr('class', classBar)\n .style('stroke', color)\n .style('fill', color);\n $$.mainBar\n .style('opacity', initialOpacity);\n $$.mainBar.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawBar = function (drawBar, withTransition) {\n return [\n (withTransition ? this.mainBar.transition(Math.random().toString()) : this.mainBar)\n .attr('d', drawBar)\n .style('fill', this.color)\n .style('opacity', 1),\n ];\n};\nconst getBarW = function (axis, barTargetsNum) {\n let $$ = this, config = $$.config,\n w = typeof config.bar_width === 'number' ? config.bar_width : barTargetsNum ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum : 0;\n return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;\n};\nconst getBars = function (i, id) {\n const $$ = this;\n return (id ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));\n};\nconst expandBars = function (i, id, reset) {\n const $$ = this;\n if (reset) { $$.unexpandBars(); }\n $$.getBars(i, id).classed(CLASS.EXPANDED, true);\n};\nconst unexpandBars = function (i) {\n const $$ = this;\n $$.getBars(i).classed(CLASS.EXPANDED, false);\n};\nconst generateDrawBar = function (barIndices, isSub) {\n let $$ = this, config = $$.config,\n getPoints = $$.generateGetBarPoints(barIndices, isSub);\n return function (d, i) {\n // 4 points that make a bar\n const points = getPoints(d, i);\n\n // switch points if axis is rotated, not applicable for sub chart\n const indexX = config.axis_rotated ? 1 : 0;\n const indexY = config.axis_rotated ? 0 : 1;\n\n const path = 'M ' + points[0][indexX] + ',' + points[0][indexY] + ' ' +\n 'L' + points[1][indexX] + ',' + points[1][indexY] + ' ' +\n 'L' + points[2][indexX] + ',' + points[2][indexY] + ' ' +\n 'L' + points[3][indexX] + ',' + points[3][indexY] + ' ' +\n 'z';\n\n return path;\n };\n};\nconst generateGetBarPoints = function (barIndices, isSub) {\n let $$ = this,\n axis = isSub ? $$.subXAxis : $$.xAxis,\n barTargetsNum = barIndices.__max__ + 1,\n barW = $$.getBarW(axis, barTargetsNum),\n barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),\n barY = $$.getShapeY(!!isSub),\n barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),\n yScale = isSub ? $$.getSubYScale : $$.getYScale;\n return function (d, i) {\n let y0 = yScale.call($$, d.id)(0),\n offset = barOffset(d, i) || y0, // offset is for stacked bar chart\n posX = barX(d), posY = barY(d);\n // fix posY not to overflow opposite quadrant\n if ($$.config.axis_rotated) {\n if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }\n }\n // 4 points that make a bar\n return [\n [posX, offset],\n [posX, posY - (y0 - offset)],\n [posX + barW, posY - (y0 - offset)],\n [posX + barW, offset],\n ];\n };\n};\nconst isWithinBar = function (that) {\n let mouse = this.d3.mouse(that), box = that.getBoundingClientRect(),\n seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1),\n x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y),\n w = box.width, h = box.height, offset = 2,\n sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset;\n return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;\n};\n\nexport {\n initBar,\n updateTargetsForBar,\n updateBar,\n redrawBar,\n getBarW,\n getBars,\n expandBars,\n unexpandBars,\n generateDrawBar,\n generateGetBarPoints,\n isWithinBar,\n};\n","import { CLASS } from './class';\nimport { isUndefined } from './util';\n\nconst getShapeIndices = function (typeFilter) {\n let $$ = this, config = $$.config,\n indices = {}, i = 0, j, k;\n $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach((d) => {\n for (j = 0; j < config.data_groups.length; j++) {\n if (config.data_groups[j].indexOf(d.id) < 0) { continue; }\n for (k = 0; k < config.data_groups[j].length; k++) {\n if (config.data_groups[j][k] in indices) {\n indices[d.id] = indices[config.data_groups[j][k]];\n break;\n }\n }\n }\n if (isUndefined(indices[d.id])) { indices[d.id] = i++; }\n });\n indices.__max__ = i - 1;\n return indices;\n};\nconst getShapeX = function (offset, targetsNum, indices, isSub) {\n let $$ = this, scale = isSub ? $$.subX : $$.x;\n return function (d) {\n const index = d.id in indices ? indices[d.id] : 0;\n return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;\n };\n};\nconst getShapeY = function (isSub) {\n const $$ = this;\n return function (d) {\n const scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);\n return scale(d.value);\n };\n};\nconst getShapeOffset = function (typeFilter, indices, isSub) {\n let $$ = this,\n targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))),\n targetIds = targets.map((t) => { return t.id; });\n return function (d, i) {\n let scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),\n y0 = scale(0), offset = y0;\n targets.forEach((t) => {\n const values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;\n if (t.id === d.id || indices[t.id] !== indices[d.id]) { return; }\n if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {\n // check if the x values line up\n if (typeof values[i] === 'undefined' || +values[i].x !== +d.x) { // \"+\" for timeseries\n // if not, try to find the value that does line up\n i = -1;\n values.forEach((v, j) => {\n if (v.x === d.x) {\n i = j;\n }\n });\n }\n if (i in values && values[i].value * d.value >= 0) {\n offset += scale(values[i].value) - y0;\n }\n }\n });\n return offset;\n };\n};\nconst isWithinShape = function (that, d) {\n let $$ = this,\n shape = $$.d3.select(that), isWithin;\n if (!$$.isTargetToShow(d.id)) {\n isWithin = false;\n }\n else if (that.nodeName === 'circle') {\n isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);\n }\n else if (that.nodeName === 'path') {\n isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true;\n }\n return isWithin;\n};\n\n\nconst getInterpolate = function (d) {\n let $$ = this,\n interpolation = $$.isInterpolationType($$.config.spline_interpolation_type) ? $$.config.spline_interpolation_type : 'cardinal';\n return $$.isSplineType(d) ? interpolation : $$.isStepType(d) ? $$.config.line_step_type : 'linear';\n};\n\nexport {\n getShapeIndices,\n getShapeX,\n getShapeY,\n getShapeOffset,\n isWithinShape,\n getInterpolate,\n};\n","import { CLASS } from './class';\nimport { isDefined, isUndefined, isValue, isFunction } from './util';\n\nconst initLine = function () {\n const $$ = this;\n $$.main.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartLines);\n};\nconst updateTargetsForLine = function (targets) {\n let $$ = this, config = $$.config,\n mainLineUpdate, mainLineEnter,\n classChartLine = $$.classChartLine.bind($$),\n classLines = $$.classLines.bind($$),\n classAreas = $$.classAreas.bind($$),\n classCircles = $$.classCircles.bind($$),\n classFocus = $$.classFocus.bind($$);\n mainLineUpdate = $$.main.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)\n .data(targets)\n .attr('class', (d) => { return classChartLine(d) + classFocus(d); });\n mainLineEnter = mainLineUpdate.enter().append('g')\n .attr('class', classChartLine)\n .style('opacity', 0)\n .style('pointer-events', 'none');\n // Lines for each data\n mainLineEnter.append('g')\n .attr('class', classLines);\n // Areas\n mainLineEnter.append('g')\n .attr('class', classAreas);\n // Circles for each data point on lines\n mainLineEnter.append('g')\n .attr('class', (d) => { return $$.generateClass(CLASS.selectedCircles, d.id); });\n mainLineEnter.append('g')\n .attr('class', classCircles)\n .style('cursor', (d) => { return config.data_selection_isselectable(d) ? 'pointer' : null; });\n // Update date for selected circles\n targets.forEach((t) => {\n $$.main.selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll('.' + CLASS.selectedCircle).each((d) => {\n d.value = t.values[d.index].value;\n });\n });\n // MEMO: can not keep same color...\n // mainLineUpdate.exit().remove();\n};\nconst updateLine = function (durationForExit) {\n const $$ = this;\n $$.mainLine = $$.main.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)\n .data($$.lineData.bind($$));\n $$.mainLine.enter().append('path')\n .attr('class', $$.classLine.bind($$))\n .style('stroke', $$.color);\n $$.mainLine\n .style('opacity', $$.initialOpacity.bind($$))\n .style('shape-rendering', (d) => { return $$.isStepType(d) ? 'crispEdges' : ''; })\n .attr('transform', null);\n $$.mainLine.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawLine = function (drawLine, withTransition) {\n return [\n (withTransition ? this.mainLine.transition(Math.random().toString()) : this.mainLine)\n .attr('d', drawLine)\n .style('stroke', this.color)\n .style('opacity', 1),\n ];\n};\nconst generateDrawLine = function (lineIndices, isSub) {\n let $$ = this, config = $$.config,\n line = $$.d3.svg.line(),\n getPoints = $$.generateGetLinePoints(lineIndices, isSub),\n yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,\n xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },\n yValue = function (d, i) {\n return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);\n };\n\n line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);\n if (!config.line_connectNull) { line = line.defined((d) => { return d.value != null; }); }\n return function (d) {\n let values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,\n x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;\n if ($$.isLineType(d)) {\n if (config.data_regions[d.id]) {\n path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);\n } else {\n if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }\n path = line.interpolate($$.getInterpolate(d))(values);\n }\n } else {\n if (values[0]) {\n x0 = x(values[0].x);\n y0 = y(values[0].value);\n }\n path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;\n }\n return path ? path : 'M 0 0';\n };\n};\nconst generateGetLinePoints = function (lineIndices, isSub) { // partial duplication of generateGetBarPoints\n let $$ = this, config = $$.config,\n lineTargetsNum = lineIndices.__max__ + 1,\n x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),\n y = $$.getShapeY(!!isSub),\n lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),\n yScale = isSub ? $$.getSubYScale : $$.getYScale;\n return function (d, i) {\n let y0 = yScale.call($$, d.id)(0),\n offset = lineOffset(d, i) || y0, // offset is for stacked area chart\n posX = x(d), posY = y(d);\n // fix posY not to overflow opposite quadrant\n if (config.axis_rotated) {\n if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }\n }\n // 1 point that marks the line position\n return [\n [posX, posY - (y0 - offset)],\n [posX, posY - (y0 - offset)], // needed for compatibility\n [posX, posY - (y0 - offset)], // needed for compatibility\n [posX, posY - (y0 - offset)], // needed for compatibility\n ];\n };\n};\n\n\nconst lineWithRegions = function (d, x, y, _regions) {\n let $$ = this, config = $$.config,\n prev = -1, i, j,\n s = 'M', sWithRegion,\n xp, yp, dx, dy, dd, diff, diffx2,\n xOffset = $$.isCategorized() ? 0.5 : 0,\n xValue, yValue,\n regions = [];\n\n function isWithinRegions(x, regions) {\n let i;\n for (i = 0; i < regions.length; i++) {\n if (regions[i].start < x && x <= regions[i].end) { return true; }\n }\n return false;\n }\n\n // Check start/end of regions\n if (isDefined(_regions)) {\n for (i = 0; i < _regions.length; i++) {\n regions[i] = {};\n if (isUndefined(_regions[i].start)) {\n regions[i].start = d[0].x;\n } else {\n regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;\n }\n if (isUndefined(_regions[i].end)) {\n regions[i].end = d[d.length - 1].x;\n } else {\n regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;\n }\n }\n }\n\n // Set scales\n xValue = config.axis_rotated ? function (d) { return y(d.value); } : function (d) { return x(d.x); };\n yValue = config.axis_rotated ? function (d) { return x(d.x); } : function (d) { return y(d.value); };\n\n // Define svg generator function for region\n function generateM(points) {\n return 'M' + points[0][0] + ' ' + points[0][1] + ' ' + points[1][0] + ' ' + points[1][1];\n }\n if ($$.isTimeSeries()) {\n sWithRegion = function (d0, d1, j, diff) {\n let x0 = d0.x.getTime(), x_diff = d1.x - d0.x,\n xv0 = new Date(x0 + x_diff * j),\n xv1 = new Date(x0 + x_diff * (j + diff)),\n points;\n if (config.axis_rotated) {\n points = [[y(yp(j)), x(xv0)], [y(yp(j + diff)), x(xv1)]];\n } else {\n points = [[x(xv0), y(yp(j))], [x(xv1), y(yp(j + diff))]];\n }\n return generateM(points);\n };\n } else {\n sWithRegion = function (d0, d1, j, diff) {\n let points;\n if (config.axis_rotated) {\n points = [[y(yp(j), true), x(xp(j))], [y(yp(j + diff), true), x(xp(j + diff))]];\n } else {\n points = [[x(xp(j), true), y(yp(j))], [x(xp(j + diff), true), y(yp(j + diff))]];\n }\n return generateM(points);\n };\n }\n\n // Generate\n for (i = 0; i < d.length; i++) {\n // Draw as normal\n if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {\n s += ' ' + xValue(d[i]) + ' ' + yValue(d[i]);\n }\n // Draw with region // TODO: Fix for horizotal charts\n else {\n xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());\n yp = $$.getScale(d[i - 1].value, d[i].value);\n\n dx = x(d[i].x) - x(d[i - 1].x);\n dy = y(d[i].value) - y(d[i - 1].value);\n dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n diff = 2 / dd;\n diffx2 = diff * 2;\n\n for (j = diff; j <= 1; j += diffx2) {\n s += sWithRegion(d[i - 1], d[i], j, diff);\n }\n }\n prev = d[i].x;\n }\n\n return s;\n};\n\n\nconst updateArea = function (durationForExit) {\n let $$ = this, d3 = $$.d3;\n $$.mainArea = $$.main.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)\n .data($$.lineData.bind($$));\n $$.mainArea.enter().append('path')\n .attr('class', $$.classArea.bind($$))\n .style('fill', $$.color)\n .style('opacity', function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });\n $$.mainArea\n .style('opacity', $$.orgAreaOpacity);\n $$.mainArea.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawArea = function (drawArea, withTransition) {\n return [\n (withTransition ? this.mainArea.transition(Math.random().toString()) : this.mainArea)\n .attr('d', drawArea)\n .style('fill', this.color)\n .style('opacity', this.orgAreaOpacity),\n ];\n};\nconst generateDrawArea = function (areaIndices, isSub) {\n let $$ = this, config = $$.config, area = $$.d3.svg.area(),\n getPoints = $$.generateGetAreaPoints(areaIndices, isSub),\n yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,\n xValue = function (d) { return (isSub ? $$.subxx : $$.xx).call($$, d); },\n value0 = function (d, i) {\n return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));\n },\n value1 = function (d, i) {\n return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);\n };\n\n area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1);\n if (!config.line_connectNull) {\n area = area.defined((d) => { return d.value !== null; });\n }\n\n return function (d) {\n let values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values,\n x0 = 0, y0 = 0, path;\n if ($$.isAreaType(d)) {\n if ($$.isStepType(d)) { values = $$.convertValuesToStep(values); }\n path = area.interpolate($$.getInterpolate(d))(values);\n } else {\n if (values[0]) {\n x0 = $$.x(values[0].x);\n y0 = $$.getYScale(d.id)(values[0].value);\n }\n path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;\n }\n return path ? path : 'M 0 0';\n };\n};\nconst getAreaBaseValue = function () {\n return 0;\n};\nconst generateGetAreaPoints = function (areaIndices, isSub) { // partial duplication of generateGetBarPoints\n let $$ = this, config = $$.config,\n areaTargetsNum = areaIndices.__max__ + 1,\n x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),\n y = $$.getShapeY(!!isSub),\n areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),\n yScale = isSub ? $$.getSubYScale : $$.getYScale;\n return function (d, i) {\n let y0 = yScale.call($$, d.id)(0),\n offset = areaOffset(d, i) || y0, // offset is for stacked area chart\n posX = x(d), posY = y(d);\n // fix posY not to overflow opposite quadrant\n if (config.axis_rotated) {\n if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) { posY = y0; }\n }\n // 1 point that marks the area position\n return [\n [posX, offset],\n [posX, posY - (y0 - offset)],\n [posX, posY - (y0 - offset)], // needed for compatibility\n [posX, offset], // needed for compatibility\n ];\n };\n};\n\n\nconst updateCircle = function () {\n const $$ = this;\n $$.mainCircle = $$.main.selectAll('.' + CLASS.circles).selectAll('.' + CLASS.circle)\n .data($$.lineOrScatterData.bind($$));\n $$.mainCircle.enter().append('circle')\n .attr('class', $$.classCircle.bind($$))\n .attr('r', $$.pointR.bind($$))\n .style('fill', $$.color);\n $$.mainCircle\n .style('opacity', $$.initialOpacityForCircle.bind($$));\n $$.mainCircle.exit().remove();\n};\nconst redrawCircle = function (cx, cy, withTransition) {\n const selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle);\n return [\n (withTransition ? this.mainCircle.transition(Math.random().toString()) : this.mainCircle)\n .style('opacity', this.opacityForCircle.bind(this))\n .style('fill', this.color)\n .attr('cx', cx)\n .attr('cy', cy),\n (withTransition ? selectedCircles.transition(Math.random().toString()) : selectedCircles)\n .attr('cx', cx)\n .attr('cy', cy),\n ];\n};\nconst circleX = function (d) {\n return d.x || d.x === 0 ? this.x(d.x) : null;\n};\nconst updateCircleY = function () {\n let $$ = this, lineIndices, getPoints;\n if ($$.config.data_groups.length > 0) {\n lineIndices = $$.getShapeIndices($$.isLineType),\n getPoints = $$.generateGetLinePoints(lineIndices);\n $$.circleY = function (d, i) {\n return getPoints(d, i)[0][1];\n };\n } else {\n $$.circleY = function (d) {\n return $$.getYScale(d.id)(d.value);\n };\n }\n};\nconst getCircles = function (i, id) {\n const $$ = this;\n return (id ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));\n};\nconst expandCircles = function (i, id, reset) {\n let $$ = this,\n r = $$.pointExpandedR.bind($$);\n if (reset) { $$.unexpandCircles(); }\n $$.getCircles(i, id)\n .classed(CLASS.EXPANDED, true)\n .attr('r', r);\n};\nconst unexpandCircles = function (i) {\n let $$ = this,\n r = $$.pointR.bind($$);\n $$.getCircles(i)\n .filter(function () { return $$.d3.select(this).classed(CLASS.EXPANDED); })\n .classed(CLASS.EXPANDED, false)\n .attr('r', r);\n};\nconst pointR = function (d) {\n let $$ = this, config = $$.config;\n return $$.isStepType(d) ? 0 : (isFunction(config.point_r) ? config.point_r(d) : config.point_r);\n};\nconst pointExpandedR = function (d) {\n let $$ = this, config = $$.config;\n return config.point_focus_expand_enabled ? (config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75) : $$.pointR(d);\n};\nconst pointSelectR = function (d) {\n let $$ = this, config = $$.config;\n return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4);\n};\nconst isWithinCircle = function (that, r) {\n let d3 = this.d3,\n mouse = d3.mouse(that), d3_this = d3.select(that),\n cx = +d3_this.attr('cx'), cy = +d3_this.attr('cy');\n return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;\n};\nconst isWithinStep = function (that, y) {\n return Math.abs(y - this.d3.mouse(that)[1]) < 30;\n};\n\nexport {\n initLine,\n updateTargetsForLine,\n updateLine,\n redrawLine,\n generateDrawLine,\n generateGetLinePoints,\n lineWithRegions,\n updateArea,\n redrawArea,\n generateDrawArea,\n getAreaBaseValue,\n generateGetAreaPoints,\n updateCircle,\n redrawCircle,\n circleX,\n updateCircleY,\n getCircles,\n expandCircles,\n unexpandCircles,\n pointR,\n pointExpandedR,\n pointSelectR,\n isWithinCircle,\n isWithinStep,\n};\n","import { isValue, ceil10 } from './util';\nimport { CLASS } from './class';\n\nconst getCurrentWidth = function () {\n let $$ = this, config = $$.config;\n return config.size_width ? config.size_width : $$.getParentWidth();\n};\nconst getCurrentHeight = function () {\n let $$ = this, config = $$.config,\n h = config.size_height ? config.size_height : $$.getParentHeight();\n return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);\n};\nconst getCurrentPaddingTop = function () {\n let $$ = this,\n config = $$.config,\n padding = isValue(config.padding_top) ? config.padding_top : 0;\n if ($$.title && $$.title.node()) {\n padding += $$.getTitlePadding();\n }\n return padding;\n};\nconst getCurrentPaddingBottom = function () {\n const config = this.config;\n return isValue(config.padding_bottom) ? config.padding_bottom : 0;\n};\nconst getCurrentPaddingLeft = function (withoutRecompute) {\n let $$ = this, config = $$.config;\n if (isValue(config.padding_left)) {\n return config.padding_left;\n } else if (config.axis_rotated) {\n return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);\n } else if (!config.axis_y_show || config.axis_y_inner) { // && !config.axis_rotated\n return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;\n } else {\n return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));\n }\n};\nconst getCurrentPaddingRight = function () {\n let $$ = this, config = $$.config,\n defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;\n if (isValue(config.padding_right)) {\n return config.padding_right + 1; // 1 is needed not to hide tick line\n } else if (config.axis_rotated) {\n return defaultPadding + legendWidthOnRight;\n } else if (!config.axis_y2_show || config.axis_y2_inner) { // && !config.axis_rotated\n return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);\n } else {\n return ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;\n }\n};\n\nconst getParentRectValue = function (key) {\n let parent = this.selectChart.node(), v;\n while (parent && parent.tagName !== 'BODY') {\n try {\n v = parent.getBoundingClientRect()[key];\n } catch (e) {\n if (key === 'width') {\n // In IE in certain cases getBoundingClientRect\n // will cause an \"unspecified error\"\n v = parent.offsetWidth;\n }\n }\n if (v) {\n break;\n }\n parent = parent.parentNode;\n }\n return v;\n};\nconst getParentWidth = function () {\n return this.getParentRectValue('width');\n};\nconst getParentHeight = function () {\n const h = this.selectChart.style('height');\n return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;\n};\n\n\nconst getSvgLeft = function (withoutRecompute) {\n let $$ = this, config = $$.config,\n hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner),\n leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,\n leftAxis = $$.main.select('.' + leftAxisClass).node(),\n svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : { right: 0 },\n chartRect = $$.selectChart.node().getBoundingClientRect(),\n hasArc = $$.hasArcType(),\n svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));\n return svgLeft > 0 ? svgLeft : 0;\n};\n\n\nconst getAxisWidthByAxisId = function (id, withoutRecompute) {\n let $$ = this, position = $$.axis.getLabelPositionById(id);\n return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40);\n};\nconst getHorizontalAxisHeight = function (axisId) {\n let $$ = this, config = $$.config, h = 30;\n if (axisId === 'x' && !config.axis_x_show) { return 8; }\n if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }\n if (axisId === 'y' && !config.axis_y_show) {\n return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;\n }\n if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }\n // Calculate x axis height when tick rotated\n if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {\n h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);\n }\n // Calculate y axis height when tick rotated\n if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {\n h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_y_tick_rotate) / 180);\n }\n return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);\n};\n\nconst getEventRectWidth = function () {\n return Math.max(0, this.xAxis.tickInterval());\n};\n\nexport {\n getCurrentWidth,\n getCurrentHeight,\n getCurrentPaddingTop,\n getCurrentPaddingBottom,\n getCurrentPaddingLeft,\n getCurrentPaddingRight,\n getParentRectValue,\n getParentWidth,\n getParentHeight,\n getSvgLeft,\n getAxisWidthByAxisId,\n getHorizontalAxisHeight,\n getEventRectWidth,\n};\n","import { CLASS } from './class';\nimport { isFunction } from './util';\n\nconst initBrush = function () {\n let $$ = this, d3 = $$.d3;\n $$.brush = d3.svg.brush().on('brush', () => { $$.redrawForBrush(); });\n $$.brush.update = function () {\n if ($$.context) { $$.context.select('.' + CLASS.brush).call(this); }\n return this;\n };\n $$.brush.scale = function (scale) {\n return $$.config.axis_rotated ? this.y(scale) : this.x(scale);\n };\n};\nconst initSubchart = function () {\n let $$ = this, config = $$.config,\n context = $$.context = $$.svg.append('g').attr('transform', $$.getTranslate('context')),\n visibility = config.subchart_show ? 'visible' : 'hidden';\n\n context.style('visibility', visibility);\n\n // Define g for chart area\n context.append('g')\n .attr('clip-path', $$.clipPathForSubchart)\n .attr('class', CLASS.chart);\n\n // Define g for bar chart area\n context.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartBars);\n\n // Define g for line chart area\n context.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartLines);\n\n // Add extent rect for Brush\n context.append('g')\n .attr('clip-path', $$.clipPath)\n .attr('class', CLASS.brush)\n .call($$.brush);\n\n // ATTENTION: This must be called AFTER chart added\n // Add Axis\n $$.axes.subx = context.append('g')\n .attr('class', CLASS.axisX)\n .attr('transform', $$.getTranslate('subx'))\n .attr('clip-path', config.axis_rotated ? '' : $$.clipPathForXAxis)\n .style('visibility', config.subchart_axis_x_show ? visibility : 'hidden');\n};\nconst updateTargetsForSubchart = function (targets) {\n let $$ = this, context = $$.context, config = $$.config,\n contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate,\n classChartBar = $$.classChartBar.bind($$),\n classBars = $$.classBars.bind($$),\n classChartLine = $$.classChartLine.bind($$),\n classLines = $$.classLines.bind($$),\n classAreas = $$.classAreas.bind($$);\n\n if (config.subchart_show) {\n // -- Bar --//\n contextBarUpdate = context.select('.' + CLASS.chartBars).selectAll('.' + CLASS.chartBar)\n .data(targets)\n .attr('class', classChartBar);\n contextBarEnter = contextBarUpdate.enter().append('g')\n .style('opacity', 0)\n .attr('class', classChartBar);\n // Bars for each data\n contextBarEnter.append('g')\n .attr('class', classBars);\n\n // -- Line --//\n contextLineUpdate = context.select('.' + CLASS.chartLines).selectAll('.' + CLASS.chartLine)\n .data(targets)\n .attr('class', classChartLine);\n contextLineEnter = contextLineUpdate.enter().append('g')\n .style('opacity', 0)\n .attr('class', classChartLine);\n // Lines for each data\n contextLineEnter.append('g')\n .attr('class', classLines);\n // Area\n contextLineEnter.append('g')\n .attr('class', classAreas);\n\n // -- Brush --//\n context.selectAll('.' + CLASS.brush + ' rect')\n .attr(config.axis_rotated ? 'width' : 'height', config.axis_rotated ? $$.width2 : $$.height2);\n }\n};\nconst updateBarForSubchart = function (durationForExit) {\n const $$ = this;\n $$.contextBar = $$.context.selectAll('.' + CLASS.bars).selectAll('.' + CLASS.bar)\n .data($$.barData.bind($$));\n $$.contextBar.enter().append('path')\n .attr('class', $$.classBar.bind($$))\n .style('stroke', 'none')\n .style('fill', $$.color);\n $$.contextBar\n .style('opacity', $$.initialOpacity.bind($$));\n $$.contextBar.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {\n (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar)\n .attr('d', drawBarOnSub)\n .style('opacity', 1);\n};\nconst updateLineForSubchart = function (durationForExit) {\n const $$ = this;\n $$.contextLine = $$.context.selectAll('.' + CLASS.lines).selectAll('.' + CLASS.line)\n .data($$.lineData.bind($$));\n $$.contextLine.enter().append('path')\n .attr('class', $$.classLine.bind($$))\n .style('stroke', $$.color);\n $$.contextLine\n .style('opacity', $$.initialOpacity.bind($$));\n $$.contextLine.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {\n (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine)\n .attr('d', drawLineOnSub)\n .style('opacity', 1);\n};\nconst updateAreaForSubchart = function (durationForExit) {\n let $$ = this, d3 = $$.d3;\n $$.contextArea = $$.context.selectAll('.' + CLASS.areas).selectAll('.' + CLASS.area)\n .data($$.lineData.bind($$));\n $$.contextArea.enter().append('path')\n .attr('class', $$.classArea.bind($$))\n .style('fill', $$.color)\n .style('opacity', function () { $$.orgAreaOpacity = +d3.select(this).style('opacity'); return 0; });\n $$.contextArea\n .style('opacity', 0);\n $$.contextArea.exit().transition().duration(durationForExit)\n .style('opacity', 0)\n .remove();\n};\nconst redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {\n (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea)\n .attr('d', drawAreaOnSub)\n .style('fill', this.color)\n .style('opacity', this.orgAreaOpacity);\n};\nconst redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {\n let $$ = this, d3 = $$.d3, config = $$.config,\n drawAreaOnSub, drawBarOnSub, drawLineOnSub;\n\n $$.context.style('visibility', config.subchart_show ? 'visible' : 'hidden');\n\n // subchart\n if (config.subchart_show) {\n // reflect main chart to extent on subchart if zoomed\n if (d3.event && d3.event.type === 'zoom') {\n $$.brush.extent($$.x.orgDomain()).update();\n }\n // update subchart elements if needed\n if (withSubchart) {\n // extent rect\n if (!$$.brush.empty()) {\n $$.brush.extent($$.x.orgDomain()).update();\n }\n // setup drawer - MEMO: this must be called after axis updated\n drawAreaOnSub = $$.generateDrawArea(areaIndices, true);\n drawBarOnSub = $$.generateDrawBar(barIndices, true);\n drawLineOnSub = $$.generateDrawLine(lineIndices, true);\n\n $$.updateBarForSubchart(duration);\n $$.updateLineForSubchart(duration);\n $$.updateAreaForSubchart(duration);\n\n $$.redrawBarForSubchart(drawBarOnSub, duration, duration);\n $$.redrawLineForSubchart(drawLineOnSub, duration, duration);\n $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);\n }\n }\n};\nconst redrawForBrush = function () {\n let $$ = this, x = $$.x;\n $$.redraw({\n withTransition: false,\n withY: $$.config.zoom_rescale,\n withSubchart: false,\n withUpdateXDomain: true,\n withDimension: false,\n });\n $$.config.subchart_onbrush.call($$.api, x.orgDomain());\n};\nconst transformContext = function (withTransition, transitions) {\n let $$ = this, subXAxis;\n if (transitions && transitions.axisSubX) {\n subXAxis = transitions.axisSubX;\n } else {\n subXAxis = $$.context.select('.' + CLASS.axisX);\n if (withTransition) { subXAxis = subXAxis.transition(); }\n }\n $$.context.attr('transform', $$.getTranslate('context'));\n subXAxis.attr('transform', $$.getTranslate('subx'));\n};\nconst getDefaultExtent = function () {\n let $$ = this, config = $$.config,\n extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent;\n if ($$.isTimeSeries()) {\n extent = [$$.parseDate(extent[0]), $$.parseDate(extent[1])];\n }\n return extent;\n};\n\nexport {\n initBrush,\n initSubchart,\n updateTargetsForSubchart,\n updateBarForSubchart,\n redrawBarForSubchart,\n updateLineForSubchart,\n redrawLineForSubchart,\n updateAreaForSubchart,\n redrawAreaForSubchart,\n redrawSubchart,\n redrawForBrush,\n transformContext,\n getDefaultExtent,\n};\n","import { CLASS } from './class';\n\nconst initText = function () {\n const $$ = this;\n $$.main.select('.' + CLASS.chart).append('g')\n .attr('class', CLASS.chartTexts);\n $$.mainText = $$.d3.selectAll([]);\n};\nconst updateTargetsForText = function (targets) {\n let $$ = this, mainTextUpdate, mainTextEnter,\n classChartText = $$.classChartText.bind($$),\n classTexts = $$.classTexts.bind($$),\n classFocus = $$.classFocus.bind($$);\n mainTextUpdate = $$.main.select('.' + CLASS.chartTexts).selectAll('.' + CLASS.chartText)\n .data(targets)\n .attr('class', (d) => { return classChartText(d) + classFocus(d); });\n mainTextEnter = mainTextUpdate.enter().append('g')\n .attr('class', classChartText)\n .style('opacity', 0)\n .style('pointer-events', 'none');\n mainTextEnter.append('g')\n .attr('class', classTexts);\n};\nconst updateText = function (durationForExit) {\n let $$ = this, config = $$.config,\n barOrLineData = $$.barOrLineData.bind($$),\n classText = $$.classText.bind($$);\n $$.mainText = $$.main.selectAll('.' + CLASS.texts).selectAll('.' + CLASS.text)\n .data(barOrLineData);\n $$.mainText.enter().append('text')\n .attr('class', classText)\n .attr('text-anchor', (d) => { return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'; })\n .style('stroke', 'none')\n .style('fill', (d) => { return $$.color(d); })\n .style('fill-opacity', 0);\n $$.mainText\n .text((d, i, j) => { return $$.dataLabelFormat(d.id)(d.value, d.id, i, j); });\n $$.mainText.exit()\n .transition().duration(durationForExit)\n .style('fill-opacity', 0)\n .remove();\n};\nconst redrawText = function (xForText, yForText, forFlow, withTransition) {\n return [\n (withTransition ? this.mainText.transition() : this.mainText)\n .attr('x', xForText)\n .attr('y', yForText)\n .style('fill', this.color)\n .style('fill-opacity', forFlow ? 0 : this.opacityForText.bind(this)),\n ];\n};\nconst getTextRect = function (text, cls, element) {\n let dummy = this.d3.select('body').append('div').classed('c3', true),\n svg = dummy.append('svg').style('visibility', 'hidden').style('position', 'fixed').style('top', 0).style('left', 0),\n font = this.d3.select(element).style('font'),\n rect;\n svg.selectAll('.dummy')\n .data([text])\n .enter().append('text')\n .classed(cls ? cls : '', true)\n .style('font', font)\n .text(text)\n .each(function () { rect = this.getBoundingClientRect(); });\n dummy.remove();\n return rect;\n};\nconst generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {\n let $$ = this,\n getAreaPoints = $$.generateGetAreaPoints(areaIndices, false),\n getBarPoints = $$.generateGetBarPoints(barIndices, false),\n getLinePoints = $$.generateGetLinePoints(lineIndices, false),\n getter = forX ? $$.getXForText : $$.getYForText;\n return function (d, i) {\n const getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints;\n return getter.call($$, getPoints(d, i), d, this);\n };\n};\nconst getXForText = function (points, d, textElement) {\n let $$ = this,\n box = textElement.getBoundingClientRect(), xPos, padding;\n if ($$.config.axis_rotated) {\n padding = $$.isBarType(d) ? 4 : 6;\n xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);\n } else {\n xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];\n }\n // show labels regardless of the domain if value is null\n if (d.value === null) {\n if (xPos > $$.width) {\n xPos = $$.width - box.width;\n } else if (xPos < 0) {\n xPos = 4;\n }\n }\n return xPos;\n};\nconst getYForText = function (points, d, textElement) {\n let $$ = this,\n box = textElement.getBoundingClientRect(),\n yPos;\n if ($$.config.axis_rotated) {\n yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;\n } else {\n yPos = points[2][1];\n if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {\n yPos += box.height;\n if ($$.isBarType(d) && $$.isSafari()) {\n yPos -= 3;\n }\n else if (!$$.isBarType(d) && $$.isChrome()) {\n yPos += 3;\n }\n } else {\n yPos += $$.isBarType(d) ? -3 : -6;\n }\n }\n // show labels regardless of the domain if value is null\n if (d.value === null && !$$.config.axis_rotated) {\n if (yPos < box.height) {\n yPos = box.height;\n } else if (yPos > this.height) {\n yPos = this.height - 4;\n }\n }\n return yPos;\n};\n\nexport {\n initText,\n updateTargetsForText,\n updateText,\n redrawText,\n getTextRect,\n generateXYForText,\n getXForText,\n getYForText,\n};\n","const initTitle = function () {\n const $$ = this;\n $$.title = $$.svg.append('text')\n .text($$.config.title_text)\n .attr('class', $$.CLASS.title);\n};\nconst redrawTitle = function () {\n const $$ = this;\n $$.title\n .attr('x', $$.xForTitle.bind($$))\n .attr('y', $$.yForTitle.bind($$));\n};\nconst xForTitle = function () {\n let $$ = this, config = $$.config, position = config.title_position || 'left', x;\n if (position.indexOf('right') >= 0) {\n x = $$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width - config.title_padding.right;\n } else if (position.indexOf('center') >= 0) {\n x = ($$.currentWidth - $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) / 2;\n } else { // left\n x = config.title_padding.left;\n }\n return x;\n};\nconst yForTitle = function () {\n const $$ = this;\n return $$.config.title_padding.top + $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).height;\n};\nconst getTitlePadding = function () {\n const $$ = this;\n return $$.yForTitle() + $$.config.title_padding.bottom;\n};\n\nexport {\n initTitle,\n redrawTitle,\n xForTitle,\n yForTitle,\n getTitlePadding,\n};\n","import { isString, sanitise, isValue } from './util';\nimport { CLASS } from './class';\nimport { c3_chart_internal_fn } from './index';\n\nconst initTooltip = function () {\n let $$ = this, config = $$.config, i;\n $$.tooltip = $$.selectChart\n .style('position', 'relative')\n .append('div')\n .attr('class', CLASS.tooltipContainer)\n .style('position', 'absolute')\n .style('pointer-events', 'none')\n .style('display', 'none');\n // Show tooltip if needed\n if (config.tooltip_init_show) {\n if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {\n config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);\n for (i = 0; i < $$.data.targets[0].values.length; i++) {\n if (($$.data.targets[0].values[i].x - config.tooltip_init_x) === 0) { break; }\n }\n config.tooltip_init_x = i;\n }\n $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map((d) => {\n return $$.addName(d.values[config.tooltip_init_x]);\n }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));\n $$.tooltip.style('top', config.tooltip_init_position.top)\n .style('left', config.tooltip_init_position.left)\n .style('display', 'block');\n }\n};\nconst getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {\n let $$ = this, config = $$.config,\n titleFormat = config.tooltip_format_title || defaultTitleFormat,\n nameFormat = config.tooltip_format_name || function (name) { return name; },\n valueFormat = config.tooltip_format_value || defaultValueFormat,\n text, i, title, value, name, bgcolor,\n orderAsc = $$.isOrderAsc();\n\n if (config.data_groups.length === 0) {\n d.sort((a, b) => {\n let v1 = a ? a.value : null, v2 = b ? b.value : null;\n return orderAsc ? v1 - v2 : v2 - v1;\n });\n } else {\n const ids = $$.orderTargets($$.data.targets).map((i) => {\n return i.id;\n });\n d.sort((a, b) => {\n let v1 = a ? a.value : null, v2 = b ? b.value : null;\n if (v1 > 0 && v2 > 0) {\n v1 = a ? ids.indexOf(a.id) : null;\n v2 = b ? ids.indexOf(b.id) : null;\n }\n return orderAsc ? v1 - v2 : v2 - v1;\n });\n }\n\n for (i = 0; i < d.length; i++) {\n if (!(d[i] && (d[i].value || d[i].value === 0))) { continue; }\n\n if (!text) {\n title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);\n text = \"
\" + title + ' | |
---|---|
\" + name + ' | ';\n text += \"\" + value + ' | ';\n text += '