constructor()

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);
  }