ASCII table where each field is capable of containing multiple lines of text

Below is a function that generates an ASCII table:

        function ascii_table(array, header) {
            if (!array.length) {
                return '';
            }
            var lengths = array[0].map(function(_, i) {
                var col = array.map(function(row) {
                    if (row[i] != undefined) {
                        return row[i].length;
                    } else {
                        return 0;
                    }
                });
                return Math.max.apply(Math, col);
            });
            array = array.map(function(row) {
                return '| ' + row.map(function(item, i) {
                    var size = item.length;
                    if (size < lengths[i]) {
                        item += new Array(lengths[i]-size+1).join(' ');
                    }
                    return item;
                }).join(' | ') + ' |';
            });
            var sep = '+' + lengths.map(function(length) {
                return new Array(length+3).join('-');
            }).join('+') + '+';
            if (header) {
                return sep + '\n' + array[0] + '\n' + sep + '\n' +
                    array.slice(1).join('\n') + '\n' + sep;
            } else {
                return sep + '\n' + array.join('\n') + '\n' + sep;
            }
        }

However, when the cell contains a new line, the output looks like this:

+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+
| date                | nick   | email | www | comment                       | ip         | avatar              |
+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+
| 2016-01-27 21:11:10 | stefan | kanev |     | dsfdsfsd
sdfsdf
sdfsdf
sdfdsf | 1308240552 | avatars/default.png |
+---------------------+--------+-------+-----+-------------------------------+------------+---------------------+

To fix this issue and have the desired result like below, you need to make some changes in your function:

+---------------------+--------+-------+-----+----------+------------+---------------------+
| date                | nick   | email | www | comment  | ip         | avatar              |
+---------------------+--------+-------+-----+----------+------------+---------------------+
| 2016-01-27 21:11:10 | stefan | kanev |     | dsfdsfsd | 1308240552 | avatars/default.png |
|                     |        |       |     | sdfsdf   |            |                     |
|                     |        |       |     | sdfsdf   |            |                     |
|                     |        |       |     | sdfdsf   |            |                     |
+---------------------+--------+-------+-----+----------+------------+---------------------+

Answer №1

To enhance the functionality of the table, you can customize it by inserting new rows into the table prior to rendering:

function ascii_table(array, header) {
    if (!array.length) {
        return '';
    }

    //additional logic
    for (var i = array.length - 1; i >= 0; i--) {
        var row = array[i];
        var stacks = [];
        for (var j = 0; j < row.length; j++) {
            var newLines = row[j].split("\n");
            row[j] = newLines.shift();
            stacks.push(newLines);
        }
        var newRowsCount = stacks.reduce(function(a, b) {
            return a.length > b.length ? a : b;
        }).length;
        for (var k = newRowsCount - 1; k >= 0; k--) {
            array.splice(i + 1, 0, stacks.map(function(stackColumn) {
                return stackColumn[k] || "";
            }));
        }
    }
    //additional logic

    var lengths = array[0].map(function(_, i) {
        var col = array.map(function(row) {
            if (row[i] != undefined) {
                return row[i].length;
            } else {
                return 0;
            }
        });
        return Math.max.apply(Math, col);
    });
    array = array.map(function(row) {
        return '| ' + row.map(function(item, i) {
            var size = item.length;
            if (size < lengths[i]) {
                item += new Array(lengths[i] - size + 1).join(' ');
            }
            return item;
        }).join(' | ') + ' |';
    });
    var sep = '+' + lengths.map(function(length) {
        return new Array(length + 3).join('-');
    }).join('+') + '+';
    if (header) {
        return sep + '\n' + array[0] + '\n' + sep + '\n' +
            array.slice(1).join('\n') + '\n' + sep;
    } else {
        return sep + '\n' + array.join('\n') + '\n' + sep;
    }
}

Output:

+---------------------+------+--------+-----+------------------+------------+---------------------+
| date                | nick | email  | www | comment          | ip         | avatar              |
+---------------------+------+--------+-----+------------------+------------+---------------------+
| 2016-01-28 11:40:59 | lol  | lol@lo |     | nocomment        | 1844311719 | avatars/default.png |
|                     |      | l.fr   |     | lol              |            |                     |
|                     |      |        |     | lol              |            |                     |
|                     |      |        |     | lol              |            |                     |
| 2016-01-10 15:13:59 | ehs  | what   |     | ente rm comment. | 1423172924 | avatars/default.png |
+---------------------+------+--------+-----+------------------+------------+---------------------+

(Introducing a new line in an email cell to test multiple column formatting).

Answer №2

To implement this feature without altering your existing code, you can simply extend your array by adding a new row for each additional line in the comment. The initial row will remain unchanged, but with only the first line of the comment in the comment cell. Subsequent rows will have empty cells except for the comment cell which will contain that specific comment line.

For better readability, I recommend breaking down most of the functions. However, if you prefer to stick to your coding style, the implementation may resemble the following snippet:

  array = array.reduce(function (carry, originalRow) {
    var commentLines = originalRow[4].split(/\n/g);

    var rows = commentLines.map(function (commentLine, rowIndex) {
        var newRow = originalRow.map(function (originalCellContent, columnIndex) {
            var cellContent = '';

            if (rowIndex === 0) {
                cellContent = originalCellContent;
            }
            if (columnIndex === 4) {
                cellContent = commentLine;
            }

            return cellContent;
        });
        carry.push(newRow);
    });

    return carry;
  }, []);

You can access a modified version of your fiddle at this link, where this code has been integrated.

Answer №3

Here is the link you requested: https://jsfiddle.net/zww557sh/1/

    function generateAsciiTable(dataArray, includeHeader) {
        if (!dataArray.length) {
            return '';
        }
        var columnLengths = dataArray[0].map(function(_, i) {
            var column = dataArray.map(function(row) {
                if (row[i] !== undefined) {
                    return row[i].length;
                } else {
                    return 0;
                }
            });
            return Math.max.apply(Math, column);
        });
        dataArray = dataArray.map(function(row) {
            var columns = row.map(function(item) {
              return item.split("\n");
            });
            var maxColumnHeight = (columns.reduce(function(i,j){return i.length > j.length ? i : j})).length;

            var tableRow = "";
            for (h=0; h<maxColumnHeight; h++) {
              tableRow += "| ";
              for (c=0; c<columns.length; c++) {
                if (c > 0) tableRow += " | ";
                var dataItem = columns[c][h] || "";
                var dataSize = dataItem.length;
                if (dataSize < columnLengths[c]) {
                  dataItem += new Array(columnLengths[c]-dataSize+1).join(' ');
                }
                tableRow += dataItem;
              }
              tableRow += " |";
              if (h < maxColumnHeight-1) tableRow += "\n";
            }
          return tableRow;
        });
        var separator = '+' + columnLengths.map(function(length) {
            return new Array(length+3).join('-');
        }).join('+') + '+';
        if (includeHeader) {
            return separator + '\n' + dataArray[0] + '\n' + separator + '\n' +
                dataArray.slice(1).join('\n') + '\n' + separator;
        } else {
            return separator + '\n' + dataArray.join('\n') + '\n' + separator;
        }
    }

Output:

+---------------------+------+------------+-----+-----------------------+------------+---------------------+
| date                | nick | email      | www | comment               | ip         | avatar              |
+---------------------+------+------------+-----+-----------------------+------------+---------------------+
| 2016-01-28 11:40:59 | lol  | <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ff939093bf939093d1998d">[email protected]</a> |     | nocomment             | 1844311719 | avatars/default.png |
|                     |      |            |     | lol                   |            |                     |
|                     |      |            |     | lol                   |            |                     |
|                     |      |            |     | lol                   |            |                     |
| 2016-01-10 15:13:59 | ehs  | what       |     | ente rm comment.      | 1423172924 | avatars/default.png |
+---------------------+------+------------+-----+-----------------------+------------+---------------------+

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sending arrays to a PHP script

I've hit a roadblock trying to figure out how to resolve this issue. Unfortunately, my attempts to find answers online have been futile. Here is a snippet of the code: var params = "nome=" + encodeURI(document.getElementById("name").value )+ "&e ...

Unable to get jQuery scrollTo() function to work within Angular 4

I have encountered an issue while using a library called ng2-pdf-viewer. The default way to stick to a page in the PDF document was not working as expected. To overcome this, I utilized jQuery's scrollTo() method to navigate to the specific .page clas ...

Learn to display multiple collections of data on a webpage using Node.js and MongoDB

Struggling with displaying multiple collections on my webpage. After extensive research, I keep encountering an error message saying "Failed to look up view in views directory." Here is the code snippet causing the issue: router.get('/', functio ...

Ways to customize the appearance of a unique component

I'm faced with a challenge where I need to make edits to a component that is not editable: import * as React from 'react' import styled from '@emotion/styled' import FlexRow from '../../layouts/FlexRow' const RowContaine ...

The JSON output didn't render properly and returned as 'undefined'

I am dealing with JSON output from a web method, and I need to figure out how to render it properly. The data looks like this: {"d":"[{\"id\":1,\"username\":\"deepak_nhm\",\"companyid\":4,\"MaxEQuizScoreAvailab ...

obtain an inner element within a container using the class name in a div

I am attempting to locate a span element with the class of main-tag within a nested div. However, I want to avoid using querySelector due to multiple elements in the HTML file sharing the same class and my preference against using IDs. I realize there mig ...

Ways to conceal an image by using two functions upon clicking

I have a unique concept in mind - I want to create a functionality where on clicking an image, it would hide the image and start playing content in the background. The content would be an iframe video without a play button, so clicking anywhere on the vi ...

Event handler or callback function in Socialite.js

Exploring the capabilities of Socialite.js for the first time has been quite intriguing. This JavaScript plugin allows loading social media plugins after page load, adding an interesting dynamic to website interactivity. However, I am faced with the challe ...

Instructions on transferring a variable from JavaScript to PHP once the form is submitted

I'm looking for a solution to dynamically add rows to a table with textfields every time a user clicks a button: <script language = "javascript"> var x = 0; function addRow(){ var tbody = document.getElementById(tabID).getElementsByTagNa ...

Error occurs during array initialization in c programming runtime

Here is my code snippet for initializing the array: #include <stdio.h> int main (void) { int x, n; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int *array = {2, 4, 6, 9, 11, 13, 15, 17, 19, 21, 25, 29, 30, 3 ...

"Conditional statement checks for the presence of a specific key in a JavaScript

While working on a MEAN stack project in Node.JS, I came across an interesting issue with a dictionary object. Earlier in my code, I created a dictionary named keywordSearches. It holds information about the frequency of keyword searches, pulled from Mong ...

VBScript - Retrieve a Recordset as an Array (SQL-Like Feature)

I am currently developing a program to assist the accountant at my company. I am encountering an issue with returning articles' families in an array where each family must have an accounting code that starts with "707". Below is the VBScript code I ha ...

Scripting in jQuery to create dropdown menus

I've encountered a unique issue on my website where a user's selection from one list should update the values in another list: <form id="form1"> <div> <select id="workField"> <option value ...

Converting Strings to HTML Using JavaScript

I need assistance with printing p as an HTML object on my webpage. Currently, it is displaying as a string. What steps should I take to ensure it prints as an HTML object? The code in question is provided below: const page_nav = () => { ...

Prevent the use of unnecessary object properties

Currently, my project involves using Typescript and React in conjunction with Material-UI. Specifically, I am utilizing Material-UI's styling solution, which implements CSS in JS methodology in a Hook-like manner as outlined in their documentation: co ...

Troubleshooting: Why Laravel 5 VueJS Integration is Failing

I have recently set up a Laravel project and am attempting to integrate Vue.js into it. After running the following commands in my terminal: npm install npm run dev The commands executed without any errors. However, when I tried to import the default Vue ...

Tips for inserting SVG images into PDF documents

Is there a way to generate a PDF upon clicking the "generate PDF" button? The PDF should display an image containing highlighted squares corresponding to the user's selections on the webpage. I've been struggling to include the SVG in the PDF as ...

What potential risks come with allowing unvalidated user-inputted text in Django?

Recently, a colleague of mine introduced a vulnerability to a page in development. This vulnerability allows a user to input 30 characters of unescaped code that will be executed with the |safe filter. This means that HTML unsafe characters (<, >, &a ...

Unable to locate the specified view within AngularJS framework

<!doctype html> <html lang="en" ng-app="phonecatApp"> <head> <script src="/js/angular-1.5.2/angular.js"></script> <script src="/js/angular-1.5.2/angular-route.js"></script> <script src="/js/app.js">< ...

Exploring the possibilities of combining Selenium Code and F# with Canopy

Currently, I am facing the challenge of incorporating Selenium code into my F# project while utilizing the canopy wrapper. Canopy relies on Selenium for certain functions. My main struggle lies in converting Selenium code from Java or C# to fit within an ...