Skip to content

Commit fb96b4e

Browse files
committed
[REC-17/st] dom
Solving 3 tasks. Getting/creating "DOM" el's. Listening "events". FS-dev: B-3 / JS basic
1 parent 4730902 commit fb96b4e

File tree

3 files changed

+286
-0
lines changed

3 files changed

+286
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Recall - DOM</title>
8+
<link rel="stylesheet" href="./style.css">
9+
<script src="./practice.js" defer></script>
10+
</head>
11+
12+
<body>
13+
<div id="app">
14+
<p>Количество кликов: <span id="counter-value">0</span></p>
15+
<button id="increment-btn">Кликни меня!</button>
16+
</div>
17+
18+
<div class="form-group">
19+
<label for="password-input">Пароль (мин. 6 символов):</label>
20+
<input id="password-input" type="text" placeholder="Введите пароль">
21+
<p class="error-text" id="error-message">Пароль слишком короткий</p>
22+
</div>
23+
24+
<h2>Мой список дел</h2>
25+
<div class="input-group">
26+
<input id="todo-input" type="text" placeholder="Добавить новое дело...">
27+
<button id="add-btn">Добавить</button>
28+
</div>
29+
<ul id="todo-list">
30+
</ul>
31+
32+
<div class="shop">
33+
<h2>Наши товары</h2>
34+
<ul id="product-list">
35+
<li>
36+
<span class="item-desc">Яблоко (50р)</span>
37+
<button class="add-to-cart-btn" data-id="1" data-name="Яблоко" data-price="50">Добавить</button>
38+
</li>
39+
<li>
40+
<span class="item-desc">Банан (70р)</span>
41+
<button class="add-to-cart-btn" data-id="2" data-name="Банан" data-price="70">Добавить</button>
42+
</li>
43+
<li>
44+
<span class="item-desc">Апельсин (90р)</span>
45+
<button class="add-to-cart-btn" data-id="3" data-name="Апельсин" data-price="90">Добавить</button>
46+
</li>
47+
</ul>
48+
</div>
49+
50+
<div class="cart">
51+
<h2>Корзина</h2>
52+
<ul id="cart-items">
53+
</ul>
54+
<p>Итого: <span id="total-price">0</span> р</p>
55+
<button id="clear-cart-btn">Очистить корзину</button>
56+
</div>
57+
</body>
58+
59+
</html>
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
'use strict';
2+
3+
// Задание 1:
4+
// Дана вот такая HTML-структура:
5+
/*
6+
<div id="app">
7+
<p>Количество кликов: <span id="counter-value">0</span></p>
8+
<button id="increment-btn">Кликни меня!</button>
9+
</div>
10+
*/
11+
// Твоя задача — написать JavaScript-код, который:
12+
// 1. Находит кнопку (increment-btn) и элемент span (counter-value).
13+
// 2. Создаёт переменную-счётчик, которая изначально равна 0.
14+
// 3. При клике на кнопку увеличивает этот счётчик на 1.
15+
// 4. Обновляет текстовое содержимое span'а, чтобы в нём отображалось актуальное значение счётчика.
16+
17+
const appSpan = document.getElementById('counter-value');
18+
const appBtn = document.getElementById('increment-btn');
19+
20+
let count = 0;
21+
let countTimer; // переменная для хранения ID таймера
22+
23+
function increaseCount() {
24+
count++;
25+
appSpan.textContent = count;
26+
27+
// очищаем предыдущий таймер
28+
clearTimeout(countTimer);
29+
30+
// устанавливаем новый таймер (заносим в переменную ID таймера)
31+
countTimer = setTimeout(() => {
32+
appSpan.textContent = 0;
33+
}, 3000);
34+
}
35+
36+
appBtn.addEventListener('click', increaseCount);
37+
38+
// Задание 2:
39+
// Представь, что у тебя есть поле для ввода пароля, и ты хочешь в реальном времени показывать пользователю, соответствует ли его ввод минимальным требованиям.
40+
// Твоя задача — написать JavaScript-код, который:
41+
// 1. Находит поле ввода (password-input) и сообщение об ошибке (error-message).
42+
// 2. Добавляет на поле ввода обработчик события input (оно срабатывает каждый раз, когда меняется содержимое поля).
43+
// 3. Внутри обработчика реализует следующую логику:
44+
// Если длина введённого текста меньше 6 символов, то:
45+
// - Полю ввода добавляется класс error.
46+
// - У поля ввода удаляется класс success.
47+
// - Сообщению об ошибке добавляется класс visible.
48+
// Если длина введённого текста 6 символов или больше, то:
49+
// - У поля ввода удаляется класс error.
50+
// - Полю ввода добавляется класс success.
51+
// - У сообщения об ошибке удаляется класс visible.
52+
53+
const passInput = document.getElementById('password-input');
54+
const errMessage = document.getElementById('error-message');
55+
56+
function checkPassword() {
57+
const value = passInput.value;
58+
59+
if (value.length === 0) {
60+
passInput.classList.remove('success');
61+
passInput.classList.remove('error');
62+
errMessage.classList.remove('visible');
63+
} else if (value.length < 6) {
64+
passInput.classList.add('error');
65+
passInput.classList.remove('success');
66+
errMessage.classList.add('visible');
67+
} else {
68+
passInput.classList.remove('error');
69+
passInput.classList.add('success');
70+
errMessage.classList.remove('visible');
71+
}
72+
}
73+
74+
passInput.addEventListener('input', checkPassword);
75+
76+
// Задание 3:
77+
// Это классическая задача, которая отлично тренирует навыки создания элементов.
78+
/*
79+
<h2>Мой список дел</h2>
80+
<div class="input-group">
81+
<input type="text" id="todo-input" placeholder="Добавить новое дело...">
82+
<button id="add-btn">Добавить</button>
83+
</div>
84+
<ul id="todo-list">
85+
</ul>
86+
*/
87+
// Твоя задача — написать JavaScript-код, который:
88+
// 1. Находит поле ввода (todo-input), кнопку (add-btn) и список (todo-list).
89+
// 2. Вешает на кнопку обработчик события click.
90+
// 3. Когда происходит клик, функция-обработчик должна:
91+
// - Получить текст из поля ввода.
92+
// - Проверить, что текст не пустой.
93+
// - Если текст есть, создать новый элемент <li>.
94+
// - Присвоить textContent этого <li> тексту из поля ввода.
95+
// - Добавить новый <li> в конец списка <ul>.
96+
// - Очистить поле ввода, чтобы было удобно добавлять следующее дело.
97+
// Бонус: Попробуй сделать так, чтобы дело добавлялось не только по клику на кнопку, но и по нажатию клавиши Enter в поле ввода.
98+
99+
const todoInput = document.getElementById('todo-input');
100+
const addBtn = document.getElementById('add-btn');
101+
const todoList = document.getElementById('todo-list');
102+
103+
function addTodoTask() {
104+
const value = todoInput.value.trim(); // лучше/желательно всегда добавлять trim().. да бы исключать пробелы
105+
106+
if (value !== '') {
107+
const item = document.createElement('li');
108+
109+
item.textContent = value;
110+
todoList.append(item);
111+
112+
todoInput.value = '';
113+
}
114+
}
115+
116+
addBtn.addEventListener('click', addTodoTask);
117+
todoInput.addEventListener('keydown', (event) => {
118+
if (event.code === 'Enter') {
119+
addTodoTask();
120+
}
121+
});
122+
123+
// Задание 4:
124+
// Эта задача объединит сразу несколько важных тем: делегирование событий, работу с data- атрибутами и сохранение данных в localStorage. Это уже похоже на настоящую маленькую фичу для сайта.
125+
// Концепция: Мы не будем вешать обработчик на каждую кнопку "Добавить". Вместо этого мы повесим один обработчик на весь список товаров и будем "ловить" клики внутри него. Это и называется делегированием.
126+
/*
127+
<div class="shop">
128+
<h2>Наши товары</h2>
129+
<ul id="product-list">
130+
<li>
131+
<span>Яблоко (50р)</span>
132+
<button class="add-to-cart-btn" data-id="1" data-name="Яблоко" data-price="50">Добавить</button>
133+
</li>
134+
<li>
135+
<span>Банан (70р)</span>
136+
<button class="add-to-cart-btn" data-id="2" data-name="Банан" data-price="70">Добавить</button>
137+
</li>
138+
<li>
139+
<span>Апельсин (90р)</span>
140+
<button class="add-to-cart-btn" data-id="3" data-name="Апельсин" data-price="90">Добавить</button>
141+
</li>
142+
</ul>
143+
</div>
144+
145+
<div class="cart">
146+
<h2>Корзина</h2>
147+
<ul id="cart-items">
148+
</ul>
149+
<p>Итого: <span id="total-price">0</span> р</p>
150+
<button id="clear-cart-btn">Очистить корзину</button>
151+
</div>
152+
*/
153+
// Твоя задача — написать JS-код, который реализует полную логику корзины:
154+
// 1. Инициализация:
155+
// - При загрузке страницы нужно попытаться загрузить корзину из localStorage.
156+
// - Создай функцию renderCart(), которая будет брать массив товаров из localStorage, отображать их в списке cart-items и пересчитывать общую стоимость. Вызови её при старте скрипта.
157+
// 2. Добавление товара (Делегирование):
158+
// - Повесь один обработчик click на весь список product-list.
159+
// - Внутри обработчика проверь, что клик был именно по кнопке с классом add-to-cart-btn. (Подсказка: event.target.classList.contains(...)).
160+
// - Если да, то считай data- атрибуты (id, name, price) с этой кнопки.
161+
// - Добавь товар (как объект) в массив корзины, сохрани обновлённый массив в localStorage и вызови renderCart() для обновления отображения.
162+
// 3. Очистка корзины:
163+
// - Повесь обработчик click на кнопку clear-cart-btn.
164+
// - При клике он должен очищать массив в localStorage и снова вызывать renderCart().
165+
166+
const productList = document.getElementById('product-list');
167+
const totalPrice = document.getElementById('total-price');
168+
const clearBtn = document.getElementById('clear-cart-btn');
169+
let currentCart = JSON.parse(localStorage.getItem('Cart')) || [];
170+
171+
function renderCart() {}
172+
173+
function clearStorage() {
174+
// if (currentCart.length === 0) {
175+
// return;
176+
// }
177+
178+
totalPrice.textContent = 0;
179+
localStorage.setItem('Cart', JSON.stringify([]));
180+
}
181+
182+
renderCart();
183+
184+
productList.addEventListener('click', renderCart);
185+
clearBtn.addEventListener('click', clearStorage);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#app {
2+
margin-bottom: 10px;
3+
}
4+
5+
.form-group {
6+
font-family: sans-serif;
7+
}
8+
9+
#password-input {
10+
border: 2px solid #cccccc;
11+
border-radius: 4px;
12+
padding: 8px;
13+
}
14+
15+
/* Стили для поля с ошибкой */
16+
#password-input.error {
17+
border-color: red;
18+
}
19+
20+
/* Стили для корректно заполненного поля */
21+
#password-input.success {
22+
border-color: green;
23+
}
24+
25+
/* Стили для текста ошибки (изначально скрыт) */
26+
.error-text {
27+
display: none;
28+
font-size: 12px;
29+
color: red;
30+
/* Скрываем по умолчанию */
31+
}
32+
33+
/* Класс, который делает текст ошибки видимым */
34+
.error-text.visible {
35+
display: block;
36+
}
37+
38+
.item-desc {
39+
display: inline-block;
40+
width: 100%;
41+
max-width: 120px;
42+
}

0 commit comments

Comments
 (0)