diff --git a/src/ChartInternal/shape/point.ts b/src/ChartInternal/shape/point.ts index 0d4e6d2ba..26c804791 100644 --- a/src/ChartInternal/shape/point.ts +++ b/src/ChartInternal/shape/point.ts @@ -9,6 +9,7 @@ import { import type {d3Selection} from "../../../types/types"; import {$CIRCLE, $COMMON, $SELECT} from "../../config/classes"; import {document} from "../../module/browser"; +import type {IDataRow} from "../data/IData"; import {getBoundingRect, getPointer, getRandom, isFunction, isObject, isObjectType, isUndefined, isValue, toArray, notEmpty} from "../../module/util"; const getTransitionName = () => getRandom(); @@ -188,7 +189,7 @@ export default { * @param {object} d Selected data * @private */ - showCircleFocus(d?): void { + showCircleFocus(d?: IDataRow[]): void { const $$ = this; const {config, state: {hasRadar, resizing, toggling, transiting}, $el} = $$; let {circle} = $el; @@ -202,7 +203,7 @@ export default { if (d) { circle = circle .filter(function(t) { - const data = d.filter(v => v.id === t.id); + const data = d.filter?.(v => v.id === t.id); return data.length ? d3Select(this).datum(data[0]) : false; diff --git a/src/Plugin/sparkline/index.ts b/src/Plugin/sparkline/index.ts index c1dc5a18a..0985f643a 100644 --- a/src/Plugin/sparkline/index.ts +++ b/src/Plugin/sparkline/index.ts @@ -221,6 +221,11 @@ export default class Sparkline extends Plugin { } $$.state.event = e; + + if ($$.config.point_focus_only && d) { + $$.showCircleFocus?.([d]); + } + $$.setExpand(index, data.id, true); $$.showTooltip([d], e.target); } @@ -229,7 +234,10 @@ export default class Sparkline extends Plugin { const {$$} = this; $$.state.event = e; - $$.unexpandCircles(); + + $$.config.point_focus_only ? + $$.hideCircleFocus() : $$.unexpandCircles(); + $$.hideTooltip(); } diff --git a/test/plugin/sparkline/sparkline-spec.ts b/test/plugin/sparkline/sparkline-spec.ts index abfffb0ae..73652482f 100644 --- a/test/plugin/sparkline/sparkline-spec.ts +++ b/test/plugin/sparkline/sparkline-spec.ts @@ -11,7 +11,7 @@ import util from "../../assets/util"; describe("PLUGIN: SPARKLINE", () => { let chart; const selector = ".sparkline"; - const args = { + let args: any = { size: { width: 150, height: 50 @@ -54,54 +54,103 @@ describe("PLUGIN: SPARKLINE", () => { chart = util.generate(args); }); - it("Sparkline generated correctly?", () => { - expect(document.body.querySelectorAll(selector).length).to.be.equal(chart.data().length); + describe("basic functionality", () => { + it("Sparkline generated correctly?", () => { + expect(document.body.querySelectorAll(selector).length).to.be.equal(chart.data().length); + }); + + it("check for tooltip interaction", () => { + const el = chart.plugins[0].element[0]; + const {tooltip} = chart.$; + const svg = el.querySelector("svg"); + + // hover 1st chart element + util.fireEvent(svg, "mousemove", { + clientX: 10, + clientY: 10 + }, chart); + + expect(tooltip.style("display")).to.be.equal("block"); + + expect(tooltip.select("th").text()).to.be.equal("0"); + expect(tooltip.select(".name").text()).to.be.equal("data1"); + expect(tooltip.select(".value").text()).to.be.equal("30"); + + const circle = svg.querySelector(`.${$COMMON.EXPANDED}`); + + expect(circle).to.be.ok; + expect(circle.classList.contains(`${$CIRCLE.circle}-0`)).to.be.true; + + // when + util.fireEvent(svg, "mouseout", { + clientX: 10, + clientY: 10 + }, chart); + + expect(tooltip.style("display")).to.be.equal("none"); + }); + + it("set options", () => { + args.padding = false; + args.tooltip.show = false; + }); + + it("check for the dimension & tooltip", () => { + const last = document.querySelectorAll(selector)[2]; + const {width, height} = last.querySelector(`.${$AREA.areas} path`)?.getBoundingClientRect() ?? {width:0, height: 0}; + + // chart element should occupy the whole dimension of given size + expect({width, height}).to.be.deep.equal(args.size); + + // tooltip element shouldn't be added to the DOM + expect(chart.$.tooltip).to.be.null; + }); }); - it("check for tooltip interaction", () => { - const el = chart.plugins[0].element[0]; - const {tooltip} = chart.$; - const svg = el.querySelector("svg"); - - // hover 1st chart element - util.fireEvent(svg, "mousemove", { - clientX: 10, - clientY: 10 - }, chart); - - expect(tooltip.style("display")).to.be.equal("block"); - - expect(tooltip.select("th").text()).to.be.equal("0"); - expect(tooltip.select(".name").text()).to.be.equal("data1"); - expect(tooltip.select(".value").text()).to.be.equal("30"); - - const circle = svg.querySelector(`.${$COMMON.EXPANDED}`); - - expect(circle).to.be.ok; - expect(circle.classList.contains(`${$CIRCLE.circle}-0`)).to.be.true; - - // when - util.fireEvent(svg, "mouseout", { - clientX: 10, - clientY: 10 - }, chart); - - expect(tooltip.style("display")).to.be.equal("none"); - }); - - it("set options", () => { - args.padding = false; - args.tooltip.show = false; - }); - - it("check for the dimension & tooltip", () => { - const last = document.querySelectorAll(selector)[2]; - const {width, height} = last.querySelector(`.${$AREA.areas} path`)?.getBoundingClientRect() ?? {width:0, height: 0}; - - // chart element should occupy the whole dimension of given size - expect({width, height}).to.be.deep.equal(args.size); - - // tooltip element shouldn't be added to the DOM - expect(chart.$.tooltip).to.be.null; + describe("point option", () => { + before(() => { + args = { + size: { + width: 150, + height: 50 + }, + data: { + columns: [ + ["data1", 130, 200, 150, 140, 160, 150], + ["data2", 200, 130, 90, 240, 130, 220], + ["data3", 300, 200, 160, 400, 250, 250], + ], + type: "area", + types: { + data1: "line", + data2: "step" + } + }, + point: { + focus: { + only: true + } + }, + plugins: [ + new Sparkline({ + selector + }) + ] + }; + }); + + it("when point.focus.only=true is set, only one point per dataseries should show.", () => { + const testX = 3; + + expect(chart.$.circles.size()).to.be.equal(args.data.columns.length); + + // when + chart.tooltip.show({x: testX}); + + chart.$.circles.each(function(d) { + expect(d.x).to.be.equal(testX); + expect(+this.getAttribute("cx")).to.be.equal(90); + }); + }); }); }); diff --git a/types/options.d.ts b/types/options.d.ts index 1845c8e43..4c31499bf 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -4,9 +4,6 @@ */ import {Axis} from "./axis"; import {ChartTypes, d3Selection, DataItem, PrimitiveArray} from "./types"; -import Bubblecompare from "./plugin/bubblecompare/index"; -import Stanford from "./plugin/stanford/index"; -import TextOverlap from "./plugin/textoverlap/index"; import {Chart} from "./chart"; import {IArcData, IData, IDataRow} from "../src/ChartInternal/data/IData"; import { @@ -334,7 +331,7 @@ export interface ChartOptions { /** * Set plugins */ - plugins?: Array<(Bubblecompare | Stanford | TextOverlap)>; + plugins?: Array>; /** * Control the render timing