diff --git a/src/Chart/api/load.ts b/src/Chart/api/load.ts index cbdbcad2f..8eca6bcbb 100644 --- a/src/Chart/api/load.ts +++ b/src/Chart/api/load.ts @@ -3,7 +3,7 @@ * billboard.js project is licensed under the MIT license */ import {requestIdleCallback} from "../../module/browser"; -import {isString, isArray} from "../../module/util"; +import {isString, isArray, isEmpty} from "../../module/util"; import {callDone} from "../../ChartInternal/data/load"; export default { @@ -182,7 +182,6 @@ export default { requestIdleCallback(() => $$.loadFromArgs(args)); }); } else { - // $$.api.tooltip.hide(); $$.loadFromArgs(args); } }, @@ -216,6 +215,9 @@ export default { const $$ = this.internal; let args = argsValue || {}; + // hide possible tooltip display when data is completely unloaded + isEmpty(args) && this.tooltip.hide(); + if (isArray(args)) { args = {ids: args}; } else if (isString(args)) { diff --git a/src/Chart/api/tooltip.ts b/src/Chart/api/tooltip.ts index 845ee27aa..2c7bd9ffc 100644 --- a/src/Chart/api/tooltip.ts +++ b/src/Chart/api/tooltip.ts @@ -2,7 +2,7 @@ * Copyright (c) 2017 ~ present NAVER Corp. * billboard.js project is licensed under the MIT license */ -import {isValue, isDefined} from "../../module/util"; +import {isDefined} from "../../module/util"; /** * Define tooltip @@ -48,6 +48,10 @@ const tooltip = { * } * }); * + * // for Arc types, specify 'id' or 'index' + * chart.tooltip.show({ data: { id: "data2" }}); + * chart.tooltip.show({ data: { index: 2 }}); + * * // when data.xs is used * chart.tooltip.show({ * data: { @@ -80,7 +84,7 @@ const tooltip = { // determine focus data if (args.data) { const {data} = args; - const y = $$.getYScaleById(data.id)(data.value); + const y = $$.getYScaleById(data.id)?.(data.value); if (hasTreemap && data.id) { eventReceiver.rect = $el.main.select(`${$$.selectorTarget(data.id, undefined, "rect")}`); @@ -92,7 +96,11 @@ const tooltip = { mouse = [0, y]; } - index = isValue(data.index) ? data.index : $$.getIndexByX(data.x); + index = data.index ?? ( + $$.hasArcType() && data.id ? + $$.getArcElementByIdOrIndex(data.id)?.datum().index : + $$.getIndexByX(data.x) + ); } } else if (isDefined(args.x)) { index = $$.getIndexByX(args.x); diff --git a/src/ChartInternal/data/data.ts b/src/ChartInternal/data/data.ts index 4df474f02..02e2cba4a 100644 --- a/src/ChartInternal/data/data.ts +++ b/src/ChartInternal/data/data.ts @@ -2,6 +2,7 @@ * Copyright (c) 2017 ~ present NAVER Corp. * billboard.js project is licensed under the MIT license */ +import {select as d3Select} from "d3-selection"; import {$BAR, $CANDLESTICK, $COMMON} from "../../config/classes"; import {KEY} from "../../module/Cache"; import type {IData, IDataPoint, IDataRow} from "./IData"; @@ -664,18 +665,34 @@ export default { */ getDataIndexFromEvent(event): number { const $$ = this; - const {config, state: {inputType, eventReceiver: {coords, rect}}} = $$; - const isRotated = config.axis_rotated; - - // get data based on the mouse coords - const e = inputType === "touch" && event.changedTouches ? event.changedTouches[0] : event; - const index = findIndex( - coords, - isRotated ? e.clientY - rect.top : e.clientX - rect.left, - 0, - coords.length - 1, - isRotated - ); + const {config, state: {hasRadar, inputType, eventReceiver: {coords, rect}}} = $$; + let index; + + if (hasRadar) { + let target = event.target; + + // in case of multilined axis text + if (/tspan/i.test(target.tagName)) { + target = target.parentNode; + } + + const d: any = d3Select(target).datum(); + + index = d && Object.keys(d).length === 1 ? d.index : undefined; + } else { + const isRotated = config.axis_rotated; + + // get data based on the mouse coords + const e = inputType === "touch" && event.changedTouches ? event.changedTouches[0] : event; + + index = findIndex( + coords, + isRotated ? e.clientY - rect.top : e.clientX - rect.left, + 0, + coords.length - 1, + isRotated + ); + } return index; }, diff --git a/src/ChartInternal/interactions/eventrect.ts b/src/ChartInternal/interactions/eventrect.ts index 03742271b..6bb1ef088 100644 --- a/src/ChartInternal/interactions/eventrect.ts +++ b/src/ChartInternal/interactions/eventrect.ts @@ -61,7 +61,7 @@ export default { $el.eventRect = eventRectUpdate; if ($$.state.inputType === "touch" && !$el.svg.on("touchstart.eventRect") && !$$.hasArcType()) { - $$.bindTouchOnEventRect(isMultipleX); + $$.bindTouchOnEventRect(); } // when initilazed with empty data and data loaded later, need to update eventRect @@ -87,12 +87,12 @@ export default { $$.updateEventRectData(); }, - bindTouchOnEventRect(isMultipleX: boolean): void { + bindTouchOnEventRect(): void { const $$ = this; const {config, state, $el: {eventRect, svg}} = $$; const selectRect = context => { - if (isMultipleX) { + if ($$.isMultipleX()) { $$.selectRectForMultipleXs(context); } else { const index = $$.getDataIndexFromEvent(state.event); @@ -101,7 +101,7 @@ export default { index === -1 ? $$.unselectRect() : - $$.selectRectForSingle(context, eventRect, index); + $$.selectRectForSingle(context, index); } }; @@ -313,7 +313,74 @@ export default { }); }, - selectRectForMultipleXs(context): void { + /** + * Seletct rect for single x value + * @param {d3Selection} context Event rect element + * @param {number} index x Axis index + * @private + */ + selectRectForSingle(context: SVGRectElement, index: number): void { + const $$ = this; + const {config, $el: {main, circle}} = $$; + const isSelectionEnabled = config.data_selection_enabled; + const isSelectionGrouped = config.data_selection_grouped; + const isSelectable = config.data_selection_isselectable; + const isTooltipGrouped = config.tooltip_grouped; + const selectedData = $$.getAllValuesOnIndex(index); + + if (isTooltipGrouped) { + $$.showTooltip(selectedData, context); + $$.showGridFocus?.(selectedData); + + if (!isSelectionEnabled || isSelectionGrouped) { + return; + } + } + + // remove possible previous focused state + !circle && main.selectAll(`.${$COMMON.EXPANDED}:not(.${$SHAPE.shape}-${index})`).classed($COMMON.EXPANDED, false); + + const shapeAtIndex = main.selectAll(`.${$SHAPE.shape}-${index}`) + .classed($COMMON.EXPANDED, true) + .style("cursor", isSelectable ? "pointer" : null) + .filter(function(d) { + return $$.isWithinShape(this, d); + }); + + if (shapeAtIndex.empty() && !isTooltipGrouped) { + $$.hideGridFocus?.(); + $$.hideTooltip(); + + !isSelectionGrouped && $$.setExpand(index); + } + + shapeAtIndex + .call(selected => { + const d = selected.data(); + + if (isSelectionEnabled && + (isSelectionGrouped || isSelectable?.bind($$.api)(d)) + ) { + context.style.cursor = "pointer"; + } + + if (!isTooltipGrouped) { + $$.showTooltip(d, context); + $$.showGridFocus?.(d); + $$.unexpandCircles?.(); + + selected.each(d => $$.setExpand(index, d.id)); + } + }); + }, + + /** + * Select rect for multiple x values + * @param {d3Selection} context Event rect element + * @param {boolean} [triggerEvent=true] Whether trigger event or not + * @private + */ + selectRectForMultipleXs(context: SVGRectElement, triggerEvent = true): void { const $$ = this; const {config, state} = $$; const targetsToShow = $$.filterTargetsToShow($$.data.targets); @@ -326,7 +393,7 @@ export default { const mouse = getPointer(state.event, context); const closest = $$.findClosestFromTargets(targetsToShow, mouse); - if (state.mouseover && (!closest || closest.id !== state.mouseover.id)) { + if (triggerEvent && state.mouseover && (!closest || closest.id !== state.mouseover.id)) { config.data_onout.call($$.api, state.mouseover); state.mouseover = undefined; } @@ -357,7 +424,7 @@ export default { if ($$.isBarType(closest.id) || dist < $$.getPointSensitivity(closest)) { $$.$el.svg.select(`.${$EVENT.eventRect}`).style("cursor", "pointer"); - if (!state.mouseover) { + if (triggerEvent && !state.mouseover) { config.data_onover.call($$.api, closest); state.mouseover = closest; } @@ -461,7 +528,7 @@ export default { } index === -1 ? - $$.unselectRect() : $$.selectRectForSingle(this, rect, index); + $$.unselectRect() : $$.selectRectForSingle(this, index); // As of individual data point(or ) element can't bind mouseover/out event // to determine current interacting element, so use 'mousemove' event instead. diff --git a/src/ChartInternal/interactions/interaction.ts b/src/ChartInternal/interactions/interaction.ts index 6d13d13ab..9586124fd 100644 --- a/src/ChartInternal/interactions/interaction.ts +++ b/src/ChartInternal/interactions/interaction.ts @@ -10,61 +10,6 @@ import {emulateEvent, getPointer, isNumber, isObject} from "../../module/util"; import type {IArcDataRow} from "../data/IData"; export default { - selectRectForSingle(context, eventRect, index: number): void { - const $$ = this; - const {config, $el: {main, circle}} = $$; - const isSelectionEnabled = config.data_selection_enabled; - const isSelectionGrouped = config.data_selection_grouped; - const isSelectable = config.data_selection_isselectable; - const isTooltipGrouped = config.tooltip_grouped; - const selectedData = $$.getAllValuesOnIndex(index); - - if (isTooltipGrouped) { - $$.showTooltip(selectedData, context); - $$.showGridFocus?.(selectedData); - - if (!isSelectionEnabled || isSelectionGrouped) { - return; - } - } - - // remove possible previous focused state - !circle && main.selectAll(`.${$COMMON.EXPANDED}:not(.${$SHAPE.shape}-${index})`).classed($COMMON.EXPANDED, false); - - const shapeAtIndex = main.selectAll(`.${$SHAPE.shape}-${index}`) - .classed($COMMON.EXPANDED, true) - .style("cursor", isSelectable ? "pointer" : null) - .filter(function(d) { - return $$.isWithinShape(this, d); - }); - - if (shapeAtIndex.empty() && !isTooltipGrouped) { - $$.hideGridFocus?.(); - $$.hideTooltip(); - - !isSelectionGrouped && $$.setExpand(index); - } - - shapeAtIndex - .call(selected => { - const d = selected.data(); - - if (isSelectionEnabled && - (isSelectionGrouped || isSelectable?.bind($$.api)(d)) - ) { - eventRect.style("cursor", "pointer"); - } - - if (!isTooltipGrouped) { - $$.showTooltip(d, context); - $$.showGridFocus?.(d); - $$.unexpandCircles?.(); - - selected.each(d => $$.setExpand(index, d.id)); - } - }); - }, - /** * Expand data shape/point * @param {number} index Index number @@ -225,11 +170,11 @@ export default { const $$ = this; const {config, state: { eventReceiver, hasAxis, hasRadar, hasTreemap - }, $el: {eventRect, arcs, radar, treemap}} = $$; + }, $el: {eventRect, radar, treemap}} = $$; const element = ( (hasTreemap && eventReceiver.rect) || (hasRadar && radar.axes.select(`.${$AXIS.axis}-${index} text`)) || ( - eventRect || arcs?.selectAll(`.${$COMMON.target} path`).filter((d, i) => i === index) + eventRect || $$.getArcElementByIdOrIndex?.(index) ) )?.node(); diff --git a/src/ChartInternal/internals/redraw.ts b/src/ChartInternal/internals/redraw.ts index 60c7b1dca..77fa34fca 100644 --- a/src/ChartInternal/internals/redraw.ts +++ b/src/ChartInternal/internals/redraw.ts @@ -105,6 +105,8 @@ export default { initializing && $$.updateTypesElements(); $$.generateRedrawList(targetsToShow, flow, duration, wth.Subchart); + $$.updateTooltipOnRedraw(); + $$.callPluginHook("$redraw", options, duration); }, diff --git a/src/ChartInternal/internals/tooltip.ts b/src/ChartInternal/internals/tooltip.ts index a3036b91e..37dde4914 100644 --- a/src/ChartInternal/internals/tooltip.ts +++ b/src/ChartInternal/internals/tooltip.ts @@ -5,7 +5,7 @@ import {select as d3Select} from "d3-selection"; import {document} from "../../module/browser"; import {$ARC, $TOOLTIP} from "../../config/classes"; -import type {IDataRow} from "../data/IData"; +import type {IArcData, IDataRow} from "../data/IData"; import {getPointer, isFunction, isObject, isString, isValue, callFn, sanitise, tplProcess, isUndefined, parseDate} from "../../module/util"; export default { @@ -270,7 +270,7 @@ export default { const datum = tooltip.datum(); if (!bindto && datum) { - const [x, y] = getPointer(state.event, eventTarget ?? eventRect.node()); // get mouse event position + const [x, y] = getPointer(state.event, eventTarget ?? eventRect?.node()); // get mouse event position const currPos: {x: number, y: number, xAxis?: number} = {x, y}; if (scale.x && datum && "x" in datum) { @@ -494,5 +494,61 @@ export default { } }); } + }, + + /** + * Update tooltip content on redraw + * - In a situation where tooltip is displayed and data load happens, it should reflect loaded data to tooltip + * @param {d3Selection} context Event rect element + * @param {number} index Data index + * @private + */ + updateTooltipOnRedraw(context?: SVGRectElement, index?: number): void { + const $$ = this; + const { + config, + $el: {eventRect, svg, tooltip}, + state: {event, hasAxis, hasRadar, hasTreemap} + } = $$; + + // Update tooltip, when tooltip is in shown state + if (tooltip?.style("display") === "block" && event) { + const rect = context ?? (hasRadar ? svg : eventRect)?.node(); + + // for Axis based & Radar + if (hasAxis || hasRadar) { + if ($$.isMultipleX()) { + $$.selectRectForMultipleXs(rect, false); + } else { + const idx = index ?? $$.getDataIndexFromEvent(event); + + if (index === -1) { + $$.api.tooltip.hide(); + } else { + $$.selectRectForSingle(rect, idx); + $$.setExpand(idx, null, true); + } + } + + // for Arc & Treemap + } else { + const {clientX, clientY} = event; + + setTimeout(() => { + let target = document.elementFromPoint(clientX, clientY); + const data = d3Select(target).datum() as IArcData; + + if (data) { + const d = $$.hasArcType() ? + $$.convertToArcData($$.updateAngle(data)) : data?.data; + + hasTreemap && (target = svg.node()); + d && $$.showTooltip([d], target); + } else { + $$.api.tooltip.hide(); + } + }, config.transition_duration); + } + } } }; diff --git a/src/ChartInternal/shape/arc.ts b/src/ChartInternal/shape/arc.ts index 6dc9d5bd8..434a8b522 100644 --- a/src/ChartInternal/shape/arc.ts +++ b/src/ChartInternal/shape/arc.ts @@ -694,7 +694,8 @@ export default { .style("opacity", "0") .remove(); - mainArc = mainArc.enter().append("path") + mainArc = mainArc.enter() + .append("path") .attr("class", $$.getClass("arc", true)) .style("fill", d => $$.color(d.data)) .style("cursor", d => (isSelectable?.bind?.($$.api)(d) ? "pointer" : null)) @@ -771,7 +772,7 @@ export default { .call(endall, function() { if ($$.levelColor) { const path = d3Select(this); - const d: any = path.datum(); + const d: any = path.datum(this._current); $$.updateLegendItemColor(d.data.id, path.style("fill")); } @@ -1109,5 +1110,22 @@ export default { .text($$.textForGaugeMinMax(config.gauge_max, true)); } } + }, + + /** + * Get Arc element by id or index + * @param {string|number} value id or index of Arc + * @returns {d3Selection} Arc path element + * @private + */ + getArcElementByIdOrIndex(value: string | number): d3Selection { + const $$ = this; + const {$el: {arcs}} = $$; + const filterFn = isNumber(value) ? + d => d.index === value : + d => d.data.id === value; + + return arcs?.selectAll(`.${$COMMON.target} path`) + .filter(filterFn); } }; diff --git a/src/ChartInternal/shape/radar.ts b/src/ChartInternal/shape/radar.ts index 17d593d6c..450864e88 100644 --- a/src/ChartInternal/shape/radar.ts +++ b/src/ChartInternal/shape/radar.ts @@ -301,22 +301,13 @@ export default { if (config.interaction_enabled) { const isMouse = inputType === "mouse"; - const getIndex = event => { - let target = event.target; - // in case of multilined axis text - if (/tspan/i.test(target.tagName)) { - target = target.parentNode; - } - - const d: any = d3Select(target).datum(); - - return d && Object.keys(d).length === 1 ? d.index : undefined; - }; const hide = event => { state.event = event; - const index = getIndex(event); + // const index = getIndex(event); + + const index = $$.getDataIndexFromEvent(event); const noIndex = isUndefined(index); if (isMouse || noIndex) { @@ -341,9 +332,9 @@ export default { } state.event = event; - const index = getIndex(event); + const index = $$.getDataIndexFromEvent(event); - $$.selectRectForSingle(svg.node(), null, index); + $$.selectRectForSingle(svg.node(), index); isMouse ? $$.setOverOut(true, index) : $$.callOverOutForTouch(index); }) .on("mouseout", isMouse ? hide : null); diff --git a/test/assets/helper.ts b/test/assets/helper.ts index ddd6c7c6d..08456ad3c 100644 --- a/test/assets/helper.ts +++ b/test/assets/helper.ts @@ -26,8 +26,11 @@ export { * @param {bb} chart billboard.js instance */ const fireEvent = (element, name, options: any = {}, chart?: Chart) => { - const paddingLeft = - (chart && chart.$.main.node().transform.baseVal.getItem(0).matrix.e) || 0; + let paddingLeft = 0; + + try { + paddingLeft = chart.$.main.node().transform.baseVal.getItem(0).matrix.e; + } catch (e) {} // adjust clientX/Y value "clientX" in options && (options.clientX += paddingLeft); @@ -59,10 +62,10 @@ const simulator = (el, option = {}, callback) => { * @param {Object} [pos={clientX: 100, clientY: 100}] * @param {Number} [dataIndex=2] */ -const hoverChart = (hoverChart, eventName = "mousemove", pos = {clientX: 100, clientY: 100}) => { +const hoverChart = (hoverChart, eventName = "mousemove", pos = {clientX: 100, clientY: 100}, target) => { const {eventRect} = hoverChart.internal.$el; - fireEvent(eventRect.node(), eventName, pos, hoverChart); + fireEvent(target ?? eventRect?.node(), eventName, pos, hoverChart); }; // do mouse drag selection diff --git a/test/internals/tooltip-redraw-spec.ts b/test/internals/tooltip-redraw-spec.ts new file mode 100644 index 000000000..70dba86a8 --- /dev/null +++ b/test/internals/tooltip-redraw-spec.ts @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2017 ~ present NAVER Corp. + * billboard.js project is licensed under the MIT license + */ +/* eslint-disable */ +// @ts-nocheck +import {expect} from "chai"; +import util from "../assets/util"; +import {$COMMON, $ARC} from "../../src/config/classes"; + +describe("TOOLTIP: on redraws", function() { + let chart; + let args; + + beforeEach(() => { + chart = util.generate(args); + }); + + function getTooltipText(ctx) { + const {tooltip} = ctx.$; + + return { + name: tooltip.selectAll(".name"), + value: tooltip.selectAll(".value") + }; + } + + describe("Multiple xs", () => { + before(() => { + args = { + data: { + xs: { + data1: "x1", + data2: "x2" + }, + columns: [ + ["x1", 10, 30, 45, 50, 70, 100], + ["x2", 30, 50, 70, 100, 120], + ["data1", 30, 200, 100, 400, 150, 250], + ["data2", 20, 180, 148, 100, 190] + ], + type: "line" + } + }; + }); + + it("tooltip has been updated?", done => { + util.hoverChart(chart, "mousemove", { + clientX: 487, + clientY: 317 + }); + + chart.load({ + xs: { + data3: "x2" + }, + columns: [ + ["data3", 100, 250, 145, 100, 100] + ], + done: function() { + const {name, value} = getTooltipText(this); + + expect(name.size()).to.be.equal(3); + expect(value.size()).to.be.equal(3); + + expect(name.filter((d, i) => i === 2).text()).to.be.equal("data3"); + expect(+value.filter((d, i) => i === 2).text()).to.be.equal(100); + + done(); + } + }); + }); + }); + + describe("Single x", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", 300, 350, 148, 300, 500] + ], + type: "line" + }, + point: { + focus: { + only: true + } + } + }; + }); + + it("tooltip has been updated?", done => { + util.hoverChart(chart, "mousemove", { + clientX: 487, + clientY: 317 + }); + + chart.load({ + columns: [ + ["data3", 100, 250, 145, 100, 100] + ], + done: function() { + const {name, value} = getTooltipText(this); + const {circles} = this.$; + + expect(circles.size()).to.be.equal(2); + + // check if all data points are expanded + circles.each(function() { + expect(this.getAttribute("class").indexOf($COMMON.EXPANDED) > -1).to.be.true; + expect(+this.getAttribute("r")).to.be.greaterThan(4); + }); + + expect(name.filter((d, i) => i === 1).text()).to.be.equal("data3"); + expect(+value.filter((d, i) => i === 1).text()).to.be.equal(100); + + done(); + } + }); + }); + }); + + describe("Single x, load different value", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", 130, 340, 200, 500, 250] + ], + type: "line" + }, + axis: { + y: { + min: 0 + } + } + }; + }); + + it("tooltip has been updated?", done => { + util.hoverChart(chart, "mousemove", { + clientX: 487, + clientY: 317 + }); + + chart.load({ + columns: [ + ["data1", 100, 250, 145, 100, 100] + ], + done: function() { + const {value} = getTooltipText(this); + + expect(value.size()).to.be.equal(1); + expect(+value.text()).to.be.equal(100); + + done(); + } + }); + }); + }); + + describe("Treemap", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", 1300], + ["data2", 200], + ["data3", 500], + ["data4", 50], + ["data5", 100], + ["data6", 70], + ["data7", 200], + ["data8", 133], + ["data9", 220], + ["data10", 15] + ], + type: "treemap", + labels: { + colors: "#fff" + } + } + }; + }); + + it("tooltip has been updated?", done => { + chart.tooltip.show({ + data: { + id: "data1" + } + }); + + chart.load({ + columns: [ + ["data4", 1000], + ["data5", 280] + ], + unload: ["data1"], + done: function() { + setTimeout(() => { + const {name, value} = getTooltipText(this); + + expect(value.size()).to.be.equal(1); + expect(value.text()).to.be.equal("38.20%"); + + done(); + }, 300); + } + }); + }); + }); + + describe("Pie", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", 30], + ["data2", 120] + ], + type: "pie" + } + }; + }); + + it("tooltip has been updated?", done => { + const target = chart.$.arc.select(`path.${$ARC.arc}-data2`).node(); + + setTimeout(() => { + util.hoverChart(chart, "mouseover", { + clientX: 350, + clientY: 100 + }, target); + + const prev = getTooltipText(chart).value.text(); + + expect(prev).to.be.equal("80.0%"); + + chart.load({ + columns: [ + ["sentosa", 20] + ], + done: function() { + setTimeout(() => { + const current = getTooltipText(this).value.text(); + + expect(prev).to.not.equal(current); + expect(current).to.be.equal("70.6%"); + + done(); + }, 300); + } + }); + }, 300); + }); + }); + + describe("Radar", () => { + before(() => { + args = { + data: { + x: "x", + columns: [ + ["x", "Data A", "Data B", "Data C", "Data D", "Data E"], + ["data1", 330, 350, 200, 380, 150], + ["data2", 130, 100, 30, 200, 80], + ["data3", 230, 153, 85, 300, 250] + ], + type: "radar", + labels: true + }, + radar: { + axis: { + max: 400 + }, + level: { + depth: 4 + }, + direction: { + clockwise: true + } + } + }; + }); + + it("tooltip has been updated?", done => { + chart.tooltip.show({index: 2}) + + chart.load({ + columns: [ + ["data4", 220, 100, 50, 70, 120] + ], + done: function() { + const {name} = getTooltipText(this); + + expect(name.size()).to.be.equal(4); + + expect(name.filter(function(d, i) { + return this.textContent === "data4"; + }).size()).to.be.equal(1); + + done(); + } + }); + }); + }); + + describe("Using .groups() API", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", -30, 200, 200, 400, -150, 250], + ["data2", 130, 100, -100, 200, -150, 50], + ["data3", -230, 200, 200, -300, 250, 250] + ], + type: "bar", + groups: [ + [ + "data1", + "data2" + ] + ] + } + }; + }); + + it("tooltip has been updated?", done => { + // when + chart.tooltip.show({index: 3}); + chart.groups([["data1", "data2", "data3"]]); + + setTimeout(() => { + chart.load({ + columns: [["data4", 100, -50, 150, 200, -300, -100]], + done: function() { + const {name, value} = getTooltipText(this); + + expect(name.size()).to.be.equal(4); + + expect(name.filter(function(d, i) { + return this.textContent === "data4"; + }).size()).to.be.equal(1); + + done(); + } + }); + }, 300); + }); + }); +}); diff --git a/test/internals/tooltip-spec.ts b/test/internals/tooltip-spec.ts index 69e46fa3e..b402cb318 100644 --- a/test/internals/tooltip-spec.ts +++ b/test/internals/tooltip-spec.ts @@ -1775,5 +1775,5 @@ describe("TOOLTIP", function() { spy.resetHistory(); }); }); - }); + }); }); diff --git a/test/shape/radar-spec.ts b/test/shape/radar-spec.ts index 87815eefa..30a1180af 100644 --- a/test/shape/radar-spec.ts +++ b/test/shape/radar-spec.ts @@ -201,7 +201,7 @@ describe("SHAPE RADAR", () => { }); describe("Axis", () => { - const textPos = []; + const textPos: any = []; before(() => { args = {