Skip to content

Commit d68d80a

Browse files
authored
Merge pull request #3100 from adumesny/master
scroll take into account ScrollContainer position
2 parents c880c61 + a5f1968 commit d68d80a

File tree

1 file changed

+30
-35
lines changed

1 file changed

+30
-35
lines changed

src/utils.ts

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export class Utils {
220220
target[key] = source[key];
221221
} else if (typeof source[key] === 'object' && typeof target[key] === 'object') {
222222
// property is an object, recursively add it's field over... #1373
223-
this.defaults(target[key], source[key]);
223+
Utils.defaults(target[key], source[key]);
224224
}
225225
}
226226
});
@@ -346,45 +346,40 @@ export class Utils {
346346
if (overflowRegex.test(style.overflow + style.overflowY)) {
347347
return el;
348348
} else {
349-
return this.getScrollElement(el.parentElement);
349+
return Utils.getScrollElement(el.parentElement);
350350
}
351351
}
352352

353353
/** @internal */
354354
static updateScrollPosition(el: HTMLElement, position: {top: number}, distance: number): void {
355-
// is widget in view?
356-
const rect = el.getBoundingClientRect();
355+
const scrollEl = Utils.getScrollElement(el);
356+
if (!scrollEl) return;
357+
358+
const elRect = el.getBoundingClientRect();
359+
const scrollRect = scrollEl.getBoundingClientRect();
357360
const innerHeightOrClientHeight = (window.innerHeight || document.documentElement.clientHeight);
358-
if (rect.top < 0 ||
359-
rect.bottom > innerHeightOrClientHeight
360-
) {
361-
// set scrollTop of first parent that scrolls
362-
// if parent is larger than el, set as low as possible
363-
// to get entire widget on screen
364-
const offsetDiffDown = rect.bottom - innerHeightOrClientHeight;
365-
const offsetDiffUp = rect.top;
366-
const scrollEl = this.getScrollElement(el);
367-
if (scrollEl !== null) {
368-
const prevScroll = scrollEl.scrollTop;
369-
if (rect.top < 0 && distance < 0) {
370-
// moving up
371-
if (el.offsetHeight > innerHeightOrClientHeight) {
372-
scrollEl.scrollTop += distance;
373-
} else {
374-
scrollEl.scrollTop += Math.abs(offsetDiffUp) > Math.abs(distance) ? distance : offsetDiffUp;
375-
}
376-
} else if (distance > 0) {
377-
// moving down
378-
if (el.offsetHeight > innerHeightOrClientHeight) {
379-
scrollEl.scrollTop += distance;
380-
} else {
381-
scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown;
382-
}
383-
}
384-
// move widget y by amount scrolled
385-
position.top += scrollEl.scrollTop - prevScroll;
361+
362+
const offsetDiffDown = elRect.bottom - Math.min(scrollRect.bottom, innerHeightOrClientHeight);
363+
const offsetDiffUp = elRect.top - Math.max(scrollRect.top, 0);
364+
const prevScroll = scrollEl.scrollTop;
365+
366+
if (offsetDiffUp < 0 && distance < 0) {
367+
// scroll up
368+
if (el.offsetHeight > scrollRect.height) {
369+
scrollEl.scrollTop += distance;
370+
} else {
371+
scrollEl.scrollTop += Math.abs(offsetDiffUp) > Math.abs(distance) ? distance : offsetDiffUp;
372+
}
373+
} else if (offsetDiffDown > 0 && distance > 0) {
374+
// scroll down
375+
if (el.offsetHeight > scrollRect.height) {
376+
scrollEl.scrollTop += distance;
377+
} else {
378+
scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown;
386379
}
387380
}
381+
382+
position.top += scrollEl.scrollTop - prevScroll;
388383
}
389384

390385
/**
@@ -395,13 +390,13 @@ export class Utils {
395390
* @param distance Distance from the V edges to start scrolling
396391
*/
397392
static updateScrollResize(event: MouseEvent, el: HTMLElement, distance: number): void {
398-
const scrollEl = this.getScrollElement(el);
393+
const scrollEl = Utils.getScrollElement(el);
399394
const height = scrollEl.clientHeight;
400395
// #1727 event.clientY is relative to viewport, so must compare this against position of scrollEl getBoundingClientRect().top
401396
// #1745 Special situation if scrollEl is document 'html': here browser spec states that
402397
// clientHeight is height of viewport, but getBoundingClientRect() is rectangle of html element;
403398
// this discrepancy arises because in reality scrollbar is attached to viewport, not html element itself.
404-
const offsetTop = (scrollEl === this.getScrollElement()) ? 0 : scrollEl.getBoundingClientRect().top;
399+
const offsetTop = (scrollEl === Utils.getScrollElement()) ? 0 : scrollEl.getBoundingClientRect().top;
405400
const pointerPosY = event.clientY - offsetTop;
406401
const top = pointerPosY < distance;
407402
const bottom = pointerPosY > height - distance;
@@ -562,7 +557,7 @@ export class Utils {
562557

563558
/** returns true if event is inside the given element rectangle */
564559
// Note: Safari Mac has null event.relatedTarget which causes #1684 so check if DragEvent is inside the coordinates instead
565-
// this.el.contains(event.relatedTarget as HTMLElement)
560+
// Utils.el.contains(event.relatedTarget as HTMLElement)
566561
// public static inside(e: MouseEvent, el: HTMLElement): boolean {
567562
// // srcElement, toElement, target: all set to placeholder when leaving simple grid, so we can't use that (Chrome)
568563
// const target: HTMLElement = e.relatedTarget || (e as any).fromElement;

0 commit comments

Comments
 (0)