Установите зависимости проекта:
npm install
После этого вам будут доступны следующие команды:
npm run lint
- проверка качества вашего кода утилитой ESLintnpm run test [test-file]
- запустить unit-тесты из указанного файла в консоли, например:npm run test test/spec/task-1.spec.js
npm run test
- запуск всех unit-тестов в консолиnpm run test:watch [test-file]
,npm run test:watch
- запуск одного или всех unit-тестов в консоли, с автоматическим перезапуском при изменении исходного кода. Например:npm run test:watch test/spec/task-1.spec.js
Кроме того, для выполнения заданий связанных с DOM-деревом и событиями вам нужно тестировать ваш код в браузере. Для этого есть команда
npm run start
- открывает в браузере страничку с необходимой для вашего кода разметкой. При изменении кода страничка автоматически перезагружается.
Декофеинизированная команда марсохода из второй практической работы решила проблемы с поступлением марсоходу бессмысленных команд и с порядком их получения. Заодно они решили сменить API управления марсоходом и сделать его в ООП-стиле.
Напишите класс Rover, который имеет следующий публичный интерфейс:
Метод | Параметры | Описание | Дополнительно |
---|---|---|---|
constructor |
|
Конструктор. Nuff said. |
Выбрасывает исключение TypeError если переданы не целочисленные координаты,
или несуществующее направление движения
|
left |
- | Поворот марсохода налево | - |
right |
- | Поворот марсохода направо | - |
move |
n - (целочисленное) число шагов |
Движение на n шагов вперед. Может быть отрицательным. |
Выбрасывает исключение TypeError если передано не целочисленное число шагов. |
getPosition() |
- | Возвращает текущие координаты марсохода | Формат: { x: 5, y: 6 } |
getDirection() |
- | Возвращает текущее направление | Возвращает одно из значений NORTH, EAST, SOUTH, WEST |
Кроме того, методы left
, right
, move
должны быть "chainable", т.е. должны иметь возможность вызываться цепочкой:
const r = new Rover(0, 0, NORTH);
r.left().move(5).right().right().move(1);
r.getPosition(); // { x: -4, y: 0 }
r.getDirection(); // EAST
У стандартного класса Set
есть фатальный недостаток.
Ему недостаёт нескольких полезных методов.
union(s)
- (объединение множеств) создать новое множество, куда входят все объекты из множестваthis
и множестваs
intersection(s)
- (пересечение множеств) создать новое множество, куда входят только объекты, принадлежащие иthis
, и множествуs
difference(s)
- (разность множеств) создать новое множество, куда входят объекты, принадлежащиеthis
, но не принадлежащие множествуs
symmetricDifference(s)
- (симметрическая разность) создать новое множество, куда входят объекты принадлежащие илиthis
, или множествуs
, но не обоим множествам одновременноisSuperset(s)
- функция, возвращающаяtrue
, если множествоs
вложено в множествоthis
isSubset(s)
- функция, возвращающаяtrue
, если множествоthis
вложено в множествоs
Напишите класс EnhancedSet
, который наследуется от Set
, и расширяет его этими шестью методами.
Представим что на дворе 2008 год, и попробуем попрограммировать в стиле jquery.
Дана HTML таблица, каждая строка которой представлет одну запись из базы данных.
Первая ячейка каждой строки - порядковый номер в таблице
Некоторые ячейки содержат аттрибут data-field-name
, в котором хранится имя поля из базы данных, которое отображается в этой ячейке.
Например:
<tr>
<td>1</td>
<td data-field-name="album">Fly on the Wall</td>
<td data-field-name="performer">AC/DC</td>
<td data-field-name="genre">hard rock</td>
<td data-field-name="year">1985</td>
<td><a href="http://www.wikidata.org/entity/Q901854">Link</a></td>
</tr>
Напишите функцию, filterTable
, которая будет фильтровать строки таблицы по заданному условию.
Она получает два аргумента: DOM-элемент с телом таблицы, и объект с фильтрами в виде <имя поля>: значение
Например:
{
year: "1980",
genre: "rock"
}
Этот фильтр должен оставить только те строки таблицы, в поле year
которых содержится "1980", а поле genre
содержит слово "rock" - i.e. "rock", "punk rock", "exotic instrumental post-rockabilly".
Функция filterTable
должна:
- Прятать не соответствующие фильтрам строки добавляя к соответствующему тегу
<tr>
классd-none
- Сохранять последовательную нумерацию строк, перезаписывая числа в первых ячейках строк
- Сохранять "зебровую" раскраску таблицы - четные строки должны иметь класс
table-row-even
, у нечетных этот класс должен отсутствовать. - Быть независимой от порядка ячеек и имен полей в них, т.е. работать для любой таблицы с любыми именами полей в фильтруемых ячейках.
PS: Закройте глаза представьте что вам нужно было бы еще реализовать сортировку таблицы по значениям полей, обменивая строки внутри таблицы местами. Откройте глаза и с облегчением выдохните: вам не нужно этого делать. Возможно, вы заметили что такой jquery-style код трудно читать, поддерживать и изменять.
Представим что на дворе 2009 год, мы осознали что охапка функций в глобальной области видимости - это прошлый век и решили использовать самописный-наивный-прото-компонентный подход.
Напишите класс, который реализует функционал корзины покупок на сайте. В корзине есть следующие элементы:
- Сообщение о том что список покупок пуст. Оно должно отображаться только в случае если пользователь не добавил ни одного товара.
- Список товаров в корзине. Каждый раз когда пользователь нажимает на кнопку "Buy", товар добавляется в этот список. Если такой товар в списке уже есть, то количество этого товара в корзине увеличивается на 1, и изменяется общая цена для этого товара. У каждого товара есть кнопка "Remove", которая удаляет его из корзины (удаляются все единицы этого товара).
- Общая сумма цен всех товаров в корзине. Изменяется каждый раз когда мы добавляем или удаляем товар из корзины.
- Кнопка "Remove All", клик по которой полностью очищает корзину.
Некоторые методы этого класса уже написаны, некоторые реализованы частично, и у всех методов заботливо прописана документация в формате JSDoc, из которой вы можете узнать назначение метода, его параметры и возвращаемое значение. Вам остается всего лишь заполнить оставшиеся лакуны!
Прятать элементы можно с помощью класса d-none
.
Храните всю вспомогательную информацию только в сберегательных кассах data-атрибутах HTML-элементов:
например, чтобы проверить существует ли в корзине товар с заданным id
, нужно проверить существование
в корзине HTML-элемента с соответствующим data-item-id
.
Рекомендуемый порядок действий:
- Начните с метода
isCartEmpty
- Реализуйте показ/скрытие сообщения о пустой корзине и кнопки "Remove All" в методах
updateNoItemsMessage
иupdateRemoveAllButton
. - Реализуйте проверку
isItemInCart
- Реализуйте метод
incrementItem
, увеличивающий количество товара, и общую сумму товара, если он уже добавлен в корзину. Не забудьте при этом обновить атрибутыdata-item-qty
иdata-item-total
, они вам пригодятся при последующих добавлениях товара и подсчете общей суммы всех товаров. - Кстати, вот теперь и реализуйте подсчет общей суммы всех товаров в методе
getTotalSum
и обновление этого числа в методеupdateTotal
. - В методе
addEventListeners
добавьте обработчик клика на кнопку "Remove All", который должен вызывать методremoveAll
- Добавьте обработчики клика на кнопки "Remove" каждого товара в корзине, которые вызывают метод
removeItem
с соответствующимid
. У вас есть два варианта решения: добавлять обработчик каждый раз когда добавляется новый товар в корзину, или добавить один обработчик на всех в методеaddEventListeners
, используя делегацию обработки событий. - Реализуйте методы
removeItem
иremoveAll
.
Представьте что вам нужно дополнить ваш класс: нужно добавить общее число купленных товаров внизу списка, по аналогии с Total Sum. Прикиньте число мест в вашем классе, в которые придется внести изменения.