in js/vnext/projection/column-group.js [151:272]
constructor(columns) {
/**
* The column header rows
* @type {RowContent[]}
*/
this.headerRows = [];
/**
* The leaf columns
* @type {ExtendedColumnConfig[]}
*/
this.leafColumns = [];
/**
* The columns indexed by name
* @type {Object.<string,ExtendedColumnConfig>}
*/
this.columnIndex = {};
/*
* Build tree-like columns structure using DFS
*/
const buildColumn = col => {
/**
* An extended internal representation of columns. It extends
* {@link ColumnConfig} with several extra properties.
* @typedef ExtendedColumnConfig
* @type ColumnConfig
* @property {ExtendedColumnConfig} parent
* The parent column if there's a column hierarchy.
* @property {ExtendedColumnConfig[]} columns
* The children columns.
* @property {CellContent} cell
* The configuration of the header cell.
* @property {number} height
* The rowspan of the header cell.
* @property {number} treeWidth
* The colspan of the header cell. The tree width of the column
* subtree in number of columns.
* @property {number} treeHeight
* The height of the column subtree in number of rows.
*/
const { parent, columns, height, name, property, sortable } = col;
this.columnIndex[name] = col;
col.property = normalizeProperty(property, col);
col.sortable = normalizeSortable(sortable, col);
if (!_.isFunction(col.template)) {
col.template = defaultCellTemplate;
}
col.height = _.isNumber(height) ? height : 1;
col.rowIndex = parent ? parent.rowIndex + parent.height : 0;
col.columns = _.map(columns, c => buildColumn(_.extend({ parent: col }, c)));
col.treeHeight = col.height;
col.treeWidth = 1;
if (_.isEmpty(col.columns)) {
this.leafColumns.push(col);
} else {
col.treeHeight += _.chain(col.columns)
.map(_.property('treeHeight')).max().value();
col.treeWidth = _.chain(col.columns)
.map(_.property('treeWidth')).reduce((a, b) => a + b, 0).value();
}
return col;
};
/*
* Build column header with DFS
*/
const buildColumnHeader = col => {
if (col.parent) {
const colspan = col.treeWidth;
const rowspan = _.isEmpty(col.columns) ? this.root.treeHeight - col.rowIndex : col.height;
const name = col.name;
const group = _.result(col, 'group', 'other');
const html = col.html || col.title || col.name;
while (this.headerRows.length <= col.rowIndex) {
this.headerRows.push({ cells: [], attributes: {} });
}
const classes = _.union(normalizeClasses(col.headClasses, col), ['column-header']);
if (_.isEmpty(col.columns)) {
classes.push('column-header-leaf');
}
const attributes = _.defaults({
colspan,
rowspan,
'aria-colspan': colspan,
'aria-rowspan': rowspan,
'data-name': name,
}, normalizeAttributes(col.headAttributes, col));
col.cell = {
html,
name,
classes,
attributes,
group,
parentName: col.parent.name,
hasChild: colspan > 1,
};
this.headerRows[col.rowIndex].cells.push(col.cell);
}
_.each(col.columns, buildColumnHeader);
};
/**
* The root column
* @type {ExtendedColumnConfig}
*/
this.root = buildColumn({
name: '__root__',
height: 0,
columns,
});
buildColumnHeader(this.root);
}