Created
September 19, 2010 18:46
-
-
Save guybrush/587002 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Table.js | |
* Copyright(c) 2010 TJ Holowaychuk <[email protected]> | |
* MIT Licensed | |
*/ | |
/** | |
* http://github.com/Marak/table.js/blob/master/lib/table.js | |
*/ | |
/** | |
* Module dependencies. | |
*/ | |
var sys = require('sys'); | |
/** | |
* Initialize a Table. | |
* | |
* @api public | |
*/ | |
var Table = exports = module.exports = function Table(){ | |
this.align = {}; | |
this.chars = '+-|'; | |
}; | |
sys.inherits(Table, Array); | |
/** | |
* Add a `row` of cells. | |
* | |
* @param {Array} row | |
* @return {Row} | |
* @api public | |
*/ | |
Table.prototype.addRow = function(row){ | |
this.push(row = new Row(row)); | |
return row; | |
}; | |
/** | |
* Add a head `row` of cells. | |
* | |
* @param {Array} row | |
* @return {Head} | |
* @api public | |
*/ | |
Table.prototype.addHead = function(row){ | |
this.push(row = new Head(row)); | |
return row; | |
}; | |
/** | |
* Align `col` to `align`. | |
* | |
* @param {Number} col | |
* @param {Number|String} align | |
* @api public | |
*/ | |
Table.prototype.alignColumn = function(col, align){ | |
this.align[col] = alignmentString(align); | |
}; | |
/** | |
* Convert table to a string. | |
* | |
* @return {String} | |
* @api public | |
*/ | |
Table.prototype.toString = function(){ | |
var sep = this.separator(); | |
return sep + '\n' | |
+ this.map(function(row){ | |
return this.chars[2] | |
+ row.toString(this) | |
+ ' ' | |
+ this.chars[2] | |
+ (row instanceof Head ? '\n' + sep : ''); | |
}, this).join('\n') + '\n' | |
+ sep; | |
}; | |
/** | |
* Return table seperator. | |
* | |
* @return {String} | |
* @api private | |
*/ | |
Table.prototype.separator = function(){ | |
return this.chars[0] | |
+ Array(this.rowWidth()).join(this.chars[1]) | |
+ this.chars[0]; | |
}; | |
/** | |
* Return largest row width. | |
* | |
* @return {number} | |
* @api private | |
*/ | |
Table.prototype.rowWidth = function(){ | |
var self = this; | |
return this.reduce(function(width, row){ | |
var n = row.width(self); | |
return n > width ? n : width; | |
}, 0) + 2; | |
}; | |
/** | |
* Return largest cell width in the given `col`. | |
* | |
* @param {Number} col | |
* @return {Number} | |
* @api private | |
*/ | |
Table.prototype.largestCellWidth = function(col){ | |
return this.reduce(function(width, row){ | |
var n = row[col].str.length; | |
return n > width ? n : width; | |
}, 0); | |
}; | |
// Row | |
/** | |
* Initialize a new row with the given `cells`. | |
* | |
* @param {Array} cells | |
* @api public | |
*/ | |
var Row = exports.Row = function Row(cells){ | |
if (cells) { | |
for (var i = 0, len = cells.length; i < len; ++i) { | |
this.addCell(cells[i]); | |
} | |
} | |
}; | |
sys.inherits(Row, Array); | |
/** | |
* Add the given `cell` with optional `align`ment. | |
* | |
* @param {Cell|String} cell | |
* @param {Number|Object} align | |
* @return {Cell} | |
* @api public | |
*/ | |
Row.prototype.addCell = function(cell, align){ | |
if (cell instanceof Cell) { | |
this.push(cell); | |
} else { | |
align = typeof align === 'object' | |
? align.align | |
: align; | |
this.push(cell = new Cell(cell, align)); | |
} | |
return cell; | |
}; | |
/** | |
* Return row width. | |
* | |
* @param {Table} table | |
* @return {Number} | |
* @api private | |
*/ | |
Row.prototype.width = function(table){ | |
return this.reduce(function(sum, cell, i){ | |
return sum + table.largestCellWidth(i) + 2; | |
}, this.length - 1); | |
}; | |
/** | |
* Convert row to a string. | |
* | |
* @param {Table} table | |
* @return {String} | |
* @api private | |
*/ | |
Row.prototype.toString = function(table){ | |
return this.map(function(cell, i){ | |
var align = table.align[i] === undefined | |
? -1 | |
: table.align[i]; | |
return cell.toString(table.largestCellWidth(i), align); | |
}).join(table.chars[2]); | |
}; | |
// Head | |
/** | |
* Initialize a new head with the given `cells`. | |
* | |
* @param {Array} cells | |
* @api public | |
*/ | |
var Head = exports.Head = function Head(cells){ | |
Row.call(this, cells); | |
}; | |
sys.inherits(Head, Row); | |
// Cell | |
/** | |
* Initialize new cell with the given `str` and `align`ment. | |
* | |
* @param {String} str | |
* @param {Number|String} align | |
* @api public | |
*/ | |
var Cell = exports.Cell = function Cell(str, align){ | |
this.str = str; | |
this.align = align === undefined | |
? align | |
: alignmentString(align); | |
}; | |
/** | |
* Convert cell to a string with the given `width`, and `align`ment. | |
* | |
* @param {Number} width | |
* @param {Number} align | |
* @return {String} | |
* @api private | |
*/ | |
Cell.prototype.toString = function(width, align){ | |
var len = this.str.length, | |
align = typeof this.align === 'number' | |
? this.align | |
: align; | |
if (len < width) { | |
var pad = width - len; | |
switch (align) { | |
case 0: | |
pad = pad / 2; | |
while (pad--) { | |
this.str = ' ' + this.str + ' '; | |
} | |
break; | |
case 1: | |
while (pad--) { | |
this.str = ' ' + this.str; | |
} | |
break; | |
default: | |
while (pad--) { | |
this.str += ' '; | |
} | |
} | |
} | |
return ' ' + this.str + ' '; | |
}; | |
// Utilities | |
/** | |
* Accept an `align`ment string such as 'left', 'right' | |
* or 'center'. When a `Number` is passed it is returned. | |
* | |
* @param {String|Number} align | |
* @return {Number} | |
* @api private | |
*/ | |
function alignmentString(align) { | |
switch (align) { | |
case 'right': | |
return 1; | |
case 'left': | |
return -1; | |
case 'center': | |
return 0; | |
default: | |
return align; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment