Skip to content

Commit f854ec9

Browse files
committed
[PROJ-18.15/compl] adding-habit-by-pop-up-window
Adding "new" habit by "pop-up" window. Form validation, data update. Worth noting: - that all this work/part.. needs to be captured. FS-dev: B-3 / JS basic
1 parent e0106f8 commit f854ec9

File tree

3 files changed

+116
-11
lines changed

3 files changed

+116
-11
lines changed

full-stack-dev/3-js-basic/18-proj-habit-tracker/18-15-adding-habit-by-pop-up-window/css/pop-up.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@
160160
outline-color: var(--add-color-11, #a87ae4);
161161
}
162162

163+
.input-error {
164+
outline: 2px solid var(--add-color-12, #bd0b22);
165+
}
166+
163167
.pop-up__form-btn {
164168
align-self: center;
165169
border: none;

full-stack-dev/3-js-basic/18-proj-habit-tracker/18-15-adding-habit-by-pop-up-window/index.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,33 +66,33 @@ <h2 class="pop-up__title">Новая привычка</h2>
6666
<ul class="pop-up__icons-list">
6767
<li class="pop-up__icons-item">
6868
<button class="pop-up__icons-btn" type="button" aria-label="Выбрать иконку" title="Спорт"
69-
onclick="setHabbitIcon(this, 'gantel-icon')">
69+
onclick="setHabbitIcon(this, 'gantel-icon', '23', '23', 'Гантеля')">
7070
<img class="pop-up__icons-icon" src="./images/gantel-icon.svg" width="23" height="23"
7171
alt="Иконка: Гантеля">
7272
</button>
7373
</li>
7474
<li class="pop-up__icons-item">
7575
<button class="pop-up__icons-btn pop-up__icons-btn_active" type="button" aria-label="Выбрать иконку"
76-
title="Жидкости" onclick="setHabbitIcon(this, 'water-icon')">
76+
title="Жидкости" onclick="setHabbitIcon(this, 'water-icon', '25', '25', 'Бутылка с водой')">
7777
<img class="pop-up__icons-icon" src="./images/water-icon.svg" width="25" height="25"
7878
alt="Иконка: Бутылка с водой">
7979
</button>
8080
</li>
8181
<li class="pop-up__icons-item">
8282
<button class="pop-up__icons-btn" type="button" aria-label="Выбрать иконку" title="Питание"
83-
onclick="setHabbitIcon(this, 'food-icon')">
83+
onclick="setHabbitIcon(this, 'food-icon', '23', '24', 'Тарелка с едой')">
8484
<img class="pop-up__icons-icon" src="./images/food-icon.svg" width="23" height="24"
8585
alt="Иконка: Тарелка с едой">
8686
</button>
8787
</li>
8888
</ul>
8989
</div>
9090
<div class="pop-up__form-wrap">
91-
<form class="pop-up__form" id="pop-up-form">
91+
<form class="pop-up__form" id="pop-up-form" onsubmit="addNewHabbit(event)">
92+
<input class="pop-up__form-input" id="hidden-input" type="text" name="icon-habbit" placeholder="Иконка"
93+
autocomplete="off" value="water-icon" data-width='25' data-height='25' data-alt='Бутылка с водой' hidden>
9294
<input class="pop-up__form-input" id="title-input" type="text" name="title-habbit" placeholder="Название"
9395
autocomplete="off">
94-
<input class="pop-up__form-input" id="hidden-input" type="text" name="icon-habbit" placeholder="Иконка"
95-
autocomplete="off" value="water-icon" hidden>
9696
<input class="pop-up__form-input" id="target-input" type="number" name="target-habbit"
9797
placeholder="Цель/дней" autocomplete="off">
9898
<button class="pop-up__form-btn" type="submit">Добавить</button>

full-stack-dev/3-js-basic/18-proj-habit-tracker/18-15-adding-habit-by-pop-up-window/js/index.js

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ function saveData() {
7474

7575
function togglePopup() {
7676
app['pop-up'].popupCover.classList.toggle('pop-up_cover-hidden');
77+
78+
// очистка формы/полей, возврат к по default выбранной иконке
79+
if (!app['pop-up'].popupCover.classList.contains('pop-up_cover-hidden')) {
80+
const form = app['pop-up'].popupElement.querySelector('.pop-up__form');
81+
82+
if (form) {
83+
form.reset(); // сброс полей/значений
84+
const titleInput = form['title-habbit'];
85+
const targetInput = form['target-habbit'];
86+
titleInput.classList.remove('input-error'); // снятие "красной" обводки
87+
targetInput.classList.remove('input-error'); // ...
88+
89+
const defaultIcon = document.querySelector(
90+
'.pop-up__icons-btn[title="Жидкости"]'
91+
); // фиксация default/иконки (по середине)
92+
93+
if (defaultIcon) {
94+
defaultIcon.click(); // имитация её выбора (т.е. при новом открытии pop-up на неё перемещение, обновление скрытого инпута)
95+
}
96+
}
97+
}
7798
}
7899

79100
// ** render **
@@ -200,7 +221,7 @@ function rerender(activeHabbitId) {
200221
function addCommentDay(event) {
201222
event.preventDefault(); // отмена default отправки формы, перезагрузки страницы
202223

203-
const targetForm = event.target;
224+
const targetForm = event.target; // фиксация формы
204225
const commentInput = targetForm['comment-day']; // фиксация инпута
205226
const formData = new FormData(targetForm); // создание объекта данных согласно искомой формы (получаемой через onsubmit/event.target логику)
206227
const dayComment = formData.get('comment-day'); // получение значения/комментария из инпута согласно его имени/name
@@ -238,14 +259,77 @@ function deleteCommentDay(index) {
238259
saveData(); // обновление/сохранение в localStorage
239260
}
240261

241-
function setHabbitIcon(context, iconName) {
242-
app['pop-up'].hiddenIconInput.value = iconName; // обновление value у "скрытого" инпута
262+
function setHabbitIcon(context, iconName, iconWidth, iconHeight, altText) {
263+
app['pop-up'].hiddenIconInput.value = iconName; // обновление value/названия иконки у "скрытого" инпута
264+
app['pop-up'].hiddenIconInput.dataset.width = iconWidth; // обновление width/иконки
265+
app['pop-up'].hiddenIconInput.dataset.height = iconHeight; // обновление height/иконки
266+
app['pop-up'].hiddenIconInput.dataset.alt = altText; // обновление alt/текста
267+
268+
// определение активной иконки/кнопки (какая выделена)
243269
const activeIcon = document.querySelector(
244270
'.pop-up__icons-btn.pop-up__icons-btn_active'
245271
);
272+
activeIcon.classList.remove('pop-up__icons-btn_active'); // удаление "активности"
246273

247-
activeIcon.classList.remove('pop-up__icons-btn_active'); // у ранее "активной" удаление
248-
context.classList.add('pop-up__icons-btn_active'); // текущей кнопке добавление, т.е. по котрой onclick=""
274+
context.classList.add('pop-up__icons-btn_active'); // добавление "активности" текущей кнопке, т.е. по котрой onclick
275+
}
276+
277+
function addNewHabbit(event) {
278+
event.preventDefault(); // отмена default отправки формы, перезагрузки страницы
279+
280+
const targetForm = event.target; // фиксация формы
281+
const titleInput = targetForm['title-habbit']; // фиксация названия привычки
282+
const targetInput = targetForm['target-habbit']; // фиксация количества дней
283+
284+
// валидация полей формы через флаг (добавление соответствующей обводки)
285+
let formIsValid = true;
286+
287+
if (!titleInput.value.trim()) {
288+
titleInput.classList.add('input-error');
289+
formIsValid = false;
290+
} else {
291+
titleInput.classList.remove('input-error');
292+
}
293+
294+
if (!targetInput.value.trim()) {
295+
targetInput.classList.add('input-error');
296+
formIsValid = false;
297+
} else {
298+
targetInput.classList.remove('input-error');
299+
}
300+
301+
if (!formIsValid) {
302+
return; // если не валидна.. возврат
303+
}
304+
305+
// а если форма валидна, фиксация данных добавление объекта привычки
306+
const iconInput = targetForm['icon-habbit']; // фиксация выбранной иконки
307+
const iconWidth = targetForm['icon-habbit'].dataset.width; // фиксация размера/width выбранной иконки
308+
const iconHeight = targetForm['icon-habbit'].dataset.height; // фиксация размера/height выбранной иконки
309+
const iconAlt = targetForm['icon-habbit'].dataset.alt; // фиксация alt/текста выбранной иконки
310+
311+
const maxId = habbits.reduce(
312+
(acc, habbit) => (acc > habbit.id ? acc : habbit.id),
313+
0
314+
); // формирование последующего id
315+
316+
habbits.push({
317+
id: maxId + 1,
318+
icon: iconInput.value,
319+
name: iconAlt,
320+
title: titleInput.value,
321+
width: iconWidth,
322+
height: iconHeight,
323+
target: targetInput.value,
324+
days: [],
325+
});
326+
327+
saveData(); // обновление/сохранение в localStorage
328+
togglePopup(); // закрытие pop-up окна
329+
330+
setTimeout(() => {
331+
rerender(maxId + 1); // перерисовка всего/content элемента
332+
}, 300); // замедление перерисовки
249333
}
250334

251335
// init
@@ -257,4 +341,21 @@ function setHabbitIcon(context, iconName) {
257341
if (habbits.length > 0) {
258342
rerender(habbits[0].id); // пока.. принудительно передаёт
259343
}
344+
345+
// организация прослушек pop-up инпутов для корректировки классов ошибки (т.е. ввод данных, отмена обводки)
346+
const form = app['pop-up'].popupElement.querySelector('.pop-up__form');
347+
const titleInput = form['title-habbit'];
348+
const targetInput = form['target-habbit'];
349+
350+
titleInput.addEventListener('input', () => {
351+
if (titleInput.classList.contains('input-error')) {
352+
titleInput.classList.remove('input-error');
353+
}
354+
});
355+
356+
targetInput.addEventListener('input', () => {
357+
if (targetInput.classList.contains('input-error')) {
358+
targetInput.classList.remove('input-error');
359+
}
360+
});
260361
})();

0 commit comments

Comments
 (0)