Socket
Socket
Sign inDemoInstall

fin-hypergrid

Package Overview
Dependencies
Maintainers
2
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fin-hypergrid - npm Package Compare versions

Comparing version 2.0.2 to 2.1.1

3.0.0/build/fin-hypergrid.js

20

package.json
{
"name": "fin-hypergrid",
"version": "2.0.2",
"description": "Canvas-based high-performance spreadsheet",
"version": "2.1.1",
"description": "Canvas-based high-performance grid",
"repository": {

@@ -9,3 +9,3 @@ "type": "git",

},
"author": "SWirts, JEiten, DJones",
"author": "SWirts, JEiten, DJones, NMichaud",
"license": "MIT",

@@ -22,5 +22,6 @@ "readmeFilename": "README.md",

"fin-hypergrid-data-source-base": "^0.4.10",
"fin-hypergrid-event-logger": "^1.0.3",
"finbars": "1.5.2",
"inject-stylesheet-template": "^1.0.1",
"mustache": "2.2.0",
"mustache": "^2.3.0",
"object-iterators": "1.3.0",

@@ -33,9 +34,8 @@ "overrider": "^0",

"browser-sync": "^2.10.0",
"browserify": "^15.1.0",
"css-injector": "^1.1.0",
"gulp": "^3.9.0",
"gulp-beautify": "^2.0.0",
"gulp-browserify": "^0.5.1",
"gulp-concat": "^2.6.0",
"gulp-each": "^0.1.1",
"gulp-eslint": "^1.1.0",
"gulp-eslint": "^4.0.0",
"gulp-exclude-gitignore": "^1.0.0",

@@ -50,3 +50,3 @@ "gulp-footer": "^1.0.5",

"gulp-replace": "^0.5.4",
"gulp-uglify": "^1.5.1",
"gulp-uglify": "^3.0.0",
"gulp-util": "^3.0.7",

@@ -58,4 +58,6 @@ "gutil": "^1.6.4",

"run-sequence": "^1.1.4",
"through2": "^2.0.0"
"through2": "^2.0.0",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0"
}
}
[![Build Status](https://travis-ci.org/openfin/fin-hypergrid.svg?branch=develop)](https://travis-ci.org/openfin/fin-hypergrid)
**fin-hypergrid** is an ultra-fast HTML5 grid presentation layer, achieving its speed by rendering (in a canvas tag) only the currently visible portion of your (virtual) grid, thus avoiding the latency and life-cycle issues of building, walking, and maintaining a complex DOM structure. Please be sure to checkout our [design overview](https://github.com/openfin/fin-hypergrid/blob/master/OVERVIEW.md)
**fin-hypergrid** is an ultra-fast HTML5 grid presentation layer, achieving its speed by rendering (in a canvas tag) only the currently visible portion of your (virtual) grid, thus avoiding the latency and life-cycle issues of building, walking, and maintaining a complex DOM structure. Please be sure to checkout our [design overview](OVERVIEW.md)
Below is an example custom application built ontop of the Hypergrid API tooling. It also highlights a DOM based custom external editor triggered via hypergrid events as well as interaction with Hypergrid's column ordering API
Below is an example custom application built on top of the Hypergrid API tooling.
It also highlights a DOM-based custom external editor triggered via hypergrid events as well as interaction with Hypergrid's column ordering API
<img src="https://github.com/openfin/fin-hypergrid/blob/master/images/README/gridshot04.gif">
<img src="images/README/gridshot04.gif">
## Table of Contents
* [Current Release](https://github.com/openfin/fin-hypergrid#current-release-121---27-october-2016)
* [Demos](https://github.com/openfin/fin-hypergrid/blob/master/README.md#demos)
* [Features](https://github.com/openfin/fin-hypergrid/blob/master/README.md#features)
* [Testing](https://github.com/openfin/fin-hypergrid/blob/master/README.md#testing)
* [Documentation](https://github.com/openfin/fin-hypergrid/blob/master/README.md#developer-documentation)
* [Roadmap](https://github.com/openfin/fin-hypergrid/blob/master/README.md#roadmap)
* [Contributing](https://github.com/openfin/fin-hypergrid/blob/master/README.md#contributors)
* [Current Release](#current-release-211---29-january-2018)
* [Demos](#demos)
* [Features](#features)
* [Testing](#testing)
* [Documentation](#developer-documentation)
* [Roadmap](#roadmap)
* [Contributing](#contributors)
### Current Release (2.0.2 - 4 June 2017)
### Current Release (2.1.1 - 29 January 2018)
2.0 reflects a substantial simplification of the core functionality of the grid to just customized rendering. The rendering engine does allow support for showing sorting, filtering, grouping, etc. but specific logic on how a user may want to do that is not apart for this project. Demos will be made available on the [wiki](https://github.com/openfin/fin-hypergrid/wiki) for this.
**Hypergrid 2.1.1** includes bug fixes as well as some new properties and methods that offer new capabilities.
2.0 also replaces the 2015-2016 [prototype version](https://github.com/openfin/fin-hypergrid/tree/polymer-prototype), which was built around Polymer. It is now completely "de-polymerized" and is being made available as:
* An [npm module](https://www.npmjs.com/package/fin-hypergrid) for use with browserify.
* A single JavaScript file [fin-hypergrid.js](https://openfin.github.io/fin-hypergrid/build/fin-hypergrid.js) you can reference in a `<script>` tag.
_For a complete list of changes, see the [release notes](https://github.com/fin-hypergrid/core/releases)._
_For a complete list of changes, see the [release notes](https://github.com/openfin/fin-hypergrid/releases)._
### Demos

@@ -32,3 +29,3 @@

Here is an [application](http://openfin.github.io/fin-hypergrid/) that demos various features.
Our [dev testbed](https://fin-hypergrid.github.io/core) demos various features.

@@ -41,31 +38,31 @@ ##### Hyperblotter

![](https://github.com/openfin/fin-hypergrid/blob/master/images/README/Hyperblotter%20Tabled%20Reduced%20Rows.png)
![](images/README/Hyperblotter%20Tabled%20Reduced%20Rows.png)
### Features
![](https://github.com/openfin/fin-hypergrid/blob/master/images/README/Hypergrid%20Features.png)
![](images/README/Hypergrid%20Features.png)
### Testing
Please use github [issues](https://github.com/openfin/fin-hypergrid/issues) or email support@openfin.co to report problems
Please use github [issues](https://github.com/fin-hypergrid/core/issues) to report problems
We invite everyone to test the alpha branch for changes going into the next release
Find more infomation on our [testing page](https://github.com/openfin/fin-hypergrid/blob/master/TESTING.md)
Find more information on our [testing page](TESTING.md)
### Developer Documentation
Primarily our tutorials will be on the [wiki](https://github.com/openfin/fin-hypergrid/wiki).
Primarily our tutorials will be on the [wiki](https://github.com/fin-hypergrid/core/wiki).
We are also maintaining [online API documentation](http://openfin.github.io/fin-hypergrid/doc/Hypergrid.html) for all public objects and modules. This documentation is necessarily a on-going work-in-progress.
We also maintain versioned [online API documentation](https://fin-hypergrid.github.io/core/2.1.0/doc/Hypergrid.html) for all public objects and modules. This documentation is necessarily an on-going work-in-progress.
(Cell editor information can be found [here](https://github.com/openfin/fin-hypergrid/wiki/Cell-Editors).)
(Cell editor information can be found [here](https://github.com/fin-hypergrid/core/wiki/Cell-Editors).)
(Cell Rendering information can be found [here](https://github.com/openfin/fin-hypergrid/wiki/Cell-Renderers).)
(Cell Rendering information can be found [here](https://github.com/fin-hypergrid/core/wiki/Cell-Renderers).)
Hypergrid global configurations can be found [here](http://openfin.github.io/fin-hypergrid/doc/module-defaults.html).
Hypergrid global configurations can be found [here](https://fin-hypergrid.github.io/core/2.1.0/doc/module-defaults.html).
### Roadmap
For our current queue of up coming work you can find it [here](https://github.com/openfin/fin-hypergrid/blob/master/ROADMAP.md)
For our current queue of up coming work you can find it [here](ROADMAP.md)

@@ -72,0 +69,0 @@ ### Contributors

@@ -8,2 +8,6 @@ 'use strict';

var cellEventFactory = require('../lib/cellEventFactory');
var Features = require('../features');
var propClassEnum = require('../defaults.js').propClassEnum;
var noExportProperties = [

@@ -42,3 +46,3 @@ 'columnHeader',

this.initializeFeatureChain(grid);
this.initializeFeatureChain();

@@ -50,11 +54,19 @@ this.grid.behavior = this;

/**
* @desc create the feature chain - this is the [chain of responsibility](http://c2.com/cgi/wiki?ChainOfResponsibilityPattern) pattern.
* @param {Hypergrid} grid
* @desc Create the feature chain - this is the [chain of responsibility](http://c2.com/cgi/wiki?ChainOfResponsibilityPattern) pattern.
* @param {Hypergrid} [grid] Unnecesary legacy parameter. May be omitted.
* @memberOf Behavior#
*/
initializeFeatureChain: function(grid) {
var self = this;
var constructors;
/**
* @summary Hash of feature class names.
* @summary Controller chain of command.
* @desc Each feature is linked to the next feature.
* @type {Feature}
* @memberOf Behavior#
*/
this.featureChain = undefined;
/**
* @summary Hash of instantiated features by class names.
* @desc Built here but otherwise not in use.

@@ -66,23 +78,30 @@ * @type {object}

this.features.forEach(function(FeatureConstructor) {
var newFeature = new FeatureConstructor;
self.featureMap[newFeature.$$CLASS_NAME] = newFeature;
if (self.featureChain) {
self.featureChain.setNext(newFeature);
this.featureRegistry = this.featureRegistry || new Features;
if (this.grid.properties.features) {
var getFeatureConstructor = this.featureRegistry.get.bind(this.featureRegistry);
constructors = this.grid.properties.features.map(getFeatureConstructor);
} else if (this.features) {
constructors = this.features;
warnBehaviorFeaturesDeprecation.call(this);
}
constructors.forEach(function(FeatureConstructor, i) {
var feature = new FeatureConstructor;
this.featureMap[feature.$$CLASS_NAME] = feature;
if (i) {
this.featureChain.setNext(feature);
} else {
/**
* @summary Controller chain of command.
* @desc Each feature is linked to the next feature.
* @type {Feature}
* @memberOf Behavior#
*/
self.featureChain = newFeature;
this.featureChain = feature;
}
});
}, this);
if (this.featureChain) {
this.featureChain.initializeOn(grid);
this.featureChain.initializeOn(this.grid);
}
},
features: [], // override in implementing class unless no features
features: [], // override in implementing class; or provide feature names in grid.properties.features; else no features

@@ -138,10 +157,2 @@ /**

get treeColumnIndex() {
return -1;
},
get rowColumnIndex() {
return -2;
},
get leftMostColIndex() {

@@ -152,4 +163,16 @@ return this.grid.properties.showRowNumbers ? this.rowColumnIndex : (this.hasTreeColumn() ? this.treeColumnIndex : 0);

clearColumns: function() {
var tc = this.treeColumnIndex;
var rc = this.rowColumnIndex;
var schema = this.dataModel.schema,
tc = this.treeColumnIndex,
rc = this.rowColumnIndex;
schema[tc] = schema[tc] || {
name: 'Tree',
header: 'Tree'
};
schema[rc] = schema[rc] || {
name: '',
header: ''
};
/**

@@ -169,8 +192,13 @@ * @type {Column[]}

index: tc,
header: this.dataModel.schema[tc].header
header: schema[tc].header
});
this.allColumns[rc] = this.columns[rc] = this.newColumn({
index: rc,
header: this.dataModel.schema[rc].header
header: schema[rc].header
});
this.columns[tc].properties.propClassLayers = this.columns[rc].properties.propClassLayers = [propClassEnum.COLUMNS];
// Signal the renderer to size the now-reset handle column before next render
this.grid.renderer.resetRowHeaderColumnWidth();
},

@@ -726,8 +754,71 @@

* @memberOf Behavior#
* @param {number} rowIndex - Data row coordinate local to datsModel.
* @param {number|CellEvent} yOrCellEvent - Data row index local to `dataModel`; or a `CellEvent` object.
* @param {boolean} [properties] - New properties object when one does not already exist. If you don't provide this and one does not already exist, this call will return `undefined`. _(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).
* @returns {object|undefined} The row properties object which will be one of:
* * The row properties object if it existed.
* * The value you provided in `properties` if the row properties for a new row properties object when the object did not already exist in the metadata
* * `undefined` if the row properties object did not exist _and_ you did not provide a value in `properties`.
*/
getRowProperties: function(yOrCellEvent, properties, dataModel) {
if (typeof yOrCellEvent === 'object') {
yOrCellEvent = yOrCellEvent.dataCell.y;
dataModel = yOrCellEvent.subgrid;
}
var metadata = (dataModel || this.dataModel).getRowMetadata(yOrCellEvent, properties && {});
return metadata && (metadata.__ROW || (metadata.__ROW = properties));
},
/**
* Reset the row properties in its entirety to the given row properties object.
* @memberOf Behavior#
* @param {number|CellEvent} yOrCellEvent - Data row index local to `dataModel`; or a `CellEvent` object.
* @param {object} properties - The new row properties object.
* @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).
*/
setRowProperties: function(yOrCellEvent, properties, dataModel) {
if (typeof yOrCellEvent === 'object') {
yOrCellEvent = yOrCellEvent.dataCell.y;
dataModel = yOrCellEvent.subgrid;
}
(dataModel || this.dataModel).getRowMetadata(yOrCellEvent, {}, dataModel).__ROW = properties;
this.stateChanged();
},
/**
* Sets a single row property on a specific individual row.
* @memberOf Behavior#
* @param {number|CellEvent} yOrCellEvent - Data row index local to `dataModel`; or a `CellEvent` object.
* @param {string} key - The property name.
* @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).
*/
setRowProperty: function(yOrCellEvent, key, value, dataModel) {
this.getRowProperties(yOrCellEvent, {}, dataModel)[key] = value;
this.stateChanged();
},
/**
* Add all the properties in the given row properties object to the row properties.
* @memberOf Behavior#
* @param {number|CellEvent} yOrCellEvent - Data row index local to `dataModel`; or a `CellEvent` object.
* @param {object} properties - An object containing new property values(s) to assign to the row properties.
* @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).
*/
addRowProperties: function(yOrCellEvent, properties, dataModel) {
Object.assign(this.getRowProperties(yOrCellEvent, {}, dataModel), properties);
this.stateChanged();
},
/**
* @memberOf Behavior#
* @param {number} yOrCellEvent - Data row index local to `dataModel`.
* @param {dataModelAPI} [dataModel=this.dataModel]
*/
getRowHeight: function(rowIndex, dataModel) {
var rowData = (dataModel || this.dataModel).getRow(rowIndex);
return rowData && rowData.__ROW_HEIGHT || this.grid.properties.defaultRowHeight;
getRowHeight: function(yOrCellEvent, dataModel) {
var rowProps = this.getRowProperties(yOrCellEvent, undefined, dataModel);
return rowProps && rowProps.height || this.grid.properties.defaultRowHeight;
},

@@ -747,10 +838,13 @@

* @desc set the pixel height of a specific row
* @param {number} rowIndex - Data row coordinate local to dataModel.
* @param {number} yOrCellEvent - Data row index local to dataModel.
* @param {number} height - pixel height
* @param {dataModelAPI} [dataModel=this.dataModel]
*/
setRowHeight: function(rowIndex, height, dataModel) {
var rowData = (dataModel || this.dataModel).getRow(rowIndex);
if (rowData) {
rowData.__ROW_HEIGHT = Math.max(5, Math.ceil(height));
setRowHeight: function(yOrCellEvent, height, dataModel) {
var rowProps = this.getRowProperties(yOrCellEvent, {}, dataModel),
oldHeight = rowProps.height;
rowProps.height = Math.max(5, Math.ceil(height));
if (rowProps.height !== oldHeight) {
this.stateChanged();

@@ -1294,2 +1388,6 @@ }

getRowHeaderColumn: function() {
return this.allColumns[this.rowColumnIndex];
},
autosizeAllColumns: function() {

@@ -1303,3 +1401,3 @@ this.checkColumnAutosizing(true);

var autoSized = this.autoSizeRowNumberColumn() ||
this.hasTreeColumn() && this.allColumns[this.rowColumnIndex].checkColumnAutosizing(force);
this.hasTreeColumn() && this.getRowHeaderColumn().checkColumnAutosizing(force);
this.allColumns.forEach(function(column) {

@@ -1313,3 +1411,3 @@ autoSized = column.checkColumnAutosizing(force) || autoSized;

if (this.grid.properties.showRowNumbers && this.grid.properties.rowNumberAutosizing) {
return this.allColumns[this.rowColumnIndex].checkColumnAutosizing(true);
return this.getRowHeaderColumn().checkColumnAutosizing(true);
}

@@ -1406,2 +1504,53 @@ },

// define constants as immutable (i.e., !writable)
Object.defineProperties(Behavior.prototype, {
treeColumnIndex: { value: -1 },
rowColumnIndex: { value: -2 }
});
function warnBehaviorFeaturesDeprecation() {
var featureNames = [], unregisteredFeatures = [], n = 0;
this.features.forEach(function(FeatureConstructor) {
var className = FeatureConstructor.prototype.$$CLASS_NAME || FeatureConstructor.name,
featureName = className || 'feature' + n++;
// build list of feature names
featureNames.push(featureName);
// build list of unregistered features
if (!this.featureRegistry.get(featureName, true)) {
var constructorName = FeatureConstructor.name || FeatureConstructor.prototype.$$CLASS_NAME || 'FeatureConstructor' + n,
params = [];
if (!className) {
params.push('\'' + featureName + '\'');
}
params.push(constructorName);
unregisteredFeatures.push(params.join(', '));
}
}, this);
if (featureNames.length) {
var sampleCode = 'Hypergrid.defaults.features = [\n' + join('\t\'', featureNames, '\',\n') + '];';
if (unregisteredFeatures.length) {
sampleCode += '\n\nThe following custom features are unregistered and will need to be registered prior to behavior instantiation:\n\n' +
join('Features.add(', unregisteredFeatures, ');\n');
}
if (n) {
sampleCode += '\n\n(You should provide meaningful names for your custom features rather than the generated names above.)';
}
console.warn('`grid.behavior.features` (array of feature constructors) has been deprecated as of version 2.1.0 in favor of `grid.properties.features` (array of feature names). Remove `features` array from your behavior and add `features` property to your grid state object (or Hypergrid.defaults), e.g.:\n\n' + sampleCode);
}
}
function join(prefix, array, suffix) {
return prefix + array.join(suffix + prefix) + suffix;
}
// synonyms

@@ -1408,0 +1557,0 @@

@@ -149,3 +149,3 @@ /* eslint-env bro wser */

var rowData = (dataModel || this.dataModel).getRow(rowIndex),
metaData = rowData.__META = rowData.__META || {},
metadata = rowData.__META = rowData.__META || {},
props;

@@ -161,5 +161,5 @@

return (metaData[this.name] = Object.create(props));
return (metadata[this.name] = Object.create(props));
}
module.exports = cell;

@@ -73,6 +73,2 @@ /* eslint-env browser */

case this.behavior.rowColumnIndex:
// Width of icon + 3-pixel spacer (checked and unchecked should be same width)
icon = images[Object.create(this.properties.rowHeader, { isDataRow: { value: true } }).leftIcon];
this.properties.minimumColumnWidth = icon ? icon.width + 3 : 0;
// This case avoids the "out of range" error.
break;

@@ -79,0 +75,0 @@ default:

@@ -48,3 +48,2 @@ 'use strict';

header: {
enumerable: true,
get: function() {

@@ -62,3 +61,2 @@ return column.header;

type: {
enumerable: true,
get: function() {

@@ -76,3 +74,2 @@ return column.type;

calculator: {
enumerable: true,
get: function() {

@@ -113,2 +110,13 @@ return column.calculator;

}
},
toJSON: {
// although we don't generally want header, type, and calculator to be enumerable, we do want them to be serializable
value: function() {
return Object.assign({
header: this.header,
type: this.type,
calculator: this.calculator
}, this);
}
}

@@ -118,18 +126,9 @@

Object.defineProperty(properties, 'rowHeader', {
value: Object.create(properties, createColumnProperties.rowHeaderDescriptors)
Object.defineProperties(properties, {
rowHeader: { value: Object.create(properties, createColumnProperties.rowHeaderDescriptors) },
treeHeader: { value: Object.create(properties, createColumnProperties.treeHeaderDescriptors) },
columnHeader: { value: Object.create(properties, createColumnProperties.columnHeaderDescriptors) },
filterProperties: { value: Object.create(properties, createColumnProperties.filterDescriptors) }
});
Object.defineProperty(properties, 'treeHeader', {
value: Object.create(properties, createColumnProperties.treeHeaderDescriptors)
});
Object.defineProperty(properties, 'columnHeader', {
value: Object.create(properties, createColumnProperties.columnHeaderDescriptors)
});
Object.defineProperty(properties, 'filterProperties', {
value: Object.create(properties, createColumnProperties.filterDescriptors)
});
return properties;

@@ -277,11 +276,13 @@ }

get: function() {
var result;
if (this.isDataRow) {
result = this.isRowSelected ? 'checked' : 'unchecked';
} else if (this.isHeaderRow) {
result = this.allRowsSelected ? 'checked' : 'unchecked';
} else if (this.isFilterRow) {
result = 'filter-off';
if (this.grid.properties.rowHeaderCheckboxes) {
var result;
if (this.isDataRow) {
result = this.isRowSelected ? 'checked' : 'unchecked';
} else if (this.isHeaderRow) {
result = this.allRowsSelected ? 'checked' : 'unchecked';
} else if (this.isFilterRow) {
result = 'filter-off';
}
return result;
}
return result;
},

@@ -288,0 +289,0 @@ set: function(value) {

'use strict';
// This module is provided solely in support of build file usage, e.g., `fin.Hypergrid.behaviors.yada`,
// and is not meant to be used elsewhere.
module.exports = {

@@ -4,0 +7,0 @@ Behavior: require('./Behavior'),

@@ -6,3 +6,2 @@ 'use strict';

var DataModelJSON = require('../dataModels/JSON');
var features = require('../features');

@@ -35,17 +34,2 @@ /**

features: [
features.Filters,
features.CellSelection,
features.KeyPaging,
features.ColumnResizing,
// features.RowResizing,
features.RowSelection,
features.ColumnSelection,
features.ColumnMoving,
features.ColumnSorting,
features.CellClick,
features.CellEditing,
features.OnHover
],
createColumns: function() {

@@ -216,3 +200,3 @@ Behavior.prototype.createColumns.call(this);

grid.allowEvents(this.dataModel.getRowCount() > 0);
grid.allowEvents(this.getRowCount());
},

@@ -219,0 +203,0 @@

'use strict';
var Registry = require('../lib/Registry');
var deprecated = {
celleditor: undefined,
CellEditor: undefined
};
/**
*
* @param {Hypergrid} grid
* @param {boolean} [privateRegistry=false] - This instance will use a private registry.
* @classdesc Registry of cell editor constructors.
* @param {Hypergrid} options.grid
* @param {boolean} [options.private=false] - This instance will use a private registry.
* @constructor
*/
function CellEditors(grid, privateRegistry) {
this.grid = grid;
var CellEditors = Registry.extend('CellEditors', {
if (privateRegistry) {
this.editors = {};
}
BaseClass: require('./CellEditor'), // abstract base class
// preregister the standard cell editors
if (privateRegistry || !this.get('celleditor')) {
this.add(require('./CellEditor'));
this.add(require('./Color'));
this.add(require('./Date'));
this.add(require('./Number'));
this.add(require('./Slider'));
this.add(require('./Spinner'));
this.add(require('./Textfield'));
}
}
items: {}, // shared cell editor registry (when !options.private)
CellEditors.prototype = {
constructor: CellEditors.prototype.constructor, // preserve constructor
/**
* @summary Register a cell editor constructor.
* @desc Adds a custom cell editor constructor to the `editors` hash using the provided name (or the class name), converted to all lower case.
*
* > All native cell editors are "preregistered" in `editors`..
*
* @param {string} [name] - Case-insensitive editor key. If not given, `YourCellEditor.prototype.$$CLASS_NAME` is used.
*
* @param {YourCellEditor.prototype.constructor} Constructor - A constructor, typically extended from `CellEditor` (or a descendant therefrom).
*
* > Note: `$$CLASS_NAME` can be easily set up by providing a string as the (optional) first parameter (`alias`) in your {@link https://www.npmjs.com/package/extend-me|CellEditor.extend} call.
*
* @returns {CellEditor} A newly registered constructor extended from {@link CellEditor}.
*
* @memberOf CellEditors#
*/
add: function(name, Constructor) {
if (typeof name === 'function') {
Constructor = name;
name = undefined;
initialize: function(options) {
// preregister the standard cell editors
if (options && options.private || !this.items.celleditor) {
this.add(require('./Color'));
this.add(require('./Date'));
this.add(require('./Number'));
this.add(require('./Slider'));
this.add(require('./Spinner'));
this.add(require('./Textfield'));
}
name = name || Constructor.prototype.$$CLASS_NAME;
name = name && name.toLowerCase();
this.editors[name] = Constructor;
return Constructor;
},
/**
* @summary Register a synonym for an existing cell editor constructor.
* @param {string} synonymName
* @param {string} existingName
* @returns {CellEditor} The previously registered constructor this new synonym points to.
* @memberOf CellEditors#
*/
addSynonym: function(synonymName, existingName) {
var cellEditor = this.get(existingName);
return (this.editors[synonymName] = cellEditor);
construct: function(Constructor, options) {
return new Constructor(this.options.grid, options);
},
/**
* @param {string} name - Name of a registered editor.
* @returns {CellEditor} A registered constructor extended from {@link CellEditor}.
* @memberOf CellEditors#
*/
get: function(name) {
return this.editors[name && name.toLowerCase()];
},
/**
* @summary Lookup registered cell editor and return a new instance thereof.
* @desc Note: Must be called with the Hypergrid object as context!
* @returns {CellEditor} New instance of the named cell editor.
* @param {string} name - Name of a registered editor.
* @param {string} [options] - Properties to add to the instantiated editor primarily for mustache's use.
* @memberOf CellEditors#
*/
create: function(name, options) {
var cellEditor,
Constructor = this.get(name);
if (Constructor) {
if (Constructor.abstract) {
throw 'Attempt to instantiate an "abstract" cell editor class.';
if (name in deprecated) {
if (!deprecated.warned) {
console.warn('grid.cellEditors.get("' + name + '") method call has been deprecated as of v2.1.0 in favor of grid.cellEditors.BaseClass property. (Will be removed in a future release.)');
deprecated.warned = true;
}
cellEditor = new Constructor(this.grid, options);
return this.BaseClass;
}
return this.super.get.call(this, name);
}
return cellEditor;
},
});
/**
* The cell editor registry containing all the "preregistered" cell editor constructors.
* @private
* @memberOf CellEditors#
*/
editors: {}
};
CellEditors.add = Registry.prototype.add.bind(CellEditors);
module.exports = CellEditors;
'use strict';
var Registry = require('../lib/Registry');
var deprecated = {
emptycell: undefined,
EmptyCell: undefined
};
/**
* @classdesc API of cell renderer object constructors, plus some access methods.
* @classdesc Registry of cell renderer singletons.
* @param {boolean} [privateRegistry=false] - This instance will use a private registry.
* @constructor
*/
function CellRenderers(privateRegistry) {
if (privateRegistry) {
this.singletons = {};
}
var CellRenderers = Registry.extend('CellRenderers', {
// preregister the standard cell renderers
if (privateRegistry || !this.get('emptycell')) {
this.add('EmptyCell', require('./CellRenderer'));
this.add(require('./Button'));
this.add(require('./SimpleCell'));
this.add(require('./SliderCell'));
this.add(require('./SparkBar'));
this.add(require('./LastSelection'));
this.add(require('./SparkLine'));
this.add(require('./ErrorCell'));
this.add(require('./TreeCell'));
}
}
BaseClass: require('./CellRenderer'), // abstract base class
CellRenderers.prototype = {
constructor: CellRenderers.prototype.constructor, // preserve constructor
items: {}, // shared cell renderer registry (when !options.private)
/**
* @summary Register and instantiate a cell renderer singleton.
* @desc Adds a custom cell renderer to the `singletons` hash using the provided name (or the class name), converted to all lower case.
*
* > All native cell renderers are "preregistered" in `singletons`. Add more by calling `add`.
*
* @param {string} [name] - Case-insensitive renderer key. If not given, `YourCellRenderer.prototype.$$CLASS_NAME` is used.
*
* @param {CellRenderer} Constructor - A constructor, typically extended from `CellRenderer` (or a descendant therefrom).
*
* > Note: `$$CLASS_NAME` can be easily set up by providing a string as the (optional) first parameter (`alias`) in your {@link https://www.npmjs.com/package/extend-me|CellEditor.extend} call.
*
* @returns {CellRenderers} A newly registered constructor extended from {@link CellRenderers}.
*
* @memberOf CellRenderers.prototype
*/
add: function(name, Constructor) {
if (typeof name === 'function') {
Constructor = name;
name = undefined;
singletons: true,
initialize: function(options) {
// preregister the standard cell renderers
if (options && options.private || !this.items.simplecell) {
this.add(require('./Button'));
this.add(require('./SimpleCell'));
this.add(require('./SliderCell'));
this.add(require('./SparkBar'));
this.add(require('./LastSelection'));
this.add(require('./SparkLine'));
this.add(require('./ErrorCell'));
this.add(require('./TreeCell'));
}
name = name || Constructor.prototype.$$CLASS_NAME;
name = name && name.toLowerCase();
return (this.singletons[name] = new Constructor);
},
/**
* @summary Register a synonym for an existing cell renderer singleton.
* @param {string} synonymName
* @param {string} existingName
* @returns {CellRenderers} The previously registered constructor this new synonym points to.
* @memberOf CellRenderers.prototype
*/
addSynonym: function(synonymName, existingName) {
var cellRenderer = this.get(existingName);
return (this.singletons[synonymName] = cellRenderer);
},
/**
* Fetch a registered cell renderer singleton.
* @param {string} name
* @returns {CellRenderers} A registered constructor extended from {@link CellRenderers}.
* @memberOf CellRenderers.prototype
*/
get: function(name) {
var result = this.singletons[name]; // for performance reasons, do not convert to lower case
if (!result) {
result = this.singletons[name.toLowerCase()]; // name may differ in case only
if (result) {
this.singletons[name] = result; // register found name as a synonym
if (name in deprecated) {
if (!deprecated.warned) {
console.warn('grid.cellRenderers.get("' + name + '").constructor has been deprecated as of v2.1.0 in favor of grid.cellRenderers.BaseClass property. (Will be removed in a future release.)');
deprecated.warned = true;
}
this.BaseClass.constructor = this.BaseClass;
return this.BaseClass;
}
return result;
},
return this.super.get.call(this, name);
}
/**
* The cell editor registry containing all the "preregistered" cell renderer singletons.
* @private
* @memberOf CellRenderers.prototype
*/
singletons: {}
};
});
CellRenderers.add = Registry.prototype.add.bind(CellRenderers);
module.exports = CellRenderers;

@@ -22,2 +22,12 @@ 'use strict';

getRowMetadata: function(rowIndex, metadata) {
var dataRow = this.getRow(rowIndex);
return dataRow && (dataRow.__META || (dataRow.__META = metadata));
},
setRowMetadata: function(rowIndex, metadata) {
var dataRow = this.getRow(rowIndex);
return dataRow && (dataRow.__META = metadata);
},
/**

@@ -24,0 +34,0 @@ * @param {object} config

'use strict';
var DataModel = require('./DataModel');
/**

@@ -10,19 +12,16 @@ * @implements dataModelAPI

*/
function HeaderSubgrid(grid, options) {
this.grid = grid;
this.behavior = grid.behavior;
var HeaderSubgrid = DataModel.extend('HeaderSubgrid', {
initialize: function(grid, options) {
this.behavior = grid.behavior;
/**
* @type {dataRowObject}
*/
this.dataRow = {}; // for meta data (__HEIGHT)
/**
* @type {dataRowObject}
*/
this.dataRow = {}; // for meta data (__HEIGHT)
if (options && options.name) {
this.name = options.name;
}
}
if (options && options.name) {
this.name = options.name;
}
},
HeaderSubgrid.prototype = {
constructor: HeaderSubgrid.prototype.constructor,
type: 'header',

@@ -50,4 +49,4 @@

}
};
});
module.exports = HeaderSubgrid;

@@ -10,2 +10,9 @@ 'use strict';

var propClassEnum = {
COLUMNS: 1,
STRIPES: 2,
ROWS: 3,
CELLS: 4
};
/**

@@ -457,2 +464,16 @@ * This module lists the properties that can be set on a {@link Hypergrid} along with their default values.

/** @type {number}
* @default
* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.lineWidth}
*/
gridLinesHWidth: 1,
/** @type {string}
* @default
* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.lineColor}
*/
gridLinesHColor: 'rgb(199, 199, 199)',
/**

@@ -465,12 +486,44 @@ * @default

/** @type {number}
* @default
* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.lineWidth}
*/
gridLinesVWidth: 1,
/** @type {string}
* @default
* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.lineColor}
*/
gridLinesVColor: 'rgb(199, 199, 199)',
/**
* Draw horizontal grid line before first rendered column.
* 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.
*
* Caveat: The use of `grid.canvas.canvas.style.boxSizing = 'border-box'` is _not_ recommended due to
* the fact that the canvas is squashed slightly to accommodate the border resulting in blurred text.
*
* @default
* @type {boolean}
* @type {boolean|string}
* @memberOf module:defaults
*/
gridBorder: false,
/**
* Set canvas's left CSS border to this string.
* If set to `true`, uses current `lineWidth` and `lineColor`.
* If set to `false`, uses null.
* @default
* @type {boolean|string}
* @memberOf module:defaults
*/
gridBorderLeft: false,
/**
* Draw horizontal grid line after last rendered column.
* Set canvas's right CSS border to this string.
* If set to `true`, uses current `lineWidth` and `lineColor`.
* If set to `false`, uses null.
* @default

@@ -483,3 +536,5 @@ * @type {boolean}

/**
* Draw horizontal grid line above first rendered row.
* Set canvas's top CSS border to this string.
* If set to `true`, uses current `lineWidth` and `lineColor`.
* If set to `false`, uses null.
* @default

@@ -492,3 +547,5 @@ * @type {boolean}

/**
* Draw horizontal grid line below last rendered row.
* Set canvas's bottom CSS border to this string.
* If set to `true`, uses current `lineWidth` and `lineColor`.
* If set to `false`, uses null.
* @default

@@ -501,10 +558,27 @@ * @type {boolean}

/**
* Define this property to style rule lines between fixed & scolling rows differently from `lineWidth`.
* @default
* @type {number}
* @memberOf module:defaults
*/
fixedLinesHWidth: 2,
/**
* Define this property to render just the edges of the lines between fixed & scolling 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`.
* @default
* @type {number}
* @memberOf module:defaults
*/
fixedLinesHEdge: undefined, // undefined means no edge effect
/**
* Define this property to style rule lines between fixed & scolling rows differently from `lineColor`.
* @default
* @type {cssColor}
* @memberOf module:defaults
*/
lineColor: 'rgb(199, 199, 199)',
fixedLinesHColor: 'rgb(164,164,164)', // ~21% darker than `lineColor` default
/**
* Caveat: `lineWidth` should be an integer (whole pixel)
* Define this property to style rule lines between fixed & scolling columns differently from `lineWidth`.
* @default

@@ -514,7 +588,22 @@ * @type {number}

*/
lineWidth: 1,
fixedLinesVWidth: 2,
/**
* 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`.
* @default
* @type {number}
* @memberOf module:defaults
*/
fixedLinesVEdge: undefined, // undefined means no edge effect
/**
* Define this property to style rule lines between fixed & scolling columns differently from `lineColor`.
* @default
* @type {cssColor}
* @memberOf module:defaults
*/
fixedLinesVColor: 'rgb(164,164,164)', // ~21% darker than `lineColor` default
/**
* @default
* @type {number}

@@ -744,34 +833,2 @@ * @memberOf module:defaults

get x() {
if (!warned.x) {
warned.x = true;
console.warn('config.x has been deprecated as of v1.2.10 in favor of config.dataCell.x. (Will be removed in a future release.)');
}
return this.dataCell.x;
},
get untranslatedX() {
if (!warned.untranslatedX) {
warned.untranslatedX = true;
console.warn('config.untranslatedX has been deprecated as of v1.2.10 in favor of config.gridCell.x. (Will be removed in a future release.)');
}
return this.gridCell.x;
},
get y() {
if (!warned.y) {
warned.y = true;
console.warn('config.y has been deprecated as of v1.2.10 in favor of config.gridCell.y. (Will be removed in a future release.)');
}
return this.gridCell.y;
},
get normalizedY() {
if (!warned.normalizedY) {
warned.normalizedY = true;
console.warn('config.normalizedY has been deprecated as of v1.2.10 in favor of config.dataCell.y. (Will be removed in a future release.)');
}
return this.dataCell.y;
},
/**

@@ -806,4 +863,5 @@ * @summary Execute value if "calculator" (function) or if column has calculator.

* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.showRowNumbers}
*/
showRowNumbers: true,
rowHeaderNumbers: true,

@@ -814,3 +872,11 @@ /**

* @memberOf module:defaults
* @see {@link module:dynamicPropertyDescriptors.showRowNumbers}
*/
rowHeaderCheckboxes: true,
/**
* @default
* @type {boolean}
* @memberOf module:defaults
*/
showTreeColumn: true,

@@ -905,2 +971,5 @@

/* CELL EDITING */
/**

@@ -914,2 +983,4 @@ * @default

/**
* Edit cell on double-click rather than single-click.
*
* @default

@@ -922,9 +993,2 @@ * @type {boolean}

/**
* @default
* @type {number}
* @memberOf module:defaults
*/
doubleClickDelay: 325,
/**
* Grid-level property.

@@ -958,3 +1022,52 @@ * When user presses a "printable" keyboard character _or_ BACKSPACE _or_ DELETE:

/* COLUMN SORTING */
/**
* Ignore sort handling in feature/ColumnSorting.js.
* Useful for excluding some columns but not other from participating in sorting.
*
* @default
* @type {boolean}
* @memberOf module:defaults
*/
unsortable: false,
/**
* Sort column on double-click rather than single-click.
*
* Used by:
* * feature/ColumnSorting.js to decide which event to respond to (if any, see `unsortabe`).
* * feature/ColumnSelection.js to decide whether or not to wait for double-click.
* @default
* @type {boolean}
* @memberOf module:defaults
*/
sortOnDoubleClick: true,
/**
* **This is a standard property definition for sort plug-in use.
* It is not referenced in core.**
*
* The maximum number of columns that may participate in a multi-column sort (via ctrl-click headers).
* @default
* @type {number}
* @memberOf module:defaults
*/
maxSortColumns : 3,
/**
* **This is a standard property definition for sort plug-in use.
* It is not referenced in core.**
*
* Column(s) participating and subsequently hidden still affect sort.
*
* @default
* @type {boolean}
* @memberOf module:defaults
*/
sortOnHiddenColumns: true,
/**
* @summary Retain row selections.

@@ -1231,4 +1344,26 @@ * @desc When falsy, row selections are cleared when selecting cells; when truthy, row selections are kept as is when selecting cells.

*/
rowProperties: undefined,
rowStripes: undefined,
// for Renderer.prototype.assignProps
propClassEnum: propClassEnum,
propClassLayers: [ propClassEnum.COLUMNS, propClassEnum.STRIPES, propClassEnum.ROWS, propClassEnum.CELLS ],
/**
* Used to access registered features -- unless behavior has a non-empty `features` property (array of feature contructors).
*/
features: [
'filters',
'cellselection',
'keypaging',
'columnresizing',
// 'rowresizing',
'rowselection',
'columnselection',
'columnmoving',
'columnsorting',
'cellclick',
'cellediting',
'onhover'
],
/** @summary How to truncate text.

@@ -1247,2 +1382,22 @@ * @desc A "quaternary" value, one of:

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.)');
}
}
Object.defineProperty(defaults, 'rowProperties', {
get: function() {
rowPropertiesDeprecationWarning();
return this.rowStripes;
},
set: function(rowProperties) {
rowPropertiesDeprecationWarning();
this.rowStripes = rowProperties;
}
});
/** @typedef {string} cssColor

@@ -1249,0 +1404,0 @@ * @see https://developer.mozilla.org/en-US/docs/Web/CSS/color_value

@@ -18,21 +18,7 @@ 'use strict';

handleDoubleClick: function(grid, event) {
if (
grid.properties.editOnDoubleClick &&
event.isDataCell
) {
grid.onEditorActivate(event);
} else if (this.next) {
this.next.handleDoubleClick(grid, event);
}
edit.call(this, grid, event);
},
handleClick: function(grid, event) {
if (
!grid.properties.editOnDoubleClick &&
event.isDataCell
) {
grid.onEditorActivate(event);
} else if (this.next) {
this.next.handleClick(grid, event);
}
edit.call(this, grid, event, true);
},

@@ -75,2 +61,17 @@

// Note: Keep ! in place to convert both sides to bool for
// accurate equality test because either could be undefined.
function edit(grid, event, onDoubleClick) {
if (
event.isDataCell &&
!event.getCellProperty('editOnDoubleClick') === !onDoubleClick // caution see note
) {
grid.onEditorActivate(event);
}
if (this.next) {
this.next[onDoubleClick ? 'handleDoubleClick' : 'handleClick'](grid, event);
}
}
module.exports = CellEditing;

@@ -99,3 +99,3 @@ 'use strict';

var detail = event.detail,
cellEvent = grid.getGridCellFromLastSelection(),
cellEvent = grid.getGridCellFromLastSelection(true),
navKey = cellEvent && (

@@ -107,2 +107,3 @@ cellEvent.properties.mappedNavKey(detail.char, detail.ctrl) ||

// STEP 1: Move the selection

@@ -113,3 +114,3 @@ if (handler) {

// STEP 2: Open the cell editor at the new position if it has `editOnNextCell` and is `editable`
cellEvent = grid.getGridCellFromLastSelection(); // new cell
cellEvent = grid.getGridCellFromLastSelection(true); // new cell
if (cellEvent.properties.editOnNextCell) {

@@ -116,0 +117,0 @@ grid.editAt(cellEvent); // succeeds only if `editable`

@@ -117,7 +117,3 @@ 'use strict';

//delay here to give other events a chance to be dropped
//var self = this;
grid.synchronizeScrollingBoundaries();
// setTimeout(function() {
// self.attachChain();
// }, 200);
grid.behaviorShapeChanged();
} else if (this.next) {

@@ -124,0 +120,0 @@ this.next.handleMouseUp(grid, event);

@@ -6,11 +6,2 @@ 'use strict';

/**
* Extra msecs to avoid race condition with fincanvas's double click timer.
* @type {number}
* @defaultvalue 50
* NOTE: 50 msecs seems to work well. 10 and even 25 proved insufficient in Chrome.
* @private
*/
var RACE_TIME = 50;
/**
* @constructor

@@ -96,7 +87,6 @@ * @extends Feature

// HOLD OFF WHILE WAITING FOR DOUBLE-CLICK
this.doubleClickTimer = setTimeout(function() {
this.doubleClickTimer = undefined;
this.dragging = true;
this.extendSelection(grid, event.gridCell.x, event.primitiveEvent.detail.keys);
}.bind(this), grid.properties.doubleClickDelay + RACE_TIME);
this.doubleClickTimer = setTimeout(
doubleClickTimerCallback.bind(this, grid, event),
doubleClickDelay.call(this, grid, event)
);
} else if (this.next) {

@@ -439,2 +429,19 @@ this.next.handleMouseDown(grid, event);

function doubleClickDelay(grid, event) {
var columnProperties;
return (
event.isHeaderCell &&
!(columnProperties = event.columnProperties).unsortable &&
columnProperties.sortOnDoubleClick &&
300
);
}
function doubleClickTimerCallback(grid, event) {
this.doubleClickTimer = undefined;
this.dragging = true;
this.extendSelection(grid, event.gridCell.x, event.primitiveEvent.detail.keys);
}
module.exports = ColumnSelection;

@@ -16,14 +16,13 @@ 'use strict';

*/
handleClick: function(grid, event) {
sort.call(this, grid, event);
},
/**
* @memberOf ColumnSorting.prototype
* @param {Hypergrid} grid
* @param {Object} event - the event details
*/
handleDoubleClick: function(grid, event) {
var columnProperties;
if (
event.isHeaderCell &&
(columnProperties = grid.behavior.getColumnProperties(event.gridCell.x)) &&
!columnProperties.unsortable
) {
grid.fireSyntheticColumnSortEvent(event.gridCell.x, event.primitiveEvent.detail.keys);
} else if (this.next) {
this.next.handleDoubleClick(grid, event);
}
sort.call(this, grid, event, true);
},

@@ -55,2 +54,19 @@

// Note: Keep ! in place to convert both sides to bool for
// accurate equality test because either could be undefined.
function sort(grid, event, onDoubleClick) {
var columnProperties;
if (
event.isHeaderCell &&
!(columnProperties = event.columnProperties).unsortable &&
!columnProperties.sortOnDoubleClick === !onDoubleClick // caution see note
) {
grid.fireSyntheticColumnSortEvent(event.gridCell.x, event.primitiveEvent.detail.keys);
}
if (this.next) {
this.next[onDoubleClick ? 'handleDoubleClick' : 'handleClick'](grid, event);
}
}
module.exports = ColumnSorting;

@@ -309,2 +309,6 @@ 'use strict';

Feature.abstract = true; // don't instantiate directly
module.exports = Feature;
'use strict';
module.exports = {
Feature: require('./Feature'), // abstract base class
CellClick: require('./CellClick'),
CellEditing: require('./CellEditing'),
CellSelection: require('./CellSelection'),
ColumnMoving: require('./ColumnMoving'),
ColumnResizing: require('./ColumnResizing'),
ColumnSelection: require('./ColumnSelection'),
ColumnSorting: require('./ColumnSorting'),
Filters: require('./Filters'),
KeyPaging: require('./KeyPaging'),
OnHover: require('./OnHover'),
// RowResizing: require('./RowResizing'),
RowSelection: require('./RowSelection'),
ThumbwheelScrolling: require('./ThumbwheelScrolling')
};
var Registry = require('../lib/Registry');
/**
* @classdesc Registry of feature constructors.
* @param {boolean} [privateRegistry=false] - This instance will use a private registry.
* @constructor
*/
var Features = Registry.extend('Features', {
BaseClass: require('./Feature'), // abstract base class
items: {}, // shared feature registry (when !options.private)
initialize: function(options) {
// preregister the standard cell renderers
if (options && options.private || !this.items.cellclick) {
this.add(require('./CellClick'));
this.add(require('./CellEditing'));
this.add(require('./CellSelection'));
this.add(require('./ColumnMoving'));
this.add(require('./ColumnResizing'));
this.add(require('./ColumnSelection'));
this.add(require('./ColumnSorting'));
this.add(require('./Filters'));
this.add(require('./KeyPaging'));
this.add(require('./OnHover'));
// this.add(require('./RowResizing'));
this.add(require('./RowSelection'));
this.add(require('./ThumbwheelScrolling'));
}
}
});
Features.add = Registry.prototype.add.bind(Features);
// Following shared props provided solely in support of build file usage, e.g., `fin.Hypergrid.features.yada`,
// and are not meant to be used elsewhere.
Features.Feature = require('./Feature'); // abstract base class
Features.CellClick = require('./CellClick');
Features.CellEditing = require('./CellEditing');
Features.CellSelection = require('./CellSelection');
Features.ColumnMoving = require('./ColumnMoving');
Features.ColumnResizing = require('./ColumnResizing');
Features.ColumnSelection = require('./ColumnSelection');
Features.ColumnSorting = require('./ColumnSorting');
Features.Filters = require('./Filters');
Features.KeyPaging = require('./KeyPaging');
Features.OnHover = require('./OnHover');
// Features.RowResizing = require('./RowResizing');
Features.RowSelection = require('./RowSelection');
Features.ThumbwheelScrolling = require('./ThumbwheelScrolling');
module.exports = Features;

@@ -205,3 +205,3 @@ 'use strict';

var mouseY = grid.getMouseDown().y,
hasSHIFT = keys.indexOf('SHIFT') > 0;
hasSHIFT = keys.indexOf('SHIFT') !== -1;

@@ -208,0 +208,0 @@ if (y < 0) { // outside of the grid?

@@ -78,4 +78,2 @@ /* eslint-env browser */

}
return result;
};

@@ -82,0 +80,0 @@

@@ -90,2 +90,5 @@ /* eslint-env browser */

});
this.addEventListener('dblclick', function(e) {
self.findblclick(e);
});
this.addEventListener('contextmenu', function(e) {

@@ -98,3 +101,2 @@ self.fincontextmenu(e);

this.canvas.setAttribute('tabindex', 0);
this.canvas.contentEditable = true;

@@ -128,3 +130,2 @@ this.resize();

hasMouse: false,
lastDoubleClickTime: 0,
dragEndTime: 0,

@@ -219,5 +220,25 @@ lastRepaintTime: 0,

getDivBoundingClientRect: function() {
// Make sure our canvas has integral dimensions
var rect = this.div.getBoundingClientRect();
var top = Math.floor(rect.top),
left = Math.floor(rect.left),
width = Math.ceil(rect.width),
height = Math.ceil(rect.height);
return {
top: top,
right: left + width,
bottom: top + height,
left: left,
width: width,
height: height,
x: rect.x,
y: rect.y
};
},
checksize: function() {
//this is expensive lets do it at some modulo
var sizeNow = this.div.getBoundingClientRect();
var sizeNow = this.getDivBoundingClientRect();
if (sizeNow.width !== this.size.width || sizeNow.height !== this.size.height) {

@@ -229,3 +250,3 @@ this.resize();

resize: function() {
var box = this.size = this.div.getBoundingClientRect();
var box = this.size = this.getDivBoundingClientRect();

@@ -359,2 +380,6 @@ this.width = box.width;

finmouseup: function(e) {
if (!this.mousedown) {
// ignore document:mouseup unless preceded by a canvas:mousedown
return;
}
if (this.isDragging()) {

@@ -397,14 +422,6 @@ this.dispatchNewMouseKeysEvent(e, 'fin-canvas-dragend', {

finclick: function(e) {
var delay = this.component.properties.doubleClickDelay;
if (delay < 100) {
dispatchClickEvent.call(this, e);
} else if (this.doubleClickTimer && Date.now() - this.lastClickTime < delay) {
//this is a double click...
clearTimeout(this.doubleClickTimer); // prevent click event
this.doubleClickTimer = undefined;
this.findblclick(e);
} else {
this.lastClickTime = Date.now();
this.doubleClickTimer = setTimeout(dispatchClickEvent.bind(this, e), delay);
}
this.mouseLocation = this.getLocal(e);
this.dispatchNewMouseKeysEvent(e, 'fin-canvas-click', {
isRightClick: this.isRightClick(e)
});
},

@@ -414,7 +431,5 @@

this.mouseLocation = this.getLocal(e);
this.lastDoubleClickTime = Date.now();
this.dispatchNewMouseKeysEvent(e, 'fin-canvas-dblclick', {
isRightClick: this.isRightClick(e)
});
//console.log('dblclick', this.currentKeys);
},

@@ -512,4 +527,2 @@

fincontextmenu: function(e) {
var delay = this.component.properties.doubleClickDelay;
if (e.ctrlKey && this.currentKeys.indexOf('CTRL') === -1) {

@@ -519,14 +532,5 @@ this.currentKeys.push('CTRL');

if (delay < 100) {
dispatchContextMenuEvent.call(this, e);
} else if (this.doubleRightClickTimer && Date.now() - this.lastClickTime < delay) {
//this is a double click...
clearTimeout(this.doubleRightClickTimer); // prevent context menu event
this.doubleRightClickTimer = undefined;
this.findblclick(e);
} else {
this.lastClickTime = Date.now();
this.doubleRightClickTimer = setTimeout(dispatchContextMenuEvent.bind(this, e), delay);
}
this.dispatchNewMouseKeysEvent(e, 'fin-canvas-context-menu', {
isRightClick: this.isRightClick(e)
});
},

@@ -634,17 +638,2 @@

function dispatchClickEvent(e) {
this.doubleClickTimer = undefined;
this.mouseLocation = this.getLocal(e);
this.dispatchNewMouseKeysEvent(e, 'fin-canvas-click', {
isRightClick: this.isRightClick(e)
});
}
function dispatchContextMenuEvent(e) {
this.doubleRightClickTimer = undefined;
this.dispatchNewMouseKeysEvent(e, 'fin-canvas-context-menu', {
isRightClick: this.isRightClick(e)
});
}
function paintLoopFunction(now) {

@@ -789,4 +778,4 @@ if (paintRequest) {

map[121] = ['F10', 'F10SHIFT'];
map[122] = ['F11', 'F1S1HIFT'];
map[123] = ['F12', 'F121HIFT'];
map[122] = ['F11', 'F11SHIFT'];
map[123] = ['F12', 'F12SHIFT'];

@@ -793,0 +782,0 @@ return map;

@@ -12,10 +12,10 @@ 'use strict';

factory.prototypeDescriptors = Object.defineProperties({}, {
factory.cellEventProperties = Object.defineProperties({}, {
value: {
get: function() { return this.visibleRow.subgrid.getValue(this.dataCell.x, this.dataCell.y); },
set: function(value) { this.visibleRow.subgrid.setValue(this.dataCell.x, this.dataCell.y, value); }
get: function() { return this.subgrid.getValue(this.dataCell.x, this.dataCell.y); },
set: function(value) { this.subgrid.setValue(this.dataCell.x, this.dataCell.y, value); }
},
dataRow: {
get: function() { return this.visibleRow.subgrid.getRow(this.dataCell.y); }
get: function() { return this.subgrid.getRow(this.dataCell.y); }
},

@@ -55,5 +55,6 @@

} },
cellOwnProperties: { get: function() { // do not use for get/set prop because may return null; instead use .getCellProperty('prop') or .properties.prop (preferred) to get and setCellProperty('prop', value) to set
cellOwnProperties: { get: function() {
// do not use for get/set prop because may return null; instead use .getCellProperty('prop') or .properties.prop (preferred) to get, setCellProperty('prop', value) to set
if (this._cellOwnProperties === undefined) {
this._cellOwnProperties = this.column.getCellOwnProperties(this.dataCell.y, this.visibleRow.subgrid);
this._cellOwnProperties = this.column.getCellOwnProperties(this.dataCell.y, this.subgrid);
}

@@ -65,9 +66,37 @@ return this._cellOwnProperties; // null return means there is no cell properties object

} },
getCellProperty: { value: function(key) { // included for completeness but .properties[key] is preferred
getCellProperty: { value: function(key) {
// included for completeness but `.properties[key]` is preferred
return this.properties[key];
} },
setCellProperty: { value: function(key, value) { // do not use .cellOwnProperties[key] = value because object may be null (this method creates object as needed)
this._cellOwnProperties = this.column.setCellProperty(this.dataCell.y, key, value, this.visibleRow.subgrid);
setCellProperty: { value: function(key, value) {
// do not use `.cellOwnProperties[key] = value` because object may be null (this method creates new object as needed)
this._cellOwnProperties = this.column.setCellProperty(this.dataCell.y, key, value, this.subgrid);
} },
rowOwnProperties: {
// undefined return means there is no row properties object
get: function() {
return this.behavior.getRowProperties(this);
}
},
rowProperties: {
get: function() {
// use carefully! creates new object as needed; only use when object definitely needed: for setting prop with `.rowProperties[key] = value` or `Object.assign(.rowProperties, {...})`; use getRowProperty(key) instead for getting a property that may not exist because it will not create a new object
return this.behavior.getRowProperties(this, {});
},
set: function(properties) {
// for resetting whole row properties object: `.rowProperties = {...}`
this.behavior.setRowProperties(this, properties); // calls `stateChanged()`
}
},
getRowProperty: { value: function(key) {
// undefined return means there is no row properties object OR no such row property `[key]`
var rowProps = this.rowOwnProperties;
return rowProps && rowProps[key];
} },
setRowProperty: { value: function(key, value) {
// creates new object as needed
this.rowProperties[key] = value; // todo: call `stateChanged()` after refac-as-flags
} },
// special methods for use by renderer which reuses cellEvent object for performance reasons

@@ -108,3 +137,6 @@ reset: { value: function(visibleColumn, visibleRow) {

resetGridCY: { value: function(gridC, gridY) {
var vr, vc, visible = (vc = this.renderer.getVisibleColumn(gridC)) && (vr = this.renderer.getVisibleRow(gridY));
var vr, vc, visible = (
(vc = this.renderer.getVisibleColumn(gridC)) &&
(vr = this.renderer.getVisibleRow(gridY))
);
if (visible) { this.reset(vc, vr); }

@@ -123,3 +155,6 @@ return visible;

resetGridXY: { value: function(gridX, gridY) {
var vr, vc, visible = (vc = this.renderer.visibleColumns[gridX]) && (vr = this.renderer.getVisibleRow(gridY));
var vr, vc, visible = (
(vc = this.renderer.visibleColumns[gridX]) &&
(vr = this.renderer.getVisibleRow(gridY))
);
if (visible) { this.reset(vc, vr); }

@@ -139,3 +174,6 @@ return visible;

resetDataXY: { value: function(dataX, dataY, subgrid) {
var vr, vc, visible = (vc = this.renderer.getVisibleDataColumn(dataX)) && (vr = this.renderer.getVisibleDataRow(dataY, subgrid));
var vr, vc, visible = (
(vc = this.renderer.getVisibleDataColumn(dataX)) &&
(vr = this.renderer.getVisibleDataRow(dataY, subgrid))
);
if (visible) { this.reset(vc, vr); }

@@ -151,8 +189,33 @@ return visible;

* @param {dataModelAPI} [subgrid=this.behavior.subgrids.data]
* @param {boolean} [useAllCells] - Search in all rows and columns instead of only rendered ones.
* @returns {boolean} Visibility.
* @memberOf CellEvent#
*/
resetGridXDataY: { value: function(gridX, dataY, subgrid) {
var vr, vc, visible = (vc = this.renderer.getVisibleColumn(gridX)) && (vr = this.renderer.getVisibleDataRow(dataY, subgrid));
if (visible) { this.reset(vc, vr); }
resetGridXDataY: { value: function(gridX, dataY, subgrid, useAllCells) {
var visible, vc, vr;
if (useAllCells) {
// When expanding selections larger than the viewport, the origin/corner
// points may not be rendered and would normally fail to reset cell's position.
// Mock column and row objects for this.reset() to use:
vc = {
column: this.behavior.getColumn(gridX),
columnIndex: gridX
};
vr = {
subgrid: subgrid || this.behavior.subgrids.lookup.data,
rowIndex: dataY
};
visible = true;
} else {
visible = (
(vc = this.renderer.getVisibleColumn(gridX)) &&
(vr = this.renderer.getVisibleDataRow(dataY, subgrid))
);
}
if (visible) {
this.reset(vc, vr);
}
return visible && this;

@@ -195,3 +258,3 @@ } },

isDataRow: { get: function() { return this.visibleRow.subgrid.isData; } },
isDataRow: { get: function() { return this.subgrid.isData; } },
isDataColumn: { get: function() { return this.gridCell.x >= 0; } },

@@ -212,24 +275,24 @@ isDataCell: { get: function() { return this.isDataRow && this.isDataColumn; } },

isHandleColumn: { get: function() { return this.gridCell.x === this.grid.behavior.rowColumnIndex && this.grid.properties.showRowNumbers; } },
isHandleColumn: { get: function() { return this.gridCell.x === this.behavior.rowColumnIndex && this.grid.properties.showRowNumbers; } },
isHandleCell: { get: function() { return this.isHandleColumn && this.isDataRow; } },
isTreeColumn: { get: function() { return this.gridCell.x === this.grid.behavior.treeColumnIndex; } },
isTreeColumn: { get: function() { return this.gridCell.x === this.behavior.treeColumnIndex; } },
isHeaderRow: { get: function() { return this.visibleRow.subgrid.isHeader; } },
isHeaderRow: { get: function() { return this.subgrid.isHeader; } },
isHeaderHandle: { get: function() { return this.isHeaderRow && this.isHandleColumn; } },
isHeaderCell: { get: function() { return this.isHeaderRow && this.isDataColumn; } },
isFilterRow: { get: function() { return this.visibleRow.subgrid.isFilter; } },
isFilterRow: { get: function() { return this.subgrid.isFilter; } },
isFilterHandle: { get: function() { return this.isFilterRow && this.isHandleColumn; } },
isFilterCell: { get: function() { return this.isFilterRow && this.isDataColumn; } },
isSummaryRow: { get: function() { return this.visibleRow.subgrid.isSummary; } },
isSummaryRow: { get: function() { return this.subgrid.isSummary; } },
isSummaryHandle: { get: function() { return this.isSummaryRow && this.isHandleColumn; } },
isSummaryCell: { get: function() { return this.isSummaryRow && this.isDataColumn; } },
isTopTotalsRow: { get: function() { return this.visibleRow.subgrid === this.behavior.subgrids.lookup.topTotals; } },
isTopTotalsRow: { get: function() { return this.subgrid === this.behavior.subgrids.lookup.topTotals; } },
isTopTotalsHandle: { get: function() { return this.isTopTotalsRow && this.isHandleColumn; } },
isTopTotalsCell: { get: function() { return this.isTopTotalsRow && this.isDataColumn; } },
isBottomTotalsRow: { get: function() { return this.visibleRow.subgrid === this.behavior.subgrids.lookup.bottomTotals; } },
isBottomTotalsRow: { get: function() { return this.subgrid === this.behavior.subgrids.lookup.bottomTotals; } },
isBottomTotalsHandle: { get: function() { return this.isBottomTotalsRow && this.isHandleColumn; } },

@@ -350,5 +413,3 @@ isBottomTotalsCell: { get: function() { return this.isBottomTotalsRow && this.isDataColumn; } },

CellEvent.prototype = Object.create(factory.prototypeDescriptors);
Object.defineProperties(CellEvent.prototype, {
CellEvent.prototype = Object.create(factory.cellEventProperties, {
constructor: { value: CellEvent },

@@ -355,0 +416,0 @@ grid: { value: grid },

'use strict';
var warnedDoubleClickDelay;
/**

@@ -41,3 +43,7 @@ * @summary Dynamic grid property getter/setters.

set: function(subgrids) {
this.grid.behavior.subgrids = this.var.subgrids = subgrids;
this.var.subgrids = subgrids;
if (this.grid.behavior) {
this.grid.behavior.subgrids = subgrids;
}
}

@@ -49,2 +55,19 @@ },

*/
features: {
enumerable: true,
get: function() {
return this.var.features;
},
set: function(features) {
this.var.features = features;
if (this.grid.behavior) {
this.grid.behavior.initializeFeatureChain(features);
this.grid.allowEvents(this.grid.getRowCount());
}
}
},
/**
* @memberOf module:dynamicPropertyDescriptors
*/
gridRenderer: {

@@ -133,3 +156,80 @@ enumerable: true,

}
}
},
/**
* @memberOf module:dynamicPropertyDescriptors
*/
rowHeaderCheckboxes: {
enumerable: true,
get: function() {
return this.var.rowHeaderCheckboxes;
},
set: function(enabled) {
this.var.rowHeaderCheckboxes = enabled;
this.grid.renderer.resetRowHeaderColumnWidth();
}
},
/**
* @memberOf module:dynamicPropertyDescriptors
*/
rowHeaderNumbers: {
enumerable: true,
get: function() {
return this.var.rowHeaderNumbers;
},
set: function(enabled) {
this.var.rowHeaderNumbers = enabled;
this.grid.renderer.resetRowHeaderColumnWidth();
}
},
/**
* Legacy property; now points to both `rowHeaderFeatures` props.
* @memberOf module:dynamicPropertyDescriptors
*/
showRowNumbers: {
enumerable: false,
get: function() {
return this.rowHeaderCheckboxes || this.rowHeaderNumbers;
},
set: function(enabled) {
this.rowHeaderCheckboxes = this.rowHeaderNumbers = enabled;
}
},
// remove to expire warning:
doubleClickDelay: {
enumerable: true,
get: function() {
return this.var.doubleClickDelay;
},
set: function(delay) {
if (!warnedDoubleClickDelay) {
warnedDoubleClickDelay = true;
console.warn('The doubleClickDelay property has been deprecated as of v2.1.0. Setting this property no longer has any effect. Set double-click speed in your system\'s mouse preferences. (This warning will be removed in a future release.)');
}
this.var.doubleClickDelay = delay;
}
},
// The following grid line props are now dynamic (as of v2.1.0).
// They non-enumerable so they will not be output with `grid.saveState()`.
// The new (as of 2.1.0) props they refer to is output instead:
// `gridLinesHColor`, `gridLinesVColor`, `gridLinesHWidth`, and `gridLinesVWidth`
lineColor: {
get: function() { return this.gridLinesHColor; },
set: function(color) { this.gridLinesHColor = this.gridLinesVColor = color; }
},
lineWidth: {
get: function() { return this.gridLinesHWidth; },
set: function(width) { this.gridLinesHWidth = this.gridLinesVWidth = width; }
},
gridBorder: getGridBorderDescriptor(),
gridBorderLeft: getGridBorderDescriptor('Left'),
gridBorderRight: getGridBorderDescriptor('Right'),
gridBorderTop: getGridBorderDescriptor('Top'),
gridBorderBottom: getGridBorderDescriptor('Bottom')
};

@@ -139,9 +239,10 @@

var subgrids = {};
this.grid.behavior.subgrids.forEach(function(dataModel) {
var behavior = this.grid.behavior;
behavior.subgrids.forEach(function(dataModel) {
var key = dataModel.name || dataModel.type;
for (var rowIndex = 0, rowCount = dataModel.getRowCount(); rowIndex < rowCount; ++rowIndex) {
var height = dataModel.getRow(rowIndex).__ROW_HEIGHT;
if (height !== undefined) {
var rowProps = behavior.getRowProperties(rowIndex, undefined, dataModel);
if (rowProps) {
var subgrid = subgrids[key] = subgrids[key] || {};
subgrid[rowIndex] = { height: height };
subgrid[rowIndex] = rowProps;
}

@@ -284,2 +385,31 @@ }

function getGridBorderDescriptor(edge) {
edge = edge || '';
var propName = 'gridBorder' + edge,
styleName = 'border' + edge;
return {
enumerable: true,
get: function() {
return this.var[propName];
},
set: function(border) {
this.var[propName] = border;
if (!edge) {
this.var.gridBorderLeft = this.var.gridBorderRight = this.var.gridBorderTop = this.var.gridBorderBottom = border;
}
switch (border) {
case true:
border = this.lineWidth + 'px solid ' + this.lineColor;
break;
case false:
border = null;
break;
}
this.grid.canvas.canvas.style[styleName] = border;
}
};
}
module.exports = dynamicPropertyDescriptors;

@@ -29,3 +29,3 @@ /* eslint-env browser */

decorator: function(e) {
if (self.allowEventHandlers){
if (self.allowEventHandlers) {
listener(e);

@@ -91,6 +91,10 @@ }

allowEvents: function(allow){
if ((this.allowEventHandlers = !!allow)){
this.behavior.featureChain.attachChain();
} else {
this.behavior.featureChain.detachChain();
this.allowEventHandlers = !!allow;
if (this.behavior.featureChain) {
if (allow){
this.behavior.featureChain.attachChain();
} else {
this.behavior.featureChain.detachChain();
}
}

@@ -150,15 +154,7 @@

fireSyntheticRowSelectionChangedEvent: function() {
return dispatchEvent.call(this, 'fin-row-selection-changed', {
rows: this.getSelectedRows(),
columns: this.getSelectedColumns(),
selections: this.selectionModel.getSelections(),
});
},
return dispatchEvent.call(this, 'fin-row-selection-changed', this.selectionDetailGetters);
},
fireSyntheticColumnSelectionChangedEvent: function() {
return dispatchEvent.call(this, 'fin-column-selection-changed', {
rows: this.getSelectedRows(),
columns: this.getSelectedColumns(),
selections: this.selectionModel.getSelections()
});
return dispatchEvent.call(this, 'fin-column-selection-changed', this.selectionDetailGetters);
},

@@ -172,5 +168,3 @@

fireSyntheticContextMenuEvent: function(event) {
event.rows = this.getSelectedRows();
event.columns = this.getSelectedColumns();
event.selections = this.selectionModel.getSelections();
Object.defineProperties(event, this.selectionDetailGetterDescriptors);
return dispatchEvent.call(this, 'fin-context-menu', {}, event);

@@ -180,5 +174,3 @@ },

fireSyntheticMouseUpEvent: function(event) {
event.rows = this.getSelectedRows();
event.columns = this.getSelectedColumns();
event.selections = this.selectionModel.getSelections();
Object.defineProperties(event, this.selectionDetailGetterDescriptors);
return dispatchEvent.call(this, 'fin-mouseup', {}, event);

@@ -188,5 +180,3 @@ },

fireSyntheticMouseDownEvent: function(event) {
event.rows = this.getSelectedRows();
event.columns = this.getSelectedColumns();
event.selections = this.selectionModel.getSelections();
Object.defineProperties(event, this.selectionDetailGetterDescriptors);
return dispatchEvent.call(this, 'fin-mousedown', {}, event);

@@ -350,2 +340,6 @@ },

function handleMouseEvent(e, cb) {
if (self.getRowCount() === 0) {
return;
}
var c = self.getGridCellFromMousePoint(e.detail.mouse),

@@ -352,0 +346,0 @@ primitiveEvent,

@@ -8,2 +8,23 @@ /* eslint-env browser */

module.exports = {
selectionInitialize: function() {
var grid = this;
/** for use by fin-selection-changed, fin-row-selection-changed, fin-column-selection-changed
* @memberOf Hypergrid#
* @private
*/
this.selectionDetailGetters = {
get rows() { return grid.getSelectedRows(); },
get columns() { return grid.getSelectedColumns(); },
get selections() { return grid.selectionModel.getSelections(); }
};
/**
* for use by fin-context-menu, fin-mouseup, fin-mousedown
* @memberOf Hypergrid#
* @private
*/
this.selectionDetailGetterDescriptors = Object.getOwnPropertyDescriptors(this.selectionDetailGetters);
},
/**

@@ -510,7 +531,3 @@ * @memberOf Hypergrid#

var selectionEvent = new CustomEvent('fin-selection-changed', {
detail: {
rows: this.getSelectedRows(),
columns: this.getSelectedColumns(),
selections: this.selectionModel.getSelections(),
}
detail: this.selectionDetailGetters
});

@@ -550,2 +567,3 @@ this.canvas.dispatchEvent(selectionEvent);

}
this.fireSyntheticRowSelectionChangedEvent();
}

@@ -675,4 +693,4 @@ },

this.clearMostRecentSelection();
this.select(origin.x, origin.y, newX, newY);
this.setDragExtent(this.newPoint(newX, newY));

@@ -690,5 +708,6 @@

* @returns {undefined|CellEvent}
* @param {boolean} [useAllCells] - Search in all rows and columns instead of only rendered ones.
* @memberOf Hypergrid#
*/
getGridCellFromLastSelection: function() {
getGridCellFromLastSelection: function(useAllCells) {
var cellEvent,

@@ -699,3 +718,3 @@ sel = this.selectionModel.getLastSelection();

cellEvent = new this.behavior.CellEvent;
cellEvent.resetGridXDataY(sel.origin.x, sel.origin.y);
cellEvent.resetGridXDataY(sel.origin.x, sel.origin.y, null, useAllCells);
}

@@ -702,0 +721,0 @@

@@ -23,10 +23,10 @@ 'use strict';

gridPrefillColor = gridProps.backgroundColor,
rowPropsList = gridProps.rowProperties,
rowStripes = gridProps.rowStripes,
rowPrefillColors = Array(R),
rowProperties, backgroundColor;
stripe, backgroundColor;
for (r = 0; r < R; r++) {
vr = visibleRows[r]; // first cell in row r
rowProperties = vr.subgrid.isData && rowPropsList && rowPropsList[vr.rowIndex % rowPropsList.length];
backgroundColor = rowPrefillColors[r] = rowProperties && rowProperties.backgroundColor || gridPrefillColor;
stripe = vr.subgrid.isData && rowStripes && rowStripes[vr.rowIndex % rowStripes.length];
backgroundColor = rowPrefillColors[r] = stripe && stripe.backgroundColor || gridPrefillColor;
if (bundle && bundle.backgroundColor === backgroundColor) {

@@ -33,0 +33,0 @@ bundle.bottom = vr.bottom;

@@ -40,4 +40,5 @@ 'use strict';

viewHeight = R ? visibleRows[R - 1].bottom : 0,
lineWidth = gridProps.lineWidth,
lineColor = gridProps.lineColor;
drawLines = gridProps.gridLinesH,
lineWidth = gridProps.gridLinesHWidth,
lineColor = gridProps.gridLinesHColor;

@@ -72,3 +73,3 @@ gc.clearRect(0, 0, this.bounds.width, this.bounds.height);

if (gridProps.gridLinesH) {
if (drawLines) {
gc.cache.fillStyle = lineColor;

@@ -75,0 +76,0 @@ gc.fillRect(0, pool[p].visibleRow.bottom, viewWidth, lineWidth);

@@ -10,9 +10,26 @@ /* eslint-env browser */

var propClassGet = [
undefined,
function(cellEvent) {
return cellEvent.columnProperties;
},
function(cellEvent) {
var rowStripes = cellEvent.isDataRow && cellEvent.columnProperties.rowStripes;
return rowStripes && rowStripes[cellEvent.dataCell.y % rowStripes.length];
},
function(cellEvent) {
return cellEvent.rowOwnProperties;
},
function(cellEvent) {
return cellEvent.cellOwnProperties;
}
];
var visibleColumnPropertiesDescriptorFn = function(grid) {
return {
findWithNeg: {
// Like the Array.prototype version except searches negative indexes as well.
// Like the Array.prototype version except searches the negative indexes as well.
value: function(iteratee, context) {
for (var i = grid.behavior.leftMostColIndex; i in this; --i); // eslint-disable-line curly
while (++i) {
for (var i = grid.behavior.leftMostColIndex; i < 0; i++) {
if (!this[i]) {

@@ -29,6 +46,5 @@ continue;

forEachWithNeg: {
// Like the Array.prototype version except it iterates negative indexes as well.
// Like the Array.prototype version except it iterates the negative indexes as well.
value: function(iteratee, context) {
for (var i = grid.behavior.leftMostColIndex; i in this; --i); // eslint-disable-line curly
while (++i) {
for (var i = grid.behavior.leftMostColIndex; i < 0; i++) {
if (!this[i]) {

@@ -217,211 +233,8 @@ continue;

/**
* This function creates several data structures:
* * {@link Renderer#visibleColumns}
* Original comment:
* "this function computes the grid coordinates used for extremely fast iteration over
* painting the grid cells. this function is very fast, for thousand rows X 100 columns
* on a modest machine taking usually 0ms and no more that 3 ms."
*/
resetRowHeaderColumnWidth: function() {
this.lastKnowRowCount = undefined;
},
computeCellsBounds: function() {
//var startTime = Date.now();
var scrollTop = this.getScrollTop(),
scrollLeft = this.getScrollLeft(),
fixedColumnCount = this.grid.getFixedColumnCount(),
fixedRowCount = this.grid.getFixedRowCount(),
bounds = this.getBounds(),
grid = this.grid,
behavior = grid.behavior,
editorCellEvent = grid.cellEditor && grid.cellEditor.event,
vcEd, xEd,
vrEd, yEd,
sgEd, isSubgridEd,
insertionBoundsCursor = 0,
previousInsertionBoundsCursorValue = 0,
lineWidth = grid.properties.lineWidth,
start = 0,
numOfInternalCols = 0,
x, X, // horizontal pixel loop index and limit
y, Y, // vertical pixel loop index and limit
c, C, // column loop index and limit
g, G, // subgrid loop index and limit
r, R, // row loop index and limitrows in current subgrid
subrows, // rows in subgrid g
base, // sum of rows for all subgrids so far
subgrids = behavior.subgrids,
subgrid,
rowIndex,
scrollableSubgrid,
footerHeight,
vx, vy,
vr, vc,
width, height,
firstVX, lastVX,
firstVY, lastVY,
topR,
xSpaced, widthSpaced, heightSpaced; // adjusted for cell spacing
if (editorCellEvent) {
xEd = editorCellEvent.gridCell.x;
yEd = editorCellEvent.dataCell.y;
sgEd = editorCellEvent.subgrid;
}
if (grid.properties.showRowNumbers) {
start = behavior.rowColumnIndex;
numOfInternalCols = Math.abs(start);
}
this.scrollHeight = 0;
this.visibleColumns.length = 0;
this.visibleRows.length = 0;
this.visibleColumnsByIndex = []; // array because number of columns will always be reasonable
this.visibleRowsByDataRowIndex = {}; // hash because keyed by (fixed and) scrolled row indexes
this.insertionBounds = [];
for (
x = 0, c = start, C = grid.getColumnCount(), X = bounds.width || grid.canvas.width;
c < C && x <= X;
c++
) {
if (c === behavior.treeColumnIndex && !behavior.hasTreeColumn()) {
numOfInternalCols = (numOfInternalCols > 0) ? numOfInternalCols - 1 : 0;
this.visibleColumns[c] = undefined;
continue;
}
vx = c;
if (c >= fixedColumnCount) {
lastVX = vx += scrollLeft;
if (firstVX === undefined) {
firstVX = lastVX;
}
}
if (vx >= C) {
break; // scrolled beyond last column
}
width = Math.ceil(behavior.getColumnWidth(vx));
xSpaced = x ? x + lineWidth : x;
widthSpaced = x ? width - lineWidth : width;
this.visibleColumns[c] = this.visibleColumnsByIndex[vx] = vc = {
index: c,
columnIndex: vx,
column: behavior.getActiveColumn(vx),
left: xSpaced,
width: widthSpaced,
right: xSpaced + widthSpaced
};
if (xEd === vx) {
vcEd = vc;
}
x += width;
insertionBoundsCursor += Math.round(width / 2) + previousInsertionBoundsCursorValue;
this.insertionBounds.push(insertionBoundsCursor);
previousInsertionBoundsCursorValue = Math.round(width / 2);
}
// get height of total number of rows in all subgrids following the data subgrid
footerHeight = grid.properties.defaultRowHeight *
subgrids.reduce(function(rows, subgrid) {
if (scrollableSubgrid) {
rows += subgrid.getRowCount();
} else {
scrollableSubgrid = subgrid.isData;
}
return rows;
}, 0);
for (
base = r = g = y = 0, G = subgrids.length, Y = bounds.height - footerHeight;
g < G;
g++, base += subrows
) {
subgrid = subgrids[g];
subrows = subgrid.getRowCount();
scrollableSubgrid = subgrid.isData;
isSubgridEd = (sgEd === subgrid);
topR = r;
// For each row of each subgrid...
for (R = r + subrows; r < R && y < Y; r++) {
vy = r;
if (scrollableSubgrid && r >= fixedRowCount) {
vy += scrollTop;
lastVY = vy - base;
if (firstVY === undefined) {
firstVY = lastVY;
}
if (vy >= R) {
break; // scrolled beyond last row
}
}
rowIndex = vy - base;
height = behavior.getRowHeight(rowIndex, subgrid);
heightSpaced = height - lineWidth;
this.visibleRows[r] = vr = {
index: r,
subgrid: subgrid,
rowIndex: rowIndex,
top: y,
height: heightSpaced,
bottom: y + heightSpaced
};
if (scrollableSubgrid) {
this.visibleRowsByDataRowIndex[vy - base] = vr;
}
if (isSubgridEd && yEd === rowIndex) {
vrEd = vr;
}
y += height;
}
if (scrollableSubgrid) {
subrows = r - topR;
Y += footerHeight;
}
}
if (editorCellEvent) {
editorCellEvent.visibleColumn = vcEd;
editorCellEvent.visibleRow = vrEd;
editorCellEvent.gridCell.y = vrEd && vrEd.index;
editorCellEvent._bounds = null;
}
this.viewHeight = Y;
this.dataWindow = this.grid.newRectangle(firstVX, firstVY, lastVX - firstVX, lastVY - firstVY);
// Resize CellEvent pool
var pool = this.cellEventPool,
previousLength = pool.length,
P = (this.visibleColumns.length + numOfInternalCols) * this.visibleRows.length;
if (P > previousLength) {
pool.length = P; // grow pool to accommodate more cells
}
for (var p = previousLength; p < P; p++) {
pool[p] = new behavior.CellEvent; // instantiate new members
}
this.resetAllGridRenderers();
this.needsComputeCellsBounds = true;
},

@@ -628,2 +441,62 @@

/**
* @desc Calculate the minimum left column index so the target column shows up in viewport (we need to be aware of viewport's width, number of fixed columns and each column's width)
* @param {number} targetColIdx - Target column index
* @returns {number} Minimum left column index so target column shows up
*/
getMinimumLeftPositionToShowColumn: function(targetColIdx) {
var fixedColumnCount = this.grid.getFixedColumnCount();
var fixedColumnsWidth = 0;
var rowNumbersWidth = 0;
var filtersWidth = 0;
var viewportWidth = 0;
var leftColIdx = 0;
var targetRight = 0;
var lastFixedColumn = null;
var computedCols = [];
var col = null;
var i = 0;
var left = 0;
var right = 0;
// 1) for each column, we'll compute left and right position in pixels (until target column)
for (i = 0; i <= targetColIdx; i++) {
left = right;
right += Math.ceil(this.grid.getColumnWidth(i));
computedCols.push({
left: left,
right: right
});
}
targetRight = computedCols[computedCols.length - 1].right;
// 2) calc usable viewport width
lastFixedColumn = computedCols[fixedColumnCount - 1];
if (this.properties.showRowNumbers) {
rowNumbersWidth = this.grid.getColumnWidth(this.grid.behavior.rowColumnIndex);
}
if (this.grid.hasTreeColumn()) {
filtersWidth = this.grid.getColumnWidth(this.grid.behavior.treeColumnIndex);
}
fixedColumnsWidth = lastFixedColumn ? lastFixedColumn.right : 0;
viewportWidth = this.getBounds().width - fixedColumnsWidth - rowNumbersWidth - filtersWidth;
// 3) from right to left, find the last column that can still render target column
i = targetColIdx;
do {
leftColIdx = i;
col = computedCols[i];
i--;
} while (col.left + viewportWidth > targetRight && i >= 0);
return leftColIdx;
},
/**
* @summary Get the visibility of the column matching the provided data column index.

@@ -734,7 +607,24 @@ * @desc Requested column may not be visible due to being scrolled out of view or if the column is inactive.

renderGrid: function(gc) {
this.grid.deferredBehaviorChange();
gc.beginPath();
this.buttonCells = {};
var rowCount = this.grid.getRowCount();
if (rowCount !== this.lastKnowRowCount) {
var newWidth = resetRowHeaderColumnWidth.call(this, gc, rowCount);
if (newWidth !== this.handleColumnWidth) {
this.needsComputeCellsBounds = true;
this.handleColumnWidth = newWidth;
}
this.lastKnowRowCount = rowCount;
}
if (this.needsComputeCellsBounds) {
computeCellsBounds.call(this);
this.needsComputeCellsBounds = false;
}
this.gridRenderer.paintCells.call(this, gc);
resetNumberColumnWidth(gc, this.grid.behavior);

@@ -981,38 +871,50 @@ this.renderOverrides(gc);

var gridProps = this.properties,
lineWidth = gridProps.lineWidth,
lineColor = gridProps.lineColor;
viewWidth = visibleColumns[C - 1].right,
viewHeight = visibleRows[R - 1].bottom;
if (gridProps.gridLinesV) {
gc.cache.fillStyle = lineColor;
var viewHeight = visibleRows[R - 1].bottom,
c = this.grid.behavior.leftMostColIndex;
if (gridProps.gridBorderLeft) {
gc.fillRect(visibleColumns[c].left, 0, lineWidth, viewHeight);
gc.cache.fillStyle = gridProps.gridLinesVColor;
for (var right, vc = visibleColumns[0], c = 1; c < C; c++) {
right = vc.right;
vc = visibleColumns[c];
if (!vc.gap) {
gc.fillRect(right, 0, gridProps.gridLinesVWidth, viewHeight);
}
}
//Don't Paint LeftMost Border
var first = true;
this.visibleColumns.forEachWithNeg(function(vc) {
first = false;
if (!first) { gc.fillRect(vc.left - lineWidth, 0, lineWidth, viewHeight); }
});
if (gridProps.gridBorderRight) {
gc.fillRect(visibleColumns[C - 1].right + 1 - lineWidth, 0, lineWidth, viewHeight);
}
}
if (gridProps.gridLinesH) {
gc.cache.fillStyle = lineColor;
var viewWidth = visibleColumns[C - 1].right;
if (gridProps.gridBorderTop) {
gc.fillRect(0, visibleRows[0].top, viewWidth, lineWidth);
gc.cache.fillStyle = gridProps.gridLinesHColor;
for (var bottom, vr = visibleRows[0], r = 1; r < R; r++) {
bottom = vr.bottom;
vr = visibleRows[r];
if (!vr.gap) {
gc.fillRect(0, bottom, viewWidth, gridProps.gridLinesHWidth);
}
}
if (!gridProps.gridBorderBottom) {
R -= 1;
}
var edgeWidth;
var gap = visibleRows.gap;
if (gap) {
gc.cache.fillStyle = gridProps.fixedLinesHColor || gridProps.gridLinesHColor;
edgeWidth = gridProps.fixedLinesHEdge;
if (edgeWidth) {
gc.fillRect(0, gap.top, viewWidth, edgeWidth);
gc.fillRect(0, gap.bottom - edgeWidth, viewWidth, edgeWidth);
} else {
gc.fillRect(0, gap.top, viewWidth, gap.bottom - gap.top);
}
if (gridProps.gridBorderRight) {
viewWidth += lineWidth;
}
gap = visibleColumns.gap;
if (gap) {
gc.cache.fillStyle = gridProps.fixedLinesVColor || gridProps.gridLinesVColor;
edgeWidth = gridProps.fixedLinesVEdge;
if (edgeWidth) {
gc.fillRect(gap.left, 0, edgeWidth, viewHeight);
gc.fillRect(gap.right - edgeWidth, 0, edgeWidth, viewHeight);
} else {
gc.fillRect(gap.left, 0, gap.right - gap.left, viewHeight);
}
for (var r = 0; r < R; r++) {
gc.fillRect(0, visibleRows[r].bottom, viewWidth, lineWidth);
}
}

@@ -1041,11 +943,2 @@ }

* @summary Render a single cell.
* @desc IMPORTANT NOTE: Do not change the line below with the comment "SEE IMPORTANT NOTE ABOVE" without careful performance testing. Building the config object from cell properties object produced much slower rendering times. The original line was:
* ```javascript
* config = Object.create(cellEvent.columnProperties),
* ```
* Cell properties object came into play when `cellEvent.properties` getter which returns cell properties object when there is one (else it returns column properties object). The reason seemed to be that doing so caused optimization to fail on the cell renderer function. The work-around was to always build the `config` object from the column properties object, and then _copy_ the "own" cell properties onto it. The current line is:
* ```javascript
* config = Object.assign(Object.create(cellEvent.columnProperties), cellEvent.cellOwnProperties),
* ```
* We kept the cell properties object prototype in place (extended from column properties) for other logic.
* @param {CanvasRenderingContext2D} gc

@@ -1062,3 +955,2 @@ * @param {CellEvent} cellEvent

behavior = grid.behavior,
subgrid = cellEvent.subgrid,

@@ -1079,3 +971,4 @@ isHandleColumn = cellEvent.isHandleColumn,

config = Object.assign(Object.create(cellEvent.columnProperties), cellEvent.cellOwnProperties), // SEE IMPORTANT NOTE ABOVE
config = this.assignProps(cellEvent),
x = (config.gridCell = cellEvent.gridCell).x,

@@ -1096,9 +989,4 @@ r = (config.dataCell = cellEvent.dataCell).y,

format = config.format;
// Iff we have a defined rowProperties array, apply it to config, treating it as a repeating pattern, keyed to row index.
// Note that Object.assign will ignore undefined.
var row = cellEvent.columnProperties.rowProperties;
Object.assign(config, row && row[cellEvent.dataCell.y % row.length]);
} else {
format = subgrid.format || config.format; // subgrid format can override column format
format = cellEvent.subgrid.format || config.format; // subgrid format can override column format
if (isFilterRow) {

@@ -1123,3 +1011,5 @@ isSelected = false;

// row handle for a data row
config.value = r + 1; // row number is 1-based
if (config.rowHeaderNumbers) {
config.value = r + 1; // row number is 1-based
}
} else if (isHeaderRow) {

@@ -1190,2 +1080,25 @@ // row handle for header row: gets "master" checkbox

/**
* Overridable for alternative or faster logic.
* @param cellEvent
*/
assignProps: function(cellEvent) {
var i, base, assignments,
propLayers = cellEvent.columnProperties.propClassLayers;
if (propLayers[0] !== 1) {
i = 0; // all prop layers
base = this.grid.properties;
} else {
i = 1; // skip column prop layer
base = cellEvent.columnProperties; // because column has grid properties as prototype
}
for (assignments = [Object.create(base)]; i < propLayers.length; ++i) {
assignments.push(propClassGet[propLayers[i]](cellEvent));
}
return Object.assign.apply(Object, assignments);
},
/**
* @param {number|CellEvent} colIndexOrCellEvent - This is the "data" x coordinate.

@@ -1264,22 +1177,298 @@ * @param {number} [rowIndex] - This is the "data" y coordinate. Omit if `colIndexOrCellEvent` is a `CellEvent`.

function resetNumberColumnWidth(gc, behavior) {
var rowCount = behavior.dataModel.getRowCount(),
columnProperties = behavior.getColumnProperties(behavior.rowColumnIndex),
cellProperties = columnProperties.rowHeader,
padding = 2 * columnProperties.cellPadding,
iconWidth = columnProperties.preferredWidth = Math.max(
images.checked ? images.checked.width : 0,
images.unchecked ? images.unchecked.width : 0
);
/**
* This function creates several data structures:
* * {@link Renderer#visibleColumns}
* * {@link Renderer#visibleRows}
*
* Original comment:
* "this function computes the grid coordinates used for extremely fast iteration over
* painting the grid cells. this function is very fast, for thousand rows X 100 columns
* on a modest machine taking usually 0ms and no more that 3 ms."
*
* @this {Renderer}
*/
function computeCellsBounds() {
//var startTime = Date.now();
gc.cache.font = cellProperties.foregroundSelectionFont.indexOf('bold ') >= 0
? cellProperties.foregroundSelectionFont : cellProperties.font;
var scrollTop = this.getScrollTop(),
scrollLeft = this.getScrollLeft(),
columnProperties.preferredWidth = iconWidth + padding + gc.getTextWidth(rowCount);
fixedColumnCount = this.grid.getFixedColumnCount(),
fixedRowCount = this.grid.getFixedRowCount(),
if (columnProperties.width === undefined) {
columnProperties.width = columnProperties.preferredWidth;
bounds = this.getBounds(),
grid = this.grid,
behavior = grid.behavior,
noTreeColumn = !behavior.hasTreeColumn(),
editorCellEvent = grid.cellEditor && grid.cellEditor.event,
vcEd, xEd,
vrEd, yEd,
sgEd, isSubgridEd,
insertionBoundsCursor = 0,
previousInsertionBoundsCursorValue = 0,
gridProps = grid.properties,
lineWidthV = gridProps.gridLinesVWidth,
lineWidthH = gridProps.gridLinesHWidth,
fixedWidthV = gridProps.fixedLinesVWidth || gridProps.gridLinesVWidth,
fixedWidthH = gridProps.fixedLinesHWidth || gridProps.gridLinesHWidth,
hasFixedColumnGap = fixedWidthV && fixedColumnCount,
hasFixedRowGap = fixedWidthH && fixedRowCount,
start = 0,
numOfInternalCols = 0,
x, X, // horizontal pixel loop index and limit
y, Y, // vertical pixel loop index and limit
c, C, // column loop index and limit
g, G, // subgrid loop index and limit
r, R, // row loop index and limit
subrows, // rows in subgrid g
base, // sum of rows for all subgrids so far
subgrids = behavior.subgrids,
subgrid,
rowIndex,
scrollableSubgrid,
footerHeight,
vx, vy,
vr, vc,
width, height,
firstVX, lastVX,
firstVY, lastVY,
topR,
gap,
left, widthSpaced, heightSpaced; // adjusted for cell spacing
if (editorCellEvent) {
xEd = editorCellEvent.gridCell.x;
yEd = editorCellEvent.dataCell.y;
sgEd = editorCellEvent.subgrid;
}
if (noTreeColumn) {
this.visibleColumns[behavior.treeColumnIndex] = undefined;
} else {
start = Math.min(start, behavior.treeColumnIndex);
numOfInternalCols += 1;
}
if (gridProps.showRowNumbers) {
start = Math.min(start, behavior.rowColumnIndex);
numOfInternalCols += 1;
}
this.scrollHeight = 0;
this.visibleColumns.length = 0;
this.visibleColumns.gap = undefined;
this.visibleRows.length = 0;
this.visibleRows.gap = undefined;
this.visibleColumnsByIndex = []; // array because number of columns will always be reasonable
this.visibleRowsByDataRowIndex = {}; // hash because keyed by (fixed and) scrolled row indexes
this.insertionBounds = [];
for (
x = 0, c = start, C = grid.getColumnCount(), X = bounds.width || grid.canvas.width;
c < C && x <= X;
c++
) {
if (noTreeColumn && c === behavior.treeColumnIndex) {
continue;
}
vx = c;
if (c >= fixedColumnCount) {
lastVX = vx += scrollLeft;
if (firstVX === undefined) {
firstVX = lastVX;
}
}
if (vx >= C) {
break; // scrolled beyond last column
}
width = Math.ceil(behavior.getColumnWidth(vx));
if (x) {
if ((gap = hasFixedColumnGap && c === fixedColumnCount)) {
x += fixedWidthV - lineWidthV;
this.visibleColumns.gap = {
left: vc.right,
right: undefined
};
}
left = x + lineWidthV;
widthSpaced = width - lineWidthV;
} else {
left = x;
widthSpaced = width;
}
this.visibleColumns[c] = this.visibleColumnsByIndex[vx] = vc = {
index: c,
columnIndex: vx,
column: behavior.getActiveColumn(vx),
gap: gap,
left: left,
width: widthSpaced,
right: left + widthSpaced
};
if (gap) {
this.visibleColumns.gap.right = vc.left;
}
if (xEd === vx) {
vcEd = vc;
}
x += width;
insertionBoundsCursor += Math.round(width / 2) + previousInsertionBoundsCursorValue;
this.insertionBounds.push(insertionBoundsCursor);
previousInsertionBoundsCursorValue = Math.round(width / 2);
}
// get height of total number of rows in all subgrids following the data subgrid
footerHeight = gridProps.defaultRowHeight *
subgrids.reduce(function(rows, subgrid) {
if (scrollableSubgrid) {
rows += subgrid.getRowCount();
} else {
scrollableSubgrid = subgrid.isData;
}
return rows;
}, 0);
for (
base = r = g = y = 0, G = subgrids.length, Y = bounds.height - footerHeight;
g < G;
g++, base += subrows
) {
subgrid = subgrids[g];
subrows = subgrid.getRowCount();
scrollableSubgrid = subgrid.isData;
isSubgridEd = (sgEd === subgrid);
topR = r;
// For each row of each subgrid...
for (R = r + subrows; r < R && y < Y; r++) {
vy = r;
if (scrollableSubgrid) {
if ((gap = hasFixedRowGap && r === fixedRowCount)) {
y += fixedWidthH - lineWidthH;
this.visibleRows.gap = {
top: vr.bottom,
bottom: undefined
};
}
if (r >= fixedRowCount) {
vy += scrollTop;
lastVY = vy - base;
if (firstVY === undefined) {
firstVY = lastVY;
}
if (vy >= R) {
break; // scrolled beyond last row
}
}
}
rowIndex = vy - base;
height = behavior.getRowHeight(rowIndex, subgrid);
heightSpaced = height - lineWidthH;
this.visibleRows[r] = vr = {
index: r,
subgrid: subgrid,
gap: gap,
rowIndex: rowIndex,
top: y,
height: heightSpaced,
bottom: y + heightSpaced
};
if (gap) {
this.visibleRows.gap.bottom = vr.top;
}
if (scrollableSubgrid) {
this.visibleRowsByDataRowIndex[vy - base] = vr;
}
if (isSubgridEd && yEd === rowIndex) {
vrEd = vr;
}
y += height;
}
if (scrollableSubgrid) {
subrows = r - topR;
Y += footerHeight;
}
}
if (editorCellEvent) {
editorCellEvent.visibleColumn = vcEd;
editorCellEvent.visibleRow = vrEd;
editorCellEvent.gridCell.y = vrEd && vrEd.index;
editorCellEvent._bounds = null;
}
this.viewHeight = Y;
this.dataWindow = this.grid.newRectangle(firstVX, firstVY, lastVX - firstVX, lastVY - firstVY);
// Resize CellEvent pool
var pool = this.cellEventPool,
previousLength = pool.length,
P = (this.visibleColumns.length + numOfInternalCols) * this.visibleRows.length;
if (P > previousLength) {
pool.length = P; // grow pool to accommodate more cells
}
for (var p = previousLength; p < P; p++) {
pool[p] = new behavior.CellEvent; // instantiate new members
}
this.resetAllGridRenderers();
}
/**
* @summary Resize the handle column.
* @desc Handle column width is sum of:
* * Width of text the maximum row number, if visible, based on handle column's current font
* * Width of checkbox, if visible
* * Some padding
*
* @this {Renderer}
* @param gc
* @param rowCount
*/
function resetRowHeaderColumnWidth(gc, rowCount) {
var columnProperties = this.grid.behavior.getColumnProperties(this.grid.behavior.rowColumnIndex),
gridProps = this.grid.properties,
width = 2 * columnProperties.cellPadding;
// Checking images.checked also supports a legacy feature in which checkbox could be hidden by undefining the image.
if (gridProps.rowHeaderCheckboxes && images.checked) {
width += images.checked.width;
}
if (gridProps.rowHeaderNumbers) {
var cellProperties = columnProperties.rowHeader;
gc.cache.font = cellProperties.foregroundSelectionFont.indexOf('bold ') >= 0
? cellProperties.foregroundSelectionFont
: cellProperties.font;
width += gc.getTextWidth(rowCount);
}
columnProperties.preferredWidth = columnProperties.width = width;
}
function registerGridRenderer(paintCellsFunction) {

@@ -1286,0 +1475,0 @@ if (paintCellsFunctions.indexOf(paintCellsFunction) < 0) {

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc