From 85cd6e7b3421ef75fd38604c0c3e3c7f7de6932f Mon Sep 17 00:00:00 2001 From: Jonathan Eiten Date: Wed, 27 Jun 2018 13:05:55 -0400 Subject: [PATCH 1/6] fix partial render grid lines (Issue #730) --- src/renderer/by-cells.js | 4 ++++ src/renderer/by-columns.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/by-cells.js b/src/renderer/by-cells.js index 9a16ef7b4..0db675b0d 100644 --- a/src/renderer/by-cells.js +++ b/src/renderer/by-cells.js @@ -81,6 +81,10 @@ function paintCellsAsNeeded(gc) { }.bind(this)); // gc.clipRestore(clipToGrid); + + if (this.grid.properties.boxSizing === 'border-box') { + this.paintGridlines(gc); + } } paintCellsAsNeeded.key = 'by-cells'; diff --git a/src/renderer/by-columns.js b/src/renderer/by-columns.js index 84fad7d49..0667733c7 100644 --- a/src/renderer/by-columns.js +++ b/src/renderer/by-columns.js @@ -7,7 +7,7 @@ var bundleColumns = require('./bundle-columns'); * * First, a background rect is drawn using the grid background color. * - * Then, if there are any columns with their own background color _that differs from the grid background color,_ these are consolidated and the consolidated groups of column backgrounds are all drawn before iterating through cells. Note that these column rects are _not_ suitable for clipping overflow text from previous columns. If you have overflow text, either turn on clipping (big performance hit) or turn on one of the `truncateTextWithEllipsis` options. + * Then, if there are any columns with their own background color _that differs from the grid background color,_ these are consolidated and the consolidated groups of column backgrounds are all drawn before iterating through cells. Note that these column rects are _not_ suitable for clipping overflow text from previous columns. If you have overflow text, either turn on clipping (`grid.properties.columnClip = true` but big performance hit) or turn on one of the `truncateTextWithEllipsis` options. * * `try...catch` surrounds each cell paint in case a cell renderer throws an error. * The error message is error-logged to console AND displayed in cell. From 06a24bf102a67106c3da6839083eda499b0f090c Mon Sep 17 00:00:00 2001 From: Mike Bender Date: Thu, 7 Jun 2018 10:52:04 -0400 Subject: [PATCH 2/6] Disable alpha on canvas context. Since the grid background is drawn anyway, the grid does not need to be transparent. This allows optimizations of the canvas for better performance: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas In particular, it allows subpixel aliasing, which makes text look much crisper. --- src/features/ColumnMoving.js | 4 ++-- src/lib/Canvas.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/ColumnMoving.js b/src/features/ColumnMoving.js index 3f6579d17..acfb569c4 100644 --- a/src/features/ColumnMoving.js +++ b/src/features/ColumnMoving.js @@ -99,7 +99,7 @@ var ColumnMoving = Feature.extend('ColumnMoving', { dragger.style.position = 'fixed'; document.body.appendChild(dragger); - draggerCTX = dragger.getContext('2d'); + draggerCTX = dragger.getContext('2d', { alpha: false }); } if (!floatColumn) { floatColumn = document.createElement('canvas'); @@ -108,7 +108,7 @@ var ColumnMoving = Feature.extend('ColumnMoving', { floatColumn.style.position = 'fixed'; document.body.appendChild(floatColumn); - floatColumnCTX = floatColumn.getContext('2d'); + floatColumnCTX = floatColumn.getContext('2d', { alpha: false }); } }, diff --git a/src/lib/Canvas.js b/src/lib/Canvas.js index b2a554007..ccbb60f4e 100644 --- a/src/lib/Canvas.js +++ b/src/lib/Canvas.js @@ -792,7 +792,7 @@ function makeCharMap() { } function getCachedContext(canvasElement, type) { - var gc = canvasElement.getContext(type || '2d'), + var gc = canvasElement.getContext(type || '2d', { alpha: false }), props = {}, values = {}; From dd7366b200f60c4a04930709bb0ec9399f801de4 Mon Sep 17 00:00:00 2001 From: Jonathan Eiten Date: Wed, 27 Jun 2018 21:19:31 -0400 Subject: [PATCH 3/6] add Hypergrid option canvasContextAttributes --- demo/js/demo/index.js | 1 + src/Hypergrid.js | 43 ++++++++++++++++++++++++++++++++++++------- src/lib/Canvas.js | 10 +++++----- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/demo/js/demo/index.js b/demo/js/demo/index.js index 217f00c9b..3b7c2c3a4 100644 --- a/demo/js/demo/index.js +++ b/demo/js/demo/index.js @@ -42,6 +42,7 @@ window.onload = function() { margin: { bottom: '17px', right: '17px'}, schema: schema, plugins: require('fin-hypergrid-event-logger'), + // canvasContextAttributes: { alpha: false }, state: { color: 'orange' } }, grid = new Hypergrid('div#json-example', gridOptions), diff --git a/src/Hypergrid.js b/src/Hypergrid.js index 536d99f3b..3418fc9f6 100644 --- a/src/Hypergrid.js +++ b/src/Hypergrid.js @@ -32,7 +32,34 @@ var EDGE_STYLES = ['top', 'bottom', 'left', 'right'], * @mixes themes.mixin * @mixes themes.sharedMixin * @constructor - * @param {string|Element} [container] - CSS selector or Element + * @classdesc An object representing a Hypergrid. + * @desc The first parameter, `container`, is optional. If omitted, the `options` parameter is promoted to first position. (Note that the container can also be given in `options.container.`) + * #### `options.canvasContextAttributes` object (see below) + * The only currently meaningful property of this object is `alpha`: + * + * ```js + * var gridOptions = { + * canvasContextAttributes: { alpha: false } + * }; + * var myGrid = new Hypergrid(gridOptions); + * ``` + * + * `alpha` is a boolean that indicates if the canvas contains an alpha channel. If set to `false`, the browser now knows that the backdrop is always opaque, which can speed up drawing of transparent content and images. + * + * This option was added by request although testing failed to show any measurable performance benefit. + * + * Use with caution. In particular, if the canvas is set to "opaque" (`{alpha: false}`), do _not_ also specify a transparent or translucent color for `grid.properties.backGround` because content may then be drawn with corrupt anti-aliasing (at lest in Chrome v67). + * + * Note that such an "opaque" canvas can still be made to appear translucent using the CSS `opacity` property — a different effect entirely. + * + * Although this option has no apparent performance gains (in Chrome v63), it does permit the graphics context to use [sub-pixel rendering](https://en.wikipedia.org/wiki/Subpixel_rendering) for sharper text as viewed on LCD or LED screens, especially black text on white backgrounds, and especially when viewed on a high-pixel-density display such as an [Apple retina display](https://en.wikipedia.org/wiki/Retina_Display). + * + * value | Canvas | Text | Sample + * ----- | :----: | :--: | ------ + * `{ alpha: true } ` | transparent | regular
anti-aliasing | ![regular.png](https://cdn-pro.dprcdn.net/files/acc_645730/ZqurK3) + * `{ alpha: false }` | opaque | sub-pixel
rendering | ![sub-pixel.png](https://cdn-std.dprcdn.net/files/acc_645730/bf3VXh) + * + * @param {string|Element} [container] - CSS selector or Element. If omitted, Hypergrid first looks for an _empty_ element with an ID of `hypergrid`. If not found, it will create a new element. In either case, the container element has the class name `hypergrid-container` added to its class name list. Finally, if the there is more than one such element with that class name, the element's ID attribute is set to `hypergrid` + _n_ where n is an ordinal one less than the number of such elements. * @param {object} [options] * @param {function} [options.Behavior=behaviors.JSON] - A grid behavior constructor (extended from {@link Behavior}). * @param {function[]} [options.pipeline] - A list function constructors to use for passing data through a series of transforms to occur on reindex call @@ -52,10 +79,12 @@ var EDGE_STYLES = ['top', 'bottom', 'left', 'right'], * * @param {string|Element} [options.container] - CSS selector or Element * + * @param {object} [options.canvasContextAttributes] - Passed to [`HTMLCanvasElement.getContext`](https://developer.mozilla.org/docs/Web/API/HTMLCanvasElement/getContext). _Please see discussion above._ + * * @param {string} [options.localization=Hypergrid.localization] - * @param {string|string[]} [options.localization.locale=Hypergrid.localization.locale] - The default locale to use when an explicit `locale` is omitted from localizer constructor calls. Passed to Intl.NumberFomrat` and `Intl.DateFomrat`. See {@ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation|Locale identification and negotiation} for more information. - * @param {string} [options.localization.numberOptions=Hypergrid.localization.numberOptions] - Options passed to `Intl.NumberFormat` for creating the basic "number" localizer. - * @param {string} [options.localization.dateOptions=Hypergrid.localization.dateOptions] - Options passed to `Intl.DateFomrat` for creating the basic "date" localizer. + * @param {string|string[]} [options.localization.locale=Hypergrid.localization.locale] - The default locale to use when an explicit `locale` is omitted from localizer constructor calls. Passed to Intl.NumberFomrat` and `Intl.DateFomrat`. See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation|Locale identification and negotiation} for more information. + * @param {string} [options.localization.numberOptions=Hypergrid.localization.numberOptions] - Options passed to [`Intl.NumberFormat`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) for creating the basic "number" localizer. + * @param {string} [options.localization.dateOptions=Hypergrid.localization.dateOptions] - Options passed to [`Intl.DateTimeFormat`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat) for creating the basic "date" localizer. * * @param {object} [options.schema] * @@ -126,7 +155,7 @@ var Hypergrid = Base.extend('Hypergrid', { this.cellEditors = Object.create(cellEditors); Object.defineProperty(this.cellEditors, 'create', { value: createCellEditor.bind(this) }); - this.initCanvas(); + this.initCanvas(options.canvasContextAttributes); if (this.options.Behavior) { this.setBehavior(this.options); // also sets this.options.pipeline and this.options.data @@ -1048,7 +1077,7 @@ var Hypergrid = Base.extend('Hypergrid', { * @summary Initialize drawing surface. * @private */ - initCanvas: function() { + initCanvas: function(contextAttributes) { if (!this.divCanvas) { var divCanvas = document.createElement('div'); @@ -1056,7 +1085,7 @@ var Hypergrid = Base.extend('Hypergrid', { this.div.appendChild(divCanvas); - var canvas = new Canvas(divCanvas, this.renderer, this.options.canvas); + var canvas = new Canvas(divCanvas, this.renderer, contextAttributes); canvas.canvas.classList.add('hypergrid'); this.divCanvas = divCanvas; diff --git a/src/lib/Canvas.js b/src/lib/Canvas.js index ccbb60f4e..ac42752ea 100644 --- a/src/lib/Canvas.js +++ b/src/lib/Canvas.js @@ -22,7 +22,7 @@ var RESIZE_POLLING_INTERVAL = 200, resizeInterval, charMap = makeCharMap(); -function Canvas(div, component) { +function Canvas(div, component, contextAttributes) { var self = this; // create the containing
...
@@ -37,8 +37,8 @@ function Canvas(div, component) { this.div.appendChild(this.infoDiv); // create and append the canvas - this.gc = getCachedContext(this.canvas = document.createElement('canvas')); - this.bc = getCachedContext(this.buffer = document.createElement('canvas')); + this.gc = getCachedContext(this.canvas = document.createElement('canvas'), contextAttributes); + this.bc = getCachedContext(this.buffer = document.createElement('canvas'), contextAttributes); this.div.appendChild(this.canvas); @@ -791,8 +791,8 @@ function makeCharMap() { return map; } -function getCachedContext(canvasElement, type) { - var gc = canvasElement.getContext(type || '2d', { alpha: false }), +function getCachedContext(canvasElement, contextAttributes) { + var gc = canvasElement.getContext('2d', contextAttributes), props = {}, values = {}; From b6fce085043b0d08dab4367df1b35f4d7603a9b4 Mon Sep 17 00:00:00 2001 From: Jonathan Eiten Date: Wed, 27 Jun 2018 21:28:49 -0400 Subject: [PATCH 4/6] fix error in terminate (Issue #733) --- src/Hypergrid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Hypergrid.js b/src/Hypergrid.js index 3418fc9f6..2ce50de5f 100644 --- a/src/Hypergrid.js +++ b/src/Hypergrid.js @@ -203,7 +203,7 @@ var Hypergrid = Base.extend('Hypergrid', { terminate: function() { document.removeEventListener('mousedown', this.mouseCatcher); this.canvas.stop(); - Hypergrid.grids.splice(this.grids.indexOf(this), 1); + Hypergrid.grids.splice(Hypergrid.grids.indexOf(this), 1); }, From fe1db3c7a410a9b751caf2c114bd3766405bfc80 Mon Sep 17 00:00:00 2001 From: Jonathan Eiten Date: Thu, 28 Jun 2018 10:52:14 -0400 Subject: [PATCH 5/6] bump version to 2.1.15 --- README.md | 10 +++++----- demo/formatter-workbench/instructions.html | 3 ++- demo/index.html | 2 +- demo/multiple-grids.html | 2 +- demo/row-props.html | 2 +- package-lock.json | 2 +- package.json | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ddf3cb3a6..dc00e8b0b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ It also highlights a DOM-based custom external editor triggered via hypergrid ev ## Table of Contents -* [Current Release](#current-release-2111---12-june-2018) +* [Current Release](#current-release-2115---29-june-2018) * [Demos](#demos) * [Features](#features) * [Testing](#testing) @@ -16,9 +16,9 @@ It also highlights a DOM-based custom external editor triggered via hypergrid ev * [Roadmap](#roadmap) * [Contributing](#contributors) -### Current Release (2.1.14 - 12 June 2018) +### Current Release (2.1.15 - 29 June 2018) -**Hypergrid 2.1.14** includes bug fixes. +**Hypergrid 2.1.15** includes bug fixes and new features. _For a complete list of changes, see the [release notes](https://github.com/fin-hypergrid/core/releases)._ @@ -52,13 +52,13 @@ Find more information on our [testing page](TESTING.md) Primarily our tutorials will be on the [wiki](https://github.com/fin-hypergrid/core/wiki). -We also maintain versioned [online API documentation](https://fin-hypergrid.github.io/core/2.1.14/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.15/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/fin-hypergrid/core/wiki/Cell-Editors).) (Cell Rendering information can be found [here](https://github.com/fin-hypergrid/core/wiki/Cell-Renderers).) -Hypergrid global configurations can be found [here](https://fin-hypergrid.github.io/core/2.1.14/doc/module-defaults.html). +Hypergrid global configurations can be found [here](https://fin-hypergrid.github.io/core/2.1.15/doc/module-defaults.html). ### Roadmap diff --git a/demo/formatter-workbench/instructions.html b/demo/formatter-workbench/instructions.html index 78c766e9b..7bf1ffb56 100644 --- a/demo/formatter-workbench/instructions.html +++ b/demo/formatter-workbench/instructions.html @@ -173,7 +173,7 @@

Define a new localizer and add it to the grid

  • Code your localizer referring to examples and the localizer interface documentation.
  • Be sure to assign your localizer to module.exports.
  • Click the grid.localization.add(…) button.
  • -
  • Optional: Edit the localizer and click grid.localization.add(…) to update it.
  • +
  • Optional: Edit the localizer and click grid.localization.add(…) again to update it.
  • @@ -299,6 +299,7 @@
    Throw error on parser failer
    1. In the Localizer pane, select the trend localizer.
    2. Uncomment the if statement with the throw statement within it.
    3. +
    4. Click the grid.localization.add(…) button to update it.
    5. Edit another cell, again setting the contents to some invalid value.
    6. Press the enter key.
    7. The parser cannot convert the value.
    8. diff --git a/demo/index.html b/demo/index.html index 981012c65..d39465739 100644 --- a/demo/index.html +++ b/demo/index.html @@ -22,7 +22,7 @@ b = g.behavior, m = b.dataModel;">top-level global vars -

      Hypergrid 2.1.14 dev testbench

      +

      Hypergrid 2.1.15 dev testbench

      Dashboard
      diff --git a/demo/multiple-grids.html b/demo/multiple-grids.html index 30b0d24f5..c4a9a033a 100644 --- a/demo/multiple-grids.html +++ b/demo/multiple-grids.html @@ -5,7 +5,7 @@ -

      Hypergrid 2.1.14 multiple grids demo

      +

      Hypergrid 2.1.15 multiple grids demo

      diff --git a/demo/row-props.html b/demo/row-props.html index e6129bdf7..9f60530a1 100644 --- a/demo/row-props.html +++ b/demo/row-props.html @@ -38,7 +38,7 @@ -

      Hypergrid 2.1.14 performance workbench

      +

      Hypergrid 2.1.15 performance workbench