Skip to content

Commit

Permalink
feat(legend): Intent to ship legend.item.interaction.dblclick
Browse files Browse the repository at this point in the history
- Implement double click interaction and option
- Reenforce legend click interaction on API doc

Close #1404
  • Loading branch information
netil committed Jun 22, 2023
1 parent af87d10 commit 18f5c4a
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 13 deletions.
4 changes: 3 additions & 1 deletion demo/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ var billboardDemo = {
.replace(/([A-Z]+)/g, " $1");

// set description
this.$description.innerHTML = demos[type[0]][type[1]].description || "";
let desc = demos[type[0]][type[1]];
this.$description.innerHTML = desc.description || (Array.isArray(desc) && desc[0].description) || "";

this.$codeArea.style.display = "block";

// remove selected class
Expand Down
60 changes: 60 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3194,6 +3194,66 @@ d3.select(".chart_area")
}
}
},
LegendItemInteraction: [
{
description: "<b>Single click + AltKey(Win)/optionKey(Mac)</b><br>or <b>Double click</b> legend item to show/hide data series",
options: {
title: {
text: "Single click"
},
data: {
columns: [
["data1", 300, 350, 300],
["data2", 130, 100, 140],
["data3", 230, 200, 240]
],
type: "line"
}
}
},
{
options: {
title: {
text: "Double click"
},
data: {
columns: [
["data1", 300, 350, 300],
["data2", 130, 100, 140],
["data3", 230, 200, 240]
],
type: "line"
},
legend: {
item: {
interaction: {
dblclick: true
}
}
}
}
},
{
options: {
title: {
text: "Interaction=false"
},
data: {
columns: [
["data1", 300, 350, 300],
["data2", 130, 100, 140],
["data3", 230, 200, 240]
],
type: "line"
},
legend: {
item: {
interaction: false
}
}
}
},
],
LegendItemTileType: [
{
options: {
Expand Down
23 changes: 16 additions & 7 deletions src/ChartInternal/internals/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ export default {
const isTouch = state.inputType === "touch";
const hasGauge = $$.hasType("gauge");
const useCssRule = config.boost_useCssRule;
const hasInteraction = config.legend_item_interaction;
const interaction = config.legend_item_interaction;

item
.attr("class", function(id) {
Expand All @@ -421,12 +421,21 @@ export default {
}

item
.on("click", hasInteraction || isFunction(config.legend_item_onclick) ?
.on(interaction.dblclick ? "dblclick" : "click", interaction || isFunction(config.legend_item_onclick) ?
function(event, id) {
if (!callFn(config.legend_item_onclick, api, id)) {
if (event.altKey) {
api.hide();
api.show(id);
const {altKey, target, type} = event;

if (type === "dblclick" || altKey) {
// when focused legend is clicked(with altKey or double clicked), reset all hiding.
if (state.hiddenTargetIds.length &&
target.parentNode.getAttribute("class").indexOf($LEGEND.legendItemHidden) === -1
) {
api.show();
} else {
api.hide();
api.show(id);
}
} else {
api.toggle(id);

Expand All @@ -439,7 +448,7 @@ export default {
} : null);

!isTouch && item
.on("mouseout", hasInteraction || isFunction(config.legend_item_onout) ?
.on("mouseout", interaction || isFunction(config.legend_item_onout) ?
function(event, id) {
if (!callFn(config.legend_item_onout, api, id)) {
d3Select(this).classed($FOCUS.legendItemFocused, false);
Expand All @@ -451,7 +460,7 @@ export default {
$$.api.revert();
}
} : null)
.on("mouseover", hasInteraction || isFunction(config.legend_item_onover) ?
.on("mouseover", interaction || isFunction(config.legend_item_onover) ?
function(event, id) {
if (!callFn(config.legend_item_onover, api, id)) {
d3Select(this).classed($FOCUS.legendItemFocused, true);
Expand Down
29 changes: 26 additions & 3 deletions src/config/Options/common/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,34 @@ export default {
* - defines the max step the legend has (e.g. If 2 set and legend has 3 legend item, the legend 2 columns).
* @property {boolean} [legend.equally=false] Set to all items have same width size.
* @property {number} [legend.padding=0] Set padding value
* @property {boolean} [legend.item.interaction=true] Set legend item interaction.<br>
* @property {boolean} [legend.item.interaction=true] Set legend item interaction.
* - **NOTE:**
* - This setting will not have effect on `.toggle()` method.
* - `legend.item.onXXX` listener options will work if set, regardless of this option value.
* @property {boolean} [legend.item.interaction.dblclick=false] Set legend item to interact on double click.
* - **NOTE:**
* - Double clicking will make focused clicked dataseries only, hiding all others.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - To return initial state(which all dataseries are showing), double click current focused legend item again.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - In this case, default `click` interaction will be disabled.
* @property {Function} [legend.item.onclick=undefined] Set click event handler to the legend item.
* - **NOTE:**
* - When set, default `click` interaction will be disabled.
* - When `interaction.dblclick=true` is set, will be called on double click.
* @property {Function} [legend.item.onover=undefined] Set mouse/touch over event handler to the legend item.
* - **NOTE:** When set, default `mouseover` interaction will be disabled.
* @property {Function} [legend.item.onout=undefined] Set mouse/touch out event handler to the legend item.
* - **NOTE:** When set, default `mouseout` interaction will be disabled.
* @property {number} [legend.item.tile.width=10] Set width for 'rectangle' legend item tile element.
* @property {number} [legend.item.tile.height=10]
* @property {number} [legend.item.tile.height=10] Set height for 'rectangle' legend item tile element.
* @property {number} [legend.item.tile.r=5] Set the radius for 'circle' legend item tile type.
* @property {string} [legend.item.tile.type="rectangle"] Set legend item shape type.<br>
* - **Available Values:**
* - circle
* - rectangle
* @property {boolean} [legend.usePoint=false] Whether to use custom points in legend.
* @see [Demo: item.interaction](https://naver.github.io/billboard.js/demo/#Legend.LegendItemInteraction)
* @see [Demo: item.tile.type](https://naver.github.io/billboard.js/demo/#Legend.LegendItemTileType)
* @see [Demo: position](https://naver.github.io/billboard.js/demo/#Legend.LegendPosition)
* @see [Demo: contents.template](https://naver.github.io/billboard.js/demo/#Legend.LegendTemplate1)
Expand Down Expand Up @@ -92,6 +105,13 @@ export default {
* // will disable default interaction
* interaction: false,
*
* // set legend interact on double click
* // by double clicking, will make focused clicked dataseries only, hiding all others.
* interaction: {
* dblclick: true
* }
*
* // when set below callback, will disable corresponding default interactions
* onclick: function(id) { ... },
* onover: function(id) { ... },
* onout: function(id) { ... },
Expand Down Expand Up @@ -120,7 +140,10 @@ export default {
legend_inset_x: 10,
legend_inset_y: 0,
legend_inset_step: <number|undefined> undefined,
legend_item_interaction: true,
legend_item_interaction: <boolean|{
dblclick?: boolean;
}> true,
legend_item_dblclick: false,
legend_item_onclick: <Function|undefined> undefined,
legend_item_onover: <Function|undefined> undefined,
legend_item_onout: <Function|undefined> undefined,
Expand Down
25 changes: 25 additions & 0 deletions test/internals/legend-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {expect} from "chai";
import {select as d3Select} from "d3-selection";
import util from "../assets/util";
import {$FOCUS, $LEGEND} from "../../src/config/classes";
import {fireEvent} from "../assets/helper";

describe("LEGEND", () => {
let chart;
Expand Down Expand Up @@ -850,5 +851,29 @@ describe("LEGEND", () => {
expect(item.style("cursor")).to.be.equal("pointer");
});
});

it("set options: legend.item.interaction.dblclik=true", () => {
args.legend.item.interaction = {
dblclick: true
};
});

it("check dblclick interaction", () => {
const {$: {legend}, internal: {state}} = chart;

chart.data().forEach(({id}) => {
const item = legend.select(`.bb-legend-item-${id}`).node();

// when double click
fireEvent(item, "dblclick", undefined, chart);

expect(state.hiddenTargetIds.length && state.hiddenTargetIds.indexOf(id) === -1).to.be.true;

// when double click again, it should return to initial state
fireEvent(item, "dblclick", undefined, chart);

expect(state.hiddenTargetIds).to.be.empty;
});
});
});
});
20 changes: 18 additions & 2 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,22 +475,38 @@ export interface LegendOptions {
* Set legend item interaction.
* - **NOTE:**
* - This setting will not have effect on `.toggle()` method.
* - `legend.item.onXXX` listener options will work if set, regardless of this option value.
* - `legend.item.onXXX` listener options will work if set, regardless of this option value.
*/
interaction?: boolean;
interaction?: boolean | {
/**
* Set legend item to interact on double click.
* - **NOTE:**
* - Double clicking will make focused clicked dataseries only, hiding all others.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - To return initial state(which all dataseries are showing), double click current focused legend item again.
* - for single click case, `click + altKey(Win)/optionKey(Mac OS)` to have same effect.
* - In this case, default `click` interaction will be disabled.
*/
dblclick?: boolean;
};

/**
* Set click event handler to the legend item.
* - **NOTE:**
* - 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;

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

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

0 comments on commit 18f5c4a

Please sign in to comment.