Далее на странице...
- Исходные данные
- Решение задачи - События на странице Рекурсия - вызов функции внутри себя
Продолжается практическая работа со страницей средствами JavaScript. Здесь будет проводится работа с событиями на странице.
Исходный код берется из предыдущей практики.
Задание на отработку действий со страницей.
1) Реализовать функционал, что после заполнения формы и нажатия кнопки "Подтвердить" - новый фильм добавляется в список. Страница не должна перезагружаться. Новый фильм должен добавляться в movieDB.movies. Для получения доступа к значению input - обращаемся к нему как input.value;
P.S. Здесь есть несколько вариантов решения задачи, принимается любой, но рабочий.
2) Если название фильма больше, чем 21 символ - обрезать его и добавить три точки
3) При клике на мусорную корзину - элемент будет удаляться из списка (сложно)
4) Если в форме стоит галочка "Сделать любимым" - в консоль вывести сообщение: "Добавляем любимый фильм"
5) Фильмы должны быть отсортированы по алфавиту
Исходные данные
Есть исходная html-страница и js-файл из предыдущей практики. Ниже представлен их код.
HTML-код - Из предыдущей практики
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Работа со страницей 2 - JavaScript</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,700&display=swap&subset=cyrillic-ext" rel="stylesheet">
<link rel="stylesheet" href="css/style.min.css">
</head>
<body>
<header class="header">
<div class="header__search">
<form action="#">
<input type="text" placeholder="Поиск">
</form>
</div>
<div class="header__logo">
<img src="icons/Logotype.svg" alt="logo">
</div>
</header>
<main class="promo">
<div class="promo__menu">
<nav class="promo__menu-list">
<ul>
<li><a class="promo__menu-item promo__menu-item_active" href="#">Фильмы</a></li>
<li><a class="promo__menu-item" href="#">Сериалы</a></li>
<li><a class="promo__menu-item" href="#">Мультфильмы</a></li>
<li><a class="promo__menu-item" href="#">Клипы</a></li>
<li><a class="promo__menu-item" href="#">Трейлеры</a></li>
</ul>
</nav>
</div>
<div class="promo__content">
<div class="promo__bg">
<div class="promo__genre">КОМЕДИЯ</div>
<div class="promo__title">МАРСИАНИН</div>
<div class="promo__descr">ИСТОРИЯ ЧЕЛОВЕКА, ВЫЖИВШЕГО НА ЧУЖОЙ ПЛАНЕТЕ В ОДИНОЧКУ</div>
<div class="promo__ratings">
<span>IMDb: 8.0</span>
<span>Кинопоиск: 7.7</span>
</div>
</div>
<div class="promo__interactive">
<div>
<div class="promo__interactive-title">ПРОСМОТРЕННЫЕ ФИЛЬМЫ</div>
<ul class="promo__interactive-list">
<li class="promo__interactive-item">ЛОГАН
<div class="delete"></div>
</li>
<li class="promo__interactive-item">ЛИГА СПРАВЕДЛИВОСТИ
<div class="delete"></div>
</li>
<li class="promo__interactive-item">ЛА-ЛА ЛЭНД
<div class="delete"></div>
</li>
<li class="promo__interactive-item">ОДЕРЖИМОСТЬ
<div class="delete"></div>
</li>
<li class="promo__interactive-item">СКОТТ ПИЛИГРИМ ПРОТИВ...
<div class="delete"></div>
</li>
</ul>
</div>
<div>
<form class="add">
<div class="promo__interactive-title">ДОБАВИТЬ НОВЫЙ ФИЛЬМ</div>
<span>Введите название фильма</span>
<input class="adding__input" type="text" placeholder="Что уже посмотрено...?">
<span>Сделать его любимым?</span>
<input type="checkbox">
<span class="yes">Да!</span>
<button>Подтвердить</button>
</form>
</div>
</div>
</div>
<div class="promo__adv">
<div class="promo__adv-title">Реклама от спонсоров</div>
<img src="img/content_1.jpg" alt="some picture">
<img src="img/content_2.jpg" alt="some picture">
<img src="img/content_3.png" alt="some picture">
</div>
</main>
<script src="js/script.js"></script>
</body>
</html>
JS-код - Из предыдущей практики
'use strict';
const movieDB = {
movies: [
"Логан",
"Лига справедливости",
"Ла-ла лэнд",
"Одержимость",
"Скотт Пилигрим против..."
]
};
// ------------------------ 1-я часть задания ------------------------
// Доступ к изображениям img из блока с рекламой promo__adv - строка №77
const adv = document.querySelectorAll('.promo__adv img');
// Удаляем все изображения/рекламные блоки
adv.forEach(item => {
item.remove();
});
// ------------------------ 2-я и 3-я части задания ------------------
// Доступ к блоку с постером - строка №34. И через него к блоку с жанром - строка №35
const poster = document.querySelector('.promo__bg'),
genre = poster.querySelector('.promo__genre');
// Меняем жанр
genre.textContent = 'драма';
// Меняем задний фон постера
poster.style.backgroundImage = 'url("img/bg.jpg")';
// ----------------------- 4-я и 5-я части задания --------------------
// Доступ к блоку/списку с просмотренными фильмами - строка №46
const movieFilms = document.querySelector(".promo__interactive-list");
// Удаляем список с фильмами (весь код в данном блоке) - вместо него "ничего"
movieFilms.innerHTML = "";
// Сортировка массива/списка с фильмами - Исходный JS-код - строка №3
movieDB.movies.sort();
// Методом перебора forEach перебираем все элементы массива (названия фильмов)
// И вставляем названия фильмов в блок movieFilms вместе с фрагментом соответствующего кода
// item - элемент массива, i - индекс элемента массива
movieDB.movies.forEach((item, i) => {
movieFilms.innerHTML += `
<li class="promo__interactive-item">${i + 1}. ${item}
<div class="delete"></div>
</li>`;
});
Страница из предыдущей практики в Браузере
Решение задачи - События на странице
JavaScript-код
'use strict';
const movieDB = {
movies: [
"Логан",
"Лига справедливости",
"Ла-ла лэнд",
"Одержимость",
"Скотт Пилигрим против..."
]
};
// Доступ к элементам
const adv = document.querySelectorAll('.promo__adv img'), // Изображения из блока с рекламой
poster = document.querySelector('.promo__bg'), // Постер -> Жанры
genre = poster.querySelector('.promo__genre'),
movieFilms = document.querySelector(".promo__interactive-list"), // Список с фильмами
addForm = document.querySelector('form.add'), // Форма -> input
addInput = addForm.querySelector('.adding__input'),
checkbox = addForm.querySelector('[type="checkbox"]'); // input - type="checkbox"
// Обработчик события для Формы - Срабатывает при нажатии кнопки "Подтвердить"
// Здесь будут реализованы ЗАДАНИЯ №1, №2 и №4
addForm.addEventListener('submit', (event) => {
event.preventDefault(); // Страница не перегружается - Отмена станд. поведения
let newFilm = addInput.value; // Название фильма, которое вводится в поле
const favorite = checkbox.checked; // Атрибут checked: определяет - есть ли флажок?
if (newFilm) { // Проверка на пустую строку. Введено ли название фильма?
// ЗАДАНИЕ №2
if (newFilm.length > 21) {
newFilm = `${newFilm.substring(0,22)}...`;
}
// ЗАДАНИЕ №4
if (favorite) {
console.log('Добавляем любимый фильм');
}
// ЗАДАНИЕ №1
movieDB.movies.push(newFilm); // Добавляем новый фильм в БАЗУ movieDB.movies
// Перебор фильмов в БАЗЕ и добавление их в movieFilms - список на странице
createMovieList(movieDB.movies, movieFilms);
}
// addForm.reset(); - Очистка формы. Здесь addForm меняем на event.target
event.target.reset();
});
// Функция для удаления рекламных блоков. Аргумент - Массив
const deleteAdv = (arr) => {
arr.forEach(item => {
item.remove();
});
};
// Функция -> различные/небольшие изменения
const makeChanges = () => {
// Меняем жанр
genre.textContent = 'драма';
// Меняем задний фон постера
poster.style.backgroundImage = 'url("img/bg.jpg")';
};
// Функция сортировки. Аргумент - Массив
const sortArr = (arr) => {
arr.sort();
};
// Функция createMovieList
// 1. Перебор фильмов и добавление фильма на страницу в movieFilms
// 2. Удаление фильма при клике на корзину
// films - массив с фильмами: в д.сл. БАЗА movieDB.movies
// parent - блок на странице, в который помещаются фильмы: в д.сл. movieFilms
function createMovieList(films, parent) {
parent.innerHTML = ""; // Удаляем начальный список с фильмами (весь код в блоке movieFilms)
// ЗАДАНИЕ №5 - Сортировка фильмов
sortArr(films);
// 1. Перебор и добавление фильмов в movieFilms.
films.forEach((film, i) => {
parent.innerHTML += `
<li class="promo__interactive-item">${i + 1}. ${film}
<div class="delete"></div>
</li>`;
});
// 2. Удаление фильма при клике на корзину - ЗАДАНИЕ №3
// Получаем доступ ко всем корзинам и сразу же перебираем их...
document.querySelectorAll('.delete').forEach((btn, i) => {
// Обработчик для каждой корзины - срабатывает при клике на ней
btn.addEventListener('click', () => {
// 1. При клике удаляется родительский элемент со страницы: элемент списка li, т.е. фильм и ....
btn.parentElement.remove();
movieDB.movies.splice(i, 1); // ... 2. соответствующий элемент массива/фильм из БАЗЫ
// Рекурсия - вызываем функцию внутри себя же - чтобы после удаления фильма, шла их пере нумерация
createMovieList(films, parent);
});
});
}
// Вызов функций
deleteAdv(adv);
makeChanges();
createMovieList(movieDB.movies, movieFilms);
Стоит обратить внимание!!! Все названия фильмов в базе movieDB.movies начинаются с заглавной буквы. А на странице они отображаются только заглавными буквами. Однако, сортировка строк происходит таким образом, что, например, названия "Асса", "асса" и "АССА" - имеют различный приоритет. Сначала "АССА", "Асса" и потом "асса". Это следует учесть при добавлении фильмов в поле "Введите название фильма". Иначе может возникнуть путаница и недопонимание того, как работает скрипт. То есть, следует писать фильмы с первой заглавной буквы - остальные строчные.
Измененная страница в Браузере
Получаем доступ к необходимым элементам: помимо элементов из прошлой практики...
-
Здесь добавлен доступ к форме - тег form с классом .add, и через нее доступ к тегу input с классом .adding__input. Строки кода 18 и 19.
-
А также - доступ к тегу через атрибут - это тег input, у которого для атрибута type указано значение checkbox - см. Часть задания №4.
При этом атрибут тега заключается в квадратные скобки - строка кода №20
checkbox = addForm.querySelector('[type="checkbox"]');
-
Реализация 1-ой части задания
- для формы, используя метод addEventListener, назначается обработчик для события 'submit' (Отправка данных формы - щелчок по кнопке - <input type="submit">). Строка кода №24.
- обработчик события - стрелочная функция, в которую в качестве аргумента передается объект Event - Объект события.
- благодаря объекту события Event, отменяется стандартное поведение браузера - при этом используется метод preventDefault(). В итоге при нажатии кнопки "Подтвердить" страница не перегружается. Строка кода №21
- кроме этого - одним из вариантов очистки формы является использование свойства target объекта Event совместно с методом reset(). Строка кода №49.
-
Реализация 1-ой части задания - Продолжение
- Согласно условию задачи: после заполнения формы и нажатия кнопки "Подтвердить" - новый фильм добавляется в список фильмов на странице и добавляется в movieDB.movies.
1. Новый фильм добавляется в movieDB.movies с помощью метода push. Строка кода №43.
2. Функция createMovieList(movieDB.movies, movieFilms) - сортирует фильмы по алфавиту и добавляет их на страницу. Строка кода №45. Код самой функции - см. строку №78.
-
Реализация 2-ой части задания
- 2-я часть задачи реализуется в функции-обработчике (для первой части задания), которая запускается при нажатии кнопки "Подтвердить". Строка кода №32.
- при этом для обрезки строки используется метод substring. А для формирования комплексной строки - интерполяция.
-
Реализация 3-ой части задания
- 3-я часть задачи реализуется в теле функции createMovieList. Строка кода №92. При этом...
1. Получаем доступ ко всем корзинам и перебираем их методом forEach.
2. В процессе перебора для каждой корзины назначается обработчик для события 'click' (одинарный щелчок, клик).
3. Таким образом, при клике по корзине: удаляется фильм из БАЗЫ (Строка кода №99) и фильм со страницы - Строка кода №98 (при этом используется метод parentElement: он позволяет получить доступ к родительскому элементу - непосредственно тегу <li>, который и удаляется вместе с названием фильма).
Здесь же используется рекурсия - вызов функции внутри себя же. В данном случае это нужно для того, чтобы после удаления фильма, шла их пере нумерация.
-
4-ая часть задачи, также, как и 2-я, реализуется в функции-обработчике (для первой части задания). Строка кода №37.
При этом для проверки состояния "чекбокса" (тега input с атрибутом type="checkbox") используется атрибут checked, который определяет, помечен ли заранее такой элемент формы, как флажок или переключатель.
Переменная const favorite = checkbox.checked; (Строка кода №28) - в зависимости от того помечен ли флажок - возвращает true или false.
-
5-ая часть задачи - сортировка фильмов по алфавиту - реализуется в теле функции createMovieList. Строка кода №82.
-
Кроме выполнения всего задания оптимизация кода из предыдущей практики заключается в добавлении и использовании функции для удаления рекламных блоков, функции для различных/небольших изменений и функции сортировки. Строки кода №52, №59 и №68.