Aplicación web de notas, crea la tuya propia de forma rápida

Una vez más aquí. Hoy vengo a dejar un pequeño y rápido artículo en el que veremos como crear una aplicación web de notas utilizando HTML, CSS y JavaScript. Este tipo de aplicaciones yo las utilizo habitualmente, por aquello de no olvidarme de ideas que se me van ocurriendo a lo largo del día. Por eso, y esperando que a alguien más les resulte útil, veremos como crear una aplicación propia, para no depender de nadie a la hora de tomar notas.

En esta sencilla aplicación de notas que vamos a crear, los usuarios podremos añadir, editar o eliminar fácilmente las notas que tomemos. Gracias a JavaScript, estas notas se van a guardar en el almacenamiento local del navegador, por lo que no durarán eternamente, y se eliminarán al cerrar el navegador.

Un vistazo rápido a las funcionalidades de la aplicación

Como decía líneas más arriba, esta aplicación se ha construido HTML, CSS y JavaScript. Para iniciar la aplicación bastará con hacer clic sobre el archivo index.html que vamos a crear. Cuando se abra el navegador, veremos algo parecido a lo siguiente.

Para añadir nuevas notas, basta con hacer clic sobre el icono + que se puede ver en el primer cuadro blanco. Esto hará que se abra una ventana en la que podremos añadir una nueva nota.

Una vez que tengamos escrito el título y la descripción de nuestra nota, basta con pulsar el botón «Añadir nota». Esto hará que aparezca automáticamente la nota que acabamos de crear en la pantalla.

Todas las notas creadas podremos editarlas y borrarlas. Para hacer esto, no tendremos más que hacer clic en el botón que tiene cada una de las notas en la parte inferior derecha.

Si seleccionamos la opción «Borrar«, tendremos que confirmar que queremos eliminar la nota en cuestión. Si hacemos clic sobre la opción «Editar«, aparecerá en pantalla una ventana similar a la de crear nota, en la que podremos editar todos los datos de nuestra nota.

Esta acción actualizará también la hora y la fecha, que aparece en cada una de las notas, en la parte inferior izquierda.

Y bueno, esto es todo lo que hace esta aplicación web de notas. Llegados a este punto, vamos a ver el código fuente con el que podemos crear la aplicación.

Código fuente de la aplicación web de notas

Para crear esta aplicación de notas en JavaScript, solo necesitaremos tres archivos: uno HTML, otro CSS y otro JavaScript. Después de crear los archivos, tan solo es necesario pegar los siguientes códigos en su archivo correspondiente.

Archivo index.html

Como decíamos, el primer archivo a crear será el que tiene la extensión HTML, con el nombre index.html. Dentro no hay más que pegar el siguiente código.

<!DOCTYPE html>

<html lang="es">
  <head>
    <meta charset="utf-8"/>  
    <title>Nota-Ría</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="texto">CREA TUS NOTAS</div>

    <div class="popup-box">
      <div class="popup">
        <div class="content">
          <header>
            <p></p>
            <i class="uil uil-times"></i>
          </header>
          <!--Formulario para crear la nota-->
          <form action="#">
            <div class="row title">
              <label for="Title">Título</label>
              <input type="text" id="Title" spellcheck="false">
            </div>
            <div class="row description">
              <label for="Description">Descripción</label>
              <textarea id="Description" spellcheck="false"></textarea>
            </div>
            <button>Añadir nota</button>
          </form>
        </div>
      </div>
    </div>
    <!--Botón para añadir notas-->
    <div class="wrapper">
      <li class="add-box" onclick="showPopup()">
        <div class="icon"><i class="uil uil-plus"></i></div>
        <p>Añadir nota</p>
      </li>
    </div>
    <div class="note-container">
      
    </div>
    <footer>
      entreunosyceros.net - 2023
    </footer>
    <script src="script.js"></script>
  </body>
</html>

Archivo style.css

En segundo lugar, vamos a crear el archivo CSS con el nombre de style.css. Dentro pegaremos el siguiente código para darle los estilos necesarios a nuestra aplicación:

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Comic Sans MS', sans-serif;
}
body{
  background-color:#000000;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
::selection{
  color: #fff;
  background: #618cf8;
}
/*Texto fluorescente*/
.texto {
  display: inline-block;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  padding: 10px;
  border: none;
  font: normal 48px/normal "Warnes", Helvetica, sans-serif;
  color: rgba(255,255,255,1);
  text-decoration: normal;
  text-align: center;
  -o-text-overflow: clip;
  text-overflow: clip;
  white-space: pre;
  text-shadow: 0 0 10px rgba(255,255,255,1) , 0 0 20px rgba(255,255,255,1) , 0 0 30px rgba(255,255,255,1) , 0 0 40px #ff0000 , 0 0 70px #ff0000 , 0 0 80px #ff0040 , 0 0 100px #ff00de ;
  -webkit-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1);
  -moz-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1);
  -o-transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1);
  transition: all 200ms cubic-bezier(0.42, 0, 0.58, 1);
  width: 100%;
  margin-top:1%;
}

.texto:hover {
  text-shadow: 0 0 10px rgba(255,255,255,1) , 0 0 20px rgba(255,255,255,1) , 0 0 30px rgba(255,255,255,1) , 0 0 40px #00ffff , 0 0 70px #00ffff , 0 0 80px #00ffff , 0 0 100px #00ffff ;
}
.wrapper{
  margin: 50px;
  display: grid;
  gap: 25px;
  grid-template-columns: repeat(auto-fill, 265px);
}
.wrapper li{
  height: 250px;
  list-style: none;
  border-radius: 5px;
  padding: 15px 20px 20px;
  background: #fff;
  box-shadow: 0px 0px 10px 0px #333 inset;
}
.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: 78px;
  width: 78px;
  color: #c300ff;
  font-size: 40px;
  border-radius: 50%;
  justify-content: center;
  border: 2px dashed #646464;
}
.add-box p{
  color: #e788ff;
  font-weight: 500;
  margin-top: 20px;
}
.note{
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.note .details{
  max-height: 165px;
  overflow-y: auto;
}
.note .details::-webkit-scrollbar,
.popup textarea::-webkit-scrollbar{
  width: 0;
}
.note .details:hover::-webkit-scrollbar,
.popup textarea:hover::-webkit-scrollbar{
  width: 5px;
}
.note .details:hover::-webkit-scrollbar-track,
.popup textarea:hover::-webkit-scrollbar-track{
  background: #f1f1f1;
  border-radius: 25px;
}
.note .details:hover::-webkit-scrollbar-thumb,
.popup textarea:hover::-webkit-scrollbar-thumb{
  background: #e6e6e6;
  border-radius: 25px;
}
.note p{
  font-size: 22px;
  font-weight: 500;
}
.note span{
  display: block;
  color: #575757;
  font-size: 16px;
  margin-top: 5px;
}
.note .bottom-content{
  padding-top: 10px;
  border-top: 1px solid #ccc;
}
.bottom-content span{
  color: #6D6D6D;
  font-size: 14px;
}
.bottom-content .settings{
  position: relative;
}
.bottom-content .settings i{
  color: #6D6D6D;
  cursor: pointer;
  font-size: 15px;
}
.settings .menu{
  z-index: 1;
  bottom: 0;
  right: -5px;
  padding: 5px 0;
  background: #fff;
  position: absolute;
  border-radius: 4px;
  transform: scale(0);
  transform-origin: bottom right;
  box-shadow: 0 0 6px rgba(0,0,0,0.15);
  transition: transform 0.2s ease;
}
.settings.show .menu{
  transform: scale(1);
}
.settings .menu li{
  height: 25px;
  font-size: 16px;
  margin-bottom: 2px;
  padding: 17px 15px;
  cursor: pointer;
  box-shadow: none;
  border-radius: 0;
  justify-content: flex-start;
}
.menu li:last-child{
  margin-bottom: 0;
}
.menu li:hover{
  background: #f5f5f5;
}
.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.4);
}
.popup-box .popup{
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: 100%;
  max-width: 400px;
  justify-content: center;
  transform: translate(-50%, -50%) scale(0.95);
}
.popup-box, .popup{
  opacity: 0;
  pointer-events: none;
  transition: all 0.25s 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: 5px;
  background: #fff;
  width: calc(100% - 15px);
  box-shadow: 0 0 15px rgba(0,0,0,0.1);
}
.content header{
  padding: 15px 25px;
  border-bottom: 1px solid #ccc;
}
.content header p{
  font-size: 20px;
  font-weight: 500;
}
.content header i{
  color: #8b8989;
  cursor: pointer;
  font-size: 23px;
}
.content form{
  margin: 15px 25px 35px;
}
.content form .row{
  margin-bottom: 20px;
}
form .row label{
  font-size: 18px;
  display: block;
  margin-bottom: 6px;
}
form :where(input, textarea){
  height: 50px;
  width: 100%;
  outline: none;
  font-size: 17px;
  padding: 0 15px;
  border-radius: 4px;
  border: 1px solid #999;
}
form :where(input, textarea):focus{
  box-shadow: 0 2px 4px rgba(0,0,0,0.11);
}
form .row textarea{
  height: 150px;
  resize: none;
  padding: 8px 15px;
}
form button{
  width: 100%;
  height: 50px;
  color: #fff;
  outline: none;
  border: none;
  cursor: pointer;
  font-size: 17px;
  border-radius: 4px;
  background: #d06af8;
}

@media (max-width: 660px){
  .wrapper{
    margin: 15px;
    gap: 15px;
    grid-template-columns: repeat(auto-fill, 100%);
  }
  .popup-box .popup{
    max-width: calc(100% - 15px);
  }
  .bottom-content .settings i{
    font-size: 17px;
  }
}

Archivo script.js

Por último crearemos un archivo JavaScript con el nombre script.js, en el que pegaremos el siguiente código. Este servirá para darle toda la funcionalidad a la aplicación web para notas.

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 = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio",
              "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
const notes = JSON.parse(localStorage.getItem("notes") || "[]");
let isUpdate = false, updateId;

//Se utiliza para abrir una ventana emergente
addBox.addEventListener("click", () => {
    //Utilizamos el método "innerText" para establecer el texto del elemento "popupTitle" en "Añadir nueva nota".
    popupTitle.innerText = "Añadir nueva nota";
    //Utilizamos el método "innerText" para establecer el texto del elemento "addBtn" en "Añadir nota".
    addBtn.innerText = "Añadir nota";
    //Utilizaremos el método "classList.add" para agregar la clase "show" al elemento "popupBox". 
    popupBox.classList.add("show");
    //Utiliza el método "querySelector" para seleccionar el elemento "body" y utiliza el método 
    //"style" para establecer el estilo "overflow" en "hidden". 
    document.querySelector("body").style.overflow = "hidden";
    //Verificamos si el ancho de la ventana es mayor a 660 px, si es así, se activa el evento "focus" en el elemento "titleTag".
    if(window.innerWidth > 660) titleTag.focus();
});

//Se activa al hacer clic en el icono de cierre, y limpia los campos de entrada, 
//cierra la ventana emergente, y habilita el desplazamiento en la página
closeIcon.addEventListener("click", () => {
    isUpdate = false;
    //Limpia los valores de los elementos "titleTag" y "descTag"
    titleTag.value = descTag.value = "";
    //Oculta una ventana emergente o una caja de diálogo en la página.
    popupBox.classList.remove("show");
    //Habilitar o deshabilitar el desplazamiento en la página.
    document.querySelector("body").style.overflow = "auto";
});

/*esta función se encarga de mostrar las notas existentes en la página, elimina las notas existentes en la página, 
y agrega las notas existentes en la página con los datos de la matriz "notes" en un formato de lista.
Además, tiene acceso a funciones como updateNote() y deleteNote() para actualizar y eliminar notas respectivamente.*/

function showNotes() {
    //Comprueba si notes tiene algún valor
    if(!notes) return;
    //seleccionar todos los elementos con la clase "note" y utiliza un "forEach" para eliminar cada uno de ellos.
    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} - ${note.hour}</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>Editar</li>
                                    <li onclick="deleteNote(${id})"><i class="uil uil-trash"></i>Borrar</li>
                                </ul>
                            </div>
                        </div>
                    </li>`;
        addBox.insertAdjacentHTML("afterend", liTag);
    });
}
showNotes();

//Se activa al hacer clic en un elemento específico (elem).
//Esta función se utiliza para mostrar un menú u otro contenido de la interfaz de usuario al 
//hacer clic en un icono o botón específico
function showMenu(elem) {
    /*Agrega la clase "show" al elemento padre del elemento "elem" al hacer clic en "elem". 
    Esto hará que el elemento padre se muestre en la pantalla.*/
    elem.parentElement.classList.add("show");
    //Agrega un evento "click"
    document.addEventListener("click", e => {
        /* verificar si el elemento clickeado es diferente de "elem" o si su etiqueta es 
        diferente de "I". Si se cumple esta condición, la clase "show" se elimina del elemento padre de "elem", 
        haciendo que el elemento padre desaparezca de la pantalla.*/
        if(e.target.tagName != "I" || e.target != elem) {
            elem.parentElement.classList.remove("show");
        }
    });
}

/*Este código es una función JavaScript llamada "deleteNote" que se utiliza para eliminar una nota existente*/
function deleteNote(noteId) {
    //Muestra una ventana de confirmación
    let confirmDel = confirm("¿Estás seguro de que quieres eliminar esta nota?");
    if(!confirmDel) return;
    /*Se utiliza el método "splice" para eliminar la nota correspondiente del arreglo "notes" 
    y luego se guarda el arreglo actualizado en el almacenamiento local del navegador utilizando 
    el método "setItem" de LocalStorage.*/
    notes.splice(noteId, 1);
    localStorage.setItem("notes", JSON.stringify(notes));
    //Actualiza la interfaz de usuario y mostrar las notas actualizadas
    showNotes();
}

/*Se utiliza para actualizar una nota existente en una aplicación web.*/
function updateNote(noteId, title, filterDesc) {
    /** reemplaza todas las etiquetas "<br/>" con saltos de línea en la 
     * variable "filterDesc" y luego asigna los valores de "noteId", "title", 
     * y "filterDesc" a las variables correspondientes en el código.*/
    let description = filterDesc.replaceAll('<br/>', '\r\n');
    updateId = noteId;
    isUpdate = true;
    addBox.click();
    /*Cambia el texto del botón y del título en la interfaz de usuario*/
    titleTag.value = title;
    descTag.value = description;
    popupTitle.innerText = "Actualizar la nota";
    addBtn.innerText = "Actualizar Nota";
}

/* Manejador de eventos para el evento "click" del botón "addBtn". 
Cuando se hace clic en el botón, se ejecuta una función anónima que tiene como objetivo agregar o actualizar una nota.*/

addBtn.addEventListener("click", e => {
    //utilizamos el método "preventDefault()" para evitar que el botón envíe un formulario o refresque la página.
    e.preventDefault();
    // Se obtienen el valor de los elementos "titleTag" y "descTag" y se eliminan los espacios en blanco al inicio 
    //y al final de cada uno, se almacenan en las variables "title" y "description" respectivamente.
    let title = titleTag.value.trim(),
    description = descTag.value.trim();

    /* Se verifica si alguna de las variables "title" o "description" tiene un valor, si es así, 
    se crea un objeto "noteInfo" con las propiedades "title", "description" y "date", donde "date" es una cadena que contiene la fecha actual.*/
    if(title || description) {
        let currentDate = new Date(),
        month = months[currentDate.getMonth()],
        day = currentDate.getDate(),
        year = currentDate.getFullYear(),
        hour = currentDate.getHours() + ':' + currentDate.getMinutes();


        let noteInfo = {title, description, date: `${day} ${month}, ${year}`, hour}
        /*si la variable global "isUpdate" es falsa, si es así, se agrega el objeto "noteInfo" al arreglo "notes", 
        si no se actualiza el elemento del arreglo "notes" en la posición "updateId" con el objeto "noteInfo"*/
        if(!isUpdate) {
            notes.push(noteInfo);
        } else {
            isUpdate = false;
            notes[updateId] = noteInfo;
        }
        localStorage.setItem("notes", JSON.stringify(notes));
        showNotes();
        closeIcon.click();
    }
});

Estos archivos se han colocado todos dentro de la misma carpeta. Y eso es todo. Ya tienes creada una aplicación web de notas, creada con HTML, CSS y JavaScript. Si quieres ver este ejemplo funcionando, solo tienes que seguir el siguiente link.

Post relacionados

Recetario web, crea el tuyo y ten tus recetas de cocina a mano

Registro de transacciones exportando a Excel utilizando PHP y MySQL

Aplicación del tiempo. Crea la tuya con la API de openweathermap

WordPress › Error

Ha habido un error crítico en esta web.

Aprende más sobre el diagnóstico de WordPress.