{}const=>[]async()letfn</>var
JSWeb

Miniaplicación web en JavaScript: aplicación con notas

Una guía paso a paso para crear una miniaplicación web en JavaScript puro. En este tutorial, crearemos una aplicación de notas usando HTML, CSS y JavaScript, y también conectaremos localStorage para guardar datos entre sesiones del navegador.

К

Kodik

Autor

7 min de lectura

¡Hola! 👋 Hoy vamos a crear mini aplicación web en JavaScriptaplicación para notas utilizando HTML, CSS y JavaScript.

Esta aplicación te permitirá añadir, editar y eliminar notas, que se guardarán en localStorage navegador. Esto significa que tus notas no desaparecerán incluso después de recargar la página!

Lo revisaremos cada paso de la creación de la aplicaciónpara que puedas entender cómo funciona y crear tu propia miniaplicación web en JS puro.

¿Listo? ¡Vamos! 🚀

Para obtener el código fuente completo y posiblemente mejoras adicionales, echa un vistazo a nuestro GitHub.


Qué hace nuestra aplicación

Nuestra aplicación de notas permite a los usuarios:

  1. Añadir notas con títulos y descripciones.

  2. Guarda las notas en el navegador para que los datos no se pierdan al recargar la página.

  3. Ver la lista de todas las notas creadas.

  4. Editar notas existentes.

  5. Eliminar notas innecesarias.

¡Ahora vamos a crear!


1. Creación de una estructura HTML

HTML es responsable de la estructura de nuestra aplicación. Primero, crea un archivo index.html con el marcado básico:

<!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>

Breve explicación del código:

  • popup-box: Ventana emergente para crear una nueva nota. Contiene un formulario con campos para el título y la descripción.

  • add-box: Elemento que abre una ventana emergente para añadir una nueva nota.


2. Estilizar con CSS

Crea el archivo style.css para añadir estilos a nuestra aplicación. Estos son los estilos principales que debes conocer:

/* 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;
  }
}

Breve explicación:

  • Fondo: Hemos establecido un bonito fondo rosa para la página.

  • add-box: Elemento con el icono «+» para añadir una nueva nota.

  • popup-box: Ventana emergente que se mostrará al añadir/editar una nota.

El código de estilo está disponible en repositorios.


3. Lógica de la aplicación en JavaScript

Crea un archivo script.js para añadir la funcionalidad de la aplicación. Revisaremos las funciones básicas necesarias para que la aplicación funcione.

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");

// Meses en ruso
const months = ["January", "February", "March", "April", "May", "June", "July",
    "August", "September", "October", "November", "December"];

// Obtenemos las notas guardadas de localStorage, si las hay
const notes = JSON.parse(localStorage.getItem("notes") || "[]");
let isUpdate = false, updateId;

// Abrimos una ventana para añadir una nueva nota
addBox.addEventListener("click", () => {
    popupTitle.innerText = "Add a new note";
    addBtn.innerText = "Add a note";
    popupBox.classList.add("show");
    document.querySelector("body").style.overflow = "hidden";
    if(window.innerWidth > 660) titleTag.focus();
});

// Cerrar la ventana para añadir/editar notas
closeIcon.addEventListener("click", () => {
    isUpdate = false;
    titleTag.value = descTag.value = "";
    popupBox.classList.remove("show");
    document.querySelector("body").style.overflow = "auto";
});

// Función de visualización de todas las notas
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>Edit</li>
                                    <li onclick="deleteNote(${id})"><i class="uil uil-trash"></i>Delete</li>
                                </ ul>
                            </ div>
                        </ div>
                    </ li>`;
        addBox.insertAdjacentHTML("afterend", liTag);
    });
}
showNotes();

// Mostrar el menú de configuración de la nota
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");
        }
    });
}

// Eliminar nota
function deleteNote(noteId) {
    let confirmDel = confirm("Are you sure you want to delete this note?");
    if(!confirmDel) return;
    notes.splice(noteId, 1);
    localStorage.setItem("notes", JSON.stringify(notes));
    showNotes();
}

// Actualizar nota
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 = "Update note";
    addBtn.innerText = "Update note";
}

// Añadir o actualizar una nota
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();
    }
});

Explicación detallada:

  1. addBox y popupBox: Estas variables hacen referencia a los elementos para añadir una nueva nota y una ventana emergente.

  2. Función de apertura de formularios: Al hacer clic en "añadir" se abre un formulario para introducir datos.

  3. Añadir y guardar notas: Al hacer clic en el botón "Guardar", los datos se guardan en localStorage.

  4. Visualización de notas: Todas las notas guardadas se muestran en la página usando la función showNotes().

El resto del código está disponible en repositorios.


Conclusión

¡Ahora tienes una aplicación completa con notas en JavaScript! Puedes descargar el código fuente e intentar mejorarlo añadiendo nuevas funciones. ¡Buena suerte con el desarrollo! 🚀

🎯Deja de postergar

¿Te gustó el artículo?
¡Hora de practicar!

En Kodik no solo lees — escribes código de inmediato. Teoría + práctica = habilidades reales.

Práctica instantánea
🧠IA explica código
🏆Certificado

Sin registro • Sin tarjeta