SelectionInViewMixin

Scrolls to ensure the selected item is visible

Overview

Purpose: ensures the selected item is scrolled into view.

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

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

Expects the component to provide:

  • items property that returns the list's items. You can supply that with ContentItemsMixin.
  • state.selectedIndex state member updatable via setState.

Provides the component with:

  • Automatic scrolling of the selected item into view.
  • scrollSelectionIntoView method to force the currently-selected item into view.

Usage

import SelectionInViewMixin from 'elix/src/SelectionInViewMixin.js';
class MyElement extends SelectionInViewMixin(HTMLElement) {}

In horizontally or vertically scrollable lists, the component may be asked to select an item which is not currently in view. The SelectionInViewMixin listens for changes in the selection and, if the newly-selected item is not in view, scrolls the component by the minimum amount necessary to bring the 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 selection with the keyboard using Up/Down keys, Page Up/Page Down, Home/End. Navigation in the list is handled by KeyboardDirectionMixin and KeyboardPagedSelectionMixin. Those mixins only change the selected item, but not directly scroll the list. It is SelectionInViewMixin that scrolls the list to ensure a newly-selected 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, SelectionInViewMixin 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 symbols.scrollTarget that returns the desired element.

API

Used by classes FilterListBox, ListBox, and Menu.

scrollSelectionIntoView() method

Scroll the selected item element 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.

symbols.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 symbols.scrollTarget.