123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- import { ARIA_CONTROLS, ARIA_CURRENT, ARIA_LABEL } from '../../constants/attributes';
- import { CLASS_ACTIVE } from '../../constants/classes';
- import {
- EVENT_MOVE,
- EVENT_PAGINATION_MOUNTED,
- EVENT_PAGINATION_UPDATED,
- EVENT_REFRESH,
- EVENT_SCROLLED,
- EVENT_UPDATED,
- } from '../../constants/events';
- import { EventInterface } from '../../constructors';
- import { Splide } from '../../core/Splide/Splide';
- import { BaseComponent, Components, Options } from '../../types';
- import {
- addClass, apply,
- ceil,
- create,
- empty,
- focus,
- format,
- remove,
- removeAttribute,
- removeClass,
- setAttribute,
- } from '../../utils';
- /**
- * The interface for the Pagination component.
- *
- * @since 3.0.0
- */
- export interface PaginationComponent extends BaseComponent {
- items: PaginationItem[];
- getAt( index: number ): PaginationItem;
- update(): void;
- }
- /**
- * The interface for data of the pagination.
- *
- * @since 3.0.0
- */
- export interface PaginationData {
- list: HTMLUListElement;
- items: PaginationItem[];
- }
- /**
- * The interface for each pagination item.
- *
- * @since 3.0.0
- */
- export interface PaginationItem {
- li: HTMLLIElement;
- button: HTMLButtonElement;
- page: number;
- }
- /**
- * The component for handling previous and next arrows.
- *
- * @since 3.0.0
- *
- * @param Splide - A Splide instance.
- * @param Components - A collection of components.
- * @param options - Options.
- *
- * @return A Arrows component object.
- */
- export function Pagination( Splide: Splide, Components: Components, options: Options ): PaginationComponent {
- const { on, emit, bind, unbind } = EventInterface( Splide );
- const { Slides, Elements, Controller } = Components;
- const { hasFocus, getIndex } = Controller;
- /**
- * Stores all pagination items.
- */
- const items: PaginationItem[] = [];
- /**
- * The pagination element.
- */
- let list: HTMLUListElement;
- /**
- * Called when the component is mounted.
- */
- function mount(): void {
- init();
- on( [ EVENT_UPDATED, EVENT_REFRESH ], init );
- on( [ EVENT_MOVE, EVENT_SCROLLED ], update );
- }
- /**
- * Initializes the pagination.
- */
- function init(): void {
- destroy();
- if ( options.pagination && Slides.isEnough() ) {
- createPagination();
- emit( EVENT_PAGINATION_MOUNTED, { list, items }, getAt( Splide.index ) );
- update();
- }
- }
- /**
- * Destroys the component.
- */
- function destroy(): void {
- if ( list ) {
- remove( list );
- items.forEach( item => { unbind( item.button, 'click' ) } );
- empty( items );
- list = null;
- }
- }
- /**
- * Creates the pagination element and appends it to the slider.
- */
- function createPagination(): void {
- const { length } = Splide;
- const { classes, i18n, perPage } = options;
- const parent = options.pagination === 'slider' && Elements.slider || Elements.root;
- const max = hasFocus() ? length : ceil( length / perPage );
- list = create( 'ul', classes.pagination, parent );
- for ( let i = 0; i < max; i++ ) {
- const li = create( 'li', null, list );
- const button = create( 'button', { class: classes.page, type: 'button' }, li );
- const text = ! hasFocus() && perPage > 1 ? i18n.pageX : i18n.slideX;
- bind( button, 'click', apply( onClick, i ) );
- setAttribute( button, ARIA_CONTROLS, Components.Elements.list.id );
- setAttribute( button, ARIA_LABEL, format( text, i + 1 ) );
- items.push( { li, button, page: i } );
- }
- }
- /**
- * Called when the user clicks each pagination dot.
- * Moves the focus to the active slide for accessibility.
- *
- * @link https://www.w3.org/WAI/tutorials/carousels/functionality/
- *
- * @param page - A clicked page index.
- */
- function onClick( page: number ): void {
- Controller.go( `>${ page }`, true, () => {
- const Slide = Slides.getAt( Controller.toIndex( page ) );
- Slide && focus( Slide.slide );
- } );
- }
- /**
- * Returns the pagination item at the specified index.
- *
- * @param index - An index.
- *
- * @return A pagination item object if available, or otherwise `undefined`.
- */
- function getAt( index: number ): PaginationItem | undefined {
- return items[ Controller.toPage( index ) ];
- }
- /**
- * Updates the pagination status.
- */
- function update(): void {
- const prev = getAt( getIndex( true ) );
- const curr = getAt( getIndex() );
- if ( prev ) {
- removeClass( prev.button, CLASS_ACTIVE );
- removeAttribute( prev.button, ARIA_CURRENT );
- }
- if ( curr ) {
- addClass( curr.button, CLASS_ACTIVE );
- setAttribute( curr.button, ARIA_CURRENT, true );
- }
- emit( EVENT_PAGINATION_UPDATED, { list, items }, prev, curr );
- }
- return {
- items,
- mount,
- destroy,
- getAt,
- update,
- };
- }
|