Skip to content

Commit

Permalink
fix(tooltip): Fix tooltip.show() for multi x axis
Browse files Browse the repository at this point in the history
- Correct the incorrect mouse coordinate values.
- Add more detailed description for API.

Fix #785
  • Loading branch information
netil authored Feb 21, 2019
1 parent 305d093 commit aaa8293
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 47 deletions.
176 changes: 142 additions & 34 deletions spec/api/api.tooltip-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand All @@ -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);
});
});
});
34 changes: 26 additions & 8 deletions src/api/api.tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -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`.<br>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.<br>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`.<br><br>**Key:**<br>- x {Number &verbar; Date}: x Axis value<br>- index {Number}: x Axis index (useless for data.xs)<br>- id {String}: Axis id. 'y' or 'y2'(default 'y')<br>- value {Number}: The corresponding value for tooltip. |
*
* @example
* // show the 2nd x Axis coordinate tooltip
Expand All @@ -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;
Expand All @@ -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)) {
Expand Down
8 changes: 3 additions & 5 deletions src/interactions/interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit aaa8293

Please sign in to comment.