An indexed record Datasaur module.
The datasaur-indexed data source provides a means to map the original set of rows, resulting in a subset of particular rows in a particular order.
datasaur-indexed sits on top of a static datasource. For example:
var Source = require('datasaur-local'); // v3.0.0 or higher
var Indexer = require('datasaur-indexed'); // this version must be >= that of datasaur-local
var dataModel = new Indexer(new Source);datasaur-indexed defines a custom index instance property, a version static property, and some helper methods described in the next section.
The index property when defined is an integer array that maps the y value (row index provided to other method calls) to specific rows in the original set of rows.
This property is all that is needed to effectively "index" (reorder, filter, and/or alias) the data.
Given the following set of rows (shown here in JSON syntax):
[
  { "name": "Sam", "gender": "M" },
  { "name": "Al", "gender": "F" },
  { "name": "Max", "gender": "M" },
  { "name": "Jo", "gender": "F" }
]To filter the data:
dataModel.index = [0, 2] // rows where second column is 'M'To order the data:
dataModel.index = [1, 3, 2, 0] // alpha ascending by first columnTo alias all rows:
dataModel.index = [0, 0, 1, 1, 2, 2, 3, 3]To remove the index and revert to the original set of rows:
dataModel.index = undefinedWhile the above approach works, it is wholly inadequate, however, as a generalized solution for filtering and sorting.
See buildIndex and Generalized sorting below for better solutions.
The version string from package.json. (This is a static property of the constructor.)
datasaur-indexed defines four custom methods.
Using the dataModel.setIndex([...]) method, rather than assigning directly to dataModel.index, will dispatch the pre- and post-index data events back to the applicaiton (see Event strings below).
dataModel.buildIndex and dataModel.sort both call dataModel.setIndex.
Calling without an argument is the same as calling dataModel.clearIndex.
Undefines the index (by calling setIndex(undefined)).
Builds a new index and calls dataModel.setIndex on it:
dataModel.buildIndex(predicate);where predicate returns truthy for desired rows, for example:
function predicate(y) {
    return this.getValue(1, y) === 'M'; // rows where second column is 'M'
}Calling without a predicate is the same as calling dataModel.clearIndex().
Note that the above example predicate would fail on a computed cell or column.
To properly handle such data, you can use DatasaurIndexed.valOrFunc instead of calling this.getValue:
function predicate(y) {
    return DatasaurIndexed.valOrFunc(this.getRow(y), 'gender', this.schema.gender.calculator)  === 'M'; // rows where second column is 'M'
}The event string definitions have the following defaults:
DatasaurIndexed.preindexEventString = 'fin-hypergrid-data-prereindex';
DatasaurIndexed.postindexEventString = 'fin-hypergrid-data-postreindex';For generalized single-column sorting, use datasaur-simple-sort, which sits on top of datasaur-indexed:
var Sorter = require('datasaur-simple-sort');
var dataModel = new Sorter(new Indexer(new Source));
dataModel.sort(0); // alpha ascending by first columnAs noted in datasaur-simple-sort's README, it fails on computed cells and columns.
Sorting by multiple columns, each of which may be ascending or descending, is somewhat more complicated,
essentially involving dynamically adding a Sorter stage for each column to be sorted.
See datasaur-filter which does something like that,
but forces Array.prototype.sort to do a stable sort
(which is is not naturally inclined to do), and properly handles computed cells and columns.
Note: As of this writing datasaur-filter has not yet been updated to v3.0.0.
Published as an npm module to npmjs.org to be npm installed:
npm install datasaur-indexedPublished as a Hypergrid Client Module to be loaded by the client with a <script> tag:
<script src="https://fin-hypergrid.github.io/datasaur-indexed/3.0.0/build/datasaur-indexed.js"></script>The above <script> tag loads the module into fin.Hypergrid.modules['datasaur-indexed'].
Once loaded it can be referenced from another Hypergrid client module with require(...):
var DatasaurIndexed = require('datasaur-indexed');Or from some other script with fin.Hypergrid.require(...):
var DatasaurIndexed = fin.Hypergrid.require('datasaur-indexed');