UNPKG

lamed_table

Version:
373 lines (342 loc) 11.9 kB
'use strict' // Comment out in test functions console.log(`Starting ${__filename}...`) // comment line to remove simple logging /* ------------------------------------------------------ * tableFunctions.js * Purpose: The purpose of this module is to implement functions for the table object * Date Created: 2019/12/12 * Created by : Perez Lamed van Niekerk --------------------------------------------------------- */ /* jshint esversion: 6 */ const _test = require('lamed_test') const { Ok, notOk, notOk_Then, Equal, notEqual, con, testAND, unZip } = _test // eslint-disable-line // con.setupChalk(require('chalk')) // con.traceSet(0) const _name = require('lamed_name') const _cols = require('./tableCols') const _format = require('io_format') // const _lio = require('lamed_io') /** * Create an empty table object * @param {string} tableName - the table name */ function createEmpty (tableName = 'tableName') { const table = { name: tableName, cols: [], rows: [] } return table } /** * Create a table object with the specified columns * @param {array} columns - string array of the columns to add * @param {string} tableName - table name. */ function create (columns, tableName = 'tableName') { if (Array.isArray(columns) === false) columns = [columns] // if (columns.length === 0) throw new Error('Cannot create table with no columns!\n') const table = createEmpty(tableName) _cols.colsCreate(table, columns) checkTableData(table) return table } /** * Show the data within a table * @param {table} table - The table object * @param {bool} show - If true, show the output * @param {int} rowCount - The max rows to show. Default = -1 (all rows) * @param {int} colCount - The max cols to show. Default = -1 (all cols) * @param {int} maxColLength - The maximum length of a col. Default = -1 (not trimming) * @returns {void} - Nothing but output table to the console */ function showTable (table, show = true, rowCount = -1, colCount = -1, maxColLength = -1) { if (show === false) return const name = table.name // Get cols & rows let cols = table.cols let rows = table.rows if (rowCount !== -1 || colCount !== -1 || maxColLength !== -1) { if (rowCount === -1) rows = table.rows.slice(0) else rows = table.rows.slice(0, rowCount) } if (rowCount === -1) rowCount = rows.length // colCount if (colCount === -1) colCount = cols.length else { for (let ii = 0; ii < rows.length; ii++) { rows[ii] = rows[ii].slice(0, colCount) } if (colCount < cols.length) { cols = cols.slice(0, colCount) cols[colCount - 1] = cols[colCount - 1] + '...' } } // maxColLength if (maxColLength !== -1) { // con.log({maxColLength}) for (let ii = 0; ii < rows.length; ii++) { let row = rows[ii] row = row.map(x => _format.formatLine(x, maxColLength)) // Trim cell values rows[ii] = row // con.log({row}) } } con.log('') con.logHeading(`Table: ${name}`) if (Ok(table.count)) { const count = table.count if (Ok(table.totalCol)) { const totalCol = table.totalCol const min = table.min const max = table.max const sum = table.sum const avg = table.avg con.log({ name, cols, totalCol, count, min, max, sum, avg }) } else con.log({ name, cols, count }) } else { // Show cols // cols.map((x, ii) => con.logGreen(`${ii} ${x}`)) let heading = '' cols.map((x, ii) => heading += `${ii}.'${x}', `) // eslint-disable-line con.logHeading(heading, true) // con.logHeading(cols.join(', '), true) } con.logTable(rows) if (colCount < table.cols.length) con.log(` (displaying ${colCount} / ${table.cols.length} columns)`) if (rowCount < table.rows.length) con.log(` (displaying ${rowCount} / ${table.rows.length} rows)`) con.logLine() } /** * Show tracing information about the table object * @param {object} table - table object * @param {boolean} showTrace - If true, show trace information * @param {boolean} showError - If true throw error when table is not a table */ function TableCheck (table, showTrace = false, showError = true) { return checkTableData(table.DATA, showTrace, showError) } /** * Show tracing information about the table object * @param {object} tableData - table object * @param {boolean} showTrace - If true, show trace information * @param {boolean} showError - If true throw error when table is not a table */ function checkTableData (tableData, showTrace = false, showError = true) { const name = tableData.name const cols = tableData.cols const rows = tableData.rows const isTable = (Ok(name) && cols !== undefined && rows !== undefined) if (isTable === false && showError) showTrace = true showTable(tableData, showTrace) if (isTable === false && showError) throw new Error('in checkTableData(). input parameter is not a table\n') return isTable } // /** // * Sort table ascending on the specified columns // * @param {object} table - The Table object // * @param {string / number} colNamesOrNumbers - The columns names or the numbers to sort on // */ // function sortFields (table, colNamesOrNumbers, acending = true) { // if (Array.isArray(colNamesOrNumbers) === false) throw new Error('colNamesOrNumbers must be an array') // let colNames = colNamesOrNumbers.reverse() // for (let ii = 0; ii < colNames.length; ii++) { // let colName = colNames[ii] // sort(table, colName, acending) // } // } /** * Sort table ascending on the specified column * @param {object} table - The Table object * @param {string / number} colNameOrNumber - The column number or the the name */ function sort (table, colNameOrNumber, acending = true) { checkTableData(table, false, true) const colNo = _cols.colsNumber(table.cols, colNameOrNumber) if (acending) table.rows.sort((a, b) => sortAsc1(a, b, colNo)) else table.rows.sort((a, b) => sortDec1(a, b, colNo)) } function sortAsc1 (a, b, col = 0) { if (a[col] === b[col]) return 0 else return (a[col] < b[col]) ? -1 : 1 } function sortDec1 (a, b, col = 0) { if (a[col] === b[col]) return 0 else return (a[col] > b[col]) ? -1 : 1 } /** * Convert a array table to markdown table * @param {object} table - The table object * @param {string / number} boldCol - The col name or number to bold * @param {string} heading - The heading to use for the markdown table. Default = table name */ function table2MD (table, boldColumn = -1, heading = '') { const boldCol = _cols.colsNumber(table.cols, boldColumn) if (notOk(heading)) { // Lets build heading from the table name heading = table.name heading = _name.name2Heading(heading) heading = `## ${heading}` } let result = `${heading}\n\n| ` let header = '| ' for (let ii = 0; ii < table.cols.length; ii++) { let item = table.cols[ii] item = _name.name2Heading(item) result += item + ' |' header += ' ---- |' } result += '\n' + header + '\n' for (let ii = 0; ii < table.rows.length; ii++) { const row = table.rows[ii] for (let jj = 0; jj < row.length; jj++) { let item = row[jj] // con.log({item}) if (typeof item === 'string') { item = item.trim() item = item.replaceAll('\n', '<br>') // '\n' is not supported in markdown tables } if (jj === boldCol) item = `**${item}**` result += item + ' |' } result += '\n' } // con.trace({result}) return result } // Convert table to CSV /** * Convert a table to CSV format * @param {table} table - The table to convert * @param {bool} addHeadings - If true, add the headings */ function Table2CSV (table, addHeadings = true) { const result = [] if (addHeadings) result.push(table.cols.join(', ')) for (let ii = 0; ii < table.rows.length; ii++) { const row = table.rows[ii] result.push(row.join(', ')) } return result.join('\r\n') } /** * Return header information for the table */ function table2HTML_Header () { // eslint-disable-line const result = // ' <link rel="stylesheet" type="text/css" href="./DataTables/jquery-ui.css"/>\n'+ // ' <link rel="stylesheet" type="text/css" href="./DataTables/dataTables.jqueryui.min.css"/>\n'+ ' <link rel="stylesheet" type="text/css" href="./cdn/jquery.dataTables.min.css"/>\n' + ' <script type="text/javascript" src="./cdn/jquery-3.3.1.js"></script>\n' + ' <script type="text/javascript" src="./cdn/jquery.dataTables.min.js"></script>\n' return result } /** * Return script for the table */ function table2HTML_Script (idName = 'dataTable') { // eslint-disable-line const result = '<script>\n' + ' $(document).ready(function() {\n' + ` $('#${idName}').DataTable({ autoFill: true, keys : true } );\n` + ' } );\n' + '</script>\n' return result } /** * Convert a array table to HTML table * @param {object} table - The table object */ function table2HTML (table, idName = 'dataTable', htmlClass = 'cell-border', addFooter = true, buildPage = true) { htmlClass = 'display compact' htmlClass = 'cell-border compact stripe hover' let result = `<table id="${idName}" class="${htmlClass}" style="width:100%">\n` let header = ' <tr> ' const header1 = '<th>' const header2 = '</th> ' for (let ii = 0; ii < table.cols.length; ii++) { let item = table.cols[ii] item = _name.name2Heading(item) header += header1 + item + header2 } header += ' </tr>\n' result += ' <thead>\n' + header + ' </thead>\n' result += ' <tbody>\n' let footer = '' if (addFooter) footer = ' <tfoot>\n' + header + ' </tfoot>\n' for (let ii = 0; ii < table.rows.length; ii++) { let line = ' <tr> ' const row = table.rows[ii] for (let jj = 0; jj < row.length; jj++) { let item = row[jj] // con.log({item}) if (typeof item === 'string') { item = item.trim() item = item.replaceAll('\n', '<br>') // '\n' is not supported in markdown tables } const value = '<td>' + item + '</td> ' // con.log({value}) line += value } line += ' </tr>\n' // con.log({line}) result += line } result += ' </tbody>\n' result += footer result += '</table>\n\n' // con.trace({result}) if (buildPage) { result = '<html>\n<head>\n' + table2HTML_Header() + '</head>\n' + '<body>\n' + result + table2HTML_Script() + '</body>\n</html>' } return result } /** * Import items from a list into a table. This can be used to divide lists into columns * @param {array} list - List of array * @param {object} table - The table */ function TableArray2Columns (list, table) { const total = table.totalCols() // con.log({total}) let index = 0 let row = [] for (let ii = 0; ii < list.length; ii++) { const item = list[ii] table.Rows.Set(row, index, item) index++ if (index === total) { table.Rows.Add(row) row = [] index = 0 } } } /** * Total columns in the table * @param {object} table - The table object * @returns {number} - the total columns in the table */ function totalCols (table) { return table.cols.length } /** * Total rows in the table * @param {object} table - The table object * @returns {number} - The total rows in the table */ function totalRows (table) { return table.rows.length } // Exports -------------------------- module.exports = { create, showTable, TableCheck, checkTableData, totalCols, totalRows, // Adding TableArray2Columns, // Format sort, table2MD, Table2CSV, table2HTML }