Skip to content

Commit

Permalink
fix(tooltip): Fix tootip display on tooltip.init
Browse files Browse the repository at this point in the history
Fix tooltip initial call to call .tooltip.show() api
to follow internal flow process

Fix #3369
  • Loading branch information
netil authored and netil committed Sep 5, 2023
1 parent 1209138 commit 52083bf
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 137 deletions.
27 changes: 1 addition & 26 deletions src/ChartInternal/internals/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,6 @@ export default {
const anchorString = getRotateAnchor(angle);
const rotateString = angle ? `rotate(${angle})` : "";


// $$.meetsLabelThreshold(ratio,

$$.$el.text
.style("fill", $$.getStylePropValue($$.updateTextColor))
.attr("filter", $$.updateTextBacgroundColor.bind($$))
Expand Down Expand Up @@ -452,7 +449,7 @@ export default {
*/
getXForText(points, d: IDataRow, textElement): number {
const $$ = this;
const {config, state} = $$;
const {config} = $$;
const isRotated = config.axis_rotated;
const isTreemapType = $$.isTreemapType(d);
let xPos = points[0][0];
Expand Down Expand Up @@ -484,17 +481,6 @@ export default {
}
}

// show labels regardless of the domain if value is null
if (d.value === null) {
if (xPos > state.width) {
const {width} = getBoundingRect(textElement);

xPos = state.width - width;
} else if (xPos < 0) {
xPos = 4;
}
}

if (isRotated || isTreemapType) {
xPos += $$.getCenteredTextPos(d, points, textElement, "x");
}
Expand Down Expand Up @@ -572,17 +558,6 @@ export default {
}
}

// show labels regardless of the domain if value is null
if (d.value === null && !isRotated) {
const boxHeight = rect.height;

if (yPos < boxHeight) {
yPos = boxHeight;
} else if (yPos > state.height) {
yPos = state.height - 4;
}
}

if (!isRotated || isTreemapType) {
yPos += $$.getCenteredTextPos(d, points, textElement, "y");
}
Expand Down
48 changes: 17 additions & 31 deletions src/ChartInternal/internals/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {select as d3Select} from "d3-selection";
import {document} from "../../module/browser";
import {$ARC, $TOOLTIP} from "../../config/classes";
import type {IArcData, IDataRow} from "../data/IData";
import {getPointer, isFunction, isObject, isString, isValue, callFn, sanitize, tplProcess, isUndefined, parseDate} from "../../module/util";
import {getPointer, isEmpty, isFunction, isObject, isString, isValue, callFn, sanitize, tplProcess, isUndefined, parseDate} from "../../module/util";

export default {
/**
Expand All @@ -31,50 +31,36 @@ export default {
$$.bindTooltipResizePos();
},

/**
* Show tooltip at initialization.
* Is called only when tooltip.init.show=true option is set
* @private
*/
initShowTooltip(): void {
const $$ = this;
const {config, $el, state: {hasAxis, hasRadar}} = $$;

// Show tooltip if needed
if (config.tooltip_init_show) {
const isArc = !(hasAxis && hasRadar);
const isArc = !(hasAxis || hasRadar);

if ($$.axis?.isTimeSeries() && isString(config.tooltip_init_x)) {
const targets = $$.data.targets[0];
let i;
let val;

config.tooltip_init_x = parseDate.call($$, config.tooltip_init_x);

for (i = 0; (val = targets.values[i]); i++) {
if ((val.x - config.tooltip_init_x) === 0) {
break;
}
}

config.tooltip_init_x = i;
}

let data = $$.data.targets.map(d => {
const x = isArc ? 0 : config.tooltip_init_x;

return $$.addName(d.values[x]);
$$.api.tooltip.show({
data: {
[isArc ? "index" : "x"]: config.tooltip_init_x
}
});

if (isArc) {
data = [data[config.tooltip_init_x]];
}
const position = config.tooltip_init_position;

$el.tooltip.html($$.getTooltipHTML(
data,
$$.axis?.getXAxisTickFormat(),
$$.getDefaultValueFormat(),
$$.color
));
if (!config.tooltip_contents.bindto && !isEmpty(position)) {
const {top = 0, left = 50} = position;

if (!config.tooltip_contents.bindto) {
$el.tooltip.style("top", config.tooltip_init_position.top)
.style("left", config.tooltip_init_position.left)
$el.tooltip.style("top", isString(top) ? top : `${top}px`)
.style("left", isString(left) ? left : `${left}px`)
.style("display", null);
}
}
Expand Down Expand Up @@ -368,7 +354,7 @@ export default {
* @param {SVGElement} eventTarget Event element
* @private
*/
showTooltip(selectedData: IDataRow[], eventTarget?: SVGElement): void {
showTooltip(selectedData: IDataRow[], eventTarget: SVGElement): void {
const $$ = this;
const {config, $el: {tooltip}} = $$;
const dataToShow = selectedData.filter(d => d && isValue($$.getBaseValue(d)));
Expand Down
13 changes: 5 additions & 8 deletions src/config/Options/common/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default {
* - The value array length should match with the data length
* @property {boolean} [tooltip.init.show=false] Show tooltip at the initialization.
* @property {number} [tooltip.init.x=0] Set x Axis index(or index for Arc(donut, gauge, pie) types) to be shown at the initialization.
* @property {object} [tooltip.init.position={top: "0px",left: "50px"}] Set the position of tooltip at the initialization.
* @property {object} [tooltip.init.position] Set the position of tooltip at the initialization.
* @property {Function} [tooltip.onshow] Set a callback that will be invoked before the tooltip is shown.
* @property {Function} [tooltip.onhide] Set a callback that will be invoked before the tooltip is hidden.
* @property {Function} [tooltip.onshown] Set a callback that will be invoked after the tooltip is shown
Expand Down Expand Up @@ -155,10 +155,10 @@ export default {
* // show at the initialization
* init: {
* show: true,
* x: 2, // x Axis index(or index for Arc(donut, gauge, pie) types)
* x: 2, // x Axis index (or index for Arc(donut, gauge, pie) types)
* position: {
* top: "150px",
* left: "250px"
* top: "150px", // specify as number or as string with 'px' unit string
* left: 250 // specify as number or as string with 'px' unit string
* }
* },
*
Expand Down Expand Up @@ -212,10 +212,7 @@ export default {
> {},
tooltip_init_show: false,
tooltip_init_x: 0,
tooltip_init_position: {
top: "0px",
left: "50px"
},
tooltip_init_position: undefined,
tooltip_linked: false,
tooltip_linked_name: "",
tooltip_onshow: () => {},
Expand Down
6 changes: 5 additions & 1 deletion src/module/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,11 @@ function getPathBox(
*/
function getPointer(event, element?: Element): number[] {
const touches = event && (event.touches || (event.sourceEvent && event.sourceEvent.touches))?.[0];
const pointer = d3Pointer(touches || event, element);
let pointer = [0, 0];

try {
pointer = d3Pointer(touches || event, element);
} catch (e) {}

return pointer.map(v => (isNaN(v) ? 0 : v));
}
Expand Down
165 changes: 106 additions & 59 deletions test/internals/text-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,90 +180,137 @@ describe("TEXT", () => {
});

describe("rotate", () => {
before(() => {
args = {
data: {
columns: [
["data1", 90, 100, -100]
],
type: "bar",
labels: {
rotate: 90
describe("normal axis", () => {
before(() => {
args = {
data: {
columns: [
["data1", 90, 100, -100]
],
type: "bar",
labels: {
rotate: 90
}
},
axis: {
rotated: false
}
},
axis: {
rotated: false
}
}
});
});

it("rotate attribute should be applied", () => {
chart.$.text.texts.each(function(d) {
const transform = this.getAttribute("transform");
const anchor = this.getAttribute("text-anchor");
it("rotate attribute should be applied", () => {
chart.$.text.texts.each(function(d) {
const transform = this.getAttribute("transform");
const anchor = this.getAttribute("text-anchor");

expect(transform.indexOf(`rotate(${args.data.labels.rotate})`) > -1).to.be.true;
expect(anchor).to.be.equal("end");
expect(transform.indexOf(`rotate(${args.data.labels.rotate})`) > -1).to.be.true;
expect(anchor).to.be.equal("end");

if (d.value < 0) {
const y = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];
if (d.value < 0) {
const y = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];

expect(y).to.be.closeTo(405, 1);
}
expect(y).to.be.closeTo(405, 1);
}
});
});
});

it("set options: data.labels.rotate=180", () => {
args.data.labels.rotate = 180;
});
it("set options: data.labels.rotate=180", () => {
args.data.labels.rotate = 180;
});

it("text-anchor should be middle for rotate(180deg)", () => {
chart.$.text.texts.each(function() {
const anchor = this.getAttribute("text-anchor");
it("text-anchor should be middle for rotate(180deg)", () => {
chart.$.text.texts.each(function() {
const anchor = this.getAttribute("text-anchor");

expect(anchor).to.be.equal("middle");
expect(anchor).to.be.equal("middle");
});
});
});

it("set options: data.labels.rotate=270", () => {
args.data.labels.rotate = 270;
});
it("set options: data.labels.rotate=270", () => {
args.data.labels.rotate = 270;
});

it("text-anchor should be middle for rotate(270deg)", () => {
chart.$.text.texts.each(function(d) {
const anchor = this.getAttribute("text-anchor");
it("text-anchor should be middle for rotate(270deg)", () => {
chart.$.text.texts.each(function(d) {
const anchor = this.getAttribute("text-anchor");

expect(anchor).to.be.equal("start");
expect(anchor).to.be.equal("start");

if (d.value < 0) {
const y = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];
if (d.value < 0) {
const y = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];

expect(y).to.be.closeTo(405, 1);
}
expect(y).to.be.closeTo(405, 1);
}
});
});
});

it("set options: axis.rotated=true", () => {
args.axis.rotated = true;
args.data.labels.rotate = 90;
});
it("set options: axis.rotated=true", () => {
args.axis.rotated = true;
args.data.labels.rotate = 90;
});

it("check for rotated axis", () => {
const expectedY = [80, 220, 362];
it("check for rotated axis", () => {
const expectedY = [80, 220, 362];

chart.$.text.texts.each(function(d, i) {
const transform = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];
const anchor = this.getAttribute("text-anchor");
chart.$.text.texts.each(function(d, i) {
const transform = +this.getAttribute("transform").match(/\s(\d+\.\d+)/)[1];
const anchor = this.getAttribute("text-anchor");

expect(transform).to.be.closeTo(expectedY[i], 1);
expect(anchor).to.be.equal("end");
expect(transform).to.be.closeTo(expectedY[i], 1);
expect(anchor).to.be.equal("end");

if (d.value < 0) {
const x = +this.getAttribute("transform").match(/\((\d+\.\d+)/)[1];
if (d.value < 0) {
const x = +this.getAttribute("transform").match(/\((\d+\.\d+)/)[1];

expect(x).to.be.closeTo(57, 1);
}
});
});
});

expect(x).to.be.closeTo(57, 1);
describe("rotated axis", () => {
before(() => {
args = {
data: {
columns: [
["data1", 90, 100, -100]
],
type: "bar",
labels: {
rotate: 90
}
},
axis: {
rotated: true
}
}
});

it("check when rotate=90", () => {
chart.$.text.texts.each(function() {
expect(this.getAttribute("text-anchor")).to.be.equal("end");
});
});

it("set options: data.labels.rotate=200", () => {
args.data.labels.rotate = 200;
});

it("check when rotate=200", () => {
chart.$.text.texts.each(function() {
expect(this.getAttribute("text-anchor")).to.be.equal("start");
});
});

it("set options: data.labels.rotate=400", () => {
args.data.labels.rotate = 400;
});

it("check when rotate=400", () => {
chart.$.text.texts.each(function() {
expect(this.getAttribute("text-anchor")).to.be.equal("middle");
});
});
});
});

Expand Down

0 comments on commit 52083bf

Please sign in to comment.