Сегодня у меня начался второй проект на хекслете В нем нужно написать консольное приложение, которое будет сравнивать содержание двух файлов и показывать, чем они отличаются.
Скорее всего, проект потребует много усилий и времени, поэтому работу над моим собственным проектом с графиками придется на неделю приостановить.
Когда одновременно с систематическим обучением пытаешься сделать какой-то проект самостоятельно, получается интересный эффект: буквально после каждого урока появляется желание переписать уже сделанное по-новому. После курса «прототипы» захотелось сделать абстракцию данных при помощи классов, а не простых объектов, как решил изначально. После «обработки ошибок» понял, что нужно как-то изящно решать вопрос, когда информацию из файла на входе не получается отрендерить из-за неправильного формата. В результате так все время и разрываешься между добавлением новых фич и рефакторингом старых.
После второго проекта тоже наверняка будет что применить нового. Как минимум нужно будет добавить автоматическое тестирование, которому учат в проекте, и которого у меня до сих пор не было.
Решил попробовать поучаствовать в хекслетовской программе наставничества. Для попадания в нее нужно вести блог в вебе, мой канал в телеграмчике не подошел. Пришлось по-быстрому искать способ перенести его на сайт.
Решил для этого использовать какой-нибудь генератор статических сайтов. Это такая программа, которая берет на входе папку с текстовыми файлами, и превращает ее в набор хтмл-страниц, готовых к размещению на сервере. Процесс добавления постов выглядит так:
Таких генераторов существует огромное количество на любом языке. Вот список в порядке популярности: staticgen.com
Сначала хотел взять что-нибудь на джаваскрипте и нагуглил gatsby. На сайте пишут, что он предназначен для реакта, про который я ничего не знаю. Поэтому этот вариант сразу отбросил.
Потом попробовал Frog, написанный на ракете, который я тоже изучаю. К сожалению, после добавления постов он отказывался генерировать сайт заново. Разбираться в причинах было лень, поэтому фрог тоже отпал.
В итоге взял самый популярный и банальный вариант — jekyll. Установил все по гайду хекслета. Немного поправил шаблон на свой вкус и задеплоил результат на digitalocean.com.
Пока не разобрался во всем, что хотел сделать. Например, не понял, как автоматически сделать страницы с тегами и поменять подсветку синтаксиса в отрывках с кодом.
До этого данные, по которым нужно рисовать диаграмму, хранились в исходом коде в виде джаваскрипт-объектов. Теперь приложение может использовать данные извне в виде специального файла в формате .json
, описывающего диаграмму.
Такой файл состоит из объекта с двумя значениями. В одном хранится заголовок графика, во втором — список из событий. Каждое событие, в свою очедерь, тоже объект с тремя уже знакомыми значениями. Выглядит файл примерно так:
{
"chartName": "Ученые",
"events": [
{
"name": "Галилей",
"start": "1564-02-15",
"end": "1642-01-08"
},
{
"name": "Ньютон",
"start": "1642-12-25",
"end": "1727-03-20"
}
]
}
Приложение преобразует информацию по схеме:
Файл с информацией → Представление данных в виде жс-объектов → Страница с отрендеренным графиком в ДОМ
Вопрос с генерацией графика в виде ДОМ-объектов на основе данных в жс уже был решен. Чтобы получить данные из файла пришлось разобраться, во-первых, как загрузить файл; во-вторых, как этот файл распарсить. Для первого в браузере есть объект FileReader, для второго — функция JSON.parse
Еще поправил механизм рисования подписей с датами. Чтобы они не наплывали друг на друга, алгоритм смотрит, сколько подписей получится вместить, и соответственно выбирает шаг сетки от одного дня до столетия.
Добавил генерацию временной сетки. Пока что отмечены первые даты каждого месяца, но по науке нужно будет высчитывать период исходя из дат и ширины графика.
Решил для вдохновения глянуть, какие есть на гитхабе проекты на жс для работы с свг. А там почти что фотошоп в браузерe.
Есть куда стремиться, в общем.
Параллельно с работой над своим проектиком продолжаю проходить хекслетовские курсы. Сейчас прохожу «прототипы».
Что прикольно, там в качестве практики нужно написать библиотеку для генерации хтмл-кода, что очень напоминает, то, что я пытаюсь делать в своем проекте. Уже на середине курса становится понятно, как мои решения можно улучшить.
Поначалу курсы почти полностью фокусировались на самом программировании, не затрагивая сильно особенности джаваскрипта. А сейчас все чаще приходится сталкиваться с этими особенностями, и некоторые из них, надо признаться, довольно неожиданные.
Например, функция в джаваскрипте — это объект. В этом объекте есть свойство valueOf
. Функция в этом свойстве автоматически вызвается каждый раз, когда нужно получить значение объекта. Так вот, никто не запрещает взять функцию и записать в это свойство что угодно:
const f = () => 'hello';
f.valueOf = () => 10;
console.log(f + 1); // 11
На этом факте построено задание, на котором я застрял пока дольше всего: написать функцию, которую можно бесконечно применять к любому количеству чисел, а на выходе будет функция, всегда равная сумме этих чисел.
magic(1) == 1; // true
magic(1, 2)(3) == 6; // true
magic(1, 2)(3)(4, 5) == 15; // true
Написал функцию, преобразующую данные в столбики на диаграмме. Объекты с датами содержат количество милисекунд, поэтому пришлось вспомнить уроки алгебры из четвертого класса, чтобы преобразовать милисекунды в пиксели, не исказив масштабы. Теперь можно свободно задавать любую ширину для графика, а столбики будут соответствено подстраиваться.
До этого весь прототип моего проекта состоял из одного хтмл файла, и одного подключенного к нему жс файла. Решил разбить код на отдельные модули, чтобы функции для отображения событий лежали в одном файле, функции для создания ДОМ-элементов в другом, всякие вспомогательные функции — в третьем.
Оказалось, что бразуер не умеет сам подгружать зависимости из других файлов. Можно пользоваться только тем, что подключено к хтмл тегом
Поэтому если хочешь при разработке пользоваться импортами, то придется использовать сборщик модулей. Это такая программа, которая получив джавскрипт-файл, проходит по всем его зависимостям и собирает все содержимое в один файл. Его в итоге и подключаешь к странице.
Чтобы не заморачиватся с выбором конкретного сборщика, взял себе первый попавшийся — вебпак. Разобраться с его настройкой помогла статья на хабре.
С рисованием стобиков случайной длины в свг разобрался. Теперь можно вспомнить, что столбики должны отражать некие данные. А для этого данные нужно представить в программе с помощью каких-то объектов.
График состоит из нескольких отдельных событий. Чтобы описать каждое из них, нужно три значения: дата начала, дата конца и название.
Название события, ясное дело, нужно хранить в строке. Для дат жс предлагет использовать специально предназначенный тип объекта Date.
Хранить все три значения для одного события буду при помощи объектов. Это такой тип данных в джаваскрипте, представляющий собой набор ключей и соответствующих им значений. Создание события будет выглядеть так:
const event = {
name: 'ЧМ 2018',
start: new Date('2018-06-14'),
end: new Date('2018-07-15')
}
Получить отдельное значение из объекта можно по ключу через точку или квадратные скобки:
event.name // ЧМ 2018
event['start'] // 2018-06-14T00:00:00.000Z
Диаграмма тогда будет представленна массивом из нескольких таких объектов. Следующая задача — написать функцию, которая получает массив с событиями и возвращает ДОМ-элемент, отображающий диаграмму с этими событиями.
Разобрался как создавать свг-элементы в жс.
Когда браузер получает страницу в хтмл, он пытается понять, что в ней написно и построить у себя внутри древовидную структуру, соотвутствующую исходному хтмл. А потом эту структуру как-то отображает. Нам, программистам, браузер выдает набор функций для манипулирования этой структурой: поиска в ней объектов, создания и добавления новых, удаления старых, и т. п. Такой порядок вещей называется document object model, или DOM для краткости.
В моем случае диаграмма состоит из следующих тегов: прямоугольника, отображающего продолжительность события, и текста с названием события. Текст и прямоугольник одного события сгруппированы вместе тегом g, а группы эти все вложены в тег svg.
<svg id="chart">
<g>
<text>Событие</text>
<rect width="400" height="20" x="100"/>
</g>
</svg>
Благодаря ДОМу можно сделать все то же самое, но на джаваскрипте:
// создаем полоску
let bar = document.createElementNS("http://www.w3.org/2000/svg", "rect");
// снабжаем ее подходящими аттрибутами
bar.setAttribute('width', 400);
bar.setAttribute('height', '20');
bar.setAttribute('x', 100);
// создаем подпись
let text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.textContent = "Событие";
// создаем группу
let event = document.createElementNS("http://www.w3.org/2000/svg", "g");
// кладем полоску с подписью внутрь
event.appendChild(text);
event.appendChild(bar);
// находим на странице тег svg
let svg = document.getElementsByTagName('svg')[0];
// добавляем внутрь созданное событие
svg.appendChild(event);
Выглядит довольно громоздко и неудобно. Зато можно написать разнообразные функции для генерации элементов и автоматизировать таким образом их создание. Я так и сделал, теперь на странице с графиком автоматически создается 10 событий, каждый раз новых.