import { EventHandler } from '@syncfusion/ej2-base' ; import { debounce } from '@syncfusion/ej2-base' ; import { SentinelInfo , SentinelType } from '../base/type' ; import { InterSection } from '../base/interface' ; export type ScrollDirection = 'up' | 'down' | 'right' | 'left' ; hidden export class InterSectionObserver { private containerRect : ClientRect ; private element : HTMLElement ; private fromWheel : boolean = false ; private touchMove : boolean = false ; private options : InterSection = { } ; private sentinelInfo : SentinelInfo = { 'up' : { check : ( rect , info ) => { let top = rect . top - this . containerRect . top ; info . entered = top >= 0 ; return top + ( this . options . pageHeight / 2 ) >= 0 ; } , axis : 'Y' } , 'down' : { check : ( rect , info ) => { let cHeight = this . options . container . clientHeight ; let top = rect . bottom ; info . entered = rect . bottom <= this . containerRect . bottom ; return top - ( this . options . pageHeight / 2 ) <= this . options . pageHeight / 2 ; } , axis : 'Y' } , 'right' : { check : ( rect , info ) => { let right = rect . right ; info . entered = right < this . containerRect . right ; return right - this . containerRect . width <= this . containerRect . right ; } , axis : 'X' } , 'left' : { check : ( rect , info ) => { let left = rect . left ; info . entered = left > 0 ; return left + this . containerRect . width >= this . containerRect . left ; } , axis : 'X' } } ; constructor ( element , options ) { this . element = element ; this . options = options ; } public observe ( callback , onEnterCallback ) { this . containerRect = this . options . container . getBoundingClientRect ( ) ; EventHandler . add ( this . options . container , 'wheel' , ( ) => this . fromWheel = true , this ) ; EventHandler . add ( this . options . container , 'scroll' , this . virtualScrollHandler ( callback , onEnterCallback ) , this ) ; } public check ( direction ) { let info = this . sentinelInfo [ direction ] ; return info . check ( this . element . getBoundingClientRect ( ) , info ) ; } private virtualScrollHandler ( callback , onEnterCallback ) { let prevTop = 0 ; let prevLeft = 0 ; let debounced100 = debounce ( callback , 100 ) ; let debounced50 = debounce ( callback , 50 ) ; return ( e ) => { let top = ( < HTMLElement > e . target ) . scrollTop ; let left = ( < HTMLElement > e . target ) . scrollLeft ; let direction = prevTop < top ? 'down' : 'up' ; direction = prevLeft === left ? direction : prevLeft < left ? 'right' : 'left' ; prevTop = top ; prevLeft = left ; let current = this . sentinelInfo [ direction ] ; if ( this . options . axes . indexOf ( current . axis ) === - 1 ) { return ; } let check = this . check ( direction ) ; if ( current . entered ) { onEnterCallback ( this . element , current , direction , { top : top , left : left } ) ; } if ( check ) { let fn = debounced100 ; if ( current . axis === 'X' ) { fn = debounced50 ; } fn ( { direction : direction , sentinel : current , offset : { top : top , left : left } , focusElement : document . activeElement } ) ; } this . fromWheel = false ; } ; } public setPageHeight ( value ) { this . options . pageHeight = value ; } }