Выразительный JavaScript (Хавербеке) - страница 64

Функция >drawRow сперва превращает объекты ячеек строки в блоки, которые являются массивами строк, представляющими содержимое ячеек, разделённые линиями. Одна ячейка, содержащая число 3776, может быть представлена массивом из одного элемента >["3776"], а подчёркнутая ячейка может занять две строки и выглядеть как массив >["name", "----"].

Блоки для строки, у которых одинаковая высота, должны выводиться рядом друг с другом. Второй вызов >map в >drawRow строит этот результат построчно, начиная с ячеек самого левого блока, и для каждой из них дополняя строку до полной ширины таблицы. Полученные строки затем соединяются через символ новой строки, создавая целый ряд, который и возвращает >drawRow.

Функция >drawLine выцепляет строки, которые должны располагаться рядом друг с другом, из массива блоков и соединяет их через пробел, чтобы создать промежуток в один символ между столбцами таблицы.

Давайте напишем конструктор для ячеек, содержащих текст, который предоставляет интерфейс для ячеек. Он разбивает строчку в массив строк при помощи метода >split, который режет строчку каждый раз, когда в ней встречается его аргумент, и возвращает массив полученных кусочков. Метод >minWidth находит максимальную ширину строки в массиве.

>function repeat(string, times) {

>  var result = "";

>  for (var i = 0; i < times; i++)

>    result += string;

>  return result;

>}


>function TextCell(text) {

>  this.text = text.split("\n");

>}

>TextCell.prototype.minWidth = function() {

>  return this.text.reduce(function(width, line) {

>    return Math.max(width, line.length);

>  }, 0);

>};

>TextCell.prototype.minHeight = function() {

>  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));

>// → ##    ##    ##

>//      ##    ##

>//   ##    ##    ##

>//      ##    ##

>//   ##    ##    ##

Работает! Но так как у всех ячеек один размер, код форматирования таблицы не делает ничего интересного.