npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@raydreams/jscontrols

v1.1.2

Published

Common.js + Bootstrap 5 UI controls library

Downloads

13

Readme

raytools 1.1.2

Raytools is my personal collection of Javascript controls that depend on Bootstrap 5 (that may change later to no dependencies or multiple CSS libs).

Raytools data grid

I wanted a very simple to use JavaScript data table that met 95% of the patterns I needed which included paging, sorting, adding a few button columns with custom handlers, and using icons and styles from Bootstrap to keep it simple. This started out of me getting totally hosed by Telerik's Kendo UI jQuery in which the grid was originally free and then they started charging.

I know ther are TONS of JS gridtables in the world but the best ones cost and others take some time to figure out all the settings. I'm trying to keep this one as simple as possible.

I'm no Bootstrap/CSS guru so if you have some tips to clean-up the layout, feel free to pass them along. I'm totally open to snazzing it up and even completly removing the Bootstrap dependency to make this a pure jQuery data table.

There's no plan to make this an inline editable grid table since my prefered UI is to use edit modals when a row is clicked.

Installation

You can download the package from NPM

Implementation

Bootstrap 5 and Bootstrap Icons are a required dependency.

Live Demo

See demo/index.html to see how to configure.


import * as ray from '@raydreams/jscontrols'

var dataTable = null;

document.addEventListener("DOMContentLoaded", function (event) {

    dataTable = new ray.RayGrid(document.getElementById("dataTable"), {
        keyfield: 'id',
        styleClasses: ['table-bordered', 'table-hover'],
        columns: [
            { title: "Info", icons: [{ glyph: "info-circle-fill", handler: iconAction, data: "color" }], renderIf: isManager },
            { field: "firstName", title: "First Name", sort: true },
            { field: "lastName", title: "LastName", sort: true },
            { field: "title", title: "Title", sort: false },
            { field: "email", title: "Email" },
            { field: "grade", title: "Grade", sort: true },
            { field: "ssn", title: "SSN", sort: false },
            { field: "dob", title: "DOB", sort: true, format: (date) => { return new Date(date).toLocaleString('en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' }); } },
            { title: "Delete", icons: [{ glyph: "trash", handler: deleteRecord, data: "color" }] }
        ],
        rowNumbers: { visible: true, title: "Row", styleClasses: ['rowNumStyle'], },
        pageSize: 11,
        maxPageButtons: 5,
        footer: { autoHide: true },
        rowClickHandler: rowAction
    });

    getData();
});

/* callback when data is loaded from an API call or file */
function loadData(myData) {
    dataTable.data = myData;
    dataTable.render();
}

Using Icons

The whole original idea was to just use the Bootstrap icons - then Bootstrap 4 happened. Version 1 of RayGrid finally goes back to just specifying the Bootstrap 5 icon label such as arrow-bar-left.

Thus, on any column use can add an array of interactive icons:

icons: [{ glyph: "trash", handler: deleteRecord, data: "someField" }]

The glyph name is just the Bootstrap 5 icon name.

Parameters & Options

The following documents parameters you can set in constructor options:

  • keyfield - keyfield is the object property to use to identify each unique row object - usually a string, GUID or INT unique identifier.
  • styleClasses - By default the table class is set - but this string array allows you to specify other Bootstrap table style classes as options.
  • columns - Columns is the array of column objects to display which mainly need a title and field to map to in the data objects.
    • field - the actual object property field name.
    • title - the column header displayed
    • icons - (optional) An arary of Bootstrap icons to display in the column so each column can have more than one icon.
      • glyph - the glyph's name e.g. trash
      • handler - (optional) a callback to handle clicking on the icon. Column icon event handlers return a JS event as well as a data object { idx: dataIdx, id: rowKey, value: data }
      • data - (optional) Additional data field value returned in the event handler
    • sort - (optional, default is false) set to true to allowing sorting on this field.
    • renderIf - (optional) a callback function with the signature (dataItem) -> bool, where item is the object bound to that row, that returns whether to even render the contents of the cell at all. This can be use to skip cell icons based on some condition and simply a shortcut to using format that returns an empty string if the condition is true.
    • format - (optional) a callback function with the signature (dataItem) -> string, where item is the object bound to that row, that returns a format string to display in that cell, such as formatting dates. WARNING this sets the InnerHTML so only set data from a trusted source.
    • width - (optional) If specified with a positive integer will set a style width property on the column in pixels.
  • pageSize - (optional, defaults to 25) Should be self-explanatory, the number of items to display per page.
  • rowNumbers - (optonal) Options for displaying row numbers as the left most column
    • visble - (bool) set to true to render, otherwise just false
    • title - (string) override the default column header which is 'Row'
    • styleClass - (string) the CSS class to set on each in this column
  • maxPageButtons - (optional) the maximum number of pager buttons to display.
  • noDataLabel - (optional) the text to display where there is no data to display.
  • rowClickHandler - (optional) If the row is clicked you can set a generic row click handler. This will set the table's currentSelection property to an object with the zero based row index as well as the keyfield ID of the object bound to that row. It will also send back a JS event as well as some additional data { idx: dataIdx, id: rowKey }. Using row click events in combination with cell icon events may cause weirdness.
  • footer - (optonal) Options for displaying the table footer containing the pager and summary
    • autoHide - (bool) When true will hide the pager if there is only a single page

Accessors

There are a few getters/setters on the table property for changing the data programmatically:

Setting Data at Runtime

Use the 'data' property to set the data then you must call render() explicitly.

dataTable.data = myData;
dataTable.render();

Accessing Bound Data

for (var i; i < dataTable.data.length; ++i)
{
	let item = dataTable.data[i];
}

Selected

Get the last selected or clicked record

let item = dataTable.selected;

Page Index

Get or set the page index which is 0 based for the first page

const pages = dataTable.maxPages;
dataTable.pageIndex = 5;

Event Handlers

Handle an Icon Click Event

function iconAction(event, item) {
    alert(`Favorite Color for item ${item.idx} is ${item.value}`);
    event.stopPropagation();
}

Handle a Row Click Event

function rowAction(event, item) {
    alert(JSON.stringify(item));
}

Handle a Conditional Render

function isManager(item) {
	return (item.grade > 3);
}

Handle Custom Formatting

Sets the InnerHTML property for now so be careful. Will change to send back only the HTML element.

function formatDate(item) {
  return new Date(item).toLocaleString('en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' });
}
function formatHyperlink(item) {
  return `<a href="https://www.linkedin.com/">${item.email}</a>`;
}

Using with vue.js

I use vue.js but I really only use it for the templating and routing i.e. I don't use it the vue way with all the HTML attribute conditionals. This make my code more portable if I want to change to something else later.

So something like this works perfectly fine in vue.

<script setup>

import { onMounted } from 'vue'
import { RayGrid } from '@raydreams/jscontrols'

let dataTable = null;

onMounted( () => {

    // define the data table using a parent block element like div
    dataTable = new RayGrid(document.getElementById("dataTable"), { 
        keyfield:'id',
        styleClasses: ['table-bordered','table-hover'],
        columns:[
            { title: "Info", icons:[ { glyph: "info-circle-fill", handler: iconAction, data: "color" }], renderIf:isManager },
            { field: "firstName", title: "First Name", sort: true },
            { field: "lastName", title: "LastName", sort: true },
            { field: "title", title: "Title", sort: false },
            { field: "email", title: "Email" },
            { field: "grade", title: "Grade", sort: true },
            { field: "ssn", title: "SSN", sort: false },
            { field: "dob", title: "DOB", sort: true, format: (item) => { return new Date(item.dob).toLocaleString('en-CA', { year: 'numeric', month: '2-digit', day: '2-digit' }); } },
            { title: "Delete", icons: [{ glyph: "trash", handler: deleteRecord, data: "color" }]}
        ],
        rowNumbers: { visible: true, title: "Row", styleClasses: ['rowNumStyle'] },
        pageSize: 13,
        maxPageButtons: 7,
        rowClickHandler: rowAction
    });

    doGetData();
})

Enjoy

Change History

Change History 1.1.0

  • Added RayDropdown.
  • Added being able to hide the pager if there is only one page.
  • Fixed bugs when there is no data.
  • Moved common utility functions to utils.js

Change History 1.0.10

  • Bug fixes
  • Documentation updates

Change History 1.0.3

  • The main control file is now raygrid.js since there might be other controls later.
  • Dependency is now on Bootstrap 5.
  • Dependency on jQuery has been removed.
  • Bootstrap glyph icons are supported again.
  • Added properties to specify the sort icons.
  • Added Getter/Setter for the data itself.
  • Added Getter for the last selected data row.
  • Added options.tableStyleClasses to set multiple style classes on the table element itself.
  • Each row is set with a data-key attribute set to the key field value
  • Added Getter/Setter for the current page index to set if you load new data.