fin-hypergrid
Advanced tools
Comparing version 2.1.10 to 2.1.13
{ | ||
"name": "fin-hypergrid", | ||
"version": "2.1.10", | ||
"version": "2.1.13", | ||
"description": "Canvas-based high-performance grid", | ||
@@ -22,3 +22,3 @@ "repository": { | ||
"fin-hypergrid-event-logger": "^1.0.3", | ||
"finbars": "1.5.2", | ||
"finbars": "^1.6.0", | ||
"inject-stylesheet-template": "^1.0.1", | ||
@@ -25,0 +25,0 @@ "mustache": "^2.3.0", |
@@ -11,3 +11,3 @@ [![Build Status](https://travis-ci.org/openfin/fin-hypergrid.svg?branch=develop)](https://travis-ci.org/openfin/fin-hypergrid) | ||
## Table of Contents | ||
* [Current Release](#current-release-219---1-may-2018) | ||
* [Current Release](#current-release-2111---12-june-2018) | ||
* [Demos](#demos) | ||
@@ -20,5 +20,5 @@ * [Features](#features) | ||
### Current Release (2.1.9 - 1 May 2018) | ||
### Current Release (2.1.13 - 12 June 2018) | ||
**Hypergrid 2.1.9** includes bug fixes. | ||
**Hypergrid 2.1.13** includes bug fixes, new features, and a couple of additional demos. | ||
@@ -57,3 +57,3 @@ _For a complete list of changes, see the [release notes](https://github.com/fin-hypergrid/core/releases)._ | ||
We also maintain versioned [online API documentation](https://fin-hypergrid.github.io/core/2.1.9/doc/Hypergrid.html) for all public objects and modules. This documentation is necessarily an on-going work-in-progress. | ||
We also maintain versioned [online API documentation](https://fin-hypergrid.github.io/core/2.1.13/doc/Hypergrid.html) for all public objects and modules. This documentation is necessarily an on-going work-in-progress. | ||
@@ -64,3 +64,3 @@ (Cell editor information can be found [here](https://github.com/fin-hypergrid/core/wiki/Cell-Editors).) | ||
Hypergrid global configurations can be found [here](https://fin-hypergrid.github.io/core/2.1.9/doc/module-defaults.html). | ||
Hypergrid global configurations can be found [here](https://fin-hypergrid.github.io/core/2.1.13/doc/module-defaults.html). | ||
@@ -67,0 +67,0 @@ ### Roadmap |
@@ -13,11 +13,9 @@ /* eslint-env browser */ | ||
* @constructor | ||
* @param grid | ||
* @param {CellEvent} options - Properties listed below + arbitrary mustache "variables" for merging into template. | ||
* @param {Point} options.editPoint - Deprecated; use `options.gridCell`. | ||
* @param {string} [options.format] - Name of a localizer with which to override prototype's `localizer` property. | ||
*/ | ||
var CellEditor = Base.extend('CellEditor', { | ||
/** | ||
* @param grid | ||
* @param {CellEvent} options - Properties listed below + arbitrary mustache "variables" for merging into template. | ||
* @param {Point} options.editPoint - Deprecated; use `options.gridCell`. | ||
* @param {string} [options.format] - Name of a localizer with which to override prototype's `localizer` property. | ||
*/ | ||
initialize: function(grid, options) { | ||
@@ -138,2 +136,3 @@ // Mix in all enumerable properties for mustache use, typically `column` and `format`. | ||
char: keyChar, | ||
legacyChar: e.legacyKey, // decorated by getKeyChar | ||
code: e.charCode, | ||
@@ -253,13 +252,11 @@ key: e.keyCode, | ||
stopEditing: function(feedback) { | ||
/** | ||
* @type {boolean|string|Error} | ||
*/ | ||
var error = this.validateEditorValue(); | ||
var str = this.input.value; | ||
if (!error) { | ||
try { | ||
var value = this.getEditorValue(); | ||
} catch (err) { | ||
error = err; | ||
try { | ||
var error = this.validateEditorValue(str); | ||
if (!error) { | ||
var value = this.getEditorValue(str); | ||
} | ||
} catch (err) { | ||
error = err; | ||
} | ||
@@ -306,11 +303,13 @@ | ||
errorEffectBegin: function(error) { | ||
if (this.effecting) { | ||
return; | ||
} | ||
var spec = this.grid.properties.feedbackEffect, // spec may e a string or an object with name and options props | ||
options = Object.assign({}, spec.options), // if spec is a string, spec.options will be undefined | ||
effect = effects[spec.name || spec]; // if spec is a string, spec.name will be undefined | ||
if (error) { | ||
if (effect) { | ||
var options = Object.assign({}, spec.options); // if spec is a string, spec.options will be undefined | ||
options.callback = this.errorEffectEnd.bind(this, error); | ||
} | ||
if (effect) { | ||
this.effecting = true; | ||
effect.call(this, options); | ||
@@ -355,2 +354,3 @@ } | ||
} | ||
this.effecting = false; | ||
}, | ||
@@ -384,7 +384,9 @@ | ||
* Override this method if your editor has additional or alternative GUI elements. The GUI elements will influence the primitive value, either by altering the edited string before it is parsed, or by transforming the parsed value before returning it. | ||
* @param {string} str - current editors input string | ||
* @returns {object} the current editor's value | ||
* @throws {boolean|string|Error} Throws an error on parse failure. If the error's `message` is defined, the message will eventually be displayed (every `feedbackCount`th attempt). | ||
* @memberOf CellEditor.prototype | ||
*/ | ||
getEditorValue: function() { | ||
return this.localizer.parse(this.input.value); | ||
getEditorValue: function(str) { | ||
return this.localizer.parse(str); | ||
}, | ||
@@ -394,6 +396,9 @@ | ||
* If there is no validator on the localizer, returns falsy (not invalid; possibly valid). | ||
* @param {string} str - current editors input string | ||
* @returns {boolean|string} Truthy value means invalid. If a string, this will be an error message. If not a string, it merely indicates a generic invalid result. | ||
* @throws {boolean|string|Error} May throw an error on syntax failure as an alternative to returning truthy. Define the error's `message` field as an alternative to returning string. | ||
* @memberOf CellEditor.prototype | ||
*/ | ||
validateEditorValue: function() { | ||
return this.localizer.invalid && this.localizer.invalid(this.input.value); | ||
validateEditorValue: function(str) { | ||
return this.localizer.invalid && this.localizer.invalid(str); | ||
}, | ||
@@ -400,0 +405,0 @@ |
@@ -19,2 +19,3 @@ 'use strict'; | ||
this.input.style.textAlign = this.event.properties.halign; | ||
this.input.style.font = this.event.properties.font; | ||
}, | ||
@@ -21,0 +22,0 @@ |
@@ -18,4 +18,2 @@ 'use strict'; | ||
var val = config.value, | ||
c = config.dataCell.x, | ||
r = config.gridCell.y, | ||
bounds = config.bounds, | ||
@@ -60,5 +58,2 @@ x = bounds.x + 1, | ||
gc.fillText(val, x + ox, y + oy); | ||
//identify that we are a button | ||
config.buttonCells[c + ',' + r] = true; | ||
} | ||
@@ -65,0 +60,0 @@ }); |
'use strict'; | ||
/** @typedef {object} CellRenderer#renderConfig | ||
* This is the renderer config object, which is: | ||
* 1. First passed to a {@link DataModel#getCell getCell} method implementation, which may override (most of) its values before returning. | ||
* 2. Then passed to the specified cell renderers' {@link CellRenderer#paint paint} function for rendering. | ||
* | ||
* #### Standard Properties | ||
* | ||
* On each render of every visible cell, this a fresh instance of an object created from (whose prototype is) a properties object as defined by layer-props.js. It therefore has all the standard properties defined in {@link module:defaults}. | ||
* | ||
* #### Additional Properties | ||
* | ||
* In addition, the config object has the following additional properties. | ||
* | ||
* Properties marked **_read-only_** may in fact be writable, but should be considered **off limits** to overriding. Do not attempt to change these properties inside a {@link DataModel#getCell getCell} method override. | ||
* | ||
* Properties marked **_write-only_** are to be defined the cell renderer for use by the caller (the grid renderer). | ||
* | ||
* @property {boolean} config.allRowsSelected | ||
* | ||
* @property {BoundingRect} config.bounds - Bounding rect of the cell or subcell to be rendered. | ||
* | ||
* @property {object} [config.clickRect] - **_Write-only._** The Cell renderer may return in this property a subrect in the cell's local coordinates that represents a click region. If defined by the cell renderer, the CellClick feature will ignore clicks outside the click region. If not defined by the cell renderer, the entire cell is clickable. | ||
* | ||
* @property {dataCellCoords} config.dataCell - **_Read-only._** Data coordinates of the cell. | ||
* | ||
* @property {dataRowObject} config.dataRow - Access to other column values in the same row. | ||
* | ||
* @property {function} config.formatValue - _For cell renderer use only. Not available in `getCell` override._ The cell's value formatter function (based on the formatter name in `config.format`, as possibly mutated by `getCell`). | ||
* | ||
* @property {gridCellCoords} config.gridCell - **_Read-only._** Grid coordinates of the cell. | ||
* | ||
* @property {string} config.halign - The cell's horizontal alignment property, as interpreted by it's cell renderer. | ||
* | ||
* @property {boolean} config.isCellHovered - | ||
* | ||
* @property {boolean} config.isCellSelected - | ||
* | ||
* @property {boolean} config.isColumnHovered - | ||
* | ||
* @property {boolean} config.isColumnSelected - | ||
* | ||
* @property {boolean} config.isDataColumn - | ||
* | ||
* @property {boolean} config.isDataRow - | ||
* | ||
* @property {boolean} config.isFilterRow - | ||
* | ||
* @property {boolean} config.isHandleColumn - | ||
* | ||
* @property {boolean} config.isHeaderRow - | ||
* | ||
* @property {boolean} config.isInCurrentSelectionRectangle - | ||
* | ||
* @property {boolean} config.isRowHovered - | ||
* | ||
* @property {boolean} config.isRowSelected - | ||
* | ||
* @property {boolean} config.isSelected - | ||
* | ||
* @property {boolean} config.isTreeColumn - | ||
* | ||
* @property {boolean} config.isUserDataArea - | ||
* | ||
* @property {number} config.minWidth - **_Write-only._** The Cell renderer should return the pixel width of the rendered contents in this property. | ||
* | ||
* @property {boolean} config.mouseDown - The last mousedown event occurred over this cell and the mouse is still down. Note, however, that the mouse may no longer be hovering over this cell when it has been dragged away. | ||
* | ||
* @property {} [config.prefillColor] - **_Write-only._** This is the color _already painted_ by the grid renderer behind the cell to be rendered. If the cell's specified background color is the same, renderer may (and should!) skip painting it. If `undefined`, this signals a "partial render"; cell renderers that support partial rendering can use `config.snapshot` to determine whether or not to rerender the cell. | ||
* | ||
* @property {object} [config.snapshot] - **_Write-only._** Supports _partial render._ In support of the {@link Renderer#paintCellsAsNeeded by-cells} "partial" grid renderer, cell renderers can save the essential render parameters in this property so that on subsequent calls, when the parameters are the same, cell renderers can skip the actual rendering. Only when the parameters have changed is the cell rendered and this property reset (with the new parameters). This object would typically include at the very least the (formatted) `value`, plus additional properties as needed to fully describe the appearance of the render, such as color, _etc._ This property is undefined the first time a cell is rendered by the `by-cells` grid renderer. See also the {@link DataModel#configObject}'s `prefillColor` property. | ||
* | ||
* @property config.value - Value to be rendered. | ||
* | ||
* The renderer has available to it the `.formatValue()` function for formatting the value. The function comes from the localizer named in the `.format` property. If there is no localizer with that name, the function defaults to the `string` localizer's formatter (which simply invokes the value's `toString()` method). | ||
* | ||
* Typically a Local primitive value, values can be any type, including objects and arrays. The specified cell renderer is expected to know how to determine the value's type and render it. | ||
*/ | ||
var Base = require('../Base'); | ||
@@ -4,0 +82,0 @@ |
@@ -55,2 +55,45 @@ 'use strict'; | ||
/** | ||
* Multiplier for horizontal mouse wheel movement, applied to values of [`WheelEvent#deltaX`](https://developer.mozilla.org/docs/Web/API/WheelEvent/deltaX) (received by the horizontal scrollbar's listener). | ||
* | ||
* #### Caveat | ||
* Wheel granularity depends on the OS, the input device, and possibly the browser. Any setting you choose will work differently in different environments. If you don't know the user's environment, it is probably best to give users control of this setting so they can fine tune it themselves. | ||
* | ||
* #### Default values | ||
* This particular default value of `0.01` seems to work well on the MacBook Pro trackpad. It's slower than it was, which will greatly improve the scrolling experience since column scrolling often occurred inadvertently when the intent was to scroll in the veritcal direction only. | ||
* | ||
* Be aware however that the trackpad scrolling speed can be adjusted by the Mac user at the OS level (System Preferences -> Accessibility -> Mouse & Trackpad -> Trackpad Options… -> Scrolling speed). | ||
* | ||
* Hint: You can tell if the user is using a trackpad by listening for any deltaX (since a simple mouse wheel is deltaY only); and what OS by checking user agent. | ||
* @default | ||
* @type {number} | ||
* @memberOf module:defaults | ||
*/ | ||
wheelHFactor: 0.01, | ||
/** | ||
* Multiplier for vertical mouse wheel movement, applied to values of [`WheelEvent#deltaY`](https://developer.mozilla.org/docs/Web/API/WheelEvent/deltaY) (received by the vertical scrollbar's listener). | ||
* | ||
* #### Caveat | ||
* Wheel granularity depends on the OS, the input device, and possibly the browser. Any setting you choose will work differently in different environments. If you don't know the user's environment, it is probably best to give users control of this setting so they can fine tune it themselves. | ||
* | ||
* #### Default values | ||
* This particular default value of `0.05` is a compromise. It seems to work well on the MacBook Pro trackpad; and works acceptably (though differently) with a mouse wheel on both Mac OS and Windows. | ||
* | ||
* Be aware however that the trackpad scrolling speed can be adjusted by the Mac user at the OS level (System Preferences -> Accessibility -> Mouse & Trackpad -> Trackpad Options… -> Scrolling speed). Mouse wheel scrolling speed is also adjustable ( _yada yada_ -> Mouse Options… -> Scrolling speed; or on Windows search for "Change mouse wheel settings" in the Start menu). | ||
* | ||
* This default setting of `0.05` feels good on trackpad (2-finger drag). It's much slower than it was, but the way it was before was way to coarse and fast, scrolling hundreds of rows in a flash. | ||
* | ||
* With this setting, a mouse connected to a Mac, the wheel requires 5 click-stops to scroll 1 row; the same mouse connected to Windows scrolls 5 rows per click-stop. (However, I may have changed the default settings on my machines; not sure.) | ||
* | ||
* On Windows, the original multiplier setting (_i.e.,_ `1.0`) scrolled 100 grid rows on a single mouse wheel click-stop; the new default (`0.05`) scrolls 5 rows per click-stop. It stands to reason therefore that a setting of `0.01` will scroll 1:1 (1 row per 1 click-stop). | ||
* | ||
#### Hint | ||
You can tell if the user is using a trackpad by listening for any deltaX (since a simple mouse wheel is deltaY only); and what OS by checking user agent. | ||
* @default | ||
* @type {number} | ||
* @memberOf module:defaults | ||
*/ | ||
wheelVFactor: 0.05, | ||
/** | ||
* @summary List of subgrids by | ||
@@ -1156,2 +1199,10 @@ * @desc Restrict usage here to strings (naming data models) or arrays consisting of such a string + constructor arguments. That is, avoid {@link subgridSpec}'s function and object overloads and {@link subgridConstructorRef} function overload. | ||
/** | ||
* Collapse cell selection onto next row selection. | ||
* @default | ||
* @type {boolean} | ||
* @memberOf module:defaults | ||
*/ | ||
collapseCellSelections: false, | ||
/** @summary Name of a formatter for cell text. | ||
@@ -1158,0 +1209,0 @@ * @desc Unknown formatter falls back to the `string` formatter (simple conversion to string with `+ ''`). |
@@ -81,5 +81,7 @@ 'use strict'; | ||
grid.properties.columnSelection && | ||
event.mousePoint.y >= 5 && | ||
!event.primitiveEvent.detail.isRightClick && | ||
event.isHeaderCell | ||
( | ||
grid.properties.autoSelectColumns || | ||
event.isHeaderCell && event.mousePoint.y >= 5 | ||
) | ||
) { | ||
@@ -86,0 +88,0 @@ // HOLD OFF WHILE WAITING FOR DOUBLE-CLICK |
@@ -52,5 +52,7 @@ 'use strict'; | ||
this.dragArmed = false; | ||
moveCellSelection(grid); | ||
grid.fireSyntheticRowSelectionChangedEvent(); | ||
} else if (this.dragging) { | ||
this.dragging = false; | ||
moveCellSelection(grid); | ||
grid.fireSyntheticRowSelectionChangedEvent(); | ||
@@ -69,5 +71,6 @@ } else if (this.next) { | ||
var rowSelectable = grid.properties.rowSelection && | ||
!event.primitiveEvent.detail.isRightClick && | ||
grid.properties.showRowNumbers && | ||
event.isHandleColumn; | ||
!event.primitiveEvent.detail.isRightClick && ( | ||
grid.properties.autoSelectRows || | ||
grid.properties.showRowNumbers && event.isHandleColumn | ||
); | ||
@@ -356,26 +359,3 @@ if (rowSelectable && event.isHeaderHandle) { | ||
moveShiftSelect: function(grid, offsetY) { | ||
var origin = grid.getMouseDown(), | ||
extent = grid.getDragExtent(), | ||
maxViewableRows = grid.renderer.visibleRows.length - 1, | ||
maxRows = grid.getRowCount() - 1; | ||
if (!grid.properties.scrollingEnabled) { | ||
maxRows = Math.min(maxRows, maxViewableRows); | ||
} | ||
var newY = extent.y + offsetY; | ||
newY = Math.min(maxRows - origin.y, Math.max(-origin.y, newY)); | ||
grid.clearMostRecentRowSelection(); | ||
grid.selectRow(origin.y, origin.y + newY); | ||
grid.setDragExtent(grid.newPoint(0, newY)); | ||
if (grid.insureModelRowIsVisible(newY + origin.y, offsetY)) { | ||
this.pingAutoScroll(); | ||
} | ||
grid.fireSyntheticRowSelectionChangedEvent(); | ||
grid.repaint(); | ||
this.moveSingleSelect(grid, offsetY, true); | ||
}, | ||
@@ -385,28 +365,45 @@ | ||
* @memberOf RowSelection.prototype | ||
* @desc Replace the most recent selection with a single cell selection that is moved (offsetX,offsetY) from the previous selection extent. | ||
* @desc Replace the most recent row selection with a single cell row selection `offsetY` rows from the previous selection. | ||
* @param {Hypergrid} grid | ||
* @param {number} offsetX - x coordinate to start at | ||
* @param {number} offsetY - y coordinate to start at | ||
*/ | ||
moveSingleSelect: function(grid, offsetY) { | ||
var maxRows = grid.getRowCount() - 1, | ||
maxViewableRows = grid.getVisibleRowsCount() - 1, | ||
mouseCorner = grid.getMouseDown().plus(grid.getDragExtent()), | ||
newY = mouseCorner.y + offsetY; | ||
moveSingleSelect: function(grid, offsetY, shift) { | ||
var selections = grid.selectionModel.rowSelectionModel.selection, | ||
lastSelection = selections[selections.length - 1], | ||
top = lastSelection[0], | ||
bottom = lastSelection[1]; | ||
if (!grid.properties.scrollingEnabled) { | ||
maxRows = Math.min(maxRows, maxViewableRows); | ||
if (shift) { | ||
var firstOffsetY = lastSelection.offsetY = lastSelection.offsetY || offsetY; | ||
if (lastSelection.offsetY < 0) { | ||
top += offsetY; | ||
} else { | ||
bottom += offsetY; | ||
} | ||
} else { | ||
top += offsetY; | ||
bottom += offsetY; | ||
} | ||
newY = Math.min(maxRows, Math.max(0, newY)); | ||
if (top < 0 || bottom >= grid.getRowCount()) { | ||
return; | ||
} | ||
grid.clearSelections(); | ||
grid.selectRow(newY); | ||
grid.setMouseDown(grid.newPoint(0, newY)); | ||
grid.setDragExtent(grid.newPoint(0, 0)); | ||
if (grid.insureModelRowIsVisible(newY, offsetY)) { | ||
this.pingAutoScroll(); | ||
selections.length -= 1; | ||
if (selections.length) { | ||
lastSelection = selections[selections.length - 1]; | ||
delete lastSelection.offsetY; | ||
} | ||
grid.selectRow(top, bottom); | ||
if (shift && top !== bottom) { | ||
lastSelection = selections[selections.length - 1]; | ||
lastSelection.offsetY = firstOffsetY; | ||
} | ||
grid.setMouseDown(grid.newPoint(0, top)); | ||
grid.setDragExtent(grid.newPoint(0, bottom - top)); | ||
grid.scrollToMakeVisible(grid.properties.fixedColumnCount, offsetY < 0 ? top : bottom + 1); // +1 for partial row | ||
moveCellSelection(grid); | ||
grid.fireSyntheticRowSelectionChangedEvent(); | ||
@@ -422,2 +419,25 @@ grid.repaint(); | ||
function moveCellSelection(grid) { | ||
var rows; | ||
if ( | ||
grid.properties.collapseCellSelections && | ||
grid.properties.singleRowSelectionMode && // let's only attempt this when in this mode | ||
!grid.properties.multipleSelections && // and only when in single selection mode | ||
(rows = grid.getSelectedRows()).length && // user just selected a row (must be single row due to mode we're in) | ||
grid.selectionModel.getSelections().length // there was a cell region selected (must be the only one) | ||
) { | ||
var rect = grid.selectionModel.getLastSelection(), // the only cell selection | ||
x = rect.left, | ||
y = rows[0], // we know there's only 1 row selected | ||
width = rect.right - x, | ||
height = 0, // collapse the new region to occupy a single row | ||
fireSelectionChangedEvent = false; | ||
grid.selectionModel.select(x, y, width, height, fireSelectionChangedEvent); | ||
grid.repaint(); | ||
} | ||
} | ||
module.exports = RowSelection; |
@@ -434,5 +434,16 @@ /* eslint-env browser */ | ||
getKeyChar: function(e) { | ||
var key = e.keyCode || e.detail.key, | ||
shift = e.shiftKey || e.detail.shift; | ||
return charMap[key][shift ? 1 : 0]; | ||
var keyCode = e.keyCode || e.detail.key, | ||
shift = e.shiftKey || e.detail.shift, | ||
key = e.key; | ||
e.legacyKey = charMap[keyCode] && charMap[keyCode][shift ? 1 : 0]; | ||
if (typeof key === 'string' && key.length === 1) { | ||
return key; | ||
} | ||
return ( | ||
e.legacyKey || // legacy unprintable char string | ||
key // modern unprintable char string when no such legacy string | ||
); | ||
}, | ||
@@ -471,2 +482,3 @@ | ||
char: keyChar, | ||
legacyChar: e.legacyKey, | ||
code: e.charCode, | ||
@@ -502,2 +514,3 @@ key: e.keyCode, | ||
char: keyChar, | ||
legacyChar: e.legacyKey, | ||
code: e.charCode, | ||
@@ -504,0 +517,0 @@ key: e.keyCode, |
@@ -467,2 +467,14 @@ 'use strict'; | ||
/** @typedef {WritablePoint} dataCellCoords | ||
* @property {number} x - The data model's column index, unaffected by column scrolling; _i.e.,_ | ||
* an index suitable for dereferencing the column object to which the cell belongs via {@link Behavior#getColumn}. | ||
* @property {number} y - The data model's row index, adjusted for data row scrolling after fixed rows. | ||
*/ | ||
/** @typedef {WritablePoint} gridCellCoords | ||
* @property {number} x - The active column index, adjusted for column scrolling after fixed columns; _i.e.,_ | ||
* an index suitable for dereferencing the column object to which the cell belongs via {@link Behavior#getActiveColumn}. | ||
* @property {number} y - The vertical grid coordinate, unaffected by subgrid, row scrolling, and fixed rows. | ||
*/ | ||
/** | ||
@@ -469,0 +481,0 @@ * @name cellEventFactory |
@@ -33,2 +33,22 @@ 'use strict'; | ||
wheelHFactor: { | ||
enumerable: true, | ||
get: function() { | ||
return this.grid.sbHScroller.deltaXFactor; | ||
}, | ||
set: function(factor) { | ||
this.grid.sbHScroller.deltaXFactor = factor; | ||
} | ||
}, | ||
wheelVFactor: { | ||
enumerable: true, | ||
get: function() { | ||
return this.grid.sbVScroller.deltaYFactor; | ||
}, | ||
set: function(factor) { | ||
this.grid.sbVScroller.deltaYFactor = factor; | ||
} | ||
}, | ||
/** | ||
@@ -35,0 +55,0 @@ * @memberOf module:dynamicPropertyDescriptors |
@@ -123,3 +123,4 @@ /* eslint-env browser */ | ||
keyEvent: keyEvent, | ||
char: this.canvas.getCharMap()[keyEvent.keyCode][keyEvent.shiftKey ? 1 : 0] | ||
char: this.canvas.getKeyChar(keyEvent), | ||
legacyChar: keyEvent.legacyKey // decorated by getKeyChar | ||
}); | ||
@@ -132,3 +133,4 @@ }, | ||
keyEvent: keyEvent, | ||
char: this.canvas.getCharMap()[keyEvent.keyCode][keyEvent.shiftKey ? 1 : 0] | ||
char: this.canvas.getKeyChar(keyEvent), | ||
legacyChar: keyEvent.legacyKey // decorated by getKeyChar | ||
}); | ||
@@ -141,3 +143,4 @@ }, | ||
keyEvent: keyEvent, | ||
char: this.canvas.getCharMap()[keyEvent.keyCode][keyEvent.shiftKey ? 1 : 0] | ||
char: this.canvas.getKeyChar(keyEvent), | ||
legacyChar: keyEvent.legacyKey // decorated by getKeyChar | ||
}); | ||
@@ -191,3 +194,3 @@ }, | ||
fireSyntheticButtonPressedEvent: function(event) { | ||
if (this.isViewableButton(event.dataCell.x, event.gridCell.y)) { | ||
if (event.properties.renderer === 'button') { | ||
return dispatchEvent.call(this, 'fin-button-pressed', {}, event); | ||
@@ -408,5 +411,15 @@ } | ||
handleMouseEvent(e, function(mouseEvent) { | ||
mouseEvent.keys = e.detail.keys; // todo: this was in fin-tap but wasn't here | ||
this.fireSyntheticClickEvent(mouseEvent); | ||
this.delegateClick(mouseEvent); | ||
var isMouseDownCell = this.mouseDownState && this.mouseDownState.gridCell.equals(mouseEvent.gridCell); | ||
if ( | ||
isMouseDownCell && | ||
isMousePointInClickRect(mouseEvent) | ||
) { | ||
mouseEvent.keys = e.detail.keys; // todo: this was in fin-tap but wasn't here | ||
if (this.mouseDownState) { | ||
this.fireSyntheticButtonPressedEvent(this.mouseDownState); | ||
this.mouseDownState = null; | ||
} | ||
this.fireSyntheticClickEvent(mouseEvent); | ||
this.delegateClick(mouseEvent); | ||
} | ||
}); | ||
@@ -428,6 +441,2 @@ }); | ||
this.delegateMouseUp(mouseEvent); | ||
if (self.mouseDownState) { | ||
self.fireSyntheticButtonPressedEvent(self.mouseDownState); | ||
} | ||
this.mouseDownState = null; | ||
this.fireSyntheticMouseUpEvent(mouseEvent); | ||
@@ -597,2 +606,6 @@ }); | ||
function isMousePointInClickRect(e) { | ||
return !e.clickRect || e.clickRect.contains(e.mousePoint); | ||
} | ||
var details = [ | ||
@@ -599,0 +612,0 @@ 'gridCell', |
@@ -211,2 +211,3 @@ 'use strict'; | ||
orientation: 'horizontal', | ||
deltaXFactor: this.constructor.defaults.wheelHFactor, | ||
onchange: self.setHScrollValue.bind(self), | ||
@@ -218,2 +219,3 @@ cssStylesheetReferenceElement: this.div | ||
orientation: 'vertical', | ||
deltaYFactor: this.constructor.defaults.wheelVFactor, | ||
onchange: self.setVScrollValue.bind(self), | ||
@@ -220,0 +222,0 @@ paging: { |
@@ -45,11 +45,11 @@ /* eslint-env browser */ | ||
getSelectionAsTSV: function() { | ||
var sm = this.selectionModel; | ||
if (sm.hasSelections()) { | ||
var selections = this.getSelectionMatrix(); | ||
selections = selections[selections.length - 1]; | ||
return this.getMatrixSelectionAsTSV(selections); | ||
} else if (sm.hasRowSelections()) { | ||
return this.getMatrixSelectionAsTSV(this.getRowSelectionMatrix()); | ||
} else if (sm.hasColumnSelections()) { | ||
return this.getMatrixSelectionAsTSV(this.getColumnSelectionMatrix()); | ||
switch (this.selectionModel.getLastSelectionType()) { | ||
case 'cell': | ||
var selections = this.getSelectionMatrix(); | ||
selections = selections[selections.length - 1]; | ||
return this.getMatrixSelectionAsTSV(selections); | ||
case 'row': | ||
return this.getMatrixSelectionAsTSV(this.getRowSelectionMatrix()); | ||
case 'column': | ||
return this.getMatrixSelectionAsTSV(this.getColumnSelectionMatrix()); | ||
} | ||
@@ -560,5 +560,4 @@ }, | ||
y1 = y2; | ||
} else { | ||
// multiple row selection | ||
y2 = y2 || y1; | ||
} else if (y2 === undefined) { | ||
y2 = y1; | ||
} | ||
@@ -597,4 +596,4 @@ | ||
}, | ||
getLastSelectionType: function() { | ||
return this.selectionModel.getLastSelectionType(); | ||
getLastSelectionType: function(n) { | ||
return this.selectionModel.getLastSelectionType(n); | ||
}, | ||
@@ -601,0 +600,0 @@ isInCurrentSelectionRectangle: function(x, y) { |
@@ -5,2 +5,4 @@ 'use strict'; | ||
var InclusiveRectangle = require('./InclusiveRectangle'); | ||
/** | ||
@@ -73,3 +75,3 @@ * | ||
this.setLastSelectionType(''); | ||
this.lastSelectionType = []; | ||
}, | ||
@@ -88,15 +90,34 @@ | ||
/** | ||
* The most recent selection type. This is the TOS of `this.lastSelectionType`, the stack of unique selection types. | ||
* | ||
* Note that in the case where the only remaining previous selection of `type` was deselected, and `setLastSelectionType` was called with `reset` truthy, `type` is removed from the stack. If it was previously TOS, the TOS will now be what was the 2nd most recently pushed type (or nothing if no other selections). | ||
* | ||
* Returns empty string (`''`) if there are no selections. | ||
* @memberOf SelectionModel.prototype | ||
* @returns {*} | ||
*/ | ||
getLastSelectionType: function() { | ||
return this.lastSelectionType; | ||
getLastSelectionType: function(n) { | ||
return this.lastSelectionType[n || 0] || ''; | ||
}, | ||
/** | ||
* @param type | ||
* Set the most recent selection's `type`. That is, push onto TOS of `this.lastSelectionType`, the stack of unique selection types. If already in the stack, move it to the top. | ||
* | ||
* If `reset` is truthy, remove the given `type` from the stack, regardless of where found therein (or not), thus "revealing" the 2nd most recently pushed type. | ||
* | ||
* @param {string} type - One of: `'cell'`, `'row'`, or `'column'` | ||
* @param {boolean} [reset=false] - Remove the given `type` from the stack. Specify truthy when the only remaining previous selection of `type` has been deselected. | ||
* @memberOf SelectionModel.prototype | ||
*/ | ||
setLastSelectionType: function(type) { | ||
this.lastSelectionType = type; | ||
setLastSelectionType: function(type, reset) { | ||
var i = this.lastSelectionType.indexOf(type); | ||
if (i === 0 && !reset) { | ||
return; | ||
} | ||
if (i >= 0) { | ||
this.lastSelectionType.splice(i, 1); | ||
} | ||
if (!reset) { | ||
this.lastSelectionType.unshift(type); | ||
} | ||
}, | ||
@@ -115,3 +136,3 @@ | ||
select: function(ox, oy, ex, ey, silent) { | ||
var newSelection = this.grid.newRectangle(ox, oy, ex, ey); | ||
var newSelection = new InclusiveRectangle(ox, oy, ex + 1, ey + 1); | ||
@@ -167,2 +188,3 @@ //Cache the first selected cell before it gets normalized to top-left origin | ||
this.flattenedY.splice(index, 1); | ||
this.setLastSelectionType('cell', !this.selections.length); | ||
this.grid.selectionChanged(); | ||
@@ -185,2 +207,3 @@ } else { | ||
if (this.flattenedY.length) { --this.flattenedY.length; } | ||
this.setLastSelectionType('cell', !this.selections.length); | ||
//this.getGrid().selectionChanged(); | ||
@@ -194,3 +217,3 @@ }, | ||
this.columnSelectionModel.clearMostRecentSelection(); | ||
this.setLastSelectionType('column'); | ||
this.setLastSelectionType('column', !this.columnSelectionModel.selection.length); | ||
}, | ||
@@ -203,3 +226,3 @@ | ||
this.rowSelectionModel.clearMostRecentSelection(); | ||
this.setLastSelectionType('row'); | ||
this.setLastSelectionType('row', !this.rowSelectionModel.selection.length); | ||
}, | ||
@@ -212,3 +235,3 @@ | ||
this.rowSelectionModel.clear(); | ||
this.setLastSelectionType('row'); | ||
this.setLastSelectionType('row', !this.rowSelectionModel.selection.length); | ||
}, | ||
@@ -318,4 +341,7 @@ | ||
if (!keepRowSelections) { | ||
this.lastSelectionType.length = 0; | ||
this.setAllRowsSelected(false); | ||
this.rowSelectionModel.clear(); | ||
} else if (this.lastSelectionType.indexOf('row') >= 0) { | ||
this.lastSelectionType = ['row']; | ||
} | ||
@@ -367,3 +393,3 @@ //this.getGrid().selectionChanged(); | ||
this.columnSelectionModel.select(x1, x2); | ||
this.setLastSelectionType('column'); | ||
this.setLastSelectionType('column', !this.columnSelectionModel.selection.length); | ||
}, | ||
@@ -399,3 +425,3 @@ | ||
this.rowSelectionModel.select(y1, y2); | ||
this.setLastSelectionType('row'); | ||
this.setLastSelectionType('row', !this.rowSelectionModel.selection.length); | ||
}, | ||
@@ -410,3 +436,3 @@ | ||
this.columnSelectionModel.deselect(x1, x2); | ||
this.setLastSelectionType('column'); | ||
this.setLastSelectionType('column', !this.columnSelectionModel.selection.length); | ||
}, | ||
@@ -427,3 +453,3 @@ | ||
this.rowSelectionModel.deselect(y1, y2); | ||
this.setLastSelectionType('row'); | ||
this.setLastSelectionType('row', !this.rowSelectionModel.selection.length); | ||
}, | ||
@@ -535,3 +561,3 @@ | ||
isInCurrentSelectionRectangle: function(x, y) { | ||
var last = this.selections[this.selections.length - 1]; | ||
var last = this.getLastSelection(); | ||
return last && this.rectangleContains(last, x, y); | ||
@@ -538,0 +564,0 @@ }, |
@@ -9,4 +9,4 @@ /* eslint-env browser */ | ||
var layerProps = require('./layer-props'); | ||
var InclusiveRectangle = require('../lib/InclusiveRectangle'); | ||
var visibleColumnPropertiesDescriptorFn = function(grid) { | ||
@@ -347,6 +347,5 @@ return { | ||
* @param {Point} point | ||
* @returns {Point} Cell coordinates | ||
* @returns {{cellEvent:CellEvent,fake:boolean}} Cell coordinates | ||
*/ | ||
getGridCellFromMousePoint: function(point) { | ||
var x = point.x, | ||
@@ -379,10 +378,5 @@ y = point.y, | ||
var mousePoint = this.grid.newPoint(x - vc.left, y - vr.top), | ||
cellEvent = new this.grid.behavior.CellEvent(vc.columnIndex, vr.index); | ||
result.cellEvent = Object.create(this.findCell(new this.grid.behavior.CellEvent(vc.columnIndex, vr.index))); | ||
result.cellEvent.mousePoint = this.grid.newPoint(x - vc.left, y - vr.top); | ||
// cellEvent.visibleColumn = vc; | ||
// cellEvent.visibleRow = vr; | ||
result.cellEvent = Object.defineProperty(cellEvent, 'mousePoint', {value: mousePoint}); | ||
if (isPseudoCol || isPseudoRow) { | ||
@@ -592,4 +586,2 @@ result.fake = true; | ||
this.buttonCells = {}; | ||
var rowCount = this.grid.getRowCount(); | ||
@@ -620,8 +612,43 @@ if (rowCount !== this.lastKnowRowCount) { | ||
renderLastSelection: function(gc) { | ||
var selections = this.grid.selectionModel.getSelections(); | ||
if (!selections || selections.length === 0) { | ||
return; | ||
var selection, left, top, width, height, | ||
grid = this.grid, | ||
gridProps = grid.properties, | ||
sm = grid.selectionModel; | ||
switch (sm.getLastSelectionType()) { | ||
case 'column': | ||
var columnSelections = sm.columnSelectionModel.selection, | ||
lastColumnSelection = columnSelections[columnSelections.length - 1]; | ||
left = lastColumnSelection[0]; | ||
top = 0; | ||
width = lastColumnSelection[1] - left + 1; | ||
height = grid.getRowCount(); | ||
selection = new InclusiveRectangle(left, top, width, height); | ||
break; | ||
case 'row': | ||
if (!(gridProps.collapseCellSelections && sm.getLastSelectionType(1) === 'cell')) { | ||
var rowSelections = sm.rowSelectionModel.selection, | ||
lastRowSelection = rowSelections[rowSelections.length - 1]; | ||
left = 0; | ||
top = lastRowSelection[0]; | ||
width = grid.behavior.getActiveColumns().length; | ||
height = lastRowSelection[1] - top + 1; | ||
selection = new InclusiveRectangle(left, top, width, height); | ||
break; | ||
} | ||
// fall through to 'cell' | ||
case 'cell': | ||
selection = sm.getLastSelection(); | ||
break; | ||
} | ||
var selection = this.grid.selectionModel.getLastSelection(); | ||
if (!selection) { | ||
return; // no selection | ||
} | ||
// todo not sure what this is for; might be defunct logic | ||
if (selection.origin.x === -1) { | ||
@@ -634,20 +661,32 @@ // no selected area, lets exit | ||
vri = this.visibleRowsByDataRowIndex, | ||
lastColumn = this.visibleColumns[this.visibleColumns.length - 1], // last column in scrollable section | ||
lastRow = vri[this.dataWindow.corner.y]; // last row in scrollable data section | ||
lastScrollableColumn = this.visibleColumns[this.visibleColumns.length - 1], // last column in scrollable section | ||
lastScrollableRow = this.visibleRows[this.visibleRows.length - 1], // last row in scrollable data section | ||
firstScrollableColumn = vci[this.dataWindow.origin.x], | ||
firstScrollableRow = vri[this.dataWindow.origin.y], | ||
fixedColumnCount = gridProps.fixedColumnCount, | ||
fixedRowCount = gridProps.fixedRowCount, | ||
headerRowCount = grid.getHeaderRowCount(); | ||
if ( | ||
!lastColumn || !lastRow || | ||
selection.origin.x > lastColumn.columnIndex || | ||
selection.origin.y > lastRow.rowIndex | ||
) { | ||
// selection area begins to right or below grid | ||
return; | ||
} | ||
// entire selection scrolled out of view to left of visible columns; or | ||
selection.corner.x < this.visibleColumns[0].columnIndex || | ||
var vcOrigin = vci[selection.origin.x], | ||
vcCorner = vci[selection.corner.x], | ||
vrOrigin = vri[selection.origin.y], | ||
vrCorner = vri[selection.corner.y]; | ||
if ( | ||
!(vcOrigin || vcCorner) || // entire selection scrolled out of view to left of scrollable region | ||
!(vrOrigin || vrCorner) // entire selection scrolled out of view above scrollable region | ||
// entire selection scrolled out of view between fixed columns and scrollable columns; or | ||
fixedColumnCount && | ||
selection.origin.x > this.visibleColumns[fixedColumnCount - 1].columnIndex && | ||
selection.corner.x < firstScrollableColumn.columnIndex || | ||
// entire selection scrolled out of view to right of visible columns; or | ||
selection.origin.x > lastScrollableColumn.columnIndex || | ||
// entire selection scrolled out of view above visible rows; or | ||
selection.corner.y < this.visibleRows[headerRowCount].rowIndex || | ||
// entire selection scrolled out of view between fixed rows and scrollable rows; or | ||
fixedRowCount && | ||
selection.origin.y > this.visibleRows[headerRowCount + fixedRowCount - 1].rowIndex && | ||
selection.corner.y < firstScrollableRow.rowIndex || | ||
// entire selection scrolled out of view below visible rows | ||
selection.origin.y > lastScrollableRow.rowIndex | ||
) { | ||
@@ -657,7 +696,6 @@ return; | ||
var gridProps = this.properties; | ||
vcOrigin = vcOrigin || this.visibleColumns[gridProps.fixedColumnCount]; | ||
vrOrigin = vrOrigin || this.visibleRows[gridProps.fixedRowCount]; | ||
vcCorner = vcCorner || (selection.corner.x > lastColumn.columnIndex ? lastColumn : vci[gridProps.fixedColumnCount - 1]); | ||
vrCorner = vrCorner || (selection.corner.y > lastRow.rowIndex ? lastRow : vri[gridProps.fixedRowCount - 1]); | ||
var vcOrigin = vci[selection.origin.x] || firstScrollableColumn, | ||
vrOrigin = vri[selection.origin.y] || firstScrollableRow, | ||
vcCorner = vci[selection.corner.x] || (selection.corner.x > lastScrollableColumn.columnIndex ? lastScrollableColumn : vci[fixedColumnCount - 1]), | ||
vrCorner = vri[selection.corner.y] || (selection.corner.y > lastScrollableRow.rowIndex ? lastScrollableRow : vri[fixedRowCount - 1]); | ||
@@ -675,3 +713,5 @@ // Render the selection model around the bounds | ||
}; | ||
this.grid.cellRenderers.get('lastselection').paint(gc, config); | ||
grid.cellRenderers.get('lastselection').paint(gc, config); | ||
if (this.gridRenderer.paintCells.key === 'by-cells') { | ||
@@ -867,5 +907,6 @@ this.gridRenderer.reset = true; // fixes GRID-490 | ||
var gridLinesVWidth = gridProps.gridLinesVWidth, | ||
userDataAreaTop = visibleRows[this.grid.getHeaderRowCount()].top, | ||
headerRowCount = this.grid.getHeaderRowCount(), | ||
userDataAreaTop = visibleRows[headerRowCount].top, | ||
top = gridProps.gridLinesColumnHeader ? 0 : userDataAreaTop, | ||
bottom = gridProps.gridLinesUserDataArea ? viewHeight : visibleRows[this.grid.getHeaderRowCount() - 1].bottom; | ||
bottom = gridProps.gridLinesUserDataArea ? viewHeight : visibleRows[headerRowCount - 1].bottom; | ||
@@ -1052,7 +1093,4 @@ gc.cache.fillStyle = gridLinesVColor; | ||
config.prefillColor = prefillColor; | ||
config.mouseDown = grid.mouseDownState && grid.mouseDownState.gridCell.equals(cellEvent.gridCell); | ||
if (grid.mouseDownState) { | ||
config.mouseDown = grid.mouseDownState.gridCell.equals(cellEvent.gridCell); | ||
} | ||
// compute value if a calculator | ||
@@ -1070,5 +1108,2 @@ if (isUserDataArea && !(config.value && config.value.constructor === Array)) { // fastest array determination | ||
//allow the renderer to identify itself if it's a button | ||
config.buttonCells = this.buttonCells; | ||
config.formatValue = grid.getFormatter(format || config.format); | ||
@@ -1087,2 +1122,5 @@ | ||
// Following supports clicking in a renderer-defined Rectangle of a cell (in the cell's local coordinates) | ||
cellEvent.clickRect = config.clickRect; | ||
return config.minWidth; | ||
@@ -1110,5 +1148,5 @@ }, | ||
// colIndexOrCellEvent is a cell event object | ||
dataModel = rowIndex; | ||
rowIndex = colIndexOrCellEvent.visibleRow.rowIndex; | ||
colIndex = colIndexOrCellEvent.column.index; | ||
dataModel = colIndexOrCellEvent.subgrid; | ||
rowIndex = colIndexOrCellEvent.dataCell.y; | ||
colIndex = colIndexOrCellEvent.dataCell.x; | ||
} else { | ||
@@ -1120,8 +1158,12 @@ colIndex = colIndexOrCellEvent; | ||
for (var p = 0, len = this.visibleColumns.length * this.visibleRows.length; p < len; ++p) { | ||
var len = this.visibleColumns.length; | ||
if (this.grid.properties.showRowNumbers) { len++; } | ||
if (this.grid.behavior.hasTreeColumn()) { len++; } | ||
len *= this.visibleRows.length; | ||
for (var p = 0; p < len; ++p) { | ||
cellEvent = pool[p]; | ||
if ( | ||
cellEvent.subgrid === dataModel && | ||
cellEvent.column.index === colIndex && | ||
cellEvent.visibleRow.rowIndex === rowIndex | ||
cellEvent.dataCell.x === colIndex && | ||
cellEvent.dataCell.y === rowIndex | ||
) { | ||
@@ -1152,7 +1194,2 @@ return cellEvent; | ||
isViewableButton: function(c, r) { | ||
var key = c + ',' + r; | ||
return this.buttonCells[key] === true; | ||
}, | ||
getBounds: function() { | ||
@@ -1434,3 +1471,3 @@ return this.bounds; | ||
this.dataWindow = this.grid.newRectangle(firstVX, firstVY, lastVX - firstVX, lastVY - firstVY); | ||
this.dataWindow = new InclusiveRectangle(firstVX, firstVY, lastVX - firstVX + 1, lastVY - firstVY + 1); | ||
@@ -1437,0 +1474,0 @@ // Resize CellEvent pool |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
755221
89
18644
+ Addedfinbars@1.6.3(transitive)
- Removedfinbars@1.5.2(transitive)
Updatedfinbars@^1.6.0