return this.text.length;
};
TextCell.prototype.draw = function(width, height) {
var result = [];
for (var i = 0; i < height; i++) {
var line = this.text[i] || "";
result.push(line + repeat(" ", width - line.length));
}
return result;
};
В коде используется вспомогательная функция repeat
draw использует её для создания отступов в ячейках, чтобы они все были необходимой длины.Давайте нарисуем для опыта шахматную доску 5×5.
var rows = [];
for (var i = 0; i < 5; i++) {
var row = [];
for (var j = 0; j < 5; j++) {
if ((j + i) % 2 == 0)
row.push(new TextCell("##"));
else
row.push(new TextCell(" "));
}
rows.push(row);
}
console.log(drawTable(rows));
// → ## ## ##
// ## ##
// ## ## ##
// ## ##
// ## ## ##
Работает! Но так как у всех ячеек один размер, код форматирования таблицы не делает ничего интересного.
Исходные данные для таблицы гор, которую мы строим, содержатся в переменной MOUNTAINS
Нам нужно выделить верхнюю строку, содержащую названия столбцов, при помощи подчёркивания. Никаких проблем – мы просто создаём тип ячейки, который этим занимается.
function UnderlinedCell(inner) {
this.inner = inner;
};
UnderlinedCell.prototype.minWidth = function() {
return this.inner.minWidth();
};
UnderlinedCell.prototype.minHeight = function() {
return this.inner.minHeight() + 1;
};
UnderlinedCell.prototype.draw = function(width, height) {
return this.inner.draw(width, height - 1)
.concat([repeat("-", width)]);
};
Подчёркнутая ячейка содержит другую ячейку. Она возвращает такие же размеры, как и у ячейки inner
minWidth и minHeight), но добавляет единичку к высоте из-за места, занятого чёрточками.Рисовать её просто – мы берём содержимое ячейки inner
Теперь, имея основной движок, мы можем написать функцию, строящую сетку ячеек из нашего набора данных.
function dataTable(data) {
var keys = Object.keys(data[0]);
var headers = keys.map(function(name) {
return new UnderlinedCell(new TextCell(name));
});
var body = data.map(function(row) {
return keys.map(function(name) {
return new TextCell(String(row[name]));
});
});
return [headers].concat(body);
}
console.log(drawTable(dataTable(MOUNTAINS)));
// → name height country
// ------------ ------ -------------
// Kilimanjaro 5895 Tanzania
// … и так далее
Стандартная функция Object.keys
map по массиву keys, чтобы гарантировать одинаковый порядок ячеек в каждой из строк.Итоговая таблица напоминает таблицу из примера, только вот числа не выровнены по правому краю. Мы займёмся этим чуть позже.
Геттеры и сеттеры
При создании интерфейса можно ввести свойства, не являющиеся методами. Мы могли бы определить minHeight
minWidth как переменные для хранения чисел. Но это потребовало бы от нас написать код вычисления их значений в конструкторе, что плохо, поскольку эти операции не связаны напрямую с конструированием объекта. Это может аукнуться, когда, например, внутренняя ячейка подчёркнутой ячейки изменяется – в этот момент размер подчеркивания тоже должен измениться.