Skip to content

Commit

Permalink
feat(legend): Itent to ship legend.format, legend.tooltip
Browse files Browse the repository at this point in the history
Implement the way to format legend text value.
Also implement visualize full legend text via system tooltip

Close #3533
  • Loading branch information
netil committed Nov 27, 2023
1 parent 3a1804c commit aecff2f
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 7 deletions.
22 changes: 22 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3193,6 +3193,28 @@ d3.select(".chart_area")
}
}
},
LegendFormat: {
description: "Stay hovering on each of legend items to see full data name text.",
options: {
data: {
columns: [
["SELECT idx, title, date, count from TEST_TABLE WHERE idx=5", 2, 3, 5],
["very long long data name needed to be", 1, 2, 2],
],
type: "line"
},
legend: {
format: function(id) {
if (id.length > 5) {
id = id.substr(0, 5) + "...";
}

return id;
},
tooltip: true
}
}
},
LegendItemInteraction: [
{
description: "<b>Single click + AltKey(Win)/optionKey(Mac)</b><br>or <b>Double click</b> legend item to show/hide data series",
Expand Down
30 changes: 28 additions & 2 deletions src/ChartInternal/internals/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ function getLegendColor(id: string): string {
return color;
}

/**
* Get formatted text value
* @param {string} id Legend text id
* @returns {string} Formatted legend text
*/
function getFormattedText<T = string>(id: T): T {
const {config} = this;
let text = config.data_names[id] ?? id;

if (isFunction(config.legend_format)) {
text = config.legend_format(text);
}

return text;
}

export default {
/**
* Initialize the legend.
Expand Down Expand Up @@ -570,9 +586,15 @@ export default {
.append("rect");
}

if (config.legend_tooltip) {
legend.selectAll("title")
.data(targetIdz)
.text(id => id);
}

const texts = legend.selectAll("text")
.data(targetIdz)
.text(id => (isDefined(config.data_names[id]) ? config.data_names[id] : id)) // MEMO: needed for update
.text(getFormattedText.bind($$)) // MEMO: needed for update
.each(function(id, i) {
updatePositions(this, id, i);
});
Expand Down Expand Up @@ -722,8 +744,12 @@ export default {

$$.setLegendItem(l);

if (config.legend_tooltip) {
l.append("title").text(id => id);
}

l.append("text")
.text(id => (isDefined(config.data_names[id]) ? config.data_names[id] : id))
.text(getFormattedText.bind($$))
.each(function(id, i) {
updatePositions(this, id, i);
})
Expand Down
2 changes: 1 addition & 1 deletion src/config/Options/axis/x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ export default {
axis_x_tick_width: <number|null> null,

/**
* Set to display system tooltip(via 'title' attribute) for tick text
* Set to display system tooltip(via `<title>` element) for tick text
* - **NOTE:** Only available for category axis type (`axis.x.type='category'`)
* @name axis鈥鈥ick鈥ooltip
* @memberof Options
Expand Down
17 changes: 17 additions & 0 deletions src/config/Options/common/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ export default {
* - **Available Values:**
* - circle
* - rectangle
* @property {boolean} [legend.format] Set formatter function for legend text.
* The argument:<br>
* - `id`: legend text(which is data id) value
* @property {boolean} [legend.tooltip=false] Show full legend text value using system tooltip(via `<title>` element).
* @property {boolean} [legend.usePoint=false] Whether to use custom points in legend.
* @see [Demo: format](https://naver.github.io/billboard.js/demo/#Legend.LegendFormat)
* @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)
Expand Down Expand Up @@ -129,6 +134,16 @@ export default {
* r: 10
* }
* },
* format: function(id) {
* // set ellipsis string when length is > 5
* // to get full legend value, combine with 'legend.tooltip=true'
* if (id.length > 5) {
* id = id.substr(0, 5) + "...";
* }
*
* return id;
* },
* tooltip: true,
* usePoint: true
* }
*/
Expand All @@ -151,8 +166,10 @@ export default {
legend_item_tile_height: 10,
legend_item_tile_r: 5,
legend_item_tile_type: <"rectangle"|"circle"> "rectangle",
legend_format: <Function|undefined> undefined,
legend_padding: 0,
legend_position: <"bottom"|"right"|"inset"> "bottom",
legend_show: true,
legend_tooltip: false,
legend_usePoint: false
};
47 changes: 47 additions & 0 deletions test/internals/legend-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -876,4 +876,51 @@ describe("LEGEND", () => {
});
});
});

describe("legend format", () => {
before(() => {
args = {
data: {
columns: [
["data1 data1 data1 data1 data1 data1 ", 2, 3, 5],
["data2 data1 data1 data1 data1 data1", 1, 2, 2],
],
type: "line"
},
legend: {
format: function(id) {
if (id.length > 5) {
id = id.substr(0, 5) + "...";
}

return id;
}
}
};
});

it("legend text are formatted correctly?", () => {
const formatted = chart.data().map(v => {
return args.legend.format(v.id);
});

const legendText = chart.$.legend
.selectAll("text").nodes()
.map(v => v.textContent);

expect(formatted).to.be.deep.equal(legendText);
expect(chart.$.legend.selectAll("title").empty()).to.be.true;
});

it("set options: legend.format.tooltip=true", () => {
args.legend.tooltip = true;
});

it("legend text title are set correctly?", () => {
const dataIds = chart.data().map(v => v.id);
const legendTitle = chart.$.legend.selectAll("title").nodes().map(v => v.textContent);

expect(dataIds).to.be.deep.equal(legendTitle);
});
});
});
24 changes: 20 additions & 4 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ export interface LegendOptions {
*/
hide?: boolean | string[] | string;

/**
* Set to all items have same width size.
*/
equally?: boolean;

/**
* Change the position of legend.
* Currently bottom, right and inset are supported.
Expand All @@ -441,10 +446,6 @@ export interface LegendOptions {
y?: number;
step?: number;
};
/**
* Padding between legend elements.
*/
padding?: number;

item?: {
/**
Expand Down Expand Up @@ -534,6 +535,21 @@ export interface LegendOptions {
template?: ((this: Chart, title: string, color: string, data: DataItem[]) => void) | string;
};

/**
* Padding between legend elements.
*/
padding?: number;

/**
* Set formatter function for legend text.
*/
format?: (id: string) => string;

/**
* Show full legend text value using system tooltip(via 'title' element).
*/
tooltip?: boolean;

/**
* Whether to use custom points in legend.
*/
Expand Down

0 comments on commit aecff2f

Please sign in to comment.