Skip to content

Commit

Permalink
feat(tooltip): Intent to ship linked tooltip with name
Browse files Browse the repository at this point in the history
Option to interact using name

Fix #401
Close #402
  • Loading branch information
netil committed May 9, 2018
1 parent 9067138 commit ae263a1
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 82 deletions.
2 changes: 1 addition & 1 deletion spec/api/api.show-spec.js
Expand Up @@ -153,7 +153,7 @@ describe("API show", () => {
chart.toggle();

main.selectAll(`.${CLASS.chartLine}`).each(function() {
expect(+this.style.opacity).to.be.equal(0);
expect(+this.style.opacity).to.be.below(1);
});

legend = internal.svg.selectAll(`.${CLASS.legendItemHidden}`);
Expand Down
127 changes: 56 additions & 71 deletions spec/internals/tooltip-spec.js
Expand Up @@ -29,20 +29,26 @@ describe("TOOLTIP", function() {
},
tooltip: {}
};
const spy1 = sinon.spy();
const spy2 = sinon.spy();


// check for the tooltip's ordering
const checkTooltip = (chart, expected) => {
const eventRect = chart.internal.main
// hover chart
const hoverChart = (hoverChart, eventName = "mousemove") => {
const eventRect = hoverChart.internal.main
.select(`.${CLASS.eventRect}-2`)
.node();

util.fireEvent(eventRect, "mousemove", {
util.fireEvent(eventRect, eventName, {
clientX: 100,
clientY: 100
}, chart);
}, hoverChart);
};

// check for the tooltip's ordering
const checkTooltip = (checkChart, expected) => {
hoverChart(checkChart);

const tooltips = d3.select(chart.element)
const tooltips = d3.select(checkChart.element)
.selectAll(`.${CLASS.tooltip} tr`)
.nodes();

Expand All @@ -55,17 +61,10 @@ describe("TOOLTIP", function() {
};

// check for the tooltip's ordering
const checkLinkedTooltip = (hoverChart, checkChart, expected) => {
const eventRect = hoverChart.internal.main
.select(`.${CLASS.eventRect}-2`)
.node();

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, hoverChart);
const checkLinkedTooltip = (chart1, chart2, expected) => {
hoverChart(chart1);

const tooltips = d3.select(checkChart.element)
const tooltips = d3.select(chart2.element)
.selectAll(`.${CLASS.tooltip} tr`)
.nodes();

Expand All @@ -76,22 +75,9 @@ describe("TOOLTIP", function() {
}
};

const checkCallback = (chart, doHide) => {
const eventRect = chart.internal.main
.select(`.${CLASS.eventRect}-2`)
.node();

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, chart);

if (doHide) {
util.fireEvent(eventRect, "mouseout", {
clientX: 100,
clientY: 100
}, chart);
}
const checkCallback = (checkChart, doHide) => {
hoverChart(checkChart);
doHide && hoverChart(checkChart, "mouseout");
};

beforeEach(() => {
Expand Down Expand Up @@ -182,12 +168,7 @@ describe("TOOLTIP", function() {
describe("tooltip position", () => {
describe("without left margin", () => {
it("should show tooltip on proper position", () => {
const eventRect = chart.internal.main.select(`.${CLASS.eventRect}-2`).node();

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, chart);
hoverChart(chart);

const tooltipContainer = chart.internal.tooltip;
const top = Math.floor(+tooltipContainer.style("top").replace(/px/, ""));
Expand All @@ -211,12 +192,7 @@ describe("TOOLTIP", function() {
});

it("should show tooltip on proper position", () => {
const eventRect = chart.internal.main.select(`.${CLASS.eventRect}-2`).node();

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, chart);
hoverChart(chart);

const tooltipContainer = d3.select(chart.element).select(`.${CLASS.tooltipContainer}`);
const top = Math.floor(+tooltipContainer.style("top").replace(/px/, ""));
Expand Down Expand Up @@ -254,12 +230,8 @@ describe("TOOLTIP", function() {
});

it("should be set to the coordinate where the function returned", () => {
const eventRect = chart.internal.main.select(`.${CLASS.eventRect}-2`).node();
hoverChart(chart);

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, chart);
const tooltipContainer = d3.select(chart.element).select(`.${CLASS.tooltipContainer}`);
const top = Math.floor(+tooltipContainer.style("top").replace(/px/, ""));
const left = Math.floor(+tooltipContainer.style("left").replace(/px/, ""));
Expand Down Expand Up @@ -366,6 +338,38 @@ describe("TOOLTIP", function() {
});
});

describe("linked tooltip", () => {
beforeEach(() => {
spy1.resetHistory();
spy2.resetHistory();
});

it("set options tooltip.linked=false", () => {
args.tooltip.linked = false;
args2.tooltip.order = spy2;
});

it("second chart tooltip shouldn't be called", () => {
hoverChart(chart);

expect(args2.tooltip.order.called).to.be.false;
});

it("set options tooltip.linked=false", () => {
args2.tooltip.linked = args.tooltip.linked = {name: "some"};
args.tooltip.order = spy1;

chart2 = util.generate(args2);
});

it("both charts should be called", () => {
hoverChart(chart2);

expect(args.tooltip.order.called).to.be.true;
expect(args2.tooltip.order.called).to.be.true;
});
});

describe("linked tooltip positionFunction", () => {
const topExpected = 37;
const leftExpected = 79;
Expand Down Expand Up @@ -412,12 +416,8 @@ describe("TOOLTIP", function() {
});

it("linked tooltips should be set to the coordinate where the function returned", () => {
const eventRect = chart.internal.main.select(`.${CLASS.eventRect}-2`).node();
hoverChart(chart);

util.fireEvent(eventRect, "mousemove", {
clientX: 100,
clientY: 100
}, chart);
const tooltipContainer1 = d3.select(chart.element).select(`.${CLASS.tooltipContainer}`);
const top1 = Math.floor(+tooltipContainer1.style("top").replace(/px/, ""));
const left1 = Math.floor(+tooltipContainer1.style("left").replace(/px/, ""));
Expand Down Expand Up @@ -567,9 +567,7 @@ describe("TOOLTIP", function() {
});

it("linked charts set options tooltip.order=function", () => {
args2.tooltip.order = args.tooltip.order = sinon.spy(function(a, b) {
return a.value - b.value;
});
args2.tooltip.order = args.tooltip.order = sinon.spy((a, b) => a.value - b.value);
});

it("chart 1 data.order function should be called", () => {
Expand All @@ -583,19 +581,6 @@ describe("TOOLTIP", function() {
});
});

describe("linked tooltip", () => {
before(() => {
args.tooltip.linked = false;
args2.tooltip.order = sinon.spy();
});

it("second chart tooltip shouldn't be called", () => {
checkLinkedTooltip(chart, chart2);

expect(args2.tooltip.order.called).to.be.false;
});
});

describe("tooltip display at initialization", () => {
before(() => {
args = {
Expand Down
11 changes: 9 additions & 2 deletions src/config/Options.js
Expand Up @@ -2523,7 +2523,8 @@ export default class Options {
* @type {Object}
* @property {Boolean} [tooltip.show=true] Show or hide tooltip.<br>
* @property {Boolean} [tooltip.grouped=true] Set if tooltip is grouped or not for the data points.
* @property {Boolean} [tooltip.linked=false] Set if tooltips on all visible charts with like x points are shown together when one is shown.<br>
* @property {Boolean} [tooltip.linked=false] Set if tooltips on all visible charts with like x points are shown together when one is shown.
* @property {Boolean} [tooltip.linked.name] Groping name for linked tooltip.<br>If specified, linked tooltip will be groped interacting to be worked only with the same name.
* @property {Function} [tooltip.format.title] Set format for the title of tooltip.<br>
* Specified function receives x of the data point to show.
* @property {Function} [tooltip.format.name] Set format for the name of each data in tooltip.<br>
Expand Down Expand Up @@ -2597,7 +2598,12 @@ export default class Options {
*
* // Link any tooltips when multiple charts are on the screen where same x coordinates are available
* // Useful for timeseries correlation
* linked: true
* linked: true,
*
* // Specify name to interact those with the same name only.
* linked: {
* name: "some-group"
* }
* }
*/
tooltip_show: true,
Expand All @@ -2617,6 +2623,7 @@ export default class Options {
left: "50px"
},
tooltip_linked: false,
tooltip_linked_name: "",
tooltip_onshow: () => {},
tooltip_onhide: () => {},
tooltip_onshown: () => {},
Expand Down
19 changes: 11 additions & 8 deletions src/internals/tooltip.js
Expand Up @@ -297,17 +297,20 @@ extend(ChartInternal.prototype, {
const $$ = this;

if ($$.config.tooltip_linked) {
const linkedName = $$.config.tooltip_linked_name;

$$.api.internal.charts.forEach(c => {
const isLinked = c.internal.config.tooltip_linked;
const isInDom = document.body.contains(c.element);
if (c !== $$.api) {
const internal = c.internal;
const isLinked = internal.config.tooltip_linked;
const name = internal.config.tooltip_linked_name;
const isInDom = document.body.contains(c.element);

if (c !== $$.api && isLinked && isInDom) {
const isShowing = c.internal.tooltip.style("display") === "block";
if (isLinked && linkedName === name && isInDom) {
const isShowing = internal.tooltip.style("display") === "block";

if (isShowing && !show) {
c.tooltip.hide();
} else if (!isShowing && show) {
c.tooltip.show({x});
isShowing ^ show &&
c.tooltip[isShowing ? "hide" : "show"]({x});
}
}
});
Expand Down

0 comments on commit ae263a1

Please sign in to comment.