Skip to content

Commit

Permalink
fix(react-chart): fix event coordinates calculation in a scrolled con…
Browse files Browse the repository at this point in the history
…tainer (#1950)
  • Loading branch information
DmitryBogomolov committed Apr 8, 2019
1 parent 785f8a1 commit 498969f
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 34 deletions.
19 changes: 10 additions & 9 deletions packages/dx-chart-core/src/plugins/tooltip/computeds.test.ts
Expand Up @@ -11,11 +11,6 @@ jest.mock('../../utils/hover-state', () => ({
processPointerMove: jest.fn().mockReturnValue('test-target'),
}));

// @ts-ignore
window.pageXOffset = 120;
// @ts-ignore
window.pageYOffset = 110;

describe('#getParameters', () => {
const createSeries = name => ({
name,
Expand Down Expand Up @@ -50,6 +45,12 @@ describe('#createReference', () => {
it('should return reference object', () => {
const root = {
getBoundingClientRect: () => ({ left: 10, top: 5 }),
ownerDocument: {
defaultView: { pageXOffset: 120, pageYOffset: 110 },
documentElement: {
getBoundingClientRect: () => ({ left: 3, top: 2 }),
},
},
};

const obj = createReference([41, 32, 45, 34], { current: root as any });
Expand All @@ -60,10 +61,10 @@ describe('#createReference', () => {
getBoundingClientRect: expect.any(Function),
});
expect(obj.getBoundingClientRect()).toEqual({
left: 171,
top: 147,
right: 175,
bottom: 149,
left: 174,
top: 149,
right: 178,
bottom: 151,
width: 0,
height: 0,
});
Expand Down
16 changes: 10 additions & 6 deletions packages/dx-chart-core/src/plugins/tooltip/computeds.ts
@@ -1,5 +1,5 @@
import { processPointerMove } from '../../utils/hover-state';
import { getRootOffset } from '../../utils/root-offset';
import { getOffset } from '../../utils/root-offset';
import {
SeriesList, SeriesRef, TransformedPoint, TargetList, NotifyPointerMoveFn,
TooltipParameters, TooltipReference, Rect,
Expand All @@ -26,12 +26,16 @@ export const createReference = (
getBoundingClientRect() {
// This function is expected to be called (by the *Popper*) when DOM is ready -
// so *rootRef.current* can be accessed.
const offset = getRootOffset(rootRef.current!);
const offset = getOffset(rootRef.current!);
// *getBoundingClientRect* of a real html element is affected by window scrolling.
// *popper.js* subscribes "html -> getBoundingClientRect -> (left, top)" from
// "reference -> getBoundingClientRect" - so here it is added.
const htmlRect = rootRef.current!.ownerDocument!.documentElement.getBoundingClientRect();
return {
left: rect[0] + offset[0],
top: rect[1] + offset[1],
right: rect[2] + offset[0],
bottom: rect[3] + offset[1],
left: rect[0] + offset[0] + htmlRect.left,
top: rect[1] + offset[1] + htmlRect.top,
right: rect[2] + offset[0] + htmlRect.left,
bottom: rect[3] + offset[1] + htmlRect.top,
width: 0,
height: 0,
};
Expand Down
23 changes: 11 additions & 12 deletions packages/dx-chart-core/src/utils/event-tracker.test.ts
@@ -1,8 +1,4 @@
import { buildEventHandlers } from './event-tracker';
// @ts-ignore
window.pageXOffset = 120;
// @ts-ignore
window.pageYOffset = 110;

describe('EventTracker', () => {
describe('#buildEventHandlers', () => {
Expand Down Expand Up @@ -35,6 +31,9 @@ describe('EventTracker', () => {

const currentTarget = {
getBoundingClientRect: () => ({ left: 40, top: 30 }),
ownerDocument: {
defaultView: { pageXOffset: 120, pageYOffset: 110 },
},
};

const call = () => buildEventHandlers([series1, series2, series3] as any, {
Expand All @@ -52,8 +51,8 @@ describe('EventTracker', () => {
const func = call();
func({
currentTarget,
clientX: 454,
clientY: 343,
pageX: 454,
pageY: 343,
});

expect(series1.createHitTester).toBeCalledWith('coordinates-1');
Expand Down Expand Up @@ -82,8 +81,8 @@ describe('EventTracker', () => {
const func = call();
func({
currentTarget,
clientX: 352,
clientY: 421,
pageX: 352,
pageY: 421,
nativeEvent: 'nativeEvent',
});

Expand Down Expand Up @@ -124,8 +123,8 @@ describe('EventTracker', () => {
const func = call();
func({
currentTarget,
clientX: 481,
clientY: 324,
pageX: 481,
pageY: 324,
nativeEvent: 'nativeEvent',
});

Expand Down Expand Up @@ -183,8 +182,8 @@ describe('EventTracker', () => {
});
mouseleave({
currentTarget,
clientX: 572,
clientY: 421,
pageX: 572,
pageY: 421,
});

expect(handler1).toBeCalledWith({ location: [412, 281], targets: [] });
Expand Down
8 changes: 4 additions & 4 deletions packages/dx-chart-core/src/utils/event-tracker.ts
@@ -1,14 +1,14 @@
import { getRootOffset } from './root-offset';
import { getOffset } from './root-offset';
import {
TrackerTarget, HandlerFnList, SeriesList, HitTesters, Location,
EventHandlerFn, TargetData, EventHandlers, HandlersObject,
} from '../types';

const getEventCoords = (e: any): Location => {
const offset = getRootOffset(e.currentTarget);
const offset = getOffset(e.currentTarget);
return [
e.clientX - offset[0],
e.clientY - offset[1],
e.pageX - offset[0],
e.pageY - offset[1],
];
};

Expand Down
16 changes: 16 additions & 0 deletions packages/dx-chart-core/src/utils/root-offset.test.ts
@@ -0,0 +1,16 @@
import { getOffset } from './root-offset';

describe('Root Offset', () => {
describe('#getOffset', () => {
it('should return element offset', () => {
const mock = {
getBoundingClientRect: () => ({ left: 400, top: 300 }),
ownerDocument: {
defaultView: { pageXOffset: 40, pageYOffset: 30 },
},
};

expect(getOffset(mock as any)).toEqual([440, 330]);
});
});
});
9 changes: 6 additions & 3 deletions packages/dx-chart-core/src/utils/root-offset.ts
@@ -1,8 +1,11 @@
import { NumberArray } from '../types';
// This function is to be called from context where DOM is available -
// so *window* can be accessed safely.
/** @internal */
export const getRootOffset = (root: Element) => {
const { left, top } = root.getBoundingClientRect();
const { pageXOffset, pageYOffset } = window;
export const getOffset = (element: Element): NumberArray => {
const { left, top } = element.getBoundingClientRect();
// Safer way to get window.
const { defaultView } = element.ownerDocument!;
const { pageXOffset, pageYOffset } = defaultView!;
return [left + pageXOffset, top + pageYOffset];
};

0 comments on commit 498969f

Please sign in to comment.