@@ -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