Skip to content

Commit

Permalink
Merge pull request #802 from fin-hypergrid/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
joneit authored May 3, 2019
2 parents 9d19656 + 1772951 commit a556956
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 49 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ It also highlights a DOM-based custom external editor triggered via hypergrid ev
* [Roadmap](#roadmap)
* [Contributing](#contributors)

### Current Release (3.2.0 - 17 November 2018)
### Current Release (3.2.1 - 2 May 2019)

> **CAUTION:** For those considering upgrading directly from v2, be advised Hypergrid v3 introduced a revised data model _with breaking changes._ The impact of these changes has been intentionally minimized and should not affect the vast majority of users. See the [v3.0.0 release notes](https://github.com/fin-hypergrid/core/releases/tag/v3.0.0) for more information.
Expand All @@ -25,7 +25,7 @@ _For a complete list of changes, see the [release notes](https://github.com/fin-

#### npm module _(recommended)_
Published as a CommonJS module to npmjs.org.
Specify a <a href="https://semver.org/">SEMVER</a> of `"fin-hypergrid": "3.2.0"` (or `"^3.2.0"`) in your package.json file,
Specify a <a href="https://semver.org/">SEMVER</a> of `"fin-hypergrid": "3.2.1"` (or `"^3.2.1"`) in your package.json file,
issue the `npm install` command, and let your bundler (<a target="webpack" href="https://webpack.js.org/">wepback</a>,
<a target="browserify" href="http://browserify.org/">Browserify</a>) create a single file containing both Hypergrid and your application.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fin-hypergrid",
"version": "3.2.0",
"version": "3.2.1",
"description": "Canvas-based high-performance grid",
"main": "src/Hypergrid",
"repository": {
Expand Down
18 changes: 12 additions & 6 deletions src/behaviors/Column.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,15 +383,21 @@ function resolveCalculator(calculator) {
var matches, key,
calculators = this.behavior.grid.properties.calculators || (this.behavior.grid.properties.calculators = {});

if (/^\w+$/.test(calculator)) {
key = calculator; // just a function name
if (/^\w+$/.test(calculator)) { // just a function name?
// use as registry key but make sure it is in fact a registered calculator
key = calculator;
if (!calculators[key]) {
throw new HypergridError('Unknown calculator name "' + key + forColumnName);
}
} else if ((matches = calculator.match(REGEX_NAMED_FUNC))) {
key = matches[1]; // function name extracted from stringified function
} else if (calculator.test(REGEX_ANON_FUNC)) {
key = calculator; // anonymous stringified function

} else if ((matches = calculator.match(REGEX_NAMED_FUNC))) { // named stringified function?
// extract function name from stringified function to use as registry key
key = matches[1];

} else if (REGEX_ANON_FUNC.test(calculator)) { // anonymous stringified function?
// use entire anonymous stringified function as registry key
key = calculator;

} else if (REGEX_ARROW_FUNC.test(calculator)) {
throw new HypergridError('Arrow function not permitted as column calculator ' + forColumnName);
}
Expand Down
9 changes: 5 additions & 4 deletions src/behaviors/Local/dispatchDataModelEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ var REGEX_DATA_EVENT_STRING = /^fin-hypergrid-(data|schema)(-[a-z]+)+$/;
* 3. Re-emits the event as a DOM event to the `<canvas>` element (unless the handler has already done so).
*
* The data model's `dispatchEvent` method is bound to the grid by {@link module:decorators.injectCode injectCode}.
* A curried version of this function, bound to the grid instance, is either:
* A bound version of this function, bound to the grid instance, is either:
* * Added to the data model via its `addListener` method, if it has one; or
* * Force-injected into the data model, overriding any native implementation. (A native implementation may exist simply to "catch" calls that might be made before the data model is attached to Hypergrid.)
*
* @this {Hypergrid}
* @param {string|NormalizedDataModelEvent} event
* @memberOf module:decorators~
*/
module.exports = function(event) {
function dispatchDataModelEvent(event) {
var type;

switch (typeof event) {
Expand Down Expand Up @@ -55,4 +54,6 @@ module.exports = function(event) {
}

return dispatched !== undefined ? dispatched : dispatchGridEvent.call(this, event.type, event);
};
}

module.exports = dispatchDataModelEvent;
57 changes: 23 additions & 34 deletions src/behaviors/Local/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,36 @@

/**
* @namespace dataModelEventHandlers
* @desc These handlers are called by {@link module:decorators.dispatchDataModelEvent dataModel.dispatchEvent}.
* @desc These handlers are called by {@link dispatchDataModelEvent dataModel.dispatchEvent} to perform Hypergrid housekeeping tasks.
*
* (Hypergrid registers itself with the data model by calling `dataModel.addListener`. Both `addListener` and `dispatchEvent` are optional API. If the data model lacks `addListener`, Hypergrid inserts a bound version of `dispatchEvent` directly into the data model.)
*
* They perform some Hypergrid housekeeping chores before (and possibly after) optionally re-emiting the event as a standard
* Hypergrid event (to the `<canvas>` element).
* #### Coding pattern
* If there are no housekeeping tasks to be performed, do not define a handler here.
*
* All the built-in data model events re-emit their events (all non-cancelable).
* Otherwise, the typical coding pattern is for our handler to perform the housekeeping tasks, returning `undefined` to the caller ({@link DispatchDataModelEvent}) which then re-emits the event as a Hypergrid event (_i.e.,_ as a DOM event to the `<canvas>` element).
*
* #### Coding patterns
* These handlers should return a boolean if they re-emit the event as a grid event themselves, when they have chores to perform post-re-emission. If they don't, they should return `undefined` which signals the caller (`dataModel.dispatchEvent`) to re-emit it as a grid event as a final step for the handler.
* Alternatively, our handler can re-emit the event itself by calling the grid event handler and propagating its boolean return value value to the caller which signals the caller _not_ to re-emit on our behalf. This is useful when tasks need to be performed _after_ the Hypergrid event handler is called (or before _and_ after).
*
* Given the above, there are four typical coding patterns for these handlers:
* 1. Perform chores with no event re-emission:
* ```
* Chores();
* return true; // (or any defined value) signals caller not to re-emit the event
* ```
* 2. First perform chores; then re-emit the event as a grid event:
* ```
* Chores();
* return undefined; // (or omit) signals caller to re-emit the event for us
* ```
* 3. First perform some pre-re-emit chores (optional); then re-emit the event as a _non-cancelable_ grid event; then perform remaining chores:
* ```
* optionalPreReemitChores();
* var dispatchGridEvent = require('../../lib/dispatchGridEvent.js');
* dispatchGridEvent.call(this, event.type, event); // non-cancelable
* remainingChores();
* return true; // signals caller that we've already re-emitted the event and it was not canceled
* ```
* 3. First perform some pre-re-emit chores (optional); then re-emit the event as a _cancelable_ grid event; then perform remaining chores conditionally [iff](https://en.wikipedia.org/wiki/If_and_only_if) not canceled (_important:_ note the `true` in the following):
* ```
* optionalPreReemitChores();
* if (dispatchGridEvent.call(this, event.type, true, event)) { // `true` here means cancelable
* conditionalChores();
* return true; // signals caller that we've already re-emitted the event (which was not canceled)
* } else {
* return false; // signals caller that we've already re-emitted the event (which was canceled)
* The pattern, in general:
* ```js
* exports['fin-hypergrid-data-myevent'] = function(event) {
* var notCanceled;
*
* PerformHousekeepingTasks();
*
* // optionally re-emit the event as a grid event
* var dispatchGridEvent = require('../../lib/dispatchGridEvent.js');
* notCanceled = dispatchGridEvent.call(this, event.type, isCancelable, event);
*
* if (!notCanceled) {
* PerformAdditionalHousekeepingTasks()
* }
*
* return notCanceled;
* }
* ```
* Re-emitting the event is optional; if `notCanceled` is never defined, the caller will take care of it. If your handler does choose to re-emit the event itself by calling `dispatchGridEvent`, you should propagate its return value (the result of its internal call to [`dispatchEvent`](https://developer.mozilla.org/docs/Web/API/EventTarget/dispatchEvent), which is either `false` if the event was canceled or `true` if it was not).
*
*/
module.exports = {
/**
Expand Down
2 changes: 0 additions & 2 deletions src/behaviors/Local/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ var Local = Behavior.extend('Local', {
this.dataModel.setSchema(newSchema);
},

dataModelEventHandlers: require('./events').dataModelEventHandlers, // for adding additional event handlers

createColumns: function() {
this.super.createColumns.call(this, createColumns);
},
Expand Down

0 comments on commit a556956

Please sign in to comment.