license import { MDCTopAppBarAdapter } from '../adapter' ; import { numbers } from '../constants' ; import { MDCTopAppBarBaseFoundation } from '../foundation' ; const INITIAL_VALUE = 0 ; export class MDCTopAppBarFoundation extends MDCTopAppBarBaseFoundation { /**
     * Indicates if the top app bar was docked in the previous scroll handler iteration.
     */ private wasDocked = true ; /**
     * Indicates if the top app bar is docked in the fully shown position.
     */ private isDockedShowing = true ; /**
     * Variable for current scroll position of the top app bar
     */ private currentAppBarOffsetTop = 0 ; /**
     * Used to prevent the top app bar from being scrolled out of view during resize events
     */ private isCurrentlyBeingResized = false ; /**
     * The timeout that's used to throttle the resize events
     */ private resizeThrottleId = INITIAL_VALUE ; /**
     * Used for diffs of current scroll position vs previous scroll position
     */ private lastScrollPosition : number ; /**
     * Used to verify when the top app bar is completely showing or completely hidden
     */ private topAppBarHeight : number ; /**
     * The timeout that's used to debounce toggling the isCurrentlyBeingResized
     * variable after a resize
     */ private resizeDebounceId = INITIAL_VALUE ; constructor ( adapter ? ) { super ( adapter ) ; this . lastScrollPosition = this . adapter . getViewportScrollY ( ) ; this . topAppBarHeight = this . adapter . getTopAppBarHeight ( ) ; } override destroy ( ) { super . destroy ( ) ; this . adapter . setStyle ( 'top' , '' ) ; } /**
     * Scroll handler for the default scroll behavior of the top app bar.
     */ override handleTargetScroll ( ) { const currentScrollPosition = Math . max ( this . adapter . getViewportScrollY ( ) , 0 ) ; const diff = currentScrollPosition - this . lastScrollPosition ; this . lastScrollPosition = currentScrollPosition ; if ( ! this . isCurrentlyBeingResized ) { this . currentAppBarOffsetTop -= diff ; if ( this . currentAppBarOffsetTop > 0 ) { this . currentAppBarOffsetTop = 0 ; } else if ( Math . abs ( this . currentAppBarOffsetTop ) > this . topAppBarHeight ) { this . currentAppBarOffsetTop = - this . topAppBarHeight ; } this . moveTopAppBar ( ) ; } } /**
     * Top app bar resize handler that throttle/debounce functions that execute updates.
     */ override handleWindowResize ( ) { if ( ! this . resizeThrottleId ) { this . resizeThrottleId = setTimeout ( ( ) => { this . resizeThrottleId = INITIAL_VALUE ; this . throttledResizeHandler ( ) ; } , numbers . DEBOUNCE_THROTTLE_RESIZE_TIME_MS ) ; } this . isCurrentlyBeingResized = true ; if ( this . resizeDebounceId ) { clearTimeout ( this . resizeDebounceId ) ; } this . resizeDebounceId = setTimeout ( ( ) => { this . handleTargetScroll ( ) ; this . isCurrentlyBeingResized = false ; this . resizeDebounceId = INITIAL_VALUE ; } , numbers . DEBOUNCE_THROTTLE_RESIZE_TIME_MS ) ; } /**
     * Function to determine if the DOM needs to update.
     */ private checkForUpdate ( ) { const offscreenBoundaryTop = - this . topAppBarHeight ; const hasAnyPixelsOffscreen = this . currentAppBarOffsetTop < 0 ; const hasAnyPixelsOnscreen = this . currentAppBarOffsetTop > offscreenBoundaryTop ; const partiallyShowing = hasAnyPixelsOffscreen && hasAnyPixelsOnscreen ; if ( partiallyShowing ) { this . wasDocked = false ; } else { if ( ! this . wasDocked ) { this . wasDocked = true ; return true ; } else if ( this . isDockedShowing !== hasAnyPixelsOnscreen ) { this . isDockedShowing = hasAnyPixelsOnscreen ; return true ; } } return partiallyShowing ; } /**
     * Function to move the top app bar if needed.
     */ private moveTopAppBar ( ) { if ( this . checkForUpdate ( ) ) { let offset = this . currentAppBarOffsetTop ; if ( Math . abs ( offset ) >= this . topAppBarHeight ) { offset = - numbers . MAX_TOP_APP_BAR_HEIGHT ; } this . adapter . setStyle ( 'top' , offset + 'px' ) ; } } /**
     * Throttled function that updates the top app bar scrolled values if the
     * top app bar height changes.
     */ private throttledResizeHandler ( ) { const currentHeight = this . adapter . getTopAppBarHeight ( ) ; if ( this . topAppBarHeight !== currentHeight ) { this . wasDocked = false ; this . currentAppBarOffsetTop -= this . topAppBarHeight - currentHeight ; this . topAppBarHeight = currentHeight ; } this . handleTargetScroll ( ) ; } } export default MDCTopAppBarFoundation ;