diff --git a/spec/api/api.tooltip-spec.js b/spec/api/api.tooltip-spec.js index 7bb384498..b1124ad86 100644 --- a/spec/api/api.tooltip-spec.js +++ b/spec/api/api.tooltip-spec.js @@ -7,7 +7,8 @@ import util from "../assets/util"; import CLASS from "../../src/config/classes"; describe("API tooltip", () => { - const chart = util.generate({ + let chart; + let args = { data: { x: "x", columns: [ @@ -24,54 +25,161 @@ describe("API tooltip", () => { } } } + }; + + beforeEach(() => { + chart = util.generate(args); }); - it("should show/hide tooltip using 'index' option", () => { - const internal = chart.internal; - const config = internal.config; - const tooltip = internal.tooltip; - const x = 1; + describe("for non multiple x", () => { + it("should show/hide tooltip using 'index' option", () => { + const internal = chart.internal; + const config = internal.config; + const tooltip = internal.tooltip; + const x = 1; + + // show tooltip + chart.tooltip.show({ + index: x, + mouse: [10, 200] + }); + + expect(tooltip.html()).to.be.ok; + expect(tooltip.style("display")).to.be.equal("block"); + + // check if tooltip data are correctly rendered + chart.data().forEach(v => { + const id = v.id; + const data = tooltip.select(`.${CLASS.tooltipName}-${id}`); + const value = chart.data(id)[0].values[x]; + + expect(id).to.be.equal(v.id); + expect(tooltip.select("th").html()).to.be.equal(d3.timeFormat(config.axis_x_tick_format)(value.x)); + expect(data.select(".name").text()).to.be.equal(id); + expect(+data.select(".value").html()).to.be.equal(value.value); + }); + + // hide tooltip + chart.tooltip.hide(); - // show tooltip - chart.tooltip.show({ - index: x, - mouse: [10, 200] + expect(tooltip.style("display")).to.be.equal("none"); }); - expect(tooltip.html()).to.be.ok; - expect(tooltip.style("display")).to.be.equal("block"); + it("should show/hide tooltip using 'x' option", () => { + const tooltip = chart.internal.tooltip; + const x = new Date("2018-01-03 00:00"); + + // show tooltip + chart.tooltip.show({ x }); + + expect(tooltip.html()).to.be.ok; + expect(tooltip.style("display")).to.be.equal("block"); + + // hide tooltip + chart.tooltip.hide(); + + expect(tooltip.style("display")).to.be.equal("none"); + }); + }); - // check if tooltip data are correctly rendered - chart.data().forEach(v => { - const id = v.id; - const data = tooltip.select(`.${CLASS.tooltipName}-${id}`); - const value = chart.data(id)[0].values[x]; + describe("for multiple x", () => { + const spy1 = sinon.spy(); + const spy2 = sinon.spy(); - expect(id).to.be.equal(v.id); - expect(tooltip.select("th").html()).to.be.equal(d3.timeFormat(config.axis_x_tick_format)(value.x)); - expect(data.select(".name").text()).to.be.equal(id); - expect(+data.select(".value").html()).to.be.equal(value.value); + before(() => { + args = { + data: { + xs: { + data1: "x1", + data2: "x2", + }, + columns: [ + ["x1", "2018-08-1", "2018-09-1", "2018-10-1"], + ["x2", "2018-10-14", "2018-10-28"], + ["data1", 10, 15, 18], + ["data2", 14, 14] + ] + }, + axis: { + x: { + type: "timeseries", + tick: { + format: "%Y-%m-%d" + } + } + }, + tooltip: { + onshow: spy1, + onhide: spy2 + } + } }); - // hide tooltip - chart.tooltip.hide(); + it("check for tooltip.show/hide() for data.xs option", () => { + const value = 15; + + chart.tooltip.show({ + data: { + x: new Date("2018-09-1 0:0:0"), + id: "y", + value + } + }); + + chart.tooltip.hide(); - expect(tooltip.style("display")).to.be.equal("none"); + expect(spy1.called).to.be.true; + expect(spy2.called).to.be.true; + expect(+chart.$.tooltip.select(".value").text()).to.be.equal(value); + }); }); - it("should show/hide tooltip using 'x' option", () => { - const tooltip = chart.internal.tooltip; - const x = new Date("2018-01-03 00:00"); + describe("for tooltip.grouped=false", () => { + const spy1 = sinon.spy(); + const spy2 = sinon.spy(); - // show tooltip - chart.tooltip.show({ x }); + before(() => { + args = { + data: { + x: "x", + columns: [ + ["x", "2018-08-1", "2018-09-1", "2018-10-1"], + ["data1", 10, 15, 18], + ["data2", 14, 14] + ] + }, + axis: { + x: { + type: "timeseries", + tick: { + format: "%Y-%m-%d" + } + } + }, + tooltip: { + grouped: false, + onshow: spy1, + onhide: spy2 + } + } + }); - expect(tooltip.html()).to.be.ok; - expect(tooltip.style("display")).to.be.equal("block"); + it("check for tooltip.show/hide() for data.xs option", () => { + const value = 14; - // hide tooltip - chart.tooltip.hide(); + chart.tooltip.show({ + data: { + x: new Date("2018-09-1 0:0:0"), + id: "y", + value + } + }); + + chart.tooltip.hide(); - expect(tooltip.style("display")).to.be.equal("none"); + expect(spy1.called).to.be.true; + expect(spy2.called).to.be.true; + expect(+chart.$.tooltip.select(".value").text()).to.be.equal(value); + }); }); }); diff --git a/src/api/api.tooltip.js b/src/api/api.tooltip.js index 686f5e54b..f07e85877 100644 --- a/src/api/api.tooltip.js +++ b/src/api/api.tooltip.js @@ -21,8 +21,8 @@ const tooltip = extend(() => {}, { * | --- | --- | --- | * | index | Number | Determine focus by index | * | x | Number | Date | Determine focus by x Axis index | - * | data | Object | Determine focus data with following keys: `x` or `index`.
When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is set, the target is determined by mouse position and needs specify `x`, `id` and `value`. | * | mouse | Array | Determine x and y coordinate value relative the targeted x Axis element.
It should be used along with `data`, `index` or `x` value. The default value is set as `[0,0]` | + * | data | Object | When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is used or [tooltip.grouped](Options.html#.tooltip) set to 'false', `should be used giving this param`.

**Key:**
- x {Number | Date}: x Axis value
- index {Number}: x Axis index (useless for data.xs)
- id {String}: Axis id. 'y' or 'y2'(default 'y')
- value {Number}: The corresponding value for tooltip. | * * @example * // show the 2nd x Axis coordinate tooltip @@ -40,6 +40,24 @@ const tooltip = extend(() => {}, { * chart.tooltip.show({ * x: new Date("2018-01-02 00:00") * }); + * + * // when data.xs is used + * chart.tooltip.show({ + * data: { + * x: 3, // x Axis value + * id: "y", // axis id. 'y' or 'y2' (default 'y') + * value: 500 // data value + * } + * }); + * + * // when data.xs isn't used, but tooltip.grouped=false is set + * chart.tooltip.show({ + * data: { + * index: 3, // or 'x' key value + * id: "y", // axis id. 'y' or 'y2' (default 'y') + * value: 500 // data value + * } + * }); */ show: function(args = {}) { const $$ = this.internal; @@ -53,16 +71,16 @@ const tooltip = extend(() => {}, { // determine focus data if (args.data) { + const y = $$.getYScale(args.data.id)(args.data.value); + if ($$.isMultipleX()) { // if multiple xs, target point will be determined by mouse - mouse = [ - $$.x(args.data.x), - $$.getYScale(args.data.id)(args.data.value) - ]; - - index = null; + mouse = [$$.x(args.data.x), y]; } else { - // TODO: when tooltip_grouped = false + if (!$$.config.tooltip_grouped) { + mouse = [0, y]; + } + index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x); } } else if (isDefined(args.x)) { diff --git a/src/interactions/interaction.js b/src/interactions/interaction.js index 67f4f0647..86a892b73 100644 --- a/src/interactions/interaction.js +++ b/src/interactions/interaction.js @@ -613,13 +613,11 @@ extend(ChartInternal.prototype, { */ dispatchEvent(type, index, mouse) { const $$ = this; - const selector = `.${ - $$.isMultipleX() ? CLASS.eventRect : `${CLASS.eventRect}-${index}` - }`; - + const isMultipleX = $$.isMultipleX(); + const selector = `.${isMultipleX ? CLASS.eventRect : `${CLASS.eventRect}-${index}`}`; const eventRect = $$.main.select(selector).node(); const {width, left, top} = eventRect.getBoundingClientRect(); - const x = left + (mouse ? mouse[0] : 0) + (width / 2); + const x = left + (mouse ? mouse[0] : 0) + (isMultipleX ? 0 : (width / 2)); const y = top + (mouse ? mouse[1] : 0); const params = { screenX: x,