UNPKG

@siberiaweb/components

Version:
250 lines (200 loc) 6.39 kB
import Col from "../custom-grid/Col"; import CSS from "./CSS"; import CustomGrid from "../custom-grid/CustomGrid"; import HandlerTypes from "./HandlerTypes"; import HTTPRequestInterface from "@siberiaweb/http-request-interface/lib/HTTPRequestInterface"; /** * Бесконечная сетка. * * @template TRecord Тип записи. */ export default class EndlessGrid< TRecord > extends CustomGrid< TRecord > { /** * Наименование компонента. */ public static readonly COMPONENT_NAME: string = "sw-endless-grid"; /** * Количество записей, загружаемых за один раз. */ private static readonly ATTR_LOAD_RECORD_COUNT: string = "load-record-count"; /** * Количество записей, загружаемых за один раз по умолчанию. */ public static readonly DEFAULT_LOAD_RECORD_COUNT: number = 100; /** * Количество записей, загружаемых за один раз. */ private _loadRecordCount = EndlessGrid.DEFAULT_LOAD_RECORD_COUNT; /** * Сетевой запрос. */ private httpRequest: HTTPRequestInterface | null = null; /** * Страница для загрузки данных. */ private page: number = 1; /** * Признак, что все данные загружены. */ private completed: boolean = false; /** * Обработчик загрузки данных. */ public onLoad: HandlerTypes.Load | null = null; /** * Наблюдаемые атрибуты. */ public static get observedAttributes(): string[] { return CustomGrid.observedAttributes.concat( [ EndlessGrid.ATTR_LOAD_RECORD_COUNT ] ); } /** * @override */ protected firstConnectedCallback(): void { super.firstConnectedCallback(); this.classList.add( CSS.ENDLESS_GRID ); let scrollTop: number = 0; this.addEventListener( "scroll", (): void => { if ( this.scrollTop !== scrollTop ) { scrollTop = this.scrollTop; if ( ( scrollTop > 0 ) && ( ( this.clientHeight + scrollTop ) >= this.scrollHeight ) ) { this.load(); } } } ); } /** * Обработка изменения атрибута "load-record-count". * * @param newValue Новое значение. */ protected attrLoadRecordCountChange( newValue: string | null ): void { let value: number = newValue === null ? EndlessGrid.DEFAULT_LOAD_RECORD_COUNT : parseInt( newValue ); if ( isNaN( value ) ) { value = EndlessGrid.DEFAULT_LOAD_RECORD_COUNT; } if ( value < 1 ) { value = 1; } this._loadRecordCount = value; } /** * @override */ protected attributeChangedCallback( name: string, oldValue: string | null, newValue: string | null ): void { super.attributeChangedCallback( name, oldValue, newValue ); if ( name === EndlessGrid.ATTR_LOAD_RECORD_COUNT ) { this.attrLoadRecordCountChange( newValue ); } } /** * Загрузка данных. * * @throws Error Если не указан обработчик загрузки данных. */ protected load(): void { if ( this.completed ) { return; } if ( this.onLoad === null ) { throw new Error( "Не указан обработчик загрузки данных." ); } if ( this.httpRequest !== null ) { this.httpRequest.abort(); } let httpRequest: HTTPRequestInterface = this.onLoad( this.page, this.loadRecordCount ) .onBeforeSend( () => { if ( ( this.httpRequest !== null ) && ( this.httpRequest !== httpRequest ) ) { return; } this.loading = true; } ) .onComplete( () => { if ( ( this.httpRequest !== null ) && ( this.httpRequest !== httpRequest ) ) { return; } this.loading = false; } ) .onSuccess( ( response ) => { if ( ( this.httpRequest !== null ) && ( this.httpRequest !== httpRequest ) ) { return; } response.json().then( ( data: TRecord[] ) => { this.addDataSet( data ); } ); } ); this.httpRequest = httpRequest; httpRequest.send(); } /** * Начало загрузки данных - очистка таблицы и загрузка данных с первой страницы. */ public beginLoading(): void { this.clear(); this.completed = false; this.page = 1; this.load(); } /** * @override */ public sort( col: Col ): void { super.sort( col ); this.beginLoading(); } /** * @override */ public addDataSet( dataSet: TRecord[] ): void { if ( dataSet.length < this.loadRecordCount ) { this.completed = true; } else { this.page++; } super.addDataSet( dataSet ); } /** * Получение количества записей, загружаемых за один раз. */ public get loadRecordCount(): number { return this._loadRecordCount; } /** * Установка количества записей, загружаемых за один раз. * * @param value Значение. */ public set loadRecordCount( value: number ) { this.setAttribute( EndlessGrid.ATTR_LOAD_RECORD_COUNT, value.toString() ); } /** * Получение страницы для загрузки данных. */ public getPage(): number { return this.page; } /** * Конструктор. */ constructor() { super(); } }