Неделя 5 · JS30 Widgets

🧭 ← 02c — Shelter Part 3 — JavaScript · ← Roadmap · Следующая → Podcast

🎯 Что строим

Два виджета из шести предложенных — homage курсу JavaScript30 Wes Bos. Каждый виджет — standalone статика на чистом vanilla JS + Web APIs. Три стадии на виджет: воспроизведение оригинала → обязательная доп. фича → опциональные улучшения.

Особенности этой задачи:

  • Общий курсовой репо (не свой!) — куратор даёт collaborator-доступ, каждый студент в своей подпапке students/<github-login>/<task-slug>/
  • Netlify Preview Bot автоматически деплоит превью на PR — именно эту ссылку сабмитишь в rs app
  • Self-evaluation в console — на загрузке страница печатает в console.log список зачтённых пунктов с баллами

📄 Полное задание на GitHub →

🏷 Required Skills (как заявлено в задании)

HTML5 · CSS3 · vanilla JS (ES2020+) · DOM API · event handling · CSS animations · Web Audio API · Canvas API · HTMLVideoElement / HTMLAudioElement · Git branching · PR workflow · code review · Netlify Preview

🚫 Запреты и штрафы

Что нельзя Штраф
🔴 jQuery, React, Vue, Angular, Lodash и любые JS-фреймворки/библиотеки -65 (виджет обнуляется целиком)
🔴 Прямой copy-paste кода оригинала Wes Bos / других студентов вплоть до -65
🟡 Minified / obfuscated JS в коммите -10 за виджет
🟡 Один коммит-дамп вместо реальной истории разработки -10 за виджет
🟡 PR не открыт против main курсового репо / нет Netlify preview -10 за виджет
🟡 Нет self-evaluation в browser console -5 за виджет
🟡 Major bug — функционал ломается после манипуляций или throws в консоль -15 за баг
🟡 Minor bug — визуал/state косячит без ошибок в консоли -5 за баг

💡 Разрешено: Bootstrap и любые CSS-фреймворки, Sass/Less/PostCSS препроцессоры. Перепечатывать код с видео своими руками тоже норм — суть в том, что ты понял каждую строку.


⛰ Compound из предыдущих задач

К этой неделе у тебя уже есть из Shelter P3:

  • DOM-манипуляцииquerySelector, classList, dataset (Photofilter, Drum Kit)
  • СобытияaddEventListener, делегирование, event.target (все виджеты)
  • Анимации CSStransition, transform, @keyframes (Clock, Drum Kit, Mole)
  • Модульная архитектура — раздели UI / state / data layer

Из Slider:

  • transform: translate и плавные transition — Vertical Slider, стрелки Clock

🎯 Рекомендация по выбору: для первого захода в JS30 бери Drum Kit + JS Clock — обе короткие (10-20 мин видео), без Canvas и сложного state. Если уверен в DOM/событиях после Shelter — Photofilter + Custom Video Player (там работа с CSS variables и Media API). Whack-A-Mole — самый трудоёмкий из-за Canvas/таймингов, бери только если хочется challenge.


📚 Что изучить (по порядку)

⚠️ Идти строго по порядку. Виджеты разные, но фундамент (DOM/события/Web API base) общий.

📥 Что должен знать ДО старта

Это пятая задача bootcamp. К этому моменту у тебя должны быть:


1 · Compound из Shelter P3: DOM + события (фундамент)

Зачем: все 6 виджетов на 80% состоят из «слушай событие → меняй DOM/CSS». Без уверенного DOM ты завязнешь даже в Drum Kit.

Self-check: в чём разница event.target и event.currentTarget при делегировании? Когда вешать слушатель — на DOMContentLoaded или сразу в <script defer>?


2 · CSS Variables (нужно для Photofilter, опционально для всех)

Зачем: Photofilter полностью построен на чтении <input type="range"> → запись в CSS custom property → filter: применяется автоматически. Это паттерн «JS пишет переменную — CSS реагирует».

Self-check: как из JS прочитать значение CSS custom property --base? Чем element.style.setProperty('--x', val) отличается от element.style.x = val?


3 · Web APIs — обзор и навигация

Зачем: «Web API» — это всё, что браузер даёт сверх ECMAScript. На JS30 ты пощупаешь сразу несколько разных API. Понимать общую карту полезно, чтобы не путать HTMLAudioElement (DOM-обёртка тега) с Web Audio API (графовый процессор звука) — это разные штуки.

Self-check: что лучше для анимации стрелки часов — setInterval(1000) или requestAnimationFrame? Почему?


4 · HTMLAudioElement + Web Audio API (Drum Kit)

Зачем: Drum Kit играет звук на клавишу. На «по-быстрому» хватает <audio>.play(), но обязательная доп. фича (см. js30-1.md) обычно требует контроля над звуком — а это уже Web Audio API.

Self-check: почему повторное нажатие на ту же клавишу не воспроизводит звук с начала? (подсказка: audio.currentTime = 0). Чем event.key отличается от event.code для клавиш KeyA?


5 · HTMLVideoElement (Custom Video Player)

Зачем: Custom Video Player полностью заменяет встроенные controls. Тебе нужен ручной play/pause, scrubber (seek-бар), volume slider, playback rate, fullscreen.

Self-check: какое событие даёт надёжный момент «видео реально стартовало» — play или playing? Как из currentTime (число секунд) получить строку "02:35"?


6 · Date API + CSS transitions (JS Clock)

Зачем: Clock — самый минималистичный виджет: setInterval + Date + transform: rotate. Главная ловушка — «прыжок» стрелки при переходе с 59→0 секунд (CSS пытается анимировать обратно по часовой) — придётся гасить transition на этот тик.

Self-check: что произойдёт со стрелкой секунд при переходе 59s→0s, если оставить transition: 0.5s all? Как это починить?


7 · Canvas API (Whack-A-Mole, опционально)

Зачем: Whack-A-Mole можно сделать и на чистом DOM (как в оригинале Wes Bos), но если хочешь wow-эффект для Stage 3 — добавь Canvas-фон с эффектом удара (взрыв частиц, ряби).

Self-check: зачем перед каждым кадром clearRect(0, 0, width, height)? Что произойдёт, если этого не делать?


8 · События клавиатуры (Drum Kit)

Зачем: Drum Kit маппит клавиатуру на «барабаны». Главный момент — слушать keydown (не keypress!) на window, а не на конкретном элементе, и сопоставлять event.key / event.code с data-key на DOM-элементах.

Self-check: почему keypress устарел? Как поймать момент, когда CSS-анимация удара по барабану закончилась, чтобы убрать класс .playing?


9 · Workflow в shared-репо + Netlify Preview Bot

Зачем: на этой задаче впервые не свой репо, а общий курсовой. Один неаккуратный коммит — и ты задеваешь чужие папки. Нужно дисциплинированно держаться своей ветки и своей подпапки students/<login>/<task-slug>/.

Self-check: что писать в PR description, чтобы reviewer быстро нашёл список Stage 1 / 2 / 3 пунктов? Где брать deploy-link для сабмита в rs app — из gh-pages или из коммента Netlify-бота?


10 · Self-evaluation шаблон (обязательно!)

Зачем: без console.log self-evaluation на загрузке страницы — -5 за виджет. Reviewer открывает DevTools → Console и сверяет твой claim с тем, что реально работает в превью.

Шаблон, который вставь в script.js (или в отдельный self-eval.js):

console.log('%c=== Self-evaluation: Drum Kit ===', 'font-weight:bold;font-size:14px');
console.table([
  { stage: 1, item: 'Visual match with original',        claimed: 10 },
  { stage: 1, item: 'Core behaviour (keys play sounds)', claimed: 10 },
  { stage: 2, item: 'Mandatory feature: <название>',     claimed: 15 },
  { stage: 3, item: 'Optional: visual hit feedback',     claimed: 10 },
  { stage: 3, item: 'Optional: tempo control',           claimed: 10 },
  { stage: 3, item: 'Optional: localStorage preset',     claimed: 10 },
]);
console.log('Claimed total: 65/65');

Self-check: твой console.log выводится на загрузке (не по клику)? Список пунктов совпадает с PR description?


✅ Чек-лист критериев (130 баллов = 65 × 2 виджета)

Виджет 1 (65) и Виджет 2 (65) — одинаковый разбор

Stage 1 · Reproduction · 20

  • Visual match с оригиналом (layout, цвета, ключевые интеракции) (+10)
  • Core behaviour работает end-to-end, без ошибок в консоли (+10)

Stage 2 · Mandatory feature · 15

  • Обязательная доп. фича (см. js30-N.md) реализована и работает (+10)
  • Фича интегрирована: не ломает Stage 1, обрабатывает edge cases (+5)

Stage 3 · Optional improvements · до 30 (cap 30)

  • Улучшение №1 — +10
  • Улучшение №2 — +10
  • Улучшение №3 — +10

Engineering & delivery (штрафы внутри 65)

  • JS читаемый, не minified (-10)
  • Нет jQuery / React / Vue / Angular (-65 voids widget)
  • Self-evaluation в console на загрузке (-5 if missing)
  • Commit history отражает реальную разработку (-10)
  • PR открыт в main курсового репо + Netlify preview работает (-10)

Submission

  • Ветка <github-login>/<task-slug> (lowercase + dashes)
  • Папка students/<github-login>/<task-slug>/ со всеми файлами виджета
  • PR открыт, не смержен
  • Deploy-link (Netlify preview из коммента бота) засабмичен в rs app

🧠 Self-check перед коммитом

Не нажимай git push, пока не сможешь ответить:

  1. Почему я выбрал именно эти 2 виджета? (не «самые лёгкие», а есть причина)
  2. Я могу объяснить каждую строку в своём script.js? Или где-то скопировал с видео не понимая?
  3. Mandatory feature реально работает на превью или только «вроде бы»?
  4. console.log self-eval запускается на DOMContentLoaded и показывает ровно те пункты, что я заявил в PR description?
  5. Моя ветка не трогает чужие папки students/<другой-login>/?
  6. Коммиты — это реальная история (feat: add keydown handler, fix: prevent autorepeat), а не один дамп?
  7. PR description заполнен по схеме + список Stage 1/2/3 пунктов?
  8. Я открыл Netlify preview URL в инкогнито — всё работает без моих закешированных файлов?

➡️ Что переходит в следующие задачи (compound forward)

После JS30 в Podcast переиспользуешь:

  • Блоки 1, 4, 5 — DOM/события + HTMLAudioElement = базис для player'а подкастов
  • Блок 9 — workflow на отдельном репо (но уже не shared)

В Hangman:

  • Блок 8 — обработка клавиатуры (буквы a-z)
  • Блок 1 — DOM-стейт игры

В Async Race:

  • Блок 3requestAnimationFrame для гонки машинок
  • Блок 6transform: translate + CSS transition (паттерн из Slider тоже здесь)

В Shooter (если будет):

  • Блок 7 — Canvas API как фундамент игрового рендера

📚 Внешние ресурсы