/data-grid

worlds most efficient and smoothest big data grid

Primary LanguageJavaScriptMIT LicenseMIT

data-grid

GitHub license GitHub issues Bower version

What is it? Worlds most efficient and smooth big data grid. Has the most essential features without redundant bloat.

Why? Because most of the time you need to display data. Show the user a grid of data so he can browse it quickly. No need for heavy features that will slow down the website and will make the grid stutter. Simple as that.

TOC

Usage

Initiate a grid with new StorkGrid(options). This will return a grid object for further adjusting the grid later.

Options

element: the HTML DOM Element that will hold the grid. Example: { element: document.getElementById('my_grid') }

data: an Array of Objects. Every item is a Key-Value pairs where the Key indicates the column the value belongs to. Example:

{ data: [
  {name: "John", age: 20, weight: 70 },
  {name: "Ben", age: 23, weight: 80 },
  {name: "Dan", age: 24, weight: 76 }
] }

rowHeight [optional]: the height of each row. defaults to 32 (pixels). Example: { rowHeight: 40 }

headerHeight [optional]: the height of the table headers (the column names). defaults to rowHeight. Example: { headerHeight: 50 }

selection [optional]: an Object with properties defining how selections on the grid are done.

  • selection.multi: whether the user can select multiple values from the grid or not. defaults to False. Example: { selection: { multi: true } }
  • selection.type: what type of element can the user select - a whole row or a single cell. defaults to "row". Example: { selection: { type: "cell" } }

trackBy [optional]: the column which the grid should keep track of its content by (index). defaults to null. Example: { trackBy: "age" }

columns [optional]: an Array of Objects. Each item in the array is an object that defines a column. These objects have the following properties:

  • field: the key that will be looked for in the data object.
  • label: the display name of the column (the text in the table headers).
  • width: a user defined width for the column.
  • minWidth: a user defined minimum width for when the client resizes the column.
  • fixed: whether this column is fixed to the left and will not be moved when scrolling horizontally.
  • sortable: if false than clicking the column will do nothing (becomes unsortable) and also adds a class to indicate this.
  • render(tdDiv, value, dataIndex, rowData): special function that will render the data inside the TD instead of the default renderer. This function lets you decide how to print the data (instead of just printing it as plain text), even put html inside.
  • resizable: whether this specific column is not resizable. Example:
{ columns: [
  { field: 'name', label: 'Full Name', width: 75 },
  { field: 'age', label: 'Age', resizable: false },
  { field: 'weight', label: 'Weight (kg)', width: 60, render: function(tdDiv, value, dataIndex, rowData) { tdDiv.innerHTML = value+'!'; } }
] }

minColumnWidth [optional]: the minimum column width that can be set. defaults to 50. Example: { minColumnWidth: 65 }

resizableColumns [optional]: can the user resize the columns by dragging the header. defaults to true. Example: { resizableColumns: false }

sortable [optional]: does clicking the header cells emit a sort event. defaults to true. Example: { sortable: false }

onload [optional]: function to run after the grid finished constructing. defaults to null. the event's detail has a gridObj property holding the grid object. Example:

{ onload: function(e) {
  console.log(e.detail);
} }

asyncLoading [optional]: should the data grid load asynchronous thus letting other scripts run before it. defaults to false. Example: { asyncLoading: true }

Methods

setRowHeight(height): sets the height of each row. arguments: height {integer}.

setHeaderHeight(height): sets the height of the header. arguments: height {integer}.

addEventListener(type, listener, optionsUseCapture): adds an event listener to the DOM Element of the grid. arguments: type {string}, listener {function}, [optionsUseCapture] {boolean|object}. Example:

var myEventListener = function(e) {
  console.log(e.detail); // logs: {column: "age", dataIndex: 17}
};
myGrid.addEventListener("select", myEventListener, false);

removeEventListener(type, listener, optionsUseCapture): removes an event listener from the DOM Element of the grid. arguments: type {string}, listener {function}, [optionsUseCapture] {boolean|object}. Example:

myGrid.removeEventListener("select", myEventListener, false);

addScrollEvent(type, amount, fromBottom): add a custom event to be emitted on certain positions when scrolling. arguments: type {string} - the name of the event to be emitted. amount {integer} - the threshold in pixels for when to emit the event. fromBottom {boolean} - threshold is relative to the bottom of the grid or else to the top (defaults to true).

resizeCalculate: re-calculates the viewport's height and the inner tables scrolling thresholds (in charge of replacing the data rows while scrolling). use this when the user resizes the window or the grid.

resize: a method for completely calculating and rebuilding new inner data tables when the grid's main element has changed its size.

setData(data): sets a new data object and then refreshes the grid. arguments: data {object}.

refresh: calculates the height of the data and the maximum scroll available, and updates the height of the rows container and then repositions the data rows. use this in cases where the grid's data was altered by reference and the grid wasn't aware of it.

destroy: completely destroy the grid - its DOM elements, methods and data.

setColumns(columns): set a new columns for the grid. can be used to re-arrange the columns or set some as fixed etc.. arguments: columns {object}.

addColumnClass(field, className): add a class to a specific column header (to a TH). arguments: field {string}, className {string}.

removeColumnClass(field, className): remove a class off a specific column header (off a TH). arguments: field {string}, className {string}.

Events

select: when the user selected something from the grid. this event has a detail object containing four properties - the index of the selected data (event.detail.dataIndex), the row's data object (event.detail.rowData), the selected column (event.detail.column) and whether it is a select or un-select (event.detail.isSelect). Example:

myGrid.addEventListener("select", function(e) {
  console.log(e.detail); // logs: {dataIndex: 17, rowData: {name: "joe", age: 20}, column: "age", isSelect: true}
});

dblselect: same as select but emitted when user double clicks the grid. 🔸notice: on the first click of the double-click a select event is still emitted and then on the second click a dblclick event is emitted.

enter-select: same as select but emitted when user presses ENTER for selecting data on the grid.

data-click: when the user performs a full click on something from the grid. this event has a detail object containing four properties - the index of the selected data (event.detail.dataIndex), the row's data object (event.detail.rowData), the selected column (event.detail.column) and whether it is a select or un-select (event.detail.isSelect). Example:

myGrid.addEventListener("data-click", function(e) {
  console.log(e.detail); // logs: {dataIndex: 17, rowData: {name: "joe", age: 20}, column: "age", isSelect: true}
});

column-click: when the user clicks on a column header this event is emitted with a detail object holding one property - the column field name (event.detail.column). this event can be used to sort the column and then add an 'ascending' or 'descending' class to the column via addColumnClass. :small_orange_diamond:notice: this is just an event. the actual sort and grid refresh is not done by the grid.

resize-column: is emitted after the user has resized a column's width. this event has a detail object containing two properties - the index of the resized column (event.detail.columnIndex) and the new width of the column (event.detail.width).

grid-loaded: when the grid completes its constructing this event is emitted. you can listen to this event instead of giving the onload option.

Custom scroll events: these events will be emitted if defined via the addScrollEvent method.

Code Example

<div id="my_grid" style="width: 80%; height: 400px;"></div>
var myData = [
  {name: "John", age: 20, weight: 70, miscInfo: "is tall" },
  {name: "Ben", age: 23, weight: 80, miscInfo: "is short" },
  {name: "Dan", age: 24, weight: 86, miscInfo: "is fat" }
];

var sortColumn = function sortColumn(column, state) {
  return function(a, b) {
    if(state === null && a.id) {
      column = 'id';
      state = 'ascending';
    }
    if (a[column] < b[column]) { return (state === 'ascending' ? 1 : -1); }
    if (a[column] > b[column]) { return (state === 'ascending' ? -1 : 1); }
    return 0;
  }
};

document.getElementById('my_grid').addEventListener('grid-loaded', function(e) {
  console.log('second way of onload', e.detail.gridObj);
}, { capture: false });

myGrid = new StorkGrid({
  element: document.getElementById('my_grid'),
  data: myData,
  rowHeight: 30,
  headerHeight: 50,
  sortable: true,
  selection: {
    multi: false,
    type: 'row'
  },
  columns: [
    { field: 'name', label: 'Full Name', width: 75 },
    { field: 'age', label: 'Age' },
    { field: 'weight', label: 'Weight (kg)', width: 60, fixed: true, render: function(tdDiv, value) {
      if(value.length > 10) { tdDiv.innerHTML = value.substr(0, 7) + '...'; }
        else { tdDiv.innerHTML = value; }
      }
    }
  ],
  trackBy: 'age',
  minColumnWidth: 65,
  resizableColumns: true,
  onload: function(e) { console.log('first way of onload', e.detail.gridObj); }
});

myGrid.addEventListener("select", function(e) {
  console.log('column selected', e.detail); // logs: {column: "age", dataIndex: 17}
}, false);
myGrid.addEventListener("dblselect", function(e) {
  console.log('double clicked column', e.detail); // logs: {column: "age", dataIndex: 17}
}, false);
myGrid.addEventListener("enter-select", function(e) {
  console.log('enter pressed', e.detail); // logs: {column: "age", dataIndex: 17}
}, false);

// a way to make an infinite scroll. just load ajax content instead of this dummy
myGrid.addScrollEvent('almostHitBottom', 100); // when to emit
myGrid.addEventListener('almostHitBottom', function(e) {
  myData.push({name: "Dave", age: 27, weight: 90, miscInfo: "is old" });
  testGrid.setData(myData);
}, false);

myGrid.addEventListener('sort', function(e) {
  testGrid.data.sort(sortColumn(e.detail.column, e.detail.state));
  testGrid.refresh();
}, false);

myGrid.addEventListener('resize-column', function(e) {
  console.log(e.detail);
}, false);

Demo

View demo on plunker