ScrollWatcher listens for scroll events in any direction.

It manages registered callbacks globally and reuses event listeners for more efficient performance.

Methods

  • Returns the scrollable element that holds the wrapper around the main page content. By default it's document.scrollable (unless document.body is actually scrollable, in which case it will be used) but it will be different if settings.mainScrollableElementSelector is set.

    It will wait for the element to be available if not already.

    Returns Promise<HTMLElement>

Properties

fetchCurrentScroll: (
    scrollable?: ScrollTarget,
    realtime?: boolean,
) => Promise<ScrollData>

Get the scroll offset of the given scrollable. By default, it will waitForMeasureTime and so will be delayed by one frame.

Type declaration

LisnUsageError If the scrollable is invalid.

fetchCurrentScrollAction: (scrollable?: Element) => Promise<null | ScrollAction>

Returns the current ScrollAction if any.

Type declaration

LisnUsageError If the scrollable is invalid.

noTrackScroll: (
    handler?: null | OnScrollHandler,
    scrollable?: ScrollTarget,
) => void

Removes a previously added handler for trackScroll.

LisnUsageError If the scrollable is invalid.

offScroll: (handler: OnScrollHandler, scrollable?: ScrollTarget) => void

Removes a previously added handler.

LisnUsageError If the scrollable is invalid.

onScroll: (handler: OnScrollHandler, options?: OnScrollOptions) => Promise<void>

Call the given handler whenever the given scrollable is scrolled.

Unless OnScrollOptions.skipInitial is true, the handler is also called (almost) immediately with the latest scroll data. If a scroll has not yet been observed on the scrollable and its scrollTop and scrollLeft are 0, then the direction is Types.NoDirection and the handler is only called if Types.NoDirection is part of the supplied options.directions (or options.directions is not given).

IMPORTANT: The same handler can not be added multiple times for the same scrollable, even if the options differ. If the handler has already been added for this scrollable, either using trackScroll or using onScroll, then it will be removed and re-added with the current options. So if previously it was also tracking content size changes using trackScroll, it will no longer do so.

LisnUsageError If the options are invalid.

scroll: (
    direction: XYDirection,
    options?: ScrollOptions,
) => Promise<null | ScrollAction>

Scrolls the given scrollable element to in the given direction.

LisnUsageError If the direction or options are invalid.

scrollTo: (
    to: string | Element | TargetCoordinates,
    options?: ScrollToOptions,
) => Promise<null | ScrollAction>

Scrolls the given scrollable element to the given to scrollable.

Returns null if there's an ongoing scroll that is not cancellable.

Note that if to is an element or a selector, then it must be a descendant of the scrollable element.

Type declaration

    • (
          to: string | Element | TargetCoordinates,
          options?: ScrollToOptions,
      ): Promise<null | ScrollAction>
    • Parameters

      • to: string | Element | TargetCoordinates

        If this is an element, then its top-left position is used as the target coordinates. If it is a string, then it is treated as a selector for an element using querySelector.

      • Optionaloptions: ScrollToOptions
        • OptionalaltOffset?: CoordinateOffset

          Offset the target coordinates by the given amount(s) when altTarget is used.

          See ScrollToOptions.offset.

          undefined
          
        • OptionalaltTarget?: string | Element | TargetCoordinates

          If the scrolling element is already at the given coordinates (or strictly speaking we allow for 5 pixels difference), then if altTarget is given, this will become the target to scroll to.

          undefined
          
        • Optionalduration?: number

          The duration of the scroll animation. If not given, it is instant.

          0
          
        • Optionaloffset?: CoordinateOffset

          Offset the target coordinates by the given amount(s).

          E.g. if the final target coordinates are computed to be {top: 100, left: 0} and you specify offset as {top: 10, left: 20}, it will scroll to {top: 110, left: 20}.

          undefined
          
        • Optionalscrollable?: Element

          The element that should be scrolled.

          If document.body is scrollable, will use that; otherwise document.scrollingElement

        • OptionaluserCanInterrupt?: boolean

          Whether a user attempt to scroll the target can interrupt this before it finishes.

          false
          
        • OptionalweCanInterrupt?: boolean

          Whether another request to us to scroll the same target can interrupt this scroll before it finishes.

          false
          

      Returns Promise<null | ScrollAction>

      null if there's an ongoing scroll that is not cancellable, otherwise a ScrollAction.

LisnUsageError If the "to" coordinates or options are invalid.

stopUserScrolling: (
    options?: { immediate?: boolean; scrollable?: ScrollTarget },
) => Promise<void>

Cancels the ongoing scroll that's resulting from smooth scrolling triggered in the past. Does not interrupt or prevent further scrolling.

LisnUsageError If the scrollable is invalid.

trackScroll: (
    handler?: null | OnScrollHandler,
    options?: OnScrollOptions,
) => Promise<void>

This everything that onScroll does plus more:

In addition to a scroll event, the handler is also called when either the offset size or scroll (content) size of the scrollable changes as that would affect its scrollTopFraction and scrollLeftFraction and possibly the scrollTop and scrollLeft as well.

IMPORTANT: The same handler can not be added multiple times for the same scrollable, even if the options differ. If the handler has already been added for this scrollable, either using trackScroll or using onScroll, then it will be removed and re-added with the current options.


If handler is not given, then it defaults to an internal handler that updates a set of CSS variables on the scrollable element's style:

  • If options.scrollable is not given, or is null, window or document, the following CSS variables are set on the root (html) element and represent the scroll of the fetchMainScrollableElement:

    • --lisn-js--page-scroll-top
    • --lisn-js--page-scroll-top-fraction
    • --lisn-js--page-scroll-left
    • --lisn-js--page-scroll-left-fraction
    • --lisn-js--page-scroll-width
    • --lisn-js--page-scroll-height
  • Otherwise, the following variables are set on the scrollable itself, and represent its scroll offset:

    • --lisn-js--scroll-top
    • --lisn-js--scroll-top-fraction
    • --lisn-js--scroll-left
    • --lisn-js--scroll-left-fraction
    • --lisn-js--scroll-width
    • --lisn-js--scroll-height

LisnUsageError If the options are invalid.