Hypergrid

cell-borders demo

This demo contains sample code showing how to paint custom cell borders as an alterative to using Hypergrid's grid lines feature.

Example 1.

This example uses the default grid lines feature, where grid rule lines are painted between cells after each grid render.

grid.addProperties({ // add properties to grid.properties object showRowNumbers: false, gridLinesH: true, gridLinesV: true // (these are the default settings) });

Example 2.

This example uses the Borders overlay cell renderer, defined herein, which is controlled by optionally defined properties borderTop, borderTop, borderBottom, and borderLeft, all of which take a CSS color spec. Defining the bottom and right of each cell produces the following result, which is very similar to the default grid lines feature. (These are defined on the grid.properties object, which each cell has in its properties scope.)

var GREY = '#bbb', renderer = ['SimpleCell', 'Borders']; grid.addProperties({ showRowNumbers: false, gridLinesH: false, gridLinesV: false, renderer: renderer, columnHeaderRenderer: renderer, borderBottom: GREY, borderRight: GREY });

Example 3.

This example also uses the Borders cell renderer but only defines some borders on selected cells.

grid.addProperties({ showRowNumbers: false, gridLinesH: false, gridLinesV: false, cells: rect });

Example 4.

This example again uses the Borders cell renderer, combining examples 2 and 3 above by setting the the properties set by both.

grid.addProperties({ gridLinesH: false, gridLinesV: false, renderer: renderer, columnHeaderRenderer: renderer, borderBottom: GREY, borderRight: GREY, cells: rect });

Example 5.

This example uses a different cell renderer, OpaqueBorders, controlled by a single property, border whose properties are "opaque" (have no scope). See the discussion below for more details.

renderer = ['SimpleCell', 'OpaqueBorders']; grid.addProperties({ gridLinesH: false, gridLinesV: false, renderer: renderer, columnHeaderRenderer: renderer, border: { bottom: GREY, right: GREY }, cells: opaqueRect });

var RED = 'red'; var rect = { // cell properties for use with Borders cell renderer data: { // subgrid key 1: { // row index prevclose: { borderLeft: RED, borderTop: RED }, name: { borderTop: RED, borderRight: RED } }, 2: { // row index prevclose: { borderLeft: RED, borderBottom: RED }, name: { borderBottom: RED, borderRight: RED } } } }; var opaqueRect = { // cell properties for use with OpaqueBorders cell renderer data: { // subgrid key 1: { // row index prevclose: { border: { left: RED, top: RED } }, name: { border: { top: RED, right: RED } } }, 2: { // row index prevclose: { border: { left: RED, bottom: RED } }, name: { border: { bottom: RED, right: RED } } } } };

About cells grid property

The cells grid property is a dynamic property (an accessor), implemented specifically for use with setState/addState calls. This is not however the only way to set cell properties; they can also be set programmatically. Both methods set the cell metadata for you. Another way is to load the metadata directly.

The definitions used herein, rect and opaqueRect are excerpted at right (or see GitHub).

About Borders vs. OpaqueBorders

It is worth studying the cell renderer examples provided here. These are both overlay cell renderers in that they perform additional rendering after an initial background cell renderer (in this case SimpleCell, the default cell renderer).

Disclaimer: As the saying goes, there are "many ways to skin a cat." Likewise, there are many ways to implement cell borders and to write cell renderers. The examples given here are just that: examples. In particular, as with all Hypergrid coding, performance is always in issue. In general, cell borders are never going to be anywhere as performant as Hypergrid's grid lines feature — which renders grid rule lines after all the cells have been rendered.

The Borders overlay cell renderer (file or GitHub) uses flat properties borderTop, borderRight, borderBottom, and borderLeft, which have scope up the prototype chain of properties objects (which typically looks like grid.propertiescolumn.propertiescell.properties) and will "cascade" when a more local definition is lacking.

The OpaqueBorders overlay cell renderer (file or GitHub) uses a complex (nested) property called border which may have top, right, bottom, and/or left properties. But because the border property itself has no prototype chain, these properties have no scope and will not cascade. The implication of this is that the most local definition of border must fully describe the cell's borders. This is best explained by observing the difference between the final two examples above (examples 4 and 5). (Note how the grid.properties.border object is obscured by the cell's border object.)

A final note: If we were to properly set up the prototype chain of these border objects (with Object.create or Object.setPrototypeOf), then the OpaqueBorders renderer would produce the same results as the Borders and we wouldn't need both. However, although this can be demonstrated, doing so in practice would be unmanageable (not to mention subtle and obscure).

Regarding right-most rule line

Hypergrid's grid lines feature does not paint a grid line at the right of the final column but the cell border is appearing there. To avoid painting this line, we could have "undefined" the final column's borderRight property to obscure the underlying grid.properties.borderRight property value, for example by including the columns dynamic grid property in the addState call, like this: columns: { name: { borderRight: undefine } }

A note about this demo's modules

Module standards in JavaScript are all over the place. There are many ways to split up code into separate files, both at build time as well as in the server. For this demo, I wanted to split up the code into distinctly served .js files so I could link to them here. To avoid a build just to bundle them, I've defined a window.onload handler in each, called in the order referenced in `index.html` when the page is loaded.