import { makeElement, selectElement } from 'muze-utils';
import { cellSpanMaker } from './span-maker';
import {
TOP, LEFT, RIGHT, BOTTOM, CENTER, WIDTH, ROW_SPAN, COL_SPAN
} from '../enums/constants';
import { BLANK_BORDERS } from './defaults';
/**
* Creates a table element of the layout
*
* @param {Object} mount Mount point for table elements
* @param {string} className defines class name
* @param {Array} rowData set of rows for the table
* @return {Selection} set of selections for the table
*/
function renderTable (mount, className, rowData) {
const table = makeElement(mount, 'table', ['layout'], `${className}-table`);
const body = makeElement(table, 'tbody', ['layout'], `${className}-body`);
const rows = makeElement(body, 'tr', rowData, `${className}-tr`);
const cells = makeElement(rows, 'td', (d, i) => d.filter(e => e !== null && e.config().show).map(e =>
({ placeholder: e, rowIndex: i })), `${className}-td`, {}, key => key.placeholder.id);
return { table, body, rows, cells };
}
function applyRowBorders (cells, borderStyle, showBorders, color) {
[TOP, BOTTOM].forEach((borderType) => {
const style = `${borderStyle} ${showBorders[borderType] ? color : BLANK_BORDERS}`;
cells.style(`border-${borderType}`, style);
});
}
function applyColBorders (cells, borderStyle, showBorders, color) {
[LEFT, RIGHT].forEach((borderType) => {
const style = `${borderStyle} ${showBorders[borderType] ? color : BLANK_BORDERS}`;
cells.style(`border-${borderType}`, style);
});
}
/**
* Applies borders to the cells in a matrix
*
* @param {Selection} cells Set of cells made from the matrix
* @param {Object} border Border info for layout
* @param {string} type Type of matrix(top/center/bottom)
* @param {number} index Column index of matrix in the row
*/
function applyBorders (cells, border, type, index) {
const {
width,
style,
color,
showRowBorders,
showColBorders,
showValueBorders
} = border;
const borderStyle = `${width}px ${style}`;
if (type === CENTER && index === 1) {
[TOP, BOTTOM, LEFT, RIGHT].forEach((borderType) => {
cells.style(`border-${borderType}`, `${borderStyle} ${showValueBorders[borderType] ?
color : BLANK_BORDERS}`);
});
} else if (type === CENTER) {
applyRowBorders(cells, borderStyle, showRowBorders, color);
} else if (index === 1) {
applyColBorders(cells, borderStyle, showColBorders, color);
}
}
/**
* Renders a set of matrices in a row
*
* @param {Array} matrices Set of matrices in a row
* @param {Selection} mountPoint Mount point for the row
* @param {string} type top/center/bottom
* @param {Object} dimensions dimensions of the matrix
*/
function renderMatrix (matrices, mountPoint, type, dimensions, classPrefix) {
matrices.forEach((matrix, index) => {
// Creating containers for each matrix individually
const containerForMatrix = makeElement(mountPoint, 'div', [1], `${classPrefix}-grid-${type}-${index + 1}`)
.classed(`${classPrefix}-grid-${type}`, true)
.classed(`${classPrefix}-grid`, true);
const {
viewMatrix,
spans
} = cellSpanMaker(matrix, type, index);
// Rendering the table components
const { cells } = renderTable(containerForMatrix, `${classPrefix}-grid`, viewMatrix);
if (type === CENTER && spans) {
cells.attr(ROW_SPAN, function (cell, colIndex) {
const placeholder = cell.placeholder;
selectElement(this).style('height', `${placeholder.availHeight() + dimensions.border.width}px`);
return spans[cell.rowIndex][colIndex];
});
} else if ((type === TOP || type === BOTTOM) && index === 1) {
cells.attr(COL_SPAN, function (cell, colIndex) {
const span = spans[cell.rowIndex][colIndex];
const placeholder = cell.placeholder;
if (span > 1) {
placeholder.setAvailableSpace(0, placeholder.availHeight());
}
selectElement(this).style('height', `${placeholder.availHeight()}px`);
return span;
});
}
// Rendering content within placeholders
cells.each(function (cell) {
cell.placeholder && cell.placeholder.render(this);
}).exit().each((cell) => {
cell.placeholder && cell.placeholder.remove();
});
applyBorders(cells, dimensions.border, type, index);
});
}
/**
* Renders all the matrices of the layout
*
* @export
* @param {Array} matrices Set of matrices in the layout
* @param {Array} mountPoints Mount points for each row of matrix
* @param {Array} layoutDimensions Dimensions(height/width) of all the matrices
*/
export function renderMatrices (context, matrices, layoutDimensions) {
const {
top,
center,
bottom
} = matrices;
const {
classPrefix
} = context.config();
const {
width
} = context.measurement();
const mount = context.mountPoint();
const data = [
{ type: TOP, matrix: top },
{ type: CENTER, matrix: center },
{ type: BOTTOM, matrix: bottom }
];
makeElement(mount, 'div', data, `${classPrefix}-grid-layout-row`)
.each(function (d, i) {
const row = selectElement(this);
row.classed(`${classPrefix}-grid-layout-row-${i}`, true);
renderMatrix(d.matrix, row, d.type, layoutDimensions, classPrefix);
})
.style(WIDTH, `${Math.ceil(width)}px`);
}