Приветствую! 👋 Сегодня мы создадим приложение для заметок с использованием HTML, CSS и JavaScript. Это приложение позволит вам добавлять, редактировать и удалять заметки, которые будут сохраняться в localStorage
браузера. Это значит, что ваши заметки не исчезнут даже после перезагрузки страницы! Мы рассмотрим каждый шаг создания приложения, чтобы вы могли понять, как оно работает. Готовы? Поехали! 🚀
Для полного исходного кода и, возможно, дополнительных улучшений, загляни на наш GitHub.
Наше приложение для заметок позволяет пользователям:
Добавлять заметки с заголовками и описанием.
Сохранять заметки в браузере, чтобы данные не терялись при перезагрузке страницы.
Просматривать список всех созданных заметок.
Редактировать существующие заметки.
Удалять ненужные заметки.
Теперь приступим к созданию!
HTML отвечает за структуру нашего приложения. Сначала создайте файл index.html
с базовой разметкой:
<!DOCTYPE html>
<html lang="ru" dir="ltr">
<head>
<meta charset="utf-8">
<title>Приложение для заметок на JavaScript | Coursme</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Подключение иконок -->
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
</head>
<body>
<!-- Всплывающее окно для добавления/редактирования заметок -->
<div class="popup-box">
<div class="popup">
<div class="content">
<header>
<p>Добавить новую заметку</p>
<i class="uil uil-times"></i> <!-- Кнопка закрытия -->
</header>
<form action="#">
<div class="row title">
<label>Заголовок</label>
<input type="text" spellcheck="false">
</div>
<div class="row description">
<label>Описание</label>
<textarea spellcheck="false"></textarea>
</div>
<button>Сохранить заметку</button>
</form>
</div>
</div>
</div>
<!-- Контейнер для добавления новой заметки -->
<div class="wrapper">
<li class="add-box">
<div class="icon"><i class="uil uil-plus"></i></div>
<p>Добавить новую заметку</p>
</li>
</div>
<script src="script.js"></script>
</body>
</html>
Краткое объяснение кода:
popup-box
: Всплывающее окно для создания новой заметки. Содержит форму с полями для заголовка и описания.
add-box
: Элемент, который открывает всплывающее окно для добавления новой заметки.
Создайте файл style.css
, чтобы добавить стили к нашему приложению. Вот основные стили, которые вам нужно знать:
/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body {
background: #FFB3B3;
}
::selection {
color: #fff;
background: #FF6F61;
}
.wrapper {
margin: 40px;
display: grid;
gap: 20px;
grid-template-columns: repeat(auto-fill, 270px);
}
.wrapper li {
height: 260px;
list-style: none;
border-radius: 8px;
padding: 15px 18px 18px;
background: #ffffff;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease-in-out;
}
.wrapper li:hover {
transform: translateY(-5px);
}
.add-box,
.icon,
.bottom-content,
.popup,
header,
.settings .menu li {
display: flex;
align-items: center;
justify-content: space-between;
}
.add-box {
cursor: pointer;
flex-direction: column;
justify-content: center;
}
.add-box .icon {
height: 80px;
width: 80px;
color: #FF6F61;
font-size: 42px;
border-radius: 50%;
justify-content: center;
border: 3px dashed #FF6F61;
}
.add-box p {
color: #FF6F61;
font-weight: 500;
margin-top: 18px;
}
.note {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.note .details {
max-height: 170px;
overflow-y: auto;
}
.note .details::-webkit-scrollbar,
.popup textarea::-webkit-scrollbar {
width: 0;
}
.note .details:hover::-webkit-scrollbar,
.popup textarea:hover::-webkit-scrollbar {
width: 6px;
}
.note .details:hover::-webkit-scrollbar-track,
.popup textarea:hover::-webkit-scrollbar-track {
background: #f3f3f3;
border-radius: 20px;
}
.note .details:hover::-webkit-scrollbar-thumb,
.popup textarea:hover::-webkit-scrollbar-thumb {
background: #ddd;
border-radius: 20px;
}
.note p {
font-size: 20px;
font-weight: 500;
}
.note span {
display: block;
color: #626262;
font-size: 15px;
margin-top: 6px;
}
.note .bottom-content {
padding-top: 8px;
border-top: 1px solid #bbb;
}
.bottom-content span {
color: #7A7A7A;
font-size: 13px;
}
.bottom-content .settings {
position: relative;
}
.bottom-content .settings i {
color: #7A7A7A;
cursor: pointer;
font-size: 16px;
}
.settings .menu {
z-index: 1;
bottom: 0;
right: -5px;
padding: 6px 0;
background: #ffffff;
position: absolute;
border-radius: 6px;
transform: scale(0);
transform-origin: bottom right;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.18);
transition: transform 0.3s ease;
}
.settings.show .menu {
transform: scale(1);
}
.settings .menu li {
height: 28px;
font-size: 15px;
margin-bottom: 2px;
padding: 18px 16px;
cursor: pointer;
box-shadow: none;
border-radius: 0;
justify-content: flex-start;
}
.menu li:last-child {
margin-bottom: 0;
}
.menu li:hover {
background: #f4f4f4;
}
.menu li i {
padding-right: 8px;
}
.popup-box {
position: fixed;
top: 0;
left: 0;
z-index: 2;
height: 100%;
width: 100%;
background: rgba(0, 0, 0, 0.5);
}
.popup-box .popup {
position: absolute;
top: 50%;
left: 50%;
z-index: 3;
width: 100%;
max-width: 420px;
justify-content: center;
transform: translate(-50%, -50%) scale(0.9);
}
.popup-box,
.popup {
opacity: 0;
pointer-events: none;
transition: all 0.35s ease;
}
.popup-box.show,
.popup-box.show .popup {
opacity: 1;
pointer-events: auto;
}
.popup-box.show .popup {
transform: translate(-50%, -50%) scale(1);
}
.popup .content {
border-radius: 8px;
background: #ffffff;
width: calc(100% - 20px);
box-shadow: 0 0 18px rgba(0, 0, 0, 0.12);
}
.content header {
padding: 16px 28px;
border-bottom: 1px solid #bbb;
}
.content header p {
font-size: 21px;
font-weight: 500;
}
.content header i {
color: #9a9898;
cursor: pointer;
font-size: 24px;
}
.content form {
margin: 18px 28px 40px;
}
.content form .row {
margin-bottom: 22px;
}
form .row label {
font-size: 17px;
display: block;
margin-bottom: 7px;
}
form :where(input, textarea) {
height: 52px;
width: 100%;
outline: none;
font-size: 16px;
padding: 0 16px;
border-radius: 5px;
border: 1px solid #aaa;
}
form :where(input, textarea):focus {
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15);
}
form .row textarea {
height: 155px;
resize: none;
padding: 10px 16px;
}
form button {
width: 100%;
height: 52px;
color: #fff;
outline: none;
border: none;
cursor: pointer;
font-size: 17px;
border-radius: 5px;
background: #FF6F61;
}
@media (max-width: 660px) {
.wrapper {
margin: 12px;
gap: 12px;
grid-template-columns: repeat(auto-fill, 100%);
}
.popup-box .popup {
max-width: calc(100% - 12px);
}
.bottom-content .settings i {
font-size: 18px;
}
}
Краткое объяснение:
Фон: Мы установили приятный розовый фон для страницы.
add-box
: Элемент с "+" иконкой для добавления новой заметки.
popup-box
: Всплывающее окно, которое будет отображаться при добавлении/редактировании заметки.
Код стилей доступен в репозитории.
Создайте файл script.js
для добавления функционала приложения. Мы рассмотрим основные функции, необходимые для работы приложения.
const addBox = document.querySelector(".add-box"),
popupBox = document.querySelector(".popup-box"),
popupTitle = popupBox.querySelector("header p"),
closeIcon = popupBox.querySelector("header i"),
titleTag = popupBox.querySelector("input"),
descTag = popupBox.querySelector("textarea"),
addBtn = popupBox.querySelector("button");
// Месяцы на русском языке
const months = ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль",
"Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
// Получаем сохраненные заметки из localStorage, если есть
const notes = JSON.parse(localStorage.getItem("notes") || "[]");
let isUpdate = false, updateId;
// Открываем окно для добавления новой заметки
addBox.addEventListener("click", () => {
popupTitle.innerText = "Добавить новую заметку";
addBtn.innerText = "Добавить заметку";
popupBox.classList.add("show");
document.querySelector("body").style.overflow = "hidden";
if(window.innerWidth > 660) titleTag.focus();
});
// Закрываем окно добавления/редактирования заметки
closeIcon.addEventListener("click", () => {
isUpdate = false;
titleTag.value = descTag.value = "";
popupBox.classList.remove("show");
document.querySelector("body").style.overflow = "auto";
});
// Функция отображения всех заметок
function showNotes() {
if(!notes) return;
document.querySelectorAll(".note").forEach(li => li.remove());
notes.forEach((note, id) => {
let filterDesc = note.description.replaceAll("\n", '<br/>');
let liTag = `<li class="note">
<div class="details">
<p>${note.title}</p>
<span>${filterDesc}</span>
</div>
<div class="bottom-content">
<span>${note.date}</span>
<div class="settings">
<i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i>
<ul class="menu">
<li onclick="updateNote(${id}, '${note.title}', '${filterDesc}')"><i class="uil uil-pen"></i>Редактировать</li>
<li onclick="deleteNote(${id})"><i class="uil uil-trash"></i>Удалить</li>
</ul>
</div>
</div>
</li>`;
addBox.insertAdjacentHTML("afterend", liTag);
});
}
showNotes();
// Показать меню настроек для заметки
function showMenu(elem) {
elem.parentElement.classList.add("show");
document.addEventListener("click", e => {
if(e.target.tagName != "I" || e.target != elem) {
elem.parentElement.classList.remove("show");
}
});
}
// Удалить заметку
function deleteNote(noteId) {
let confirmDel = confirm("Вы уверены, что хотите удалить эту заметку?");
if(!confirmDel) return;
notes.splice(noteId, 1);
localStorage.setItem("notes", JSON.stringify(notes));
showNotes();
}
// Обновить заметку
function updateNote(noteId, title, filterDesc) {
let description = filterDesc.replaceAll('<br/>', '\r\n');
updateId = noteId;
isUpdate = true;
addBox.click();
titleTag.value = title;
descTag.value = description;
popupTitle.innerText = "Обновить заметку";
addBtn.innerText = "Обновить заметку";
}
// Добавление или обновление заметки
addBtn.addEventListener("click", e => {
e.preventDefault();
let title = titleTag.value.trim(),
description = descTag.value.trim();
if(title || description) {
let currentDate = new Date(),
month = months[currentDate.getMonth()],
day = currentDate.getDate(),
year = currentDate.getFullYear();
let noteInfo = {title, description, date: `${month} ${day}, ${year}`}
if(!isUpdate) {
notes.push(noteInfo);
} else {
isUpdate = false;
notes[updateId] = noteInfo;
}
localStorage.setItem("notes", JSON.stringify(notes));
showNotes();
closeIcon.click();
}
});
Подробное объяснение:
addBox
и popupBox
: Эти переменные ссылаются на элементы для добавления новой заметки и всплывающее окно.
Функция открытия формы: При нажатии на "добавить" открывается форма для ввода данных.
Добавление и сохранение заметок: При нажатии на кнопку "Сохранить" данные сохраняются в localStorage
.
Отображение заметок: Все сохраненные заметки отображаются на странице с помощью функции showNotes()
.
Остальная часть кода доступна в репозитории.
Теперь у вас есть полное приложение с заметками на JavaScript! Вы можете скачать исходный код и попробовать улучшить его, добавив новые функции. Удачи в разработке! 🚀
Не нашли нужной статьи?
Напишите нам и ее сделаем!