fin-hypergrid
Advanced tools
Comparing version 2.1.15 to 3.0.0
{ | ||
"name": "fin-hypergrid", | ||
"version": "2.1.15", | ||
"version": "3.0.0", | ||
"description": "Canvas-based high-performance grid", | ||
"main": "src/Hypergrid", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/openfin/fin-hypergrid.git" | ||
"url": "git://github.com/fin-hypergrid/core.git" | ||
}, | ||
@@ -18,5 +19,5 @@ "author": "SWirts, JEiten, DJones, NMichaud", | ||
"dependencies": { | ||
"datasaur-base": "^3.0.0", | ||
"datasaur-local": "^3.0.0", | ||
"extend-me": "^2.7.0", | ||
"fin-hypergrid-data-source-base": "^0.4.10", | ||
"fin-hypergrid-event-logger": "^1.0.3", | ||
"finbars": "^1.6.0", | ||
@@ -32,30 +33,13 @@ "inject-stylesheet-template": "^1.0.1", | ||
"devDependencies": { | ||
"browser-sync": "^2.10.0", | ||
"browserify": "^15.1.0", | ||
"chai": "^3.5.0", | ||
"css-injector": "^1.1.0", | ||
"gulp": "^3.9.0", | ||
"gulp-concat": "^2.6.0", | ||
"gulp-each": "^0.1.1", | ||
"gulp-eslint": "^4.0.0", | ||
"gulp-exclude-gitignore": "^1.0.0", | ||
"gulp-footer": "^1.0.5", | ||
"gulp-eslint": "^4.0.2", | ||
"gulp-footer": "^1.1.1", | ||
"gulp-header": "^1.8.2", | ||
"gulp-imagine-64": "^1.0.1", | ||
"gulp-load-plugins": "^1.1.0", | ||
"gulp-mirror": "^0.4.0", | ||
"gulp-mocha": "^6.0.0", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-replace": "^0.5.4", | ||
"gulp-uglify": "^3.0.0", | ||
"gulp-util": "^3.0.7", | ||
"gutil": "^1.6.4", | ||
"header": "^0.1.1", | ||
"multipipe": "^0.2.1", | ||
"multiple": "^0.2.1", | ||
"run-sequence": "^1.1.4", | ||
"through2": "^2.0.0", | ||
"vinyl-buffer": "^1.0.1", | ||
"vinyl-source-stream": "^2.0.0" | ||
"run-sequence": "^1.1.4" | ||
} | ||
} |
@@ -11,3 +11,4 @@ [![Build Status](https://travis-ci.org/openfin/fin-hypergrid.svg?branch=develop)](https://travis-ci.org/openfin/fin-hypergrid) | ||
## Table of Contents | ||
* [Current Release](#current-release-2115---29-june-2018) | ||
* [Current Release](#current-release-300---7-july-2018) | ||
* [Distribution](#distribution) | ||
* [Demos](#demos) | ||
@@ -20,20 +21,42 @@ * [Features](#features) | ||
### Current Release (2.1.15 - 29 June 2018) | ||
### Current Release (3.0.0 - 7 July 2018) | ||
**Hypergrid 2.1.15** includes bug fixes and new features. | ||
**Hypergrid 3.0.0 includes a revised data model with some breaking changes.** | ||
_For a complete list of changes, see the [release notes](https://github.com/fin-hypergrid/core/releases)._ | ||
### Demos | ||
### Distribution | ||
##### Sample demo | ||
#### npm module | ||
Published as a CommonJS module to npmjs.org. Specify SEMVER `"fin-hypergrid": "3.0.0"` (or `"^3.0.0"`) in your package.json file, issue the `npm install` command, and let your bundler (wepback, Browserify) do the rest. | ||
Our [dev testbed](https://fin-hypergrid.github.io/core) demos various features. | ||
#### Build file | ||
Published as a pre-bundled build file, which contains a JavaScript [IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression) that creates (as needed) the global namespace `window.fin` and populates `window.fin.Hypergrid`. See the [CDN index](https://fin-hypergrid.github.io#index) for links. | ||
### Hypergrid demos | ||
The [`fin-hypergrid/build`](https://github.com/fin-hypergrid/build) repo imports (via `require`) Hypergrid to generate the build files. It also hosts the demo source files that test and show off various Hypergrid features. Some of these use the npm module while others use the build file. Working versions of all demos are published to the CDN ([list of links](https://fin-hypergrid.github.io#demos)). | ||
#### Testbench | ||
The [default](https://fin-hypergrid.github.io/core) demo is the Hypergrid [dev testbench](https://fin-hypergrid.github.io/core/demo/index.html) ([source](https://github.com/fin-hypergrid/build/tree/master/testbench)). | ||
#### Simple example | ||
See `example.html` for a very simple example ([repo](https://github.com/fin-hypergrid/build/blob/master/demo/example.html), [demo](https://fin-hypergrid.github.io/core/demo/example.html)): | ||
![](images/README/simple.png) | ||
#### Who else is using Hypergrid? | ||
##### Perspective | ||
The [Perspective](https://github.com/jpmorganchase/perspective) open source project uses Hypergrid v3 (demo links in the README) and does a lot more than Hypergrid alone, such as table pivots and charting. | ||
![](images/README/perspective.png) | ||
##### Hyperblotter | ||
Hyperblotter is a demo app that shows the capabilities of both OpenFin and Hypergrid. | ||
[Openfin](http://openfin.co)'s Hyperblotter ([installer](https://dl.openfin.co/services/download?fileName=Hyperblotter&config=http://cdn.openfin.co/demos/hyperblotter/app.json)) is a demo app that shows the capabilities of both OpenFin and Hypergrid. | ||
Check out the Table view on Hyperblotter on a Windows machine via [this installer](https://dl.openfin.co/services/download?fileName=Hyperblotter&config=http://cdn.openfin.co/demos/hyperblotter/app.json). | ||
![](images/README/Hyperblotter%20Tabled%20Reduced%20Rows.png) | ||
@@ -40,0 +63,0 @@ |
@@ -8,5 +8,7 @@ 'use strict'; | ||
var cellEventFactory = require('../lib/cellEventFactory'); | ||
var fields = require('../lib/fields'); | ||
var featureRegistry = require('../features'); | ||
var Synonomous = require('synonomous'); | ||
var assignOrDelete = require('../lib/misc').assignOrDelete; | ||
var ArrayDecorator = require('synonomous'); | ||
var assignOrDelete = require('../lib/assignOrDelete'); | ||
var dispatchGridEvent = require('../lib/dispatchGridEvent'); | ||
@@ -26,16 +28,22 @@ | ||
/** | ||
* @mixes cellProperties.behaviorMixin | ||
* @mixes rowProperties.mixin | ||
* @mixes subgrids.mixin | ||
* @mixes dataModel.mixin | ||
* @constructor | ||
* @desc A controller for the data model. | ||
* > This constructor (actually `initialize`) will be called upon instantiation of this class or of any class that extends from this class. See {@link https://github.com/joneit/extend-me|extend-me} for more info. | ||
* @param {Hypergrid} grid | ||
* @param {object} [options] - _(Passed to {@link Behavior#reset reset})._ | ||
* @param {DataModel} [options.dataModel] - _Per {@link Behavior#reset reset}._ | ||
* @param {object} [options.metadata] - _Per {@link Behavior#reset reset}._ | ||
* @param {function} [options.DataModel=require('datasaur-local')] - _Per {@link Behavior#reset reset}._ | ||
* @param {function|object[]} [options.data] - _Per {@link Behavior#setData setData}._ | ||
* @param {function|menuItem[]} [options.schema] - _Per {@link Behavior#setData setData}._ | ||
* @param {subgridSpec[]} [options.subgrids=this.grid.properties.subgrids] - _Per {@link Behavior#setData setData}._ | ||
* @param {boolean} [options.apply=true] - _Per {@link Behavior#setData setData}._ | ||
* @abstract | ||
* @desc A sort of "model++." It contains all code/data that's necessary for easily implementing a virtual data source and its manipulation/analytics. | ||
* | ||
*/ | ||
var Behavior = Base.extend('Behavior', { | ||
/** | ||
* @desc this is the callback for the plugin pattern of nested tags | ||
* @param {Hypergrid} grid | ||
* @param {object} [options] - _(See {@link behaviors.JSON#setData} for additional options.)_ | ||
* @param {DataModels[]} [options.subgrids] | ||
* @memberOf Behavior# | ||
*/ | ||
initialize: function(grid, options) { | ||
@@ -48,4 +56,2 @@ /** | ||
this.synonomous = new Synonomous; | ||
this.initializeFeatureChain(); | ||
@@ -111,26 +117,12 @@ | ||
/** | ||
* @param {object} [options] | ||
* @param {object} [options.pipeline] - Consumed by {@link dataModels.JSON#reset}. | ||
* | ||
* If omitted, previously established pipeline is reused. | ||
* @param {object} [options.controllers] - Consumed by {@link dataModels.JSON#reset}. | ||
* | ||
* If omitted, previously established controllers list is reused. | ||
* Reset the behavior. | ||
* @param {object} [options] - _Same as constructor's `options`._<br> | ||
* _Passed to {@link Behavior#resetDataModel resetDataModel} and {@link Behavior#setData setData} (both of which see)._ | ||
* @memberOf Behavior# | ||
*/ | ||
reset: function(options) { | ||
if (this.dataModel) { | ||
options = options || {}; | ||
this.dataModel.reset({ | ||
pipeline: options.pipeline, | ||
controllers: options.controllers | ||
}); | ||
} else { | ||
/** | ||
* @type {dataModelAPI} | ||
* @memberOf Behavior# | ||
*/ | ||
this.dataModel = this.getNewDataModel(options); | ||
var dataModelChanged = this.resetDataModel(options); | ||
// recreate `CellEvent` class so it can set up its internal `grid`, `behavior`, and `dataModel` convenience properties | ||
if (dataModelChanged) { | ||
// recreate `CellEvent` class so it can update its cached `grid`, `behavior`, and `dataModel` properties | ||
this.CellEvent = cellEventFactory(this.grid); | ||
@@ -152,5 +144,88 @@ } | ||
*/ | ||
this.subgrids = options.subgrids || this.subgrids || this.grid.properties.subgrids; | ||
this.subgrids = options && options.subgrids || | ||
!dataModelChanged && this.subgrids || | ||
this.grid.properties.subgrids; | ||
this.setData(options); | ||
}, | ||
/** | ||
* @memberOf Local# | ||
* @description Set the header labels. | ||
* @param {string[]|object} headers - The header labels. One of: | ||
* * _If an array:_ Must contain all headers in column order. | ||
* * _If a hash:_ May contain any headers, keyed by field name, in any order. | ||
*/ | ||
setHeaders: function(headers) { | ||
if (headers instanceof Array) { | ||
// Reset all headers | ||
var allColumns = this.allColumns; | ||
headers.forEach(function(header, index) { | ||
allColumns[index].header = header; // setter updates header in both column and data source objects | ||
}); | ||
} else if (typeof headers === 'object') { | ||
// Adjust just the headers in the hash | ||
this.allColumns.forEach(function(column) { | ||
if (headers[column.name]) { | ||
column.header = headers[column.name]; | ||
} | ||
}); | ||
} | ||
}, | ||
/** | ||
* @summary Set grid data. | ||
* @desc Fails silently if `dataRows` and `options.data` are both undefined. | ||
* | ||
* @param {function|object[]} [dataRows=options.data] - Array of uniform data row objects or function returning same. | ||
* | ||
* @param {object} [options] - _(Promoted to first argument position when `dataRows` omitted.)_ | ||
* | ||
* @param {function|object[]} [options.data] - The data when `dataRows` undefined. | ||
* | ||
* @param {function|menuItem[]} [options.schema] - May be: | ||
* * A schema array | ||
* * A function returning same. Called at filter reset time with behavior as context. | ||
* * Omit to allow the data model to generate a basic schema from its data. | ||
* | ||
* @param {boolean} [options.apply=true] Apply data transformations to the new data. | ||
* | ||
* @memberOf Behavior# | ||
*/ | ||
setData: function(dataRows, options) { | ||
if (!(Array.isArray(dataRows) || typeof dataRows === 'function')) { | ||
options = dataRows; | ||
dataRows = options && options.data; | ||
} | ||
dataRows = this.unwrap(dataRows); | ||
if (dataRows === undefined) { | ||
return; | ||
} | ||
if (!Array.isArray(dataRows)) { | ||
throw 'Expected data to be an array (of data row objects).'; | ||
} | ||
options = options || {}; | ||
var schema = this.unwrap(options.schema); | ||
// Inform interested data models of data. | ||
this.subgrids.forEach(function(dataModel) { | ||
dataModel.setData(dataRows, schema); | ||
}); | ||
if (this.grid.cellEditor) { | ||
this.grid.cellEditor.cancelEditing(); | ||
} | ||
if (options.apply || options.apply === undefined) { // default is `true` | ||
this.reindex(); | ||
} | ||
this.grid.allowEvents(this.getRowCount()); | ||
}, | ||
get renderedColumnCount() { | ||
@@ -169,3 +244,3 @@ return this.grid.renderer.visibleColumns.length; | ||
clearColumns: function() { | ||
var schema = this.dataModel.schema, | ||
var schema = this.schema, | ||
tc = this.treeColumnIndex, | ||
@@ -176,8 +251,8 @@ rc = this.rowColumnIndex; | ||
schema[tc].index = tc; | ||
if (schema[tc].name === undefined) { schema[tc].name = 'Tree'; } | ||
if (schema[tc].header === undefined) { schema[tc].header = 'Tree'; } | ||
if (schema[tc].name === undefined) { schema[tc].name = this.treeColumnNameDefault; } | ||
if (schema[tc].header === undefined) { schema[tc].header = this.treeColumnHeaderDefault; } | ||
schema[rc] = schema[rc] || {}; | ||
schema[rc].index = rc; | ||
if (schema[rc].name === undefined) { schema[rc].name = 'RowHeader'; } | ||
if (schema[rc].name === undefined) { schema[rc].name = this.rowColumnNameDefault; } | ||
if (schema[rc].header === undefined) { schema[rc].header = ''; } | ||
@@ -189,3 +264,3 @@ | ||
*/ | ||
this.columns = []; | ||
this.columns = this.grid.decorateColumnArray(); | ||
@@ -196,3 +271,3 @@ /** | ||
*/ | ||
this.allColumns = []; | ||
this.allColumns = this.grid.decorateColumnArray(); | ||
@@ -225,15 +300,2 @@ this.allColumns[tc] = this.columns[tc] = this.newColumn(schema[tc]); | ||
getVisibleColumn: function() { | ||
return this.deprecated('getVisibleColumn(x)', 'getActiveColumn(x)', '1.0.6', arguments); | ||
}, | ||
getVisibleColumnName: function() { | ||
return this.deprecated('getVisibleColumnName(x)', 'getActiveColumn(x).name', '1.0.6', arguments); | ||
}, | ||
getColumnId: function() { | ||
return this.deprecated('getColumnId(x)', 'getActiveColumn(x).header', '1.0.6', arguments); | ||
}, | ||
getHeader: function() { | ||
return this.deprecated('getHeader(x)', 'getActiveColumn(x).header', '1.0.6', arguments); | ||
}, | ||
getColumn: function(x) { | ||
@@ -249,10 +311,10 @@ return this.allColumns[x]; | ||
var column = this.newColumn(options), | ||
columns = this.columns, | ||
allColumns = this.allColumns; | ||
arrayDecorator = new ArrayDecorator, | ||
synonyms = arrayDecorator.getSynonyms(column.name); | ||
columns.push(column); | ||
this.synonomous.decorateList(columns.length - 1, columns); | ||
this.columns.push(column); | ||
arrayDecorator.decorateObject(this.columns, synonyms, column); | ||
allColumns.push(column); | ||
this.synonomous.decorateList(allColumns.length - 1, allColumns); | ||
this.allColumns.push(column); | ||
arrayDecorator.decorateObject(this.allColumns, synonyms, column); | ||
@@ -262,9 +324,28 @@ return column; | ||
createColumns: function() { | ||
createColumns: function(realImplementation) { | ||
var schema = this.dataModel.getSchema(); | ||
fields.normalizeSchema(schema); | ||
fields.decorateSchema(schema); | ||
fields.decorateColumnSchema(schema, this.grid.properties.headerify); | ||
this.createDataRowProxy(); | ||
this.clearColumns(); | ||
//concrete implementation here | ||
if (realImplementation) { | ||
realImplementation.call(this); | ||
} | ||
this.changed(); | ||
dispatchGridEvent.call(this.grid, 'fin-hypergrid-columns-created'); | ||
}, | ||
createDataRowProxy: function() { | ||
// concrete implementation here if behavior doesn't implement its own getRow() | ||
}, | ||
getColumnWidth: function(x) { | ||
var column = this.getActiveColumn(x); | ||
var column = (x !== this.treeColumnIndex || this.hasTreeColumn()) && this.getActiveColumn(x); | ||
return column ? column.getWidth() : 0; | ||
@@ -284,9 +365,2 @@ }, | ||
getCellProvider: function(name) { | ||
return this.deprecated('getCellProvider()', 'grid.cellRenderers', '1.0.6', arguments); | ||
}, | ||
createCellProvider: function(name) { | ||
console.error('getCellProvider() is deprecated as of v1.0.6. No replacement; do not call. Previously called by `Behavior` constructor; `new CellRenderers()` is now called by `Hypergrid` constructor instead.', arguments); | ||
}, | ||
/** | ||
@@ -297,3 +371,2 @@ * @memberOf Behavior# | ||
this.dataModel.reindex(); | ||
this.shapeChanged(); | ||
}, | ||
@@ -324,11 +397,2 @@ | ||
/** | ||
* @memberOf Behavior# | ||
* @desc getter for a [Memento](http://c2.com/cgi/wiki?MementoPattern) Object | ||
* @returns {object} | ||
*/ | ||
getPrivateState: function() { | ||
return this.deprecated('getPrivateState()', 'grid.properties', '1.2.0'); | ||
}, | ||
//this is effectively a clone, with certain things removed.... | ||
@@ -411,5 +475,6 @@ getState: function() { | ||
var columns = this.columns, | ||
allColumns = this.allColumns; | ||
allColumns = this.allColumns, | ||
arrayDecorator = new ArrayDecorator; | ||
// avoid recreating the array to keep refs valid; just empty it (including name dictionary) | ||
// avoid recreating the `columns` array object to keep refs valid; just empty it | ||
columns.length = 0; | ||
@@ -431,3 +496,3 @@ var tc = this.treeColumnIndex.toString(), rc = this.rowColumnIndex.toString(); | ||
this.synonomous.decorateList(columns); | ||
arrayDecorator.decorateArray(columns); | ||
} | ||
@@ -443,6 +508,2 @@ }, | ||
_setColumnOrder: function(columnIndexes) { | ||
this.deprecated('_setColumnOrder(columnIndexes)', 'setColumnOrder(columnIndexes)', '1.2.10', arguments); | ||
}, | ||
/** | ||
@@ -504,6 +565,4 @@ * @memberOf Behavior# | ||
var newColumns = columnIndexes | ||
// Look up columns using provided indexes | ||
.map(function(index) { return sourceColumnList[index]; }) | ||
// Remove any undefined columns | ||
.filter(function(column) { return column; }); | ||
.map(function(index) { return sourceColumnList[index]; }) // Look up columns using provided indexes | ||
.filter(function(column) { return column; }); // Remove any undefined columns | ||
@@ -567,25 +626,2 @@ // Default insertion point is end (i.e., before (last+1)th element) | ||
/** | ||
* @memberOf Behavior# | ||
* @desc A specific cell was clicked; you've been notified. | ||
* @param {Object} event - all event information | ||
* @return {boolean} Clicked in a drill-down column. | ||
*/ | ||
cellClicked: function(event) { | ||
if (arguments.length === 2) { | ||
return this.deprecated('cellClicked(cell, event)', 'cellClicked(event)', '1.2.0', arguments); | ||
} | ||
return this.dataModel.cellClicked(event); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc A specific cell was le double-clicked; you've been notified. | ||
* @param {Point} cell - point of cell coordinates | ||
* @param {Object} event - all event information | ||
*/ | ||
cellDoubleClicked: function(cell, event) { | ||
}, | ||
lookupFeature: function(key) { | ||
@@ -596,200 +632,3 @@ return this.featureMap[key]; | ||
/** | ||
* @param {CellEvent|number} xOrCellEvent - Grid column coordinate. | ||
* @param {number} [y] - Grid row coordinate. Omit if `xOrCellEvent` is a CellEvent. | ||
* @param {dataModelAPI} [dataModel] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. If given, x and y are interpreted as data cell coordinates (unadjusted for scrolling). Does not default to the data subgrid, although you can provide it explicitly (`this.subgrids.lookup.data`). | ||
* @memberOf Behavior# | ||
*/ | ||
getValue: function(xOrCellEvent, y, dataModel) { | ||
if (typeof xOrCellEvent !== 'object') { | ||
var x = xOrCellEvent; | ||
xOrCellEvent = new this.CellEvent; | ||
if (dataModel) { | ||
xOrCellEvent.resetDataXY(x, y, dataModel); | ||
} else { | ||
xOrCellEvent.resetGridCY(x, y); | ||
} | ||
} | ||
return xOrCellEvent.value; | ||
}, | ||
/** | ||
* @summary Gets the number of rows in the data subgrid. | ||
* @memberOf Behavior.prototype | ||
*/ | ||
getRowCount: function() { | ||
return this.dataModel.getRowCount(); | ||
}, | ||
getUnfilteredValue: function(x, y) { | ||
return this.deprecated('getUnfilteredValue()', '', '1.4.0', arguments, 'No longer supported'); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc update the data at point x, y with value | ||
* @return The data. | ||
* @param {CellEvent|number} xOrCellEvent - Grid column coordinate. | ||
* @param {number} [y] - Grid row coordinate. Omit if `xOrCellEvent` is a CellEvent. | ||
* @param {Object} value - The value to use. _When `y` omitted, promoted to 2nd arg._ | ||
* @param {dataModelAPI} [dataModel] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. If given, x and y are interpreted as data cell coordinates (unadjusted for scrolling). Does not default to the data subgrid, although you can provide it explicitly (`this.subgrids.lookup.data`). | ||
* @return {boolean} Consumed. | ||
*/ | ||
setValue: function(xOrCellEvent, y, value, dataModel) { | ||
if (typeof xOrCellEvent === 'object') { | ||
value = y; | ||
} else { | ||
var x = xOrCellEvent; | ||
xOrCellEvent = new this.CellEvent; | ||
if (dataModel) { | ||
xOrCellEvent.resetDataXY(x, y, dataModel); | ||
} else { | ||
xOrCellEvent.resetGridCY(x, y); | ||
} | ||
} | ||
xOrCellEvent.value = value; | ||
}, | ||
getDataValue: function(x, y) { | ||
return this.deprecated('getDataValue(x, y)', 'dataModel.getValue(x, y)', '1.1.0', arguments); | ||
}, | ||
setDataValue: function(x, y, value) { | ||
return this.deprecated('setDataValue(x, y, value)', 'dataModel.setValue(x, y, value)', '1.1.0', arguments); | ||
}, | ||
/** | ||
* @summary Get the cell's own properties object. | ||
* @desc May be undefined because cells only have their own properties object when at lest one own property has been set. | ||
* @param {CellEvent|number} xOrCellEvent - Data x coordinate. | ||
* @param {number} [y] - Grid row coordinate. _Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
* @returns {undefined|object} The "own" properties of the cell at x,y in the grid. If the cell does not own a properties object, returns `undefined`. | ||
* @memberOf Behavior# | ||
*/ | ||
getCellOwnProperties: function(xOrCellEvent, y, dataModel) { | ||
switch (arguments.length) { | ||
case 1: // xOrCellEvent is cellEvent | ||
return xOrCellEvent.column.getCellOwnProperties(xOrCellEvent.dataCell.y, xOrCellEvent.subgrid); | ||
case 2: case 3: // xOrCellEvent is x | ||
return this.getColumn(xOrCellEvent).getCellOwnProperties(y, dataModel); | ||
} | ||
}, | ||
/** | ||
* @summary Get the properties object for cell. | ||
* @desc This is the cell's own properties object if found else the column object. | ||
* | ||
* If you are seeking a single specific property, consider calling {@link Behavior#getCellProperty} instead. | ||
* @param {CellEvent|number} xOrCellEvent - Data x coordinate. | ||
* @param {number} [y] - Grid row coordinate. _Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
* @return {object} The properties of the cell at x,y in the grid. | ||
* @memberOf Behavior# | ||
*/ | ||
getCellProperties: function(xOrCellEvent, y, dataModel) { | ||
switch (arguments.length) { | ||
case 1: // xOrCellEvent is cellEvent | ||
return xOrCellEvent.properties; | ||
case 2: case 3: // xOrCellEvent is x | ||
return this.getColumn(xOrCellEvent).getCellProperties(y, dataModel); | ||
} | ||
}, | ||
/** | ||
* @summary Return a specific cell property. | ||
* @desc If there is no cell properties object, defers to column properties object. | ||
* @param {CellEvent|number} xOrCellEvent - Data x coordinate. | ||
* @param {number} [y] - Grid row coordinate._ Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {string} key - Name of property to get. _When `y` omitted, this param promoted to 2nd arg._ | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
* @return {object} The specified property for the cell at x,y in the grid. | ||
* @memberOf Behavior# | ||
*/ | ||
getCellProperty: function(xOrCellEvent, y, key, dataModel) { | ||
if (typeof xOrCellEvent === 'object') { | ||
key = y; | ||
return xOrCellEvent.properties[key]; | ||
} else { | ||
return this.getColumn(xOrCellEvent).getCellProperty(y, key, dataModel); | ||
} | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc update the data at point x, y with value | ||
* @param {CellEvent|number} xOrCellEvent - Data x coordinate. | ||
* @param {number} [y] - Grid row coordinate. _Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {Object} properties - Hash of cell properties. _When `y` omitted, this param promoted to 2nd arg._ | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
*/ | ||
setCellProperties: function(xOrCellEvent, y, properties, dataModel) { | ||
if (typeof xOrCellEvent === 'object') { | ||
properties = y; | ||
return xOrCellEvent.column.setCellProperties(xOrCellEvent.dataCell.y, properties, xOrCellEvent.subgrid); | ||
} else { | ||
return this.getColumn(xOrCellEvent).setCellProperties(y, properties, dataModel); | ||
} | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc update the data at point x, y with value | ||
* @param {CellEvent|number} xOrCellEvent - Data x coordinate. | ||
* @param {number} [y] - Grid row coordinate. _Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {Object} properties - Hash of cell properties. _When `y` omitted, this param promoted to 2nd arg._ | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
*/ | ||
addCellProperties: function(xOrCellEvent, y, properties, dataModel) { | ||
if (typeof xOrCellEvent === 'object') { | ||
properties = y; | ||
return xOrCellEvent.column.addCellProperties(xOrCellEvent.dataCell.y, properties, xOrCellEvent.subgrid); // y omitted so y here is actually properties | ||
} else { | ||
return this.getColumn(xOrCellEvent).addCellProperties(y, properties, dataModel); | ||
} | ||
}, | ||
/** | ||
* @summary Set a specific cell property. | ||
* @desc If there is no cell properties object, defers to column properties object. | ||
* | ||
* NOTE: For performance reasons, renderer's cell event objects cache their respective cell properties objects. This method accepts a `CellEvent` overload. Whenever possible, use the `CellEvent` from the renderer's cell event pool. Doing so will reset the cell properties object cache. | ||
* | ||
* If you use some other `CellEvent`, the renderer's `CellEvent` properties cache will not be automatically reset until the whole cell event pool is reset on the next call to {@link Renderer#computeCellBoundaries}. If necessary, you can "manually" reset it by calling {@link Renderer#resetCellPropertiesCache|resetCellPropertiesCache(yourCellEvent)} which searches the cell event pool for one with matching coordinates and resets the cache. | ||
* | ||
* The raw coordinates overload calls the `resetCellPropertiesCache(x, y)` overload for you. | ||
* @param {CellEvent|number} xOrCellEvent - `CellEvent` or data x coordinate. | ||
* @param {number} [y] - Grid row coordinate. _Omit when `xOrCellEvent` is a `CellEvent`._ | ||
* @param {string} key - Name of property to get. _When `y` omitted, this param promoted to 2nd arg._ | ||
* @param value | ||
* @param {dataModelAPI} [dataModel=this.subgrids.lookup.data] - For use only when `xOrCellEvent` is _not_ a `CellEvent`: Provide a subgrid. | ||
* @memberOf Behavior# | ||
*/ | ||
setCellProperty: function(xOrCellEvent, y, key, value, dataModel) { | ||
var cellOwnProperties; | ||
if (typeof xOrCellEvent === 'object') { | ||
value = key; | ||
key = y; | ||
cellOwnProperties = xOrCellEvent.setCellProperty(key, value); | ||
} else { | ||
cellOwnProperties = this.getColumn(xOrCellEvent).setCellProperty(y, key, value, dataModel); | ||
this.grid.renderer.resetCellPropertiesCache(xOrCellEvent, y, dataModel); | ||
} | ||
return cellOwnProperties; | ||
}, | ||
getUnfilteredRowCount: function() { | ||
return this.deprecated('getUnfilteredRowCount()', '', '1.2.0', arguments, 'No longer supported'); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc The value is lazily initialized and comes from the properties mechanism for '`defaultRowHeight`', which should be ~20px. | ||
* @returns {number} The row height in pixels. | ||
*/ | ||
getDefaultRowHeight: function() { | ||
return this.deprecated('getDefaultRowHeight()', 'grid.properties.defaultRowHeight', '1.2.0'); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @return {number} The width of the fixed column area in the hypergrid. | ||
@@ -835,47 +674,2 @@ */ | ||
* @memberOf Behavior# | ||
* @desc Set the scroll position in vertical dimension and notify listeners. | ||
* @param {number} y - the new y value | ||
*/ | ||
_setScrollPositionY: function(y) { | ||
this.setScrollPositionY(y); | ||
this.changed(); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc Set the scroll position in horizontal dimension and notify listeners. | ||
* @param {number} x - the new x value | ||
*/ | ||
_setScrollPositionX: function(x) { | ||
this.setScrollPositionX(x); | ||
this.changed(); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc The fixed row area has been clicked, massage the details and call the real function. | ||
* @param {Hypergrid} grid | ||
* @param {Object} mouse - event details | ||
*/ | ||
_fixedRowClicked: function(grid, mouse) { | ||
var x = this.translateColumnIndex(this.getScrollPositionX() + mouse.gridCell.x - this.getFixedColumnCount()); | ||
var translatedPoint = new Point(x, mouse.gridCell.y); | ||
mouse.gridCell = translatedPoint; | ||
this.fixedRowClicked(grid, mouse); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc The fixed column area has been clicked, massage the details and call the real function. | ||
* @param {Hypergrid} grid | ||
* @param {Object} mouse - event details | ||
*/ | ||
_fixedColumnClicked: function(grid, mouse) { | ||
var translatedPoint = new Point(mouse.gridCell.x, this.getScrollPositionY() + mouse.gridCell.y - this.getFixedRowCount()); | ||
mouse.gridCell = translatedPoint; | ||
this.fixedColumnClicked(grid, mouse); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc delegate setting the cursor up the feature chain of responsibility | ||
@@ -1063,3 +857,3 @@ * @param {Hypergrid} grid | ||
getColumnProperties: function(x) { | ||
var column = this.getColumn(x); | ||
var column = (x !== this.treeColumnIndex || this.hasTreeColumn()) && this.getColumn(x); | ||
return column && column.properties; | ||
@@ -1089,3 +883,12 @@ }, | ||
clearAllCellProperties: function(x) { | ||
if (x !== undefined) { | ||
var X; | ||
if (x === undefined) { | ||
x = 0; | ||
X = this.columns.length; | ||
} else { | ||
X = x + 1; | ||
} | ||
for (; x < X; x++) { | ||
var column = this.getColumn(x); | ||
@@ -1095,11 +898,2 @@ if (column) { | ||
} | ||
} else if (this.subgrids) { | ||
this.subgrids.forEach(function(dataModel) { | ||
for (var i = dataModel.getRowCount(); i--;) { | ||
delete dataModel.getRow(i).__META; | ||
// todo: test if optimizer wants following instead | ||
// dataRow = dataModel.getRow(i); | ||
// if (dataRow.__META !== undefined) { dataRow.__META = undefined; } | ||
} | ||
}); | ||
} | ||
@@ -1203,5 +997,2 @@ }, | ||
}, | ||
getColumnCount: function() { | ||
return this.deprecated('getColumnCount()', 'getActiveColumnCount()', '1.0.6', arguments); | ||
}, | ||
@@ -1271,6 +1062,6 @@ /** | ||
* @desc this function is a hook and is called just before the painting of a cell occurs | ||
* @param {window.fin.rectangular.Point} cell | ||
* @param {Point} cell | ||
*/ | ||
cellPropertiesPrePaintNotification: function(cell) { | ||
set cellPropertiesPrePaintNotification(cell) { | ||
throw new this.HypergridError('cellPropertiesPrePaintNotification has been deprecated as of v3.0.0. Code to inspect or mutate the render config object should be moved to the getCell hook.'); | ||
}, | ||
@@ -1280,29 +1071,2 @@ | ||
* @memberOf Behavior# | ||
* @desc this function is a hook and is called just before the painting of a fixed row cell occurs | ||
* @param {window.fin.rectangular.Point} cell | ||
*/ | ||
cellFixedRowPrePaintNotification: function(cell) { | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc this function is a hook and is called just before the painting of a fixed column cell occurs | ||
* @param {window.fin.rectangular.Point} cell | ||
*/ | ||
cellFixedColumnPrePaintNotification: function(cell) { | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc this function is a hook and is called just before the painting of a top left cell occurs | ||
* @param {window.fin.rectangular.Point} cell | ||
*/ | ||
cellTopLeftPrePaintNotification: function(cell) { | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @desc swap src and tar columns | ||
@@ -1320,15 +1084,2 @@ * @param {number} src - column index | ||
getColumnEdge: function(c, renderer) { | ||
return this.dataModel.getColumnEdge(c, renderer); | ||
}, | ||
/** | ||
* @memberOf Behavior# | ||
* @return {object} The object at y index. | ||
* @param {number} y - the row index of interest | ||
*/ | ||
getRow: function(y) { | ||
return this.dataModel.getRow(y); | ||
}, | ||
convertViewPointToDataPoint: function(unscrolled) { | ||
@@ -1341,3 +1092,3 @@ return new Point( | ||
hasTreeColumn: function() { | ||
hasTreeColumn: function(columnIndex) { | ||
return false; | ||
@@ -1366,5 +1117,5 @@ }, | ||
checkColumnAutosizing: function(force) { | ||
var autoSized = this.autoSizeRowNumberColumn() || this.autoSizeTreeColumn(); | ||
var autoSized = this.autoSizeRowNumberColumn(force) || this.autoSizeTreeColumn(force); | ||
this.allColumns.forEach(function(column) { | ||
this.allColumns.findWithNeg(function(column) { | ||
autoSized = column.checkColumnAutosizing(force) || autoSized; | ||
@@ -1376,55 +1127,14 @@ }); | ||
autoSizeRowNumberColumn: function() { | ||
autoSizeRowNumberColumn: function(force) { | ||
if (this.grid.properties.showRowNumbers && this.grid.properties.rowNumberAutosizing) { | ||
return this.getRowHeaderColumn().checkColumnAutosizing(true); | ||
return this.getRowHeaderColumn().checkColumnAutosizing(force); | ||
} | ||
}, | ||
autoSizeTreeColumn: function() { | ||
autoSizeTreeColumn: function(force) { | ||
if (this.grid.properties.showTreeColumn && this.grid.properties.treeColumnAutosizing) { | ||
return this.getTreeColumn().checkColumnAutosizing(true); | ||
return this.getTreeColumn().checkColumnAutosizing(force); | ||
} | ||
}, | ||
/** | ||
* @summary Get the given data controller. | ||
* @param {string} type | ||
* @returns {undefined|*} The data controller; or `undefined` if data controller unknown to data model. | ||
* @memberOf Behavior# | ||
*/ | ||
getController: function(type) { | ||
return this.dataModel.getController(type); | ||
}, | ||
/** | ||
* @summary Set the given data controller(s). | ||
* @desc Triggers a shape change. | ||
* @param {string} typeOrHashOfTypes - One of: | ||
* * **object** - Hash of multiple data controllers, by type. | ||
* * **string** - Type of the single data controller given in `controller`. | ||
* @param {dataControlInterface} [controller] - Only required when 'hash' is a string; omit when `hash` is an object. | ||
* @returns {object} - Hash of all results, by type. Each member will be: | ||
* * The given data controller for that type when defined. | ||
* * A new "null" data controller, generated by the data model when the given data controller for that type was `undefined`. | ||
* * `undefined` - The data controller was unknown to the data model.. | ||
* @memberOf Behavior# | ||
*/ | ||
setController: function(typeOrHashOfTypes, controller) { | ||
var results = this.dataModel.setController(typeOrHashOfTypes, controller); | ||
this.changed(); | ||
return results; | ||
}, | ||
prop: function(type, columnIndex, keyOrHash, value) { | ||
var result = this.dataModel.prop.apply(this.dataModel, arguments); | ||
if (result === undefined) { | ||
this.changed(); | ||
} | ||
return result; | ||
}, | ||
get charMap() { | ||
return this.dataModel.charMap; | ||
}, | ||
getColumns: function() { | ||
@@ -1465,11 +1175,4 @@ return this.allColumns; | ||
getData: function() { | ||
return this.dataModel.getData(); | ||
}, | ||
getFilteredData: function() { | ||
return this.deprecated('getIndexedData()', 'getIndexedData', '1.2.0', arguments); | ||
}, | ||
getIndexedData: function() { | ||
this.dataModel.getIndexedData(); | ||
return this.deprecated('getIndexedData()', 'getData()', '3.0.0'); | ||
} | ||
@@ -1479,6 +1182,10 @@ }); | ||
// define constants as immutable (i.e., !writable) | ||
// tree and row number column defaults; define indexes as immutable (i.e., !writable) | ||
Object.defineProperties(Behavior.prototype, { | ||
treeColumnIndex: { value: -1 }, | ||
rowColumnIndex: { value: -2 } | ||
treeColumnNameDefault: { value: 'Tree', writable: true }, | ||
treeColumnHeaderDefault: { value: 'Tree', writable: true }, | ||
rowColumnIndex: { value: -2 }, | ||
rowColumnNameDefault: { value: 'RowHeader', writable: true } | ||
}); | ||
@@ -1542,6 +1249,8 @@ | ||
// mix-ins | ||
Behavior.prototype.mixIn(require('./subgrids')); | ||
Behavior.prototype.mixIn(require('./rowProperties').mixin); | ||
Behavior.prototype.mixIn(require('./gridCellProperties').mixin); | ||
Behavior.prototype.mixIn(require('./dataModel').mixin); | ||
Behavior.prototype.mixIn(require('./subgrids').mixin); | ||
module.exports = Behavior; |
@@ -1,13 +0,10 @@ | ||
/* eslint-env bro wser */ | ||
'use strict'; | ||
var assignOrDelete = require('../lib/misc').assignOrDelete; | ||
var assignOrDelete = require('../lib/assignOrDelete'); | ||
/** | ||
* Column.js mixes this module into its prototype. | ||
* @module | ||
* @mixin | ||
*/ | ||
var cell = { | ||
exports.mixin = { | ||
@@ -20,2 +17,3 @@ /** | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @return {object} The properties of the cell at x,y in the grid. | ||
@@ -31,2 +29,3 @@ * @memberOf Column# | ||
* @param {object|undefined} properties - Hash of cell properties. If `undefined`, this call is a no-op. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {*} New cell properties object, based on column properties object, with `properties` copied to it. | ||
@@ -44,2 +43,3 @@ * @memberOf Column# | ||
* @param {object|undefined} properties - Hash of cell properties. If `undefined`, this call is a no-op. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {object} Cell's own properties object, which will be created by this call if it did not already exist. | ||
@@ -56,3 +56,3 @@ * @memberOf Column# | ||
* @summary Get the cell's own properties object. | ||
* @desc Due to memory constraints, we don't create a cell options properties object for every cell. | ||
* @desc Due to memory constraints, we don't create a cell properties object for every cell. | ||
* | ||
@@ -68,11 +68,12 @@ * If the cell has its own properties object, it: | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @returns {null|object} The "own" properties of the cell at x,y in the grid. If the cell does not own a properties object, returns `undefined`. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {null|object} The "own" properties of the cell at x,y in the grid. If the cell does not own a properties object, returns `null`. | ||
* @memberOf Column# | ||
*/ | ||
getCellOwnProperties: function(rowIndex, dataModel) { | ||
var rowData; | ||
var metadata; | ||
return ( | ||
// this.index >= 0 && // no cell props on row handle cells | ||
(rowData = (dataModel || this.dataModel).getRow(rowIndex)) && // no cell props on non-existent rows | ||
rowData.__META && rowData.__META[this.name] || | ||
(metadata = (dataModel || this.dataModel).getRowMetadata(rowIndex)) && // no cell props on non-existent rows | ||
metadata && metadata[this.name] || | ||
null // null means not previously created | ||
@@ -82,6 +83,16 @@ ); | ||
/** | ||
* Delete cell's own properties object. | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @memberOf Column# | ||
*/ | ||
deleteCellOwnProperties: function(rowIndex, dataModel) { | ||
var rowData = (dataModel || this.dataModel).getRow(rowIndex); | ||
if (rowData.__META) { | ||
delete rowData.__META[this.name]; | ||
dataModel = dataModel || this.dataModel; | ||
var metadata = dataModel.getRowMetadata(rowIndex); | ||
if (metadata) { | ||
delete metadata[this.name]; | ||
if (Object.keys(metadata).length === 0) { | ||
dataModel.setRowMetadata(rowIndex); | ||
} | ||
} | ||
@@ -95,2 +106,3 @@ }, | ||
* @param {string} key | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @return {object} The specified property for the cell at x,y in the grid. | ||
@@ -107,3 +119,4 @@ * @memberOf Column# | ||
* @param value | ||
* @returns {object} | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {object} Cell's own properties object, which will be created by this call if it did not already exist. | ||
* @memberOf Column# | ||
@@ -117,2 +130,9 @@ */ | ||
/** | ||
* @summary Delete a cell own property. | ||
* @summary If the property is not an own property, it is not deleted. | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @param {string} key | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
*/ | ||
deleteCellProperty: function(rowIndex, key, dataModel) { | ||
@@ -125,18 +145,12 @@ var cellProps = this.getCellOwnProperties(rowIndex, dataModel); | ||
/** | ||
* Clear all cell properties from all cells in this column. | ||
* @memberOf Column# | ||
*/ | ||
clearAllCellProperties: function() { | ||
var key = this.name; | ||
this.behavior.subgrids.forEach(function(dataModel) { | ||
for (var i = dataModel.getRowCount(); i--;) { | ||
var rowData = dataModel.getRow(i), | ||
meta = rowData.__META; | ||
if (meta) { | ||
if (Object.keys(meta).length === 1) { | ||
delete rowData.__META; | ||
} | ||
if (meta) { | ||
delete meta[key]; | ||
} | ||
} | ||
for (var y = dataModel.getRowCount(); y--;) { | ||
this.deleteCellOwnProperties(y, dataModel); | ||
} | ||
}); | ||
}, this); | ||
} | ||
@@ -146,4 +160,6 @@ }; | ||
/** | ||
* @todo: Theoretically setData should call this method to ensure each cell's persisted properties object is properly recreated with prototype set to its column's properties object. | ||
* @this {Column} | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {object} | ||
@@ -157,6 +173,5 @@ * @private | ||
/** | ||
* @todo: For v8 optimization, consider setting the new `__META` object to a "regularly shaped object" (i.e., with all the columns) instead of simply to `{}`. Considerations include how many of these objects are there, how often are they referenced, etc. | ||
* @todo: We need a function to reset the prototypes of pre-existing __META members to their respective column properties objects. | ||
* @this {Column} | ||
* @param {number} rowIndex - Data row coordinate. | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {object} | ||
@@ -166,3 +181,3 @@ * @private | ||
function newCellPropertiesObject(rowIndex, dataModel) { | ||
var metadata = (dataModel || this.dataModel).getRowMetadata(rowIndex, {}), | ||
var metadata = (dataModel || this.dataModel).getRowMetadata(rowIndex, null), | ||
props = this.properties; | ||
@@ -172,6 +187,6 @@ | ||
case this.behavior.treeColumnIndex: | ||
props = this.properties.treeHeader; | ||
props = props.treeHeader; | ||
break; | ||
case this.behavior.rowColumnIndex: | ||
props = this.properties.rowHeader; | ||
props = props.rowHeader; | ||
break; | ||
@@ -186,3 +201,1 @@ default: | ||
} | ||
module.exports = cell; |
@@ -7,5 +7,4 @@ /* eslint-env browser */ | ||
var deprecated = require('../lib/deprecated'); | ||
var toFunction = require('../lib/toFunction'); | ||
var assignOrDelete = require('../lib/misc').assignOrDelete; | ||
var assignOrDelete = require('../lib/assignOrDelete'); | ||
var HypergridError = require('../lib/error'); | ||
@@ -19,3 +18,2 @@ var images = require('../../images'); | ||
/** @summary Create a new `Column` object. | ||
* @see {@link module:Cell} is mixed into Column.prototype. | ||
* @mixes cellProperties.columnMixin | ||
@@ -37,4 +35,4 @@ * @mixes columnProperties.mixin | ||
* :-----: | -------- | ||
* -1 | Row header column | ||
* -2 | Tree (drill-down) column | ||
* -2 | Row header column | ||
* -1 | Tree (drill-down) column | ||
*/ | ||
@@ -63,3 +61,3 @@ function Column(behavior, columnSchema) { | ||
if (index < 0) { | ||
throw new ReferenceError('Column named "' + name + '" not found in schema.'); | ||
throw new this.HypergridError('Column named "' + name + '" not found in schema.'); | ||
} | ||
@@ -82,3 +80,3 @@ columnSchema = { | ||
if (index < 0) { | ||
throw new ReferenceError('Column named "' + name + '" not found in schema.'); | ||
throw new this.HypergridError('Column named "' + name + '" not found in schema.'); | ||
} | ||
@@ -122,3 +120,3 @@ columnSchema.index = index; | ||
if (columnSchema.index < 0) { | ||
throw new RangeError('New column index ' + columnSchema.index + ' out of range.'); | ||
throw new this.HypergridError('New column index ' + columnSchema.index + ' out of range.'); | ||
} | ||
@@ -131,3 +129,2 @@ } | ||
$$CLASS_NAME: 'Column', | ||
deprecated: deprecated, | ||
@@ -138,6 +135,2 @@ HypergridError: HypergridError, | ||
set: function(options) { | ||
return this.deprecated('set(options)', 'setProperties(options)', '1.2.0', arguments); | ||
}, | ||
/** | ||
@@ -154,3 +147,2 @@ * @summary Get or set the text of the column's header. | ||
this.schema.header = header; | ||
this.dataModel.prop(null, this.index, 'header', header); | ||
this.behavior.grid.repaint(); | ||
@@ -164,5 +156,3 @@ }, | ||
* @summary Get or set the computed column's calculator function. | ||
* @desc Setting the value here updates the calculator in both: | ||
* * the `calculator` array in the underlying data source; and | ||
* * the filter. | ||
* @desc Setting the value here updates the calculator in the data model schema. | ||
* | ||
@@ -176,3 +166,3 @@ * The results of the new calculations will appear in the column cells on the next repaint. | ||
this.schema.calculator = calculator; | ||
this.behavior.grid.reindex(); // deferred reindex as there may be several of these calls at instantiation | ||
this.behavior.grid.reindex(); | ||
} | ||
@@ -193,4 +183,2 @@ }, | ||
this.schema.type = type; | ||
//TODO: This is calling reindex for every column during grid init. Maybe defer all reindex calls until after an grid 'ready' event | ||
this.dataModel.prop(null, this.index, 'type', type); | ||
this.behavior.reindex(); | ||
@@ -202,14 +190,10 @@ }, | ||
getUnfilteredValue: function(y) { | ||
return this.deprecated('getUnfilteredValue(y)', null, '1.2.0', arguments, 'No longer supported'); | ||
getValue: function(y, dataModel) { | ||
return this.dataModel.getValue(this.index, y, dataModel); | ||
}, | ||
getValue: function(y) { | ||
return this.dataModel.getValue(this.index, y); | ||
setValue: function(y, value, dataModel) { | ||
return this.dataModel.setValue(this.index, y, value, dataModel); | ||
}, | ||
setValue: function(y, value) { | ||
return this.dataModel.setValue(this.index, y, value); | ||
}, | ||
getWidth: function() { | ||
@@ -237,2 +221,5 @@ return this.properties.width || this.behavior.grid.properties.defaultColumnWidth; | ||
properties.width = force ? preferredWidth : Math.max(width, preferredWidth); | ||
if (properties.columnAutosizingMax && properties.width > properties.columnAutosizingMax) { | ||
properties.width = properties.columnAutosizingMax; | ||
} | ||
properties.columnAutosized = !isNaN(properties.width); | ||
@@ -326,6 +313,2 @@ autoSized = properties.width !== width; | ||
getProperties: function() { | ||
return this.deprecated('getProperties()', 'properties', '1.2.0'); | ||
}, | ||
/** This method is provided because some grid renderer optimizations require that the grid renderer be informed when column colors change. Due to performance concerns, they cannot take the time to figure it out for themselves. Along the same lines, making the property a getter/setter (in columnProperties.js), though doable, might present performance concerns as this property is possibly the most accessed of all column properties. | ||
@@ -342,15 +325,2 @@ * @param color | ||
/** | ||
* @param {object} properties | ||
* @param {boolean} [preserve=false] | ||
*/ | ||
setProperties: function(properties, preserve) { | ||
if (!preserve) { | ||
this.deprecated('setProperties', 'setProperties(properties) has been deprecated in favor of properties (setter) as of v1.2.0. (Will be removed in a future version.) This advice only pertains to usages of setProperties when called with a single parameter. When called with a truthy second parameter, use the new addProperties(properties) call instead.'); | ||
this.properties = properties; | ||
} else { | ||
this.deprecated('setPropertiesPreserve', 'setProperties(properties, preserve)', 'addProperties(properties)', '1.2.0', arguments, 'This warning pertains to setProperties only when preserve is truthy. When preserve is faulty, use the new properties setter.'); | ||
} | ||
}, | ||
/** | ||
* @summary Get a new cell editor. | ||
@@ -367,4 +337,7 @@ * @desc The cell editor to use must be registered with the key in the cell's `editor` property. | ||
var columnIndex = this.index, | ||
rowIndex = cellEvent.gridCell.y, | ||
editorName = cellEvent.properties.editor, | ||
options = Object.create(cellEvent, { | ||
@@ -374,3 +347,3 @@ format: { | ||
// 1. Subject to adjustment by the `getCellEditorAt` override. | ||
// 2. Then used by the cell editor to reference the predefined localizer. | ||
// 2. Then used by the cell editor to reference the registered localizer (defaults to 'string' localizer) | ||
writable: true, | ||
@@ -381,4 +354,5 @@ enumerable: true, // so cell editor will copy it to self | ||
}), | ||
cellEditor = this.dataModel.getCellEditorAt(columnIndex, rowIndex, editorName, options); | ||
cellEditor = cellEvent.subgrid.getCellEditorAt(columnIndex, rowIndex, editorName, options); | ||
if (cellEditor && !cellEditor.grid) { | ||
@@ -454,5 +428,5 @@ // cell editor returned but not fully instantiated (aborted by falsy return from fireRequestCellEdit) | ||
Column.prototype.mixIn(require('./cellProperties')); | ||
Column.prototype.mixIn(require('./columnProperties')); | ||
Column.prototype.mixIn(require('./cellProperties').mixin); | ||
Column.prototype.mixIn(require('./columnProperties').mixin); | ||
module.exports = Column; |
'use strict'; | ||
var FIELD = 'columnProperties.field is deprecated as of v1.1.0 in favor of columnProperties.name. (Will be removed in a future release.)', | ||
COLUMN_NAME = 'columnProperties.columnName is deprecated as of v1.1.0 in favor of columnProperties.name. (Will be removed in a future release.)', | ||
COLUMN_ONLY_PROPERTY = 'Attempt to set column-only property on a non-column properties object.'; | ||
/** | ||
@@ -33,3 +29,2 @@ * @this {Column} | ||
get: function() { | ||
if (FIELD) { console.warn(FIELD); FIELD = undefined; } | ||
return column.name; | ||
@@ -41,3 +36,2 @@ } | ||
get: function() { | ||
if (COLUMN_NAME) { console.warn(COLUMN_NAME); COLUMN_NAME = undefined; } | ||
return column.name; | ||
@@ -53,3 +47,3 @@ } | ||
if (this !== column.properties) { | ||
throw new column.HypergridError(COLUMN_ONLY_PROPERTY); | ||
tableState.header = header; // throws an error | ||
} | ||
@@ -66,3 +60,3 @@ column.header = header; | ||
if (this !== column.properties) { | ||
throw new column.HypergridError(COLUMN_ONLY_PROPERTY); | ||
tableState.type = type; // throws an error | ||
} | ||
@@ -79,3 +73,3 @@ column.type = type; | ||
if (this !== column.properties) { | ||
throw new column.HypergridError(COLUMN_ONLY_PROPERTY); | ||
tableState.calculator = calculator; // throws an error | ||
} | ||
@@ -106,2 +100,7 @@ column.calculator = calculator; | ||
switch (column.index) { | ||
case column.behavior.treeColumnIndex: properties = properties.treeHeader; break; | ||
case column.behavior.rowColumnIndex: properties = properties.rowHeader; break; | ||
} | ||
return properties; | ||
@@ -165,3 +164,3 @@ } | ||
get: function() { | ||
return this.treeRenderer; | ||
return this.isDataRow ? this.treeRenderer : this.grid.properties.renderer; | ||
}, | ||
@@ -181,2 +180,22 @@ set: function(value) { | ||
} | ||
}, | ||
columnAutosizing: { | ||
configurable: true, | ||
enumerable: true, | ||
get: function() { | ||
return this.treeColumnAutosizing; | ||
}, | ||
set: function(value) { | ||
this.treeColumnAutosizing = value; | ||
} | ||
}, | ||
columnAutosizingMax: { | ||
configurable: true, | ||
enumerable: true, | ||
get: function() { | ||
return this.treeColumnAutosizingMax; | ||
}, | ||
set: function(value) { | ||
this.treeColumnAutosizingMax = value; | ||
} | ||
} | ||
@@ -272,2 +291,12 @@ //leftIcon: undefined | ||
} | ||
}, | ||
columnAutosizing: { | ||
configurable: true, | ||
enumerable: true, | ||
get: function() { | ||
return this.rowNumberAutosizing; | ||
}, | ||
set: function(value) { | ||
this.rowNumberAutosizing = value; | ||
} | ||
} | ||
@@ -363,3 +392,3 @@ }; | ||
if (this.filterable) { | ||
result = this.value.length ? 'filter-on' : 'filter-off'; | ||
result = this.filter ? 'filter-on' : 'filter-off'; | ||
} | ||
@@ -451,2 +480,12 @@ return result; | ||
}, | ||
format: { | ||
configurable: true, | ||
enumerable: true, | ||
get: function() { | ||
return this.columnHeaderFormat; | ||
}, | ||
set: function(value) { | ||
this.columnHeaderFormat = value; | ||
} | ||
}, | ||
renderer: { | ||
@@ -467,2 +506,8 @@ configurable: true, | ||
exports.createColumnProperties = createColumnProperties; | ||
/** | ||
* Column.js mixes this module into its prototype. | ||
* @mixin | ||
*/ | ||
exports.mixin = { | ||
createColumnProperties: createColumnProperties | ||
}; |
'use strict'; | ||
/** | ||
* Behavior.js mixes this module into its prototype. | ||
* @mixin | ||
*/ | ||
exports.mixin = { | ||
@@ -45,3 +49,3 @@ /** | ||
* _(Required when 3rd param provided.)_ | ||
* @param {dataModelAPI} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
* @param {DataModel} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
* @returns {object|undefined} The row properties object which will be one of: | ||
@@ -67,3 +71,3 @@ * * object - existing row properties object or new row properties object created from `prototype`; else | ||
* @param {object|undefined} properties - The new row properties object. If `undefined`, this call is a no-op. | ||
* @param {dataModelAPI} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
* @param {DataModel} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
*/ | ||
@@ -84,2 +88,3 @@ setRowProperties: function(yOrCellEvent, properties, dataModel) { | ||
this.addRowProperties(yOrCellEvent, properties, dataModel, metadata.__ROW); | ||
this.stateChanged(); | ||
} | ||
@@ -94,3 +99,3 @@ }, | ||
* @param value - The new property value. | ||
* @param {dataModelAPI} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
* @param {DataModel} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
*/ | ||
@@ -124,3 +129,3 @@ setRowProperty: function(yOrCellEvent, key, value, dataModel) { | ||
* @param {object|undefined} properties - An object containing new property values(s) to assign to the row properties. If `undefined`, this call is a no-op. | ||
* @param {dataModelAPI} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
* @param {DataModel} [dataModel=this.dataModel] - This is the subgrid. You only need to provide the subgrid when it is not the data subgrid _and_ you did not give a `CellEvent` object in the first param (which already knows what subgrid it's in). | ||
*/ | ||
@@ -159,3 +164,3 @@ addRowProperties: function(yOrCellEvent, properties, dataModel, rowProps) { | ||
* @param {number} yOrCellEvent - Data row index local to `dataModel`. | ||
* @param {dataModelAPI} [dataModel=this.dataModel] | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
* @returns {number} The row height in pixels. | ||
@@ -173,3 +178,3 @@ */ | ||
* @param {number} height - pixel height | ||
* @param {dataModelAPI} [dataModel=this.dataModel] | ||
* @param {DataModel} [dataModel=this.dataModel] | ||
*/ | ||
@@ -176,0 +181,0 @@ setRowHeight: function(yOrCellEvent, height, dataModel) { |
'use strict'; | ||
var dataModels = require('../dataModels'); | ||
var dataModels = require('../dataModels/index'); | ||
@@ -23,3 +23,7 @@ /** @typedef subgridConstructorRef | ||
module.exports = { | ||
/** | ||
* Behavior.js mixes this module into its prototype. | ||
* @mixin | ||
*/ | ||
exports.mixin = { | ||
/** | ||
@@ -43,3 +47,3 @@ * An array where each element represents a subgrid to be rendered in the hypergrid. | ||
* | ||
* @type {dataModelAPI[]} | ||
* @type {DataModel[]} | ||
* | ||
@@ -69,3 +73,3 @@ * @memberOf Behavior# | ||
* @param {subgridSpec} spec | ||
* @returns {dataModelAPI} A data model. | ||
* @returns {DataModel} A data model. | ||
* @memberOf Behavior# | ||
@@ -81,3 +85,4 @@ */ | ||
variableArgArray = spec.slice(1); | ||
subgrid = this.createApply(Constructor, variableArgArray, this.grid); | ||
subgrid = this.createApply(Constructor, variableArgArray, undefined, { grid: this.grid }); | ||
subgrid = this.decorateDataModel(subgrid); | ||
} else if (typeof spec === 'object') { | ||
@@ -88,10 +93,13 @@ subgrid = spec; | ||
variableArgArray = Array.prototype.slice.call(arguments, 1); | ||
subgrid = this.createApply(Constructor, variableArgArray, this.grid); | ||
subgrid = this.createApply(Constructor, variableArgArray, undefined, { grid: this.grid }); | ||
subgrid = this.decorateDataModel(subgrid); | ||
} | ||
// undefined type is data | ||
subgrid.type = subgrid.type || 'data'; | ||
if (!subgrid.type) { | ||
subgrid.type = 'data'; | ||
} | ||
// make dictionary lookup entry | ||
var key = subgrid.name || subgrid.type; | ||
var key = subgrid.type === 'data' && subgrid.type || subgrid.name || subgrid.type; | ||
this._subgrids.lookup[key] = this._subgrids.lookup[key] || subgrid; // only save first with this key | ||
@@ -108,3 +116,3 @@ | ||
* @desc Defined as the sum of all rows in all subgrids before the (first) data subgrid. | ||
* @memberOf behaviors.JSON.prototype | ||
* @memberOf Local.prototype | ||
*/ | ||
@@ -127,3 +135,3 @@ getHeaderRowCount: function() { | ||
* @desc Defined as the sum of all rows in all subgrids after the (last) data subgrid. | ||
* @memberOf behaviors.JSON.prototype | ||
* @memberOf Local.prototype | ||
*/ | ||
@@ -145,3 +153,3 @@ getFooterRowCount: function() { | ||
* @desc Defined as the sum of all rows in all subgrids. | ||
* @memberOf behaviors.JSON.prototype | ||
* @memberOf Local.prototype | ||
*/ | ||
@@ -167,3 +175,3 @@ getLogicalRowCount: function() { | ||
case 'string': | ||
Constructor = dataModels[ref]; | ||
Constructor = dataModels.get(ref); | ||
break; | ||
@@ -170,0 +178,0 @@ case 'function': |
@@ -5,4 +5,2 @@ /* eslint-env browser */ | ||
var mustache = require('mustache'); | ||
var Base = require('../Base'); | ||
@@ -14,4 +12,12 @@ var effects = require('../lib/DOM/effects'); | ||
* @constructor | ||
* @param grid | ||
* @param {CellEvent} options - Properties listed below + arbitrary mustache "variables" for merging into template. | ||
* @desc Displays a cell editor and handles cell editor interactions. | ||
* | ||
* > This constructor (actually `initialize`) will be called upon instantiation of this class or of any class that extends from this class. See {@link https://github.com/joneit/extend-me|extend-me} for more info. | ||
* | ||
* Instances of `CellEditor` are used to render an HTML element on top of the grid exactly within the bound of a cell for purposes of editing the cell value. | ||
* | ||
* Extend this base class to implement your own cell editor. | ||
* | ||
* @param {Hypergrid} grid | ||
* @param {object} options - Properties listed below + arbitrary mustache "variables" for merging into template. | ||
* @param {Point} options.editPoint - Deprecated; use `options.gridCell`. | ||
@@ -30,3 +36,3 @@ * @param {string} [options.format] - Name of a localizer with which to override prototype's `localizer` property. | ||
var value = grid.behavior.getValue(this.event); | ||
var value = this.event.value; | ||
if (value instanceof Array) { | ||
@@ -47,5 +53,7 @@ value = value[1]; //it's a nested object | ||
// override native localizer with localizer named in format if defined (from instantiation options) | ||
if (options.format) { | ||
this.localizer = this.grid.localization.get(options.format); | ||
// Only override cell editor's default 'null' localizer if the custom localizer lookup succeeds. | ||
// Failure is when it returns the default ('string') localizer when 'string' is not what was requested. | ||
var localizer = this.grid.localization.get(options.format); // try to get named localizer | ||
if (!(localizer === Localization.prototype.string || options.format === 'string')) { | ||
this.localizer = localizer; | ||
} | ||
@@ -56,3 +64,3 @@ | ||
var container = document.createElement('DIV'); | ||
container.innerHTML = mustache.render(this.template, this); | ||
container.innerHTML = this.grid.modules.templater.render(this.template, this); | ||
@@ -137,2 +145,3 @@ /** | ||
var finEvent = grid.canvas.newEvent(e, 'fin-editor-keydown', { | ||
grid: grid, | ||
alt: e.altKey, | ||
@@ -196,5 +205,2 @@ ctrl: e.ctrlKey, | ||
}, | ||
beginEditAt: function(Constructor, name) { | ||
return this.deprecated('beginEditAt(point)', 'beginEditing()', '1.0.6'); | ||
}, | ||
@@ -372,3 +378,3 @@ /** | ||
if (save) { | ||
this.grid.behavior.setValue(this.event, value); | ||
this.event.value = value; | ||
this.grid.fireAfterCellEdit(this.event.gridCell, this.initialValue, value, this); | ||
@@ -479,5 +485,2 @@ } | ||
CellEditor.abstract = true; // don't instantiate directly | ||
module.exports = CellEditor; |
@@ -6,2 +6,3 @@ 'use strict'; | ||
/** | ||
* The default cell rendering function for a button cell. | ||
* @constructor | ||
@@ -11,7 +12,2 @@ * @extends CellRenderer | ||
var Button = CellRenderer.extend('Button', { | ||
/** | ||
* @summary The default cell rendering function for a button cell. | ||
* @memberOf Button.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -18,0 +14,0 @@ var val = config.value, |
'use strict'; | ||
/** @typedef {object} CellRenderer#renderConfig | ||
* | ||
* This is the renderer config object, which is: | ||
@@ -79,23 +80,12 @@ * 1. First passed to a {@link DataModel#getCell getCell} method implementation, which may override (most of) its values before returning. | ||
* Typically a Local primitive value, values can be any type, including objects and arrays. The specified cell renderer is expected to know how to determine the value's type and render it. | ||
*/ | ||
*/ | ||
var Base = require('../Base'); | ||
/** @typedef paintFunction | ||
* @type {function} | ||
* @this {CellEditor} | ||
* @param {CanvasRenderingContext2D} gc | ||
* @param {object} config | ||
* @param {Rectangle} config.bounds - The clipping rect of the cell to be rendered. | ||
* @param {number} config.x - the "translated" index into the `behavior.allColumns` array | ||
* @param {number} config.normalizedY - the vertical grid coordinate normalized to first data row | ||
* @param {number} config.untranslatedX - the horizontal grid coordinate measured from first data column | ||
* @param {number} config.y - the vertical grid coordinate measured from top header row | ||
*/ | ||
/** @constructor | ||
* @desc Instances of `CellRenderer` are used to render the 2D graphics context within the bound of a cell. Extend this base class to implement your own cell renderer | ||
* @desc Instances of `CellRenderer` are used to render the 2D graphics context within the bound of a cell. | ||
* | ||
* Extend this base class to implement your own cell renderer. | ||
* | ||
* See also {@tutorial cell-renderer}. | ||
* @tutorial cell-renderer | ||
*/ | ||
@@ -105,3 +95,11 @@ var CellRenderer = Base.extend('CellRenderer', { | ||
* @desc An empty implementation of a cell renderer, see [the null object pattern](http://c2.com/cgi/wiki?NullObject). | ||
* @implements paintFunction | ||
* | ||
* @this {CellEditor} | ||
* | ||
* @param {CanvasRenderingContext2D} gc | ||
* | ||
* @param {CellRenderer#renderConfig} config | ||
* | ||
* @returns {number} Preferred pixel width of content. The content may or may not be rendered at that width depending on whether or not `config.bounds` was respected and whether or not the grid renderer is using clipping. (Clipping is generally not used due to poor performance.) | ||
* | ||
* @memberOf CellRenderer.prototype | ||
@@ -152,4 +150,2 @@ */ | ||
CellRenderer.abstract = true; // don't instantiate directly | ||
module.exports = CellRenderer; |
@@ -33,3 +33,2 @@ 'use strict'; | ||
paint: function(gc, config, message) { | ||
//var images = require('../../images/index'); | ||
var x = config.bounds.x, | ||
@@ -36,0 +35,0 @@ y = config.bounds.y, |
@@ -7,10 +7,6 @@ 'use strict'; | ||
* @constructor | ||
* @desc A rendering of the last Selection Model | ||
* @extends CellRenderer | ||
*/ | ||
var LastSelection = CellRenderer.extend('LastSelection', { | ||
/** | ||
* @desc A rendering of the last Selection Model | ||
* @memberOf LastSelection.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -17,0 +13,0 @@ var visOverlay = gc.alpha(config.selectionRegionOverlayColor) > 0, |
'use strict'; | ||
var CellRenderer = require('./CellRenderer'); | ||
var images = require('../../images/index'); | ||
var images = require('../../images'); | ||
@@ -10,11 +10,12 @@ var WHITESPACE = /\s\s+/g; | ||
* @constructor | ||
* @summary The default cell renderer for a vanilla cell. | ||
* @desc Great care has been taken in crafting this function as it needs to perform extremely fast. | ||
* | ||
* Use `gc.cache` instead which we have implemented to cache the graphics context properties. Reads on the graphics context (`gc`) properties are expensive but not quite as expensive as writes. On read of a `gc.cache` prop, the actual `gc` prop is read into the cache once and from then on only the cache is referenced for that property. On write, the actual prop is only written to when the new value differs from the cached value. | ||
* | ||
* Clipping bounds are not set here as this is also an expensive operation. Instead, we employ a number of strategies to truncate overflowing text and content. | ||
* | ||
* @extends CellRenderer | ||
*/ | ||
var SimpleCell = CellRenderer.extend('SimpleCell', { | ||
/** | ||
* @summary The default cell rendering function for rendering a vanilla cell. | ||
* @desc Great care has been taken in crafting this function as it needs to perform extremely fast. Reads on the gc object are expensive but not quite as expensive as writes to it. We do our best to avoid writes, then avoid reads. Clipping bounds are not set here as this is also an expensive operation. Instead, we truncate overflowing text and content by filling a rectangle with background color column by column instead of cell by cell. This column by column fill happens higher up on the stack in a calling function from fin-hypergrid-renderer. Take note we do not do cell by cell border rendering as that is expensive. Instead we render many fewer gridlines after all cells are rendered. | ||
* @memberOf SimpleCell.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -21,0 +22,0 @@ var val = config.value, |
@@ -6,2 +6,4 @@ 'use strict'; | ||
/** | ||
* Renders a slider button. | ||
* Currently however the user cannot interact with it. | ||
* @constructor | ||
@@ -11,7 +13,2 @@ * @extends CellRenderer | ||
var Slider = CellRenderer.extend('Slider', { | ||
/** | ||
* @desc Emerson's paint function for a slider button. currently the user cannot interact with it | ||
* @memberOf Slider.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -18,0 +15,0 @@ var x = config.bounds.x, |
@@ -6,2 +6,3 @@ 'use strict'; | ||
/** | ||
* Renders a bar chart sparkline, hence the name. | ||
* @constructor | ||
@@ -11,7 +12,2 @@ * @extends CellRenderer | ||
var SparkBar = CellRenderer.extend('SparkBar', { | ||
/** | ||
* @desc A simple implementation of a sparkline, because it's a barchart we've changed the name ;). | ||
* @memberOf SparkBar.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -18,0 +14,0 @@ var x = config.bounds.x, |
@@ -6,2 +6,4 @@ 'use strict'; | ||
/** | ||
* Renders a sparkline. | ||
* @see [Edward Tufte sparkline](http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR) | ||
* @constructor | ||
@@ -11,7 +13,2 @@ * @extends CellRenderer | ||
var SparkLine = CellRenderer.extend('SparkLine', { | ||
/** | ||
* @desc A simple implementation of a sparkline. see [Edward Tufte sparkline](http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR) | ||
* @memberOf SparkLine.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
@@ -18,0 +15,0 @@ var x = config.bounds.x, |
@@ -6,2 +6,3 @@ 'use strict'; | ||
/** | ||
* Renders a tree cell (presumably in the tree column). | ||
* @constructor | ||
@@ -11,21 +12,13 @@ * @extends CellRenderer | ||
var TreeCell = CellRenderer.extend('TreeCell', { | ||
/** | ||
* @desc A simple implementation of a tree cell renderer for use mainly with the tree column. | ||
* @memberOf TreeCell.prototype | ||
*/ | ||
paint: function(gc, config) { | ||
var x = config.bounds.x, | ||
y = config.bounds.y, | ||
width = config.bounds.width, | ||
height = config.bounds.height; | ||
val = config.value.data, | ||
indent = config.value.indent, | ||
icon = config.value.icon; | ||
var val = config.value.data; | ||
var indent = config.value.indent; | ||
var icon = config.value.icon; | ||
//fill background only if our bgColor is populated or we are a selected cell | ||
// Fill background only if our bgColor is populated or we are a selected cell. | ||
if (config.backgroundColor || config.isSelected) { | ||
gc.cache.fillStyle = config.isSelected ? config.backgroundColor : config.backgroundColor; | ||
gc.fillRect(x, y, width, height); | ||
gc.fillRect(x, y, config.bounds.width, config.bounds.height); | ||
} | ||
@@ -36,10 +29,9 @@ | ||
} | ||
var valignOffset = Math.ceil(height / 2); | ||
gc.cache.fillStyle = config.isSelected ? config.backgroundColor : config.backgroundColor; | ||
var valignOffset = Math.ceil(config.bounds.height / 2); | ||
gc.fillText(icon + val, x + indent, y + valignOffset); | ||
var textWidth = gc.getTextWidth(icon + val); | ||
var minWidth = x + indent + textWidth + 10; | ||
config.minWidth = minWidth; | ||
config.minWidth = x + indent + gc.getTextWidth(icon + val) + 10; | ||
} | ||
@@ -46,0 +38,0 @@ }); |
'use strict'; | ||
var DataModel = require('./DataModel'); | ||
var DataSourceBase = require('datasaur-base'); | ||
/** | ||
* @implements dataModelAPI | ||
* @implements DataModel | ||
* @param {Hypergrid} grid | ||
@@ -12,20 +12,9 @@ * @param {object} [options] | ||
*/ | ||
var HeaderSubgrid = DataModel.extend('HeaderSubgrid', { | ||
initialize: function(grid, options) { | ||
this.behavior = grid.behavior; | ||
var HeaderSubgrid = DataSourceBase.extend('HeaderSubgrid', { | ||
type: 'header', | ||
/** | ||
* @type {dataRowObject} | ||
*/ | ||
this.dataRow = {}; // for meta data (__HEIGHT) | ||
if (options && options.name) { | ||
this.name = options.name; | ||
} | ||
initialize: function(nextDataSource, options) { | ||
this.grid = options.grid; | ||
}, | ||
type: 'header', | ||
format: 'header', // override column format | ||
getRowCount: function() { | ||
@@ -36,3 +25,3 @@ return this.grid.properties.showHeaderRow ? 1 : 0; | ||
getValue: function(x, y) { | ||
var column = this.behavior.getColumn(x); | ||
var column = this.grid.behavior.getColumn(x); | ||
return column.header || column.name; // use field name when header undefined | ||
@@ -43,3 +32,3 @@ }, | ||
if (y < this.getRowCount()) { | ||
this.behavior.getColumn(x).header = value; | ||
this.grid.behavior.getColumn(x).header = value; | ||
} | ||
@@ -46,0 +35,0 @@ }, |
'use strict'; | ||
var Registry = require('../lib/Registry'); | ||
/** | ||
* @namespace | ||
* @classdesc Registry of cell editor constructors. | ||
* @param {object} options | ||
* @constructor | ||
*/ | ||
var dataModels = { | ||
DataModel: require('./DataModel'), | ||
JSON: require('./JSON'), | ||
HeaderSubgrid: require('./HeaderSubgrid') | ||
}; | ||
var DataModels = Registry.extend('DataModels', { | ||
// add and get are non-enumerable | ||
Object.defineProperties(dataModels, { | ||
/** | ||
* @function | ||
* @memberOf dataModels | ||
* @summary Register a data model by name. | ||
*/ | ||
add: { | ||
value: function(name, Constructor) { | ||
this[name] = Constructor; | ||
} | ||
}, | ||
/** | ||
* @function | ||
* @memberOf dataModels | ||
* @summary Lookup a registered data model by name. | ||
*/ | ||
get: { | ||
value: function(name) { | ||
return this[name]; | ||
} | ||
}, | ||
/** | ||
* @type {string[]} | ||
* @memberOf dataModels | ||
* @summary Array of names of registered data models. | ||
*/ | ||
keys: { | ||
get: function() { | ||
return Object.keys(this); | ||
} | ||
BaseClass: require('datasaur-base'), | ||
initialize: function() { | ||
// preregister the standard cell editors | ||
this.add(require('./HeaderSubgrid')); | ||
} | ||
}); | ||
module.exports = dataModels; | ||
module.exports = new DataModels; |
'use strict'; | ||
var version = require('../package.json').version; | ||
var graphics = require('./lib/graphics'); | ||
var HypergridError = require('./lib/error'); | ||
var COLUMN_ONLY_PROPERTY = 'Attempt to set column-only property on a non-column properties object.'; | ||
var warned = {}; | ||
var propClassEnum = { | ||
@@ -17,2 +13,3 @@ COLUMNS: 1, | ||
}; | ||
var propClassLayersMap = { | ||
@@ -23,2 +20,3 @@ DEFAULT: [propClassEnum.COLUMNS, propClassEnum.STRIPES, propClassEnum.ROWS, propClassEnum.CELLS], | ||
/** | ||
@@ -40,9 +38,2 @@ * This module lists the properties that can be set on a {@link Hypergrid} along with their default values. | ||
set name(x) { throw new HypergridError(COLUMN_ONLY_PROPERTY); }, | ||
set type(x) { throw new HypergridError(COLUMN_ONLY_PROPERTY); }, | ||
set header(x) { throw new HypergridError(COLUMN_ONLY_PROPERTY); }, | ||
set calculator(x) { throw new HypergridError(COLUMN_ONLY_PROPERTY); }, | ||
mixIn: require('overrider').mixIn, | ||
/** | ||
@@ -221,3 +212,11 @@ * The default message to display in front of the canvas when there are no grid rows. | ||
/** | ||
* There is no standard format called "header"; unless defined, defaults to "string" (pass-thru formatter). | ||
* @default | ||
* @type {string} | ||
* @memberOf module:defaults | ||
*/ | ||
columnHeaderFormat: 'header', | ||
/********** SECTION: ROW HEADER COLORS **********/ | ||
@@ -375,3 +374,3 @@ | ||
*/ | ||
filterEditor: undefined, | ||
filterEditor: 'TextField', | ||
@@ -435,2 +434,3 @@ /** | ||
/** | ||
* Horizontal alignment of each cell as interpreted by it's cell renderer. | ||
* @default | ||
@@ -471,4 +471,5 @@ * @type {string} | ||
* @summary Name of image to appear at right of cell. | ||
* Must be a key from {@link module:images|images}. | ||
* @desc Used by {@link SimpleCell} cell renderer. | ||
* @desc Must be a key from {@link module:images|images}. | ||
* | ||
* Used by {@link SimpleCell} cell renderer. | ||
* @see {@link module:defaults.centerIcon|centerIcon} | ||
@@ -485,4 +486,5 @@ * @see {@link module:defaults.rightIcon|rightIcon} | ||
* @summary Name of image to appear at right of cell. | ||
* Must be a key from {@link module:images|images}. | ||
* @desc Used by {@link SimpleCell} cell renderer. | ||
* @desc Must be a key from {@link module:images|images}. | ||
* | ||
* Used by {@link SimpleCell} cell renderer. | ||
* @see {@link module:defaults.leftIcon|leftIcon} | ||
@@ -499,4 +501,5 @@ * @see {@link module:defaults.rightIcon|rightIcon} | ||
* @summary Name of image to appear at right of cell. | ||
* Must be a key from {@link module:images|images}. | ||
* @desc Used by {@link SimpleCell} cell renderer. | ||
* @desc Must be a key from {@link module:images|images}. | ||
* | ||
* Used by {@link SimpleCell} cell renderer. | ||
* @see {@link module:defaults.leftIcon|leftIcon} | ||
@@ -520,2 +523,17 @@ * @see {@link module:defaults.centerIcon|centerIcon} | ||
/** | ||
* The name of a transformer function defined in require('synonomous/transformers'). | ||
* | ||
* If the named headerify function is defined, whenever the schema array changes, it is applied each element | ||
* (column schema) for each column that does not already have an explicitly defined `header` property. | ||
* | ||
* When this property does not name a defined headerify function, undefined column headers default to their column names. | ||
* | ||
* @see lib/headerifiers.js | ||
* @default | ||
* @type {string} | ||
* @memberOf module:defaults | ||
*/ | ||
headerify: 'toTitle', | ||
/** | ||
* Enable rendering of horizontal grid lines. | ||
@@ -533,3 +551,3 @@ * @default | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.lineWidth} | ||
* @see {@link module:dynamicProperties.lineWidth lineWidth} | ||
*/ | ||
@@ -543,3 +561,3 @@ gridLinesHWidth: 1, | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.lineColor} | ||
* @see {@link module:dynamicProperties.lineColor lineColor} | ||
*/ | ||
@@ -561,3 +579,3 @@ gridLinesHColor: 'rgb(199, 199, 199)', | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.lineWidth} | ||
* @see {@link module:dynamicProperties.lineWidth lineWidth} | ||
*/ | ||
@@ -571,3 +589,3 @@ gridLinesVWidth: 1, | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.lineColor} | ||
* @see {@link module:dynamicProperties.lineColor lineColor} | ||
*/ | ||
@@ -601,6 +619,12 @@ gridLinesVColor: 'rgb(199, 199, 199)', | ||
/** | ||
* Set canvas's CSS border to this string as well as `gridBorderLeft`, `gridBorderRight`, `gridBorderTop`, and `gridBorderBottom`. | ||
* If set to `true`, uses current `lineWidth` and `lineColor`. | ||
* If set to `false`, uses null. | ||
* Set canvas's CSS border to this string as well as: | ||
* * {@link module:dynamicProperties.gridBorderLeft gridBorderLeft} | ||
* * {@link module:dynamicProperties.gridBorderRight gridBorderRight} | ||
* * {@link module:dynamicProperties.gridBorderTop gridBorderTop} | ||
* * {@link module:dynamicProperties.gridBorderBottom gridBorderBottom}. | ||
* | ||
* If set to: | ||
* `true`: uses current {@link module:dynamicProperties.lineWidth lineWidth} and {@link module:dynamicProperties.lineColor lineColor} | ||
* `false`: uses null | ||
* | ||
* Caveat: The use of `grid.canvas.canvas.style.boxSizing = 'border-box'` is _not_ recommended due to | ||
@@ -617,4 +641,6 @@ * the fact that the canvas is squashed slightly to accommodate the border resulting in blurred text. | ||
* Set canvas's left CSS border to this string. | ||
* If set to `true`, uses current `lineWidth` and `lineColor`. | ||
* If set to `false`, uses null. | ||
* | ||
* If set to: | ||
* * `true`: uses current {@link module:dynamicProperties.lineWidth lineWidth} and {@link module:dynamicProperties.lineColor lineColor} | ||
* * `false`: uses null | ||
* @default | ||
@@ -628,4 +654,6 @@ * @type {boolean|string} | ||
* Set canvas's right CSS border to this string. | ||
* If set to `true`, uses current `lineWidth` and `lineColor`. | ||
* If set to `false`, uses null. | ||
* | ||
* If set to: | ||
* * `true`: uses current {@link module:dynamicProperties.lineWidth lineWidth} and {@link module:dynamicProperties.lineColor lineColor} | ||
* * `false`: uses null | ||
* @default | ||
@@ -639,4 +667,6 @@ * @type {boolean} | ||
* Set canvas's top CSS border to this string. | ||
* If set to `true`, uses current `lineWidth` and `lineColor`. | ||
* If set to `false`, uses null. | ||
* | ||
* If set to: | ||
* * `true`: uses current {@link module:dynamicProperties.lineWidth lineWidth} and {@link module:dynamicProperties.lineColor lineColor} | ||
* * `false`: uses null | ||
* @default | ||
@@ -650,4 +680,6 @@ * @type {boolean} | ||
* Set canvas's bottom CSS border to this string. | ||
* If set to `true`, uses current `lineWidth` and `lineColor`. | ||
* If set to `false`, uses null. | ||
* | ||
* If set to: | ||
* * `true`: uses current {@link module:dynamicProperties.lineWidth lineWidth} and {@link module:dynamicProperties.lineColor lineColor} | ||
* * `false`: uses null | ||
* @default | ||
@@ -660,3 +692,3 @@ * @type {boolean} | ||
/** | ||
* Define this property to style rule lines between non-scrollable rows AND scrollable rows differently from `lineWidth`. | ||
* Define this property to style rule lines between non-scrollable rows and scrollable rows differently from {@link module:defaults.gridLinesHWidth gridLinesHWidth}. | ||
* Undefine it to show normal grid line in that position. | ||
@@ -670,3 +702,5 @@ * @default | ||
/** | ||
* Define this property to render just the edges of the lines between fixed rows & scrollable rows, creating a double-line effect. The value is the thickness of the edges. Typical definition would be `1` in tandem with setting `fixedLinesWidth` to `3`. | ||
* Define this property to render just the edges of the lines between non-scrollable rows & scrollable rows, creating a double-line effect. | ||
* The value is the thickness of the edges. | ||
* Typical definition would be `1` in tandem with setting {@link module:defaults.fixedLinesHWidth fixedLinesHWidth} to `3`. | ||
* @default | ||
@@ -679,3 +713,3 @@ * @type {number} | ||
/** | ||
* Define this property to style rule lines between fixed & scolling rows differently from `lineColor`. | ||
* Define this property to style rule lines between fixed & scolling rows differently from {@link module:defaults.gridLinesHColor}. | ||
* @default | ||
@@ -685,6 +719,6 @@ * @type {cssColor} | ||
*/ | ||
fixedLinesHColor: 'rgb(164,164,164)', // ~21% darker than `lineColor` default | ||
fixedLinesHColor: 'rgb(164,164,164)', // ~21% darker than {@link module:defaults.gridLinesHColor} default | ||
/** | ||
* Define this property to style rule lines between non-scrollable columns AND scrollable columns differently from `lineWidth`. | ||
* Define this property to style rule lines between non-scrollable columns and scrollable columns differently from {@link module:defaults.gridLinesVWidth gridLinesVWidth}. | ||
* Undefine it to show normal grid line in that position. | ||
@@ -698,3 +732,6 @@ * @default | ||
/** | ||
* Define this property to render just the edges of the lines between fixed & scolling columns, creating a double-line effect. The value is the thickness of the edges. Typical definition would be `1` in tandem with setting `fixedLinesWidth` to `3`. | ||
* Define this property to render just the edges of the lines between fixed & scrolling columns, creating a double-line effect. | ||
* The value is the thickness of the edges. | ||
* Typical definition would be `1` in tandem with setting {@link module:defaults.fixedLinesVWidth fixedLinesVWidth} to `3`. | ||
* @see {@link module:defaults.fixedLinesVWidth} | ||
* @default | ||
@@ -707,3 +744,3 @@ * @type {number} | ||
/** | ||
* Define this property to style rule lines between fixed & scolling columns differently from `lineColor`. | ||
* Define this property to style rule lines between fixed & scolling columns differently from {@link module:defaults.gridLinesVColor}. | ||
* @default | ||
@@ -713,3 +750,3 @@ * @type {cssColor} | ||
*/ | ||
fixedLinesVColor: 'rgb(164,164,164)', // ~21% darker than `lineColor` default | ||
fixedLinesVColor: 'rgb(164,164,164)', // ~21% darker than {@link module:defaults.gridLinesVColor} default | ||
@@ -853,40 +890,2 @@ /** | ||
/** | ||
* Returns any value of `keyChar` that passes the following logic test: | ||
* 1. If a non-printable, white-space character, then nav key. | ||
* 2. If not (i.e., a normal character), can still be a nav key if not editing on key down. | ||
* 3. If not, can still be a nav key if CTRL key is down. | ||
* | ||
* Note: Callers are typcially only interested in the following values of `keyChar` and will ignore all others: | ||
* * `'LEFT'` and `'LEFTSHIFT'` | ||
* * `'RIGHT'` and `'RIGHTSHIFT'` | ||
* * `'UP'` and `'UPSHIFT'` | ||
* * `'DOWN'` and `'DOWNSHIFT'` | ||
* | ||
* @param {string} keyChar - A value from Canvas's `charMap`. | ||
* @param {boolean} [ctrlKey=false] - The CTRL key was down. | ||
* @returns {undefined|string} `undefined` means not a nav key; otherwise returns `keyChar`. | ||
* @memberOf module:defaults | ||
*/ | ||
navKey: function(keyChar, ctrlKey) { | ||
var result; | ||
if (keyChar.length > 1 || !this.editOnKeydown || ctrlKey) { | ||
result = keyChar; // return the mapped value | ||
} | ||
return result; | ||
}, | ||
/** | ||
* Returns only values of `keyChar` that, when run through {@link module:defaults.navKeyMap|navKeyMap}, pass the {@link module:defaults.navKey|navKey} logic test. | ||
* | ||
* @param {string} keyChar - A value from Canvas's `charMap`, to be remapped through {@link module:defaults.navKeyMap|navKeyMap}. | ||
* @param {boolean} [ctrlKey=false] - The CTRL key was down. | ||
* @returns {undefined|string} `undefined` means not a nav key; otherwise returns `keyChar`. | ||
* @memberOf module:defaults | ||
*/ | ||
mappedNavKey: function(keyChar, ctrlKey) { | ||
keyChar = this.navKeyMap[keyChar]; | ||
return keyChar && this.navKey(keyChar); | ||
}, | ||
/** @summary Validation failure feedback. | ||
@@ -930,44 +929,3 @@ * @desc Validation occurs on {@link CellEditor#stopEditing}, normally called on commit (`TAB`, `ENTER`, or any other keys listed in `navKeyMap`). | ||
// inherited by cell renderers | ||
/** | ||
* This function is referenced here so it will be available to the renderer and cell renderers. | ||
* @default {@link module:defaults.getTextWidth|getTextWidth} | ||
* @type {function} | ||
* @memberOf module:defaults | ||
*/ | ||
getTextWidth: function(gc, string) { | ||
if (!warned.getTextWidth) { | ||
warned.getTextWidth = true; | ||
console.warn('getTextWidth(gc, string) has been deprecated on the properties (or config) object as of v1.2.4 in favor of the graphics context (aka gc) object and will be removed from the properties object in a future release. Please change your calling context to gc.getTextWidth(string), excluding the first parameter (gc) from your call.'); | ||
} | ||
return graphics.getTextWidth.apply(gc, string); | ||
}, | ||
/** | ||
* This function is referenced here so it will be available to the renderer and cell renderers. | ||
* @default {@link module:defaults.getTextHeight|getTextHeight} | ||
* @type {function} | ||
* @memberOf module:defaults | ||
*/ | ||
getTextHeight: function(font) { | ||
if (!warned.getTextHeight) { | ||
warned.getTextHeight = true; | ||
console.warn('getTextHeight(font) has been deprecated on the properties (or config) object as of v1.2.4 in favor of the graphics context (aka gc) object and will be removed from the properties object in a future release. Please change your calling context to gc.getTextHeight(font).'); | ||
} | ||
return graphics.getTextHeight(font); | ||
}, | ||
/** | ||
* @summary Execute value if "calculator" (function) or if column has calculator. | ||
* @desc This function is referenced here so: | ||
* 1. it will be available to the cell renderers. | ||
* 2. Its context will naturally be the `config` object | ||
* @default {@link module:defaults.exec|exec} | ||
* @type {function} | ||
* @memberOf module:defaults | ||
*/ | ||
exec: exec, | ||
/** | ||
* @default | ||
@@ -990,3 +948,3 @@ * @type {number} | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.showRowNumbers} | ||
* @see {@link module:dynamicProperties.showRowNumbers} | ||
*/ | ||
@@ -999,3 +957,3 @@ rowHeaderNumbers: true, | ||
* @memberOf module:defaults | ||
* @see {@link module:dynamicPropertyDescriptors.showRowNumbers} | ||
* @see {@link module:dynamicProperties.showRowNumbers} | ||
*/ | ||
@@ -1071,2 +1029,14 @@ rowHeaderCheckboxes: true, | ||
/** | ||
* @summary Whether to automatically expand column width to accommodate widest rendered value. | ||
* @desc When truthy for a given column _and_ user has not manually resized it, column will expand to accommodate widest rendered value. | ||
* | ||
* What's actually happening is (`props` in the following refers to the column's properties): | ||
* 1. On each grid render, for all visible columns: | ||
* 1. The cell renderer reports back the width of each rendered cell contents. | ||
* 2. The largest value for each column is saved (in `props.preferredWidth`). | ||
* 2. At the conclusion of the grid render, the renderer calls `grid.gridRenderedNotification`, which calls `grid.behavior.checkColumnAutosizing`, which for all columns for which `props.columnAutosizing` is truthy, determines if the column needs to be widened subject to the following conditions: | ||
* 1. If user has not already manually set column width (`props.columnAutosized` is still falsy) | ||
* 2. If render width > current width (`props.preferredWidths > props.width`) | ||
* 3. If column's max autosizing width is defined and it's greater than render width (`props.peferredWidths < props.columnAutosizingMax`) | ||
* 3. If any column width has changed, re-shape the grid with the new column widths and re-render it. As this typically happens before the next monitor refresh, user only sees the final result. | ||
* @default | ||
@@ -1079,2 +1049,5 @@ * @type {boolean} | ||
/** | ||
* @summary Whether to automatically expand row number column width to accommodate widest rendered row number | ||
* @desc `grid.properties.rowNumberAutosizing` is the backing store for `grid.behavior.columns[-2].columnAutosizing`. | ||
* Supports row number column styling via the `rowNumber_______` grid state properties. | ||
* @default | ||
@@ -1087,2 +1060,5 @@ * @type {boolean} | ||
/** | ||
* @summary Whether to automatically expand row number column width to accommodate widest rendered group label. | ||
* @desc `grid.properties.treeColumnAutosizing` is the backing store for `grid.behavior.columns[-1].columnAutosizing`. | ||
* Supports tree column styling via the `rowColumn_______` grid state properties. | ||
* @default | ||
@@ -1095,2 +1071,6 @@ * @type {boolean} | ||
/** | ||
* @summary The widest the column will be auto-sized to. | ||
* @desc For no limit, set this property to a falsy value such as `undefined` or `0`. | ||
* | ||
* Note this property only specifies a maximum column width for _auto-sizing;_ it places no limit on manual resizing of column width. | ||
* @default | ||
@@ -1100,2 +1080,21 @@ * @type {boolean} | ||
*/ | ||
columnAutosizingMax: 400, | ||
/** | ||
* @summary The widest the tree column will be auto-sized to. | ||
* @desc `grid.properties.treeColumnAutosizingMax` is the store for `grid.behavior.columns[-1].columnAutosizingMax`. | ||
* Supports tree column styling via the `rowColumn_______` grid state properties. | ||
* @default | ||
* @type {boolean} | ||
* @memberOf module:defaults | ||
*/ | ||
treeColumnAutosizingMax: 400, | ||
/** | ||
* @summary Whether text in header cells is wrapped. | ||
* @desc For performance reasons, text in data cells is not wrapped. (This is a function of the supplied `SimpleCell` renderer. Override with a custom renderer if you must have wrapped text in data cells.) | ||
* @default | ||
* @type {boolean} | ||
* @memberOf module:defaults | ||
*/ | ||
headerTextWrapping: false, | ||
@@ -1333,3 +1332,3 @@ | ||
* * `function` - A function to execute to get the URL ready for decorating. The function is passed a single parameter, `cellEvent`, from which you can get the field `name`, `dataRow`, _etc._ | ||
* * `Array` - An array to "apply" to {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open window.open} in its entirety. The first element is interpreted as above for `string` or `function`. | ||
* * `Array` - An array to "apply" to {@link https://developer.mozilla.org/docs/Web/API/Window/open window.open} in its entirety. The first element is interpreted as above for `string` or `function`. | ||
* | ||
@@ -1429,15 +1428,2 @@ * In the case of `string` or `Array`, the link is further unpacked by {@link module:CellClick.openLink|openLink} and then sent to `grid.windowOpen`. | ||
/** @summary Reapply cell properties after `getCell`. | ||
* @type {boolean} | ||
* @default | ||
* @memberOf module:defaults | ||
*/ | ||
set reapplyCellProperties(value) { | ||
if (!warned.reapplyCellProperties) { | ||
console.warn('The `.reapplyCellProperties` property has been deprecated as of v2.1.3 in favor of using the new `.propClassLayers` property. (May be removed in a future version.) This property is now a setter which sets `.propClassLayers` to `.propClassLayersMap.DEFAULT` (grid ← columns ← stripes ← rows ← cells) on truthy or `propClassLayersMap.NO_ROWS` (grid ← columns ← cells) on falsy, which is what you will see on properties stringification. This will give the same effect in most cases as the former property implementation, but not in all cases due to it no longer being applied dynamically. Developers should discontinue use of this property and start specifying `.propClassLayers` instead.'); | ||
warned.reapplyCellProperties = true; | ||
} | ||
this.propClassLayers = value ? propClassLayersMap.NO_ROWS : propClassLayersMap.DEFAULT; | ||
}, | ||
/** @summary Column grab within this number of pixels from top of cell. | ||
@@ -1490,4 +1476,2 @@ * @type {number} | ||
// for Renderer.prototype.assignProps | ||
propClassEnum: propClassEnum, | ||
propClassLayersMap: propClassLayersMap, | ||
propClassLayers: propClassLayersMap.DEFAULT, | ||
@@ -1543,6 +1527,8 @@ | ||
var warned = {}; | ||
function rowPropertiesDeprecationWarning() { | ||
if (!warned.rowProperties) { | ||
warned.rowProperties = true; | ||
console.warn('The `rowProperties` property has been deprecated as of v3.0.0 in favor of `rowStripes`. (Will be removed in a future release.)'); | ||
console.warn('The `rowProperties` property has been deprecated as of v2.1.0 in favor of `rowStripes`. (Will be removed in a future release.)'); | ||
} | ||
@@ -1564,10 +1550,96 @@ } | ||
function columnOnlyError() { | ||
throw new HypergridError('Attempt to set/get column-only property on a non-column properties object.'); | ||
} | ||
['name', 'type', 'header', 'calculator'].forEach(function(key) { | ||
Object.defineProperty(defaults, key, { | ||
set: columnOnlyError | ||
}); | ||
}); | ||
/** @typedef {string} cssColor | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/color_value | ||
* @see https://developer.mozilla.org/docs/Web/CSS/color_value | ||
*/ | ||
/** @typedef {string} cssFont | ||
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/font | ||
* @see https://developer.mozilla.org/docs/Web/CSS/font | ||
*/ | ||
/** | ||
* Returns any value of `keyChar` that passes the following logic test: | ||
* 1. If a non-printable, white-space character, then nav key. | ||
* 2. If not (i.e., a normal character), can still be a nav key if not editing on key down. | ||
* 3. If not, can still be a nav key if CTRL key is down. | ||
* | ||
* Note: Callers are typcially only interested in the following values of `keyChar` and will ignore all others: | ||
* * `'LEFT'` and `'LEFTSHIFT'` | ||
* * `'RIGHT'` and `'RIGHTSHIFT'` | ||
* * `'UP'` and `'UPSHIFT'` | ||
* * `'DOWN'` and `'DOWNSHIFT'` | ||
* | ||
* @param {string} keyChar - A value from Canvas's `charMap`. | ||
* @param {boolean} [ctrlKey=false] - The CTRL key was down. | ||
* @returns {undefined|string} `undefined` means not a nav key; otherwise returns `keyChar`. | ||
* @memberOf module:defaults | ||
*/ | ||
function navKey(keyChar, ctrlKey) { | ||
var result; | ||
if (keyChar.length > 1 || !this.editOnKeydown || ctrlKey) { | ||
result = keyChar; // return the mapped value | ||
} | ||
return result; | ||
} | ||
/** | ||
* Returns only values of `keyChar` that, when run through {@link module:defaults.navKeyMap|navKeyMap}, pass the {@link module:defaults.navKey|navKey} logic test. | ||
* | ||
* @param {string} keyChar - A value from Canvas's `charMap`, to be remapped through {@link module:defaults.navKeyMap|navKeyMap}. | ||
* @param {boolean} [ctrlKey=false] - The CTRL key was down. | ||
* @returns {undefined|string} `undefined` means not a nav key; otherwise returns `keyChar`. | ||
* @memberOf module:defaults | ||
*/ | ||
function mappedNavKey(keyChar, ctrlKey) { | ||
keyChar = this.navKeyMap[keyChar]; | ||
return keyChar && this.navKey(keyChar); | ||
} | ||
/** @summary Reapply cell properties after `getCell`. | ||
* @type {boolean} | ||
* @default | ||
* @memberOf module:defaults | ||
*/ | ||
function reapplyCellProperties(value) { | ||
if (!warned.reapplyCellProperties) { | ||
console.warn('The `.reapplyCellProperties` property has been deprecated as of v2.1.3 in favor of using the new `.propClassLayers` property. (May be removed in a future release.) This property is now a setter which sets `.propClassLayers` to `.propClassLayersMap.DEFAULT` (grid ← columns ← stripes ← rows ← cells) on truthy or `propClassLayersMap.NO_ROWS` (grid ← columns ← cells) on falsy, which is what you will see on properties stringification. This will give the same effect in most cases as the former property implementation, but not in all cases due to it no longer being applied dynamically. Developers should discontinue use of this property and start specifying `.propClassLayers` instead.'); | ||
warned.reapplyCellProperties = true; | ||
} | ||
this.propClassLayers = value ? propClassLayersMap.NO_ROWS : propClassLayersMap.DEFAULT; | ||
} | ||
function deleteProp(propName) { | ||
var descriptor = Object.getOwnPropertyDescriptor(this, propName); | ||
if (!descriptor) { | ||
return false; // own property not found | ||
} else if (!descriptor.get) { | ||
return delete this[propName]; // non-accessor property found (returns !descriptor.configurable) | ||
} else if (descriptor.get.toString().indexOf('.var.')) { | ||
this.var[propName] = Object.getPrototypeOf(this)[propName]; | ||
} else { | ||
return true; // property not deletable | ||
} | ||
this.grid.repaint(); | ||
return false; // delete was successful | ||
} | ||
/** | ||
* @summary Execute value if "calculator" (function) or if column has calculator. | ||
* @desc This function is referenced here so: | ||
* 1. It will be available to the cell renderers | ||
* 2. Its context will naturally be the `config` object | ||
* @default {@link module:defaults.exec|exec} | ||
* @method | ||
* @param vf - Value or function. | ||
* @memberOf module:defaults | ||
*/ | ||
function exec(vf) { | ||
@@ -1577,3 +1649,3 @@ if (this.dataRow) { | ||
if (calculator) { | ||
vf = calculator(this.dataRow, this.name); | ||
vf = calculator(this.dataRow, this.name, this.subrow); | ||
} | ||
@@ -1584,2 +1656,14 @@ } | ||
// Add "utility" props so they will be available wherever props are available but make them non-enumerable because they are not real props. | ||
Object.defineProperties(defaults, { | ||
mixIn: { value: require('overrider').mixIn }, | ||
delete: { value: deleteProp }, | ||
propClassEnum: { value: propClassEnum }, | ||
propClassLayersMap: { value: propClassLayersMap }, | ||
navKey: { value: navKey }, | ||
mappedNavKey: { value: mappedNavKey }, | ||
reapplyCellProperties: { set: reapplyCellProperties }, | ||
exec: { value: exec } | ||
}); | ||
module.exports = defaults; |
@@ -13,3 +13,3 @@ 'use strict'; | ||
* The pixel location of the mouse pointer during a drag operation. | ||
* @type {window.fin.rectangular.Point} | ||
* @type {Point} | ||
* @memberOf CellSelection.prototype | ||
@@ -16,0 +16,0 @@ */ |
@@ -13,3 +13,3 @@ 'use strict'; | ||
* The pixel location of the mouse pointer during a drag operation. | ||
* @type {window.fin.rectangular.Point} | ||
* @type {Point} | ||
* @default null | ||
@@ -16,0 +16,0 @@ * @memberOf ColumnSelection.prototype |
@@ -251,12 +251,2 @@ 'use strict'; | ||
*/ | ||
isFixedRow: function(grid, event) { | ||
this.deprecated('isFixedRow', 'isFixedRow(grid, event) has been deprecated as of v1.2.0 in favor of event.isRowFixed. (Will be removed in a future version.)'); | ||
return event.isRowFixed; | ||
}, | ||
/** | ||
* @memberOf Feature.prototype | ||
* @param {Hypergrid} grid | ||
* @param {Object} event - the event details | ||
*/ | ||
isFirstFixedRow: function(grid, event) { | ||
@@ -271,12 +261,2 @@ return event.gridCell.y < 1; | ||
*/ | ||
isFixedColumn: function(grid, event) { | ||
this.deprecated('isFixedColumn', 'isFixedColumn(grid, event) has been deprecated as of v1.2.0 in favor of event.isColumnFixed. (Will be removed in a future version.)'); | ||
return event.isColumnFixed; | ||
}, | ||
/** | ||
* @memberOf Feature.prototype | ||
* @param {Hypergrid} grid | ||
* @param {Object} event - the event details | ||
*/ | ||
isFirstFixedColumn: function(grid, event) { | ||
@@ -290,12 +270,2 @@ return event.gridCell.x === 0; | ||
* @param {Object} event - the event details | ||
*/ | ||
isTopLeft: function(grid, event) { | ||
this.deprecated('isTopLeft', 'isTopLeft(grid, event) has been deprecated as of v1.2.0 in favor of event.isCellFixed. (Will be removed in a future version.)'); | ||
return event.isCellFixed; | ||
}, | ||
/** | ||
* @memberOf Feature.prototype | ||
* @param {Hypergrid} grid | ||
* @param {Object} event - the event details | ||
* @private | ||
@@ -329,5 +299,2 @@ * @comment Not really private but was cluttering up all the feature doc pages. | ||
Feature.abstract = true; // don't instantiate directly | ||
module.exports = Feature; |
'use strict'; | ||
var deprecated = require('./deprecated'); | ||
var WritablePoint = require('./WritablePoint'); | ||
var writableDescriptor = { writable: true }; | ||
var eumerableDescriptor = { writable: true, enumerable: true }; | ||
// The nullSubgrid is for CellEvents representing clicks below last row. | ||
// var nullSubgrid = {}; | ||
factory.cellEventProperties = Object.defineProperties({}, { | ||
var cellEventProperties = Object.defineProperties({}, { // all props non-enumerable | ||
/** | ||
@@ -60,6 +51,4 @@ * The raw value of the cell, unformatted. | ||
cp = this.column.properties; | ||
if (this.isHandleColumn){ | ||
cp = cp.rowHeader; | ||
} else if (this.isTreeColumn) { | ||
cp = cp.treeHeader; | ||
if (!this.isDataColumn) { | ||
// cp already set to cp.rowHeader or cp.treeHeader | ||
} else if (this.isDataRow) { | ||
@@ -146,5 +135,5 @@ // cp already set to basic props | ||
// partial render support | ||
this.snapshot = undefined; | ||
this.snapshot = []; | ||
this.minWidth = undefined; | ||
this.disabled = undefined; | ||
// this.disabled = undefined; | ||
@@ -206,3 +195,3 @@ this.visibleColumn = visibleColumn; | ||
* @param {number} dataY - Vertical data cell coordinate. | ||
* @param {dataModelAPI} [subgrid=this.behavior.subgrids.data] | ||
* @param {DataModel} [subgrid=this.behavior.subgrids.data] | ||
* @returns {boolean} Visibility. | ||
@@ -226,3 +215,3 @@ * @method | ||
* @param {number} dataY - Vertical data cell coordinate. | ||
* @param {dataModelAPI} [subgrid=this.behavior.subgrids.data] | ||
* @param {DataModel} [subgrid=this.behavior.dataModel] | ||
* @param {boolean} [useAllCells] - Search in all rows and columns instead of only rendered ones. | ||
@@ -245,3 +234,3 @@ * @returns {boolean} Visibility. | ||
vr = { | ||
subgrid: subgrid || this.behavior.subgrids.lookup.data, | ||
subgrid: subgrid || this.behavior.dataModel, | ||
rowIndex: dataY | ||
@@ -455,19 +444,22 @@ }; | ||
$$CLASS_NAME: { value: 'CellEvent' }, | ||
deprecated: { value: deprecated }, | ||
isGridRow: { get: function() { | ||
this.deprecated('isGridRow', '.isGridRow is deprecated as of v1.2.10 in favor of .isDataRow. (Will be removed in a future release.)'); | ||
return this.isDataRow; | ||
} }, | ||
isGridColumn: { get: function() { | ||
this.deprecated('isGridColumn', '.isGridColumn is deprecated as of v1.2.10 in favor of .isDataColumn. (Will be removed in a future release.)'); | ||
return this.isDataColumn; | ||
} }, | ||
isGridCell: { get: function() { | ||
this.deprecated('isGridCell', '.isGridCell is deprecated as of v1.2.10 in favor of .isDataCell. (Will be removed in a future release.)'); | ||
return this.isDataCell; | ||
} }, | ||
$$CLASS_NAME: { value: 'CellEvent' } | ||
}); | ||
var Point = require('rectangular').Point; | ||
/** | ||
* Variation of `rectangular.Point` but with writable `x` and `y` | ||
* @constructor | ||
*/ | ||
function WritablePoint(x, y) { | ||
// skip x and y initialization here for performance | ||
// because typically reset after instantiation | ||
} | ||
WritablePoint.prototype = Point.prototype; | ||
var writableDescriptor = { writable: true }; | ||
var enumerableDescriptor = { writable: true, enumerable: true }; | ||
/** @typedef {WritablePoint} dataCellCoords | ||
@@ -512,3 +504,3 @@ * @property {number} x - The data model's column index, unaffected by column scrolling; _i.e.,_ | ||
* * Includes `this.column` defined by constructor (as enumerable). | ||
* * Excludes `this.gridCell`, `this.dataCell`, `this.visibleRow.subgrid` defined by constructor (as non-enumerable). | ||
* * Excludes all other properties defined by constructor and prototype, all of which are non-enumerable. | ||
* * Any additional (enumerable) members mixed in by application's `getCellEditorAt` override. | ||
@@ -545,3 +537,3 @@ * | ||
* @name subgrid | ||
* @type {dataModelAPI} | ||
* @type {DataModel} | ||
* @memberOf CellEvent# | ||
@@ -553,6 +545,3 @@ */ | ||
* @name gridCell | ||
* @property {number} x - The active column index, adjusted for column scrolling after fixed columns; _i.e.,_ | ||
* an index suitable for dereferencing the column object to which the cell belongs via {@link Behavior#getActiveColumn}. | ||
* @property {number} y - The vertical grid coordinate, unaffected by subgrid, row scrolling, and fixed rows. | ||
* @type {WritablePoint} | ||
* @type {gridCellCoords} | ||
* @memberOf CellEvent# | ||
@@ -566,6 +555,3 @@ */ | ||
* @name dataCell | ||
* @property {number} x - The data model's column index, unaffected by column scrolling; _i.e.,_ | ||
* an index suitable for dereferencing the column object to which the cell belongs via {@link Behavior#getColumn}. | ||
* @property {number} y - The data model's row index, adjusted for data row scrolling after fixed rows. | ||
* @type {WritablePoint} | ||
* @type {dataCellCoords} | ||
* @memberOf CellEvent# | ||
@@ -580,3 +566,3 @@ */ | ||
* | ||
* Enumerable so it will be copied to cell event on CellEvent.prototype.initialize. | ||
* This property is enumerable so that it will be copied to cell editor on {@link CellEditor} instantiation. | ||
* @name column | ||
@@ -586,3 +572,3 @@ * @type {Column} | ||
*/ | ||
column: eumerableDescriptor, | ||
column: enumerableDescriptor, | ||
@@ -605,3 +591,3 @@ // getter caches | ||
CellEvent.prototype = Object.create(factory.cellEventProperties, { | ||
CellEvent.prototype = Object.create(cellEventProperties, { | ||
constructor: { value: CellEvent }, | ||
@@ -608,0 +594,0 @@ grid: { value: grid }, |
@@ -21,3 +21,3 @@ 'use strict'; | ||
* * **object:** When theme name is not registered. | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -55,3 +55,3 @@ theme: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -73,3 +73,3 @@ subgrids: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -91,3 +91,3 @@ features: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -106,3 +106,3 @@ gridRenderer: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -123,3 +123,3 @@ columnIndexes: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -140,3 +140,3 @@ columnNames: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -155,3 +155,3 @@ rows: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -170,3 +170,3 @@ columns: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -185,3 +185,3 @@ cells: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -200,3 +200,3 @@ rowHeaderCheckboxes: { | ||
/** | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -216,3 +216,3 @@ rowHeaderNumbers: { | ||
* Legacy property; now points to both `rowHeaderFeatures` props. | ||
* @memberOf module:dynamicPropertyDescriptors | ||
* @memberOf module:dynamicProperties | ||
*/ | ||
@@ -276,3 +276,3 @@ showRowNumbers: { | ||
/** | ||
* @name module:dynamicPropertyDescriptors.columnProperties | ||
* @name module:dynamicProperties.columnProperties | ||
*/ | ||
@@ -279,0 +279,0 @@ dynamicPropertyDescriptors.columnProperties = dynamicPropertyDescriptors.columns; |
'use strict'; | ||
/** | ||
* @name fields | ||
* @module | ||
* @module fields | ||
*/ | ||
var Decorator = require('synonomous'); | ||
var REGEXP_META_PREFIX = /^__/; // starts with double underscore | ||
/** | ||
* @param {object} hash | ||
* @returns {string[]} Member names from `hash` that do _not_ begin with double-underscore. | ||
* @memberOf module:fields | ||
*/ | ||
exports.getFieldNames = function(hash) { | ||
return Object.keys(hash || []).filter(function(fieldName) { | ||
return !REGEXP_META_PREFIX.test(fieldName); | ||
}); | ||
}; | ||
var fields = { | ||
exports.titleize = require('synonomous/transformers').toTitle; | ||
/** | ||
* Decorate given grid schema with: | ||
* * Synonym(s) based on `name` property of each element: | ||
* @param {columnSchema[]} schema | ||
* @returns {columnSchema[]} The given schema. | ||
* @memberOf module:fields | ||
*/ | ||
decorateSchema: function(schema) { | ||
var decorator = new Decorator; | ||
exports.getSchema = function(data){ | ||
return exports.getFieldNames(data && data[0] || {}).map(function(name) { | ||
return { name: name, header: exports.titleize(name) }; | ||
}); | ||
decorator.decorateArray(schema); | ||
return schema; | ||
}, | ||
/** | ||
* Decorate each element of schema with: | ||
* * `header` property (when undefined) | ||
* @param {columnSchema[]} schema | ||
* @param {string} [headerifierName] - Name of string transformer to use to generate headers (from column names) for those columns without defined headers. If omitted or undefined, no decoration takes place. | ||
* @returns {columnSchema[]} The given schema. | ||
* @memberOf module:fields | ||
*/ | ||
decorateColumnSchema: function(schema, headerifierName) { | ||
var decorator = new Decorator; | ||
decorator.transformations = {}; | ||
decorator.transformations[headerifierName] = 'header'; | ||
decorator.decorateArray(schema); | ||
return schema; | ||
}, | ||
/** | ||
* @summary Normalizes and returns given schema array. | ||
* @desc For each "column schema" (element of schema array): | ||
* | ||
* 1. Objectify column schemata<br> | ||
* Ensures each column schema is an object with a `name` property. | ||
* 2. Index schema schemata<br> | ||
* Adds an `index` property to each column schema element. | ||
* 3. Decorates schema<br> | ||
* Decorates the schema array object itself with column names and column name synonyms. This is helpful for looking up column schema by column name rather than by index. To get the index of a column when you know the name: | ||
* ```javascript | ||
* var schema = dataModel.getSchema(); | ||
* var columnName = 'foo'; | ||
* var columnIndex = schema[columnName].index; | ||
* ``` | ||
* 4. Adds missing headers. | ||
* | ||
* This function is safe to call repeatedly. | ||
* | ||
* Called from {@link Behavior#createColumns createColumns} (called on receipt of the `fin-hypergrid-schema-loaded` event (dispatched by data model implementation of `setSchema`)). | ||
* | ||
* @param {rawColumnSchema[]} schema | ||
* @returns {columnSchema[]} | ||
* @memberOf module:fields | ||
*/ | ||
normalizeSchema: function(schema) { | ||
// Make sure each element of `schema` is an object with a `name` property. | ||
schema.forEach(function(columnSchema, index) { | ||
if (typeof columnSchema === 'string') { | ||
schema[index] = { | ||
name: columnSchema | ||
}; | ||
} | ||
}); | ||
// Remove all meta data columns from schema | ||
for (var i = schema.length; i--;) { | ||
if (REGEXP_META_PREFIX.test(schema[i].name)) { | ||
schema.splice(i, 1); | ||
} | ||
} | ||
// Set `index` property. | ||
schema.forEach(function(columnSchema, index) { | ||
columnSchema.index = index; | ||
}); | ||
return schema; | ||
}, | ||
/** | ||
* @summary Get keys of given hash with "metakeys" filtered out. | ||
* @desc Metakeys are keys beginning with a double-underscore. | ||
* | ||
* DO NOT REMOVE -- Not used in fin-hypergrid/core but has legacy exposure. | ||
* @param {object} hash | ||
* @returns {string[]} Member names from `hash` that do _not_ begin with double-underscore. | ||
* @memberOf module:fields | ||
*/ | ||
getFieldNames: function(hash) { | ||
return Object.keys(hash || {}).filter(function(fieldName) { | ||
return !REGEXP_META_PREFIX.test(fieldName); | ||
}); | ||
}, | ||
/** | ||
* Used by {@link module:fields.getSchema getSchema}. | ||
* Override as needed for different titleization flavor. | ||
* @param {string} key | ||
* @returns {string} Title version of key (for use as column header). | ||
* @memberOf module:fields | ||
*/ | ||
titleize: require('synonomous/transformers').toTitle, | ||
/** | ||
* @summary Returns a schema derived from given sample data row with "metakeys" filtered out. | ||
* @desc Metakeys are keys beginning with a double-underscore. | ||
* | ||
* DO NOT REMOVE -- Not used in fin-hypergrid/core but has legacy exposure. | ||
* @param {dataRowObject[]} [data] | ||
* @returns {columnSchema[]} Array object also decroated with synonyms for elements. | ||
* @memberOf module:fields | ||
*/ | ||
getSchema: function(data) { | ||
var dataRow = data && data[0] || {}, | ||
schema = fields.getFieldNames(dataRow); | ||
fields.normalizeSchema(schema); | ||
fields.decorateSchema(schema); | ||
fields.decorateColumnSchema(schema, 'toTitle'); | ||
return schema; | ||
} | ||
}; | ||
module.exports = fields; |
@@ -71,3 +71,3 @@ /* eslint-env browser */ | ||
* @param {number} width - Width of target cell; overflow point. | ||
* @param {boolean|null|undefined} truncateTextWithEllipsis - See {@link module:defaults.truncateTextWithEllipsis}. | ||
* @param {boolean|null|undefined} truncateTextWithEllipsis - _Per {@link module:defaults.truncateTextWithEllipsis}._ | ||
* @param {boolean} [abort=false] - Abort measuring upon overflow. Returned `width` sum will reflect truncated string rather than untruncated string. Note that returned `string` is truncated in either case. | ||
@@ -74,0 +74,0 @@ * @returns {{string:string,width:number}} |
@@ -10,3 +10,2 @@ /* eslint-env browser */ | ||
var Base = require('../Base'); | ||
var deprecated = require('./deprecated'); | ||
@@ -381,3 +380,2 @@ | ||
$$CLASS_NAME: 'Localization', | ||
deprecated: deprecated, | ||
@@ -437,6 +435,2 @@ /** @summary Creates a localizer from a localizer factory object using the default locale. | ||
set: function(name) { | ||
return this.deprecated('set(name, localizer)', 'add(name, localizer)', '1.0.6', arguments); | ||
}, | ||
/** | ||
@@ -443,0 +437,0 @@ * |
@@ -13,3 +13,3 @@ 'use strict'; | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign#Polyfill | ||
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/sign#Polyfill | ||
// (Safari now supports Math.sign but IE still does not as of v11.) | ||
@@ -24,3 +24,3 @@ Math.sign = Math.sign = function(x) { | ||
// Lite version of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Polyfill | ||
// Lite version of: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Polyfill | ||
if (typeof Array.prototype.findIndex !== 'function') { | ||
@@ -38,3 +38,3 @@ Array.prototype.findIndex = function(predicate) { | ||
// Simpler version of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill#Polyfill | ||
// Simpler version of: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/fill#Polyfill | ||
if (typeof Array.prototype.fill !== 'function') { | ||
@@ -51,3 +51,3 @@ Array.prototype.fill = function(value, start, end) { | ||
// Lite version of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill | ||
// Lite version of: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill | ||
if (typeof Object.assign !== 'function') { | ||
@@ -54,0 +54,0 @@ Object.assign = function(target) { |
@@ -7,2 +7,3 @@ 'use strict'; | ||
/** | ||
@@ -486,3 +487,3 @@ * | ||
var top = selection.origin.y; | ||
var size = selection.extent.y + 1; | ||
var size = selection.height; | ||
for (var r = 0; r < size; r++) { | ||
@@ -489,0 +490,0 @@ var ti = r + top; |
@@ -8,3 +8,3 @@ 'use strict'; | ||
* | ||
* Paints all the cells of a grid, one row at a time. | ||
* Partial render is supported only by those cells whose cell renderer supports it by returning before rendering (based on `config.snapshot`). | ||
* | ||
@@ -15,8 +15,6 @@ * #### On reset | ||
* | ||
* #### On the next call (afer reset) | ||
* #### On the next call (after reset) | ||
* | ||
* First, a background rect is drawn using the grid background color. | ||
* Each cell is drawn redrawn only when its appearance changes. This determination is made by the cell renderer by comparing with (and maintaining) `config.snapshot`. See {@link SimpleCell} for a sample implementation. | ||
* | ||
* Then, each cell is drawn. If its background differs from the grid background, the background is repainted. | ||
* | ||
* `try...catch` surrounds each cell paint in case a cell renderer throws an error. | ||
@@ -74,2 +72,3 @@ * The error message is error-logged to console AND displayed in cell. | ||
try { | ||
// Partial render signaled by calling `_paintCell` with undefined 3rd param (formal `prefillColor`). | ||
preferredWidth = Math.max(preferredWidth, this._paintCell(gc, pool[p])); | ||
@@ -84,3 +83,3 @@ } catch (e) { | ||
cellEvent.column.properties.preferredWidth = Math.round(preferredWidth); | ||
}.bind(this)); | ||
}, this); | ||
@@ -87,0 +86,0 @@ // gc.clipRestore(clipToGrid); |
@@ -96,3 +96,3 @@ 'use strict'; | ||
for (preferredWidth = r = 0; r < R; r++, p++) { | ||
if (!pool[p].disabled) { | ||
// if (!pool[p].disabled) { | ||
if (rowPrefillColors) { | ||
@@ -107,3 +107,3 @@ prefillColor = rowPrefillColors[r]; | ||
} | ||
} | ||
// } | ||
} | ||
@@ -114,3 +114,3 @@ | ||
cellEvent.column.properties.preferredWidth = Math.round(preferredWidth); | ||
}.bind(this)); | ||
}, this); | ||
@@ -117,0 +117,0 @@ // gc.clipRestore(clipToGrid); |
@@ -80,3 +80,3 @@ 'use strict'; | ||
cellEvent.column.properties.preferredWidth = Math.round(preferredWidth); | ||
}.bind(this)); | ||
}, this); | ||
@@ -83,0 +83,0 @@ // gc.clipRestore(clipToGrid); |
@@ -100,3 +100,3 @@ 'use strict'; | ||
cellEvent.column.properties.preferredWidth = Math.round(preferredWidth); | ||
}.bind(this)); | ||
}, this); | ||
@@ -103,0 +103,0 @@ // gc.clipRestore(clipToGrid); |
@@ -94,3 +94,3 @@ 'use strict'; | ||
gc.clipRestore(columnClip); | ||
}.bind(this)); | ||
}, this); | ||
} | ||
@@ -97,0 +97,0 @@ |
@@ -11,41 +11,2 @@ /* eslint-env browser */ | ||
var visibleColumnPropertiesDescriptorFn = function(grid) { | ||
return { | ||
findWithNeg: { | ||
// Like the Array.prototype version except searches the negative indexes as well. | ||
value: function(iteratee, context) { | ||
for (var i = grid.behavior.leftMostColIndex; i < 0; i++) { | ||
if (!this[i]) { | ||
continue; | ||
} | ||
if (iteratee.call(context, this[i], i, this)) { | ||
return this[i]; | ||
} | ||
} | ||
return Array.prototype.find.call(this, iteratee, context); | ||
} | ||
}, | ||
forEachWithNeg: { | ||
// Like the Array.prototype version except it iterates the negative indexes as well. | ||
value: function(iteratee, context) { | ||
for (var i = grid.behavior.leftMostColIndex; i < 0; i++) { | ||
if (!this[i]) { | ||
continue; | ||
} | ||
iteratee.call(context, this[i], i, this); | ||
} | ||
return Array.prototype.forEach.call(this, iteratee, context); | ||
} | ||
}, | ||
totalLength: { | ||
get: function() { | ||
return Math.abs(grid.behavior.leftMostColIndex) + this.length; | ||
} | ||
} | ||
}; | ||
}; | ||
/** | ||
@@ -62,3 +23,3 @@ * @summary List of grid renderers available to new grid instances. | ||
/** @typedef {object} CanvasRenderingContext2D | ||
* @see [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) | ||
* @see [CanvasRenderingContext2D](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D) | ||
*/ | ||
@@ -77,3 +38,3 @@ | ||
* @property {number} rowIndex - Local vertical row coordinate within the subgrid to which the row belongs, adjusted for scrolling. | ||
* @property {dataModelAPI} subgrid - A reference to the subgrid to which the row belongs. | ||
* @property {DataModel} subgrid - A reference to the subgrid to which the row belongs. | ||
* @property {number} top - Pixel coordinate of the top edge of this row, rounded to nearest integer. | ||
@@ -137,3 +98,3 @@ * @property {number} bottom - Pixel coordinate of the bottom edge of this row, rounded to nearest integer. | ||
*/ | ||
this.visibleColumns = Object.defineProperties([], visibleColumnPropertiesDescriptorFn(this.grid)); | ||
this.visibleColumns = this.grid.decorateColumnArray(); | ||
@@ -234,14 +195,3 @@ /** | ||
/** | ||
* Previously used by fin-canvas. | ||
* @memberOf Renderer.prototype | ||
* @returns {Object} a property value at a key, delegates to the grid | ||
* @deprecated | ||
*/ | ||
resolveProperty: function(key) { | ||
this.deprecated('resolveProperty', 'The .resolveProperty(key) method is deprecated as of v1.2.10 in favor of the .grid.properties object dereferenced with [key]. (Will be removed in a future release.)'); | ||
return this.properties[key]; | ||
}, | ||
/** | ||
* @memberOf Renderer.prototype | ||
* @summary Notify the fin-hypergrid every time we've repainted. | ||
@@ -277,11 +227,2 @@ * @desc This is the entry point from fin-canvas. | ||
* @memberOf Renderer.prototype | ||
* @returns {number[]} Rows we just rendered. | ||
*/ | ||
getVisibleRows: function() { | ||
this.deprecated('getVisibleRows', 'The getVisibleRows() method has been deprecated as of v1.2.0. (Will be removed in a future version.) Previously returned the this.visibleRows array but because this.visibleRows is no longer a simple array of integers but is now an array of objects, it now returns an array mapped to this.visibleRows[*].rowIndex. Note however that this mapping is not equivalent to what this method previously returned because while each object\'s .rowIndex property is still adjusted for scrolling within the data subgrid, the index is now local to (zero-based within) each subgrid'); | ||
return this.visibleRows.map(function(vr) { return vr.rowIndex; }); | ||
}, | ||
/** | ||
* @memberOf Renderer.prototype | ||
* @returns {number} Number of columns we just rendered. | ||
@@ -295,11 +236,2 @@ */ | ||
* @memberOf Renderer.prototype | ||
* @returns {number} Columns we just rendered. | ||
*/ | ||
getVisibleColumns: function() { | ||
this.deprecated('visibleColumns', 'The getVisibleColumns() method has been deprecated as of v1.2.0. (Will be removed in a future version.) Previously returned the this.visibleColumns but because this.visibleColumns is no longer a simple array of integers but is now an array of objects, it now returns an array mapped to the equivalent visibleColumns[*].columnIndex.'); | ||
return this.visibleColumns.map(function(vc) { return vc.columnIndex; }); | ||
}, | ||
/** | ||
* @memberOf Renderer.prototype | ||
* @param {CellEvent|number} x - CellEvent object or grid column coordinate. | ||
@@ -383,3 +315,5 @@ * @param {number} [y] - Grid row coordinate. Omit if `xOrCellEvent` is a CellEvent. | ||
result.cellEvent = Object.create(this.findCell(new this.grid.behavior.CellEvent(vc.columnIndex, vr.index))); | ||
var cellEvent = new this.grid.behavior.CellEvent(vc.columnIndex, vr.index), | ||
cellEventFromPool = this.findCell(cellEvent); | ||
result.cellEvent = cellEventFromPool ? Object.create(cellEventFromPool) : cellEvent; | ||
result.cellEvent.mousePoint = this.grid.newPoint(x - vc.left, y - vr.top); | ||
@@ -396,2 +330,19 @@ | ||
/** | ||
* Matrix of unformatted values of visible cells. | ||
* @returns {Array<Array>} | ||
*/ | ||
getVisibleCellMatrix: function() { | ||
var rows = Array(this.visibleRows.length); | ||
var adjust = this.grid.behavior.hasTreeColumn() ? 1 : 0; | ||
for (var y = 0; y < rows.length; ++y) { rows[y] = Array(this.visibleColumns.length); } | ||
this.cellEventPool.forEach(function(cell) { | ||
var x = cell.gridCell.x + adjust; | ||
if (x >= 0) { | ||
rows[cell.gridCell.y][x] = cell.value; | ||
} | ||
}); | ||
return rows; | ||
}, | ||
/** | ||
* @summary Get the visibility of the column matching the provided grid column index. | ||
@@ -548,3 +499,3 @@ * @desc Requested column may not be visible due to being scrolled out of view. | ||
* @param {number} rowIndex - The data row index. | ||
* @param {dataModelAPI} [subgrid=this.behavior.subgrids.data] | ||
* @param {DataModel} [subgrid=this.behavior.subgrids.data] | ||
* @returns {boolean} The given row is visible. | ||
@@ -562,7 +513,7 @@ */ | ||
* @param {number} rowIndex - The data row index within the given subgrid. | ||
* @param {dataModelAPI} [subgrid=this.behavior.subgrids.data] | ||
* @param {DataModel} [subgrid=this.behavior.subgrids.data] | ||
* @returns {object|undefined} The given row if visible or `undefined` if not. | ||
*/ | ||
getVisibleDataRow: function(rowIndex, subgrid) { | ||
subgrid = subgrid || this.grid.behavior.subgrids.lookup.data; | ||
subgrid = subgrid || this.grid.behavior.dataModel; | ||
return this.visibleRows.find(function(vr) { | ||
@@ -587,10 +538,14 @@ return vr.subgrid === subgrid && vr.rowIndex === rowIndex; | ||
* @desc This is the main forking of the renderering task. | ||
* | ||
* `dataModel.fetchData` callback renders the grid. Note however that this is not critical when the clock is | ||
* running as it will be rendered on the next tick. We let it call it anyway in case (1) fetch returns quickly | ||
* enough to be rendered on this tick rather than next or (2) clock isn't running (for debugging purposes). | ||
* @param {CanvasRenderingContext2D} gc | ||
*/ | ||
renderGrid: function(gc) { | ||
this.grid.deferredBehaviorChange(); | ||
var grid = this.grid; | ||
gc.beginPath(); | ||
grid.deferredBehaviorChange(); | ||
var rowCount = this.grid.getRowCount(); | ||
var rowCount = grid.getRowCount(); | ||
if (rowCount !== this.lastKnowRowCount) { | ||
@@ -608,11 +563,13 @@ var newWidth = resetRowHeaderColumnWidth.call(this, gc, rowCount); | ||
this.needsComputeCellsBounds = false; | ||
// Pre-fetch data if supported by data model | ||
if (grid.behavior.dataModel.fetchData) { | ||
grid.behavior.dataModel.fetchData(getSubrects.call(this), fetchCompletion.bind(this, gc)); | ||
return; // skip refresh renderGrid call below | ||
} | ||
} | ||
this.gridRenderer.paintCells.call(this, gc); | ||
this.renderOverrides(gc); | ||
this.renderLastSelection(gc); | ||
gc.closePath(); | ||
}, | ||
@@ -779,12 +736,2 @@ | ||
getColumnEdges: function() { | ||
this.deprecated('columnEdges', 'The getColumnEdges() mehtod has been deprecated as of version 1.2.0 in favor of visibleColumns[*].top. (Will be removed in a future version.) Note however that columnEdges had one additional element (representing the right edge of the last visible column) which visibleColumns lacks. Instead you can reference visibleColumns[*].bottom.'); | ||
return this.visibleColumns.map(function(vc) { return vc.left; }).concat([this.visibleColumns[this.visibleColumns.length - 1].right]); | ||
}, | ||
getRowEdges: function() { | ||
this.deprecated('rowEdges', 'The getRowEdges() method has been deprecated as of version 1.2.0 in favor of visibleRows[*].top. (Will be removed in a future version.) Note however that rowEdges had one additional element (representing the bottom edge of the last visible row) which visibleRows lacks. Instead you can reference visibleRows[*].bottom.'); | ||
return this.visibleRows.map(function(vr) { return vr.top; }).concat([this.visibleRows[this.visibleRows.length - 1].bottom]); | ||
}, | ||
/** | ||
@@ -836,10 +783,2 @@ * @memberOf Renderer.prototype | ||
* @memberOf Renderer.prototype | ||
* @returns {fin-canvas} my [fin-canvas](https://github.com/stevewirts/fin-canvas) | ||
*/ | ||
getCanvas: function() { | ||
return this.deprecated('getCanvas()', 'grid.canvas', '1.2.2'); | ||
}, | ||
/** | ||
* @memberOf Renderer.prototype | ||
* @returns {boolean} User is currently dragging a column for reordering. | ||
@@ -872,3 +811,3 @@ */ | ||
getPageDownRow: function() { | ||
return this.dataWindow.corner.y - this.properties.fixedRowCount + 1; | ||
return this.dataWindow.corner.y - this.properties.fixedRowCount; | ||
}, | ||
@@ -993,19 +932,2 @@ | ||
/** | ||
* @memberOf Renderer.prototype | ||
* @param {CanvasRenderingContext2D} gc | ||
* @param x | ||
* @param y | ||
*/ | ||
paintCell: function(gc, x, y) { | ||
gc.moveTo(0, 0); | ||
var c = this.visibleColumns[x].index, // todo refac | ||
r = this.visibleRows[y].index; | ||
if (c) { //something is being viewed at at the moment (otherwise returns undefined) | ||
this._paintCell(gc, c, r); | ||
} | ||
}, | ||
/** | ||
* @summary Render a single cell. | ||
@@ -1022,3 +944,2 @@ * @param {CanvasRenderingContext2D} gc | ||
selectionModel = grid.selectionModel, | ||
behavior = grid.behavior, | ||
@@ -1044,3 +965,3 @@ isHandleColumn = cellEvent.isHandleColumn, | ||
format, | ||
value, | ||
isSelected; | ||
@@ -1056,11 +977,8 @@ | ||
isSelected = isCellSelected || isRowSelected || isColumnSelected; | ||
} else if (isFilterRow) { | ||
isSelected = false; | ||
} else if (isColumnSelected) { | ||
isSelected = true; | ||
} else { | ||
format = cellEvent.subgrid.format; // subgrid format can override column format | ||
if (isFilterRow) { | ||
isSelected = false; | ||
} else if (isColumnSelected) { | ||
isSelected = true; | ||
} else { | ||
isSelected = selectionModel.isCellSelectedInColumn(x); // header or summary or other non-meta | ||
} | ||
isSelected = selectionModel.isCellSelectedInColumn(x); // header or summary or other non-meta | ||
} | ||
@@ -1071,16 +989,15 @@ | ||
// * For cells outside of row handle column: also set `config.dataRow` for use by valOrFunc | ||
// * For non-data row tree column cells, do nothing (these cells render blank so value is undefined) | ||
if (!isHandleColumn) { | ||
//Including hierarchyColumn | ||
// including tree column | ||
config.dataRow = cellEvent.dataRow; | ||
config.value = cellEvent.value; | ||
} else { | ||
if (isDataRow) { | ||
// row handle for a data row | ||
if (config.rowHeaderNumbers) { | ||
config.value = r + 1; // row number is 1-based | ||
} | ||
} else if (isHeaderRow) { | ||
// row handle for header row: gets "master" checkbox | ||
config.allRowsSelected = selectionModel.areAllRowsSelected(); | ||
value = cellEvent.value; | ||
} else if (isDataRow) { | ||
// row handle for a data row | ||
if (config.rowHeaderNumbers) { | ||
value = r + 1; // row number is 1-based | ||
} | ||
} else if (isHeaderRow) { | ||
// row handle for header row: gets "master" checkbox | ||
config.allRowsSelected = selectionModel.areAllRowsSelected(); | ||
} | ||
@@ -1105,35 +1022,58 @@ | ||
config.prefillColor = prefillColor; | ||
config.mouseDown = grid.mouseDownState && grid.mouseDownState.gridCell.equals(cellEvent.gridCell); | ||
// compute value if a calculator | ||
if (isUserDataArea && !(config.value && config.value.constructor === Array)) { // fastest array determination | ||
config.value = config.exec(config.value); | ||
if (grid.mouseDownState) { | ||
config.mouseDown = grid.mouseDownState.gridCell.equals(cellEvent.gridCell); | ||
} | ||
// This call's dataModel.getCell which developer can override to: | ||
// * mutate the (writable) properties of `config` | ||
// * mutate cell renderer choice (instance of which is returned) | ||
var cellRenderer = behavior.dataModel.getCell(config, config.renderer); | ||
config.subrow = 0; | ||
behavior.cellPropertiesPrePaintNotification(config); | ||
// subrow logic - coded for efficiency when no subrows (!value.subrows) | ||
var isArray = isUserDataArea && value && value.constructor === Array, // fastest array determination | ||
subrows = isArray && value.subrows && value.length; | ||
config.formatValue = grid.getFormatter(format || config.format); | ||
if (subrows) { | ||
var bounds = config.bounds = Object.assign({}, config.bounds); | ||
bounds.height /= subrows; | ||
config.subrows = subrows; | ||
config.value = config.exec(value[0]); | ||
} else { | ||
subrows = 1; | ||
config.value = !isArray && isUserDataArea ? config.exec(value) : value; | ||
} | ||
// Following supports partial render> | ||
config.snapshot = cellEvent.snapshot; | ||
config.minWidth = cellEvent.minWidth; // in case `paint` aborts before setting `minWidth` | ||
while (true) { // eslint-disable-line | ||
// This call's dataModel.getCell which developer can override to: | ||
// * mutate the (writable) properties of `config` (including config.value) | ||
// * mutate cell renderer choice (instance of which is returned) | ||
var cellRenderer = cellEvent.subgrid.getCell(config, config.renderer); | ||
// Render the cell | ||
if (cellRenderer.forEach) { | ||
cellRenderer.forEach(function(subrenderer) { | ||
subrenderer.paint(gc, config); | ||
}); | ||
} else { | ||
cellRenderer.paint(gc, config); | ||
config.formatValue = grid.getFormatter(config.format); | ||
config.snapshot = cellEvent.snapshot[config.subrow]; // supports partial render | ||
config.minWidth = cellEvent.minWidth; // in case `paint` aborts before setting `minWidth` | ||
// Render the cell | ||
if (cellRenderer.forEach) { | ||
cellRenderer.forEach(function(subrenderer) { | ||
subrenderer.paint(gc, config); | ||
}); | ||
} else { | ||
cellRenderer.paint(gc, config); | ||
} | ||
cellEvent.snapshot[config.subrow] = config.snapshot; // supports partial render | ||
if (cellEvent.minWidth === undefined || config.minWidth > cellEvent.minWidth) { | ||
cellEvent.minWidth = config.minWidth; | ||
} | ||
if (++config.subrow === subrows) { | ||
break; | ||
} | ||
bounds.y += bounds.height; | ||
config.value = config.exec(value[config.subrow]); | ||
} | ||
// Following supports partial render: | ||
cellEvent.snapshot = config.snapshot; | ||
cellEvent.minWidth = config.minWidth; | ||
// Following supports clicking in a renderer-defined Rectangle of a cell (in the cell's local coordinates) | ||
@@ -1155,3 +1095,3 @@ cellEvent.clickRect = config.clickRect; | ||
* @param {number} [rowIndex] - This is the "data" y coordinate. Omit if `colIndexOrCellEvent` is a `CellEvent`. | ||
* @param {dataModelAPI} [dataModel=this.grid.behavior.dataModel] Omit if `colIndexOrCellEvent` is a `CellEvent`. | ||
* @param {DataModel} [dataModel=this.grid.behavior.dataModel] Omit if `colIndexOrCellEvent` is a `CellEvent`. | ||
* @returns {CellEvent} The matching `CellEvent` object from the renderer's pool. Returns `undefined` if the requested cell is not currently visible (due to being scrolled out of view). | ||
@@ -1194,3 +1134,3 @@ */ | ||
* @param {number} [y] | ||
* @param {dataModelAPI} [dataModel=this.grid.behavior.dataModel] | ||
* @param {DataModel} [dataModel=this.grid.behavior.dataModel] | ||
* @returns {CellEvent} The matching `CellEvent` object. | ||
@@ -1227,2 +1167,12 @@ */ | ||
function fetchCompletion(gc, fetchError) { | ||
if (!fetchError) { | ||
// STEP 1: Render the grid immediately (before next refresh) just to get column widths | ||
// (for better performance this could be done off-screen but this works fine as is) | ||
this.gridRenderer.paintCells.call(this, gc); | ||
// STEP 2: Re-render upon next refresh with proper column widths | ||
this.grid.repaint(); | ||
} | ||
} | ||
/** | ||
@@ -1241,4 +1191,2 @@ * This function creates several data structures: | ||
function computeCellsBounds() { | ||
//var startTime = Date.now(); | ||
var scrollTop = this.getScrollTop(), | ||
@@ -1488,3 +1436,8 @@ scrollLeft = this.getScrollLeft(), | ||
this.dataWindow = new InclusiveRectangle(firstVX, firstVY, lastVX - firstVX + 1, lastVY - firstVY + 1); | ||
this.dataWindow = new InclusiveRectangle( | ||
firstVX, | ||
firstVY, | ||
Math.min(lastVX - firstVX + 1, this.visibleColumns.length), | ||
Math.min(lastVY - firstVY + 1, this.visibleRows.length) | ||
); | ||
@@ -1507,2 +1460,37 @@ // Resize CellEvent pool | ||
/** | ||
* @summary Create a list of `Rectangle`s representing visible cells. | ||
* @desc When `grid.properties.fetchSubregions` is true, this function needs to handle: | ||
* 1. unordered columns | ||
* 2. column gaps (hidden columns) | ||
* 3. the single row gap that results when there are fixed rows and remaining rows are scrolled down | ||
* | ||
* @ToDo This function currently only handles (1) above; needs (2) (multiple rectangles for multiple contiguous column regions) and (3) (double each region for above and below the fixed boundary when scrolled down) as well. In its present form, it will "fetch" all cells from upper left of fixed area to lower right of scrollable area. (Yikes.) | ||
* | ||
* When `grid.properties.fetchSubregions` is falsy, this function merely returns `this.dataWindow` as the only rectangle. | ||
* This is way more efficient than calling `getSubrects` (as it is currently implemented) and is fine so long as there are no fixed columns or rows and column re-ordering is disabled. | ||
* (If tree column in use, it is a fixed column, but this is workable so long as the data model knows to always return it regardless of rectangle.) | ||
* Hidden columns within the range of visible columns will be fetched anyway. | ||
* Column scrolling is ok. | ||
* | ||
* @ToDo This function is too slow for practical use due to map and sort. | ||
* | ||
* @this {Renderer} | ||
*/ | ||
function getSubrects() { | ||
var dw = this.dataWindow; | ||
if (!this.grid.properties.fetchSubregions) { | ||
var rect = this.grid.newRectangle(dw.left, dw.top, dw.width, dw.height); // convert from InclusiveRect | ||
return [rect]; | ||
} | ||
var orderedColumnIndexes = this.visibleColumns.map(function(vc) { return vc.column.index; }).sort(intComparator), | ||
xMin = orderedColumnIndexes[0], | ||
width = orderedColumnIndexes[orderedColumnIndexes.length - 1] - xMin + 1; | ||
return [this.grid.newRectangle(xMin, dw.top, width, dw.height)]; | ||
} | ||
function intComparator(a, b){ return a - b; } | ||
/** | ||
* @summary Resize the handle column. | ||
@@ -1515,4 +1503,4 @@ * @desc Handle column width is sum of: | ||
* @this {Renderer} | ||
* @param gc | ||
* @param rowCount | ||
* @param {CanvasRenderingContext2D} gc | ||
* @param {number} rowCount | ||
*/ | ||
@@ -1519,0 +1507,0 @@ function resetRowHeaderColumnWidth(gc, rowCount) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
10
94
93
730339
18191
+ Addeddatasaur-base@^3.0.0
+ Addeddatasaur-local@^3.0.0
+ Addeddatasaur-base@3.0.0(transitive)
+ Addeddatasaur-local@3.0.0(transitive)
- Removedfin-hypergrid-event-logger@^1.0.3
- Removedcode-match@1.0.0(transitive)
- Removedfin-hypergrid-data-source-base@0.4.11(transitive)
- Removedfin-hypergrid-event-logger@1.0.4(transitive)
- Removedgreylist@2.1.0(transitive)
- Removedmatch-point@1.0.0(transitive)
- Removedobject-catalog@1.1.2(transitive)
- Removedstarlog@1.0.0(transitive)