Skip to content

Release Notes: v3.0.0

Jonathan Eiten edited this page Mar 15, 2018 · 16 revisions
NOTICE
This document is still a
Work-in-Progress
as of 2/26/2018

ADVISORY for those upgrading directly from Hypergrid v2.0: Before reading the following Hypergrid 3.0 release notes, it is essential to review Release Notes: v2.1.0 from 13 Jan 2018, as well as the notes for 2.1.2 (30 Jan 2018), 2.1.3 (15 Feb 2018), and 2.1.4 (22 Feb 2018) on the repo's Releases page.

Contents

The main features of the 3.0.0 release are:

Data model

Hypergrid prior to v3 drove the data model: It instantiated the built-in data model, loaded it with data, updated its data, etc. In this approach, Hypergrid could make necessary rendering calls around the data model calls.

The new approach is to present to Hypergrid a fully realized data model that can be managed independently, driving Hypergrid where necessary through certain logical data events (such as data-changed or schema-changed), which Hypergrid responds to by making the necessary rendering calls.

This is not as complicated or as big a change as it sounds. There are only a handful of data events (so far). And Hypergrid still supports the old methods although their use is now discouraged.

Hypergrid always came with a built-in default behavior that controlled a built-in default data model. If an application needed an alternative data model, the intent was that the developer override the behavior. While easy enough to do if your fork the project, it was not at all easy to do at run-time.

This was improved somewhat with version 1.3.0 which introduced a Behavior option, so now (at least in theory) an application could supply its own behavior. In practice this is hard to do because the behavior interface was never formally defined. Furthermore, the built-in behavior is split across an abstract class (Behavior) and an implementing class (formerly JSON but renamed in v3 to Local) and it was not immediately clear that only the implementing class should be overridden. The boundary between the two classes is vague; the defining difference is not obvious: That the Local class "owns" the dataModel class which should not be referenced outside this class. (It doesn't help that there are a few important exceptions to this rule.)

To remedy this situation, we intend to publish the behavior interface. But before going there, we decided it would be more expedient for developers the continue to use the existing behavior and to publish instead the data model interface, which is where all the interesting action takes place. And with v3 we were able to strip it down to the bare essentials, making for a very light weight interface.

Along with the new data model interface (described below), we are also introducing two new options with v3: DataModel (constructor) and dataModel (instance) for overriding the data model at run-time. This second option, dataModel is a live instance, turns out to be the more interesting of the two. It can be defined and managed directly by the application even before (as well as after) being handed to Hypergrid.

Externalized data model

The Hypergrid data model object is now a fully externalized black box object. Although Hypergrid is still packaged with a default data model, ...

Hypergrid makes no assumptions about the data source's design or implementation details, just so long as it conforms to the interface as defined on the dataModelAPI doc page.

Formerly, grid.behavior.dataModel was an internal object that referenced an external object, grid.behavior.dataModel.dataSource. As of 3.0, there is no longer an internal data model object; grid.behavior.dataModel now references the external data model object directly.

To read the following table, refer to the table Legend below it. Column m3 summarizes the new data model interface requirements (as detailed on the dataModelAPI doc page) while the other columns compare grid, behavior, and dataModel API, version 2 vs. version 3:

Method gv2 gv3 bv2 bv3 mv2 mv3
apply O
click O
getCell O
getCellEditorAt O
getColumnCount O
getData D O
getMetadataStore O
getRowIndex O
getRow D D O
getRowCount R
getRowMetadata O
getSchema R
getValue R
isDrillDown O
setData O
setMetadataStore O
setRow O
setRowMetadata O
setSchema O
setValue O
schema (accessor)

Legend:

Symbol Meaning
g var g = new Hypergrid(options)
b var b = g.behavior
m var m = b.dataModel
This will be set to the default data model when not provided in options.dataModel.
v2 Hypergrid version 2
Note: mv2 refers to v2's internal dataModel object.
v3 Hypergrid version 3
Note: mv3 refers to the v3 data model API for the now-external dataModel object.
  method is undefined
method is defined
D method is deprecated as of 3.0.0 in favor of the data model version
Still works but issues a console warning that it will be removed in a future version.
R data model implementation required
O data model implementation optional
Fallback injected by Hypergrid if unimplemented.
Note that the fallback for setData is a no-op.

As indicated above (and outlined on the dataModelAPI page), a data model is an object with implementations of at least the getRowCount(), getSchema(), and getValue(x, y).

This change isn't as dramatic as it sounds and is largely backwards compatible with the old dataSource external object.

Comparison of old and new grid.behavior.dataModel object.

The data model can now be specified as options.dataModel, passed to the Hypergrid constructor, or subsequently to the behavior constructor via grid.setBehavior() or grid.behavior.setData().

Data model events

[Content needed.]

Properties

Property layering

Control of the order in which property layers are applied for cell rendering was added as the propClassLayers property in v2.1.0.

As a convenience feature, v3.0.0 merely adds a collection of layering configurations, propClassLayersMap. Use these predefined configurations to easily set the propClassLayers array:

grid.properties.propClassLayers = grid.properties.propClassLayersMap.DEFAULT;

Like propClassEnum, it is defined in the properties object merely as a means of making it universally available wherever props are available.

It comes with two predefined configurations (developer are free to add their own custom configurations):

Configuration Description
DEFAULT (grid properties) ← column properties ← row stripe properties ← row properties ← cell properties
NO_ROWS (grid properties) ← (column properties) ← cell properties

(Parentheses above indicate implicit properties collections that are part of the prototype chain of the non-parenthesized collection appearing to its right.)

Setting the propClassLayers array, besides affecting the appearance of the grid, can also significantly affect performance. Therefore, although row properties are on by default, if an application is not using them, better performance will be realized by eliminating them from the list with:

grid.properties.propClassLayers = grid.properties.propClassLayersMap.NO_ROWS;

Row & cell property storage

Row and cell properties are row-specific things that necessarily parallel the row data (as "row metadata" or simply "metadata"). The metadata can be stored in the data rows themselves or in a separate parallel data structure. Storing it with the data rows makes it especially convenient to persist the metadata along with the actual row data.

The default local data model stores metadata in a "hidden" column in the data rows.

As explained in the wiki page on this subject, Row and cell properties as metadata, if not implemented by the data model itself, Hypergrid injects default implementations for getRowMetadata(y, create) and setRowMetadata(y, newMetadata) into the data model which store the metadata in a separate array or hash, this.metadata.

The wiki page Row and cell properties as metadata has been updated to include these new interface additions.

Modules

Hypergrid keeps a list of module references in Hypergrid.modules, the source for both module hooks and modules loaded with Hypergrid.require().

Module hooks

Some members of Hypergrid.modules are "hooks," references to modules that can easily be overridden with alternatives (that implement the same interface, of course). When a piece of Hypergrid code needs access to one of these external modules, it references it through its hook in Hypergrid.modules rather than through require(). This way, if the hook is overridden, Hypergrid will use the override.

Hooks inlcude... [to be filled in later].

Module Loader

The Hypergrid Module Loader implementation (Hypergrid.require()) has been expanded somewhat.

See the Client Modules wiki for details.

To encourage the use of this built-in module loader, direct access to selected internal modules has been deprecated with a warning that it will be removed in v4.

NOTES:

  1. All of the requires below will work as is on the client side from within a Hypergrid Client Module or from within an unwrapped script by using fin.Hypergrid.require instead.
  2. Hypergrid.require does not expect require strings to end in /, .js, /index, or /index.js so please omit.

Accessing internal modules

Deprecated usage
(issues warning)
Favored usage
fin.Hypergrid.lib.module require('fin-hypergrid/src/lib/module')
fin.Hypergrid.features.module require('fin-hypergrid/src/features/module')
fin.Hypergrid.behaviors.module require('fin-hypergrid/src/behaviors/module')
fin.Hypergrid.dataModels.module require('fin-hypergrid/src/dataModels/module')
fin.Hypergrid.images require('fin-hypergrid/images')
fin.Hypergrid.Base require('fin-hypergrid/src/Base')

For completeness require('fin-hypergrid/src/defaults') also works although Hypergrid.defaults (synonym: Hypergrid.properties) remains the favored usage.

Accessing external modules

The following modules are all part of the build and can be accessed without loading them separately with <script> tags:

Deprecated usage Favored usage
window.datasaur.base
(throws error)
require('datasaur-base')
fin.Hypergrid.lib.DataSourceOrigin
(throws error)
require('datasaur-local')
fin.Hypergrid.lib.fields
(issues warning)
require('fin-hypergrid-field-tools')
fin.Hypergrid.rectangular
(issues warning)
require('rectangular')
(Not previously accessible) require('extend-me')
(Not previously accessible) require('scrollbar')
(a.k.a finbars)
(Not previously accessible) require('mustache')
(Not previously accessible) require('object-iterators')
(Not previously accessible) require('overrider')

Special note regarding the two "datasaur" modules. (This note pertains only to applications using the build file from the CDN.) Although the two "datasaur" modules are still in the build and the local data source is still used by default, this usage is deprecated as of 3.0.0 and a console warning will be issued. In a future version, they will be removed from the build and there will be no default data source. The fact that it still included in the 3.0.0 build and still used by default is purely a courtesy to help wean developers off of depending upon it. Developers should start getting used to this now by "bringing their own" data source. We have made this easy by wrapping them as Hypergrid Client Modules on the CDN. What this means is that the require (or Hypergrid.require as the case may be) syntax will continue to work, but the modules will need to be loaded explicitly with <script> tags.

New API members

version property

A new property version, containing the Hypergrid module version number from package.json, is now available to all instances of classes extended from Base.

addState method

Similar to setState except does not clear the state (i.e., grid properties) first.

Updated to use Object.assign() rather than a polyfill loop.

Also, moved createColumns() call from setState to clearState because columns carry state (i.e., column properties).

Themes

Moved all code dealing with themes from Hypergrid.js to a new file themes.js.

Theme Registry

[Content needed.]

New method: registerThemeCollection()

Registers a whole hash of themes all at once. Just a one liner with a loop.

Grid theme setter

[Content needed.]

Removing themes

[Content needed.]

Captured polymer themes

[Content needed.]

Also created a new repo and moved the unused buildTheme.js file to it. This file contains the buildTheme function which is verbatim from the original polymer version of Hypergrid (except renamed from buildPolymerTheme). It builds a Hypergrid theme object from a loaded Polymer Theme CSS stylesheet. It is still useful since you can utilize a Polymer Theme without having to be a Polymerized app.

Also included in the repo are:

  • The theme folder from the Polymer version containing the 16 Polymer Theme CSS stylesheet files.
  • A folder of 16 Hypergrid theme objects pre-built from the stylesheets.

To build a new theme object from a loaded and enabled Polymer Theme CSS stylesheet:

var Hypergrid = require('fin-hypergrid');
var buildTheme = require('fin-hypergrid-themes').buildTheme;
Hypergrid.registerTheme(buildTheme());

To register all the pre-built theme objects:

Hypergrid.registerThemeCollection(require('fin-hypergrid-themes'));

And to consume a registered theme:

Hypergrid.applyTheme('candy'); // apply the Candy theme as a "global theme" for grid instances
myGrid.applyTheme('dark-side'); // apply the Dark-Side them as a "local theme" overlaid on the global theme

See the README for details and some more examples.

Miscellaney

  • Added the missing (though non-essential) returns to setCellProperties and addCellProperties .
  • package.json
    • chai was erroneously being included as a dependency (!); it is now a dev-dependency. (No biggie since there were no references to it.)
    • Updated mustache to version 2.3 to avoid reported vulnerability (#638 ).
  • Moved and renamed Hypergrid.js The main file, previously ./src/Hypergrid.js is now in its own folder and has been renamed to ./src/Hypergrid/index.js. Several files required only by this one have also been moved into that folder (events.js, selections.js, themes.js).
  • Renamed build file entry point from index.js to build.js as this is more descriptive and it is never actually required anywhere.
  • Wrapped mix-in exports in a mixin property.
  • Added require('finbars') to Hypergrid.modules.scrollbar which is how Hypergrid now references it internally. This makes finbars overridable while at the same time accessible as an external module — albeit with a pseudonym — as `require('scrollbar').

Deprecated documents

Following 3.0.0-related documents discussed proposals for updating the data model and are now obsolete.

Clone this wiki locally