RevGrid - v0.9.3
    Preparing search index...

    Data Row Array Test App

    The Data Row Array Test app is used to test aspects of the data-row-array module. DataRowArray grids have a setData(data) method which updates all the rows and cells in the grid at once. Individual rows or cells cannot be updated. The data is passed as an array of JSON objects of type (DataRows).

    This app uses RevMultiHeadingDataRowArraySourcedFieldGrid which supports multi line headings. If you only require one heading line, you can use RevSingleHeadingDataRowArraySourcedFieldGrid.

    DataRowArray grids allow you to easily display static data in a grid.

    The grid itself extends from RevMultiHeadingDataRowArraySourcedFieldGrid. This sub-class:

    • creates the grid fields,
    • creates the header cell painter,
    • creates the main cell painter,
    • processes various events from the base class by overriding various functions.
    import {
    RevHorizontalAlignId,
    RevLinedHoverCell,
    RevMultiHeadingDataRowArraySourcedField,
    RevMultiHeadingDataRowArraySourcedFieldDefinition,
    RevMultiHeadingDataRowArraySourcedFieldGrid,
    RevPoint,
    RevSimpleAlphaTextCellPainter,
    RevSimpleBehavioredColumnSettings,
    RevSimpleBehavioredGridSettings,
    RevStandardHeaderTextCellPainter,
    RevViewCell,
    revSimpleReadonlyDefaultBehavioredColumnSettings,
    revSimpleReadonlyDefaultBehavioredGridSettings
    } from '../..';

    export class DataRowArrayGrid extends RevMultiHeadingDataRowArraySourcedFieldGrid<
    RevSimpleBehavioredGridSettings,
    RevSimpleBehavioredColumnSettings,
    RevMultiHeadingDataRowArraySourcedField
    > {

    cellFocusEventer: DataRowArrayGrid.CellFocusEventer | undefined;
    clickEventer: DataRowArrayGrid.RowFocusClickEventer | undefined;
    dblClickEventer: DataRowArrayGrid.RowFocusDblClickEventer | undefined;

    private readonly _headerCellPainter: RevStandardHeaderTextCellPainter<
    RevSimpleBehavioredGridSettings,
    RevSimpleBehavioredColumnSettings,
    RevMultiHeadingDataRowArraySourcedField
    >;
    private readonly _textCellPainter: RevSimpleAlphaTextCellPainter<
    RevSimpleBehavioredGridSettings,
    RevSimpleBehavioredColumnSettings,
    RevMultiHeadingDataRowArraySourcedField
    >;

    constructor(
    gridElement: HTMLElement,
    externalParent: unknown,
    ) {
    const gridSettings: RevSimpleBehavioredGridSettings = {
    ...revSimpleReadonlyDefaultBehavioredGridSettings,
    mouseColumnSelectionEnabled: false,
    mouseRowSelectionEnabled: false,
    multipleSelectionAreas: false,
    };

    super(
    gridElement,
    (viewCell) => this.getHeaderCellPainter(viewCell),
    (viewCell) => this.getMainCellPainter(viewCell),
    gridSettings,
    () => revSimpleReadonlyDefaultBehavioredColumnSettings,
    (index: number, key: string, headings: string[]) => this.createField(index, key, headings),
    { externalParent }
    );

    this._headerCellPainter = new RevStandardHeaderTextCellPainter(this, this.headerDataServer);
    this._textCellPainter = new RevSimpleAlphaTextCellPainter(this, this.mainDataServer);
    }

    get columnCount(): number { return this.activeColumnCount; }

    protected override descendantProcessCellFocusChanged(oldPoint: RevPoint | undefined, newPoint: RevPoint | undefined) {
    if (this.cellFocusEventer !== undefined) {
    this.cellFocusEventer(oldPoint, newPoint);
    }
    }

    protected override descendantProcessClick(
    event: MouseEvent,
    hoverCell: RevLinedHoverCell<RevSimpleBehavioredColumnSettings, RevMultiHeadingDataRowArraySourcedField> | null | undefined
    ) {
    if (this.clickEventer !== undefined) {
    if (hoverCell === null) {
    hoverCell = this.viewLayout.findLinedHoverCellAtCanvasOffset(event.offsetX, event.offsetY);
    }
    if (hoverCell !== undefined) {
    if (!RevLinedHoverCell.isMouseOverLine(hoverCell)) {
    const viewCell = hoverCell.viewCell;
    this.clickEventer(viewCell.viewLayoutColumn.activeColumnIndex, viewCell.viewLayoutRow.subgridRowIndex);
    }
    }
    }
    }

    protected override descendantProcessDblClick(
    event: MouseEvent,
    hoverCell: RevLinedHoverCell<RevSimpleBehavioredColumnSettings, RevMultiHeadingDataRowArraySourcedField> | null | undefined
    ) {
    if (this.dblClickEventer !== undefined) {
    if (hoverCell === null) {
    hoverCell = this.viewLayout.findLinedHoverCellAtCanvasOffset(event.offsetX, event.offsetY);
    }
    if (hoverCell !== undefined) {
    if (!RevLinedHoverCell.isMouseOverLine(hoverCell)) {
    const viewCell = hoverCell.viewCell;
    this.dblClickEventer(viewCell.viewLayoutColumn.activeColumnIndex, viewCell.viewLayoutRow.subgridRowIndex);
    }
    }
    }
    }

    // setData(data: MultiHeadingDataRowArrayServerSet.DataRow[], headerRowCount = -1): void {
    // this._serverSet.setData(data, headerRowCount)
    // }

    private createField(index: number, key: string, headings: string[]) {
    const definition = RevMultiHeadingDataRowArraySourcedFieldDefinition.create(
    { name: '' },
    key,
    headings,
    undefined,
    RevHorizontalAlignId.Left,
    );

    return new RevMultiHeadingDataRowArraySourcedField(definition);
    }

    private getHeaderCellPainter(_viewCell: RevViewCell<RevSimpleBehavioredColumnSettings, RevMultiHeadingDataRowArraySourcedField>) {
    return this._headerCellPainter;
    }

    private getMainCellPainter(_viewCell: RevViewCell<RevSimpleBehavioredColumnSettings, RevMultiHeadingDataRowArraySourcedField>) {
    return this._textCellPainter;
    }
    }

    export namespace DataRowArrayGrid {
    export type CellFocusEventer = (this: void, newPoint: RevPoint | undefined, oldPoint: RevPoint | undefined) => void;
    export type RowFocusClickEventer = (this: void, columnIndex: number, rowIndex: number) => void;
    export type RowFocusDblClickEventer = (this: void, columnIndex: number, rowIndex: number) => void;
    }

    The main class which ties everything together:

    /* eslint-disable @typescript-eslint/no-unnecessary-condition */
    /* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
    import { RevDataRowArrayGrid, RevPoint } from '../..';
    import { DataRowArrayGrid } from './data-row-array-grid';

    export class Main {
    private readonly _grid: DataRowArrayGrid;

    constructor() {
    const gridHostElement = document.querySelector('#gridHost') as HTMLElement;
    if (gridHostElement === null) {
    throw new Error('gridHost not found');
    }

    const loadStocksButtonElement = document.querySelector('#loadStocksButton') as HTMLButtonElement;
    if (loadStocksButtonElement === null) {
    throw new Error('loadStocksButton not found');
    }
    loadStocksButtonElement.onclick = () => this.loadStocks();

    const loadPetsButtonElement = document.querySelector('#loadPetsButton') as HTMLButtonElement;
    if (loadPetsButtonElement === null) {
    throw new Error('loadPetsButton not found');
    }
    loadPetsButtonElement.onclick = () => this.loadPets();

    const loadManyButtonElement = document.querySelector('#loadManyButton') as HTMLButtonElement;
    if (loadManyButtonElement === null) {
    throw new Error('loadManyButton not found');
    }
    loadManyButtonElement.onclick = () => this.loadMany();

    this._grid = this.createGrid(gridHostElement);

    this.loadStocks();
    }

    private createGrid(hostElement: HTMLElement) {
    const grid = new DataRowArrayGrid(hostElement, this);

    grid.cellFocusEventer = (newPoint, oldPoint) => this.handleCellFocusEvent(newPoint, oldPoint)
    grid.clickEventer = (columnIndex, recordIndex) => this.handleCellClickEvent(columnIndex, recordIndex);
    grid.dblClickEventer = (columnIndex, recordIndex) => this.handleRecordFocusDblClick(columnIndex, recordIndex);

    grid.activate();

    return grid;
    }

    private handleCellFocusEvent(newPoint: RevPoint | undefined, oldPoint: RevPoint | undefined): void {
    console.log(`Focus change: New: ${newPoint === undefined ? '-' : `(${newPoint.x}, ${newPoint.y})`} Old: ${oldPoint === undefined ? '-' : `(${oldPoint.x}, ${oldPoint.y})`}`);
    }

    private handleCellClickEvent(columnIndex: number, rowIndex: number): void {
    console.log(`Click for Record ${rowIndex} column ${columnIndex}`);
    }

    private handleRecordFocusDblClick(columnIndex: number, rowIndex: number): void {
    console.log(`DoubleClick for Record ${rowIndex} field ${columnIndex}`);
    }

    private loadStocks() {
    this._grid.setData([
    { symbol: 'APPL', name: 'Apple Inc.', prevclose: 93.13 },
    { symbol: 'MSFT', name: 'Microsoft Corporation', prevclose: 51.91 },
    { symbol: 'TSLA', name: 'Tesla Motors Inc.', prevclose: 196.40 },
    { symbol: 'IBM', name: 'International Business Machines Corp', prevclose: 155.35 }
    ]);
    }

    private loadPets() {
    interface Pet extends RevDataRowArrayGrid.DataRow {
    name: string;
    type: string;
    color: string;
    age: number | string;
    receiveDate: Date | string;
    favoriteFood: string;
    restrictMovement: boolean | string;
    }

    const roverAge = 5;
    const moggieAge = 7;
    const tweetsAge = 0.5;

    const pets: Pet[] = [
    {
    name: 'Name',
    type: 'Type',
    color: 'Color',
    age: 'Age',
    receiveDate: 'Receive Date',
    favoriteFood: 'Favorite Food',
    restrictMovement: 'Restrict Movement',
    },
    {
    name: 'Rover',
    type: 'Dog',
    color: 'red',
    age: roverAge,
    receiveDate: this.calculatePetReceiveDate(roverAge),
    favoriteFood: 'meat',
    restrictMovement: true,
    },
    {
    name: 'Moggie',
    type: 'Cat',
    color: 'white and black',
    age: moggieAge,
    receiveDate: this.calculatePetReceiveDate(moggieAge),
    favoriteFood: 'gravied meat',
    restrictMovement: false,
    },
    {
    name: 'Tweets',
    type: 'Canary',
    color: 'yellow',
    age: tweetsAge,
    receiveDate: this.calculatePetReceiveDate(tweetsAge),
    favoriteFood: 'pellets',
    restrictMovement: true,
    },
    ];

    this._grid.setData(pets, 1);
    }

    private calculatePetReceiveDate(age: number) {
    const ageInMilliseconds = age * 1000 * 60 * 60 * 24 * 365;
    return new Date(Date.now() - ageInMilliseconds);
    }

    private loadMany() {
    interface Row extends RevDataRowArrayGrid.DataRow {
    StrCol: string;
    NumberCol: number;
    BoolCol: boolean;
    BigIntCol: bigint;
    DateCol: Date;
    }

    const rowCount = 200;
    const rows = new Array<Row>(rowCount);

    for (let i = 1; i <= rowCount; i++) {
    const row: Row = {
    StrCol: `string${i}`,
    NumberCol: i,
    BoolCol: (i % 2) === 0,
    BigIntCol: BigInt(i),
    DateCol: new Date(2000, 1, (i % 31) + 1)
    }

    rows[i-1] = row;
    }

    this._grid.setData(rows, 0);
    }
    }