Skip to content

Release Notes: v3.0.0

Jonathan Eiten edited this page Apr 16, 2018 · 16 revisions

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 on the Releases page for the 2.1 patches:

  • 2.1.2 (30 Jan 2018)
  • 2.1.3 (15 Feb 2018)
  • 2.1.4 (22 Feb 2018)
  • 2.1.5 (6 Mar 2018)
  • 2.1.6 (16 Mar 2018)
  • 2.1.7 (13 Apr 2018)

Contents

The main features of the 3.0.0 release are:

Data model

TL;DR

  • grid.behavior.dataModel is no longer a built-in object; this property now references the external data model directly (previously referenced through grid.behavior.dataModel.dataSource, now deprecated).
  • The default data model can now be overridden at run-time with an instantiation option.
  • The external data model interface spec has been published as Data Model API. The interface has been stripped down to three essential methods: getSchema, getRowCount, and getValue.

The current code base assumes a data model API accessible through grid.behavior.dataModel that conforms to a certain minimum interface.

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, independently managed data model, that can drive Hypergrid (rather than the other way around) by dispatching data events (such as fin-hypergrid-data-changed or fin-hypergrid-schema-changed), which Hypergrid responds to by making the necessary internal calls.

Behaviors and data model adapters

Each instantiated hypergrid object has an instance of a behavior object which in turn has an instance of a data model adapter object that wraps an external data model.

Beginning with version 1.3.0, Hypergrid offered a Behavior constructor option to override the default behavior. The idea was, because the behavior instantiated the data model adapter and hosted the reference to it, replacing the behavior would let developers replace the data model. At least in theory. As it turned out, overriding the behavior was of little use. Although the behavior owned the data model reference, it did not have an exclusive on data model access; references to behavior.dataModel appear throughout the code base, not just in the default behavior.

The data model adapter concept is a good one, letting Hypergrid work with any kind of data model. However, with no easy way to override the default data model adapter without forking Hypergrid, the concept was rarely taken advantage of. There was also no published data model interface specification, a non-starter for most developers.

Implementing a custom data model

Version 3 addresses both the above problems as its primary design goals. It makes it easy to override the data model at run-time. With version 3 we are publishing (for the first time) a formal data model interface spec.

Overriding the default data model

Version 3 introduces a DataModel constructor option as well as a dataModel (small "d") instance option, either of which developers can use to override the default data model at run-time. This second option, options.dataModel (small "d") is probably the more useful of the two. It can be defined and managed directly by the application even before (as well as after) being handed to new Hypergrid(options). Developers will continue to use the Local behavior (or a descendant of Local) while supplying a custom data model through one of these new instantiation options.

But notice we have dropped the term data model adapter here for data model. Version 3 eliminates the adapter layer entirely. Formerly, grid.behavior.dataModel was an internal object that referenced an external object, grid.behavior.dataModel.dataSource and made certain assumptions about the structure and behavior of that external object.

As of 3.0, there is no longer an internal data model object. Hypergrid's existing calls to methods of grid.behavior.dataModel, which previously called the data model adapter, now call the external data model directly.

While an adapter is a useful concept, having this extra layer of indirection as a permanent and necessary part of the Hypergrid design is unnecessary. Applications with alien data model interfaces will wrap them in their own custom adapters before handing them to Hypergrid (which is very likely how developers have been solving this problem up to now anyway).

This "external" data model will actually be either the included default data model or an alternative supplied by the application using one of the options above. In any case, Hypergrid no loner makes any assumptions about the data model's internal design or implementation details, now seeing it as a black box object that conforms to the interface.

Data model interface spec

We have stripped the data model down to its bare minimum, making for a very light-weight interface.

The v3 external data model is an object that implements at least the three required methods getRowCount(), getSchema(), and getValue(x, y).

For the v3 data model interface specification, please see:

Data model events

Please see the Events section of the API doc for a list of data model events.

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