From 40fc52f00c42b624d4acd6072c8f62240bbf590c Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Thu, 27 Feb 2025 06:56:10 +0100 Subject: [PATCH 1/9] Clase 5 Intermedio | 26/02/2025 Manejo de APIs --- Intermediate/09-apis.js | 171 ++++++++++++++++++++++++++++++ Intermediate/10-apis-exercises.js | 24 +++++ README.md | 11 +- 3 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 Intermediate/09-apis.js create mode 100644 Intermediate/10-apis-exercises.js diff --git a/Intermediate/09-apis.js b/Intermediate/09-apis.js new file mode 100644 index 00000000..c6cec658 --- /dev/null +++ b/Intermediate/09-apis.js @@ -0,0 +1,171 @@ +/* +Clase 5 - Manejo de APIs (26/02/2025) +Vídeo: https://www.twitch.tv/videos/2391820998?t=00h17m25s +*/ + +// Manejo de APIs + +// - APIs REST (HTTP + URLs + JSON) + +// Métodos HTTP: +// - GET +// - POST +// - PUT +// - DELETE + +// Códigos de respuesta HTTP: +// - 200 OK +// - 201 +// - 400 +// - 404 +// - 500 + +// Consumir una API + +// https://jsonplaceholder.typicode.com + +// GET +fetch("https://jsonplaceholder.typicode.com/posts") + .then(response => { + // Transforma la respuesta a JSON + return response.json() + }) + .then(data => { + // Procesa los datos + console.log(data) + }) + .catch(error => { + // Captura errores + console.log("Error", error) + }) + +// Uso de Async/Await + +async function getPosts() { + try { + const response = await fetch("https://jsonplaceholder.typicode.com/posts") + const data = await response.json() + console.log(data) + } catch (error) { + console.log("Error", error) + } +} + +getPosts() + +// Solicitud POST + +async function createPost() { + try { + + const newPost = { + userId: 1, + title: "Este es el título de mi post", + body: "Este es el cuerpo de mi post" + } + + const response = await fetch("https://jsonplaceholder.typicode.com/posts", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(newPost) + }) + + const data = await response.json() + console.log(data) + } catch (error) { + console.log("Error", error) + } +} + +createPost() + +// Herramientas para realizar peticiones HTTP +// - https://postman.com +// - https://apidog.com +// - https://thunderclient.com + +// Manejo de errores + +fetch("https://jsonplaceholder.typicode.com/mouredev") + .then(response => { + if (!response.ok) { + throw Error(`Status HTTP: ${response.status}`) + } + return response.json() + }) + .catch(error => { + console.log("Error", error) + }) + +// Métodos HTTP adicionales +// - PATCH +// - OPTIONS + +async function partialPostUpdate() { + try { + const response = await fetch("https://jsonplaceholder.typicode.com/posts/10", { + method: "PATCH", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ title: "Este es el nuevo título de mi post" }) + }) + + const data = await response.json() + console.log(data) + } catch (error) { + console.log("Error", error) + } +} + +partialPostUpdate() + +// Autenticación mediante API Key + +async function getWeather(city) { + + // https://openweathermap.org + const apiKey = "TU_API_KEY" + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}` + + try { + const response = await fetch(url) + const data = await response.json() + console.log(data) + } catch (error) { + console.log("Error", error) + } +} + +getWeather("Madrid") + +// Otros métodos de Autenticación y Autorización +// - Bearer Tokens +// - JWT + +// Versionado de APIs +// - https://api.example.com/v1/resources +// - https://api.example.com/v2/resources + +// Otras APIs + +async function getPokemon(pokemon) { + + // https://pokeapi.co + const url = `https://pokeapi.co/api/v2/pokemon/${pokemon}` + + try { + const response = await fetch(url) + const data = await response.json() + console.log(`Habilidades de ${data.name}`) + data.abilities.forEach(ability => { + console.log(ability.ability.name) + }) + } catch (error) { + console.log("Error", error) + } +} + +getPokemon("pikachu") \ No newline at end of file diff --git a/Intermediate/10-apis-exercises.js b/Intermediate/10-apis-exercises.js new file mode 100644 index 00000000..d1452bc3 --- /dev/null +++ b/Intermediate/10-apis-exercises.js @@ -0,0 +1,24 @@ +/* +Clase 5 - Manejo de APIs (26/02/2025) +Vídeo: https://www.twitch.tv/videos/2391820998?t=00h17m25s +*/ + +// 1. Realiza una petición GET con fetch() a JSONPlaceholder y muestra en la consola la lista de publicaciones + +// 2. Modifica el ejercicio anterior para que verifique si la respuesta es correcta usando response.ok. Si no lo es, lanza y muestra un error + +// 3. Reescribe el ejercicio 1 usando la sintaxis async/await en lugar de promesas + +// 4. Realiza una petición POST a JSONPlaceholder para crear una nueva publicación. Envía un objeto con propiedades como title o body + +// 5. Utiliza el método PUT para actualizar completamente un recurso (por ejemplo, modificar una publicación) en JSONPlaceholder + +// 6. Realiza una petición PATCH para modificar únicamente uno o dos campos de un recurso existente + +// 7. Envía una solicitud DELETE a la API para borrar un recurso (por ejemplo, una publicación) y verifica la respuesta + +// 8. Crea una función que realice una solicitud GET (la que quieras) a OpenWeatherMap + +// 9. Utiliza la PokéAPI para obtener los datos de un Pokémon concreto, a continuación los detalles de la especie y, finalmente, la cadena evolutiva a partir de la especie + +// 10. Utiliza una herramienta como Postman o Thunder Client para probar diferentes endpoint de una API diff --git a/README.md b/README.md index 3d0fa36b..3706d4fa 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ ### Curso de fundamentos intermedio (continuación del desde cero). Nueva clase cada semana. -#### 🔴 PRÓXIMA CLASE EN DIRECTO: Miércoles 26 de febrero a las 20:00h (España) en [Twitch](https://twitch.tv/mouredev) y [YouTube](https://youtube.com/@mouredev) -#### 🗓️ CONSULTA EL HORARIO POR PAÍS Y CREA UN RECORDATORIO desde [Discord](https://discord.gg/DuE3fHyV?event=1341887890858442772) +#### 🔴 PRÓXIMA CLASE EN DIRECTO: Jueves 6 de marzo a las 20:00h (España) en [Twitch](https://twitch.tv/mouredev) y [YouTube](https://youtube.com/@mouredev) +#### 🗓️ CONSULTA EL HORARIO POR PAÍS Y CREA UN RECORDATORIO desde [Discord](https://discord.gg/63Q2Ts6p?event=1344414401603833886) * Clase 1 [29/01/2025] - Funciones avanzadas * [Vídeo](https://www.twitch.tv/videos/2367024319?t=00h08m45s) @@ -39,6 +39,11 @@ * [Código](./Intermediate/07-async.js) * [Ejericios](./Intermediate/08-async-exercises.js) +* Clase 5 [26/02/2025] - Manejo de APIs + * [Vídeo](https://www.twitch.tv/videos/2391820998?t=00h17m25s) + * [Código](./Intermediate/09-apis.js) + * [Ejericios](./Intermediate/10-apis-exercises.js) + ## Clases en vídeo ### Curso de fundamentos desde cero @@ -107,6 +112,8 @@ * Exploradores: [Chrome](https://www.google.com/intl/es_es/chrome/) | [Brave](https://brave.com/download/) * [Visual Studio Code](https://code.visualstudio.com/) * [Guía de estilo](https://google.github.io/styleguide/jsguide.html) +* Clientes HTTP: [Postman](https://postman.com) | [Apidog](https://apidog.com) | [Thunder Client](https://thunderclient.com) +* APIs: [JSONPlaceholder](https://jsonplaceholder.typicode.com) | [OpenWeather](https://openweathermap.org) | [PokéAPI](https://pokeapi.co) ## Únete al campus de programación de la comunidad From 409007e101d7751bbe5655fd28d9ac80d59fa5fe Mon Sep 17 00:00:00 2001 From: Brais Moure Date: Fri, 7 Mar 2025 09:09:52 +0100 Subject: [PATCH 2/9] Clase 6 Intermedio | 06/03/2025 Manejo del DOM --- Intermediate/11-dom.js | 123 +++++++++++++++++++++++++++++++ Intermediate/12-dom-example.html | 23 ++++++ Intermediate/13-dom-example.js | 11 +++ Intermediate/14-tasklist.html | 18 +++++ Intermediate/15-tasklist.js | 32 ++++++++ Intermediate/16-dom-exercises.js | 24 ++++++ README.md | 11 ++- 7 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 Intermediate/11-dom.js create mode 100644 Intermediate/12-dom-example.html create mode 100644 Intermediate/13-dom-example.js create mode 100644 Intermediate/14-tasklist.html create mode 100644 Intermediate/15-tasklist.js create mode 100644 Intermediate/16-dom-exercises.js diff --git a/Intermediate/11-dom.js b/Intermediate/11-dom.js new file mode 100644 index 00000000..a668a51e --- /dev/null +++ b/Intermediate/11-dom.js @@ -0,0 +1,123 @@ +/* +Clase 6 - Manejo del DOM (06/03/2025) +Vídeo: https://www.twitch.tv/videos/2398786900?t=00h11m52s +*/ + +// Manejo del DOM (Document Object Model) + +console.log(document) + +// - Selección de elementos + +// Métodos básicos (selector HTML) + +const myElementById = document.getElementById("id") + +const myElementsByClass = document.getElementsByClassName("class") + +const myElementsByTag = document.getElementsByTagName("tag") + +// Métodos más modernos (selector CSS) + +document.querySelector(".paragraph") +document.querySelectorAll(".paragraph") + +// - Manipulación de elementos + +const title = document.getElementById("title") +title.textContent = "Hola JavaScript" + +const container = document.querySelector(".container") +container.innerHTML = "

Esto es un nuevo párrafo

" + +// - Modificación de atributos + +// Obtención del atributo +const link = document.querySelector("a") +const url = link.getAttribute("href") + +// Establecimiento del atributo +link.setAttribute("href", "https://example.com") + +// Comprobación de atributo +const hasTarget = link.hasAttribute("target") + +// Eliminación de atributos +link.removeAttribute("target") + +// - Interacción con clases CSS + +const box = document.querySelector(".box") +box.classList.add("selected") +box.classList.remove("selected") +box.classList.toggle("selected") + +const button = document.querySelector("button") +button.style.backgroundColor = "blue" +button.style.color = "white" +button.style.padding = "10px" + +// - Creación y eliminación de elementos + +// Creación + +const newParagraph = document.createElement("p") +newParagraph.textContent = "Este es un nuevo párrafo creado desde JS" +newParagraph.style.padding = "8px" + +container.appendChild(newParagraph) + +const itemsList = document.querySelector("ul") +const newItem = document.createElement("li") +newItem.textContent = "Nuevo elemento" + +// Inserción en un lugar concreto + +const secondItem = itemsList.children[1] +itemsList.insertBefore(newItem, secondItem) + +itemsList.append(newItem) +itemsList.prepend(newItem) +secondItem.before(newItem) +secondItem.after(newItem) + +// Eliminación + +newParagraph.remove() + +// Eliminación tradicional + +const parent = newParagraph.parentElement +parent.removeChild(newParagraph) + +// - Elementos del DOM + +function showMsg() { + alert("Clic!") +} + +const sendButton = document.querySelector("#send") +sendButton.addEventListener("click", showMsg) + +sendButton.addEventListener("click", () => { + alert("Clic con una arrow function!") +}) + +// Eventos comunes + +document.addEventListener("DOMContentLoader", () => { + console.log("El DOM está completamente cargado") +}) + +sendButton.addEventListener("mouseenter", () => { + sendButton.style.backgroundColor = "green" +}) + +sendButton.addEventListener("mouseleave", () => { + sendButton.style.backgroundColor = "blue" +}) + +const form = document.querySelector("form") +form.addEventListener("submit", (event) => { + // Código +}) \ No newline at end of file diff --git a/Intermediate/12-dom-example.html b/Intermediate/12-dom-example.html new file mode 100644 index 00000000..471e1042 --- /dev/null +++ b/Intermediate/12-dom-example.html @@ -0,0 +1,23 @@ + + + + + + HTML de ejemplo + + +

Mi título

+ + + + + \ No newline at end of file diff --git a/Intermediate/13-dom-example.js b/Intermediate/13-dom-example.js new file mode 100644 index 00000000..a325bf8d --- /dev/null +++ b/Intermediate/13-dom-example.js @@ -0,0 +1,11 @@ +/* +Clase 6 - Manejo del DOM (06/03/2025) +Vídeo: https://www.twitch.tv/videos/2398786900?t=00h11m52s +*/ + +console.log(document) + +const myH1 = document.querySelector("h1") +console.log(myH1) + +myH1.textContent = "Mi nuevo título" \ No newline at end of file diff --git a/Intermediate/14-tasklist.html b/Intermediate/14-tasklist.html new file mode 100644 index 00000000..186c58d9 --- /dev/null +++ b/Intermediate/14-tasklist.html @@ -0,0 +1,18 @@ + + + + + + Lista de tareas + + +

Mis tareas

+ + + + + + \ No newline at end of file diff --git a/Intermediate/15-tasklist.js b/Intermediate/15-tasklist.js new file mode 100644 index 00000000..85e3c014 --- /dev/null +++ b/Intermediate/15-tasklist.js @@ -0,0 +1,32 @@ +/* +Clase 6 - Manejo del DOM (06/03/2025) +Vídeo: https://www.twitch.tv/videos/2398786900?t=00h11m52s +*/ + +const text = document.getElementById("text") +const button = document.getElementById("button") +const list = document.getElementById("list") + +function addTask() { + + if (text.value === "") return + + const newElement = document.createElement("li") + newElement.textContent = text.value + + newElement.addEventListener("click", () => { + newElement.remove() + }) + + list.appendChild(newElement) + + text.value = "" +} + +button.addEventListener("click", addTask) + +text.addEventListener("keypress", (event) => { + if (event.key === "Enter") { + addTask() + } +}) \ No newline at end of file diff --git a/Intermediate/16-dom-exercises.js b/Intermediate/16-dom-exercises.js new file mode 100644 index 00000000..b6a9cd7f --- /dev/null +++ b/Intermediate/16-dom-exercises.js @@ -0,0 +1,24 @@ +/* +Clase 6 - Manejo del DOM (06/03/2025) +Vídeo: https://www.twitch.tv/videos/2398786900?t=00h11m52s +*/ + +// 1. Crea un elemento (por ejemplo, un

) y cambia su contenido a "¡Hola Mundo!"" al cargar la página + +// 2. Inserta una imagen con id="myImage" y cambia su atributo src a otra URL + +// 3. Crea un
sin clases y agrega la clase resaltado cuando se cargue la página + +// 4. Crea un párrafo con id="paragraph" y cambia su color de texto a azul + +// 5. Agrega un botón que, al hacer clic, cree un nuevo elemento
  • con el texto "Nuevo elemento y lo agregue a una lista