canvas-datagrid

repository·master·Indexed 23 days ago

https://github.com/tonygermaneri/canvas-datagrid

A high-performance, canvas-based data grid web component capable of displaying millions of contiguous hierarchical rows and columns on a single canvas element without paging or loading. Compatible with modern frameworks including Vue and React, it supports custom data formatting via schema types, formatters, and the rendertext event, as well as multi-line editing and dropdown selection.

Tokens
26.3K
Snippets
65
Records
109
Agent score
80%

What's inside canvas-datagrid

  1. Overview of canvas-datagrid features

    master

    canvas-datagrid is an HTML Canvas-based grid designed for spreadsheet-like data display (similar to Excel or Google Sheets). It uses a single canvas element drawn in immediate mode, ensuring that performance remains consistent regardless of data size.

    Key capabilities include:

    • High Performance: Supports unlimited rows and columns without paging or loading.
    • Cross-Platform: Works in Firefox, Edge, Safari, and Chrome, with native support for touch devices (phones and tablets).
    • Extensibility: Supports customizable styling, filtering, formatting, resizing, selecting, and ordering.
    • Advanced Data Views: Supports hierarchical drill-down (row-level inner grids) and grids within cells.
    • Framework Agnostic: Implemented as a W3C Web Component, making it compatible with any modern web framework.
    • User Persistence: Can use localStorage to save per-user styles, column/row sizes, and view preferences.
    • Rich API: Provides a familiar W3C DOM-like interface for events, methods, and properties.
  2. Browser compatibility and Shadow DOM behavior

    master

    The grid's behavior varies depending on browser support for Custom Elements and Shadow DOM:

    • Custom Tags: In browsers that do not support custom tags, the <canvas-datagrid> tag will be treated as a standard <canvas> tag.
    • Shadow DOM: If the browser does not support Shadow DOM, no shadow root will be created. In this mode, cascading CSS from your application can alter the grid's appearance and behavior, potentially breaking in-line editing and context menus. Careful CSS management is required in these environments.
  3. How visual styling works in canvas-datagrid

    master

    Visual elements in the grid are controlled by a style object. Styling is divided into two categories:

    1. DOM Styles: Standard CSS-like properties applied to the grid's container element (e.g., width, margin).
    2. Canvas Drawing Styles: Properties specifically related to how the grid is rendered onto the HTML5 Canvas. These are managed via the style object or by interacting with the Canvas 2D context during rendering events.
  4. Set and get grid data

    master

    Data is managed via the grid.dataType MIME type. The default is application/x-canvas-datagrid.

    Supported Data Formats:

    • Array of Objects: [{col1: 'val1', col2: 'val2'}, ...]
    • Array of Arrays: [['val1', 'val2'], ['val3', 'val4']] (Columns will be named A, B, C... if no schema is provided).

    Data Loading Methods:

    MethodParser
    data propertyapplication/x-canvas-datagrid
    Web component data attributeapplication/json+x-canvas-datagrid
    Web component innerHTMLapplication/json+x-canvas-datagrid

    When getting data, it is always returned as an array of objects using the application/x-canvas-datagrid format.

  5. Unicode character support in canvas-datagrid

    master

    The canvas-datagrid component supports a wide range of Unicode characters, including complex scripts and special symbols. This allows the grid to display diverse data types such as:

    • CJK Compatibility Forms and CJK Unified Ideographs Extension B
    • Arabic Presentation Forms-B
    • Mathematical Alphanumeric Symbols
    • Musical Symbols (including Byzantine Musical Symbols)
    • Specialized Scripts like Old Italic, Gothic, and Deseret
    • Halfwidth and Fullwidth Forms

    When preparing data for the grid, ensure your data source provides these characters as valid UTF-8 strings or Unicode escape sequences.

  6. Data formats for canvas-datagrid

    master

    The canvas-datagrid uses MIME type parsers defined in grid.dataType to interpret data. The default parser is application/x-canvas-datagrid.

    This default format supports two structures, but they must strictly conform to a schema (all items must have the same properties or lengths):

    1. Array of Objects: Each object represents a row with keys corresponding to column identifiers.
    2. Array of Arrays: Each inner array represents a row, where the index corresponds to the column.

    Regardless of how data is initially set, calling the method to get data will always return an array of objects in the application/x-canvas-datagrid format.

    // Array of objects format
    [
      { col1: 'row 1 column 1', col2: 'row 1 column 2', col3: 'row 1 column 3' },
      { col1: 'row 2 column 1', col2: 'row 2 column 2', col3: 'row 2 column 3' },
    ];
    
    // Array of arrays format
    [
      ['row 1 column 1', 'row 1 column 2', 'row 1 column 3'],
      ['row 2 column 1', 'row 2 column 2', 'row 2 column 3'],
    ];
  7. Use Cell Grids (Nested Grids)

    master

    A Cell Grid is a child instance of canvas-datagrid rendered inside a single cell.

    To enable this, set the type of a header or cell to canvas-datagrid. The value of that cell will then be passed to the data property of the child grid.

    Customization Hooks:

    • beforerendercellgrid: Triggered before a cell grid is drawn. Call e.preventDefault() to stop it.
    • beforecreatecellgrid: Triggered before the child grid is instantiated. You can manipulate e.cellGridAttributes here to pass custom parameters to the child grid.

    Cells containing a grid will have cell.isGrid set to true.

  8. Define a column schema for canvas-datagrid

    master

    A schema is an optional array of header (column) objects that defines how data is interpreted and displayed. If no schema is provided, the grid will automatically generate one from the data, treating all values as strings.

    When providing data as a 2D array (an array of arrays), columns are automatically named A, B, C, D, etc., unless a schema is explicitly provided to map them.

    [
      {
        name: 'col1',
      },
      {
        name: 'col2',
      },
      {
        name: 'col3',
      },
    ];
  9. Customize cell appearance using the 'rendercell' event

    master

    You can dynamically change the visual appearance of cells by listening to the rendercell event. This event provides access to the cell's data and the Canvas 2D API context (ctx), allowing you to modify properties like fillStyle based on specific cell values or headers.

    To implement conditional styling, check the cell's header name or value within the event listener and update the e.ctx properties before the cell is drawn.

    grid.addEventListener('rendercell', function (e) {
      if (e.cell.header.name === 'MyStatusCell' && /blah/.test(e.cell.value)) {
        e.ctx.fillStyle = '#AEEDCF';
      }
    });
  10. Set grid dimensions for performance

    master

    By default, canvas-datagrid has grid.style.height: auto and grid.style.width: auto, meaning it expands to fit all rows and columns. For large datasets, this can degrade performance.

    To enable a virtual scroll box and improve performance, limit the height and width by setting grid.style.height and grid.style.width to a specific value (e.g., 100% or 300px).

  11. Format cell data using grid formatters

    master

    Grid formatters are the fastest way to format data for display without modifying the underlying data. You assign a function to a specific data type on the grid.formatters object. When the grid draws a cell with that data type, it passes the value through your function and displays the returned value instead. This method uses an O(1) hash map and is highly performant.

    Note: This requires the data type to be defined in your grid schema.

    grid.formatters.date = function (e) {
      return new Date(e.cell.value).toISOString();
    };