Skip to content

Commit

Permalink
feat(legend): Pass visibility state to legend item's event callback
Browse files Browse the repository at this point in the history
Pass visibility state argument to event callbacks

Fix #3897

Co-authored-by: netil <netil@netil.local>
  • Loading branch information
netil and netil authored Oct 14, 2024
1 parent 6f69e97 commit ba71911
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 15 deletions.
15 changes: 12 additions & 3 deletions src/ChartInternal/internals/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,10 @@ export default {
.on(interaction.dblclick ? "dblclick" : "click",
interaction || isFunction(config.legend_item_onclick) ?
function(event, id) {
if (!callFn(config.legend_item_onclick, api, id)) {
if (
!callFn(config.legend_item_onclick, api, id,
!state.hiddenTargetIds.includes(id))
) {
const {altKey, target, type} = event;

if (type === "dblclick" || altKey) {
Expand Down Expand Up @@ -493,7 +496,10 @@ export default {
!isTouch && item
.on("mouseout", interaction || isFunction(config.legend_item_onout) ?
function(event, id) {
if (!callFn(config.legend_item_onout, api, id)) {
if (
!callFn(config.legend_item_onout, api, id,
!state.hiddenTargetIds.includes(id))
) {
d3Select(this).classed($FOCUS.legendItemFocused, false);

if (hasGauge) {
Expand All @@ -506,7 +512,10 @@ export default {
null)
.on("mouseover", interaction || isFunction(config.legend_item_onover) ?
function(event, id) {
if (!callFn(config.legend_item_onover, api, id)) {
if (
!callFn(config.legend_item_onover, api, id,
!state.hiddenTargetIds.includes(id))
) {
d3Select(this).classed($FOCUS.legendItemFocused, true);

if (hasGauge) {
Expand Down
9 changes: 6 additions & 3 deletions src/config/Options/common/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,12 @@ export default {
* }
*
* // when set below callback, will disable corresponding default interactions
* onclick: function(id) { ... },
* onover: function(id) { ... },
* onout: function(id) { ... },
* onclick: function(id, visible) {
* // toggle based on the data visibility
* this[visible ? "hide" : "show"](id);
* },
* onover: function(id, visible) { ... },
* onout: function(id, visible) { ... },
*
* // set tile's size
* tile: {
Expand Down
42 changes: 36 additions & 6 deletions test/internals/legend-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ describe("LEGEND", () => {
});

it("set options: legend.item.onclick", () => {
args.legend.item.onclick = () => {};
args.legend.item.onclick = sinon.spy(() => {});
});

it("should only 'click' event lister bound", () => {
Expand All @@ -826,14 +826,24 @@ describe("LEGEND", () => {

expect(item.on("mouseover mouseout")).to.be.undefined;
expect(item.on("click")).to.not.be.undefined;

expect(item.style("cursor")).to.be.equal("pointer");

id === "data1" && chart.hide(id);

fireEvent(item.node(), "click", {
clientX: 2,
clientY: 2
}, chart);
});

// given visible state argguments?
expect(args.legend.item.onclick.args)
.to.be.deep.equal(chart.data().map(({id}) => [id, id === "data1" ? false : true]));
});

it("set options: legend.item.onover", () => {
delete args.legend.item.onclick;
args.legend.item.onover = () => {};
args.legend.item.onover = sinon.spy(() => {});
});

it("should only 'mouseover' event lister bound", () => {
Expand All @@ -844,14 +854,24 @@ describe("LEGEND", () => {

expect(item.on("click mouseout")).to.be.undefined;
expect(item.on("mouseover")).to.not.be.undefined;

expect(item.style("cursor")).to.be.equal("pointer");

id === "data2" && chart.hide(id);

fireEvent(item.node(), "mouseover", {
clientX: 2,
clientY: 2
}, chart);
});

// given visible state argguments?
expect(args.legend.item.onover.args)
.to.be.deep.equal(chart.data().map(({id}) => [id, id === "data2" ? false : true]));
});

it("set options: legend.item.onout", () => {
delete args.legend.item.onover;
args.legend.item.onout = () => {};
args.legend.item.onout = sinon.spy(() => {});
});

it("should only 'mouseout' event lister bound", () => {
Expand All @@ -862,9 +882,19 @@ describe("LEGEND", () => {

expect(item.on("click mouseover")).to.be.undefined;
expect(item.on("mouseout")).to.not.be.undefined;

expect(item.style("cursor")).to.be.equal("pointer");

id === "data1" && chart.hide(id);

fireEvent(item.node(), "mouseout", {
clientX: 2,
clientY: 2
}, chart);
});

// given visible state argguments?
expect(args.legend.item.onout.args)
.to.be.deep.equal(chart.data().map(({id}) => [id, id === "data1" ? false : true]));
});

it("set options: legend.item.interaction.dblclik=true", () => {
Expand Down
6 changes: 3 additions & 3 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,19 +517,19 @@ export interface LegendOptions {
* - When set, default `click` interaction will be disabled.
* - When `interaction.dblclick=true` is set, will be called on double click.
*/
onclick?(this: Chart, id: string): void;
onclick?(this: Chart, id: string, visible: boolean): void;

/**
* Set mouseover event handler to the legend item.
* - **NOTE:** When set, default `mouseover` interaction will be disabled.
*/
onover?(this: Chart, id: string): void;
onover?(this: Chart, id: string, visible: boolean): void;

/**
* Set mouseout event handler to the legend item.
* - **NOTE:** When set, default `mouseout` interaction will be disabled.
*/
onout?(this: Chart, id: string): void;
onout?(this: Chart, id: string, visible: boolean): void;
};

/**
Expand Down

0 comments on commit ba71911

Please sign in to comment.