Make rows move-resilient

master
Vitaliy Filippov 2019-02-11 20:32:50 +03:00
parent 5880fa26ea
commit c1ec2a1fdb
1 changed files with 25 additions and 18 deletions

View File

@ -6,11 +6,13 @@
*
* Author: Vitaliy Filippov <vitalif@yourcmc.ru>, 2019
* License: dual-license MPL 2.0 or GPL 3.0+
* Version: 2019-02-11
*/
import React from 'react';
import PropTypes from 'prop-types';
import bindCache from './bind-cache.js';
import default_css from './FixedHeaderGridTableRT.css';
/**
@ -51,7 +53,7 @@ export class FixedHeaderGridTable extends React.PureComponent
userWidths: [],
}
activeRow = 0
activeRow = null
componentDidMount()
{
@ -241,13 +243,14 @@ export class FixedHeaderGridTable extends React.PureComponent
}
c = c.parentNode;
}
row = row || null;
// Row highlight
if (this.props.hasRowHover !== false)
{
const css = this.props.theme || default_css;
if (this.activeRow != row)
{
if (this.activeRow > 0)
if (this.activeRow != null)
{
for (let e of this.rootNode.querySelectorAll('*[row="'+this.activeRow+'"]'))
{
@ -255,7 +258,7 @@ export class FixedHeaderGridTable extends React.PureComponent
}
}
this.activeRow = row;
if (this.activeRow > 0)
if (this.activeRow != null)
{
for (let e of this.rootNode.querySelectorAll('*[row="'+this.activeRow+'"]'))
{
@ -276,14 +279,14 @@ export class FixedHeaderGridTable extends React.PureComponent
{
// Remove row highlight
const css = this.props.theme || default_css;
if (this.activeRow > 0)
if (this.activeRow != null)
{
for (let e of this.rootNode.querySelectorAll('*[row="'+this.activeRow+'"]'))
{
e.className = e.className.replace(' '+css.hover, '');
}
}
this.activeRow = 0;
this.activeRow = null;
}
if (this.props.isResizable === undefined || this.props.isResizable)
{
@ -296,8 +299,9 @@ export class FixedHeaderGridTable extends React.PureComponent
this.rootNode = e;
}
decorateCells(row, decorateProps)
decorateCells = (status, row, decorateProps) =>
{
const rowKey = decorateProps && decorateProps.key;
const css = this.props.theme || default_css;
let cells = [];
let j = 0;
@ -310,8 +314,8 @@ export class FixedHeaderGridTable extends React.PureComponent
}
const isDiv = React.isValidElement(cell) && cell.type == 'div';
const className = ' ' + css.cell + ' ' +
(decorateProps.rowIndex == 0 ? ' '+css.first_row : '') +
(decorateProps.rowIndex == decorateProps.rowCount-1 ? ' '+css.last_row : '') +
(status == 'first' ? ' '+css.first_row : '') +
(status == 'last' ? ' '+css.last_row : '') +
(j == 0 && (!isDiv || !cell.props.style ||
!cell.props.style.gridColumn && !cell.props.style.gridColumnStart ||
cell.props.style.gridColumn == 1 || cell.props.style.gridColumnStart == 1) ? ' '+css.first_col : '') +
@ -319,7 +323,7 @@ export class FixedHeaderGridTable extends React.PureComponent
(j & 1 ? ' '+css.even : '');
if (!isDiv)
{
cell = (<div className={className} row={decorateProps.rowIndex} col={j} key={decorateProps.rowIndex+'-'+j}>
cell = (<div className={className} row={rowKey} col={j} key={rowKey+'-'+j}>
{this.props.noWrapDefault
? <div className={css.ellipsis}>{cell}</div>
: cell}
@ -340,9 +344,8 @@ export class FixedHeaderGridTable extends React.PureComponent
else if (cell.props.sticky_row > 0)
cls = cls + ' ' + css.stick_top;
let props = {
row: decorateProps.rowIndex,
col: j,
key: decorateProps.rowIndex+'-'+j,
row: rowKey,
key: rowKey+'-'+j,
className: cls+className,
};
if (spec.wrap || !this.props.noWrapDefault)
@ -371,19 +374,19 @@ export class FixedHeaderGridTable extends React.PureComponent
let i = 0;
for (let row of rows)
{
const rowProps = { rowIndex: i, rowCount: rows.length };
if (React.isValidElement(row))
{
// Allow element rows
// In fact, this should be the default use-case
rowProps.decorateCells = (cells) => this.decorateCells(cells, rowProps);
cells.push(React.cloneElement(row, rowProps));
cells.push(React.cloneElement(row, {
decorateCells: this.bind('decorateCells', i == 0 ? 'first' : (i == rows.length-1 ? 'last' : '')),
}));
}
else
{
// In other case just process cells in-place
// BUT this is slow, because such cells are reconciled on each render
cells.push.apply(cells, this.decorateCells(row, rowProps));
cells.push.apply(cells, this.decorateCells(i, row));
}
i++;
}
@ -393,11 +396,13 @@ export class FixedHeaderGridTable extends React.PureComponent
// So we add some extra invisible cells to do this
for (let col = 0; col < this.props.columnWidths.length; col++)
{
cells.push(<div className={css.measure_col} style={{gridColumn: (col+1)}}></div>);
cells.push(<div key={"mc"+col} className={css.measure_col}
style={{gridColumn: (col+1)}}></div>);
}
for (let row = 0; row < rows.length; row++)
{
cells.push(<div className={css.measure_row} style={{position: 'absolute', left: '-100px', width: '1px', height: '1px', gridColumn: 1, gridRow: (row+1)}}></div>);
cells.push(<div key={"mr"+row} className={css.measure_row}
style={{position: 'absolute', left: '-100px', width: '1px', height: '1px', gridColumn: 1, gridRow: (row+1)}}></div>);
}
}
const ws = this.state.userWidths || [];
@ -422,4 +427,6 @@ export class FixedHeaderGridTable extends React.PureComponent
: null}
</div>);
}
bind = bindCache(this)
}