CursorInViewMixin

Scrolls to ensure the current item is visible

Overview

Purpose: ensures the current item is scrolled into view.

This mixin works at the very end of the Elix render pipeline:

events → methods → setState → render DOM → post-render

Expects the component to provide:

  • items state member that returns the list's items. You can supply that with ContentItemsMixin.
  • currentIndex state member, e.g., via ItemsCursorMixin.
  • optional internal.scrollTarget property that returns the element that should be scrolled. See below.

Provides the component with:

  • Automatic scrolling of the current item into view when the item cursor moves.
  • scrollCurrentItemIntoView method to force the current item into view.

Usage

import CursorInViewMixin from "elix/src/base/CursorInViewMixin.js";
class MyElement extends CursorInViewMixin(HTMLElement) {}

In horizontally or vertically scrollable lists, the component may be asked to show an item which is not currently in view. The CursorInViewMixin listens for changes in the item cursor and, if the new current item is not in view, scrolls the component by the minimum amount necessary to bring the current item into view.

For reference, the Blink engine has a scrollIntoViewIfNeeded() function that does something similar, but unfortunately it's non-standard, and often ends up scrolling more than is absolutely necessary.

Example

Acai
Akee
Apple
Apricot
Avocado
Banana
Bilberry
Black sapote
Blackberry
Blackcurrant
Blood orange
Blueberry
Boysenberry
Cantaloupe
Cherimoya
Cherry
Chico fruit
Clementine
Cloudberry
Coconut
Crab apple
Cranberry
Cucumber
Currant
Damson
Date
Dragonfruit
Durian
Elderberry
Feijoa
Fig
Goji berry
Gooseberry
Grape
Grapefruit
Guava
Honeyberry
Honeydew
Horned melon
Huckleberry
Jabuticaba
Jackfruit
Jambul
Japanese plum
Jostaberry
Jujube
Juniper berry
Kiwifruit
Kumquat
Lemon
Lime
Longan
Loquat
Lychee
Mandarin
Mango
Mangosteen
Marionberry
Miracle fruit
Mulberry
Nance
Nectarine
Orange
Papaya
Passionfruit
Peach
Pear
Persimmon
Pineapple
Pineberry
Plantain
Plum
Pluot
Pomegranate
Pomelo
Purple mangosteen
Quince
Rambutan
Raspberry
Redcurrant
Salak
Salal berry
Salmonberry
Satsuma
Soursop
Star apple
Star fruit
Strawberry
Surinam cherry
Tamarillo
Tamarind
Tangerine
Ugli fruit
Watermelon
White currant
White sapote
Yuzu
Demo: A list that keeps its selection (if one exists) in view

The above ListBox lets users navigate the current item (and the selection) with the keyboard using Up/Down keys, Page Up/Page Down, Home/End. Navigation in the list is handled by KeyboardDirectionMixin and KeyboardPagedCursorMixin. Those mixins only change the current item, but not directly scroll the list. It is CursorInViewMixin that scrolls the list to ensure a newly-current item is made visible.

Determining which element to scroll

The component's scrolling surface may be the component itself, or it may be an element within the component's shadow subtree. By default, CursorInViewMixin will try to determine which element should be scrolled. If the component has a default (unnamed) <slot>, the mixin will find the closest ancestor of that slot that has overflow: auto or overflow: scroll. If no such element is found, the component itself will be assumed to be the scrollable element.

A component can also explicitly indicate which of its shadow subtree elements should be scrolled by defining a property called internal.scrollTarget that returns the desired element.

API

Used by classes FilterListBox, ListBox, Menu, MultiSelectListBox, OptionList, PlainFilterListBox, PlainListBox, PlainMenu, PlainMultiSelectListBox, and PlainOptionList.

scrollCurrentItemIntoView() method

Scroll the current item completely into view, minimizing the degree of scrolling performed.

Blink has a scrollIntoViewIfNeeded() function that does something similar, but unfortunately it's non-standard, and in any event often ends up scrolling more than is absolutely necessary.

This scrolls the containing element defined by the scrollTarget property. By default, it will scroll the element itself.

scrollTarget property

The element that should be scrolled to get the selected item into view.

By default, this uses the defaultScrollTarget helper to find the most likely candidate for scrolling. You can override this property to directly identify which element should be scrolled.

See also scrollTarget.