@siberiaweb/components
Version:
250 lines (200 loc) • 6.39 kB
text/typescript
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();
}
}