Skip to content

Commit

Permalink
fix: fixed tooltip pin/unpin for all strategies (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
zefirka authored Aug 15, 2023
1 parent e6cdb15 commit f1d5c28
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 24 deletions.
37 changes: 29 additions & 8 deletions src/YagrCore/plugins/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class YagrTooltip {
private tOverlay: HTMLDivElement;
private bound: HTMLElement;
private renderNode: HTMLElement;
/**
* Flag to skip next mouseup event, used for unpinning
* tooltip on any mousedown, but continiously pinning on drag
*/
private skipNextMouseUp = false;

yagr: Yagr;
opts: TooltipOptions;
Expand Down Expand Up @@ -517,10 +522,6 @@ class YagrTooltip {
this.handlers[event] = this.handlers[event].filter((h) => h !== handler);
};

private onMouseDown = () => {
this.state.range = [this.getCursorPosition(), null];
};

private detectClickOutside = (event: MouseEvent) => {
const target = event.target;

Expand All @@ -535,6 +536,21 @@ class YagrTooltip {
}
};

private onMouseDown = (evt: MouseEvent) => {
this.state.range = [this.getCursorPosition(), null];

if (this.state.pinned) {
this.pin(false);
this.hide();
this.render({
left: evt.clientX - this.bLeft,
top: evt.clientY - this.bTop,
idx: this.yagr.uplot.posToIdx(evt.clientX - this.bLeft),
});
this.skipNextMouseUp = true;
}
};

private onMouseMove = () => {
if (this.state.range?.length) {
this.state.range[1] = this.getCursorPosition();
Expand All @@ -545,16 +561,21 @@ class YagrTooltip {
const [from] = this.state.range || [];
const cursor = this.getCursorPosition();

if (
this.opts.strategy === 'all' ||
(this.opts.strategy === 'pin' && from && from.clientX === cursor?.clientX)
) {
if (this.opts.strategy === 'none') {
return;
}

const click = from && from.clientX === cursor?.clientX;
const drag = from && from.clientX !== cursor?.clientX;

if ((click && !this.skipNextMouseUp) || (drag && this.opts.strategy === 'all')) {
this.pin(!this.state.pinned);
this.show();
this.renderTooltipCloses();
}

this.state.range = null;
this.skipNextMouseUp = false;
};

private onMouseEnter = () => {
Expand Down
113 changes: 97 additions & 16 deletions tests/plugins/tooltip.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import {TooltipHandler} from '../../src';
import {MinimalValidConfig, TooltipHandler} from '../../src';
import Yagr from '../../src/YagrCore';

const gen = (cfg: MinimalValidConfig) => {
const el = window.document.createElement('div');
window.document.body.appendChild(el);

return new Yagr(el, cfg);
};

describe('tooltip', () => {
describe('options', () => {
beforeEach(() => {
window.document.body.innerHTML = '';
});

it('should render tooltip', () => {
const el = window.document.createElement('div');
window.document.body.appendChild(el);

const yagr = new Yagr(el, {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
});
Expand All @@ -20,10 +24,7 @@ describe('tooltip', () => {
});

it('should render tooltip sum', async () => {
const el = window.document.createElement('div');
window.document.body.appendChild(el);

const yagr = new Yagr(el, {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
});
Expand All @@ -45,9 +46,7 @@ describe('tooltip', () => {
});

describe('perScale', () => {
const el = window.document.createElement('div');
window.document.body.appendChild(el);
const y = new Yagr(el, {
const y = gen({
timeline: [1, 2, 3, 4],
series: [
{data: [1, 2, 3, 4], scale: 'y'},
Expand Down Expand Up @@ -83,10 +82,7 @@ describe('tooltip', () => {
});

describe('on/off', () => {
const el = window.document.createElement('div');
window.document.body.appendChild(el);

const yagr = new Yagr(el, {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
});
Expand Down Expand Up @@ -115,4 +111,89 @@ describe('tooltip', () => {
expect(handler).toBeCalledTimes(1);
});
});

describe('pinning', () => {
it('shouldnt pin tooltip if strategy=none', async () => {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
tooltip: {
strategy: 'none',
},
});

yagr.uplot.over.dispatchEvent(new MouseEvent('mousedown', {clientX: 30, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
yagr.uplot.over.dispatchEvent(new MouseEvent('mouseup', {clientX: 30, clientY: 30}));
expect(yagr.plugins.tooltip?.state.pinned).toBe(false);
});

it('shouldnt pin tooltip if strategy=none', async () => {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
tooltip: {
strategy: 'none',
},
});

yagr.uplot.over.dispatchEvent(new MouseEvent('mousedown', {clientX: 30, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
yagr.uplot.over.dispatchEvent(new MouseEvent('mouseup', {clientX: 30, clientY: 30}));
expect(yagr.plugins.tooltip?.state.pinned).toBe(false);
});

it('should pin tooltip if strategy=pin', async () => {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
tooltip: {
strategy: 'pin',
},
});

yagr.uplot.over.dispatchEvent(new MouseEvent('mousedown', {clientX: 30, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
yagr.uplot.over.dispatchEvent(new MouseEvent('mouseup', {clientX: 30, clientY: 30}));
expect(yagr.plugins.tooltip?.state.pinned).toBe(true);
});

it('shouldnt pin tooltip on drag if strategy=pin', async () => {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
tooltip: {
strategy: 'pin',
},
});

yagr.uplot.over.dispatchEvent(new MouseEvent('mousedown', {clientX: 30, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
yagr.uplot.over.dispatchEvent(new MouseEvent('mousemove', {clientX: 40, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
expect(yagr.plugins.tooltip?.state.range).toHaveLength(2);
yagr.uplot.over.dispatchEvent(new MouseEvent('mouseup', {clientX: 40, clientY: 30}));
expect(yagr.plugins.tooltip?.state.pinned).toBe(false);
expect(yagr.plugins.tooltip?.state.range).toBeNull();
});

it('should pin tooltip on drag if strategy=all', async () => {
const yagr = gen({
timeline: [1, 2, 3, 4],
series: [{data: [1, 2, 3, 4]}],
tooltip: {
strategy: 'all',
},
});

yagr.uplot.over.dispatchEvent(new MouseEvent('mousedown', {clientX: 30, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
yagr.uplot.over.dispatchEvent(new MouseEvent('mousemove', {clientX: 40, clientY: 30}));
await new Promise((resolve) => setTimeout(resolve, 100));
expect(yagr.plugins.tooltip?.state.range).toHaveLength(2);
yagr.uplot.over.dispatchEvent(new MouseEvent('mouseup', {clientX: 40, clientY: 30}));
expect(yagr.plugins.tooltip?.state.pinned).toBe(true);
expect(yagr.plugins.tooltip?.state.range).toBeNull();
});
});
});

0 comments on commit f1d5c28

Please sign in to comment.