Permalink
Browse files

ability to create cross tables

i.e. tables with headers in both the first row and first column
  • Loading branch information...
1 parent da91634 commit 5c18988a4af3e1dd23bc56832d3eb30e663d369d @sonnym sonnym committed Jul 27, 2012
Showing with 81 additions and 14 deletions.
  1. +17 −0 README.md
  2. +6 −0 examples/revs.js
  3. +37 −14 lib/cli-table/index.js
  4. +21 −0 test/index.test.js
View
@@ -56,6 +56,23 @@ table.push(
console.log(table.toString());
```
+### Cross Tables
+Cross tables are very similar to vertical tables, with two key differences:
+
+1. They require a `head` setting when instantiated that has an empty string as the first header
+2. The individual rows take the general form of { "Header": ["Row", "Values"] }
+
+```javascript
+var Table = require('cli-table');
+var table = new Table({ head: ["", "Top Header 1", "Top Header 2"] });
+
+table.push(
+ { 'Left Header 1': ['Value Row 1 Col 1', 'Value Row 1 Col 2'] }
+ , { 'Left Header 2': ['Value Row 2 Col 1', 'Value Row 2 Col 2'] }
+);
+
+console.log(table.toString());
+```
## Running tests
View
@@ -51,3 +51,9 @@ vertical_table.push({ "Some Key": "Some Value"},
);
console.log(vertical_table.toString());
+
+/* cross */
+var cross_table = new Table({ head: ["", "Header #1", "Header #2"] });
+cross_table.push({ "Header #3": ["Value 1", "Value 2"] },
+ { "Header #4": ["Value 3", "Value 4"] });
+console.log(cross_table.toString());
View
@@ -89,16 +89,23 @@ Table.prototype.toString = function (){
if (!colWidths.length){
this.slice(0).concat([head]).forEach(function(cells){
- if (cells.length) {
- cells.forEach(function(cell, i){
- colWidths[i] = Math.max(colWidths[i] || 0, get_width(cell) || 0);
- });
+ // horizontal (arrays)
+ if (typeof cells === 'object' && cells.length) {
+ extractColumnWidths(cells);
+
+ // vertical (objects)
} else {
var header_cell = Object.keys(cells)[0]
, value_cell = cells[header_cell];
colWidths[0] = Math.max(colWidths[0] || 0, get_width(header_cell) || 0);
- colWidths[1] = Math.max(colWidths[1] || 0, get_width(value_cell) || 0);
+
+ // cross (objects w/ array values)
+ if (typeof value_cell === 'object' && value_cell.length) {
+ extractColumnWidths(value_cell, 1);
+ } else {
+ colWidths[1] = Math.max(colWidths[1] || 0, get_width(value_cell) || 0);
+ }
}
});
};
@@ -108,6 +115,13 @@ Table.prototype.toString = function (){
return a + b
})) + colWidths.length + 1;
+ function extractColumnWidths(arr, offset) {
+ var offset = offset || 0;
+ arr.forEach(function(cell, i){
+ colWidths[i + offset] = Math.max(colWidths[i + offset] || 0, get_width(cell) || 0);
+ });
+ };
+
function get_width(obj) {
return width = typeof obj == 'object' && obj.width != undefined
? obj.width
@@ -140,6 +154,16 @@ Table.prototype.toString = function (){
ret += "\n";
};
+ function arrayToCells(arr, start_column) {
+ var ret = "", start_column = start_column || 0;
+
+ arr.forEach(function(cell, i){
+ ret += string(cell, start_column + i);
+ ret += chars.right;
+ });
+ return ret;
+ };
+
// renders a string, by padding it or truncating it
function string (str, index){
var str = String(typeof str == 'object' && str.text ? str.text : str)
@@ -194,18 +218,15 @@ Table.prototype.toString = function (){
}
}
+ // empty row
if (cells.hasOwnProperty("length") && !cells.length)
return
+ // horizontal
if (cells.hasOwnProperty("length")) {
- ret += chars.left;
+ ret += chars.left + arrayToCells(cells) + "\n";
- cells.forEach(function(cell, i){
- ret += string(cell, i);
- ret += chars.right;
- });
-
- ret += "\n";
+ // vertical
} else if (typeof cells === 'object') {
var key = Object.keys(cells)[0]
, value = cells[key];
@@ -216,8 +237,10 @@ Table.prototype.toString = function (){
});
}
- ret += chars.left + string(key, 0) + chars.right +
- string(value, 1) + chars.right + "\n"
+ // if value is not String, assume Array for cross table
+ var row = (typeof value === 'string') ? string(value, 1) + chars.right : arrayToCells(value, 1);
+
+ ret += chars.left + string(key, 0) + chars.right + row + "\n";
}
});
View
@@ -66,5 +66,26 @@ module.exports = {
];
table.toString().should.eql(expected.join("\n"));
+ },
+
+ 'test cross table output': function() {
+ var table = new Table({ head: ["", "Header 1", "Header 2"], style: {} }); // clear styles to prevent color output
+
+ table.push(
+ {"Header 3": ['v0.1', 'Testing something cool'] }
+ , {"Header 4": ['v0.1', 'Testing something cool'] }
+ );
+
+ var expected = [
+ '┌────────┬────────┬──────────────────────┐'
+ , '│ │Header 1│Header 2 │'
+ , '├────────┼────────┼──────────────────────┤'
+ , '│Header 3│v0.1 │Testing something cool│'
+ , '├────────┼────────┼──────────────────────┤'
+ , '│Header 4│v0.1 │Testing something cool│'
+ , '└────────┴────────┴──────────────────────┘'
+ ];
+
+ table.toString().should.eql(expected.join("\n"));
}
};

0 comments on commit 5c18988

Please sign in to comment.