Artículo anterior: Curso de JavaScript |
Introducción a los objetos en el proyecto JavaScript
En este artículo final de este curso, aprenderemos cómo hacer una aplicación javascript simple donde podemos agregar tareas, eliminar tareas y editarlas también. Se ha utilizado JavaScript puro (vainilla) y también utilizaremos mucho la manipulación DOM, por lo que uno de los requisitos previos principales es HTML | DOM .
Estructura del proyecto
index.html
estilos.css
list.js
- índice.html
HTML
<!DOCTYPE html> <html> <head> <title>Task Tracker</title> <link rel="stylesheet" href="styles.css" type="text/css" media="screen" charset="utf-8"> </head> <body> <div class="container"> <p> <label for="new-task" class="middle">Add Task</label> <input id="new-task" type="text"><button>Add Task</button> </p> <h3 class="middle">Todo</h3> <ul id="incomplete-tasks"> </ul> <h3 class="middle">Completed Tasks</h3> <ul id="completed-tasks"> </ul> </div> <script type="text/javascript" src="list.js"></script> </body> </html>
Explicación:
El código HTML anterior contiene etiquetas de lista simples y un campo de texto que completaremos con texto cuando agreguemos o eliminemos tareas. Se asignan ciertas clases que utilizamos al obtener ese elemento en particular mediante DOM o al diseñarlo dentro del archivo styles.css. Todo el contenido anterior está dentro de un div con clase ‘contenedor’ que tiene su propio estilo y atributos.
- estilos.css
CSS
/* Basic Style */ body { background: #ecf0f1; color: #333; font-family: Lato, sans-serif; } .container { display: block; width: 500px; margin: 50px auto 0; } ul { margin: 0; padding: 0; } li * { float: left; } li, h3 { clear: both; list-style: none; } input, button { outline: none; } button { background: none; border: 0px; color: #888; font-size: 15px; width: 100px; margin: 10px 0 0; font-family: Lato, sans-serif; cursor: pointer; } button:hover { color: #333; } /* Heading */ h3, label[for='new-task'] { color: #333; font-weight: 700; font-size: 15px; border-bottom: 2px solid #333; padding: 30px 0 10px; margin: 0; text-transform: uppercase; } input[type="text"] { margin: 0; font-size: 18px; line-height: 18px; height: 18px; padding: 10px; border: 1px solid #ddd; background: #fff; border-radius: 6px; font-family: Lato, sans-serif; color: #888; } input[type="text"]:focus { color: #333; } .middle { text-align: center; } /* New Task */ label[for='new-task'] { display: block; margin: 0 0 20px; } input#new-task { float: right; width: 318px; } p>button:hover { color: #0FC57C; } /* Task list */ li { overflow: hidden; padding: 20px 0; border-bottom: 1px solid #eee; } li>input[type="checkbox"] { margin: 0 10px; position: relative; top: 15px; } li>label { font-size: 18px; line-height: 40px; width: 237px; padding: 0 0 0 11px; } li>input[type="text"] { width: 226px; } li>.delete:hover { color: #CF2323; } /* Completed */ #completed-tasks label { text-decoration: line-through; color: #888; } /* Edit Task */ ul li input[type=text] { display: none; } ul li.editMode input[type=text] { display: block; } ul li.editMode label { display: none; }
Nota: Los archivos HTML y CSS anteriores son principalmente para la parte de presentación.
- lista.js
Javascript
// Add a new task. let taskInput = document.getElementById("new-task"); // first button let addButton = document.getElementsByTagName("button")[0]; // ul of #incomplete-tasks let incompleteTaskHolder = document.getElementById("incomplete-tasks"); // completed-tasks let completedTasksHolder = document.getElementById("completed-tasks"); /*---- Part 1 ----*/ // function to create new task item let createNewTaskElement = function (taskString) { let listItem = document.createElement("li"); // input (checkbox) let checkBox = document.createElement("input"); // checkbox // label let label = document.createElement("label"); // label // input (text) let editInput = document.createElement("input"); // text // button.edit let editButton = document.createElement("button"); // edit button // button.delete let deleteButton = document.createElement("button"); // delete button label.innerText = taskString; // Each elements, needs appending checkBox.type = "checkbox"; editInput.type = "text"; // innerText encodes special characters, HTML does not. editButton.innerText = "Edit"; editButton.className = "edit"; deleteButton.innerText = "Delete"; deleteButton.className = "delete"; // and appending. listItem.appendChild(checkBox); listItem.appendChild(label); listItem.appendChild(editInput); listItem.appendChild(editButton); listItem.appendChild(deleteButton); return listItem; } /*---- Part 2 ----*/ let addTask = function () { console.log("Add Task..."); let listItem = createNewTaskElement(taskInput.value); if (taskInput.value == "") { return; } // Append listItem to incompleteTaskHolder incompleteTaskHolder.appendChild(listItem); bindTaskEvents(listItem, taskCompleted); taskInput.value = ""; } /*---- Part 3 ----*/ let editTask = function () { console.log("Edit Task..."); console.log("Change 'edit' to 'save'"); let listItem = this.parentNode; let editInput = listItem.querySelector('input[type=text]'); let label = listItem.querySelector("label"); let containsClass = listItem.classList.contains("editMode"); // If class of the parent is .editmode if (containsClass) { label.innerText = editInput.value; } else { editInput.value = label.innerText; } listItem.classList.toggle("editMode"); } /*---- Part 4 ----*/ let deleteTask = function () { console.log("Delete Task..."); let listItem = this.parentNode; let ul = listItem.parentNode; // Remove the parent list item from the ul. ul.removeChild(listItem); } /*---- Part 5 ----*/ let taskCompleted = function () { console.log("Complete Task..."); // Append the task list item to the #completed-tasks let listItem = this.parentNode; completedTasksHolder.appendChild(listItem); bindTaskEvents(listItem, taskIncomplete); } /*---- Part 6 ----*/ let taskIncomplete = function () { console.log("Incomplete Task..."); // Mark task as incomplete. let listItem = this.parentNode; incompleteTaskHolder.appendChild(listItem); bindTaskEvents(listItem, taskCompleted); } /*---- Part 7 ----*/ addButton.onclick = addTask; addButton.addEventListener("click", addTask); let bindTaskEvents = function (taskListItem, checkBoxEventHandler) { console.log("bind list item events"); // select ListItems children let checkBox = taskListItem.querySelector("input[type=checkbox]"); let editButton = taskListItem.querySelector("button.edit"); let deleteButton = taskListItem.querySelector("button.delete"); // Bind editTask to edit button. editButton.onclick = editTask; // Bind deleteTask to delete button. deleteButton.onclick = deleteTask; // Bind taskCompleted to checkBoxEventHandler. checkBox.onchange = checkBoxEventHandler; } /*---- Part 8 ----*/ // cycle over incompleteTaskHolder ul list items // for each list item for (let i = 0; i < incompleteTaskHolder.children.length; i++) { // bind events to list items children(tasksCompleted) bindTaskEvents(incompleteTaskHolder.children[i], taskCompleted); } // cycle over completedTasksHolder ul list items for (let i = 0; i < completedTasksHolder.children.length; i++) { // bind events to list items children(tasksIncompleted) bindTaskEvents(completedTasksHolder.children[i], taskIncomplete); }
Explicación
- Parte 1
- La forma en que funciona esta función es que toma la ‘string de entrada’, es decir, el texto que pasamos dentro del campo de texto HTML como una tarea y luego crea varios elementos usando las propiedades DOM y les agrega clases específicas. Después de agregar, insertamos todos los elementos dentro de la lista como listItems.
- Parte 2
- Esta función addTask se llama cuando hacemos clic en el botón ‘addButton’ (línea 115) y luego dentro creamos un elemento de lista con el valor que ingresó el usuario y luego verificamos el valor, ya que no debe ser una string vacía, simplemente agregamos el valor anterior dentro de ‘inputTaskHolder’ y finalmente establecer el valor dentro de él como una string vacía antes de llamar a ‘bindFunction’.
- Esta función addTask se llama cuando hacemos clic en el botón ‘addButton’ (línea 115) y luego dentro creamos un elemento de lista con el valor que ingresó el usuario y luego verificamos el valor, ya que no debe ser una string vacía, simplemente agregamos el valor anterior dentro de ‘inputTaskHolder’ y finalmente establecer el valor dentro de él como una string vacía antes de llamar a ‘bindFunction’.
- parte 3
- Esta función de código se usa para editar una tarea existente y lo hacemos haciendo un seguimiento del Node principal y luego un simple if-else verifica si se hace clic en el botón ‘editMode’ o no, si se hace clic, simplemente asigne el valor de la etiqueta texto interno al valor dentro de editInput, si no, viceversa. Luego, después de editar, alternamos el valor de ‘editMode’ como lo hemos editado.
- Esta función de código se usa para editar una tarea existente y lo hacemos haciendo un seguimiento del Node principal y luego un simple if-else verifica si se hace clic en el botón ‘editMode’ o no, si se hace clic, simplemente asigne el valor de la etiqueta texto interno al valor dentro de editInput, si no, viceversa. Luego, después de editar, alternamos el valor de ‘editMode’ como lo hemos editado.
- parte 4
- En esta parte eliminamos una tarea y la forma en que lo hacemos haciendo uso del Node principal del Node actual y luego almacenando el principal del Node principal y luego simplemente eliminando el secundario de este Node.
- En esta parte eliminamos una tarea y la forma en que lo hacemos haciendo uso del Node principal del Node actual y luego almacenando el principal del Node principal y luego simplemente eliminando el secundario de este Node.
- Parte 5
- En esta función, marcamos la tarea como completa simplemente agregando el elemento secundario del Node principal dentro del elemento completeTaskHolder y luego llamando a bindFunction.
- En esta función, marcamos la tarea como completa simplemente agregando el elemento secundario del Node principal dentro del elemento completeTaskHolder y luego llamando a bindFunction.
- parte 6
- En esta función, marcamos la tarea como incompleta simplemente agregando el elemento secundario del Node principal dentro del elemento inCompleteTaskHolder y luego llamando a bindFunction.
- En esta función, marcamos la tarea como incompleta simplemente agregando el elemento secundario del Node principal dentro del elemento inCompleteTaskHolder y luego llamando a bindFunction.
- Parte 7
- En esta parte llamamos BindFunction donde respondemos a las diversas actividades de interacción del usuario y hacemos que funcionen varios botones.
- En esta parte llamamos BindFunction donde respondemos a las diversas actividades de interacción del usuario y hacemos que funcionen varios botones.
- parte 8
- En esta sección final, iteramos sobre varias partes que vinculan a los niños con la ayuda del bucle for dentro del elemento TaskHolder incompleto y completo.
Salida: (Antes de agregar cualquier tarea)
Salida: (después de agregar la tarea)
Salida: (después de completar la tarea)
Artículo siguiente: Curso de JavaScript | Cuestionario de práctica-3