<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Códice | Entradas sobre «javascript»</title><description>Feed RSS de publicaciones etiquetadas con javascript</description><link>https://javguerra.github.io/</link><item><title>Fizz buzz</title><link>https://javguerra.github.io/blog/fizzbuzz</link><guid isPermaLink="true">https://javguerra.github.io/blog/fizzbuzz</guid><description>Prueba de programación</description><pubDate>Fri, 22 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/code.BoBme8u9_ZyVCnB.webp&quot; alt=&quot;Programación&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#algoritmia&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;«Fizz buzz» es un ejercicio que habitualmente se usa como prueba para la selección de candidatos en programación. Su origen es un &lt;a href=&quot;https://en.wikipedia.org/wiki/Fizz_buzz&quot;&gt;juego de niños&lt;/a&gt; para aprender a dividir.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Escribir un programa que muestre en pantalla los números del 1 al 100, sustituyendo los múltiplos de 3 por la palabra “fizz”, los múltiplos de 5 por “buzz” y los múltiplos de ambos, es decir, los múltiplos de 3 y 5 (o de 15), por la palabra “fizzbuzz”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Este simple enunciado encierra toda una gama de posibilidades en su algoritmo de resolución, y en él es de importancia tanto la rapidez con la que se resuelve el problema como la optimización (u originalidad) del código.&lt;/p&gt;
&lt;p&gt;Esta es mi propuesta de resolución en JavaScript.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;fizz&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;buzz&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  result.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Básicamente el programa comprueba en bucle si cada número del 1 al 100 es divisible por 3 ó por 5. Si lo es, guarda  «fizz», «buzz» o «fizzbuzz» en el caso de ser divisible por los dos (3 y 5). Si no lo es, guarda el número que estoy evaluando y pasa al siguiente número.&lt;/p&gt;
&lt;p&gt;Esta es una versión que además de correcta, es muy legible. Pero si quisiéramos hacer una versión al estilo funcional, por ejemplo para usarla en React, podríamos emplear map.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Array&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;keys&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; n&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;fizz&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;buzz&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;¿Crees que puede optimizarse más?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/retos-programacion&quot;&gt;Ver el código de este y otros retos de programación en GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/code.BoBme8u9_ZyVCnB.webp"/><category>código</category><category>javascript</category><category>algoritmia</category><author>JavGuerra</author></item><item><title>Bootcamp Beca Santander</title><link>https://javguerra.github.io/blog/beca-santander-fswd</link><guid isPermaLink="true">https://javguerra.github.io/blog/beca-santander-fswd</guid><description>Programa digital reskilling Desarrollo Web Full Stack - Fundación Universia - Indra</description><pubDate>Sat, 23 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/beca-santander-fswd.HOVXfGZT_Z2wu3mz.webp&quot; alt=&quot;Beca&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#formación&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#programación&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;El pasado 9 de marzo fui informado de que había sido seleccionado para cursar el Bootcamp de Desarrollo Web Full Stack que &lt;a href=&quot;https://www.becas-santander.com/es/index.html&quot;&gt;Becas Santander&lt;/a&gt; lleva a cabo en colaboración con &lt;a href=&quot;https://www.universia.net/es/empleo&quot;&gt;Fundación Universia&lt;/a&gt;, &lt;a href=&quot;https://www.indracompany.com/&quot;&gt;Indra&lt;/a&gt; y &lt;a href=&quot;https://www.thebridge.tech/&quot;&gt;The Bridge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;La beca, denominada &lt;strong&gt;Programa DIGITAL RESKILLING Desarrolo Web Full Stack para estudiantes con Discapacidad&lt;/strong&gt;, me permite acceder al Bootcamp de formación impartido por The Bridge desde marzo a noviembre, y en él se verán los siguientes módulos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Módulo 0: Ramp up&lt;/li&gt;
&lt;li&gt;Módulo 1: JavaScript avanzado&lt;/li&gt;
&lt;li&gt;Módulo 2: Back end development&lt;/li&gt;
&lt;li&gt;Módulo 3: Front end con React&lt;/li&gt;
&lt;li&gt;Módulo 4: DevOps&lt;/li&gt;
&lt;li&gt;Módulo 5: Lanza tu carrera digital&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;trabajos-realizados-en-el-bootcamp&quot;&gt;Trabajos realizados en el Bootcamp&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/conceptos-fswd&quot;&gt;Práctica final del Ramp up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript&quot;&gt;Ejercicios de JavaScript avanzado&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/summer-quiz&quot;&gt;Práctica final JavaScript: «Summer Quiz»&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/ejercicios-backend-nodejs&quot;&gt;Ejercicios de backend con Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/ejercicios-frontend-react&quot;&gt;Ejercicios de frontend con React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/tienda-8-bits&quot;&gt;Proyecto final&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La info de la formación estaba en el enlace ya desaparecido: “&lt;a href=&quot;http://www.thebridge.tech/curso/bootcamp-indra-fundacion-universia#solicitud-beca%E2%80%9D&quot;&gt;www.thebridge.tech/curso/bootcamp-indra-fundacion-universia#solicitud-beca”&lt;/a&gt;.&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/beca-santander-fswd.HOVXfGZT_Z2wu3mz.webp"/><category>formación</category><category>javascript</category><category>programación</category><author>JavGuerra</author></item><item><title>Lógica interactiva</title><link>https://javguerra.github.io/blog/logica-interactiva</link><guid isPermaLink="true">https://javguerra.github.io/blog/logica-interactiva</guid><description>Opciones, eventos, disparadores y estados</description><pubDate>Sat, 30 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/decisiones.Dh9wsimN_1ihbMt.webp&quot; alt=&quot;Decisiones&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#algoritmia&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Programar es una diversión difícil. En ocasiones las interacciones entre los disparadores de eventos y los estados de las variables y los objetos interelacionados multiplican sus opciones, haciendo complicado establecer, de memoria, todas las permutaciones posibles para no dejar ninguna de ellas sin implementar en nuestro código.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/12-nodos.html&quot;&gt;&lt;button&gt;Página web de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En la página que he preparado para ilustrar esta entrada, tenemos cinco botones de un menú de opciones. Cada opción interactúa con los estados de los otros botones mientras se van añadiendo, quitando o cambiando elementos del DOM (en este caso artículos de una sección), y activando o desactivando los botones según sea necesario en cada momento. Es fácil entender la mecánica del ejemplo probándolo.&lt;/p&gt;
&lt;p&gt;Los disparadores son los botones que generan eventos, y algunas condiciones del propio programa, como cuando hemos borrado todos los elementos del DOM o cuando añadimos el primer elemento tras ello. Los estados corresponden a los botones ON/OFF, y al valor de las variables que se emplean para llevar a cabo las acciones asignadas a cada botón.&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Decisiones&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/opciones.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;Imaginemos que con el botón «Cambiar» alteramos el contenido del último elemento de la lista de elementos que hemos añadido al DOM (como se ve en la imagen). Esto hará que el botón «Cambiar» se desactive en este momento, porque ya no tenemos que cambiar el elemento recien cambiado, y el botón «Limpiar» se active, si no lo estaba ya, para ofrecer al usuario la opción de limpiar los elementos cambiados. Si borramos seguidamente este último elemento con «Borrar», deberemos comprobar si el botón «Limpiar» debe desactivarse si ya no hay elementos cambiados, y si el botón «Cambiar» debe activarse de nuevo si el que ahora es el último elemento no fue cambiado anteriormente, o mantenerse desactivado en tal caso. Añadir nuevos elementos altera otra vez el estado del botón «Cambiar» que debe activarse ofreciendo la opción de cambiar este nuevo elemento. Estas son algunas de las permutaciones posibles.&lt;/p&gt;
&lt;h2 id=&quot;tabla-disparadoresestados&quot;&gt;Tabla «disparadores/estados»&lt;/h2&gt;
&lt;p&gt;Mediante una tabla en una sencilla hoja de cálculo podemos contabilizar en el eje de las &lt;strong&gt;Y&lt;/strong&gt; (primera columna) todos aquellos disparadores (eventos y condiciones) de nuestra aplicación, y en el eje de las &lt;strong&gt;X&lt;/strong&gt; (filas) todos los estados, tanto de las variables como de los objetos (botones u otros), y ver cómo se interelacionan en tiempo de ejecución. &lt;u&gt;Lo difícil entonces será determinar con claridad cuáles son los disparadores y cuáles los estados&lt;/u&gt;. Si lo hacemos bien, con esta herramienta podemos clarificar, sin olvidar nada, cada interacción lógica derivada de las opciones de la aplicación, de forma similar a como se ve en la siguiente imagen.&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Decisiones&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/tabla-disparadores-estados.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo, «Arranque» se refiere al estado de los botones al inicio. «Click btn…» corresponde a la pulsación de cada uno de los cinco botones. «Sin elementos» corresponde a la situación en la que se han borrado todos los elementos. «Añadir primer elemento» corresponde a los cambios a realizar cuando esta condición se presenta. Por último, «Click de inicio» y «Click de parada» corresponden al estado de los botones cuando los pulsamos y cuando se termina de realizar su tarea asignada. Como se aprecia, los botones son desactivados al pulsarlos para impedir que puedan ser pulsados de nuevo en tanto no terminen su ejecución, momento en el que (algunos de ellos) son reactivados.&lt;/p&gt;
&lt;p&gt;Esta tabla resumida incluye sólo la interacción de estados de los botones, -obviando el estado de las variables para no complicar el ejemplo-, anotando en las celdas de cada columna el estado del botón según los disparadores indicados al principio de cada fila. A la hora de pasar a la fase de codificación de nuestra aplicación, nos será fácil determinar si hemos implementado todas y cada una de las interacciones posibles reflejadas en la tabla simplemente cotejándola. Cuando tengas ante ti un abanico de opciones inabarcables, esta puede ser una solución para salir del atolladero.&lt;/p&gt;
&lt;p&gt;De paso, este ejercicio sirve para mostrar el uso de JavaScript en el manejo de nodos del DOM.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/12-nodos.html&quot;&gt;&lt;button&gt;Ver el ejercicio interactivo on-line&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Descargar la tabla de decisiones completa del ejercicio en formato &lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/12-nodos-tabla.ods&quot;&gt;.ods (Open Document)&lt;/a&gt; o &lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/12-nodos-tabla.xls&quot;&gt;.xls (Excel)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Actualización&lt;/strong&gt;. Ver este ejemplo de uso de botonera aún más complicado: &lt;a href=&quot;/blog/cronometro-js&quot;&gt;Cronómetro en JavaScript&lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/decisiones.Dh9wsimN_1ihbMt.webp"/><category>código</category><category>javascript</category><category>algoritmia</category><author>JavGuerra</author></item><item><title>Accesibilidad Web</title><link>https://javguerra.github.io/blog/accesibilidad</link><guid isPermaLink="true">https://javguerra.github.io/blog/accesibilidad</guid><description>Buenas prácticas explicadas a través de un ejemplo</description><pubDate>Sun, 08 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/accessibility.BH_1lQGp_ZiUkNk.webp&quot; alt=&quot;Accesibilidad web&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#accesibilidad&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;blockquote&gt;
&lt;p&gt;«El poder de la Web está en su universalidad. El acceso por cualquier persona, independientemente de la discapacidad que presente es un aspecto esencial.»&lt;/p&gt;
&lt;p&gt;Fuente: &lt;em&gt;&lt;a href=&quot;https://www.w3.org/Press/IPO-announce&quot;&gt;World Wide Web Consortium Launches International Program Office for Web Accessibility Initiative&lt;/a&gt;. &lt;a href=&quot;https://www.w3.org/People/Berners-Lee/&quot;&gt;Tim Berners-Lee&lt;/a&gt;, Director del W3C e inventor de la World Wide Web&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Todos presentaremos en algún momento de nuestra vida alguna discapacidad en menor o mayor grado. El envejecimiento de la población acentúa esto, sumando un número destacable de personas que requieren algún tipo de adaptación (visual, auditiva, cognitiva, motriz) a la hora de acceder a la información en línea, por eso es importante que nuestras webs tengan esto en cuenta para poder llegar a cualquier tipo de público.&lt;/p&gt;
&lt;p&gt;Con ayuda de la página de ejemplo que preparé y reseñe en &lt;a href=&quot;/blog/conceptos-fswd&quot;&gt;esta entrada&lt;/a&gt;, iré describiendo algunas buenas prácticas que suelo emplear en las webs que desarrollo.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/conceptos-fswd/index.html&quot;&gt;&lt;button&gt;Acceder a la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;comprensión-del-contexto&quot;&gt;Comprensión del contexto&lt;/h2&gt;
&lt;p&gt;Para algunas personas el acceso a la web es posible sólo mediante el uso de programas de lectura de pantalla que traducen la página de arriba a abajo, secuencialmente, a mensajes de voz o a líneas de lectura en un teclado Braille.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;Esta entrada no pretende ser un completo compendio de buenas prácticas, sino un acercamiento básico al sentido de la accesibilidad web que permita sensibilizar sobre ello.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Mi primer objetivo es pues dar a conocer adecuadamente el contexto en el que cada elemento de la página se presenta y describir cada cosa que lo necesite, como la misma página, a través de un &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; o las imágenes con el atributo &lt;code&gt;alt&lt;/code&gt; (Los iconos, a no ser que tengan alguna función informativa, no requieren de este atributo). Afortunadamente. esta es una práctica comúnmente usada por los desarrolladores hoy día. Pero hay más.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Redes Sociales&lt;/strong&gt;&lt;br&gt;
Cuando compartimos nuestra web en redes sociales, queremos que esto ayude a generar visitas, por lo que es bueno contar con una descripción y una imagen que referencie adecuadamente su contenido. Mediante el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;Open Graph&lt;/a&gt; conseguimos que esta información sea ofrecida de manera automática al publicarla en la red social. Esto se consigue mediante una serie de indicaciones en el &lt;code&gt;head&lt;/code&gt; de la página que contienen la información necesaria debidamente formateada. Pues bien, esto que nace como un recurso para SEO y para conseguir clics de potenciales visitantes, también ayuda a las personas con alguna discapacidad a realizar una mejor navegación informándoles de lo que encontrarán al hacer clic, ahorrándoles incertidumbre y tiempo valioso.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;El lenguaje&lt;/strong&gt;&lt;br&gt;
Hay al menos dos cuestiones de importancia a tener en cuenta en este apartado:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;El contenido debe ser claro, orientado a todo tipo de público, y bien estructurado para que cualquier persona, incluso aquella que presente problemas de comprensión lectora, pueda entenderlo.&lt;/li&gt;
&lt;li&gt;La página debe contar con el atributo &lt;code&gt;lang&lt;/code&gt; en la etiqueta &lt;code&gt;html&lt;/code&gt; (&lt;code&gt;lang=&quot;es&quot;&lt;/code&gt;) que describe el idioma principal de la página. Todos aquellos textos y enlaces que se presenten en otro idioma deben ir debidamente señalizados con la esta etiqueta también. Ver este ejemplo: &lt;code&gt;&amp;lt;span lang=&quot;en&quot;&amp;gt;front end&amp;lt;/span&amp;gt;&lt;/code&gt;. Cuando se escucha una página a través de un sintetizador de voz, se agradece que las palabras en otro idioma no generen confusión.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;El color&lt;/strong&gt;
Para las personas con baja visión o con afecciones en la percepción de los colores, es importante que los textos y el fondo presenten un contraste adecuado para que sean legibles.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ir al contenido&lt;/strong&gt;&lt;br&gt;
Cuando usamos lectores de pantalla se hace tedioso escuchar o leer toda la información del &lt;code&gt;header&lt;/code&gt; (titulo, menú de navegación…) una y otra vez, por lo que es de ayuda contar con un enlace al principio de la página que nos lleve directamente al contenido. Algo como esto: &lt;code&gt;&amp;lt;a href=&quot;#contenido&quot; class=&quot;sr&quot;&amp;gt;Ir al contenido&amp;lt;/a&amp;gt;&lt;/code&gt;. Al hacer clic en el enlace saltaremos directamente al &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, ahorrándonos un tiempo valioso. Pero no querremos que este enlace aparezca en nuestro diseño web visual. Mediante la clase &lt;code&gt;.sr&lt;/code&gt; conseguimos esto. en mi caso, la clase que aplicamos a este enlace contiene lo siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.sr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  position&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;absolute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  overflow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;hidden&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  text-indent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;-9999&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La clase &lt;code&gt;.sr&lt;/code&gt; hará que la etiqueta exista y pueda ser leída por un lector de pantalla, que no toma en cuenta dónde se ubican visualmente los elementos de la página, pero no se mostrará en nuestro diseño, porque estará oculta en &lt;code&gt;-9999px&lt;/code&gt;, fuera de la pantalla.&lt;/p&gt;
&lt;p&gt;Esta técnica es útil también para incluir comentarios de navegación, información complementaria, incluso, como en el caso del formulario que incluye la web, para mostrar las etiquetas de los campos del formulario que han sido eliminadas del diseño por una cuestión estética.&lt;/p&gt;
&lt;p&gt;Por supuesto, la página debe estar adecuadamente estructurada con las etiquetas semánticas correspondientes (&lt;code&gt;section&lt;/code&gt;, &lt;code&gt;article&lt;/code&gt;, etc.) para poder realizar una navegación secuencial correcta.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interactividad&lt;/strong&gt;&lt;br&gt;
Al interactuar con la página, botones, enlaces y campos de formulario deben estar adecuadamente identificados, y dotados de un contexto semántico (p.ej. &lt;code&gt;label&lt;/code&gt;). Los enlaces deben ser auto-descriptivos, de tal forma que al leer el texto del enlace sepamos que nos depara hacer clic en él.&lt;/p&gt;
&lt;p&gt;No es muy complicado cuando tomamos conciencia de ello, pero existe una traba mayor, los cambios en la página. Cuando hacemos clic en un menú desplegable, la página cambia para mostrarnos una información que hasta ahora no estaba disponible. Cuando introducimos un valor erróneo en un campo de formulario, el mensaje de error que se muestra es una aparición que debe ser notificada, y el foco de dónde comenzar a escribir para corregir ese dato debe apuntar al campo erróneo.&lt;/p&gt;
&lt;p&gt;Mediante el uso de etiquetas &lt;a href=&quot;https://en.wikipedia.org/wiki/WAI-ARIA&quot;&gt;WAI-ARIA&lt;/a&gt; podemos describir esos eventos y mostrar sus estados correctamente. Veamos el siguiente ejemplo.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id=&quot;hamburguesa&quot; &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;aria-controls&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&quot;menu&quot; &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&quot;Botón de menú&quot; &lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;aria-expanded&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&quot;false&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; class=&quot;barra1&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; class=&quot;barra2&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; class=&quot;barra3&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;nav&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; id=&quot;menu&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; href=&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;#descripcion&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Descripción&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; href=&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;#perfiles&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Perfiles&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; href=&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;#tecnologias&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Tecnologías&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; href=&quot;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;#contactar&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Contactar&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;nav&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta pieza de código corresponde al menú de la página. El &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; permite que se despliegue o se repliegue (ON/OFF) el menú del &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; cuando nuestro dispositivo tiene una pantalla pequeña (es &lt;em&gt;responsive&lt;/em&gt;). Así pues, con &lt;code&gt;aria-controls=&quot;menu&quot;&lt;/code&gt;, establecemos esa relación. Con &lt;code&gt;aria-label=&quot;Botón de menú&quot;&lt;/code&gt; aportamos una descripción de la función del botón. Y con &lt;code&gt;aria-expanded=&quot;false&quot;&lt;/code&gt; indicamos si el botón esta activado o no. En este caso aparece como &lt;code&gt;false&lt;/code&gt;, desactivado, pero esto cambia al hacer clic en él, y es nuestra responsabilidad actualizar esta etiqueta mediante JavaScript, como se hace en el fichero &lt;code&gt;script.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;hamburguesa&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hamburguesa;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;aria-expanded&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    h.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;aria-expanded&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Al hacer click en el botón del menú (‘&lt;em&gt;hamburguesa&lt;/em&gt;’ llamado así porque su icono de tres líneas &lt;i class=&quot;bi bi-list&quot;&gt;&lt;/i&gt; se asemeja al famoso bocadillo), la etiqueta &lt;code&gt;aria-expanded&lt;/code&gt; cambia su valor de &lt;code&gt;false&lt;/code&gt; a &lt;code&gt;true&lt;/code&gt; o viceversa. Así informaremos al usuario de un lector de pantalla si el botón está pulsado o no en cada momento.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tablas&lt;/strong&gt;&lt;br&gt;
Las páginas pensadas para su uso por terminales móviles primero (&lt;em&gt;responsive&lt;/em&gt;) ayudan mucho a clarificar el flujo del contenido de la navegación, pero si hay algo que rompe con todo ello son las tablas. ¿Cuál es el orden correcto para leer una tabla? ¿fila a fila? ¿Y qué hay de las columnas o filas agrupadas?&lt;/p&gt;
&lt;p&gt;Las etiquetas semánticas nuevamente son de ayuda aquí (&lt;code&gt;&amp;lt;thead&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;tfoot&amp;gt;&lt;/code&gt;, y &lt;code&gt;&amp;lt;tr&amp;gt;&lt;/code&gt; para los encabezados) y algunos atributos de HTML ayudan a paliar esto en cierta medida, como &lt;code&gt;scope=&quot;colgroup&quot;&lt;/code&gt; (columnas) y &lt;code&gt;scope=&quot;rowgroup&quot;&lt;/code&gt; (filas) que indican que las siguientes filas o columnas forman parte de un grupo con un mismo contexto.&lt;/p&gt;
&lt;p&gt;Como se puede ver en la &lt;a href=&quot;https://javguerra.github.io/conceptos-fswd/index.html#perfiles&quot;&gt;tabla&lt;/a&gt; de la web de ejemplo, todas las celdas debajo de la celda del encabezado «&lt;em&gt;Front end&lt;/em&gt;» o del encabezado «&lt;em&gt;Back end&lt;/em&gt;» estarían dentro de un &lt;em&gt;colgroup&lt;/em&gt; y las celdas al lado de las celdas de encabezado «Desarrollo», «Diseño», «Sistemas», etc. estarían dentro de un &lt;code&gt;rowgroup&lt;/code&gt;. No es una solución perfecta, pero definiendo estos bloques, ayudamos a la navegación. Estas etiquetas se suelen aplicar a los elementos &lt;code&gt;&amp;lt;th&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusiones&quot;&gt;Conclusiones&lt;/h2&gt;
&lt;p&gt;Hacer desarrollo web accesible no es más complicado que hacer diseño &lt;em&gt;responsive&lt;/em&gt;, aunque implica dedicarle un poco más tiempo y empatía.&lt;/p&gt;
&lt;p&gt;Para que tus diseños sean exitosos, contempla lo siguiente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hacer contenido claro, bien estructurado, y definir adecuadamente el contexto de cada cosa que mostremos en la web. Desarrollamos para personas.&lt;/li&gt;
&lt;li&gt;Aportar atajos y ayudas a la navegación si es posible, y sin exagerar.&lt;/li&gt;
&lt;li&gt;Vigilar los eventos interactivos, y señala adecuadamente sus estados.&lt;/li&gt;
&lt;li&gt;Revisar el código con herramientas que nos permitan conocer si hemos pasado algo por alto, y así corregirlo, como el &lt;a href=&quot;https://wave.webaim.org/&quot;&gt;complemento WAVE&lt;/a&gt; para el navegador.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/conceptos-fswd/index.html&quot;&gt;&lt;button&gt;Acceder a la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enlaces de interés&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/fundamentals/accessibility-intro/es&quot;&gt;Introducción a la accesibilidad web&lt;/a&gt; - W3C&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://es.wikipedia.org/wiki/Accesibilidad_web&quot;&gt;Accesibilidad Web&lt;/a&gt; - Wikipedia&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://administracionelectronica.gob.es/pae_Home/pae_Estrategias/pae_Accesibilidad/pae_normativa/pae_eInclusion_Normas_Accesibilidad.html&quot;&gt;Normas de accesibilidad&lt;/a&gt; - PAE&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.ua.es/es/accesibilidad/&quot;&gt;Unidad de accesibilidad digital&lt;/a&gt; - Universidad de Alicante&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/sergiolujanmora&quot;&gt;Sergio Luján Mora&lt;/a&gt; - Profesor universitario experto&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://olgacarreras.blogspot.com/&quot;&gt;Usable y accesible&lt;/a&gt; - Consultora freelance&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wave.webaim.org/&quot;&gt;complemento WAVE&lt;/a&gt; - Herramienta&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/WAI-ARIA&quot;&gt;WAI-ARIA&lt;/a&gt; - Estándar&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/accessibility.BH_1lQGp_ZiUkNk.webp"/><category>código</category><category>html</category><category>css</category><category>javascript</category><category>accesibilidad</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Validación de formularios</title><link>https://javguerra.github.io/blog/validacion</link><guid isPermaLink="true">https://javguerra.github.io/blog/validacion</guid><description>Combinando validaciones propias con las de HTML5</description><pubDate>Fri, 13 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/formulario.DcQ-TXfn_ZQ7Ppf.webp&quot; alt=&quot;Validación de formularios&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#formularios&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;¿Cómo procesar un formulario antes de enviarlo, realizando validaciones propias en sus campos y aprovechando simultáneamente la validación de restricciones implícita en HTML5?&lt;/p&gt;
&lt;p&gt;Que ambos tipos de validaciones se den al mismo tiempo es importante, ya que si esto se hiciera consecutivamente, es decir, una a continuación de la otra, llevando a cabo primero nuestra validación y luego la de HTML5, correríamos el riesgo de que los campos propios ya validados pudieran ser alterados por el usuario una vez pasada la primera validación, si en la segunda validación hay campos erróneos que obligan al usuario a editarlos, y por tanto el formulario se enviaría con errores. Veamos cómo se haría.&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Validación de formularios&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/validacion.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/validacion.html&quot;&gt;&lt;button&gt;Formulario de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tenemos un formulario con tres campos requeridos (obligatorios): «nombre», «edad» y «correo», y al campo «edad» le añado una restricción propia, que su valor debe ser mayor o igual a 16, y si esto no se cumple, deberé mostrar un mensaje de error personalizado en el mismo campo (al estilo de los mensajes de error de HTML5). El formulario cuenta con dos botones: «Borrar» y «Enviar».&lt;/p&gt;
&lt;p&gt;Si no tuviésemos que realizar nuestra validación, el proceso sería sencillo, ya que HTML se ocupa de todo por nosotros. Al hacer click en el botón enviar de tipo submit (&lt;code&gt;&amp;lt;button type=&quot;submit&quot;&amp;gt;Enviar&amp;lt;/button&amp;gt;&lt;/code&gt;), se lanza el evento &lt;code&gt;submit()&lt;/code&gt;, y el formulario se envía si no hay errores tras validarlo, o nos muestra los errores de validación de campos implícita en HTML5. Pero para poder realizar nuestras propias validaciones debemos romper este flujo, y tomar el control de la validación.&lt;/p&gt;
&lt;h2 id=&quot;tomando-el-control&quot;&gt;Tomando el control&lt;/h2&gt;
&lt;p&gt;Esto podemos hacerlo de dos formas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Capturamos el evento &lt;code&gt;submit()&lt;/code&gt; asociado al botón «Enviar» con &lt;code&gt;enviar.addEventListener(&apos;click&apos;, validaForm);&lt;/code&gt; en JavaScript, incluyendo en &lt;code&gt;function validaForm(evento)&lt;/code&gt; un &lt;code&gt;evento.preventDefault();&lt;/code&gt; que evite que el &lt;code&gt;action&lt;/code&gt; del formulario se procese, y realizando por nuestra cuenta todas las validaciones (las propias y las de HTML5), usando su (&lt;a href=&quot;https://www.w3.org/TR/html5/forms.html#the-constraint-validation-api&quot;&gt;API&lt;/a&gt;), para terminar lanzando el evento &lt;code&gt;form.submit()&lt;/code&gt; que retomará el curso del formulario.&lt;/li&gt;
&lt;li&gt;Usamos un botón «Enviar» que no incluya el &lt;code&gt;type=&quot;submit&quot;&lt;/code&gt;, y asociamos este botón a un evento que llame a la función de validación &lt;code&gt;validaForm()&lt;/code&gt; desde la cual, al final, lanzaremos también el &lt;code&gt;form.requestSubmit()&lt;/code&gt; si se cumplan las dos condiciones de este ejemplo: edad correcta y campos obligatorios rellenados.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;La opción elegida aquí es la segunda por ser la más simple para cumplir el objetivo marcado de llevar a cabo ambas validaciones. Desde la mencionada función &lt;code&gt;validaForm()&lt;/code&gt; comprobamos la edad con la función &lt;code&gt;validaEdad()&lt;/code&gt; que debe devolver &lt;code&gt;True&lt;/code&gt; o &lt;code&gt;False&lt;/code&gt;, y comprobamos nosotros mismos si el formulario tiene errores con &lt;code&gt;form.checkValidity()&lt;/code&gt;, que también devuelve &lt;code&gt;True&lt;/code&gt; o &lt;code&gt;False&lt;/code&gt;. Si ambas comprobaciones son &lt;code&gt;True&lt;/code&gt;, el formulario se envía.&lt;/p&gt;
&lt;p&gt;Al utilizar &lt;code&gt;form.requestSubmit()&lt;/code&gt;, el navegador se comporta exactamente igual que si el usuario hiciera clic en un botón de envío: ejecuta automáticamente la validación nativa (respetando atributos como required o pattern), muestra los mensajes de error al usuario si algo falla y dispara el evento submit, permitiendo que el formulario se gestione de forma segura y completa.&lt;/p&gt;
&lt;p&gt;Veamos el código JavaScript:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. const enviar &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#enviar&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;02&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. const form   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.formulario;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;03&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;04&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. enviar.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;click&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, validaForm);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;05&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;06&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. function &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;validaForm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(evento) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;07&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.   evento.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;preventDefault&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;08.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;validaEdad&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; form.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;checkValidity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;09.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;     alert&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Ambas validaciones son correctas.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     form.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;requestSubmit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;     alert&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;El formulario contiene errores.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;14.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16.&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; /* Comprueba que el usuario tenga más de 16 años */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;17.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; validaEdad&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;18.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; edad&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Number&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(form.edad.value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (edad &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     form.edad.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setCustomValidity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Demasiado joven.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;21.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;     return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;22.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;23.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   form.edad.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setCustomValidity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;24.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;25.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para llegar a esta solución me inspiré en una &lt;a href=&quot;https://stackoverflow.com/questions/45789010/how-to-use-html-form-checkvalidity&quot;&gt;pregunta&lt;/a&gt; realizada en &lt;strong&gt;StackOverflow&lt;/strong&gt;, y en el &lt;a href=&quot;https://www.w3schools.com/js/js_validation_api.asp&quot;&gt;enlace&lt;/a&gt; de &lt;strong&gt;W3Schools&lt;/strong&gt; que aparece en la señalada como mejor respuesta de esa pregunta.&lt;/p&gt;
&lt;p&gt;En caso de tener que llevar a cabo más validaciones propias, bastaría con encadenarlas en el &lt;code&gt;ìf()&lt;/code&gt; de la línea &lt;strong&gt;8&lt;/strong&gt;, o crear una función a parte que incluya todas nuestras validaciones, que sustituya a &lt;code&gt;validaEdad()&lt;/code&gt; y que devuelva &lt;code&gt;True&lt;/code&gt; o &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;la-función-validaedad&quot;&gt;La función validaEdad()&lt;/h2&gt;
&lt;p&gt;Cuando se ejecuta la función &lt;code&gt;validaEdad()&lt;/code&gt;, pueden pasar dos cosas:&lt;/p&gt;
&lt;p&gt;Si la edad no es la adecuada, se marca el error en la línea &lt;strong&gt;20&lt;/strong&gt;: Al pasar un texto como &lt;code&gt;&apos;Demasiado joven.&apos;&lt;/code&gt;, el navegador marca el campo como inválido. Mientras exista este mensaje, el formulario estará bloqueado y no se podrá enviar.&lt;/p&gt;
&lt;p&gt;Si la edad es la adecuada, se limpiar el error en la línea &lt;strong&gt;23&lt;/strong&gt;: Es imprescindible pasar una cadena vacía &lt;code&gt;&apos;&apos;&lt;/code&gt; cuando el dato sea correcto. Esto indica al navegador que el campo vuelve a ser válido, permitiendo así el envío. Si no “limpias” el mensaje al cumplirse la condición, el campo quedará marcado como erróneo permanentemente.&lt;/p&gt;
&lt;p&gt;Debes aplicar esta misma lógica en cada validación propia que realices.&lt;/p&gt;
&lt;h2 id=&quot;valida--no-valida&quot;&gt;Valida / NO valida&lt;/h2&gt;
&lt;p&gt;¿Qué ocurre si la edad no es correcta o si uno de los campos obligatorios está vacío? Como el formulario no es correcto, se mostrará la alerta de la línea &lt;strong&gt;12&lt;/strong&gt;. Podemos sustituir esta alerta del ejemplo por una serie de acciones de aviso al usuario u otras para informar de que algo no ha ido bien (o no hacer nada, si no necesitamos el &lt;code&gt;else&lt;/code&gt;). En caso contrario, si todo ha ido bien, el formulario será válido, y se llevará a cabo lo estipulado en las líneas &lt;strong&gt;9&lt;/strong&gt; y &lt;strong&gt;10&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;La alerta de la línea &lt;strong&gt;9&lt;/strong&gt; del ejemplo puede sustituirse por cualquier cosa que queramos llevar a cabo antes de enviar el formulario en la línea &lt;strong&gt;10&lt;/strong&gt;, por ejemplo, mostrar los valores de los campos para que el usuario los revise antes de enviar, si estamos realizando una compra, un envío de dinero… Por último, en la línea &lt;strong&gt;10&lt;/strong&gt;, enviamos el formulario con &lt;code&gt;form.requestSubmit()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Eso es todo. Puedes ver el ejemplo empleado en esta entrada y más información relacionada en los siguientes enlaces:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/validacion.html&quot;&gt;&lt;button&gt;Formulario de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/html5/forms.html#the-constraint-validation-api&quot;&gt;API de formularios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/js/js_validation_api.asp&quot;&gt;Información y ejemplos en W3Schools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/45789010/how-to-use-html-form-checkvalidity&quot;&gt;Información en StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/formulario.DcQ-TXfn_ZQ7Ppf.webp"/><category>código</category><category>html</category><category>javascript</category><category>formularios</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Animación interactiva</title><link>https://javguerra.github.io/blog/animacion</link><guid isPermaLink="true">https://javguerra.github.io/blog/animacion</guid><description>Ejemplo realizado con Google Web Designer</description><pubDate>Sat, 14 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/cronometro.CAex-ef7_ZPHEux.webp&quot; alt=&quot;Cronómetro analógico&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#animación&lt;/em&gt;, &lt;em&gt;#herramienta&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Cree atractivos diseños interactivos basados ​​en HTML5 y gráficos en movimiento que puedan ejecutarse en cualquier dispositivo.&lt;/p&gt;
&lt;p&gt;Así se presenta &lt;a href=&quot;http://badared.com/javguerra/daw/animacion/&quot;&gt;Google Web Designer&lt;/a&gt; en su web. Se trata de una herramienta disponible para varios sistemas operativos que puede descargarse para crear animaciones y elementos interactivos en HTML5 y que se integra con otros productos de Google, como Google Drive, Display &amp;amp; Video 360 y Google Ads.&lt;/p&gt;
&lt;p&gt;Veamos cómo funciona con un ejemplo: &lt;a href=&quot;http://badared.com/javguerra/daw/animacion/&quot;&gt;&lt;button&gt;Ver animación&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Esta simple animación que preparé para la asignatura de Diseño de Interfaces Web de F.P.G.S. de Desarrollo de Aplicaciones Web, contiene la imagen de un cronómetro en formato SVG que creé con la herramienta Inkscape, y dos botones que nos permiten iniciar y parar la animación o reiniciar la animación. Al iniciar con el botón «START», las agujas del cronómetro comienzan a correr hasta llegar a 20 segundos, momento en el que suena una campanilla, y la animación vuelve a su punto de origen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Web Designer&lt;/strong&gt; se parece a otras herramientas de edición de animaciones como la extinta &lt;a href=&quot;https://es.wikipedia.org/wiki/Adobe_Flash&quot;&gt;Adoble Flash&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Permite:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crear eventos e interacción usando los que vienen con la herramienta o creando otros propios con JavaScript.&lt;/li&gt;
&lt;li&gt;Arrastrar y soltar componentes en su proyecto para agregar instantáneamente funcionalidades como galerías de imágenes, reproductores de video, mapas y más. Además, cada componente informa automáticamente las métricas sin necesidad de codificación.&lt;/li&gt;
&lt;li&gt;Crear varias páginas para incluir varias escenas dentro de un proyecto.&lt;/li&gt;
&lt;li&gt;Crear reglas de medios en su bloque de anuncios para establecer el estilo y el diseño del diseño, de modo que un solo bloque de anuncios pueda adaptarse a cualquier tamaño de pantalla en el que aparezca.&lt;/li&gt;
&lt;li&gt;Animar escenas simples en el modo Rápido o usando capas en una línea de tiempo en el modo Avanzado unsando rutas de movimiento y aceleración personalizada.&lt;/li&gt;
&lt;li&gt;Crea y manipula contenido 3D usando CSS3. Permite girar objetos y diseños 2D a lo largo de cualquier eje, visualizando transformaciones y traslaciones 3D mientras editamos.&lt;/li&gt;
&lt;li&gt;Admite una amplia gama de &lt;a href=&quot;https://www.richmediagallery.com/formats&quot;&gt;formatos&lt;/a&gt; de anuncios gráficos y de video en todas sus plataformas publicitarias.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aunque no es muy conocida, es una herramienta potente, y finalmente, el resultado del trabajo con &lt;strong&gt;Google Web Designer&lt;/strong&gt; es completamente compatible con los estándares web actuales, manejando con CSS y JavaScript toda la animación y gestión de eventos, y ofreciendo resultados adaptables al dispositivo donde se muestre la animación interactiva.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://badared.com/javguerra/daw/animacion/&quot;&gt;&lt;button&gt;Ver animación&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://webdesigner.withgoogle.com/intl/es_es/&quot;&gt;Descargar Google Web Designer&lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/cronometro.CAex-ef7_ZPHEux.webp"/><category>web</category><category>html</category><category>css</category><category>javascript</category><category>animación</category><category>herramienta</category><author>JavGuerra</author></item><item><title>Brackets vuelve</title><link>https://javguerra.github.io/blog/brackets</link><guid isPermaLink="true">https://javguerra.github.io/blog/brackets</guid><description>El editor para los desarrolladores front end</description><pubDate>Sat, 14 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/brackets.DXNxrSQa_1nLAca.webp&quot; alt=&quot;Brackets&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#herramienta&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;¿Acaso se había ido? &lt;a href=&quot;https://brackets.io/&quot;&gt;Brackets&lt;/a&gt; es un editor de texto orientado al desarrollo web, implementado en JavaScript, fácilmente extensible mediante HTML/CSS/JS, y que está disponible para Windows, OS X y Linux bajo una licencia abierta.&lt;/p&gt;
&lt;p&gt;Tras el éxito arrollador de Visual Studio Code, Adobe, la empresa detrás de su desarrollo, abandonó el proyecto por su baja cuota de uso, pero nuevas versiones han sido lanzadas desde entonces de la mano de la comunidad. ¡Brackets sigue vivo!&lt;/p&gt;
&lt;p&gt;Brackets emplea como base el editor &lt;a href=&quot;https://codemirror.net/&quot;&gt;CodeMirror&lt;/a&gt; y retoma ideas y conceptos ya ensayados en otra herramienta discontinuada llamada Adobe Edge Code. Tiene alrededor una amplia comunidad de desarrolladores que están ampliando los horizontes de esta herramienta rápidamente, haciéndola versátil en otras áreas del trabajo y la edición de múltiples formatos de documentos.&lt;/p&gt;
&lt;p&gt;De hecho, un nuevo proyecto derivado de Brackets ha visto la luz. Se trata de &lt;a href=&quot;https://phcode.dev/&quot;&gt;Phoenix&lt;/a&gt;, un editor web completamente on-line (aunque no funciona aún con Firefox…).&lt;/p&gt;
&lt;h2 id=&quot;extensiones&quot;&gt;Extensiones&lt;/h2&gt;
&lt;p&gt;Con las extensiones de Brackets podemos gestionar el control de versiones (p.ej. Git), revisar el código escrito, añadir notas, hacer seguimiento de TODO’s, escribir código de forma automática con unas pocas pulsaciones de tecla mediante el uso de estructuras de código pre-guardadas…&lt;/p&gt;
&lt;p&gt;La propia herramienta, una vez instalada, dispone de editor interno que permite modificar directamente, sin cambiar de documento, el código CSS asociado a una etiqueta HTML. Permite ver, con sólo pasar por encima, el color de una descripción CSS, y tiene previsualización en vivo de documentos a través de Chrome. Lo que modifiquemos en el código irá reflejándose en la página mostrada en Chrome en tiempo real.&lt;/p&gt;
&lt;p&gt;Adobe proponía seguir &lt;a href=&quot;https://github.com/adobe/brackets/wiki/How-to-Use-Brackets&quot;&gt;estos pasos&lt;/a&gt; (en inglés) para iniciarse en el uso de Brackets.&lt;/p&gt;
&lt;p&gt;Por mi parte, fue de gran ayuda la visualización de este tutorial en video de J&amp;amp;G Proyectos Web para aprender su correcto uso:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/UngFUMhv2TY&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;Cuando instalamos Brackets por primera vez, la interfaz parece algo desangelada, pero a medida que añadimos extensiones esto cambia. En el vídeo se explica muy bien cómo empezar a preparar tu entorno de trabajo.&lt;/p&gt;
&lt;p&gt;El uso de distintos temas permite cambiar su aspecto acercándolo aún más a nuestras preferencias. Son innumerables los que están disponibles, pero de entrada te recomiendo el uso del tema &lt;a href=&quot;https://github.com/Brackets-Themes/Monokai&quot;&gt;Monokai&lt;/a&gt; para Brackets o alguno de los temas contenidos en el paquete &lt;a href=&quot;https://github.com/Jacse/themes-for-brackets&quot;&gt;Themes for Brackets&lt;/a&gt;. Estos están disponibles también vía el gestor de extensiones.&lt;/p&gt;
&lt;p&gt;Una extensión que te ayudará a elegir qué instalar es &lt;a href=&quot;https://github.com/dnbard/brackets-extension-rating&quot;&gt;Extensions Rating&lt;/a&gt;, que indica valoraciones de las extensiones disponibles en función del número de descargas y su popularidad.&lt;/p&gt;
&lt;p&gt;Este es un listado de extensiones que no debes perderte:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emmet&lt;/li&gt;
&lt;li&gt;Brackets Snippets (by edc)&lt;/li&gt;
&lt;li&gt;HTMLHint&lt;/li&gt;
&lt;li&gt;Brackets Todo&lt;/li&gt;
&lt;li&gt;Special Html Characters&lt;/li&gt;
&lt;li&gt;Document outline&lt;/li&gt;
&lt;li&gt;RightClickExtended&lt;/li&gt;
&lt;li&gt;Brackets Tools&lt;/li&gt;
&lt;li&gt;SFtpUpload&lt;/li&gt;
&lt;li&gt;Bracket Git&lt;/li&gt;
&lt;li&gt;Notes&lt;/li&gt;
&lt;li&gt;CanIUse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Será fácil encontrarlas en el gestor de extensiones y conocer más sobre su uso y potencial.&lt;/p&gt;
&lt;p&gt;Para terminar de redondear el trabajo con Brackets, te propongo el uso de la fuente de letra &lt;a href=&quot;http://www.levien.com/type/myfonts/inconsolata.html&quot;&gt;Inconsolata&lt;/a&gt;. Tan sólo debes añadir ‘Inconsolata’, (con comillas, seguido de una coma) al principio, en la casilla «Tipo de letra» en Preferencias de temas, opción a la que se accede vía «Ver &amp;gt; Temas…»&lt;/p&gt;
&lt;p&gt;Si pese a todo lo dicho, Brackets no es lo que estás buscando, te recomiendo que repases esta completa &lt;a href=&quot;http://www.emezeta.com/articulos/los-mejores-editores-de-texto-para-programar&quot;&gt;comparativa de editores alternativos&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://brackets.io/&quot;&gt;&lt;button&gt;Descargar Brackets&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/brackets.DXNxrSQa_1nLAca.webp"/><category>html</category><category>css</category><category>javascript</category><category>herramienta</category><author>JavGuerra</author></item><item><title>El cadáver exquisito</title><link>https://javguerra.github.io/blog/el-cadaver-exquisito</link><guid isPermaLink="true">https://javguerra.github.io/blog/el-cadaver-exquisito</guid><description>Un juego de experimentación artística por ordenador</description><pubDate>Sun, 15 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/el-cadaver-exquisito.BzOGnvM-_Z26VyPN.webp&quot; alt=&quot;El cadáver exquisito original&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#arte&lt;/em&gt;, &lt;em&gt;#meiac&lt;/em&gt;, &lt;em&gt;#juego&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;em&gt;Imagen: Victor Brauner, André Bretón, Jacques Hérold e Yves Tanguy (1935)&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«El cadáver / exquisito / beberá / el vino / nuevo»&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alrededor de los años veinte, los pintores surrealistas inventaron un juego para «fabricar» figuras fantásticas. En realidad, era un derivado de un juego que ya se hacía con las palabras y que consistía en componer una frase entre varias personas: uno de los participantes en el juego escribe la primera palabra de una frase y luego pliega la hoja de forma que su palabra quede oculta; el que está a su lado hace lo mismo, pasa la hoja a su vecino y así sucesivamente…&lt;/p&gt;
&lt;p&gt;En Francia, el juego con las palabras se llama «&lt;a href=&quot;https://es.wikipedia.org/wiki/Cad%C3%A1ver_exquisito&quot;&gt;&lt;em&gt;Le cadavre exquis&lt;/em&gt;&lt;/a&gt;» porque la primera frase escrita con este sistema rezaba: «El cadáver / exquisito / beberá / el vino / nuevo».&lt;/p&gt;
&lt;p&gt;En lugar de jugar con palabras, los pintores surrealistas utilizaron las partes de una figura: el primer jugador dibuja la cabeza; el segundo, el cuerpo; el tercero, las piernas; y el último, los pies. Basta con indicar, sobre la línea plegada, los puntos donde se dejó el dibujo escondido. Con este sistema es posible dibujar personajes fantásticos, animales y plantas… ¡de otro mundo!&lt;/p&gt;
&lt;p&gt;Tomando esta idea como referencia, en un «&lt;strong&gt;Taller de experimentación artística por ordenador&lt;/strong&gt;» que impartí para el &lt;a href=&quot;http://meiac.es&quot;&gt;Museo Extremeño e Iberoamericano de Arte Contemporáneo (MEIAC)&lt;/a&gt; en 1997, llevamos a cabo una versión digital de dicho juego. Aquí el resultado:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://badared.com/javguerra/contenidos/lce/juego.htm&quot;&gt;&lt;button&gt;Ver la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Visualmente, el resultado no está a la altura de los estándares de hoy día. Tampoco la codificación de la página es un prodigio, pero su código guarda algo interesante que ahora contaré.&lt;/p&gt;
&lt;p&gt;La mecánica del juego es sencilla. Los alumnos hicieron un total de diez (10) dibujos completos de sus personajes fantásticos imaginarios, de cabeza a pies. Estas imágenes fueron escaneadas, divididas en tres partes y almacenadas en tres carpetas distintas: «arriba», «medio» y «abajo» todas con el mismo tamaño. Cada imagen fue numerada como &lt;code&gt;image0.jpg&lt;/code&gt; a &lt;code&gt;image9.jpg&lt;/code&gt;, y todas ellas usaban los mismos puntos de corte para la cabeza, el cuerpo y las extremidades inferiores.&lt;/p&gt;
&lt;p&gt;La página elige al azar una imagen de cada una de las tres carpetas mencionadas, mostrando una composición de ellas totalmente nueva e inesperada. ¡Ahora es el ordenador el que juega al cadáver exquisito!&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Juego del cadáver exquisito&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/lce.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;como-funciona&quot;&gt;¿Como funciona?&lt;/h2&gt;
&lt;p&gt;Esta es la parte sorprendente. En aquellos días los navegadores soportaban JavaScript limitadamente, y las versiones del lenguaje no estaban tan avanzadas. No se disponía de la función matemática &lt;code&gt;Math.random()&lt;/code&gt; y el acceso al DOM estaba en pañales. Pero con el siguiente código que me ayudó a escribir en su momento un buen amigo, se hizo posible.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; valor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fecha&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mili&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fecha.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getTime&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();	    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; segundo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fecha.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getSeconds&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; minuto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fecha.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getMinutes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();	    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hora&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fecha.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getHours&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numero;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;round&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((mili&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;segundo)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valor);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&amp;lt;img src=&quot;arriba/image&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;.jpg&quot; width=&quot;250&quot; height=&quot;130&quot;&amp;gt;&amp;lt;br&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;	    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;round&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((mili&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;minuto)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valor);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&amp;lt;img src=&quot;medio/image&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;.jpg&quot; width=&quot;250&quot; height=&quot;130&quot;&amp;gt;&amp;lt;br&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;round&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((mili&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hora)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valor);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&amp;lt;img src=&quot;abajo/image&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;.jpg&quot; width=&quot;250&quot; height=&quot;130&quot;&amp;gt;&amp;lt;br&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para mostrar imágenes al azar, usé los datos de fecha y hora para generar valores pseudo-aleatorios en un rango de enteros entre 0 y 9. Y para poner las imágenes emplee &lt;code&gt;document.write()&lt;/code&gt; pasándole como parámetro el código HTML que mostraría cada una de las tres imágenes aleatorias. Para conseguir el número de imagen empleé &lt;code&gt;Math.round()&lt;/code&gt; con la fórmula que puede verse en el código. Con dichas operaciones, cada vez que se genera la página se obtienen valores lo suficientemente distintos como para conseguir resultados que no se repiten.&lt;/p&gt;
&lt;p&gt;El código JavaScript se inserta en la página en la posición donde se deben mostrar las imágenes, de esa forma el &lt;code&gt;document.write()&lt;/code&gt; no requiere localizar el elemento dentro del cual poner las imágenes. El código ya está ahí.&lt;/p&gt;
&lt;p&gt;Para generar un nuevo «cadáver exquisito» hacemos clic en el botón «Pulse» que recargará la página, generando un nuevo resultado, pues el momento en el tiempo entre la primera composición de imágenes y la nueva es distinto.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://badared.com/javguerra/contenidos/lce/juego.htm&quot;&gt;&lt;button&gt;Ver el juego del cadáver exquisito&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://badared.com/javguerra/contenidos/lce/index.htm&quot;&gt;Ver la página de información del juego&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://es.wikipedia.org/wiki/Cad%C3%A1ver_exquisito&quot;&gt;El cadáver exquisito en Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/el-cadaver-exquisito.BzOGnvM-_Z26VyPN.webp"/><category>web</category><category>html</category><category>css</category><category>javascript</category><category>arte</category><category>meiac</category><category>juego</category><author>JavGuerra</author></item><item><title>Cronómetro en JavaScript</title><link>https://javguerra.github.io/blog/cronometro-js</link><guid isPermaLink="true">https://javguerra.github.io/blog/cronometro-js</guid><description>Gestiona cronometros y guarda sesiones de los cronometrajes</description><pubDate>Sun, 22 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/cronometro-digital.DrsDXeif_Z1xyUJk.webp&quot; alt=&quot;Cronómetro digital&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Ejercicio de programación realizado en el &lt;a href=&quot;/blog/beca-santander-fswd&quot;&gt;bootcamp Full Stack Web Developer&lt;/a&gt; que estoy haciendo.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/CronometroJS/index.html&quot;&gt;&lt;button&gt;Usar el cronómetro&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;enunciado&quot;&gt;Enunciado&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Diseñaremos un HTML que represente un cronómetro con el formato que queramos, por ejemplo: 00:00.&lt;/p&gt;
&lt;p&gt;Añadiremos los botones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Iniciar: Activará el cronómetro, incrementando el contador cada (1) segundo.&lt;/li&gt;
&lt;li&gt;Parar: Detiene el cronómetro.&lt;/li&gt;
&lt;li&gt;Continuar: Vuelve a activar el cronómetro.&lt;/li&gt;
&lt;li&gt;Contar hasta 10: Inicia el cronómetro y lo para a los 10 segundos (y para el crono).&lt;/li&gt;
&lt;li&gt;Guardar: Guarda el estado del crono en localStorage en el momento en que es pulsado (sin parar el crono).&lt;/li&gt;
&lt;li&gt;Ver tiempos: Mostrará el listado de tiempos divido en sesiones que se ha guardado en localStorage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Queremos guardar en local Storage un conjunto de listados de tiempos divididos por sesiones, si es la primera vez que el usuario accede a la página web, la sesión será la número 1, y así sucesivamente.&lt;/p&gt;
&lt;p&gt;Añadiremos los botones pertinentes para borrar todos los datos de local Storage o solo los datos de una sesión en concreto.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;resolución&quot;&gt;Resolución&lt;/h2&gt;
&lt;p&gt;Este ejercicio es un compendio de todo lo visto hasta ahora en el Bootcamp.&lt;/p&gt;
&lt;p&gt;La aplicación que he desarrollado cumple con el enunciado, haciendo uso de las funciones de manejo de tiempos de JavaScript (&lt;code&gt;setInterval&lt;/code&gt;, &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;clearInterval&lt;/code&gt;), y las funciones de manejo de &lt;code&gt;localStorage&lt;/code&gt; (&lt;code&gt;.setItem()&lt;/code&gt;, &lt;code&gt;.getItem()&lt;/code&gt;, &lt;code&gt;.clear()&lt;/code&gt;…), e incluye algunas mejoras:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Operativa de la aplicación&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Los botones del cronómetro se activan y desactivan según sean necesarios en cada función de la aplicación. Se recomienda leer mi entrada sobre &lt;a href=&quot;/blog/logica-interactiva&quot;&gt;lógica interactiva&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Implementa cuenta regresiva en el contador hasta 10.&lt;/li&gt;
&lt;li&gt;Al guardar un cronometraje, se muestra la lista de los cronometrajes de la sesión actual. Podemos listar también los cronometrajes de todas las sesiones, incluida la actual. El listado mostrará la sesión, el número del cronometraje dentro de esta sesión, el tiempo guardado (minutos y segundos), la fecha y hora, y el botón de borrar.&lt;/li&gt;
&lt;li&gt;Al borrar una sesión desde la lista de sesiones, si no se trata de la sesión actual, la aplicación reordena las sesiones para no dejar huecos entre ellas. Si tenemos cinco sesiones, y borramos la sesión tres, la sesión cuatro pasará a ser la tres, y la sesión cinco pasará a ser la cuatro.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Desde el punto de vista de la usabilidad&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Web adaptable según el dispositivo.&lt;/li&gt;
&lt;li&gt;Cuidado aspecto visual empleando CSS.&lt;/li&gt;
&lt;li&gt;El formateo básico se realiza mediante una clase CSS llamada &lt;a href=&quot;https://jgthms.com/wysiwyg.css/&quot;&gt;wysiwyg.css&lt;/a&gt; de la que hablé en &lt;a href=&quot;/blog/wysiwyg-css&quot;&gt;este post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Usa &lt;a href=&quot;https://icons.getbootstrap.com/&quot;&gt;Bootstrap Icons&lt;/a&gt; y fuente personalizada llamada &lt;a href=&quot;https://www.dafont.com/digit.font&quot;&gt;Digit&lt;/a&gt; (&lt;em&gt;sin info del autor&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Es accesible, empleando etiquetas descriptivas y etiquetas &lt;a href=&quot;https://en.wikipedia.org/wiki/WAI-ARIA&quot;&gt;WAI-ARIA&lt;/a&gt; para señalar las regiones de la web que cambian durante la ejecución de la aplicación.&lt;/li&gt;
&lt;li&gt;Ha sido probada en los navegadores web &lt;strong&gt;Firefox&lt;/strong&gt; y &lt;strong&gt;Chrome&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;problemas-resueltos&quot;&gt;Problemas resueltos:&lt;/h2&gt;
&lt;p&gt;La aplicación emplea una serie de funciones para activar y desactivar los botones e incluir las etiquetas WAI-ARIA correspondientes.&lt;/p&gt;
&lt;p&gt;Con dos variables controlo los eventos del cronómetro (&lt;code&gt;cronometro&lt;/code&gt;) y del final de la cuenta atrás (&lt;code&gt;parada10s&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;La variable &lt;code&gt;tiempo&lt;/code&gt; guarda el tiempo en segundos que se llevan contabilizados en el cronometraje en cada momento.&lt;/p&gt;
&lt;p&gt;En &lt;code&gt;sesion&lt;/code&gt; guardo los cronometrajes de la sesión actual. Es un vector o Array de objetos, donde cada objeto es un cronometraje, que se guarda en el formato:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;segundos&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: tiempo, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;fechaHora&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: fechaHora}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En &lt;code&gt;numSesion&lt;/code&gt; guardo el número de sesión actual. Las sesiones se guardan en &lt;strong&gt;localStorage&lt;/strong&gt; con el nombre que corresponde a su número de orden.&lt;/p&gt;
&lt;p&gt;Uso una sesión o clave guardada en &lt;strong&gt;localStorage&lt;/strong&gt; con el nombre &lt;code&gt;ultSesion&lt;/code&gt; que contiene el número de orden de la última sesión guardada. De esta forma puedo consultarla para saber si hay sesiones guardadas, y cuál es el número de orden de la última que se guardó.&lt;/p&gt;
&lt;p&gt;A la hora de guardar y recuperar las sesiones guardadas en &lt;strong&gt;localStorage&lt;/strong&gt; creí erróneamente que estas se guardaban en orden descendiente, que podía recorrer la lista de claves de &lt;strong&gt;localStorage&lt;/strong&gt; con un bucle, como si se tratase de una pila de datos «&lt;strong&gt;LIFO&lt;/strong&gt;» (&lt;em&gt;Last Input - First Output&lt;/em&gt;), de tal forma que la última clave que añadimos a &lt;strong&gt;localStorage&lt;/strong&gt; sería la primera en la lista, y su número de orden sería 0. Así, si recorría la lista con &lt;code&gt;clave = localStorage.key(i)&lt;/code&gt;, obtendría primero la clave 0, la última, luego la 1, la penúltima, la 2, la antepenúltima, etc… pero esto no funciona siempre así.&lt;/p&gt;
&lt;p&gt;Parece que no podemos confiar en este orden, por lo que las sesiones deben guardarse y recuperarse sin tener en cuenta la posición que ocupan en &lt;strong&gt;localStorage&lt;/strong&gt;, lo que me obligó a reescribir la función &lt;code&gt;historLocal()&lt;/code&gt; (listado del historial) y las «delicadas» funciones &lt;code&gt;borraClave(clave)&lt;/code&gt; (borra una sesión) y &lt;code&gt;ordenaClaves(clave, numSesiones)&lt;/code&gt; (ordena las sesiones cuando hay un hueco) que, sinceramente, me llevaron más tiempo del que merecían hasta que volvieron a estar perfectamente ajustadas.&lt;/p&gt;
&lt;p&gt;Otra cuestión que me sorprendió fue la del manejo de los tiempos en los intervalos empleados en la cuenta regresiva (Contar hasta 10). &lt;strong&gt;Firefox&lt;/strong&gt; y &lt;strong&gt;Chrome&lt;/strong&gt; no funcionan igual. Si contamos desde 10 segundos hasta 0, realmente hay 11 segundos. Pues bien, mientras en Firefox esto funcionaba bien empleando &lt;code&gt;parada10s = setTimeout( parateCrono, 11000);&lt;/code&gt; (parateCrono es una función que para el cronómetro) en Chrome el resultado final de la cuenta regresiva, en vez de &lt;code&gt;0&lt;/code&gt; es &lt;code&gt;-1&lt;/code&gt;, así que debí crear la siguiente función para corregir esto:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; limite&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;miliSeg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; navigator.userAgent.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;indexOf&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Firefox&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; miliSeg &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; miliSeg;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Que comprueba si estamos usando Firefox, entonces devuelve el valor &lt;code&gt;11000&lt;/code&gt; (11 segundos), sino devuelve &lt;code&gt;10000&lt;/code&gt; (10 segundos), para luego poder usarlo de esta forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parada10s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setTimeout&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( parateCrono, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;limite&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Los iconos empleados en los botones inicialmente eran confusos. Con la revisión del compañero del bootcamp &lt;strong&gt;Francesc&lt;/strong&gt; cambié la combinación de iconos para hacer la aplicación más usable.&lt;/p&gt;
&lt;p&gt;Por último, señalar que la aplicación maneja sólo minutos y segundos, hasta un máximo de 3.600 segundos (de 0 a 3.599). Inspirado por la presentación del compañero del bootcamp &lt;strong&gt;Borja&lt;/strong&gt;, incluí el siguiente código dentro de la función que muestra el cronómetro:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (minSeg.minutos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 59&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; minSeg.segundos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 59&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    parateCrono&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnContin, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esto para el cronómetro y pone inactivo el botón de continuar cuando la aplicación llega a 59 minutos y 59 segundos.&lt;/p&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/CronometroJS/index.html&quot;&gt;&lt;button&gt;Usar el cronómetro&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/JavGuerra/CronometroJS&quot;&gt;Ver el código fuente&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/jsref/met_win_settimeout.asp&quot;&gt;setTimeout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/jsref/met_win_setinterval.asp&quot;&gt;setInterval&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://es.javascript.info/localstorage&quot;&gt;localStorage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/cronometro-digital.DrsDXeif_Z1xyUJk.webp"/><category>web</category><category>código</category><category>css</category><category>html</category><category>javascript</category><author>JavGuerra</author></item><item><title>Paginación</title><link>https://javguerra.github.io/blog/paginacion</link><guid isPermaLink="true">https://javguerra.github.io/blog/paginacion</guid><description>Cómo hacer una barra de navegación en JavaScript</description><pubDate>Mon, 30 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/paginacion.Ddenk8LV_Zd8315.webp&quot; alt=&quot;Paginación&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Imaginemos una lista de entradas de un blog, o una galería de imágenes, con un número de items o elementos alto. Pongamos mil. Esto se hace difícil de manejar, tanto por las dimensiones de las pantallas como por el número de elementos al que el usuario prestará atención, y también existe un problema técnico, el consumo de memoria que implica mostrar todos los items de esa lista, y el tiempo que tarda en hacerlo. Ese retraso entre que se carga la página, se «pinta» y se devuelve el control al usuario supone un tiempo de espera incómodo.&lt;/p&gt;
&lt;p&gt;Paginar es mostrar el contenido separado en páginas para, de esta forma, hacerlo más asequible al usuario, y esta es la solución de la que hablaré en esta entrada.&lt;/p&gt;
&lt;h2 id=&quot;planteamiento&quot;&gt;Planteamiento&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Para una mejor comprensión de la resolución de este ejercicio, algunas variables que podrían ser globales, como es el caso de &lt;code&gt;longitud&lt;/code&gt; del vector y otras, se repiten en las disitntas funciones.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;En un vector o array tenemos una serie de elementos o items que queremos mostrar paginados, y queremos que estos items se muestren por ejemplo de diez en diez. Para hacerlo necesitaremos el vector, el número de elementos por página y deberemos averiguar el número de páginas que podemos mostrar. Luego recorreremos las páginas ayudandonos de una variable que hará las veces de índice.&lt;/p&gt;
&lt;p&gt;Para mostrar el resultado, el HTML contendrá lo siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;galeria&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; role&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-live&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;polite&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;navegacion&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;irInic&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Inicio&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;amp;lt;&amp;amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;anteri&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Anterior&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;   id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;pagina&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; role&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-live&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;polite&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;siguie&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Siguiente&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;irFin&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Fin&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;amp;gt;&amp;amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Una sección &lt;code&gt;galeria&lt;/code&gt; donde mostrar los items. en este caso las imágenes.&lt;/p&gt;
&lt;p&gt;Una sección de &lt;code&gt;navegacion&lt;/code&gt; con los botones para recorrer las páginas y donde informar al usuario de la página donde nos econtramos.&lt;/p&gt;
&lt;p&gt;Esto implica la siguiente configuración de valores iniciales en el fichero &lt;code&gt;.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nFotos  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pagina  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; galeria &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Obtener los datos a incluir en galeria */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elGaleria &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#galeria&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elPaginac &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#pagina&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnIrInic &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#irInic&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnAnteri &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#anteri&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnSiguie &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#siguie&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnIrFin  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#irFin&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnIrInic.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inicial;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnAnteri.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; anterior;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnSiguie.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; siguiente;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;btnIrFin.onclick  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; final;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(galeria, pagina, nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Devuelve un elemento */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; elemento&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(sel); }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La variable &lt;code&gt;nFotos&lt;/code&gt; contiene el número de elementos por página.
Iniciamos la variable &lt;code&gt;pagina&lt;/code&gt; a &lt;code&gt;1&lt;/code&gt;, y el vector galeria, que contendrá las rutas a las imagenes, a un vector vacío &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para cargar la lista de imágenes de la galería en el vector &lt;code&gt;galeria&lt;/code&gt;, podemos usar &lt;code&gt;fetch()&lt;/code&gt; contra una &lt;strong&gt;API&lt;/strong&gt; o un &lt;strong&gt;JSON&lt;/strong&gt; guardado localmente, por ejemplo.&lt;/p&gt;
&lt;p&gt;Seguidamente obtenemos los elementos &lt;code&gt;elGaleria&lt;/code&gt; y &lt;code&gt;elPagina&lt;/code&gt; y los cuatro botones para movernos por las páginas de la galería. A cada uno de ellos le asignamos un evento que ejecutará una función al hacer click que nos llevará a la primera página, a la anterior, a la siguiente o a la última respectivamente, alterando el valor de la variable &lt;code&gt;pagina&lt;/code&gt; y llamando a la función que muestra la galería. Veamos estas funciones:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Va a la primera página */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; inicial&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(galeria, pagina, nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Va a la página anterior */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; anterior&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pagina&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(galeria, pagina, nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Va a la página siguiente */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; siguiente&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pagina&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(galeria, pagina, nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Va a la última página */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; final&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; galeria.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ceil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(galeria, pagina, nFotos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cada una de estas cuatro funciones llama a la función &lt;code&gt;paginacion&lt;/code&gt;, para acutalizar el contenido de la galería con tres valores: el vector, la página a mostrar y el número de fotos por página.&lt;/p&gt;
&lt;p&gt;En la función &lt;code&gt;final&lt;/code&gt; calculo el número de páginas posibles atendiendo a la longitud del vector, así, obteniendo el valor entero resultante de dividir la longitud del vector entre el número de imágenes por página devolverá el número de la última página (o el número total de páginas) que guardo en &lt;code&gt;pagina&lt;/code&gt;, valor que necesito para llamar a la función &lt;code&gt;paginacion&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;paginando&quot;&gt;Paginando&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Pagina los elementos de un vector en función de página y elementos por página */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; paginacion&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;pagina&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;elementos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; longitud, numPags, inicio;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vector.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (longitud) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // Averigua el elemento de inicio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        numPags &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ceil&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elementos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numPags) pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numPags;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        inicio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elementos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // Ajusta el número de elementos si se requiere&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elementos) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            elementos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; longitud;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inicio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elementos) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            elementos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inicio;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // Resuelve&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        ctrlBotonesPag&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(pagina, numPags);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        listaElementos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(vector, inicio, elementos); &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta es la función donde se produce la «magia». Tras hallar la longitud del vector recibido, si esta es mayor que cero, paso a calcular primeramente el elemento de &lt;code&gt;inicio&lt;/code&gt; de la página que vamos a mostrar. Si la pagina es 1, elemento del vector que guardará &lt;code&gt;inicio&lt;/code&gt; será &lt;code&gt;0&lt;/code&gt; (cero), si la página es la &lt;code&gt;2&lt;/code&gt; el valor será &lt;code&gt;10&lt;/code&gt;, -pues cabe recordar que el número de elementos por página (&lt;code&gt;nFotos&lt;/code&gt;) es &lt;code&gt;10&lt;/code&gt;-, y así sucesivamente.&lt;/p&gt;
&lt;p&gt;Realizo una serie de comprobaciones para obtener el valor de &lt;code&gt;inicio&lt;/code&gt; adecuado: Si la página que recibimos por parámetros es mayor que el número de páginas posibles del vector, la página a mostrar será la última. Si el valor de página es menor que &lt;code&gt;1&lt;/code&gt;, el valor de página será &lt;code&gt;1&lt;/code&gt;, evitando de esta forma que el programa intente mostrar elementos del vector que no existen.&lt;/p&gt;
&lt;p&gt;Una vez tengo el valor de &lt;code&gt;inicio&lt;/code&gt; veo si es necesario ajustar el número de &lt;code&gt;elementos&lt;/code&gt; que se mostrarán en la página. Así, si el número de &lt;code&gt;elementos&lt;/code&gt; por página (&lt;code&gt;nFotos&lt;/code&gt;) es mayor que el número de items del vector, el valor de &lt;code&gt;elementos&lt;/code&gt; se ajusta al número total de items del vector. Sino, se comprueba si el número de items que quedan por mostrarse en esta página &lt;code&gt;(longitud - inicio)&lt;/code&gt; es menor que el número de &lt;code&gt;elementos&lt;/code&gt; (&lt;code&gt;nfotos&lt;/code&gt;), y si es así, se ajusta el valor de &lt;code&gt;elementos&lt;/code&gt;. Este caso ocurre cuando la última página tiene un número de elementos menor que el de &lt;code&gt;nFotos&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Como ya tengo todo lo que necesito, llamo consecutivamente a dos funciones, la encargada de activar o desactivar los botones &lt;code&gt;ctrlBotonesPag(pagina, numPags);&lt;/code&gt; y la encargada de «pintar» la galería &lt;code&gt;listaElementos(vector, inicio, elementos);&lt;/code&gt; mostrando las fotos y la información relativa a la página. Veamos la primera de ellas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Activa o desactiva los botones según la página */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ctrlBotonesPag&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;pagina&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;numPags&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnIrInic, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnAnteri, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnSiguie, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnIrFin,  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnIrInic, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnAnteri, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (pagina &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numPags) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnSiguie, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btnIrFin,  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función primeramente activa todos los botones, por si fuese el caso de que alguno de los ellos hubiera sido desactivado previamente, y luego comprueba si estamos en la primera página, desactivando entonces los botones de &lt;strong&gt;ir al inicio&lt;/strong&gt; de la galería (&lt;code&gt;btnIrInic&lt;/code&gt;) e &lt;strong&gt;ir a la página anterior&lt;/strong&gt; (&lt;code&gt;btnAnteri&lt;/code&gt;) o si estamos en la última página, desactivando entonces &lt;strong&gt;ir al a página siguiente&lt;/strong&gt; (&lt;code&gt;btnSiguie&lt;/code&gt;) e &lt;strong&gt;ir al final&lt;/strong&gt; de la galería (&lt;code&gt;btnIrFin&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Para activar y desactivar los botones, empleo la siguiente función:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Cambia el estado de un botón dado */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; btnInactivo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;boton&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;estado&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    boton.disabled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; estado;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    boton.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;aria-disabled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, estado);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Recibe como parámetros el botón y el estado que deseamos ponerle: &lt;code&gt;true = inactivo&lt;/code&gt;  o &lt;code&gt;false = activo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Una vez tengo los botones en sus estados correctos, sólo queda mostrar la galería.&lt;/p&gt;
&lt;h2 id=&quot;mostrando&quot;&gt;Mostrando&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Muestra la cantidad de elementos de un vector desde la posición dada */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; listaElementos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;vector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;inicio&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;elementos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; longitud &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vector.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; primero  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inicio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fin &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inicio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elementos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    elGaleria.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    elPaginac.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    botonera&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    vector.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(inicio, fin).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            /*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;             * Código para mostrar la galería&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;             */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    elPaginac.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `Fotos: ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;primero&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} a ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fin&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} de ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;longitud&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    botonera&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Los parámetros que recibimos son el vector (&lt;code&gt;galeria&lt;/code&gt;), el número del item inicial (&lt;code&gt;ìnicio&lt;/code&gt;) y los elementos por página (&lt;code&gt;nFotos&lt;/code&gt;) a mostrar. Con ellos obtengo la &lt;code&gt;longitud&lt;/code&gt;, el número de orden del elemento &lt;code&gt;primero&lt;/code&gt; de la página &lt;code&gt;inicio + 1&lt;/code&gt; y el elemento final del vector que debemos mostrar &lt;code&gt;inicio + elementos&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Seguidamente limpio la página para: el contenido de la galería, el contenido de la info de la paginación, y oculto la botonera. Esto último lo hago con la función &lt;code&gt;botonera(status)&lt;/code&gt; que veremos al finalizar.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;vector.slice(inicio, fin).forEach((urlFoto, i) =&amp;gt; { // })&lt;/code&gt; primeramente obtenemos los elementos del vector que necesitamos con &lt;code&gt;.slice(inicio, fin)&lt;/code&gt; y mediante el &lt;code&gt;.forEach()&lt;/code&gt; itero los elementos a mostrar, obteniendo del vector la url de la foto (&lt;code&gt;urlFoto&lt;/code&gt;) y el índice (&lt;code&gt;i&lt;/code&gt;) de elementos del &lt;code&gt;.forEach()&lt;/code&gt;. Dentro de la función flecha se debe incluir el código para mostrar las imágenes dentro del elemento &lt;code&gt;elGaleria&lt;/code&gt; del &lt;strong&gt;HTML&lt;/strong&gt;, por ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elGaleria.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`&amp;lt;div&amp;gt;&amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; target=&quot;_blank&quot;&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;img src=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; alt=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;primero&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Al terminar de recorrer el vector resultante de aplicar &lt;code&gt;.slice()&lt;/code&gt;, incluyo la información de la página en el elemento &lt;code&gt;elPagina&lt;/code&gt; del &lt;strong&gt;HTML&lt;/strong&gt;, y muestro la botonera que anteriormente oculté. Esta sería la función para hacerlo que mencioné antes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Activa o desactiva la botonera */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; botonera&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnIrInic.style.display &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;initial&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;none&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnAnteri.style.display &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;initial&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;none&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnSiguie.style.display &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;initial&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;none&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnIrFin.style.display  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;initial&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;none&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, &lt;code&gt;true = activa&lt;/code&gt; y &lt;code&gt;false = desactiva&lt;/code&gt; la botonera mostrándola u ocultándola.&lt;/p&gt;
&lt;p&gt;Con esto ya tendríamos presentada la página de la galería con el número de elementos indicado, la información de la página y los botones para movernos por la galería, que era el objetivo de esta entrada.&lt;/p&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Podemos ver un caso de uso en esta:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/17-fetch.html&quot;&gt;&lt;button&gt;galería de perritos&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El ejemplo anterior usa la API &lt;a href=&quot;https://dog.ceo/dog-api/&quot;&gt;Dog CEO&lt;/a&gt;.&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/paginacion.Ddenk8LV_Zd8315.webp"/><category>código</category><category>css</category><category>html</category><category>javascript</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Spinner loader asíncrono</title><link>https://javguerra.github.io/blog/spinner-loader-asincrono</link><guid isPermaLink="true">https://javguerra.github.io/blog/spinner-loader-asincrono</guid><description>Mantiene el spinner activo mientras finalizan todos los procesos asíncronos</description><pubDate>Mon, 30 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/spinner-loader.BwuWn1K3_1CpEz3.webp&quot; alt=&quot;Spin&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Durante los procesos asíncronos que se llevan a cabo, por ejemplo al usar &lt;code&gt;fetch()&lt;/code&gt; para consumir una &lt;strong&gt;API&lt;/strong&gt; remota, se producen retrasos al mostrar los resultados en el navegador. El uso de &lt;em&gt;spinner loader&lt;/em&gt; ayuda a informar al usuario de que uno o varios procesos están en marcha y se está procesando la información que solicitó tal vez mediante un campo de búsqueda.&lt;/p&gt;
&lt;h2 id=&quot;girando&quot;&gt;Girando…&lt;/h2&gt;
&lt;p&gt;Para mostrar un &lt;em&gt;spinner loader&lt;/em&gt; por pantalla cuando uno o varios de estos procesos se estén ejecutando necesitaré:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Una función que active o desactive el &lt;em&gt;spinner loader&lt;/em&gt; según un valor de status &lt;strong&gt;true/false&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Una función que compruebe si hay o no procesos asíncronos activos aún.&lt;/li&gt;
&lt;li&gt;Ubicar en pantalla el &lt;em&gt;spinner loader&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;El &lt;strong&gt;HTML&lt;/strong&gt; deberá contener la siguiente línea:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;dialog&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;zona&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;spinner&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;dialog&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La etiqueta &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; es relativamente desconocida, pero de gran utilidad. La descubrí en &lt;a href=&quot;https://twitter.com/Manz/status/1529836795130744834&quot;&gt;este twitt&lt;/a&gt; de &lt;a href=&quot;https://twitter.com/Manz&quot;&gt;@Manz&lt;/a&gt;. Esta etiqueta permite crear ventanas modales con &lt;strong&gt;HTML&lt;/strong&gt;. &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; muestra una ventana por encima del contenido de la página y aplica un efecto de fondo sombreado al resto de la página.&lt;/p&gt;
&lt;p&gt;Para dibujar el &lt;em&gt;spinner loader&lt;/em&gt;, seguí las indicaciones de la entrada «&lt;a href=&quot;https://midu.dev/como-crear-un-spinner-con-css/&quot;&gt;Cómo crear un spinner loader con CSS&lt;/a&gt;» Este es el código &lt;strong&gt;CSS&lt;/strong&gt; que incluye también el del diálogo.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#zona&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  border&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;none&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  background&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;none&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#zona:focus&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  outline&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;none&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.spinner&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  margin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  border&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; solid&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; LightGray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;36&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;36&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  border-radius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  border-left-color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;LightSeaGreen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  animation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: spin &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; infinite&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@keyframes&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; spin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  0%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;rotate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;deg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  100%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;rotate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;360&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;deg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El modal identificado como &lt;code&gt;#zona&lt;/code&gt; se mostrará sin fondo y sin borde, osea, totalmente transparente. En él muestro el &lt;em&gt;spinner loader&lt;/em&gt;. &lt;code&gt;#zona&lt;/code&gt; tendrá el tamaño del  &lt;em&gt;spinner loader&lt;/em&gt;, y aparecerá centrado tanto vertical como horizontalmente en la pantalla, manteniéndose centrado aún haciendo &lt;em&gt;scroll&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;.spinner&lt;/code&gt;se describe el aspecto del &lt;em&gt;spinner loader&lt;/em&gt; y se indicará que debe animarse infinitamente girando 360 grados cada segundo.&lt;/p&gt;
&lt;h2 id=&quot;activando--desactivando&quot;&gt;Activando / desactivando&lt;/h2&gt;
&lt;p&gt;Como estamos trabajando con procesos asíncronos, se puede dar el caso de que, al lanzar un proceso asíncrono, el &lt;em&gt;spinner loader&lt;/em&gt; ya esté mostrado, por tanto no tendremos que mostrarlo. Debo controlar si hay procesos asíncronos en marcha. Esto lo hago con una simple variable &lt;code&gt;spin&lt;/code&gt; que va incrementando o decrementando su valor según el número de procesos asíncronos lanzados.&lt;/p&gt;
&lt;p&gt;Inicializo también la variable &lt;code&gt;intervalo&lt;/code&gt; que usaré para controlar un &lt;code&gt;setInterval()&lt;/code&gt; que comprueba periódicamente el estado de los procesos asíncronos, osea, la variable &lt;code&gt;spin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Capturo la &lt;code&gt;#zona&lt;/code&gt; donde se mostrará el diálogo modal con el &lt;em&gt;spinner loader&lt;/em&gt;, como se muestra a continuación:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spin &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; intervalo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elZona   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#zona&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Veamos cómo funciona la activación o desactivación asíncronas mediante el siguiente código:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Activa o desactiva el spin */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ponSpin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;estado&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    estado &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (estado &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;intervalo) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        intervalo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setInterval&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(compruebaSpin, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;300&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        elZona.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;showModal&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Comprueba si el spin ha llegado a cero y desactiva comprobación */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compruebaSpin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;spin) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        clearInterval&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(intervalo);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        intervalo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        elZona.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(); &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cuando iniciamos un proceso asíncrono, se debe llamar a la función &lt;code&gt;ponSpin(true)&lt;/code&gt; con el valor &lt;code&gt;true&lt;/code&gt;, esto incrementará en &lt;code&gt;1&lt;/code&gt; el valor de &lt;code&gt;spin&lt;/code&gt;. Sólo si estoy incrementando &lt;code&gt;spin&lt;/code&gt; (&lt;code&gt;estado = true&lt;/code&gt;), y es la primera vez que se activa (&lt;code&gt;!intervalo&lt;/code&gt;), lanzo &lt;code&gt;compruebaSpin()&lt;/code&gt; cada 300 milisegundos con &lt;code&gt;intervalo = setInterval(compruebaSpin, 300);&lt;/code&gt;y muestro la ventana modal que contiene el &lt;em&gt;spinner loader&lt;/em&gt; con &lt;code&gt;elZona.showModal();&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Es necesario lanzar el &lt;code&gt;setInterval()&lt;/code&gt; porque desconocemos en qué momento los procesos asíncronos terminarán, por lo que se debe comprobar el estado de los procesos cada cierto tiempo.&lt;/p&gt;
&lt;p&gt;Al finalizar un proceso asíncrono debemos llamar de nuevo a la función con &lt;code&gt;ponSpin(false)&lt;/code&gt;, y el valor &lt;code&gt;false&lt;/code&gt; decrementará en &lt;code&gt;1&lt;/code&gt; el valor de &lt;code&gt;spin&lt;/code&gt;, que irá decreciendo hasta llegar a &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;La función &lt;code&gt;compruebaSpin()&lt;/code&gt;, como vimos, es lanzada cada 300 milisegundos, y su función es comprobar si &lt;code&gt;spin&lt;/code&gt; ha llegado a &lt;code&gt;0&lt;/code&gt;, y si es así, desactiva el &lt;code&gt;setInterval()&lt;/code&gt; y oculta la ventana modal que contiene el &lt;em&gt;spinner loader&lt;/em&gt; con &lt;code&gt;elZona.close();&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Importante&lt;/strong&gt;: Hay que ser cuidadoso para indicar tantos cierres del &lt;em&gt;spinner loader&lt;/em&gt; como aperturas se llevan a cabo, es decir, por cada &lt;code&gt;ponSpin(true)&lt;/code&gt; debe haber un &lt;code&gt;ponSpin(false)&lt;/code&gt;, de otra forma, podemos quedarnos con un &lt;em&gt;spinner loader&lt;/em&gt; girando indefinidamente o que se cerró antes de haber concluido todos los procesos asíncronos.&lt;/p&gt;
&lt;p&gt;Este podría ser un ejemplo de código para poner en marcha y concluir un &lt;em&gt;spinner loader&lt;/em&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/* Consulta la API en la ruta dada y ejecuta la función callback() */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; consultaAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ruta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    ponSpin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    fetch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ruta)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;respuesta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// fetch() no maneja errores de conexión, luego...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;respuesta.ok) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(respuesta.statusText);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(data))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;finally&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ponSpin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Podemos ver un caso de uso en esta &lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/17-fetch.html&quot;&gt;&lt;button&gt;galería de perritos&lt;/button&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El ejemplo anterior usa la API &lt;a href=&quot;https://dog.ceo/dog-api/&quot;&gt;Dog CEO&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Info sobre la etiqueta &lt;a href=&quot;https://twitter.com/Manz/status/1529836795130744834&quot;&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Artículo «&lt;a href=&quot;https://midu.dev/como-crear-un-spinner-con-css/&quot;&gt;Cómo crear un spinner loader con CSS&lt;/a&gt;».&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/spinner-loader.BwuWn1K3_1CpEz3.webp"/><category>código</category><category>css</category><category>html</category><category>javascript</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Contador de resultados</title><link>https://javguerra.github.io/blog/contador-resultados</link><guid isPermaLink="true">https://javguerra.github.io/blog/contador-resultados</guid><description>Gráfica SVG dinámica en JavaScript con aguja indicadora de resultados</description><pubDate>Sat, 04 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/contador.CvHdujvp_ZAoCzg.webp&quot; alt=&quot;Contador&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#svg&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;La información visual es percibida con más claridad que la escrita. A la hora de mostrar resultados, por ejemplo los aciertos o fallos de un examen on-line, podemos complementar la información escrita con una gráfica dinámica que muestre los resultados de un vistazo, aportando además valor al resultado.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/contador.html&quot;&gt;&lt;button&gt;Ver contador de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;el-contador&quot;&gt;El contador&lt;/h2&gt;
&lt;p&gt;Para mostrar la información de este ejemplo, he elaborado una gráfica en formato .SVG que contiene un contador en semicírculo con paneles descriptivos. La aguja apunta a los paneles rotulados con el texto: «insuficiente», «regular», «bien» y «excelente» según un resultado numérico entre 0 y 10, donde 0 es ninguna pregunta acertada y diez corresponde a un total de diez sobre diez preguntas contestadas correctamente.&lt;/p&gt;
&lt;p&gt;El fichero SVG lo he creado con &lt;a href=&quot;https://inkscape.org/es/&quot;&gt;InkScape&lt;/a&gt;, una herramienta libre de dibujo vectorial. el diseño asemeja algunas imágenes que encontré haciendo una búsqueda por Internet. Para su elaboración, he tenido en cuenta dos cuestiones importantes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;El tamaño del dibujo tiene las proporciones (ancho x alto) de la imagen que se mostrará en la página. En el caso de este contador, 400px x 240px. Es importante guardar el documento con la medida en píxeles, para poder trabajar después con el tamaño de la imagen desde CSS, si queremos aplicarle distintos tamaños, por ejemplo para la visualización de esta gráfica en diferentes tipos de pantalla (móviles, tablets…).&lt;/li&gt;
&lt;li&gt;La gráfica cuenta con una aguja indicadora. Para poder acceder a ella desde JavaScript y que la aguja apunte adecuadamente, he incluido una etiqueta ID (&lt;code&gt;id=&quot;aguja&quot;&lt;/code&gt;) en el elemento SVG que agrupa las líneas del dibujo que corresponden a la aguja. Esto podemos hacerlo directamente desde InkScape. En este caso, el elemento quedaría así:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;aguja&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;matrix(.28946 0 0 .28839 126 -138.93)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El atributo «transform» dentro del SVG indica la posición de la aguja, su tamaño y ángulo de giro. El que se muestra aquí corresponde a la aguja en posición vertical, equivalente a un resultado de 5, entre 0 y 10. Para cubrir todo el rango de puntuaciones, la aguja debe girar 18 grados en un sentido y en otro, es decir, que irá girando de 0 a 180 grados en saltos de 18 grados.&lt;/p&gt;
&lt;p&gt;Calcular los valores de la posición de la aguja en cada uno de esos intervalos no es tarea fácil. Para acortar camino, guardé la misma gráfica con la aguja en las distintas 11 posiciones y obtuve el valor de transform en cada una de ellas. Este será el valor que luego pasaremos a la gráfica para indicar qué posición debe tener la aguja en función de la puntuación obtenida. Esta es la tabla obtenida:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/ejercicios-web-javascript/img/contadores.png&quot; alt=&quot;Contadores&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align: left&quot;&gt;Puntos&lt;/th&gt;
&lt;th style=&quot;text-align: left&quot;&gt;Valores de la aguja&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(0 -.28946 .28839 0 -139.16 -20.501)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.089449 -.2753 .27428 .089119 -107.1 -76.177)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.17014 -.23418 .23332 .16951 -59.407 -119.22)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.23418 -.17014 .16951 .23332 -.74583 -145.42)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.2753 -.089449 .089119 .27428 63.14 -152.21)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.28946 0 0 .28839 126 -138.93)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.2753 .089449 -.089119 .27428 181.67 -106.87)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.23418 .17014 -.16951 .23332 224.72 -59.174)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.17014 .23418 -.23332 .16951 250.92 -.51273)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(.089449 .2753 -.27428 .089119 257.71 63.373)”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;10&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;transform=“matrix(0 .28946 -.28839 0 244.42 126.23)”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Teniendo el SVG y esta información, usando JavaScript podemos mostrar una gráfica dinámica de resultados.&lt;/p&gt;
&lt;h2 id=&quot;presentación&quot;&gt;Presentación&lt;/h2&gt;
&lt;p&gt;En el ejemplo, la gráfica aparece con un recuadro de texto debajo que indica también el resultado. Mediante CSS posiciono la gráfica con un valor de margen superior negativo para que esta quede justo por encima del recuadro, lo que consigue el efecto de que la gráfica y el recuadro está unidos por la intersección de la aguja.&lt;/p&gt;
&lt;p&gt;El código html sería el siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;resultados&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 105.83 58.208&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Contador con aguja&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;La aguja indica los aciertos de 0 a 10 en un contador en forma de semicírculo que tiene cuatro zonas rotuladas con el texto: «insuficiente», «regular», «bien» y «excelente».&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;aguja&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;matrix(.28946 0 0 .28839 126 -138.93)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;nota&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;0&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt; de 10 aciertos&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para no ocupar espacio de esta entrada el SVG no se muestra completo. Los puntos suspensivos corresponden a las etiquetas que deberían estar ahi. El SVG como se aprecia, estaría incrustado, completo, y el elemento que agrupa a los elementos que dibujan la aguja bien identificado.&lt;/p&gt;
&lt;p&gt;En el párrafo se mostraría el resultado de forma textual. ambos, imagen y resultado, están dentro de un DIV contenedor llamado «resultados».&lt;/p&gt;
&lt;p&gt;La gráfica en SVG ocupa lo suyo. Hay técnicas para &lt;a href=&quot;/blog/carga-svg&quot;&gt;cargar dinámicamente la imagen&lt;/a&gt; sin necesidad de colocar el SVG in-line desde el principio. Por ahora el SVG aparecerá incrustado en la página, ya que si lo enlazamos como una imagen (&lt;code&gt;&amp;lt;img src=&quot;contador.svg&quot; alt=&quot;Contador&quot;/&amp;gt;&lt;/code&gt;) no podremos acceder a la etiqueta «aguja» que necesitamos para hacer la gráfica interactiva.&lt;/p&gt;
&lt;p&gt;Deliberadamente he eliminado las etiquetas &lt;code&gt;width&lt;/code&gt; y &lt;code&gt;height&lt;/code&gt; de &lt;code&gt;svg&lt;/code&gt; para poderlas manejar desde CSS.&lt;/p&gt;
&lt;p&gt;Los estilos CSS para mostrar correctamente estos elementos son los siguientes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#resultados&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;480&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    margin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    text-align&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    background-color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;lightblue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    border-radius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    border-bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; solid&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; lightslategray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#resultados&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    margin-top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;-220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;400&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#resultados&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    margin-top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    margin-bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    font-family&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Arial&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Helvetica&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sans-serif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    font-size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: xxx-large;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    text-shadow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DimGray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;dinamismo&quot;&gt;Dinamismo&lt;/h2&gt;
&lt;p&gt;Ya disponemos de la gráfica incrustada en el HTML correctamente representada con CSS, y la tabla de posiciones de la aguja, y en esta parte veremos el motivo de toda esta preparación.&lt;/p&gt;
&lt;p&gt;El siguiente código en JavaScript permite obtener el resultado esperado:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nota&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;nota&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aciertos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;random&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nota.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aciertos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ponAguja&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(aciertos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ponAguja&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;aciertos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; aguja&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;aguja&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; posicionAguja&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;0 -.28946 .28839 0 -139.16 -20.501&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.089449 -.2753 .27428 .089119 -107.1 -76.177&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.17014 -.23418 .23332 .16951 -59.407 -119.22&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.23418 -.17014 .16951 .23332 -.74583 -145.42&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.2753 -.089449 .089119 .27428 63.14 -152.21&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.28946 0 0 .28839 126 -138.93&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.2753 .089449 -.089119 .27428 181.67 -106.87&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.23418 .17014 -.16951 .23332 224.72 -59.174&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.17014 .23418 -.23332 .16951 250.92 -.51273&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;.089449 .2753 -.27428 .089119 257.71 63.373&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &apos;0 .28946 -.28839 0 244.42 126.23&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    aguja.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;transform&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`matrix(${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posicionAguja&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;aciertos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;})`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obtengo el elemento «nota» donde pondremos el número de aciertos.&lt;/p&gt;
&lt;p&gt;La variable «aciertos», en este ejemplo, se obtiene aleatoriamente en un rango entero entre 0 y 10.&lt;/p&gt;
&lt;p&gt;Pongo los aciertos y llamo a la función &lt;code&gt;ponAguja(aciertos)&lt;/code&gt; y le paso el parámetro «aciertos».&lt;/p&gt;
&lt;p&gt;La función obtiene el elemento del SVG identificado con «aguja», y contiene un arreglo &lt;code&gt;posicionAguja[]&lt;/code&gt; con todos los valores posibles para la aguja, desde 0 a 10.&lt;/p&gt;
&lt;p&gt;En la última línea, cambiamos el valor del atributo ‘transform’ del SVG con el valor correspondiente a los aciertos guardado en el arreglo &lt;code&gt;posicionAguja[]&lt;/code&gt;;&lt;/p&gt;
&lt;h2 id=&quot;el-código-completo&quot;&gt;El código completo&lt;/h2&gt;
&lt;p&gt;Con cada recarga de la página, la gráfica y el cuadro de texto mostrarán un valor distinto.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; http-equiv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;X-UA-Compatible&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;IE=edge&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Contador&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #resultados&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;480&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            margin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            text-align&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            background-color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;lightblue&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            border-radius&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            border-bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; solid&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; lightslategray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #resultados&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            margin-top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;-220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;400&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;220&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #resultados&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            margin-top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            margin-bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;em&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            font-family&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Arial&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Helvetica&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sans-serif&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            font-size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: xxx-large;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            text-shadow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DimGray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;resultados&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 105.83 58.208&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Contador con aguja&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;La aguja indica los aciertos de 0 a 10 en un contador en forma de semicírculo que tiene cuatro zonas rotuladas con el texto: «insuficiente», «regular», «bien» y «excelente».&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; clip-path&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#a)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m52.914-0.001674c-4.7395 0-9.4778 0.63742-14.085 1.9017-0.06321 0.01729-0.12652 0.03416-0.18965 0.05168-0.24752 0.0689-0.49482 0.1388-0.74157 0.21136-0.29501 0.08651-0.58912 0.17555-0.88262 0.26716-0.16716 0.05233-0.33398 0.10566-0.50075 0.15968-0.35229 0.1138-0.70374 0.23024-1.0537 0.3514-0.09768 0.03392-0.19494 0.06936-0.2925 0.10387-0.40857 0.14415-0.81597 0.2918-1.2211 0.44596-0.0026 6.09e-4 -0.0032 0.0015-0.0048 0.0021-2.598 0.98893-5.1231 2.1832-7.5494 3.576-3.2712 1.8893-6.2375 4.028-9.0004 6.5319-10.096 9.0697-16.394 21.745-17.385 35.433-0.01191 0.16487-0.0085 0.32633 0.0026 0.48575-0.07855 1.0993-0.12549 2.2058-0.13951 3.3186l106.09 2.7e-5c-0.01-1.1385-0.0541-2.2702-0.13229-3.3946 6e-3 -0.13439 5e-3 -0.27062-5e-3 -0.40876-0.93929-12.97-6.6434-25.03-15.827-33.976l7e-3 -0.0072c-3.2035-3.1564-6.6655-5.7325-10.563-7.984-4.1446-2.3803-8.5755-4.1793-13.168-5.3666-0.0541-0.01402-0.10813-0.02852-0.16227-0.04237-0.40282-0.10279-0.80713-0.20018-1.2123-0.29352-0.12364-0.02855-0.24725-0.05658-0.37105-0.08423-0.37005-0.08246-0.74075-0.16212-1.1126-0.23668-0.15193-0.03054-0.30417-0.05865-0.4563-0.08785-0.27332-0.05233-0.54692-0.10285-0.82114-0.1509-0.24984-0.04391-0.50001-0.08526-0.75033-0.12557-0.21667-0.03478-0.43346-0.06866-0.65061-0.10077-0.41838-0.06208-0.83732-0.11847-1.2568-0.17053-0.07014-0.0087-0.14015-0.01845-0.21032-0.02687-0.0066-7.93e-4 -0.01323-0.0013-0.01958-0.0021-0.27715-0.03317-0.55448-0.06421-0.832-0.09302-1.8286-0.18982-3.6647-0.28891-5.501-0.28891z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#fff&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.26458&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.28892&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m14.799 16.135c-9.531 9.9166-14.753 22.823-14.928 36.701h31.392c0.09043-5.5163 2.2581-10.797 6.0732-14.796z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#f97301&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m51.864 0.020187c-8.951 0.16984-17.713 2.594-25.47 7.0468-3.8979 2.2513-7.365 4.8542-10.568 8.0106l22.427 22.033c3.7181-3.4716 8.5272-5.555 13.612-5.8964z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#ffe900&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m91.031 16.135c9.5273 9.8511 14.813 22.791 14.928 36.701h-31.392c-0.090433-5.5163-2.2581-10.797-6.0732-14.796z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#0cb200&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m53.271 0.0057678v31.169c5.333 0.1904 10.417 2.2988 14.309 5.9351l22.422-22.06c-3.2035-3.1564-6.6654-5.7323-10.563-7.9838-7.9616-4.5724-16.979-7.0059-26.168-7.0615z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#9bd701&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m53.118 8.6805c-11.772 0.0020187-23.065 4.6483-31.409 12.922-8.3434 8.2745-13.059 19.504-13.115 31.233h3.1687c-0.0035-0.08667-0.0067-0.17336-0.0097-0.26006 0-10.911 4.3503-21.375 12.094-29.09 7.7436-7.715 18.246-12.049 29.198-12.049 10.951-3.7e-5 21.454 4.3342 29.198 12.049 7.7436 7.715 12.094 18.179 12.094 29.09-3e-3 0.0867-0.0062 0.17339-0.0097 0.26006h3.3207c-0.056473-11.73-4.7727-22.96-13.118-31.236-8.3448-8.2759-19.639-12.92-31.412-12.92z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#808080&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill-opacity&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.5&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.079454&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m53.286 0v8.6857c11.439 0.052083 22.391 4.479 30.636 12.384l6.0792-6.0175c-3.1719-3.091-6.7207-5.773-10.563-7.9838-7.9573-4.577-16.97-7.0047-26.154-7.0684zm-1.3525 0.020101c-8.9701 0.16618-17.759 2.5737-25.538 7.0483-3.9002 2.2434-7.431 4.9511-10.568 8.0106l6.2254 6.2024c8.0259-7.7926 18.696-12.272 29.881-12.571zm-37.062 16.013c-9.4804 9.73-14.999 22.87-14.999 36.804h8.7223c0.055006-11.435 4.5492-22.387 12.506-30.598zm76.125 0.01402-6.0416 6.0193c8.0762 8.2283 12.627 19.261 12.693 30.768h8.3133c-8.6e-4 -13.734-5.3674-26.929-14.964-36.79z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#e5e5e5&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.079454&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m12.171 24.438 0.99192-1.3687 0.2474 0.17797-0.77966 1.0758 0.64324 0.46272 0.7471-1.0309 0.2474 0.17797-0.7471 1.0309 0.78733 0.56637 0.79859-1.1019 0.2474 0.17797-1.0108 1.3948zm-1.511 2.3014 1.2275-1.899 0.25655 0.16461-0.51509 0.79688 1.9966 1.281-0.19729 0.30523-1.9966-1.281-0.51509 0.79688zm-1.2563 2.1918 0.24028-0.42344 2.5365 0.06864-1.9517-1.0993 0.17314-0.30514 2.3329 1.314-0.24028 0.42344-2.5365-0.06864 1.9517 1.0993-0.17314 0.30514zm-1.1115 2.2062 0.74762-1.515 0.27384 0.13414-0.58763 1.1908 0.71198 0.34875 0.56309-1.1411 0.27384 0.13413-0.56309 1.1411 0.87148 0.42688 0.60187-1.2197 0.27384 0.13413-0.76186 1.5439zm-0.4834 1.0786 0.14749-0.33 2.4482 1.086-0.14748 0.33zm-0.083943 0.6806 0.3552 0.14092q-0.22616 0.10662-0.38157 0.26826-0.15474 0.15998-0.24107 0.37597-0.16999 0.42535 0.00145 0.75518 0.16984 0.32917 0.66347 0.52498 0.49197 0.19516 0.84409 0.07307 0.35045-0.12275 0.52045-0.54808 0.086326-0.21599 0.084311-0.43815-0.00145-0.22382-0.092045-0.45615l0.35187 0.13959q0.049683 0.22375 0.030697 0.44527-0.018323 0.21987-0.10597 0.43919-0.22511 0.56326-0.6998 0.75028-0.47636 0.18638-1.0751-0.05113-0.60034-0.23817-0.81607-0.69912-0.21738-0.4616 0.00773-1.0249 0.08898-0.22264 0.22737-0.39486 0.13739-0.17456 0.32486-0.30039zm-1.3344 2.8983 0.12082-0.34062 2.5268 0.88968-0.12082 0.34059zm-0.68313 2.0879 0.46418-1.4631 0.29097 0.09163-0.35491 1.1186 0.75306 0.23717 0.32029-1.0095 0.29097 0.09163-0.32029 1.0095 1.2203 0.38431-0.10928 0.34445zm-0.75549 2.7512 0.092676-0.35109 1.5745 0.41254q0.41662 0.10916 0.64037 0.0069 0.22199-0.10271 0.31102-0.43997 0.088566-0.33554-0.05399-0.53375-0.14429-0.19869-0.56092-0.30786l-1.5745-0.41254 0.092676-0.35109 1.6179 0.42393q0.5069 0.13282 0.69936 0.45139 0.19292 0.31683 0.064176 0.80455-0.1292 0.48946-0.45405 0.67247-0.3244 0.18128-0.8313 0.04847zm-0.095522 0.81326 0.34599 0.07269q-0.13919 0.18094-0.22438 0.34947-0.085197 0.16852-0.12038 0.33476-0.061105 0.28874 0.017976 0.46984 0.079448 0.17935 0.2867 0.22289 0.17388 0.03653 0.28531-0.0479 0.11004-0.08655 0.22596-0.36559l0.08909-0.20426q0.15922-0.37961 0.39028-0.52663 0.22969-0.14914 0.54934-0.08199 0.38113 0.08007 0.52378 0.37687 0.14302 0.29505 0.038953 0.78679-0.039254 0.18549-0.12585 0.38662-0.086221 0.19938-0.21617 0.40602l-0.36533-0.07675q0.16674-0.18978 0.27191-0.38336t0.14739-0.39305q0.064066-0.30272-0.020552-0.49231-0.084624-0.18958-0.30593-0.23607-0.1932-0.04059-0.32726 0.05553-0.13371 0.09437-0.24518 0.35241l-0.087706 0.20638q-0.16273 0.37886-0.36874 0.5202-0.20601 0.14132-0.50635 0.07822-0.34776-0.07305-0.49651-0.35835-0.14838-0.28705-0.057652-0.71576 0.038886-0.18374 0.11262-0.36747 0.073737-0.18373 0.1827-0.3692zm-0.90022 4.3749 0.077792-0.48023 2.4026-0.81286-2.2133-0.3559 0.056057-0.34604 2.6457 0.42543-0.077795 0.48023-2.4026 0.81286 2.2133 0.3559-0.05606 0.34604zm-0.14762 1.1651 0.045312-0.35841 2.6589 0.33367-0.045312 0.35841zm97.927-3.1896 0.24568 1.6704-0.30194 0.04407-0.19312-1.3129-0.78501 0.11461 0.18504 1.2581-0.30194 0.04408-0.18504-1.2581-0.96082 0.14028 0.19779 1.3448-0.30194 0.04408-0.25036-1.7022zm-0.49787-2.682 0.42747 2.2182-0.29968 0.05732-0.17938-0.93084-2.3322 0.44611-0.06871-0.35654 2.3322-0.44611-0.17939-0.93084zm-0.58818-2.434 0.11608 0.47247-1.8951 1.681 2.1776-0.5311 0.0836 0.34047-2.6031 0.63486-0.11609-0.47247 1.8951-1.681-2.1776 0.5311-0.08365-0.34047zm-0.6953-2.3561 0.48974 1.6162-0.29212 0.08787-0.38496-1.2703-0.75951 0.22846 0.36886 1.2173-0.29212 0.08787-0.36886-1.2173-0.92966 0.27964 0.3943 1.3012-0.29212 0.08787-0.49909-1.647zm-0.71033-2.0476 0.1211 0.3405-2.2384 0.79025 0.43587 1.2255-0.28762 0.10155-0.55698-1.566zm-0.90804-2.2725 0.64298 1.5619-0.28233 0.11536-0.5054-1.2277-0.73404 0.29993 0.48427 1.1764-0.28233 0.11536-0.48427-1.1764-0.89846 0.36712 0.51764 1.2575-0.28233 0.11536-0.65522-1.5917zm-0.46632-0.55948-0.34509 0.16395q0.07511-0.23777 0.06165-0.46119-0.01271-0.22182-0.11314-0.43166-0.19778-0.41323-0.55724-0.51192-0.35783-0.09945-0.83741 0.12839-0.47796 0.22707-0.62726 0.56746-0.14768 0.33961 0.0501 0.75284 0.10044 0.20985 0.26544 0.3593 0.16577 0.15107 0.3985 0.2426l-0.34185 0.16242q-0.19855-0.11568-0.34883-0.28007-0.1495-0.16276-0.25148-0.37583-0.26191-0.54722-0.07718-1.0213 0.18635-0.47489 0.768-0.75123 0.58326-0.2771 1.0693-0.12167 0.48765 0.15466 0.74959 0.70188 0.10353 0.21631 0.13636 0.43449 0.03523 0.21904 5.78e-4 0.44158zm-1.8763-4.1153 0.18709 0.34039-0.55394 1.0587 1.1954 0.10835 0.18709 0.34039-1.5427-0.13704-0.7803 1.4697-0.18709-0.34039 0.63762-1.2042-1.3644-0.11806-0.18795-0.34194 1.7143 0.15146zm-1.2157-1.9899 0.89293 1.4348-0.25934 0.16021-0.70185-1.1278-0.6743 0.41655 0.67253 1.0807-0.25934 0.16021-0.67253-1.0807-0.82531 0.50984 0.71887 1.1551-0.25934 0.16021-0.90995-1.4621zm-20.071-17.151 0.44154 0.20757 0.11797 2.5253 0.95669-2.0201 0.31818 0.14958-1.1436 2.4147-0.44154-0.20757-0.11797-2.5253-0.9567 2.0201-0.31817-0.14958zm-2.2809-0.94304 1.5694 0.63659-0.11507 0.28158-1.2336-0.50039-0.29919 0.73211 1.182 0.47948-0.11507 0.28158-1.182-0.47948-0.36617 0.89609 1.2635 0.51253-0.11507 0.28158-1.5993-0.64873zm-1.1057-0.40663 0.34052 0.12414-0.92092 2.5074-0.34052-0.12413zm-2.5733 0.60562-0.30266 0.93061 0.55324 0.17861q0.27833 0.089862 0.44861 0.018861 0.17252-0.072138 0.24943-0.30861 0.07746-0.23818-0.0209-0.394-0.09612-0.15699-0.37444-0.24684zm0.33974-1.0446-0.24899 0.76556 0.51055 0.16483q0.25272 0.081588 0.40611 0.027714 0.15564-0.05503 0.21872-0.24897 0.06252-0.19224-0.03114-0.32776-0.09196-0.13496-0.34469-0.21655zm-0.25308-0.39377 0.88112 0.28446q0.39445 0.12734 0.55478 0.35956 0.16033 0.23223 0.06239 0.53335-0.0758 0.23307-0.22991 0.3356-0.1541 0.10252-0.3769 0.068187 0.23672 0.13658 0.32032 0.35533 0.08584 0.21758 0.0017 0.47619-0.11066 0.34024-0.40322 0.45072-0.29253 0.11046-0.72116-0.027916l-0.91523-0.29548zm-25.533-0.24008q0.12254 0.01243 0.25808 0.11367 0.13729 0.10082 0.29618 0.29577l0.5219 0.62961-0.37971 0.086471-0.48742-0.5916q-0.18948-0.23202-0.33158-0.28954-0.14034-0.057935-0.35033-0.010122l-0.38498 0.087665 0.25238 1.1001-0.35349 0.080495-0.59716-2.6029 0.79792-0.18171q0.44797-0.10201 0.71123 0.034324 0.26328 0.13633 0.34967 0.5129 0.05639 0.24582-0.02191 0.43426-0.07655 0.18804-0.28088 0.30062zm-1.1362-0.89147 0.21198 0.924 0.44447-0.10121q0.25548-0.058183 0.35818-0.20448 0.10404-0.14843 0.05165-0.37681-0.0524-0.22838-0.21003-0.31357-0.15629-0.087319-0.41176-0.029139zm-2.0189 0.58866-0.11033 1.412 0.94827-0.26718zm-0.29412-0.28697 0.39555-0.11145 1.7121 2.2923-0.36272 0.1022-0.42198-0.5929-1.1624 0.32752-0.04782 0.72527-0.3679 0.10366zm-2.8118 0.88683 0.34385-0.11462 0.75349 2.2437 1.2375-0.41251 0.09682 0.28831-1.5814 0.52712zm-2.6804 1.0151 0.33936-0.13217 0.59273 1.5107q0.15684 0.39974 0.37155 0.51965 0.21406 0.11825 0.54007-0.00871 0.32434-0.12631 0.40116-0.35783 0.07617-0.2332-0.08067-0.63296l-0.59272-1.5107 0.33936-0.13217 0.60908 1.5523q0.19082 0.48637 0.04578 0.82895-0.14337 0.34194-0.61481 0.52553-0.47312 0.18426-0.81292 0.03048-0.33812-0.15442-0.52893-0.64077zm-0.08394 2.5292-0.30055-0.65162-0.53822 0.24642-0.12442-0.26975 0.86444-0.39579 0.48045 1.0416q-0.12862 0.22225-0.32637 0.3974-0.1985 0.17354-0.45946 0.293-0.57084 0.26136-1.0467 0.07772-0.47495-0.18602-0.74854-0.77914-0.27432-0.59475-0.10591-1.0734 0.16929-0.48098 0.74015-0.74234 0.23813-0.10902 0.47877-0.14834 0.24228-0.040072 0.47579-0.00908l0.16114 0.34938q-0.25388-0.070739-0.49535-0.05465-0.24148 0.016092-0.4682 0.11989-0.4469 0.2046-0.5573 0.55628-0.10878 0.35091 0.11833 0.84328 0.22635 0.49075 0.56448 0.63708 0.33977 0.14557 0.78666-0.059034 0.17452-0.079901 0.29803-0.17188 0.12277-0.093603 0.20281-0.20701zm-4.8108-0.18745 1.4983-0.78852 0.14253 0.26882-1.1777 0.61978 0.37057 0.69894 1.1285-0.59391 0.14253 0.26882-1.1285 0.59391 0.45358 0.85548 1.2062-0.63483 0.14253 0.26882-1.5268 0.80357zm-0.50656 1.9236q0.1204-0.0259 0.28071 0.02861 0.16185 0.05359 0.37343 0.19008l0.69169 0.43804-0.3343 0.19918-0.64709-0.41251q-0.25219-0.1623-0.40519-0.17325-0.15144-0.01185-0.3363 0.09828l-0.3389 0.20194 0.58135 0.96847-0.31117 0.18542-1.3755-2.2915 0.70246-0.41857q0.39436-0.23498 0.68706-0.18641 0.29267 0.04857 0.49168 0.3801 0.1299 0.21641 0.11391 0.41972-0.01444 0.2024-0.17385 0.3724zm-1.3572-0.49788 0.48829 0.81346 0.39129-0.23315q0.22492-0.13401 0.27718-0.30477 0.05289-0.17321-0.0678-0.37427t-0.29704-0.23352q-0.17573-0.03491-0.40064 0.09911z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.076444&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;aguja&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;matrix(.28946 0 0 .28839 126 -138.93)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m-253.45 566.27c-1.858 2e-3 -3.7288 2.2916-3.7828 5.1506l-14.79 85.096c-0.58463 3.3637-0.30092 4.8301-0.31528 8.1508 0 10.432 8.4567 18.888 18.888 18.888 10.432 0 18.888-8.9443 18.888-19.376 0-3.3866 0.21618-4.1153-0.4047-7.5835l-15.237-85.113c1.5e-4 -2.8995-1.4061-5.2129-3.2465-5.213z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m-253.45 566.27c-1.858 2e-3 -3.7288 2.2916-3.7828 5.1506l-14.79 85.096c-0.58463 3.3637-0.61848 4.7142-0.31528 8.151 0 10.432 8.4567 18.888 18.888 18.888z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#666&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;circle&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;-253.45&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;664.67&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;9.7464&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#666&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m-253.45 654.92a9.7464 9.7464 0 0 0-9.7464 9.7464 9.7464 9.7464 0 0 0 9.7464 9.7464z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;clipPath&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m23.149 9.0991c-13.438 9.0736-21.972 23.8-23.14 39.93-0.15217 2.1011 1.5767 3.8119 3.6915 3.8119h23.734c2.1149 0 3.8162-1.7234 4.2038-3.792 1.684-8.9862 8.8444-16.036 17.883-17.606 2.0808-0.36161 5.5414-0.36701 7.6197 7e-3 8.8097 1.5835 15.08 8.6234 16.556 17.595 0.34174 2.0774 2.0454 3.7972 4.1604 3.7972h24.273c2.1149 0 3.8437-1.7107 3.6915-3.8119-1.1682-16.131-9.7021-30.858-23.14-39.931-1.7503-1.1818-4.7243-2.8926-6.6269-3.8119-14.606-7.0578-31.673-7.0578-46.279 0-1.9025 0.91927-4.8765 2.63-6.6269 3.8119z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#0f0&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.079454&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;clipPath&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;nota&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;0&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;span&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt; de 10 aciertos&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; nota&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;nota&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aciertos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;random&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        nota.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aciertos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        ponAguja&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(aciertos);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; ponAguja&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;aciertos&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; aguja&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;aguja&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; posicionAguja&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;0 -.28946 .28839 0 -139.16 -20.501&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.089449 -.2753 .27428 .089119 -107.1 -76.177&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.17014 -.23418 .23332 .16951 -59.407 -119.22&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.23418 -.17014 .16951 .23332 -.74583 -145.42&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.2753 -.089449 .089119 .27428 63.14 -152.21&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.28946 0 0 .28839 126 -138.93&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.2753 .089449 -.089119 .27428 181.67 -106.87&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.23418 .17014 -.16951 .23332 224.72 -59.174&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.17014 .23418 -.23332 .16951 250.92 -.51273&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;.089449 .2753 -.27428 .089119 257.71 63.373&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &apos;0 .28946 -.28839 0 244.42 126.23&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            aguja.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;transform&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`matrix(${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posicionAguja&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;aciertos&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;})`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;enlace&quot;&gt;Enlace&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/contador.html&quot;&gt;&lt;button&gt;Ver contador de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ver ejemplo de aplicación práctica. &lt;a href=&quot;https://javguerra.github.io/summer-quiz/&quot;&gt;Summer Quiz&lt;/a&gt; Es necesario terminar una partida para obtener resultados.&lt;/li&gt;
&lt;li&gt;Ver también: &lt;a href=&quot;/blog/grafica-lineas&quot;&gt;Creación de gráfica de lineas dinámica con SVG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ver también: &lt;a href=&quot;/blog/carga-svg&quot;&gt;Cargar SVG dinámicamente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Libro sobre SVG &lt;a href=&quot;https://leanpub.com/scalable/&quot;&gt;SCALABLE&lt;/a&gt; de Jorge Aznar.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/contador.CvHdujvp_ZAoCzg.webp"/><category>código</category><category>css</category><category>html</category><category>javascript</category><category>svg</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Gráfica de lineas dinámica con SVG</title><link>https://javguerra.github.io/blog/grafica-lineas</link><guid isPermaLink="true">https://javguerra.github.io/blog/grafica-lineas</guid><description>Mostrar resultados gráficos con JavaScript</description><pubDate>Sun, 12 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/graficalineas.BU14jhGg_ZfgmGH.webp&quot; alt=&quot;Gráfica de líneas&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#svg&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Como comentaba en el anterior artículo sobre &lt;a href=&quot;/blog/contador-resultados&quot;&gt;la creación de un contador de resultados&lt;/a&gt;, la representación visual ayuda a asumir mejor la información. En este artículo mostraré cómo elaborar una gráfica de líneas dinámica que represente, por ejemplo, las puntuaciones de las últimas cinco jugadas con valores en un rango entre cero y diez.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/graficalineas.html&quot;&gt;&lt;button&gt;Ver gráfica de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;la-gráfica-de-líneas&quot;&gt;La gráfica de líneas&lt;/h2&gt;
&lt;p&gt;Primeramente toca diseñar una gráfica en .SVG que sirva de base para mostrar la línea de resultados que pretendo. Esto lo hago con &lt;a href=&quot;https://inkscape.org/es/&quot;&gt;InkScape&lt;/a&gt;. La gráfica que muestra la imagen es muy sencilla, y de ella destaca la línea roja, que, inicialmente, dibujo en la posición de la línea de puntuación cero. como se puede ver aquí:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/ejercicios-web-javascript/img/graficalineas.svg&quot; alt=&quot;Gráfica de líneas&quot;&gt;&lt;/p&gt;
&lt;p&gt;He rehecho a mano la línea roja para poder acceder a los nodos con más facilidad, empleando el elemento &lt;code&gt;polyline&lt;/code&gt; con los siguientes valores:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;polyline&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;theline&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; points&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;11 73 33.5 73 56 73 78.5 73 101 73&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-mid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-start&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linejoin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En &lt;code&gt;points=&quot;11 73 33.5 73 56 73 78.5 73 101 73&quot;&lt;/code&gt; está toda la magia. Este parámetro contiene los valores de los puntos de la linea creada, diez valores en total que corresponden a la posición &lt;strong&gt;x&lt;/strong&gt; e &lt;strong&gt;y&lt;/strong&gt; de cada punto. Si tengo la ubicación de los puntos de la línea, y un identificador &lt;code&gt;id=&quot;theline&quot;&lt;/code&gt; para poder hacer cambios, ya puedo representar valores en la gráfica dinámicamente.&lt;/p&gt;
&lt;p&gt;Para los círculos en los puntos de conexión de la línea, que son referenciados en marker-end, marker-mid y marker-start, hice los siguientes cambios en el SVG:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;dotLine&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; overflow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;visible&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; orient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;circle&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;scale(.2) translate(-8 -8)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#f0fff0&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;presentación&quot;&gt;Presentación&lt;/h2&gt;
&lt;p&gt;Como hicimos en &lt;a href=&quot;/blog/contador-resultados&quot;&gt;la creación de un contador de resultados&lt;/a&gt;, para poder acceder al identificador dentro del SVG, este debe estar disponible en el DOM, por lo que no sería posible acceder a su &lt;strong&gt;id&lt;/strong&gt; haciendo uso del elemento &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; de HTML.&lt;/p&gt;
&lt;p&gt;El código HTML para insertar «en linea» el SVG sería el siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;contenedor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Gráfica dinámica&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;grafica&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 105.83 79.375&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Gráfica de líneas&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Muestra una gráfica con dos ejes. En el eje horizontal, se muestran las últimas cinco partidas ordenadas de más antigua a más reciente. En el eje vertical, los ciertos de cada uno de los partidos. La línea une las diferentes puntuaciones del gráfico.&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;dotLine&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; overflow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;visible&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; orient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;circle&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;scale(.2) translate(-8 -8)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#f0fff0&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;polyline&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;laLinea&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; points&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;11 73 33.5 73 56 73 78.5 73 101 73&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-mid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-start&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linejoin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;arreglo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para no ocupar espacio de esta entrada, el SVG no se muestra completo. Los puntos suspensivos corresponden a las etiquetas que deberían estar ahi. El SVG como se aprecia, estaría incrustado, y el elemento de la línea bien identificado con &lt;code&gt;id=&quot;laLinea&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En el párrafo &lt;code&gt;&quot;arreglo&quot;&lt;/code&gt; es donde se mostrarán los valores numéricos que se usarán para representar la gráfica.&lt;/p&gt;
&lt;p&gt;Como dijimos en el anterior artículo, la gráfica en SVG ocupa lo suyo. Hay técnicas para &lt;a href=&quot;/blog/carga-svg&quot;&gt;cargar dinámicamente la imagen&lt;/a&gt; sin necesidad de colocar el SVG &lt;em&gt;in-line&lt;/em&gt; desde el principio.&lt;/p&gt;
&lt;p&gt;Deliberadamente he eliminado los atributos &lt;code&gt;width=&quot;400&quot;&lt;/code&gt; y &lt;code&gt;height=&quot;300&quot;&lt;/code&gt; de la etiqueta &lt;code&gt;svg&lt;/code&gt; porque voy a manejar estos valores desde CSS, aunque dejarlas tampoco sería un problema.&lt;/p&gt;
&lt;p&gt;Los estilos CSS para mostrar correctamente estos elementos son los siguientes:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#contenedor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;text-align&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#grafica&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    max-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;400&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;#laLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;animation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: elevador &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@keyframes&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; elevador&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    0%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;73&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;scaleY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    100%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)    &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;scaleY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se ve, he definido también una animación para mostrar el resultado. Al cargar los nuevos valores de la gráfica, los puntos de la línea estarán en la posición del eje de la puntuación cero, (en la posición 73px) con una escala de 0, es decir la línea estará totalmente aplastada. Durante un segundo, irá tomando su forma original ocupando toda la gráfica con las medidas correctas. Esto hace el efecto de que los nodos de la línea se elevan hasta la posición que debe ocupar en la gráfica. Se entiende mejor &lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/graficalineas.html&quot;&gt;viendo el ejemplo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;dinamismo&quot;&gt;Dinamismo&lt;/h2&gt;
&lt;p&gt;Ya disponemos de la gráfica incrustada en el HTML, y en esta parte veremos el motivo de toda esta preparación.&lt;/p&gt;
&lt;p&gt;El siguiente código en JavaScript permite obtener el resultado esperado:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; elLinea&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;laLinea&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; elArreg&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;arreglo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ejesY &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ejesY.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;random&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 11&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)); &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 0-10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elArreg.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `Valores = [${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ejesY&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}]`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fijaLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ejesY);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fijaLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ordenadas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numOrd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(numOrd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numOrd; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ord &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 73&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 7.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    elLinea.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;points&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        `11 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 33.5 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 56 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 78.5 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 101 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Primeramente obtengo los elementos que emplearé en el código &lt;code&gt;elLinea&lt;/code&gt; y &lt;code&gt;elArreg&lt;/code&gt;, y declaro el arreglo &lt;code&gt;ejesY&lt;/code&gt; que contendrá los valores a mostrar. Seguidamente relleno el arreglo con cinco valores al azar en un rango entre 0 y 10. Muestro los valores en la web, llamo a la función &lt;code&gt;fijaLinea(ejesY)&lt;/code&gt; y le paso como parámetro el arreglo. Esta función es la responsable de que la línea tenga la forma deseada.&lt;/p&gt;
&lt;p&gt;En la posición y = 73 está la línea de la puntuación 0. Cada línea de puntuación esta a una distancia de -7.1px. Así: 0 = 73, 1 = 65,9, .. 9 = 9,1, 10 = 2. Con estos datos, la función &lt;code&gt;fijaLinea()&lt;/code&gt; funciona de la siguiente manera: Si el arreglo que le pasamos tiene un número de elementos menor que cinco, rellena a ceros el arreglo. Después toma los últimos cinco elementos del arreglo (pudiera ser que el arreglo recibido tuviese más de cinco elementos).&lt;/p&gt;
&lt;p&gt;A cada elemento del array le aplica el cálculo necesario para convertir la puntuación a la coordenada «&lt;strong&gt;y&lt;/strong&gt;» correspondiente. Con este nuevo arreglo, ya podemos pasar los datos de la línea al SVG con &lt;code&gt;setAttribute&lt;/code&gt;. El valor inicial del atributo &lt;code&gt;points&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;points=&quot;11 73 33.5 73 56 73 78.5 73 101 73&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pasa a ser:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`11 ${ord[0]} 33.5 ${ord[1]} 56 ${ord[2]} 78.5 ${ord[3]} 101 ${ord[4]}`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;siendo los valores del arreglo &lt;code&gt;ord&lt;/code&gt; cada una de las cinco posiciones «&lt;strong&gt;y&lt;/strong&gt;» de los puntos de la polilínea. Esto es todo lo que necesitamos para mostrar los datos.&lt;/p&gt;
&lt;h2 id=&quot;el-código-completo&quot;&gt;El código completo&lt;/h2&gt;
&lt;p&gt;Con cada recarga de la página, la gráfica mostrará valores distintos.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; http-equiv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;X-UA-Compatible&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;IE=edge&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Gráfica de líneas&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #contenedor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;text-align&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;center&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #grafica&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            max-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;400&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;auto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        #laLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;animation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: elevador &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        @keyframes&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; elevador&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            0%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;73&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;px&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;scaleY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            100%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;translateY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)    &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;scaleY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;contenedor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Gráfica dinámica&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;grafica&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 105.83 79.375&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Gráfica de líneas&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Muestra una gráfica con dos ejes. En el eje horizontal, se muestran las últimas cinco partidas ordenadas de más antigua a más reciente. En el eje vertical, los ciertos de cada uno de los partidos. La línea une las diferentes puntuaciones del gráfico.&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;desc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;dotLine&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; overflow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;visible&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; orient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;circle&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;scale(.2) translate(-8 -8)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cx&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#f0fff0&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;marker&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;defs&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;matrix(.99339 0 0 .97827 .43246 .039862)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#ccc&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.26839&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 9.424h-99.395&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 16.73h-99.408&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 24.037h-99.309&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 31.343h-99.438&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 38.649h-99.515&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 45.956h-99.435&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 53.262h-99.416&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 59.999h-99.416&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m105.57 67.305h-99.469&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m10.957 1.98v72.528&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m100.96 1.9385v72.528&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m33.458 1.98v72.528&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m55.959 1.98v72.528&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m78.461 1.98v72.528&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;rect&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;6.2237&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; y&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.1209&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;99.342&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;72.487&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.53688&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;matrix(1.0003 0 0 1.0006 .44383 .038459)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.26458&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;109876543210&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m1.1672 4.0498h-0.44855v-2.9735l-0.89951 0.33038v-0.40514l1.2781-0.4799h0.069935z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.676 2.5522q0 0.78376-0.26768 1.1648-0.26768 0.38103-0.83681 0.38103-0.5619 0-0.83199-0.37138-0.2701-0.37379-0.27974-1.1141v-0.59566q0-0.77411 0.26768-1.1503 0.26768-0.3762 0.83923-0.3762 0.56672 0 0.8344 0.36415 0.26768 0.36174 0.27492 1.119zm-0.44614-0.61013q0-0.56672-0.15916-0.82476-0.15916-0.26045-0.50402-0.26045-0.34244 0-0.49919 0.25804t-0.16158 0.79341v0.71382q0 0.56913 0.16399 0.84164 0.1664 0.2701 0.50161 0.2701 0.33038 0 0.48955-0.25563 0.16158-0.25563 0.16881-0.80546z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.1841 9.5492q-0.13987 0.1664-0.33521 0.26768-0.19293 0.10129-0.42444 0.10129-0.30386 0-0.53054-0.14952-0.22428-0.14952-0.34727-0.41961-0.12299-0.27251-0.12299-0.60048 0-0.35209 0.13264-0.63424 0.13505-0.28215 0.38103-0.43167t0.57395-0.14952q0.5209 0 0.81993 0.39067 0.30145 0.38826 0.30145 1.0611v0.13022q0 1.0249-0.40514 1.4976-0.40514 0.47026-1.2227 0.48231h-0.086816v-0.3762h0.094051q0.55225-0.0096 0.84887-0.28698 0.29662-0.27974 0.32315-0.88263zm-0.6873 0q0.22428 0 0.41238-0.13746 0.19051-0.13746 0.27733-0.34003v-0.17846q0-0.43891-0.19051-0.71382-0.19051-0.27492-0.48231-0.27492-0.29421 0-0.47267 0.22669-0.17846 0.22428-0.17846 0.59325 0 0.35932 0.17122 0.59325 0.17363 0.23151 0.46302 0.23151z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.6037 15.541q0 0.26286-0.13987 0.46784-0.13746 0.20498-0.37379 0.32074 0.27492 0.11817 0.43408 0.34485 0.16158 0.22669 0.16158 0.51366 0 0.45579-0.30868 0.72588-0.30627 0.2701-0.80788 0.2701-0.50643 0-0.8127-0.2701-0.30386-0.27251-0.30386-0.72588 0-0.28456 0.15434-0.51366 0.15675-0.2291 0.43167-0.34727-0.23392-0.11576-0.36897-0.32074t-0.13505-0.46543q0-0.44373 0.28456-0.70418t0.75-0.26045q0.46302 0 0.74759 0.26045 0.28698 0.26045 0.28698 0.70418zm-0.36415 1.6375q0-0.29421-0.1881-0.4799-0.18569-0.18569-0.48714-0.18569t-0.48472 0.18328q-0.18087 0.18328-0.18087 0.48231t0.17604 0.47026q0.17846 0.17122 0.49437 0.17122 0.3135 0 0.49196-0.17122 0.17846-0.17363 0.17846-0.47026zm-0.67042-2.2355q-0.26286 0-0.42685 0.16399-0.16158 0.16158-0.16158 0.44132 0 0.26768 0.15916 0.43408 0.16158 0.16399 0.42926 0.16399t0.42685-0.16399q0.16158-0.1664 0.16158-0.43408t-0.1664-0.43649-0.42202-0.16881z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.7411 21.918-1.4542 3.2604h-0.46784l1.4494-3.1447h-1.9003v-0.36656h2.373z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.2251 28.707v0.37862h-0.081993q-0.5209 0.0096-0.82958 0.30868-0.30868 0.29903-0.35691 0.84164 0.27733-0.31833 0.75723-0.31833 0.4582 0 0.7307 0.32315 0.27492 0.32315 0.27492 0.8344 0 0.5426-0.29662 0.86816-0.29421 0.32556-0.79099 0.32556-0.50402 0-0.81752-0.38585-0.3135-0.38826-0.3135-0.99839v-0.17122q0-0.96945 0.41238-1.4807 0.41479-0.51366 1.2323-0.52572zm-0.58601 1.582q-0.2291 0-0.42202 0.13746-0.19293 0.13746-0.26768 0.34486v0.16399q0 0.43408 0.19534 0.69936 0.19534 0.26527 0.48714 0.26527 0.30145 0 0.47267-0.22186 0.17363-0.22186 0.17363-0.58119 0-0.36174-0.17604-0.5836-0.17363-0.22428-0.46302-0.22428z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m2.6793 37.503 0.17846-1.7508h1.799v0.41238h-1.4204l-0.10611 0.95739q0.25804-0.15193 0.58601-0.15193 0.4799 0 0.76206 0.31833 0.28215 0.31592 0.28215 0.85611 0 0.5426-0.29421 0.85611-0.2918 0.31109-0.81752 0.31109-0.46543 0-0.75964-0.25804t-0.33521-0.71382h0.42202q0.040997 0.30145 0.21463 0.45579 0.17363 0.15193 0.4582 0.15193 0.31109 0 0.48714-0.21222 0.17846-0.21222 0.17846-0.58601 0-0.35209-0.19293-0.56431-0.19051-0.21463-0.50884-0.21463-0.2918 0-0.4582 0.12781l-0.11817 0.09646z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.3577 45.127h0.48714v0.36415h-0.48714v0.81511h-0.44855v-0.81511h-1.5989v-0.26286l1.5723-2.4333h0.47508zm-1.541 0h1.0924v-1.7219l-0.053055 0.09646z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m3.123 51.377h0.33521q0.31592-0.0048 0.49678-0.1664 0.18087-0.16158 0.18087-0.43649 0-0.61736-0.61495-0.61736-0.28939 0-0.46302 0.1664-0.17122 0.16399-0.17122 0.43649h-0.44614q0-0.4172 0.30386-0.69212 0.30627-0.27733 0.77652-0.27733 0.49678 0 0.77894 0.26286 0.28215 0.26286 0.28215 0.7307 0 0.2291-0.14952 0.44373-0.14711 0.21463-0.40273 0.32074 0.28939 0.09164 0.44614 0.30386 0.15916 0.21222 0.15916 0.51849 0 0.47267-0.30868 0.75t-0.80305 0.27733-0.80546-0.26768q-0.30868-0.26768-0.30868-0.70659h0.44855q0 0.27733 0.18087 0.44373t0.48472 0.1664q0.32315 0 0.49437-0.16881t0.17122-0.48472q0-0.30627-0.1881-0.47026t-0.5426-0.16881h-0.33521z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.7749 60.392h-2.3006v-0.32074l1.2154-1.3505q0.2701-0.30627 0.37138-0.49678 0.1037-0.19292 0.1037-0.39791 0-0.27492-0.1664-0.45096t-0.44373-0.17604q-0.3328 0-0.51849 0.19051-0.18328 0.1881-0.18328 0.52572h-0.44614q0-0.48472 0.31109-0.78376 0.3135-0.29903 0.83681-0.29903 0.48955 0 0.77411 0.25804 0.28456 0.25563 0.28456 0.68247 0 0.51849-0.66077 1.2347l-0.94051 1.0201h1.7629z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m3.9405 67.435h-0.44855v-2.9735l-0.89951 0.33038v-0.40514l1.2781-0.4799h0.069935z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m4.676 72.98q0 0.78376-0.26768 1.1648-0.26768 0.38103-0.83681 0.38103-0.5619 0-0.83199-0.37138-0.2701-0.37379-0.27974-1.1141v-0.59566q0-0.77411 0.26768-1.1503 0.26768-0.3762 0.83923-0.3762 0.56672 0 0.8344 0.36415 0.26768 0.36174 0.27492 1.119zm-0.44614-0.61013q0-0.56672-0.15916-0.82476-0.15916-0.26045-0.50402-0.26045-0.34244 0-0.49919 0.25804t-0.16158 0.79341v0.71382q0 0.56913 0.16399 0.84164 0.1664 0.2701 0.50161 0.2701 0.33038 0 0.48955-0.25563 0.16158-0.25563 0.16881-0.80546z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(-.061333 -.081667)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.26458&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(.46707)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m11.524 79.312h-0.44855v-2.9735l-0.89952 0.33038v-0.40514l1.2781-0.4799h0.06993z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(.33346)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;3&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m55.289 77.34h0.33521q0.31592-0.0048 0.49678-0.1664 0.18087-0.16158 0.18087-0.43649 0-0.61736-0.61495-0.61736-0.28939 0-0.46302 0.1664-0.17122 0.16399-0.17122 0.43649h-0.44614q0-0.4172 0.30386-0.69212 0.30627-0.27733 0.77652-0.27733 0.49678 0 0.77894 0.26286t0.28215 0.7307q0 0.2291-0.14952 0.44373-0.1471 0.21463-0.40273 0.32074 0.28939 0.09164 0.44614 0.30386 0.15916 0.21222 0.15916 0.51849 0 0.47267-0.30868 0.75t-0.80305 0.27733-0.80546-0.26768q-0.30868-0.26768-0.30868-0.70659h0.44855q0 0.27733 0.18087 0.44373t0.48472 0.1664q0.32315 0 0.49437-0.16881t0.17122-0.48472q0-0.30627-0.1881-0.47026t-0.5426-0.16881h-0.33521z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(.49737)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m34.356 79.312h-2.3006v-0.32074l1.2154-1.3505q0.2701-0.30627 0.37138-0.49678 0.1037-0.19293 0.1037-0.39791 0-0.27492-0.1664-0.45096t-0.44373-0.17604q-0.3328 0-0.51849 0.19051-0.18328 0.1881-0.18328 0.52572h-0.44614q0-0.48472 0.31109-0.78376 0.3135-0.29904 0.83681-0.29904 0.48955 0 0.77411 0.25804 0.28456 0.25563 0.28456 0.68247 0 0.51849-0.66077 1.2347l-0.94051 1.0201h1.7629z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(-.47277)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;5&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m100.22 77.552 0.17846-1.7508h1.799v0.41238h-1.4204l-0.10611 0.95739q0.25804-0.15193 0.58602-0.15193 0.4799 0 0.76205 0.31833 0.28215 0.31592 0.28215 0.85611 0 0.5426-0.29421 0.85611-0.2918 0.31109-0.81752 0.31109-0.46543 0-0.75964-0.25804t-0.33521-0.71382h0.42202q0.041 0.30145 0.21463 0.45579 0.17364 0.15193 0.4582 0.15193 0.31109 0 0.48714-0.21222 0.17845-0.21222 0.17845-0.58601 0-0.35209-0.19292-0.56431-0.19052-0.21463-0.50884-0.21463-0.2918 0-0.4582 0.12781l-0.11817 0.09646z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; transform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;translate(-.13501)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; aria-label&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;4&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;m79.29 78.133h0.48714v0.36415h-0.48714v0.81511h-0.44855v-0.81511h-1.5989v-0.26286l1.5723-2.4333h0.47508zm-1.541 0h1.0924v-1.7219l-0.05305 0.09646z&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#3cb371&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;polyline&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;laLinea&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; points&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;11 73 33.5 73 56 73 78.5 73 101 73&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-mid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; marker-start&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;url(#dotLine)&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#d8232a&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linejoin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;arreglo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; elLinea&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;laLinea&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; elArreg&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;arreglo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ejesY &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            ejesY.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;floor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(Math.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;random&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 11&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)); &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 0-10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        elArreg.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `Valores = [${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ejesY&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}]`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        fijaLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(ejesY);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fijaLinea&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;ordenadas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; []) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numOrd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(numOrd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numOrd; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ord &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ordenadas.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 73&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 7.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            elLinea.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;points&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                `11 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 33.5 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 56 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 78.5 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} 101 ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ord&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con estas indicaciones, hacer tu propia gráfica de líneas no debería ser excesivamente complicado.&lt;/p&gt;
&lt;p&gt;Para conocer más sobre SVG y cómo editarlo, te recomiendo el libro &lt;a href=&quot;https://leanpub.com/scalable/&quot;&gt;SCALABLE&lt;/a&gt; de Jorge Aznar.&lt;/p&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/graficalineas.html&quot;&gt;&lt;button&gt;Ver gráfica de ejemplo&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ver ejemplo de aplicación práctica. &lt;a href=&quot;https://javguerra.github.io/summer-quiz/&quot;&gt;Summer Quiz&lt;/a&gt; (Es necesario terminar una partida para obtener resultados.)&lt;/li&gt;
&lt;li&gt;Ver también: &lt;a href=&quot;/blog/contador-resultados&quot;&gt;Creación de un contador de resultados&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ver también: &lt;a href=&quot;/blog/carga-svg&quot;&gt;Cargar SVG dinámicamente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Libro sobre SVG &lt;a href=&quot;https://leanpub.com/scalable/&quot;&gt;SCALABLE&lt;/a&gt; de Jorge Aznar.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/graficalineas.BU14jhGg_ZfgmGH.webp"/><category>código</category><category>css</category><category>html</category><category>javascript</category><category>svg</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Cargar SVG dinámicamente</title><link>https://javguerra.github.io/blog/carga-svg</link><guid isPermaLink="true">https://javguerra.github.io/blog/carga-svg</guid><description>Y una función genérica para hacer llamadas con &apos;fetch&apos;</description><pubDate>Tue, 14 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/svg-logo.JHhXWkN6_ZmLAYo.webp&quot; alt=&quot;SVG&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#svg&lt;/em&gt;, &lt;em&gt;#usabilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Esta entrada en el blog complementa el contenido de los artículos &lt;a href=&quot;/blog/contador-resultados&quot;&gt;Creación de un contador de resultados&lt;/a&gt; y &lt;a href=&quot;/blog/grafica-lineas&quot;&gt;Gráfica de lineas dinámica con SVG&lt;/a&gt;, pero puede leerse con independencia de ellos. Veremos cómo cargar un SVG (o cualquier otra cosa que nos propongamos) en el DOM una vez renderizada la página en el navegador apoyándonos en la instrucción &lt;code&gt;fetch()&lt;/code&gt;. Se asume que el lector conoce el uso de esta instrucción.&lt;/p&gt;
&lt;p&gt;La idea la tomé de este repositorio: &lt;a href=&quot;https://github.com/ojgarciab/335841-stackoverflow-es&quot;&gt;Reproducción de acceso a SVG externo con CSS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Como sabemos, podemos cargar imágenes, y también SVG en nuestra página con la etiqueta &lt;code&gt;img&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;img&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;imagen.svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; alt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Imagen de ejemplo en formato SVG&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pero esto presenta un inconveniente. Desde el DOM, con JavaScript, no podemos acceder a las etiquetas del fichero SVG, y esto es fundamental para poder aplicar cambios dinámicos a la imagen.&lt;/p&gt;
&lt;p&gt;La alternativa es poner el SVG en línea dentro del HTML, de una forma parecida a:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;imagen&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; version&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1.1&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En los puntos suspensivos estaría el cuerpo del SVG. Pero esto presentaría otro problema, y es que aumenta el tamaño del HTML de manera considerable, y lo hace menos legible.&lt;/p&gt;
&lt;p&gt;La propuesta de esta entrada es la de hacer la carga del SVG dinámicamente, una vez se ha cargado la página, empleando &lt;code&gt;fetch()&lt;/code&gt; para «traer» la imagen desde el servidor e insertarla en el DOM directamente tomando como referencia un elemento padre del HTML:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;imagen&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Veamos cómo de sencillo es esto.&lt;/p&gt;
&lt;h2 id=&quot;el-código&quot;&gt;El código&lt;/h2&gt;
&lt;p&gt;EL HTML de nuestra página sería pues muy simple:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Ejemplo SVG&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; defer&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;funciones.js&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;imagen&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Toda la magia se llevaría a cabo en la siguientes funciones para hacer posible la carga dinámica de la imagen:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. function &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;02&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;03&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. function &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fetchAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url, callback, tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;json&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;04&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// setSpin(true);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;05&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.     &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fetch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;06&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.         .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;respuesta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;07&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.             &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;respuesta.ok) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(respuesta.statusText);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;08.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;             return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;json&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;09.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;         })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;         .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;datos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(datos))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;         .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12.&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;         // .finally(setSpin(false));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;14.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; urlImagen &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cargaImagen&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xml&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#imagen&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xml;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;17.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetchAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(urlImagen, cargaImagen, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: La línea &lt;strong&gt;4&lt;/strong&gt; y la línea &lt;strong&gt;12&lt;/strong&gt; llaman a la función &lt;code&gt;setSpin()&lt;/code&gt; que describí en la entrada &lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;, y podemos prescindir de ellas sin problema si no vamos a usarlas.&lt;/p&gt;
&lt;p&gt;Veamos que hace esto. En la línea 1 tenemos una función cuya utilidad es la de acortar la llamada a &lt;code&gt;querySelector()&lt;/code&gt;. Más allá de la estética, simplifica la escritura de código. La usaré en la línea 16.&lt;/p&gt;
&lt;p&gt;La función &lt;code&gt;fetchAPI()&lt;/code&gt; contiene la estructura genérica de una consulta &lt;code&gt;fetch()&lt;/code&gt;, y la usaré en la línea 17, tras haber definido la dirección donde está ubicado el SVG en la línea 15 &lt;code&gt;urlImagen&lt;/code&gt;, y la función que se ocupará de poner la imagen en el DOM de la línea 16 &lt;code&gt;cargaImagen&lt;/code&gt;. Básicamente, la llamada:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fetchAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(urlImagen, cargaImagen, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;texto&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;lo que hace es pasar a &lt;code&gt;fetch()&lt;/code&gt; la dirección de la imagen SVG y mediante la función &lt;em&gt;callback&lt;/em&gt; &lt;code&gt;cargaImagen()&lt;/code&gt;, que es una función flecha asignada a una variable, una vez fetch obtenga la imagen, ponerla dentro del contenedor &lt;code&gt;div&lt;/code&gt; que describimos en el HTML. El parámetro &lt;code&gt;&apos;texto&apos;&lt;/code&gt; sirve para indicar que lo que vamos a cargar debe ser leído como texto, y no como un json. Realmente podríamos poner cualquier cosa aquí: ‘text’, ‘false’… lo que se nos ocurriese,  ya que la función fechAPI consulta si lo que estamos indicando que debe devolver es &lt;strong&gt;‘json’&lt;/strong&gt; en la línea 8:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;json&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;y cualquier otra opción será entendida como que debe devolver la dos datos de tipo &lt;code&gt;text()&lt;/code&gt; en vez de &lt;code&gt;json()&lt;/code&gt;, que es el formato que requiere el contenido &lt;code&gt;xml&lt;/code&gt; que describe el SVG que estamos cargando. por defecto, esta función devolverá un json si no indicamos este parámetro en la llamada.&lt;/p&gt;
&lt;p&gt;En la línea 13 comprobamos que la petición &lt;code&gt;fetch(url)&lt;/code&gt; no ha devuelto ningún error. &lt;code&gt;fetch()&lt;/code&gt; no realiza esta comprobación por nosotros, y si se obtiene respuesta del servidor, así sea un error, entenderá que la petición se ha llevado a cabo, y devolverá la respuesta obtenida. Con esta línea nos aseguramos de que todo ha ido bien, si no es así, lanzo un error que será capturado en la línea 17 y mostrado por consola, parando la ejecución de la función.&lt;/p&gt;
&lt;p&gt;Una vez devueltos los datos desde la línea 8, es en la línea 10 donde se procesa la función &lt;em&gt;callback&lt;/em&gt;_ &lt;code&gt;cargaImagen&lt;/code&gt; que paso como parámetro:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;xml&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#imagen&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xml;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función flecha toma los datos &lt;code&gt;xml&lt;/code&gt; recibidos de &lt;code&gt;fetch()&lt;/code&gt;, que deben estar en formato &lt;code&gt;.text()&lt;/code&gt; y los inserta en el div que identificamos con el &lt;code&gt;id=&quot;imagen&quot;&lt;/code&gt; usando &lt;code&gt;.innerHTML&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Desde ese momento ya disponemos de acceso completo al .SVG mediante el DOM.&lt;/p&gt;
&lt;h2 id=&quot;código-completo&quot;&gt;Código completo&lt;/h2&gt;
&lt;p&gt;Puedes copiar y pegar este código para hacer pruebas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Ejemplo SVG&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;imagen&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el) }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetchAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;tipo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;json&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            // setSpin(true);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            fetch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;respuesta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;respuesta.ok) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(respuesta.statusText);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;json&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; respuesta.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;datos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(datos))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;                // .finally(setSpin(false));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; urlImagen &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        let&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; cargaImagen&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; xml&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#imagen&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xml;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        fetchAPI&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(urlImagen, cargaImagen, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;text&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ver ejemplo de aplicación práctica. &lt;a href=&quot;https://javguerra.github.io/summer-quiz/&quot;&gt;Summer Quiz&lt;/a&gt;. El SVG inicial de la gráfica y el SVG final de resultados se cargan mediante este método. Es necesario terminar una partida para obtener resultados que se muestren en la gráfica.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/contador-resultados&quot;&gt;Creación de un contador de resultados&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/grafica-lineas&quot;&gt;Gráfica de lineas dinámica con SVG&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Libro sobre SVG &lt;a href=&quot;https://leanpub.com/scalable/&quot;&gt;SCALABLE&lt;/a&gt; de Jorge Aznar.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ojgarciab/335841-stackoverflow-es&quot;&gt;Reproducción de acceso a SVG externo con CSS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg&quot;&gt;Imagen SVG de prueba en Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/svg-logo.JHhXWkN6_ZmLAYo.webp"/><category>código</category><category>css</category><category>html</category><category>javascript</category><category>svg</category><category>usabilidad</category><author>JavGuerra</author></item><item><title>Mosaico JS</title><link>https://javguerra.github.io/blog/mosaico-js</link><guid isPermaLink="true">https://javguerra.github.io/blog/mosaico-js</guid><description>Juego de colorear pixel art</description><pubDate>Mon, 27 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/mosaico.BiJ60OK-_Zo8LIn.webp&quot; alt=&quot;Mosaico JS&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#dom&lt;/em&gt;, &lt;em&gt;#juego&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Ejercicio que combina lógica de programación en JavaScript, y el uso de eventos asociados a los elementos del DOM que consiste en elegir un pincel y pintar las celdas de una tabla para construir un mosaico de colores.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/MosaicoJS/&quot;&gt;&lt;button&gt;Probar el juego&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;el-juego&quot;&gt;El juego&lt;/h1&gt;
&lt;p&gt;La página muestra ocho botones redondos de otros tantos colores de una gama que va de los colores oscuros, empezando por el negro, a los colores claros, terminando con el blanco. Al hacer clic en cada botón elegimos el color deseado.&lt;/p&gt;
&lt;p&gt;Debajo de estos botones está la tabla de 16x16 celdas sobre las que vamos a pintar con el color seleccionado. Al hacer clic sobre una celda, esta cambia su color de fondo al nuevo color. Podemos componer dibujos con esta técnica como el que se ve en la imagen.&lt;/p&gt;
&lt;p&gt;Para borrar emplearemos el color blanco, ya que este es el color por defecto de cada celda de la tabla, o bien podemos corregir errores pintando con otro color distinto.&lt;/p&gt;
&lt;p&gt;Para borrar todo el dibujo deberemos recargar la página. Dada la simplicidad del ejemplo, no se han implementado opciones para guardar y cargar los mosaicos creados.&lt;/p&gt;
&lt;h1 id=&quot;lo-básico-el-html&quot;&gt;Lo básico, el HTML&lt;/h1&gt;
&lt;p&gt;El código html es una fuente de información para la aplicación que voy a desarrollar.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;img&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;logo&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;assets/img/mosaico.png&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; alt&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;logo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /&amp;gt;Mosaico&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;¡Elije un color y haz clic en el mosaico para pintar!&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;nav&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnNegro&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;negro&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnAzul&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;azul&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnRojo&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;rojo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnMagen&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;magen&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnVerde&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;verde&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnCian&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cian&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnAmari&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;amari&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;btnBlanc&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;blanc&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;nav&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dentro de &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; indico el identificador &lt;code&gt;id&lt;/code&gt; y la clase &lt;code&gt;class&lt;/code&gt; que definirá el color de cada botón &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;. Esta clase me va a servir para simplificar la codificación del juego, ya que, como veremos más adelante, voy a aprovechar esta información para seleccionar el color del pincel con el que pintaremos, es decir, cuando hagamos clic en cada uno de los botones, dispararemos un evento que me permitirá ejecutar una función que leerá la clase asociada a este. Como la clase indica el color del botón, podemos usarla para saber qué color hemos elegido. Al pulsar el botón rojo estaremos obteniendo la clase &lt;code&gt;.rojo&lt;/code&gt; que luego podemos aplicar en las celdas del mosaico.&lt;/p&gt;
&lt;p&gt;Por supuesto, en el CSS cada clase definirá el color, por ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.rojo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  background-color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;#f00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sencillo, ¿verdad? Veamos cómo funciona.&lt;/p&gt;
&lt;h1 id=&quot;el-programa-en-js&quot;&gt;El programa en JS&lt;/h1&gt;
&lt;p&gt;Básicamente el programa hará lo siguiente:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Asociará un evento que llama a la función &lt;code&gt;color()&lt;/code&gt; en cada uno de los ocho botones para poder elegir el color con el que pintar.&lt;/li&gt;
&lt;li&gt;Dibujará una tabla con las dimensiones deseadas (inicialmente 16x16, pero se puede cambiar), y a cada celda de la tabla le asociará un evento que llama a la función &lt;code&gt;pinta()&lt;/code&gt; cuya tarea es cambiar el color de la celda sobre la que se ha echo clic.&lt;/li&gt;
&lt;li&gt;Inicializará las dos variables que usaremos en el juego.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Esto último paso es simple:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; btnSel &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnNegro&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pincel &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; btnSel.className;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Estas variables servirán para:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align: left&quot;&gt;Variable&lt;/th&gt;
&lt;th style=&quot;text-align: left&quot;&gt;Uso&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;btnSel&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;Contendrá la referencia al botón que hemos seleccionado. Esto nos permitirá mostrar el botón como seleccionado y desmarcar el botón cuando cambiemos nuestra selección por otro botón seleccionado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;pincel&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;Contendrá la clase relativa al color seleccionado que hemos obtenido al hacer clic en alguno de los botones de la barra de navegación.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;asociando-el-evento-de-la-función-color&quot;&gt;Asociando el evento de la función color&lt;/h2&gt;
&lt;p&gt;Para que los ocho botones de colores funcionen, debo asociarles un evento de tal forma que, al hacer clic en ellos, realicen su función, nunca mejor dicho:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnNegro&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnAzul&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnRojo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnMagen&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnVerde&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnCian&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnAmari&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#btnBlanc&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;el()&lt;/code&gt; es una forma de abreviar:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el); }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, lo que hace la función &lt;code&gt;el()&lt;/code&gt;  es devolver un elemento de nuestro HTML tomando como referencia su selector, usando para ello la función &lt;code&gt;querySelector()&lt;/code&gt;;&lt;/p&gt;
&lt;p&gt;Como ya tenemos el elemento HTML que corresponde a cada botón, podemos asignarle un escuchador de evento con &lt;code&gt;.onclick&lt;/code&gt; que llame a la función &lt;code&gt;color()&lt;/code&gt; al hacer click en ese botón.&lt;/p&gt;
&lt;p&gt;¿Y qué hace la función &lt;code&gt;color()&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; color&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnSel.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;seleccion&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnSel &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pincel &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.className;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    btnSel.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;seleccion&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Primeramente elimina la clase &lt;code&gt;.seleccion&lt;/code&gt; que es la encargada de dar el efecto hundido del botón seleccionado (&lt;code&gt;btnSel&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Seguidamente obtiene la referencia del botón que acabamos de seleccionar haciendo uso de &lt;code&gt;this&lt;/code&gt;. Aquí &lt;code&gt;this&lt;/code&gt; hace referencia al objeto que llama a la función, es decir, al botón que lanzó el evento. Ahora ya sabemos cual es el botón sobre el que hemos hecho clic.&lt;/p&gt;
&lt;p&gt;Para obtener el color del &lt;code&gt;pincel&lt;/code&gt; con el que vamos a pintar, leo la clase asociada al botón con &lt;code&gt;.className&lt;/code&gt;. Esta clase, como vimos cuando creamos el HTML, es la encargada de definir el color de fondo del botón, y es la que usaremos para pintar las celdas a partir de ahora cuando llamemos a la función &lt;code&gt;pinta()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para indicar visualmente al usuario el color que ha seleccionado, ponemos la clase &lt;code&gt;.seleccion&lt;/code&gt; en el nuevo botón.&lt;/p&gt;
&lt;p&gt;En resumen, como sabemos cual fue el botón que seleccionamos anteriormente, quitamos la clase que indica visualmente que el botón está seleccionado, porque ya ha dejado de estarlo, asociamos a la variable &lt;code&gt;btnSel&lt;/code&gt; el nuevo botón, y a la variable &lt;code&gt;pincel&lt;/code&gt; la clase asociada al botón que indica su color, y finalmente ponemos la marca de selección en el nuevo botón seleccionado.&lt;/p&gt;
&lt;h2 id=&quot;dibujando-la-tabla-con-las-celdas-sobre-las-que-pintaremos&quot;&gt;Dibujando la tabla con las celdas sobre las que pintaremos&lt;/h2&gt;
&lt;p&gt;Creo la tabla y la conecto al DOM mediante:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;main&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;creaTabla&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(numCols, numFils) );&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;creaTabla()&lt;/code&gt; recibe dos parámetros que indican su altura y anchura en celdas. Si lo deseamos, podemos cambiar el valor de estas variables para hacer que el mosaico tenga otras dimensiones cambiando los valores en:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; numCols&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; numFils&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función &lt;code&gt;creaTabla()&lt;/code&gt; no destaca especialmente si no es por dos cosas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaTabla&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;numCols&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;numFils&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; table, tbody, tr, td;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    tbody &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tbody&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numFils; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numCols; i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            td &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            td.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;blanc&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            td.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pinta; &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ¡Magia!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            tr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(td);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tbody.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;table&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tbody);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; table;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hago uso de la función &lt;code&gt;.creaEl()&lt;/code&gt; para acortar la instrucción encargada de la creación de elementos del DOM:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el); }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cada vez que creo un &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; (celda) le asigno un evento que llama a la función &lt;code&gt;pinta()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    td &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; creaEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    td.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;blanc&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    td.onclick &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pinta; &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ¡Magia!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Estas tres líneas dentro del bucle anidado crean las celdas de cada fila, les asignan la clase &lt;code&gt;.blanc&lt;/code&gt; que pone el fondo de las celdas de color blanco por defecto, y luego asocia la función &lt;code&gt;pinta()&lt;/code&gt; al evento &lt;code&gt;.onclick&lt;/code&gt; de cada celda de forma que al hacer click en ella su fondo se pintará del color que indique &lt;code&gt;pincel&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; pinta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.className &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pincel; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;De nuevo aquí &lt;code&gt;this&lt;/code&gt; es fundamental para poder trabajar con la celda seleccionada, que es la que lanzó el evento. Al hacer clic en la celda, cambiamos de color esa misma celda. Así de simple.&lt;/p&gt;
&lt;h1 id=&quot;en-resumen&quot;&gt;En resumen&lt;/h1&gt;
&lt;p&gt;Esto sería todo. Resumiendo la operativa de la aplicación, partiendo de un HTML con las clases que indican el color de cada uno de los botones del juego que sirven para seleccionar el color, asocio un evento a cada botón para saber el color del pincel con el que vamos a pintar las celdas. Inicialmente, el color seleccionado es el negro, y el botón seleccionado es el que corresponde a ese color.&lt;/p&gt;
&lt;p&gt;Al hacer clic en cada celda, hacemos que el fondo de esta cambie al color seleccionado.&lt;/p&gt;
&lt;p&gt;Puedes jugar al juego y ver el código completo en el repositorio haciendo clic en los siguientes enlaces.&lt;/p&gt;
&lt;p&gt;¿Te animas a hacer tus propios dibujos pixel art?&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/MosaicoJS/&quot;&gt;&lt;button&gt;Probar el juego&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Repositorio &lt;a href=&quot;https://github.com/JavGuerra/MosaicoJS&quot;&gt;JavGuerra/MosaicoJS &lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/mosaico.BiJ60OK-_Zo8LIn.webp"/><category>web</category><category>código</category><category>css</category><category>html</category><category>javascript</category><category>dom</category><category>juego</category><author>JavGuerra</author></item><item><title>Filtrado múltiple</title><link>https://javguerra.github.io/blog/filtrado-multiple</link><guid isPermaLink="true">https://javguerra.github.io/blog/filtrado-multiple</guid><description>Como simplificar la búsqueda de información</description><pubDate>Fri, 15 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/filtrado.0LXC88F8_lExjy.webp&quot; alt=&quot;Filtrado&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#express&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;En programación es habitual trabajar con datos de entrada. Un caso común son los campos (obligatorios o no) que recibimos de un formulario para realizar búsquedas en una base de datos y devolver datos al usuario, o para dar de alta nueva información… pero estos datos de entrada, según las circunstancias, pueden variar. Para un mismo formulario, podemos recibir uno o varios campos, lo que complica la forma en que hacemos las búsquedas de información. En esta entrada veremos como simplificar el filtrado para hacer consultas a los datos.&lt;/p&gt;
&lt;h1 id=&quot;supuesto-práctico&quot;&gt;Supuesto práctico&lt;/h1&gt;
&lt;p&gt;Tenemos una lista de &lt;strong&gt;productos&lt;/strong&gt; almacenados en un arreglo o lista de objetos. Cada objeto tiene las propiedades &lt;strong&gt;nombre&lt;/strong&gt;, &lt;strong&gt;tipo&lt;/strong&gt; y &lt;strong&gt;precio&lt;/strong&gt;, y deseamos hacer búsquedas sobre esta lista, devolviendo los objetos que cumplan con los datos recibidos desde un formulario. Los datos recibidos pueden ser todos ellos, es decir, valores para cada una de las tres propiedades, o sólo el dato de búsqueda de uno de ellos o dos de ellos (faltando un dato en este último caso). Veamos primeramente la estructura de datos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; productos &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;nombre&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;LAVADORA SECAMAS&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;tipo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;hogar&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;precio&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;700&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;nombre&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;TELEVISOR TV&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;tipo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;video&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;precio&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;nombre&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ARMARIO RIO&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;tipo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;hogar&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;precio&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;300&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Una búsqueda &lt;code&gt;nombre: &apos;LAVADORA&apos;&lt;/code&gt; me devolvería el primer objeto. Si busco por &lt;code&gt;tipo: &apos;hogar&apos;&lt;/code&gt; me devolverá el primer y el tercer objeto… Y si busco por &lt;code&gt;tipo: &apos;video&apos; y precio: menor que 1500&lt;/code&gt; me devolverá el segundo objeto.&lt;/p&gt;
&lt;h2 id=&quot;comunmente&quot;&gt;Comunmente…&lt;/h2&gt;
&lt;p&gt;Para hacer una búsqueda sobre esta lista, tendría que comprobar si he recibido un valor para cada uno de las propiedades de los objetos de la lista, y si es así, realizar el filtrado por el primer valor para obtener el primer resultado, pasar al siguiente valor si lo hubiese, para obtener el siguiente resultado filtrado, y así con tantos valores como haya recibido del formulario. El código sería algo como esto:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resultados &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; productos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre) resultados &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resultados.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.nombre.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (tipo)   resultados &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resultados.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.tipo.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tipo));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (precio) resultados &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resultados.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    resultados &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(resultados);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este encadenado de filtrados me obliga a realizar tres filtrados e ir guardando el resultado para el siguiente filtro, si la entrada de formulario, por tanto la variable que guarda su valor, existe.&lt;/p&gt;
&lt;p&gt;Como se aprecia en el código, primeramente copio el contenido de &lt;code&gt;productos&lt;/code&gt; a &lt;code&gt;resultados&lt;/code&gt;, para ir filtrando el resultado. Esto lo hago porque no sé qué valores recibiré, por lo tanto no sabré donde empezará &lt;code&gt;productos.filter&lt;/code&gt;, si en el primer, segundo o tercer &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Seguidamente compruebo si tengo valores en las variables &lt;code&gt;nombre&lt;/code&gt;, &lt;code&gt;tipo&lt;/code&gt; y &lt;code&gt;precio&lt;/code&gt;. Si alguna de ellas existe, realizo el filtrado sobre los datos, sino, devuelvo un arreglo o lista vacía. Así pues, si existe nombre, filtro por nombre, si existe tipo, filtro por tipo y si existe precio filtro por precio, consecutivamente.&lt;/p&gt;
&lt;h2 id=&quot;otra-manera-de-hacerlo&quot;&gt;Otra manera de hacerlo&lt;/h2&gt;
&lt;p&gt;Es posible hacer un sólo filtrado que incluya las tres condiciones. Para ello usaré el operador condicional ternario (&lt;code&gt;?&lt;/code&gt;):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; resultados&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; productos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.nombre.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    (tipo   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.tipo.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tipo) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    (precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La lista &lt;code&gt;resultados&lt;/code&gt; tendrá el valor del filtro o una lista vacía según reciba o no reciba alguno de los valores para filtrar.&lt;/p&gt;
&lt;p&gt;Dentro de &lt;code&gt;filter&lt;/code&gt; incluimos ahora los tres criterios de filtrado de una vez, pero igualmente debemos comprobar si cada uno de las variables que recibimos tiene o no valores para filtrar, es decir, si el dato de entrada existe.&lt;/p&gt;
&lt;p&gt;Si una variable tiene valor, osea, si hemos recibido sus datos del formulario, entonces se incluirá la condición de filtrado, sino se incluirá un &lt;code&gt;true&lt;/code&gt;. Nos fijamos en una de las líneas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.nombre.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si la variable &lt;code&gt;nombre&lt;/code&gt; tiene datos, entonces se incluirá la comprobación &lt;code&gt;producto.nombre.includes(nombre)&lt;/code&gt; en el filtrado, de otra forma se incluirá un &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Como estamos filtrando por un total de hasta tres condiciones que tienen que ser verdaderas (&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;), si alguna de ellas no se cumple, el &lt;code&gt;filter&lt;/code&gt; pasará al siguiente elemento de la lista, y no devolverá este elemento.&lt;/p&gt;
&lt;p&gt;Imaginemos que sólo hemos recibido el &lt;code&gt;nombre&lt;/code&gt; del producto. ¿Qué pasa con las otras dos condiciones derivadas de &lt;code&gt;tipo&lt;/code&gt; y &lt;code&gt;precio&lt;/code&gt;?. Devolverán &lt;code&gt;true&lt;/code&gt;, condicionando la respuesta de filtrado a lo que devuelva la condición de &lt;code&gt;nombre&lt;/code&gt;. Por ello los &lt;code&gt;true&lt;/code&gt; que no sean resultado de la condición de una o varias de las variables no tendrán ninguna influencia en el valor de la comprobación.&lt;/p&gt;
&lt;p&gt;Si tenemos dos variables, la tercera será &lt;code&gt;true&lt;/code&gt;, y la condición de filtrado funcionará sólo si las dos condiciones con valores de entrada son &lt;code&gt;true&lt;/code&gt; si han pasado la comprobación asociada a esa variable.&lt;/p&gt;
&lt;h1 id=&quot;otra-manera-más&quot;&gt;Otra manera más&lt;/h1&gt;
&lt;p&gt;En programación no hay un único camino para hacer las cosas. Tras la lectura de esta entrada, &lt;strong&gt;Marcos&lt;/strong&gt;, de un foro de Discord, me propuso una alternativa aún más simple. Vamos a ver cómo funciona:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; resultados&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; productos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.nombre.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tipo   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.tipo.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tipo)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La lógica de fondo no deja de ser la misma, se basa en un booleano que nos dice si se va a tener en cuenta la condición o se va a incluir un &lt;code&gt;true&lt;/code&gt;, pero esta refinada forma de hacerlo consiste en «jugar» con el valor inverso del contenido de una variable, de tal forma que si la variable existe, su valor será &lt;code&gt;false&lt;/code&gt; (Ej. &lt;code&gt;!nombre&lt;/code&gt;) debiendo aplicar entonces la condición de filtrado (&lt;code&gt;||&lt;/code&gt;), y si no existe, el valor de la variable será &lt;code&gt;true&lt;/code&gt;. Elegante.&lt;/p&gt;
&lt;h1 id=&quot;un-poco-más-allá&quot;&gt;Un poco más allá&lt;/h1&gt;
&lt;p&gt;La siguiente es una función basada en la codificación anterior y devuelve un objeto que incluye un código de respuesta y el listado de objetos resultante.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; respuesta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;nombre&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;tipo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;precio&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; undefined&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; resultados&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; productos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;producto&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.nombre.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tipo   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.tipo.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tipo)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; producto.precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (resultados.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { codigo, resultados };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La variable &lt;code&gt;codigo&lt;/code&gt; va a contener tres posibles valores:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align: center&quot;&gt;Valor&lt;/th&gt;
&lt;th style=&quot;text-align: left&quot;&gt;Significado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;Datos encontrados.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;No se han encontrado datos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;No se han recibido datos de entrada.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;De tal forma que en:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tipo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precio) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;se determina si se ha recibido alguna de las variables, asignándole el código correspondiente, y en la línea:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) codigo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (resultados.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;se determina si se ha obtenido algún resultado tras la búsqueda, si el código era 0, es decir, si había datos de entrada.&lt;/p&gt;
&lt;p&gt;por último en la línea:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { codigo, resultados };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Devolvemos el objeto con la información de lo sucedido y el resultado de la búsqueda.&lt;/p&gt;
&lt;p&gt;La línea anterior es equivalente a:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { codigo: codigo, resultados: resultados };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función puede ser útil para, por ejemplo, trabajar con rutas en Node.js/express:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;router.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;nombre&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;tipo&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;precio&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; req.query;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;respuesta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(nombre, tipo, precio) );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/filtrado.0LXC88F8_lExjy.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>express</category><author>JavGuerra</author></item><item><title>Conexión persistente a MongoDB en Node.js</title><link>https://javguerra.github.io/blog/mongodb-connect</link><guid isPermaLink="true">https://javguerra.github.io/blog/mongodb-connect</guid><description>Abrir una única conexión a la base de datos a través de los distintos módulos de la aplicación</description><pubDate>Sun, 24 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/mongodb.B38n9K_s_1aeGYn.webp&quot; alt=&quot;MongoDB&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#express&lt;/em&gt;, &lt;em&gt;#mongodb&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Esta semana tocó aprender sobre &lt;strong&gt;MongoDB&lt;/strong&gt;. Una de las cuestiones que me llamaron la atención en los ejercicios que realizamos era la necesidad de abrir y cerrar la conexión a la Base de Datos (en adelante «BBDD») en cada consulta, algo que supone una sobrecarga importante para el servidor, así que me puse a investigar la manera de hacer que la conexión a la BBDD permaneciese abierta y dando servicio a través de los distintos módulos de la aplicación. Esto es lo que descubrí, con ayuda de la comunidad.&lt;/p&gt;
&lt;h2 id=&quot;cambiando-el-chip&quot;&gt;Cambiando el chip&lt;/h2&gt;
&lt;p&gt;Pasar de manejar datos embebidos en módulos como en el caso de la publicación sobre &lt;a href=&quot;/blog/filtrado-multiple&quot;&gt;filtrado múltiple&lt;/a&gt; a consultar una base de datos como &lt;strong&gt;MongoDB&lt;/strong&gt; presenta retos importantes. el principal es que debo establecer la conexión al servicio y esperar una respuesta. Una consulta típica a MongoDB tendría esta forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; mongoClient&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mongodb&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).MongoClient;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}:${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PORT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; collection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;products&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;database&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; database.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(db_name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    db.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;collection&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        database.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En la primera línea, en función de si la aplicación está funcionando en local, en modo desarrollo, o bien en producción en el servidor, cargo o no el módulo &lt;code&gt;dotenv&lt;/code&gt; que me permite tener las variables globales que luego usaré en url y db_name por ejemplo definidas en un fichero &lt;code&gt;.env&lt;/code&gt;. Puedes ampliar conocimientos sobre este asunto en &lt;a href=&quot;https://www.npmjs.com/package/dotenv&quot;&gt;.dovenv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tras importar mongoClient, y definir las variables que se emplearán en la conexión (url a la BBDD, nombre de la BBDD y nombre de la colección) lanzo un &lt;code&gt;mongoClient.connect()&lt;/code&gt; que devuelve bien un error de conexión o abre la conexión (cliente) al gestor de BBDD MongoDB. Luego, con  &lt;code&gt;const db = database.db(db_name);&lt;/code&gt; obtengo acceso a la BBDD, y seguidamente hago una consulta con &lt;code&gt;db.collection(collection).find()&lt;/code&gt;. Una vez obtengo el resultado de la búsqueda (en este caso todos los documentos dentro de la colección de la BBDD), los muestro por consola y cierro la base de datos con &lt;code&gt;database.close();&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pero si deseo hacer otra búsqueda, o en el módulo tengo una serie de rutas, todas ellas apuntando a una consulta a la BBDD, el número de aperturas y cierres de la conexión se multiplica por el número de consultas. Esto en una página personal o con poco tráfico es sostenible, pero no lo es para grandes flujos de acceso o incluso para situaciones de picos concretos de acceso al servidor (horas de más tráfico, momentos del año donde las consultas se incrementan, por ejemplo cuando se solicitan los resultados de un evento, las notas de fin de curso, una noticia que ha tenido popularidad o alcance…).&lt;/p&gt;
&lt;p&gt;Mantener la conexión abierta para distintas consultas en un módulo es fácil, pero, ¿cómo abrirla a través de los distintos módulos de la aplicación?&lt;/p&gt;
&lt;h2 id=&quot;primer-acercamiento-importar-y-conectar&quot;&gt;Primer acercamiento: Importar y conectar&lt;/h2&gt;
&lt;p&gt;Mi primera opción fue que si voy a emplear la conexión en distintos módulos debía extraer el proceso de conexión a un módulo a parte y luego importarlo allá donde lo necesite, y dicho y hecho:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MongoClient&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mongodb&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).MongoClient;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}:${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PORT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MongoClient.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;connect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(db_name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; loadDB;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este módulo realiza lo mismo que en el ejemplo anterior, es decir, abre una conexión a MongoDB, pero lo hace exportando la función asíncrona &lt;code&gt;loadDB&lt;/code&gt; para que pueda ser llamada desde otros módulos con:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../services/DB&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; collection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;products&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;db.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;collection&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tras cargar &lt;code&gt;loadDB&lt;/code&gt;, declaro la variable de ámbito global &lt;code&gt;db&lt;/code&gt; que contendrá la conexión a la BBDD, y en la línea:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ejecuto la función asíncrona &lt;code&gt;loadDB()&lt;/code&gt; para obtener la conexión que se guardará en &lt;code&gt;db&lt;/code&gt;, y ya puedo hacer la consulta con &lt;code&gt;db.collection(collection).find()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Esta consulta podría formar parte de una ruta de &lt;strong&gt;express&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; express&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; router&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; express.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Router&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../services/DB&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; collection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;products&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; loadDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;())();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;router.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;/ejemplo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    db.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;collection&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(collection).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toArray&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;){&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; router;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pero claro, esta forma de proceder implica abrir una conexión por cada módulo de rutas que use la función loadDB. No es lo que busco.&lt;/p&gt;
&lt;h1 id=&quot;alternativa-función-callback-al-rescate&quot;&gt;Alternativa: función &lt;em&gt;callback&lt;/em&gt; al rescate&lt;/h1&gt;
&lt;p&gt;¿Qué tal si, en vez de intentar traer a cada módulo la conexión a la BBDD llevo las rutas a la función que abre la conexión directamente mediante una función &lt;em&gt;callback&lt;/em&gt;? Veamos…&lt;/p&gt;
&lt;p&gt;Para que todas las rutas puedan usar la variable &lt;code&gt;db&lt;/code&gt; que se declara cuando se lleva a cabo la conexión, podría establecer una única conexión a la base de datos desde index.js (o app.js) osea, desde el fichero principal de la aplicación &lt;strong&gt;Node.js&lt;/strong&gt;, y referenciar las rutas dentro de una función &lt;em&gt;callback&lt;/em&gt; que le pase al módulo encargado de abrir la conexión.&lt;/p&gt;
&lt;p&gt;Esta idea fue la que me propuso &lt;strong&gt;ZeroBl&lt;/strong&gt;, que se tomó el tiempo de responder a mis preguntas en un foro de Discord, y tras pasarme el código que él usa para establecer su conexión, y buscar un poco más de información en StackOverflow, el resultado fue el siguiente:&lt;/p&gt;
&lt;h2 id=&quot;módulo-de-conexión-a-la-bbdd&quot;&gt;Módulo de conexión a la BBDD&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MongoClient&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mongodb&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).MongoClient;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}:${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PORT&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _db;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _client;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; connectDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        MongoClient.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;connect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            useNewUrlParser: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            useUnifiedTopology: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            _client &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            _db &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(db_name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err, client);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (_db) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _db;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;BBDD no encontrada.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; disconnectDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (_db) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    throw&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;BBDD no encontrada.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { connectDB, getDB, disconnectDB };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, este módulo devuelve tres funciones: &lt;code&gt;connectDB&lt;/code&gt; que abre la conexión, &lt;code&gt;getDB&lt;/code&gt; que obtiene la conexión a la BBDD, y &lt;code&gt;disconnectDB&lt;/code&gt;, que cierra la conexión a la BBDD.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;connectDB&lt;/code&gt; le paso un &lt;code&gt;callback&lt;/code&gt; que se ejecutará en el ámbito donde está viva la conexión. Igual deberemos obtener la referencia a &lt;code&gt;_db&lt;/code&gt; en cada módulo que usemos. Lo voy a explicar enseguida.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;disconnectDB&lt;/code&gt; puedo cerrar la conexión a la BBDD desde cualquier parte del programa, pero también debo importarlo si queremos usarlo.&lt;/p&gt;
&lt;h2 id=&quot;el-indexjs&quot;&gt;El index.js&lt;/h2&gt;
&lt;p&gt;O cualquier otro js que haga las veces de inicio de nuestra app:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; express&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; app&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; express&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; port&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; mongoDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;./services/DB&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mongoDB.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;connectDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Ej. http:localhost:3000/ejemplo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; RouteEjemplo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;./routes/ejemplo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    app.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;/ejemplo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, RouteEjemplo);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // otras rutas...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Ej. http:localhost:3000/exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    app.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;/exit&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Fin&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        process.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;kill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(process.pid, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;SIGTERM&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    app.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;404&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Error 404: No encontrado.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    app.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;next&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err.stack);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err.status &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 500&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(status).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`Error ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;status&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}: ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}.`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; server&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; app.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;listen&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(port, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`Servidor levantado en el puerto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}.`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    process.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;SIGTERM&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        server.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Proceso terminado.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importo el módulo de &lt;code&gt;mongoDB&lt;/code&gt; y conecto a la BBDD con:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mongoDB.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;connectDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Función callback&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Función a la que le paso como &lt;em&gt;callback&lt;/em&gt; todo el manejo de rutas, e incluso levanto el servidor. Recuerda que esta función se ejecutará tras establecer la conexión en la línea:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; callback&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err, client);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Al ejecutar la función obtengo dos posibles valores, o bien un error, o bien el cliente para la conexión. Esto me va a permitir hacer uso del cliente desde la misma función &lt;em&gt;callback&lt;/em&gt;, para, por ejemplo, cerrar la conexión, como ocurre en la ruta &lt;code&gt;/exit&lt;/code&gt; en:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usar una ruta para cerrar la aplicación por supuesto es un ejemplo ilustrativo, y no es la mejor forma de hacerlo. ;)&lt;/p&gt;
&lt;p&gt;Si quiero cerrar la aplicación desde dentro de un módulo de, por ejemplo, una ruta, debo usar &lt;code&gt;disconnectDB()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;la-ruta-de-ejemplo&quot;&gt;La ruta de ejemplo&lt;/h2&gt;
&lt;p&gt;Como dije, para poder utilizar la BBDD en las distintas rutas o en los módulos de la aplicación, debo importar la referencia a &lt;code&gt;db&lt;/code&gt; en cada módulo con:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; mongoDB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../services/DB&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mongoDB.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getDB&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;y a partir de ahí puedo usar &lt;code&gt;db&lt;/code&gt; en todo el módulo. Así de simple.&lt;/p&gt;
&lt;p&gt;Esto es posible porque, como hemos visto, estamos llamado a esta ruta dentro del &lt;em&gt;callback&lt;/em&gt; que pasamos a la función que abre la conexión.&lt;/p&gt;
&lt;h1 id=&quot;en-resumen&quot;&gt;En resumen&lt;/h1&gt;
&lt;p&gt;Mediante un módulo que devuelve tres funciones podemos abrir la conexión a la BBDD (recibiendo y ejecutando un &lt;em&gt;callback&lt;/em&gt;) obtener la referencia a la BBDD y cerrar la conexión a la BBDD.&lt;/p&gt;
&lt;p&gt;Dentro del &lt;em&gt;callback&lt;/em&gt; definimos las rutas (&lt;code&gt;app.use&lt;/code&gt;) que van a hacer uso de la BBDD, y en cada módulo donde se defina la ruta o las sub-rutas, deberemos obtener la referencia a la BBDD para poder usarla.&lt;/p&gt;
&lt;p&gt;En este &lt;a href=&quot;https://stackoverflow.com/questions/24621940/how-to-properly-reuse-connection-to-mongodb-across-nodejs-application-and-module&quot;&gt;enlace a StackOverflow&lt;/a&gt; (&lt;em&gt;en inglés&lt;/em&gt;) podrás obtener más información y alternativas a esta solución.&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/mongodb.B38n9K_s_1aeGYn.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>express</category><category>mongodb</category><author>JavGuerra</author></item><item><title>Kit básico para manejo del DOM</title><link>https://javguerra.github.io/blog/kit-dom</link><guid isPermaLink="true">https://javguerra.github.io/blog/kit-dom</guid><description>Colección de utilidades para no depender de librerías externas.</description><pubDate>Mon, 25 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/code.BoBme8u9_ZyVCnB.webp&quot; alt=&quot;Código&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#dom&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;El uso del DOM desde JavaScript ha mejorado mucho en los últimos años. Librerías como jQuery facilitaron enormemente la tarea del programador a la hora de acceder a identificadores, clases y etiquetas, y aunque ahora disponemos de nuevas formas de acceso en JavaScript que han hecho olvidar en parte aquella librería, la forma en que trabajamos con el DOM aún se puede mejorar. En esta entrada veremos unas pocas funciones que nos ayudarán en el día a día.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Este artículo ha sido publicado también en &lt;a href=&quot;https://ifgeekthen.nttdata.com/s/post/kit-basico-para-manejo-del-dom-MC33VANXA4HFFARH6TCP3P7DTPZY&quot;&gt;IfGeekThen&lt;/a&gt;, el blog de NTT Data, el 24 de abril de 2026.&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;selección-al-estilo-jquery&quot;&gt;Selección al estilo jQuery&lt;/h1&gt;
&lt;p&gt;Para empezar, un canto a la nostalgia. Si usabas la famosa librería y echas de menos su forma tan simple de funcionar, aquí tienes una aproximación a la selección de elementos del DOM.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el); };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;o en versión función flecha, como más te guste:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;$(el)&lt;/code&gt; seleccionará un elemento (&lt;code&gt;el&lt;/code&gt;) del DOM que podemos asignar a una variable o con el que podemos usar propiedades, por ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#aviso&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;rojo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;que añadirá la clase &lt;code&gt;.rojo&lt;/code&gt; al elemento con el id &lt;code&gt;aviso&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;El uso de &lt;code&gt;querySelector()&lt;/code&gt; ha venido a simplificar mucho el acceso a los elementos del DOM, pero con esta función &lt;code&gt;$()&lt;/code&gt;, seleccionar elementos es aún más simple, y va a ser de ayuda en las siguientes funciones.&lt;/p&gt;
&lt;p&gt;Podemos mejorar esta función dándole la posibilidad de buscar dentro de un elemento específico.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parent.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelector&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Podríamos usarla de esta forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; fila&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#fila3&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, tabla);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Donde &lt;code&gt;tabla&lt;/code&gt; es el elemento padre. De no indicarlo, el elemento padre será todo el documento (document).&lt;/p&gt;
&lt;p&gt;También podemos seleccionar varios elementos con &lt;code&gt;$$()&lt;/code&gt; con esta función:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $$&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E igualmente podemos mejorar esto:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $$&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parent.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el)];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aquí, además de poder indicar el nodo padre, obtendremos automáticamente el NodeList en un array ([…]).&lt;/p&gt;
&lt;h1 id=&quot;crear-nuevos-elementos-y-conectarlos-al-dom&quot;&gt;Crear nuevos elementos y conectarlos al DOM&lt;/h1&gt;
&lt;p&gt;La creación de nuevos elementos del DOM requiere de varios pasos. Crear el elemento, introducir la información en el elemento si es necesario y conectarlo al elemento padre. ¿Qué tal si lo simplificamos con una función?&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;tag&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tag);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (content) el.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; content;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    parent.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con la función &lt;code&gt;createEl()&lt;/code&gt; cubrimos los tres pasos necesarios para crear, completar y conectar un nuevo elemento, y la función nos devolverá el nuevo elemento para que podamos trabajar con él:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; $titulo&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;body&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;h1&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Hola Mundo&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con esta línea crearemos un elemento &lt;code&gt;H1&lt;/code&gt; dentro del &lt;code&gt;body&lt;/code&gt; que contendrá el texto &lt;code&gt;&apos;Hola Mundo&apos;&lt;/code&gt;, y la referencia al nuevo elemento está contenida en la variable &lt;code&gt;$titulo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;El &lt;code&gt;$&lt;/code&gt; de la variable &lt;code&gt;titulo&lt;/code&gt; no es necesario (ni que estuviésemos programando en PHP…), pero recordando el uso de jQuery, es una buena forma de identificar aquellas variables que hacen referencia a elementos del DOM para diferenciarlas de las otras.&lt;/p&gt;
&lt;p&gt;Esta versión puede mejorarse mucho para, por ejemplo, añadir atributos (attrs) e hijos (children)… hasta donde te de la imaginación.&lt;/p&gt;
&lt;h2 id=&quot;uso-práctico-creación-de-tablas-básicas-con-createel&quot;&gt;Uso práctico: Creación de tablas básicas con createEl()&lt;/h2&gt;
&lt;p&gt;Esta nueva función es muy potente, y simplifica mucho las líneas de código que tenemos que usar para crear estructuras del DOM complejas con JavaScript. Un ejemplo de ello son las tablas y sus etiquetas anidadas. Veamos cómo sería una función que crease una tabla simple con &lt;code&gt;createEl()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createTable&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;footers&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; table&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(parent, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;table&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;id&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, id);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; thead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(table, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;thead&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(thead, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; header&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; headers) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; th&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tr, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;th&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, header);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        th.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;scope&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;col&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (footers) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; tfoot&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(table, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tfoot&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tfoot, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tr&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; footer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; footers) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tr, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;td&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, footer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(table, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tbody&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;createTable()&lt;/code&gt; crea una tabla dentro de un elemento padre, le asigna un identificador, y crea las cabeceras y pies que le indiquemos, devolviendo la referencia al elemento &lt;code&gt;tbody&lt;/code&gt; de la tabla para que podamos rellenarla con filas y columnas.&lt;/p&gt;
&lt;p&gt;Un ejemplo sencillo de uso sería:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$tBody &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; createTable&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#section&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;miTabla&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;núm.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;producto&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;$tBody.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;vegetales&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;que mostrará la siguiente tabla a la que podemos seguir añadiendo elementos:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align: center&quot;&gt;núm&lt;/th&gt;
&lt;th style=&quot;text-align: left&quot;&gt;producto&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;text-align: left&quot;&gt;vegetales&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Fácil y cómodo. ¿verdad?&lt;/p&gt;
&lt;h1 id=&quot;vaciar-un-elemento-de-forma-eficiente&quot;&gt;Vaciar un elemento de forma eficiente&lt;/h1&gt;
&lt;p&gt;Vaciar un contenedor con &lt;code&gt;innerHTML = &quot;&quot;&lt;/code&gt; funciona, pero la siguiente función es más eficiente y segura, porque no reemplaza el contenedor entero y no rompe event listeners internos, lo que puede provocar pérdida o duplicación de eventos.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; emptyEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (el.firstChild) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        el.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeChild&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el.firstChild);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Un ejemplo para borrar el contenido de una lista:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;emptyEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#lista&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;añadir-o-quitar-una-clase-css&quot;&gt;Añadir o quitar una clase CSS&lt;/h1&gt;
&lt;p&gt;La función:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; toggleClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;className&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toggle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(className);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;aprovecha el.classList.toggle() para:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Añadir una clase si el elemento no la tiene.&lt;/li&gt;
&lt;li&gt;Quitar una clase si el elemento ya la tiene.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;y devuelve &lt;code&gt;true&lt;/code&gt; si la clase se añadió y &lt;code&gt;false&lt;/code&gt; si la clase se eliminó.&lt;/p&gt;
&lt;p&gt;Esta función es ideal para interacciones de usuario tipo click para abrir/cerrar, expandir/contraer, activar/desactivar.&lt;/p&gt;
&lt;h1 id=&quot;establecer-una-clase-según-un-estado-booleano&quot;&gt;Establecer una clase según un estado booleano&lt;/h1&gt;
&lt;p&gt;La función &lt;code&gt;setClass()&lt;/code&gt; permite añadir o quitar una clase según un booleano, garantizando que el elemento queda exactamente en el estado indicado. A diferencia de &lt;code&gt;toggleClass()&lt;/code&gt;, no alterna: fuerza el estado.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;className&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;active&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    el.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toggle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(className, active);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ejemplos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(menu, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;open&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// añade la clase&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(menu, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;open&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// la quita&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(input, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;error&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;isValid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(input.value)); &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Estado de error en un formulario&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tabs.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;tab&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(tab, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;active&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, tab.id &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; selectedId); &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Pestaña activa según ID&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función es perfecta para sincronizar la UI con estados lógicos (isOpen, hasError, isActive, etc.).&lt;/p&gt;
&lt;h1 id=&quot;mostrar-u-ocultar-elementos-del-dom&quot;&gt;Mostrar u ocultar elementos del DOM&lt;/h1&gt;
&lt;p&gt;Una función que nos aporte una forma simple de hacer visible u ocultar cualquier elemento del DOM, por ejemplo las secciones de una página web de una única página (&lt;strong&gt;SPA&lt;/strong&gt;) sería la siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; showEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;visible&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    visible&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el.style.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeProperty&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;display&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el.style.display &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;showEl()&lt;/code&gt; requiere dos parámetros: elemento del DOM con el que vamos a trabajar y si va a estar visible (&lt;code&gt;true&lt;/code&gt;) o invisible (&lt;code&gt;false&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Digamos que en una &lt;strong&gt;SPA&lt;/strong&gt; hemos completado un formulario, y ahora queremos mostrar los resultados. con esta función podríamos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;showEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#form&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;showEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#results&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Partimos de la base de que el elemento con identificador &lt;code&gt;results&lt;/code&gt; estaba oculto, y el elemento con identificador &lt;code&gt;form&lt;/code&gt; visible. De esta forma el formulario se ocultaría y serían visibles los datos derivados de la gestión de formulario.&lt;/p&gt;
&lt;h1 id=&quot;comprobar-si-un-elemento-está-visible&quot;&gt;Comprobar si un elemento está visible&lt;/h1&gt;
&lt;p&gt;Esta función permite saber si un elemento está realmente visible en la página.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; isVisible&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el.offsetWidth &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          el.offsetHeight &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          el.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getClientRects&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;showEl()&lt;/code&gt; e &lt;code&gt;isVisible()&lt;/code&gt; se complementan perfectamente porque la primera controla si un elemento se muestra u oculta, y la segunda detecta si un elemento está actualmente visible.&lt;/p&gt;
&lt;p&gt;Veamos un ejemplo de uso conjunto:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;isVisible&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(panel)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    showEl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(panel, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// lo muestra solo si está oculto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;activar-o-desactivar-un-botón&quot;&gt;Activar o desactivar un botón&lt;/h1&gt;
&lt;p&gt;Es una buena práctica desactivar un botón cada vez que se dispare un evento asociado a este. Nada más fácil con la siguiente función:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setInactiveBtn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;inactive&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    button.disabled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inactive;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    inactive&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; button.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;aria-disabled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;true&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; button.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;removeAttribute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;aria-disabled&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con &lt;code&gt;setInactiveBtn()&lt;/code&gt; cambiamos el estado &lt;code&gt;disabled&lt;/code&gt; del botón que indiquemos pasándole los valores &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;false&lt;/code&gt;. Un ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; setInactiveBtn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#submit&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función desactivará el botón con el identificador &lt;code&gt;submit&lt;/code&gt; (&lt;code&gt;disabled = true&lt;/code&gt;). Para volver a activarlo, será suficiente con usar la misma función con el status &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;comprobar-si-un-botón-está-activo&quot;&gt;Comprobar si un botón está activo&lt;/h1&gt;
&lt;p&gt;También podemos necesitar conocer el estado de un botón, si este está activo o inactivo.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; isInactiveBtn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; button.disabled &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Un ejemplo de uso con &lt;code&gt;setInactiveBtn()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;setInactiveBtn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btn, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;isInactiveBtn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btn));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Activa o desactiva el botón invirtiendo su estado actual (si está activo lo desactiva, y si está inactivo lo activa).&lt;/p&gt;
&lt;h1 id=&quot;decodificar-entidades-html-con-ayuda-del-dom&quot;&gt;Decodificar entidades HTML con ayuda del DOM&lt;/h1&gt;
&lt;p&gt;Pasemos ahora a cosas más específicas a modo de bonus.&lt;/p&gt;
&lt;p&gt;Aunque JavaScript incluye funciones como &lt;code&gt;encodeURIComponent()&lt;/code&gt; y &lt;code&gt;decodeURIComponent()&lt;/code&gt;, estas se utilizan exclusivamente para codificar y decodificar URLs, no entidades HTML. Por tanto, una función como esta resulta práctica cuando recibimos cadenas que contienen entidades como &lt;code&gt;&amp;amp;amp;&lt;/code&gt; o &lt;code&gt;&amp;amp;quot;&lt;/code&gt;, ya que el lenguaje no ofrece un método nativo para convertirlas en texto legible. Podemos apoyarnos en el motor del DOM para conseguirlo.&lt;/p&gt;
&lt;p&gt;La siguiente función crea un nodo temporal, asigna su contenido usando &lt;code&gt;innerHTML&lt;/code&gt; y obtiene el texto decodificado mediante &lt;code&gt;textContent&lt;/code&gt;. Es un ejemplo interesante de cómo el DOM puede ayudarnos más allá de la manipulación visual de la página.&lt;/p&gt;
&lt;p&gt;Cuando la función recibe la información codificada con entidades HTML, por ejemplo, a través de una API, y queremos reconducir esa información a, por ejemplo, un fichero de &lt;em&gt;logs&lt;/em&gt; en texto plano, o tal vez enviarla a consola, la información no se muestra correctamente. Una forma de convertir a un &lt;em&gt;string&lt;/em&gt; la información que incluye entidades HTML sería la siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; decodeHTMLEntities&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; html &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; div&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createElement&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    div.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; html;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; div.textContent &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función recibe la cadena a «decodificar» y devuelve la cadena en texto simple. Para ello obliga al DOM a trabajar para nosotros creando un elemento &lt;code&gt;div&lt;/code&gt; en el que se incluye el texto «codificado» y del que se lee luego el texto «decodificado» para devolverlo con &lt;code&gt;return&lt;/code&gt;. Como se ve, el elemento &lt;code&gt;div&lt;/code&gt; nunca llega a conectarse al árbol DOM.&lt;/p&gt;
&lt;p&gt;Tomemos el siguiente ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; texto &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; decodeHTMLEntities&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Los%20ni%C3%B1os%20com%C3%ADan%20y%20daban%20migajas%20a%20la%20cig%C3%BCe%C3%B1a.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El valor de &lt;code&gt;texto&lt;/code&gt; resultante será: ‘&lt;code&gt;Los niños comían y daban migajas a la cigüeña.&lt;/code&gt;’.&lt;/p&gt;
&lt;h1 id=&quot;iniciar-si-el-dom-está-cargado&quot;&gt;Iniciar si el DOM está cargado&lt;/h1&gt;
&lt;p&gt;Concluyo con una función primordial.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;onReady()&lt;/code&gt;, si el DOM ya está cargado, se ejecutará la función de inicio que le pasemos inmediatamente. Si el DOM aún se está cargando, añade un listener a DOMContentLoaded.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onReady&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (document.readyState &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;loading&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        fn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, fn);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Veamos un ejemplo de uso:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onReady&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; btn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;#btnStart&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setClass&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(btn, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ready&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función &lt;code&gt;onReady()&lt;/code&gt; permite escribir inicialización limpia sin preocuparte por dónde está ubicado el script o de qué forma se carga.&lt;/p&gt;
&lt;h1 id=&quot;tu-propio-kit&quot;&gt;Tu propio kit&lt;/h1&gt;
&lt;p&gt;Espero que alguna de estas funciones te resulte útil, te hagan la vida más agradable y, sobre todo, que te animen a experimentar por tu cuenta.&lt;/p&gt;
&lt;p&gt;El DOM ofrece muchísimas posibilidades, y a veces basta con probar una idea para descubrir una utilidad nueva que encaje contigo y ampliar de esta forma tu kit de herramientas. ¡Diviértete explorando!&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/code.BoBme8u9_ZyVCnB.webp"/><category>código</category><category>javascript</category><category>dom</category><author>JavGuerra</author></item><item><title>Conocer el ancho y alto de una imagen con JavaScript antes de usarla en HTML</title><link>https://javguerra.github.io/blog/ancho-alto</link><guid isPermaLink="true">https://javguerra.github.io/blog/ancho-alto</guid><description>Ideas para evitar el «FOUC» de contenido cuando desconocemos las medidas de las imágenes</description><pubDate>Mon, 01 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/img.BrQ752_Z_Z2rMVCO.webp&quot; alt=&quot;Imagen&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#imágenes&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Cuando una web está cargando, se producen cambios en el diseño conocidos como &lt;em&gt;Flash Of Unestiled Content&lt;/em&gt; (FOUC) que son visualmente molestos para el usuario y le hacen perder su punto de referencia en la página. Las imágenes son uno de los principales causantes de estos cambios. Hasta que no son cargadas no se conoce su ancho y alto, por lo que es un buen criterio de diseño indicar el ancho y alto de la imagen en el HTML. Pero ¿qué ocurre cuando no conocemos las medidas de las imágenes que vamos a cargar? Pongamos como ejemplo una galería de fotos que tomamos mediante fetch. En esta entrada veremos como afrontarlo.&lt;/p&gt;
&lt;h1 id=&quot;el-código&quot;&gt;El código&lt;/h1&gt;
&lt;p&gt;Pongamos que tenemos un arreglo con un listado de URLs de fotos de adorables perritos que queremos mostrar en una galería de fotos. Este arreglo podemos definirlo u obtenerlo mediante &lt;code&gt;fetch&lt;/code&gt; desde una API u otro lugar. Cada imagen tiene un tamaño distinto, osea, unas medidas para los valores &lt;code&gt;width&lt;/code&gt; y &lt;code&gt;height&lt;/code&gt; diferentes. Nuestro objetivo es conocer estos valores antes de mostrar las fotos en la galería, para asignarles su ancho y alto correctos y evitar de esa manera el FUOC. De otra forma, a medida que se carguen las imágenes en la galería, estas irán abriéndose hueco para ocupar su espacio «empujando» el diseño.&lt;/p&gt;
&lt;p&gt;Con este código que seguramente encontré y adapté de StackOverflow o un sitio similar podemos hacerlo. Lo describo más abajo.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; galeria&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;galeria&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; fotos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/dachshund/Stretched_Dachshund.jpg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/cattledog-australian/IMG_1211.jpg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/dachshund/dachshund-7.jpg&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; medidas&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;reject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; img&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Image&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onload&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            resolve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ ancho: img.width, alto: img.height });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onerror&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            reject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Imagen no encontrada.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.src &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; urlFoto;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fotos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    medidas&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(urlFoto)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            galeria.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;img src=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `width=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ancho&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; height=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;alto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `alt=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; title=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; /&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para usar este código, debemos tener algo como esto en el HTML:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;galeria&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vamos con JavaScript. Primero defino las variables con las que voy a trabajar. La referencia al elemento del DOM y el arreglo de URLs de fotos de perritos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; galeria&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;galeria&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; fotos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/dachshund/Stretched_Dachshund.jpg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/cattledog-australian/IMG_1211.jpg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;https://images.dog.ceo/breeds/dachshund/dachshund-7.jpg&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;obtener-las-medidas&quot;&gt;Obtener las medidas&lt;/h2&gt;
&lt;p&gt;Aquí es donde se produce la magia. Veamos como:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; medidas&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Promise&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;resolve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;reject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; img&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Image&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onload&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            resolve&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ ancho: img.width, alto: img.height });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;onerror&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;            reject&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Imagen no encontrada.&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        img.src &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; urlFoto;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esta función recibe como parámetro la URL de la imagen a calcular y envuelve una promesa que resolverá un objeto con las medidas &lt;code&gt;ancho&lt;/code&gt; y &lt;code&gt;alto&lt;/code&gt; o bien un error.&lt;/p&gt;
&lt;p&gt;Para hacerlo, instancio una nueva imagen con &lt;code&gt;const img = new Image();&lt;/code&gt; y declaro dos eventos asociados a &lt;code&gt;img&lt;/code&gt;, un evento que se disparará cuando se cargue la imagen en &lt;code&gt;img&lt;/code&gt; con &lt;code&gt;img.src = urlFoto;&lt;/code&gt; (&lt;code&gt;img.onload&lt;/code&gt;), y otro que se disparará si se produce un error al cargar la imagen (&lt;code&gt;img.onerror&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Es decir, cuando cargo la imagen con &lt;code&gt;img.src = urlFoto;&lt;/code&gt; pueden pasar dos cosas, que se lance el evento &lt;code&gt;onload&lt;/code&gt; si todo fue bien, o el evento &lt;code&gt;onerror&lt;/code&gt; si algo falló.&lt;/p&gt;
&lt;p&gt;Si todo fue bien, la imagen estará «cargada» en &lt;code&gt;img&lt;/code&gt;, y podemos obtener su ancho y alto. Mediante &lt;code&gt;resolve({ ancho: img.width, alto: img.height });&lt;/code&gt; devuelvo estos valores dentro de un objeto.&lt;/p&gt;
&lt;p&gt;Si algo falló, devuelvo un error con &lt;code&gt;reject(new Error(&apos;Imagen no encontrada.&apos;));&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;poner-las-imágenes-en-la-galería&quot;&gt;Poner las imágenes en la galería&lt;/h2&gt;
&lt;p&gt;Si tenemos la función &lt;code&gt;medidas()&lt;/code&gt; a la que podemos pasarle una URL, podemos recorrer el arreglo &lt;code&gt;fotos&lt;/code&gt; y poner en nuestro HTML cada foto con sus medidas exactas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fotos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    medidas&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(urlFoto)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;then&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            galeria.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;img src=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `width=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ancho&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; height=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;alto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `alt=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; title=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; /&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mediante un &lt;code&gt;.forEach()&lt;/code&gt; recorro cada elemento del arreglo. De él obtengo dos valores, cada una de las URLs y el índice que ocupa en el arreglo cada URL.&lt;/p&gt;
&lt;p&gt;Llamo a la función &lt;code&gt;medidas()&lt;/code&gt; a la que le paso como parámetro la URL de una foto (&lt;code&gt;urlFoto&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;La función devuelve una promesa que debe ser resuelta. Así mediante &lt;code&gt;.then()&lt;/code&gt; obtengo el objeto &lt;code&gt;mide&lt;/code&gt; que contiene el ancho y el alto de la imagen que indiqué mediante la URL, que es el resultado del &lt;code&gt;resolve&lt;/code&gt; de la promesa. De otra forma, con &lt;code&gt;.catch()&lt;/code&gt; se captura el error resultante del &lt;code&gt;reject&lt;/code&gt; de la promesa.&lt;/p&gt;
&lt;p&gt;Si tenemos las medidas de ancho y alto de la imagen a mostrar, ya podemos conectarla al DOM con:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;galeria.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;img src=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;urlFoto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `width=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ancho&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; height=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mide&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;alto&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `alt=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; title=&quot;Foto ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot; /&amp;gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esto insertará en el elemento del DOM identificado con &lt;code&gt;#galeria&lt;/code&gt; una imagen (&lt;code&gt;img&lt;/code&gt;) con el enlace a la foto (&lt;code&gt;src&lt;/code&gt;), su ancho (&lt;code&gt;width&lt;/code&gt;), alto (&lt;code&gt;height&lt;/code&gt;) y una etiqueta &lt;code&gt;alt&lt;/code&gt; que «describe» (vagamente) la foto. Con &lt;code&gt;title&lt;/code&gt; podemos obtener la misma descripción al pasar con el ratón sobre la imagen.&lt;/p&gt;
&lt;p&gt;Por supuesto a la imagen podemos aplicarle las clases CSS que deseemos para, por ejemplo, que aparezca correctamente si usamos flexbox o similar para mostrar la galería…&lt;/p&gt;
&lt;h1 id=&quot;el-módulo-image-size&quot;&gt;El módulo image-size&lt;/h1&gt;
&lt;p&gt;Si realizamos el test &lt;a href=&quot;https://pagespeed.web.dev/&quot;&gt;Page Speed de Google&lt;/a&gt; a nuestra página y no indicamos el ancho y alto de las imágenes, esto nos penalizará en la puntuación de viabilidad en el apartado &lt;em&gt;&lt;code&gt;Cumulative Layout Shift&lt;/code&gt;&lt;/em&gt; o &lt;code&gt;CLS&lt;/code&gt;. El «movimiento inesperado de contenido» en español, mide la estabilidad visual cuantificando la frecuencia con la que los usuarios experimentan cambios de diseño inesperados. Así pues, cuanto más bajo sea el CLS, mejor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Manz&lt;/strong&gt;, de &lt;a href=&quot;https://manz.dev/&quot;&gt;manz.dev&lt;/a&gt;, en su canal de &lt;a href=&quot;https://discord.manz.dev/&quot;&gt;Discord&lt;/a&gt;, cuenta lo siguiente:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;El navegador nunca va a saber las dimensiones (ancho y alto) de la imagen hasta descargar la imagen. Si la imagen es pesada va a tardar un rato y no es posible “reservar” ese espacio en la web porque no lo conoce. La única forma de evitar el CLS es indicarle tú previamente el tamaño para que no haya “salto”.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mediante la opción propuesta, podemos resolver este problema si somos nosotros los que desarrollamos todo el código, pero si estamos trabajando con &lt;em&gt;frameworks&lt;/em&gt;, también hay soluciones disponibles. &lt;strong&gt;Manz&lt;/strong&gt; sigue diciendo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hay una forma de evitarlo, si estás usando SSG (eleventy, astro, next, etc…) y es que en la fase de “compilación” le pases algún plugin que vaya mirando las imágenes y sacando sus dimensiones con node y añadiendo automáticamente el width y height. Yo, por ejemplo, uso este: &lt;a href=&quot;https://www.npmjs.com/package/image-size&quot;&gt;image-size&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Como indica &lt;strong&gt;Manz&lt;/strong&gt;, &lt;a href=&quot;https://www.npmjs.com/package/image-size&quot;&gt;image-size&lt;/a&gt; es una opción que permite obtener las dimensiones de una imagen y que podemos instalar con npm.&lt;/p&gt;
&lt;h1 id=&quot;un-truco&quot;&gt;Un truco&lt;/h1&gt;
&lt;p&gt;Em Twitter &lt;strong&gt;Manz&lt;/strong&gt; contaba:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Otras soluciones más simples e ingeniosas pueden ser establecer un alto máximo para el contenedor, de modo que no haga reflow de elementos inferiores, y los items del interior (galería) los vas haciendo aparecer a medida que se carguen con CSS/JS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Esta, sin duda, es otra opción.&lt;/p&gt;
&lt;h1 id=&quot;resumen&quot;&gt;Resumen&lt;/h1&gt;
&lt;p&gt;En Twitter, &lt;strong&gt;Manz&lt;/strong&gt; proponía también estas tres opciones para evitar el &lt;em&gt;reflow&lt;/em&gt; que podemos tomar a modo de resumen:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Establecer siempre el width y height (tedioso)&lt;/li&gt;
&lt;li&gt;Usar aspect-ratio de CSS (&lt;a href=&quot;https://caniuse.com/mdn-css_properties_aspect-ratio&quot;&gt;https://caniuse.com/mdn-css_properties_aspect-ratio&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Automatizar con alguna herramienta de preprocesado. Yo en 11ty uso image-size o soluciones parecidas&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Ejemplo de uso de la solución propuesta: &lt;a href=&quot;https://javguerra.github.io/ejercicios-web-javascript/17-fetch.html&quot;&gt;Galería de perritos&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Módulo &lt;a href=&quot;https://www.npmjs.com/package/image-size&quot;&gt;image-size&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pagespeed.web.dev/&quot;&gt;Page Speed de Google&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.itdo.com/blog/que-es-el-cumulative-layout-shift-cls/&quot;&gt;¿Qué es el Cumulative Layout Shift (CLS)?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Twitter de @Manz: &lt;a href=&quot;https://twitter.com/Manz/status/1527681719964512256&quot;&gt;¿Qué es «FUOC»?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Web de @Manz: &lt;a href=&quot;https://manz.dev/&quot;&gt;manz.dev&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/img.BrQ752_Z_Z2rMVCO.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>imágenes</category><author>JavGuerra</author></item><item><title>Modo oscuro en Laravel</title><link>https://javguerra.github.io/blog/dark-mode</link><guid isPermaLink="true">https://javguerra.github.io/blog/dark-mode</guid><description>Con Alpine.js y Tailwind CSS</description><pubDate>Tue, 16 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/dark-mode.CaMyMtw1_Z2hfeRn.webp&quot; alt=&quot;Modo oscuro&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#laravel&lt;/em&gt;, &lt;em&gt;#php&lt;/em&gt;, &lt;em&gt;#tema&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#alpine.js&lt;/em&gt;, &lt;em&gt;#tailwind&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Basándome en &lt;a href=&quot;https://jetstream.laravel.com/&quot;&gt;Laravel Jetstream&lt;/a&gt; con &lt;a href=&quot;https://laravel-livewire.com/&quot;&gt;Livewire&lt;/a&gt;, que también incluye &lt;a href=&quot;https://alpinejs.dev/&quot;&gt;Alpine.js&lt;/a&gt; y &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;TailwindCSS&lt;/a&gt;, en esta entrada muestro como implementar el modo oscuro en nuestras aplicaciones.&lt;/p&gt;
&lt;h1 id=&quot;el-modo-oscuro&quot;&gt;El modo oscuro&lt;/h1&gt;
&lt;p&gt;Cada vez es más frecuente que las aplicaciones se desarrollen pensando en implementar un modo oscuro (&lt;em&gt;dark mode&lt;/em&gt;) que permita descasar la vista del usuario con colores más apagados. La posibilidad de implementar estos modos con los &lt;em&gt;frameworks&lt;/em&gt; de CSS como Tailwindcss han ayudado a que esto sea así.&lt;/p&gt;
&lt;p&gt;Básicamente, el modo oscuro de Tailwindcss consiste en implementar clases con el prefijo &lt;code&gt;dark:&lt;/code&gt; delante. Ej.:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bg-white dark:bg-black&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esto cambiará el fondo de nuestra página si el modo oscuro está activo.&lt;/p&gt;
&lt;p&gt;Para activarlo, es suficiente con indicarlo añadiendo la clase &lt;code&gt;dark&lt;/code&gt; en la etiqueta &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mediante JavaScript podemos añadir o quitar esta clase y conseguir así que nuestra aplicación cambie el fondo del ejemplo anterior:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/Document/documentElement&quot;&gt;&lt;code&gt;document.documentElement&lt;/code&gt;&lt;/a&gt; hace referencia al elemento raíz del documento, en este caso, la etiqueta &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;pasos&quot;&gt;Pasos&lt;/h1&gt;
&lt;p&gt;Para poder mostrar el modo correctamente y cambiar de modo de forma interactiva, debemos configurar Tailwind en Laravel, necesitaremos un interruptor (&lt;em&gt;switch&lt;/em&gt;) en nuestra aplicación, y querremos también guardar nuestra opción del tema elegido para que se muestre correctamente la próxima vez que accedamos a la aplicación. para esto último me voy a servir de &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/API/Window/localStorage&quot;&gt;local.Storage&lt;/a&gt;. Esto implica lo siguiente:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Indicar a Tailwind que debe usar el cambio de modo oscuro manual.&lt;/li&gt;
&lt;li&gt;Comprobar el modo correspondiente al inicio en local.Storage.&lt;/li&gt;
&lt;li&gt;Guardar el tema la primera vez comprobando el modo del sistema al inicio.&lt;/li&gt;
&lt;li&gt;Mostrar los botones para cambiar de modo.&lt;/li&gt;
&lt;li&gt;Cambiar entre modo claro y modo oscuro y viceversa.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;indicar-a-tailwind-que-debe-usar-el-cambio-de-modo-oscuro-manual&quot;&gt;Indicar a Tailwind que debe usar el cambio de modo oscuro manual&lt;/h2&gt;
&lt;p&gt;Por defecto, Tailwindcss en Laravel está preparado para implementar el tema de las preferencias de modo en el sistema operativo. Si quiero cambiar de modo manualmente (&lt;em&gt;switch&lt;/em&gt;) en lugar de depender de la preferencia del sistema, debo indicarlo en el fichero &lt;code&gt;tailwind.config.js&lt;/code&gt; mediante &lt;code&gt;darkMode: &apos;class&apos;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  darkMode: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;class&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ahora, en vez de escuchar las preferencias de &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme&quot;&gt;prefers-color-scheme&lt;/a&gt; del CSS, Tailwind usará el modo oscuro sólo si este está indicado en `&lt;html class=&quot;dark&quot;&gt; sin tomar en cuenta las preferencias del sistema.&lt;/p&gt;
&lt;h2 id=&quot;comprobar-el-modo-correspondiente-al-inicio-en-localstorage&quot;&gt;Comprobar el modo correspondiente al inicio en local.Storage&lt;/h2&gt;
&lt;p&gt;Cuando elegimos uno de los dos modos, ya sea el modo claro o el modo oscuro para nuestra aplicación, podemos guardarlo en local.Storage para así recuperarlo la siguiente vez que abramos nuestra aplicación. Podemos guardar &lt;code&gt;true&lt;/code&gt; o &lt;code&gt;1&lt;/code&gt; para indicar que el modo oscuro está activo o bien &lt;code&gt;false&lt;/code&gt; o &lt;code&gt;0&lt;/code&gt; para indicar lo contrario. En mi caso usaré &lt;code&gt;1&lt;/code&gt; y &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En el siguiente código en javascript compruebo el valor de &lt;code&gt;localStorage.dark&lt;/code&gt;, y en función de su contenido, añado o quito la clase &lt;code&gt;dark&lt;/code&gt;a la etiqueta &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tener este dato guardado nos permite, además de cambiar de modo, mostrar el icono correcto para intercambiar de modo. Pongamos que usamos un icono de media Luna para indicar el cambio al modo oscuro y un icono de Sol para indicar el cambio al modo claro. Si iniciamos la aplicación en modo oscuro, el icono a mostrar debe ser el Sol, y al contrario si iniciamos en el modo claro.&lt;/p&gt;
&lt;p&gt;El lugar adecuado para este código es el fichero en la ruta &lt;code&gt;/resources/js/app.js&lt;/code&gt; que es llamado desde el fichero en la ruta &lt;code&gt;/resources/views/layouts/app.blade.php&lt;/code&gt;pero dejándolo en &lt;code&gt;app.js&lt;/code&gt;se produce un molesto efecto de pestañeo (&lt;em&gt;flicker&lt;/em&gt;) que nos muestra primero la página en modo claro, y seguidamente hace el cambio al modo oscuro. Así pues, lo incluyo en el fichero &lt;code&gt;app.blade.php&lt;/code&gt;en el &lt;code&gt;head&lt;/code&gt; debajo del &lt;em&gt;title&lt;/em&gt; pero antes de los &lt;em&gt;links&lt;/em&gt;, de la siguiente forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;guardar-el-tema-la-primera-vez-comprobando-el-modo-del-sistema-al-inicio&quot;&gt;Guardar el tema la primera vez comprobando el modo del sistema al inicio&lt;/h2&gt;
&lt;p&gt;La primera vez que abrimos nuestra aplicación no tenemos guardado ningún valor en local.Storage, así que conviene guardar el valor en función de algún criterio. Por defecto podría indicar que le modo oscuro está desactivado, pero ya que tengo la opción de conocer cuál es el tema del sistema operativo, ¿por qué no aprovecharlo? el siguiente código completa esta opción:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; localStorage)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; window.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;matchMedia&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;(prefers-color-scheme: dark)&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).matches)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si existe el valor &lt;code&gt;dark&lt;/code&gt; en local.Storage, o si no existe pero las preferencias del sistema &lt;code&gt;prefers-color-scheme&lt;/code&gt; indican que tenemos activado el modo oscuro, entonces guardo en local.Storage el valor de &lt;code&gt;dark = 1&lt;/code&gt; y añado la clase &lt;code&gt;dark&lt;/code&gt; a la etiqueta &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;. En caso contrario, guardo el valor &lt;code&gt;dark = 0&lt;/code&gt; en local.Storage y quito la clase &lt;code&gt;dark&lt;/code&gt; de la etiqueta &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; ya que no tendremos activo el modo oscuro previamente, ni en local.Storage ni en el sistema operativo.&lt;/p&gt;
&lt;h2 id=&quot;mostrar-los-botones-para-cambiar-de-modo&quot;&gt;Mostrar los botones para cambiar de modo&lt;/h2&gt;
&lt;p&gt;En esta parte vamos a ver cómo usar Alpine.js para mostrar u ocultar un botón en vez de otro. el siguiente código debemos incluirlo en el fichero en la ruta &lt;code&gt;/resources/views/navigation-menu-blade.php&lt;/code&gt; que contiene el menú en la parte superior del tema de la aplicación que trae por defecto Laravel Jetstream. Debemos incluirlo además dos veces, una para el modo responsive y otra para el modo normal.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;&amp;lt;!-- Selector de tema oscuro --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;mr-2&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;moon&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;setMode h-4 w-4 text-gray-400 hover:text-gray-500 cursor-pointer&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; @click&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toggle&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; :class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;{&apos;block&apos;: !show, &apos;hidden&apos;: show}&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; x-cloak&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 24 24&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;currentColor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linejoin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sun&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;setMode h-5 w-5 text-yellow-200 hover:text-yellow-300 cursor-pointer&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; @click&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;toggle&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; :class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;{&apos;hidden&apos;: !show, &apos;block&apos;: show}&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; x-cloak&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; viewBox&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 24 24&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;currentColor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linecap&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-linejoin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; stroke-width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;el &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; contiene dos SVG que corresponden a los iconos de la Luna y el Sol, pero incluyen algunas etiquetas de Alpine.js.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;:class=&quot;{&apos;block&apos;: !show, &apos;hidden&apos;: show}&lt;/code&gt; se mostrará u ocultará el SVG en función del valor de la variable &lt;code&gt;show&lt;/code&gt;. Para definir su valor inicial, en la etiqueta &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; de la línea 1, incluyo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x-data=&quot;{ open: false, show: localStorage.dark == 1 ? true: false, toggle() { this.show = !this.show } }&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con x-data inicializo variables. Lo hago pasando un objeto JavaScript con algunos valores. En este caso, el &lt;code&gt;open: false&lt;/code&gt; del principio ya estaba ahí, pues laravel lo usa para desplegar o no el menú de usuario. Veamos el resto.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;show: localStorage.dark == 1 ? true: false&lt;/code&gt; indico el valor de show en función de lo que indica local.Storage. Si local.Storage es &lt;code&gt;1&lt;/code&gt; entonces show será &lt;code&gt;true&lt;/code&gt;, y se mostrará el icono del Sol, según indica &lt;code&gt;{&apos;hidden&apos;: !show, &apos;block&apos;: show}&lt;/code&gt; del segundo SVG, (&lt;code&gt;&apos;hidden&apos; false, &apos;block&apos; true&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Para saber más sobre la directiva &lt;code&gt;:class&lt;/code&gt;, consultar: &lt;a href=&quot;https://alpinejs.dev/directives/bind#class-object-syntax&quot;&gt;x-bind en Tailwind.js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Con la directiva &lt;code&gt;@click=&quot;toggle&quot;&lt;/code&gt; llamo a la función &lt;code&gt;toggle() { this.show = !this.show }&lt;/code&gt; definida en el &lt;code&gt;x-data&lt;/code&gt; cuando se hace clic sobre el icono. Esto sólo cambiará el icono haciendo que la variable show alterne su valor entre &lt;code&gt;true&lt;/code&gt; y &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cambiar-entre-modo-claro-y-modo-oscuro-y-viceversa&quot;&gt;Cambiar entre modo claro y modo oscuro y viceversa&lt;/h2&gt;
&lt;p&gt;Hemos visto cómo cambiar entre el icono para el modo claro y oscuro y viceversa, pero lo que queremos es que se cambie también el modo en toda la aplicación. Para ello debemos gestionar eventos asociados a los iconos de tal forma que al hacer clic en ellos no sólo cambien el icono sino que añadan o quiten la etiqueta &lt;code&gt;dark&lt;/code&gt; del &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; y de esta forma hacer el cambio de modo efectivo. para conseguirlo, incluyo el siguiente código en el fichero en la ruta &lt;code&gt;/resources/js/app.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;.setMode&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;item.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            localStorage.dark &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            document.documentElement.classList.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dark&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con &lt;code&gt;querySelectorAll(&quot;.setMode&quot;)&lt;/code&gt; busco todas las clases &lt;code&gt;setMode&lt;/code&gt; en la página. De esta forma localizo a todos los SVG que están implicados con los iconos de cambio de modo (ver que cada SVG incluye &lt;code&gt;class=&quot;setMode ...&lt;/code&gt;), y a cada uno de ellos le añado un evento &lt;code&gt;click&lt;/code&gt; de tal forma que, al hacer clic sobre estos iconos, realice la siguiente comprobación: Si el valor de &lt;code&gt;localStorage.dark == 1&lt;/code&gt; guardar el valor &lt;code&gt;0&lt;/code&gt; en local.Storage y quitar el modo oscuro con &lt;code&gt;document.documentElement.classList.remove(&apos;dark&apos;)&lt;/code&gt;. en caso contrario, guardar el valor &lt;code&gt;1&lt;/code&gt; en local.Storage y poner el modo oscuro con &lt;code&gt;document.documentElement.classList.add(&apos;dark&apos;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Guarda todo y no olvides ejecutar &lt;code&gt;npm run dev&lt;/code&gt; desde el terminal para que los cambios funciones correctamente.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://tailwindcss.com/docs/dark-mode&quot;&gt;Tailwindcss dark mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blockpc.cl/blog/como-implementar-el-modo-oscuro-en-laravel&quot;&gt;Como implementar el modo oscuro en laravel?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/dark-mode.CaMyMtw1_Z2hfeRn.webp"/><category>laravel</category><category>php</category><category>tema</category><category>css</category><category>javascript</category><category>alpine.js</category><category>tailwind</category><author>JavGuerra</author></item><item><title>Conexiones asíncronas a MySQL en Node.js</title><link>https://javguerra.github.io/blog/mysql-connect</link><guid isPermaLink="true">https://javguerra.github.io/blog/mysql-connect</guid><description>Usando util.promisify() para convertir en promesas conexiones síncronas de BBDD</description><pubDate>Wed, 14 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/mysql.CIjIICAX_2rcnGP.webp&quot; alt=&quot;MySQL&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#mysql&lt;/em&gt;, &lt;em&gt;#bbdd&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;El módulo &lt;code&gt;mysql&lt;/code&gt; de Node.js lleva a cabo conexiones a la BBDD empleando &lt;em&gt;callback&lt;/em&gt; para obtener los datos de las consultas SQL y no permite, por defecto, el uso de async/await. Al abrir la conexión, el resultado de estas consultas permanecerá dentro de la función &lt;em&gt;callback&lt;/em&gt;. En este artículo mostraré cómo convertir conexiones MySQL de Node.js en promesas que permitan el uso de async/await, pudiendo así extraer de la función el resultado de la consulta.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Esta entrada es un ejercicio sin un sentido práctico específico en el que se hace uso del módulo mysql de Node.js. Para producción se recomienda el uso de mysql2, que incluye soporte para promesas, o el uso de un ORM como Sequelize.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Poder obtener los datos de la consulta SQL, en el flujo de nuestro programa, nos facilita la tarea de observar buenas prácticas que permitan separar las rutas de los controladores y los servicios. Con un módulo de conexión podemos realizar las consultas desde los servicios, y estos a su vez devolver el resultado al controlador que fue llamado desde la ruta.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;txt&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── controllers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── searchControllers.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── modules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   ├── connection.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── utils.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── routes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── searchRoutes.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── services&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   └── searchServices.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── index.js&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pongamos que llega una consulta a la ruta de nuestra API que es gestionada por &lt;code&gt;searchRoutes.js&lt;/code&gt;, esta emplea una función del controlador que importa de &lt;code&gt;searchControllers.js&lt;/code&gt; que procesa la consulta, y que a su vez llama a una función del servicio &lt;code&gt;searchServices.js&lt;/code&gt; que se encarga de hacer la petición SQL a la BBDD.&lt;/p&gt;
&lt;p&gt;Dado que todas las peticiones a la BBDD son análogas (abrir conexión, hacer petición, devolver resultado) he creado una función llamada &lt;code&gt;getMysqlDbList()&lt;/code&gt; que he colocado en un módulo llamado &lt;code&gt;utils.js&lt;/code&gt; que importo y uso en &lt;code&gt;searchServices.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;La función &lt;code&gt;getMysqlDbList()&lt;/code&gt; se encargará de hacer la conexión a la base de datos, realizar la consulta y cerrar la conexión, apoyándose en el módulo &lt;code&gt;connection.js&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;un-ejemplo&quot;&gt;Un ejemplo&lt;/h1&gt;
&lt;p&gt;Pongamos que tenemos un frontal desde el que queremos obtener todos los productos de la BBDD. Veamos ejemplos de cada uno de los ficheros mencionados sin tener mucho en cuenta en este caso las pertinentes comprobaciones de los datos recibidos para simplificar el código.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;searchRoutes.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; express&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;express&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; router&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; express.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Router&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; getAllProducts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../controllers/searchControllers&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;router.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, getAllProducts);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; router;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por supuesto, este módulo será importado en &lt;code&gt;index.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;searchControllers.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; searchServices&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../services/searchServices&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getAllProducts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;req&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; products&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; searchServices.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getAllProducts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    res.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(products);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; getAllProducts;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;searchServices.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;getMysqlDbList&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../modules/utils&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getAllProducts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;SELECT * FROM products&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getMysqlDbList&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { getAllProducts };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;la-consulta&quot;&gt;La consulta&lt;/h2&gt;
&lt;p&gt;Para que esta línea &lt;code&gt;return getMysqlDbList(request);&lt;/code&gt; en &lt;code&gt;searchServices.js&lt;/code&gt; funcione, la función &lt;code&gt;getMysqlDbList()&lt;/code&gt; en &lt;code&gt;utils.js&lt;/code&gt; debe devolver el resultado de la consulta. El código debería ser algo como esto:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;utils.js&lt;/code&gt; (no lo usaremos de esta forma)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; client&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../modules/connection&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getMysqlDbList&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; list&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; client.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El problema es que la consultas a mysql en Node.js no soportan async/await. Una conexión mysql entonces tendría esta forma, empleando una función &lt;em&gt;callback&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;utils.js&lt;/code&gt; (no lo usaremos de esta forma)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; connection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;../modules/connection&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getMysqlDbList&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    connection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;results&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;fields&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (error) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        results.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, &lt;code&gt;results&lt;/code&gt; está dentro de la función &lt;em&gt;callback&lt;/em&gt; que obtiene los datos de la consulta y desde dentro de esta función no puedo hacer un &lt;code&gt;return&lt;/code&gt; para devolver los productos como resultado de la función &lt;code&gt;getMysqlDbList()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;la-conexión&quot;&gt;La conexión&lt;/h2&gt;
&lt;p&gt;Una conexión típica a la BBDD, cuyo código estaría en &lt;code&gt;connection.js&lt;/code&gt;, podría ser:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;connection.js&lt;/code&gt; (no lo usaremos de esta forma)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mysql&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; connection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mysql.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createConnection&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    host : process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    database : process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    user : process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_USERNAME&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    password : process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    port : process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PORT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;connection.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;connect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;err&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Error de conexión: &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; err.stack);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Conectado con el identificador &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; connection.threadId);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; connection;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A continuación mostraré los cambios que sufrirá este fichero.&lt;/p&gt;
&lt;h1 id=&quot;promisificación&quot;&gt;Promisificación&lt;/h1&gt;
&lt;p&gt;Node.js tiene un módulo &lt;code&gt;util&lt;/code&gt; con algunas funciones, entre ellas &lt;code&gt;promisify()&lt;/code&gt; que permite la conversión de una función que acepta un &lt;em&gt;callback&lt;/em&gt; a una función que devuelve una promesa. A este cambio se le conoce con el aparatoso y extraño nombre de &lt;code&gt;Promisificación&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Con esta función podemos convertir nuestra consulta a la base de datos basada en &lt;em&gt;callback&lt;/em&gt; a una promesa que puede usar async/await para devolver la info resultante de la consulta, pero esto no está exento de inconvenientes. Como necesito cerrar la conexión tras la consulta SQL, lo que haré es crear una función en &lt;code&gt;connection.js&lt;/code&gt; que exportaré junto con los datos de conexión para ser usados por &lt;code&gt;getMysqlDbList()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;connection.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; util&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;util&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;mysql&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;production&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;dotenv&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    host: process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    database: process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    user: process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_USERNAME&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    password: process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PASSWORD&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    port: process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DB_PORT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; makeDb&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; connection&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mysql.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;createConnection&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(config);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        query&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sql&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; util.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;promisify&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(connection.query)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(connection, sql, args);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; util.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;promisify&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(connection.end).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(connection);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;exports&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {config, makeDb};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, importo el módulo &lt;code&gt;util&lt;/code&gt; del que utilizaré su función &lt;code&gt;promisify()&lt;/code&gt;. Nótese que este &lt;code&gt;util&lt;/code&gt; no se refiere a mi módulo &lt;code&gt;utils.js&lt;/code&gt; en la carpeta &lt;code&gt;modules&lt;/code&gt;, sino al módulo por defecto de Node.js.&lt;/p&gt;
&lt;p&gt;Defino los datos de configuración en un objeto, y creo una función &lt;code&gt;makeDb()&lt;/code&gt; que recibe como parámetro la configuración para establecer la conexión (&lt;code&gt;mysql.createConnection(config)&lt;/code&gt;) y que devuelve mediante &lt;em&gt;return&lt;/em&gt; dos funciones en un objeto: &lt;code&gt;query()&lt;/code&gt; y &lt;code&gt;close()&lt;/code&gt;. Con &lt;code&gt;.call()&lt;/code&gt; indico los parámetros de la función que va a ser convertida en promesa.&lt;/p&gt;
&lt;p&gt;Con la exportación de &lt;code&gt;config&lt;/code&gt; y &lt;code&gt;makeDb()&lt;/code&gt; tengo lo necesario para realizar una consulta a la BBDD desde &lt;code&gt;getMysqlDbList()&lt;/code&gt; en &lt;code&gt;utils.js&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;la-función-getmysqldblist&quot;&gt;La función getMysqlDbList()&lt;/h1&gt;
&lt;p&gt;{: .box-warning}
&lt;strong&gt;Advertencia:&lt;/strong&gt; En líneas generales no es buena idea conectar y desconectar a la BBDD en cada &lt;em&gt;request&lt;/em&gt; ya que se introduce esa latencia en cada solicitud, por tanto esta es una solución que puede y debe ser mejorada en el futuro.&lt;/p&gt;
&lt;p&gt;El siguiente código muestra cómo ha quedado la función &lt;code&gt;getMysqlDbList()&lt;/code&gt; dentro del fichero &lt;code&gt;utils.js&lt;/code&gt; definitivo (Obviar los anteriores ejemplos de utils.js):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;utils.js&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;makeDb&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; require&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;./connection&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; * Obtiene un listado de la BBDD MySQL mediante consulta SQL.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; * &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@param&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; {String}&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; request&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; * &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; Object&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getMysqlDbList&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; db&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; makeDb&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(config);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        list &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(request);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (err) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;finally&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; db.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;close&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importo &lt;code&gt;config&lt;/code&gt; y &lt;code&gt;makeDb()&lt;/code&gt; para poder establecer la conexión a la BBDD mediante: &lt;code&gt;const db = makeDb(config);&lt;/code&gt;. Al llamar a &lt;code&gt;makeDb()&lt;/code&gt; pasándole el parámetro &lt;code&gt;config&lt;/code&gt; se inicia la conexión a la BBDD, y en &lt;code&gt;db&lt;/code&gt; se guarda el objeto con las funciones &lt;code&gt;query()&lt;/code&gt; y &lt;code&gt;close()&lt;/code&gt; que uso a continuación.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;list = await db.query(request);&lt;/code&gt; realizo la consulta a la BBDD. Por supuesto &lt;code&gt;request&lt;/code&gt; es un parámetro que nos llega desde el servicio en &lt;code&gt;searchServices.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Por último, con &lt;code&gt;await db.close()&lt;/code&gt; cierro la conexión a la BBDD.&lt;/p&gt;
&lt;p&gt;Ahora, con &lt;code&gt;return list&lt;/code&gt; puedo devolver el resultado obtenido de la BBDD al servicio;&lt;/p&gt;
&lt;h1 id=&quot;resumiendo&quot;&gt;Resumiendo&lt;/h1&gt;
&lt;p&gt;Al hacer una petición a la ruta de nuestra API, esta llama a una función en el controlador encargada de procesar los datos recibidos en la petición que a su vez llama a una función en el servicio encargado de hacer la consulta a la BBDD.&lt;/p&gt;
&lt;p&gt;La función del servicio llama a una función en el fichero utils.js que se ocupa de establecer la conexión, realizar la consulta a la BBDD y cerrar la conexión. Esta función se externaliza porque, generalmente, su funcionalidad es la misma para cada consulta a la BBDD en cada servicio, cambiando sólo la consulta SQL a realizar.&lt;/p&gt;
&lt;p&gt;Para poder ejecutar esta función en el fichero utils.js se requiere del módulo de conexión que exporta tanto los datos de conexión como una función que permite realizar la conexión a la BBDD, la consulta y el cierre de la conexión, de tal forma que pueda usarse con async/await.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Página de la que he obtenido la pista para resolver esta cuestión &lt;a href=&quot;https://codeburst.io/node-js-mysql-and-async-await-6fb25b01b628&quot;&gt;Node.js, MySQL and async/await&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La función util.promisify() en Node.js &lt;a href=&quot;https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original&quot;&gt;util.promisify()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Usando el método .call &lt;a href=&quot;https://dev.to/imsergiobernal/para-que-sirven-los-metodos-call-y-apply-en-javascript-4bj2&quot;&gt;¿Para qué sirven los métodos .call() y .apply() en JavaScript?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Libreria alternativa que incluye promesas (Aportada por borja) &lt;a href=&quot;https://www.npmjs.com/package/mysql2&quot;&gt;Node MySQL 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ORM: &lt;a href=&quot;https://sequelize.org/&quot;&gt;Sequelize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ejemplo de uso de pool de conexiones mysql, aportado por Jose, de «Desarrollo útil». &lt;a href=&quot;https://github.com/bezkoder/nodejs-express-mysql&quot;&gt;Node.js Rest APIs with Express &amp;amp; MySQL example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/mysql.CIjIICAX_2rcnGP.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>mysql</category><category>bbdd</category><author>JavGuerra</author></item><item><title>Usando populate con paginate y filtrando los resultados</title><link>https://javguerra.github.io/blog/populate-paginate-fitrado</link><guid isPermaLink="true">https://javguerra.github.io/blog/populate-paginate-fitrado</guid><description>Cómo relacionar colecciones cuando se usa mongoose-paginate-v2</description><pubDate>Sat, 29 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/mongoose.yK9gFAu8_Z1xJtaI.webp&quot; alt=&quot;mongoose-paginate-v2&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#mongodb&lt;/em&gt;, &lt;em&gt;#mongoose&lt;/em&gt;, &lt;em&gt;#paginate&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Si bien mongodb tiene formas de obtener resultados paginados (limit, skip), el módulo mongoose-paginate-v2 de mongoose nos ahorra tiempo y código a la hora de preparar y usar los datos paginados obtenidos de las búsquedas en nuestras bases de datos, devolviendo información complementaria muy cómoda, pero ¿cómo podemos usar la paginación cuando tenemos relaciones entre colecciones? En esta entrada explicaré cómo paginar resultados agregados entre colecciones como si usásemos aggregate en mongodb o populate en mongoose, y además cómo filtrar búsquedas agregadas y paginadas con este módulo.&lt;/p&gt;
&lt;h1 id=&quot;el-ejemplo&quot;&gt;El ejemplo&lt;/h1&gt;
&lt;p&gt;Imaginemos que tenemos dos colecciones en una BBDD mongodb, una de &lt;code&gt;libros&lt;/code&gt; y otra de &lt;code&gt;autores&lt;/code&gt;, y un dato en cada documento de la colección libros llamado &lt;code&gt;autor&lt;/code&gt; que sirve para contener la información agregada del autor en la colección libros. En el &lt;em&gt;schema&lt;/em&gt;, el dato &lt;code&gt;autor&lt;/code&gt; podría tener esta forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    autor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: Schema.Types.ObjectId, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Autor&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        nombre&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La propiedad &lt;code&gt;ref&lt;/code&gt; es la que «tenderá el puente» entre ambas colecciones, y contendrá el &lt;code&gt;_id&lt;/code&gt; del documento a relacionar de la colección &lt;code&gt;autores&lt;/code&gt;. La propiedad &lt;code&gt;nombre&lt;/code&gt; contendrá, como se espera, el nombre del autor. Si bien este dato estará también en la colección &lt;code&gt;autores&lt;/code&gt;, y puede ser redundante cuando agregamos los resultados, el dato tiene su utilidad, pues nos permite realizar el filtrado de libros por autor incluso sin realizar la agregación.&lt;/p&gt;
&lt;p&gt;Una búsqueda haciendo uso de populate tendría esta forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Libro.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( filtro ).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;populate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;autor.ref&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;exec&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;donde &lt;code&gt;filtro&lt;/code&gt; es un objeto que contendrá los criterios de búsqueda, y &lt;code&gt;autor.ref&lt;/code&gt; es la necesaria referencia para poder llevar a cabo la agregación de datos de la colección &lt;code&gt;autores&lt;/code&gt; en &lt;code&gt;libros&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si queremos emplear el módulo &lt;code&gt;mongoose-paginate-v2&lt;/code&gt; para paginar los resultados de la búsqueda, esta quedaría de la siguiente forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Libro.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;paginate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(filtro, { page, limit });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;donde &lt;code&gt;page&lt;/code&gt; indica la página de resultados a obtener y &lt;code&gt;limit&lt;/code&gt; el número de resultados por página.&lt;/p&gt;
&lt;p&gt;Pero sólo nos devolverá los datos de la colección &lt;code&gt;autores&lt;/code&gt;, sin agregar los datos de la colección &lt;code&gt;libros&lt;/code&gt;. ¿Cómo se haría esto?&lt;/p&gt;
&lt;h1 id=&quot;agregando-y-paginando&quot;&gt;Agregando y paginando&lt;/h1&gt;
&lt;p&gt;Hemos visto que paginate acepta dos parámetros, los criterios de búsqueda (filtro) y las opciones (page, limit). Otra opción que podemos añadir a paginate es &lt;code&gt;populate&lt;/code&gt;. Para hacer una búsqueda agregada como la del ejemplo, usaríamos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Libro.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;paginate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(filtro, { page, limit, populate: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;autor.ref&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;de esta forma podemos obtener un resultado con la información de ambas colecciones.&lt;/p&gt;
&lt;p&gt;La opción populate permite también otras opciones. Imaginemos que en la agregación queremos obviar el dato &lt;code&gt;nombre&lt;/code&gt; de la colección &lt;code&gt;autores&lt;/code&gt; que ya tenemos en la colección &lt;code&gt;libros&lt;/code&gt;. Podemos pasarle a &lt;code&gt;populate&lt;/code&gt; un objeto de la siguiente forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Libro.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;paginate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(filtro, { page, limit, populate: {path: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;autor.ref&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, select: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;-nombre&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos; })&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;donde &lt;code&gt;select: &apos;-nombre&apos;&lt;/code&gt;, que va con un signo menos (-) delante, indica que ese dato no será requerido. Véase también que, para incluir la referencia a la colección, dentro del objeto se usa &lt;code&gt;path: &apos;autor.ref&apos;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Puedes obtener más información sobre las &lt;a href=&quot;https://mongoosejs.com/docs/api.html#query_Query-populate&quot;&gt;opciones de populate&lt;/a&gt; en el manual on-line.&lt;/p&gt;
&lt;h1 id=&quot;filtrando&quot;&gt;Filtrando&lt;/h1&gt;
&lt;p&gt;Decía más arriba que nos puede interesar hacer un filtrado en la búsqueda sobre nuestra base de datos por el nombre del autor, que es un dato dentro de otro dato, pero antes recordaré cómo buscar por uno o varios datos de la colección.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; filtro&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (titulo) filtro.titulo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { $regex: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`.*${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;titulo&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}.*`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (precio) filtro.precio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { $lte: precio };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este código creará un objeto &lt;code&gt;filtro&lt;/code&gt; que permitirá que busquemos en la colección &lt;code&gt;libros&lt;/code&gt; por título y precio, ya que, si estos datos de búsqueda existen, con &lt;code&gt;filtro.titulo&lt;/code&gt; y &lt;code&gt;filtro.precio&lt;/code&gt; añadimos ambas propiedades al objeto filtro que usaremos en la búsqueda de la forma en que hemos visto en todos los ejemplos anteriores. (Nota: entiéndase que podríamos tener libros con el mismo título y distinto precio según la editorial o la colección editorial).&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;{ $regex: `.*${titulo}.*/` }&lt;/code&gt; buscamos por la expresión regular dada, en cambio con &lt;code&gt;$lte: precio&lt;/code&gt; buscamos por un valor igual o menor al proporcionado. Ver más información sobre &lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/operator/&quot;&gt;operadores de búsqueda en mongodb&lt;/a&gt; en el manual on-line.&lt;/p&gt;
&lt;p&gt;Esto permitirá que:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;Libro.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;paginate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(filtro, { page, limit, populate: {path: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;autor.ref&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, select: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;-nombre&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos; })&lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;devuelva aquellos documentos de la colección &lt;code&gt;libros&lt;/code&gt; que tengan coincidencias con el &lt;code&gt;filtro&lt;/code&gt; indicado, es decir, que contengan en el título el texto &lt;code&gt;titulo&lt;/code&gt; indicado y cuyo precio sea igual o menor al &lt;code&gt;precio&lt;/code&gt; indicado.&lt;/p&gt;
&lt;h2 id=&quot;consulta-sobre-datos-anidados&quot;&gt;Consulta sobre datos anidados&lt;/h2&gt;
&lt;p&gt;Teniendo claro lo anterior, acceder al dato &lt;code&gt;nombre&lt;/code&gt; dentro de &lt;code&gt;autor&lt;/code&gt; no es complicado, pero para referenciar el dato tendremos que usar lo siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; filtro&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (nombre) filtro[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;autor.nombre&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { $regex: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`.*${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nombre&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}.*`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; };&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uso aquí los corchetes &lt;code&gt;[]&lt;/code&gt; porque para poder usar el filtro en mongodb debo pasarle la propiedad al objeto filtro de esta forma: &lt;code&gt;{ &quot;autor.nombre&quot; : { $regex: `.*${nombre}.*` } }&lt;/code&gt; como se indica en la sección &lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/query-embedded-documents/&quot;&gt;consulta sobre documentos incrustados/anidados&lt;/a&gt; del manual online.&lt;/p&gt;
&lt;p&gt;Este filtro devolverá aquellos documentos de la colección &lt;code&gt;libros&lt;/code&gt; que, dentro del dato &lt;code&gt;autor&lt;/code&gt;, contengan el nombre dado dentro del dato anidado &lt;code&gt;nombre&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/mongoose-paginate-v2&quot;&gt;mongoose-paginate-v2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mongoosejs.com/docs/api.html#query_Query-populate&quot;&gt;Opciones de populate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mongodb.com/docs/manual/reference/operator/&quot;&gt;Operadores de búsqueda en mongodb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mongodb.com/docs/manual/tutorial/query-embedded-documents/&quot;&gt;Consulta sobre documentos incrustados/anidados&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/mongoose.yK9gFAu8_Z1xJtaI.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>mongodb</category><category>mongoose</category><category>paginate</category><author>JavGuerra</author></item><item><title>Generar enlaces dinámicos de imágenes almacenadas en MongoDB</title><link>https://javguerra.github.io/blog/rutas-dinamicas-imagenes-mongodb</link><guid isPermaLink="true">https://javguerra.github.io/blog/rutas-dinamicas-imagenes-mongodb</guid><description>Conseguir que nuestros datos no dependan de una ubicación estática</description><pubDate>Sun, 06 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/dynamic_links.BDCzFkfb_1Co5pD.webp&quot; alt=&quot;Enlaces dinámicos&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#mongodb&lt;/em&gt;, &lt;em&gt;#imágenes&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Las bases de datos a menudo contienen referencias a recursos que no son almacenados en su misma estructura. Un claro ejemplo de ello son las fotografías o imágenes que acompañan a los productos de un catálogo. En tal caso, guardar la información es sencillo, es suficiente con almacenar la ruta completa al recurso en un campo de tipo &lt;em&gt;String&lt;/em&gt;, pero, ¿que ocurre si, presumiblemente, nuestros datos van a cambiar de ubicación, o van a correr en distintas instancias o en diferentes hospedajes? En ese caso, lo recomendable es almacenar la información del nombre del recurso en la BBDD, y entonces tendremos dos alternativas para generar el enlace completo: modificar los datos de la BBDD mediante un &lt;em&gt;script&lt;/em&gt; para que la url al recurso sea la adecuada cada vez que cambiamos de ubicación los datos, o bien generar la ruta al recurso de forma dinámica, al vuelo, cuando se realizan las consultas. Vamos a ver aquí la segunda.&lt;/p&gt;
&lt;h1 id=&quot;el-ejemplo&quot;&gt;El ejemplo&lt;/h1&gt;
&lt;p&gt;Partimos de la siguiente premisa. En las variables globales del sistema tenemos almacenadas la ruta y el puerto del servidor donde están ubicadas las imágenes, que es la información susceptible de cambiar de lugar. Tal vez estos datos estén disponibles mediante &lt;a href=&quot;https://www.npmjs.com/package/dotenv&quot;&gt;dotenv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tomemos como referencia el ejemplo de la &lt;a href=&quot;/blog/populate-paginate-fitrado&quot;&gt;entrada anterior&lt;/a&gt;. Dos colecciones relacionadas, &lt;code&gt;libros&lt;/code&gt; y &lt;code&gt;autores&lt;/code&gt;, y en las que queremos incluir un dato en cada documento de la colección libros con la foto de portada del libro, y un dato con la foto del autor en cada documento de la colección autores. Algo como:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;libro&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    portada&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;don-quijote.png&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;autor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    foto&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;cervantes.jpg&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;obviamente, tanto la colección libros como la conección autores tendrán otros datos, no sólo la portada o la foto.&lt;/p&gt;
&lt;h1 id=&quot;la-ruta&quot;&gt;La ruta&lt;/h1&gt;
&lt;p&gt;Para poder acceder a la portada del libro, necesitamos completar la ruta a la imagen. En este ejemplo usaremos el dominio &lt;code&gt;lalibreria2022.com&lt;/code&gt; al que se accede por el porto &lt;code&gt;80&lt;/code&gt;. Esta información la tenemos almacenada en un fichero &lt;code&gt;.env&lt;/code&gt; de nuestra aplicación de la siguiente forma:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;HOST=&apos;https://lalibreria2022.com&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;PORT=80&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Y asumo que las portadas se almacenan en una carpeta llamada &lt;code&gt;portadas&lt;/code&gt;, y las fotos en otra llamada &lt;code&gt;fotos&lt;/code&gt;.
De esta forma, para acceder a la imagen &lt;code&gt;don-quijote.png&lt;/code&gt; debemos completar la siguiente ruta:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;HOST + &apos;:&apos; + PORT + &apos;/&apos; + &apos;portadas&apos; + &apos;/&apos; + &apos;don-quijote.png&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;y obtendríamos:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://lalibreria2022.com:80/portadas/don-quijote.png&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;alterando-los-resultados&quot;&gt;Alterando los resultados&lt;/h1&gt;
&lt;p&gt;Cuando llevamos a cabo las búsquedas de información sobre la BBDD, esta nos devolverá, como ya sabemos, el nombre del recurso (‘don-quijote.png’), pero queremos que la BBDD devuelva dinámicamente la ruta antes mencionada. Para ello hay que recorrer el resultado obtenido y hacer cambios sobre los datos. Un &lt;code&gt;forEach()&lt;/code&gt; es suficiente.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; insertarRutas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; datos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HOST&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;:&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;/&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    datos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;( &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;elemento&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elemento.portada &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; url &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;portadas/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elemento.portada );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tras cada búsqueda, aplicando esta función al resultado, recorro todos los documentos de la colección (&lt;code&gt;datos&lt;/code&gt;) y cambio el valor del dato &lt;code&gt;portada&lt;/code&gt; en cada documento.&lt;/p&gt;
&lt;h1 id=&quot;también-con-resultados-agregados&quot;&gt;También con resultados agregados&lt;/h1&gt;
&lt;p&gt;Cuando llevamos a cabo consultas agregadas, el proceso es similar. En una consulta donde obtenemos los libros y las referencias a sus respectivos autores, debemos repetir el proceso también para el dato &lt;code&gt;foto&lt;/code&gt; de la colección &lt;code&gt;autores&lt;/code&gt;, pero hay que tener en cuenta lo siguiente:&lt;/p&gt;
&lt;p&gt;{: .box-note}
&lt;strong&gt;Nota:&lt;/strong&gt; Cuando recorremos una colección agregada lo hacemos sobre una colección y sobre referencias a otra colección, es decir, si hay varios libros de un mismo autor, aunque los datos del autor se muestren en varios libros agregados, solo están almacenados una vez.&lt;/p&gt;
&lt;p&gt;Esto tiene importancia porque, al realizar el cambio de la ruta de la foto del autor, estaríamos cambiándola tantas veces como libros existan, y generando entonces una url errónea con rutas repetidas. Si tenemos dos libros de Cervantes, la ruta a la foto podría verse así:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://lalibreria2022.com:80/fotos/https://lalibreria2022.com:80/fotos/cervantes.jpg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para evitar esto, debemos implementar el siguiente código, en el que se incluyen ambos casos, el de la portada del libro y el de la foto del autor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; insertarRutas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt; datos&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HOST&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;:&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process.env.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PORT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;/&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    datos.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;elemento&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        elemento.portada &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; url &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;portadas/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elemento.portada;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elemento.autor.ref.foto.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(url)) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;             elemento.autor.ref.foto &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; url &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;fotos/&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; elemento.autor.ref.foto;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con el condicional (&lt;code&gt;if&lt;/code&gt;) me aseguro de que la foto no contiene ya la ruta completa, y si no es así, la completa.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/populate-paginate-fitrado&quot;&gt;Usando populate con paginate y filtrando los resultados&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/dynamic_links.BDCzFkfb_1Co5pD.webp"/><category>código</category><category>javascript</category><category>node.js</category><category>mongodb</category><category>imágenes</category><author>JavGuerra</author></item><item><title>Ordenando resultados en React</title><link>https://javguerra.github.io/blog/ordenacion-react</link><guid isPermaLink="true">https://javguerra.github.io/blog/ordenacion-react</guid><description>Filtrando el listado de información por distintos criterios y mostrándolo en orden creciente o decreciente.</description><pubDate>Wed, 23 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/dalton.uMLTtW5b_zpaNY.webp&quot; alt=&quot;Ordenación&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#react&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Cuando mostramos un listado con muchos resultados en nuestra web sin un criterio de ordenación, el usuario debe encontrar la información que necesita, lo que requiere tiempo y esfuerzo por su parte. Para atajar este problema podemos incluir un campo de búsqueda, pero aún así, la información aparecerá desordenada. En esta entrada veremos como seleccionar la ordenación de listados de menor a mayor y viceversa, y cómo hacerlo por varios criterios de ordenación alternativamente en nuestra aplicación React.&lt;/p&gt;
&lt;p&gt;El lector deberá conocer el funcionamiento básico de React y JavaScript para poder seguir adecuadamente esta entrada.&lt;/p&gt;
&lt;p&gt;Esta entrada está basada en el proyecto &lt;a href=&quot;/blog/tienda-8-bits&quot;&gt;«Tienda 8 bits»&lt;/a&gt;, y puedes ver su funcionamiento en la &lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;página del proyecto&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Este artículo ha sido publicado también en &lt;a href=&quot;https://ifgeekthen.nttdata.com/s/post/ordenando-resultados-en-react-MCYT76DWYR2JEVBLOOQWIOAIXD7Q&quot;&gt;IfGeekThen&lt;/a&gt;, el blog de NTT Data, el 15 de abril de 2026.&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;el-ejemplo&quot;&gt;El ejemplo&lt;/h1&gt;
&lt;p&gt;En nuestra web, queremos listar una serie de fichas de productos por tres criterios, &lt;strong&gt;modelo de producto&lt;/strong&gt;, &lt;strong&gt;precio&lt;/strong&gt; y &lt;strong&gt;año de fabricación&lt;/strong&gt;, y queremos hacerlo alternativamente, es decir, por uno de entre esos tres criterios de ordenación cada vez.&lt;/p&gt;
&lt;p&gt;La ordenación se hará de menor a mayor, osea, en orden ascendente, y de mayor a menor, en orden descendente. Tomaremos la información de las fichas desde, por ejemplo, una API que debe estar preparada para ello, es decir, que la API pueda devolver los datos solicitados según los parámetros de ordenación necesarios. Pero no me pararé a mostrarlo en esta entrada.&lt;/p&gt;
&lt;p&gt;Los filtros, en la página, tendrán un aspecto parecido a lo que se ve en la imagen:&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Filtros&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/filtros.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;En este caso, el primer filtro de ordenación, el de modelo, es el que está seleccionado, y la ordenación la realiza en orden ascendente. Los otros dos filtros no están activos.&lt;/p&gt;
&lt;h1 id=&quot;la-aplicación&quot;&gt;La aplicación&lt;/h1&gt;
&lt;p&gt;Para este ejercicio, en la página App.jsx o la que usemos para llamar a la ordenación, voy a definir dos &lt;code&gt;useState&lt;/code&gt;, uno que contendrá los filtros de ordenación en un objeto y otro que contendrá el número de la página actual de los resultados paginados (grupos de resultados) que vamos a mostrar.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; useState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ sortmodel: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;currentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; useState&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En una aplicación completa deberemos incluir otros useState para, por ejemplo, guardar los datos obtenidos de la consulta a la API, o los criterios de búsqueda de datos… En este ejercicio me limito a incluir sólo los que son operativos para la explicación.&lt;/p&gt;
&lt;p&gt;Dentro del objeto que tendremos en &lt;code&gt;sortData&lt;/code&gt; iremos incluyendo, alternativamente, &lt;code&gt;sortmodel&lt;/code&gt; para filtrar por el modelo, &lt;code&gt;sortprice&lt;/code&gt; para filtrar por el precio, o &lt;code&gt;sortyear&lt;/code&gt; para filtrar por el año. Sólo uno de ellos a la vez. Los valores posibles para cada una de estas propiedades de filtrado serán &lt;code&gt;1&lt;/code&gt; y &lt;code&gt;-1&lt;/code&gt;, siendo 1 el valor que indica ordenación ascendente, y -1 el valor que indica ordenación descendente, que son los valores que acepta nuestra API. Inicalizamos el &lt;code&gt;useState&lt;/code&gt;  &lt;code&gt;sortData&lt;/code&gt; con &lt;code&gt;{ sortmodel: 1 }&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;useEffect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortmodel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortprice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortyear&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sortData;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Preparar los datos para la consulta a la API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Realizar la consulta a la API y obtener (set) los resultados&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, [sortData, currentPage]);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cuando el objeto almacenado en &lt;code&gt;sortData&lt;/code&gt; cambie por la interacción del usuario, al seleccionar mediante un clic otro criterio de ordenación, entrará en juego la función &lt;code&gt;setSortData&lt;/code&gt;, y el contenido dentro de &lt;code&gt;useEffect&lt;/code&gt; se ejecutará, pasando los datos de filtrado &lt;code&gt;sortData&lt;/code&gt; a la petición a la API mediante fetch, axios… Los datos deben ser preparados antes de hacer la consulta, y para ello, deberemos comprobar cual de los tres filtros (sortmodel, sortprice, sortyear) está seleccionado y cuales no (&lt;em&gt;undefined&lt;/em&gt;), e incluir el filtro indicado en la consulta.&lt;/p&gt;
&lt;p&gt;El componente que va a permitir seleccionar el tipo de ordenación se llama &lt;code&gt;Sort&lt;/code&gt;, y esta sería la llamada para renderizarlo en la página:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Sort&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        sortData&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortData}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        setSortData&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{setSortData}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{setCurrentPage}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por &lt;em&gt;props&lt;/em&gt; le hacemos llegar al componente Sort los datos de filtrado (sortData), la función que establece (set) el filtrado (setSortData) y la función que establece la página actual (setCurrentPage). setCurrentPage es necesario porque cada vez que cambie el filtrado deberemos establecer la página 1 como la página actual, de otra forma los datos obtenidos con el nuevo filtrado se mostrarían confusos para el usuario.&lt;/p&gt;
&lt;h2 id=&quot;el-componente-sort&quot;&gt;El componente Sort&lt;/h2&gt;
&lt;p&gt;El código del componente será el siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SortIcon &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;./SortIcon&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Sort&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortmodel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortprice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;sortyear&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sortData;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ [sortName]: order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortmodel&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortmodel)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Modelo &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortmodel} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortprice&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortprice)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Precio &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortprice} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;sortyear&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, sortyear)}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Año &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SortIcon&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{sortyear} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;ul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Sort;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Primeramente importo el componente &lt;code&gt;SortIcon&lt;/code&gt; que luego veremos. Éste componente se encargará de mostrar los iconos de ordenación de cada uno de los tres criterios por los que vamos a ordenar el listado.&lt;/p&gt;
&lt;p&gt;Como dije, el componente &lt;code&gt;Sort&lt;/code&gt; recibe por &lt;code&gt;props&lt;/code&gt; tres parámetros &lt;code&gt;{sortData, setSortData, setCurrentPage}&lt;/code&gt; con el dato del tipo de ordenación elegido, la función para fijar la nueva ordenación y la función para fijar la página actual de la paginación de resultados.&lt;/p&gt;
&lt;p&gt;Lo primero que hago es obtener los datos del objeto &lt;code&gt;sortData&lt;/code&gt; recibido por props. Por supuesto, sólo uno de los tres datos va a llegar con un valor. Los otros dos, que no son el criterio de filtrado seleccionado, tendrán valor &lt;em&gt;undefined&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La función &lt;code&gt;handleIcon&lt;/code&gt; será la encargada de efectuar el cambio del filtro de ordenación. Y a cada &lt;code&gt;sortIcon&lt;/code&gt;, en el renderizado, le paso el valor de &lt;code&gt;order&lt;/code&gt;, que contiene el valor de ordenación del filtrado (1 ó -1) que le corresponde.&lt;/p&gt;
&lt;p&gt;Al hacer click en cualquiera de los tres criterios de ordenación en la página, la función &lt;code&gt;handleIcon&lt;/code&gt; dentro de &lt;code&gt;onClick={() =&amp;gt; handleIcon(&quot;nombre_del_filtro&quot;, variable_de_ordenación)}&lt;/code&gt; se ejecuta, con los parámetros &lt;code&gt;&quot;nombre_del_filtro&quot;&lt;/code&gt; y &lt;code&gt;variable_de_ordenación&lt;/code&gt;, lo que permite hacer el cambio en la ordenación, disparando el &lt;code&gt;useEffect&lt;/code&gt; de nuestra aplicación que vimos antes, provocando que los productos listados se actualicen con la nueva ordenación mediante una nueva consulta a la API.&lt;/p&gt;
&lt;h2 id=&quot;la-función-handleicon&quot;&gt;La función handleIcon&lt;/h2&gt;
&lt;p&gt;Aquí es donde se lleva a cabo el cambio de filtrado.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; handleIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sortName&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setSortData&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({ [sortName]: order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    setCurrentPage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La función recibe dos parámetros, &lt;code&gt;sortName&lt;/code&gt;, con el nombre del filtro seleccionado en función del icono (SortIcon) en el que se haga clic, y &lt;code&gt;order&lt;/code&gt;, con el valor de ordenación de ese filtro (1 ó -1).&lt;/p&gt;
&lt;p&gt;Con la función &lt;code&gt;setSortData&lt;/code&gt;, que recibí por props, voy a fijar el criterio de ordenación y su valor.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;[sortName]:&lt;/code&gt; dentro del objeto que voy a pasar a &lt;code&gt;setSortData&lt;/code&gt; para cambiar &lt;code&gt;sortData&lt;/code&gt; indico que la propiedad se tiene que llamar como el nombre del filtro recibido en &lt;code&gt;sortName&lt;/code&gt; (que puede ser uno de estos tres: “sortmodel”, “sortprice” o “sortyear”). Con los corchetes consigo que el texto recibido sea el nombre de la propiedad.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;order ? -order : 1&lt;/code&gt; determino el valor de la propiedad del objeto que voy a pasar a &lt;code&gt;setSortData&lt;/code&gt;. Si el valor de order existe, es decir no es &lt;code&gt;undefined&lt;/code&gt;, y por tanto es el criterio de ordenación actual, su valor ahora será el valor alternativo (positivo o negativo) al que ya tiene. Si el valor era 1, ahora será -1. Si era -1, pasará a ser 1. Y en caso de que el valor de &lt;code&gt;order&lt;/code&gt; fuera &lt;code&gt;undefined&lt;/code&gt;, es decir, que no fuese este el filtro por el que estábamos filtrando antes, se establece su valor a 1.&lt;/p&gt;
&lt;p&gt;Como cada vez que empleo &lt;code&gt;setSortData&lt;/code&gt; defino sólo un filtro de ordenación, el resto de filtros tendrá un valor &lt;code&gt;undefined&lt;/code&gt; cuando se renderizen en el componente &lt;code&gt;Sort&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Con &lt;code&gt;setCurrentPage(1)&lt;/code&gt; fijo la página de la paginación de resultados a 1.&lt;/p&gt;
&lt;p&gt;Con esta simple función puedo entonces, como dije, seleccionar el filtrado entre uno de los tres filtros posibles, y establecer el criterio de ordenación (ascendente o descendente) del filtro seleccionado.&lt;/p&gt;
&lt;h2 id=&quot;el-componente-sorticon&quot;&gt;El componente SortIcon&lt;/h2&gt;
&lt;p&gt;Este componente es el encargado de mostrar el icono de estado de cada uno de los tres criterios de ordenación en la página.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; SortIcon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ({&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;order&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; order &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0l-3.75-3.75M17.25 21L21 17.25&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; xmlns&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;http://www.w3.org/2000/svg&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; className&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      viewBox&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0 0 24 24&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeWidth&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stroke&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;currentColor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeLinecap&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; strokeLinejoin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;round&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; d&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{d} /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; default&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; SortIcon;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por &lt;em&gt;props&lt;/em&gt;, &lt;code&gt;SortIcon&lt;/code&gt; recibe el parámetro &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En el renderizado lo que hago es dibujar el icono SVG en función del valor de &lt;code&gt;order&lt;/code&gt;, que puede ser: 1, -1 y &lt;em&gt;undefined&lt;/em&gt;. Para elegir que icono mostrar, cambio el valor de la propiedad &lt;code&gt;d&lt;/code&gt; de la imagen SVG que pinta el icono. La propiedad &lt;code&gt;d&lt;/code&gt; es la única que cambia en los tres iconos elegidos, el de ordenación ascendente (1), descendente (-1) y no seleccionado (&lt;em&gt;undefined&lt;/em&gt;), así que utilizo el mismo código SVG para los tres iconos, y cambio sólo el valor de d en función de su estatus (order).&lt;/p&gt;
&lt;p&gt;Con el operador condicional ternario compruebo si &lt;code&gt;order&lt;/code&gt; es &lt;code&gt;undefined&lt;/code&gt; (!order) y si es así, asigno a &lt;code&gt;d&lt;/code&gt; los datos para pintar el icono de “no seleccionado”. En caso contrario, hago otra comprobación con otro operador condicional ternario, esta vez para conocer si el icono a dibujar es el de ordenación ascendente o descendente, y asignar a &lt;code&gt;d&lt;/code&gt; los datos correspondientes a cada icono.&lt;/p&gt;
&lt;p&gt;Los iconos mostrados en la captura de este ejemplo corresponden a la librería &lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;, descargados en su versión JSX.&lt;/p&gt;
&lt;h1 id=&quot;en-resumen&quot;&gt;En resumen&lt;/h1&gt;
&lt;p&gt;A partir de la interacción del usuario, y gracias al &lt;code&gt;useEffect&lt;/code&gt; que se ejecuta cuando se detecta el cambio, se ha establecido un criterio de ordenación diferente, modificado el aspecto de los botones según este nuevo criterio y, como consecuencia, se ha obtenido un listado actualizado de productos ordenados a través de la API preparada para ello.&lt;/p&gt;
&lt;p&gt;Para lograrlo, se han creado dos estados (&lt;code&gt;sortData&lt;/code&gt; y &lt;code&gt;currentPage&lt;/code&gt;) y un componente &lt;code&gt;Sort&lt;/code&gt; que recibe &lt;code&gt;sortData&lt;/code&gt;, &lt;code&gt;setSortData&lt;/code&gt; y &lt;code&gt;setCurrentPage&lt;/code&gt;. Este componente detecta los clics, cambia el estado de la ordenación en &lt;code&gt;sortData&lt;/code&gt; mediante la función &lt;code&gt;handleIcon&lt;/code&gt; (activando solo un filtro cada vez y alternando entre ascendente y descendente), luego vuelve a la página 1 con &lt;code&gt;setCurrentPage(1)&lt;/code&gt; y muestra el icono apropiado para cada filtro usando el componente &lt;code&gt;SortIcon&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Tomando todo esto como referencia, ya puedes hacer tus propios filtros de ordenación para tu nueva aplicación React.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;Página de ejemplo «Tienda 8 bits»&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/tienda-8-bits&quot;&gt;Información sobre el proyecto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/dalton.uMLTtW5b_zpaNY.webp"/><category>react</category><category>javascript</category><author>JavGuerra</author></item><item><title>El algoritmo de Karaca</title><link>https://javguerra.github.io/blog/karaca</link><guid isPermaLink="true">https://javguerra.github.io/blog/karaca</guid><description>Solución en JavaScript al reto semanal n. 50 de @MoureDev</description><pubDate>Thu, 15 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/cifrado.Hb5hRkab_Z2qxri.webp&quot; alt=&quot;Cifrado&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#criptografía&lt;/em&gt;, &lt;em&gt;#ciberseguridad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;En este post resuelvo, en JavaScript el &lt;a href=&quot;https://github.com/mouredev/Weekly-Challenge-2022-Kotlin/blob/main/app/src/main/java/com/mouredev/weeklychallenge2022/Challenge50.kt&quot;&gt;reto de programación&lt;/a&gt; consistente en desarrollar una función que es capaz de encriptar y desencriptar texto utilizando el algoritmo de encriptación de Karaca.&lt;/p&gt;
&lt;p&gt;Descubrí esta semana, un poco tarde, los &lt;a href=&quot;https://retosdeprogramacion.com/semanales2022&quot;&gt;retos de programación semanales de Mouredev para 2022&lt;/a&gt; y me atrajo el enunciado de este ejercicio.&lt;/p&gt;
&lt;p&gt;Busqué información en Internet sobre el algoritmo, encontrando lo siguiente:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Make a function that encrypts a given input with these steps:&lt;br&gt;
Input: “apple”&lt;br&gt;
Step 1: Reverse the input: “elppa”&lt;br&gt;
Step 2: Replace all vowels using the following chart:&lt;br&gt;
a =&amp;gt; 0, e =&amp;gt; 1, i =&amp;gt; 2, o =&amp;gt; 3, u =&amp;gt; 4  # “1lpp0”&lt;br&gt;
Step 3: Add “aca” to the end of the word: “1lpp0aca”&lt;br&gt;
Output: “1lpp0aca”&lt;br&gt;
All inputs are strings, no uppercases and all output must be strings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Y me tomé la libertad de corregir la relación entre vocales y números que, en &lt;a href=&quot;https://edabit.com/challenge/JzBLDzrcGCzDjkk5n&quot;&gt;la fuente original&lt;/a&gt; publicada por Furkan Karaca, en el &lt;a href=&quot;https://edabit.com/&quot;&gt;portal de retos Edabit&lt;/a&gt; parece no ser correcta.&lt;/p&gt;
&lt;p&gt;El algoritmo, sin una aparente utilidad práctica, es un buen ejercicio de programación que combina el uso de expresiones regulares, uso de arreglos y cadenas y lógica.&lt;/p&gt;
&lt;h1 id=&quot;entendiendo-el-problema&quot;&gt;Entendiendo el problema&lt;/h1&gt;
&lt;p&gt;Lo que pide el ejercicio es que nuestra función debe poder codificar y decodificar un texto, en minúsculas, que le pasemos por parámetro. Este texto, lógicamente, no puede estar vacío.&lt;/p&gt;
&lt;p&gt;Cualquier dato que le pasemos que no sea texto debe impedir la ejecución de la codificación/decodificación. La función puede devolver un error, o bien el dato original suministrado. Opto por esta segunda posibilidad.&lt;/p&gt;
&lt;p&gt;La cadena de caracteres suministrada a la función puede tener espacios al inicio y/o al final, incluso puede contener sólo espacios, por lo que amerita limpiar la cadena, y que esta contenga algo más que sólo espacios.&lt;/p&gt;
&lt;p&gt;La cadena no puede contener sólo números, esto equivaldría a suministrar un número entero a la función. De hecho, el algoritmo presenta un problema importante con esto. Si se le suministra un frase que contenga dígitos en el rango del mapeo de vocales (0-1-2-3-4) no realizará bien el cifrado, pues tomará estos dígitos como parte del descifrado, mostrando un galimatías. Ej. «100 horas» -&amp;gt; «s0r3h 001aca» -&amp;gt; «eaa horas».&lt;/p&gt;
&lt;p&gt;Para saber si se puede decodificar una cadena proporcionada, es decir, para saber si está codificada con el algoritmo de Karaca, se debe cumplir que esta termine con un «aca», que contenga algún número entre el 0 y el 4, y que su longitud sea mayor que la de la cadena de control «aca». De no cumplirse esto, se entiende que la cadena que se proporciona a la función no está codificada, y entonces puede ser codificada.&lt;/p&gt;
&lt;p&gt;Para realizar la conversión, se debe recorrer la cadena teniendo en cuenta el mapeo de vocales del enunciado (a =&amp;gt; 0, e =&amp;gt; 1, i =&amp;gt; 2, o =&amp;gt; 3, u =&amp;gt; 4) y viceversa.&lt;/p&gt;
&lt;h1 id=&quot;resolución&quot;&gt;Resolución&lt;/h1&gt;
&lt;p&gt;El algoritmo de Karaca en JavaScript, atendiendo a las consideraciones anteriores, es el siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;. &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;02.  * Función en JavaScript que encripta y desencripta texto en minúsculas en &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;03.  * inglés, sin números, utilizando el algoritmo de encriptación de Karaca.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;04.  * &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@param&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; {String}&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;05.  * &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@returns&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; String&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;06.  * &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@author&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Javier Guerra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;07.  */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;08.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; karacaAlgorithm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;09.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;??&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;string&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;trim&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\D&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;14.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;trim&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toLowerCase&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;reverse&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; vowels&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;aeiou&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;17.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; control&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;aca&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;18.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;startsWith&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(control) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;21.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\d&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;22.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            str.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; control.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;23.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;24.&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            // decode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;25.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;slice&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(control.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;26.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            vowels.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;chr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(i)) str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replaceAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(i, chr);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;28.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;29.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;30.&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;            // encode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;31.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            vowels.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;forEach&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;chr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;includes&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(chr)) str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replaceAll&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(chr, i);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;33.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;34.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            str &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; control;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;35.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;36.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;37.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;38.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;39.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En la línea 8, con el valor por defecto &lt;code&gt;&quot;&quot;&lt;/code&gt; del parámetro se evita el error si llamemos a la función sin ningún parámetro, devolviendo una cadena vacía.&lt;/p&gt;
&lt;p&gt;en la línea 10 se comprueba que el parámetro recibido no está colando un valor &lt;code&gt;null&lt;/code&gt; o &lt;code&gt;undefined&lt;/code&gt; con el operador coalescente nulo (&lt;code&gt;??&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;En la línea 12 se comprueba que el dato recibido es una cadena, que tiene al menos un carácter, y cuenta con alguna consonante. De no ser así, se devuelve el parámetro recibido.&lt;/p&gt;
&lt;p&gt;En la línea 14 se realizan varias conversiones al parámetro recibido: se limpian los espacios iniciales y/o finales, se pasa la  cadena a minúsculas, y se invierte la cadena. Esto último se hace mediante la concatenación de varios métodos: &lt;code&gt;split&lt;/code&gt;, para convertir la cadena en un arreglo, &lt;code&gt;reverse&lt;/code&gt; para invertir el orden del contenido del arreglo y &lt;code&gt;join&lt;/code&gt; para unir el contenido del arreglo en una cadena.&lt;/p&gt;
&lt;p&gt;Las líneas 16 y 17 definen las variables que usaremos en el algoritmo.&lt;/p&gt;
&lt;p&gt;En la comprobación de las líneas de la 19 a la 23 se decide si se va a decodificar la cadena recibida, es decir, si se cumple que la cadena termina en «aca», contiene algún dígito y su longitud es mayor que la longitud de «aca». Si es así, se lleva a cabo la codificación a partir de la línea 25. en caso contrario, se lleva a cabo la codificación a partir de la línea 31.&lt;/p&gt;
&lt;p&gt;Para la decodificación, primero se elimina el control «aca» y luego se recorre el arreglo de vocales con forEach, de tal forma que si alguno de los elementos del arreglo es encontrado en la cadena a decodificar, este se sustituye por la vocal correspondiente.&lt;/p&gt;
&lt;p&gt;Para la codificación se lleva a cabo el proceso contrario. Al recorrer el arreglo de vocales, se sustituye el dígito por la vocal correspondiente. Luego se añade la cadena de control «aca».&lt;/p&gt;
&lt;p&gt;Por último, se devuelve el resultado de las operaciones sobre la cadena recibida convertida a cadena, por si el valor recibido fue un número, ya que la función debe devolver una cadena.&lt;/p&gt;
&lt;h1 id=&quot;prueba&quot;&gt;Prueba&lt;/h1&gt;
&lt;p&gt;El siguiente código de prueba debe poder codificar y decodificar la cadena original suministrada obteniendo la cadena original como resultado.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Testing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Solving an equation produces, instantly, great euphoria.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;karacaAlgorithm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(str));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;karacaAlgorithm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;karacaAlgorithm&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(str)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El resultado esperado debe ser:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;.02r3hp41 t01rg ,yltn0tsn2 ,s1c4d3rp n32t04q1 n0 gn2vl3saca&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;solving an equation produces, instantly, great euphoria.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;La frase, en inglés, incluye las palabras &lt;code&gt;equation&lt;/code&gt; y &lt;code&gt;euphoria&lt;/code&gt; que cuentan con todas las vocales.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://retosdeprogramacion.com/semanales2022&quot;&gt;Retos de programación semanales de Mouredev para 2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mouredev/Weekly-Challenge-2022-Kotlin/blob/main/app/src/main/java/com/mouredev/weeklychallenge2022/Challenge50.kt&quot;&gt;Reto de programación semanal n. 50 de Mouredev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://edabit.com/challenge/JzBLDzrcGCzDjkk5n&quot;&gt;La fuente original del reto por Furkan Karaca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://edabit.com/&quot;&gt;Portal de retos Edabit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/retos-programacion&quot;&gt;Ver el código de este y otros retos de programación en GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/cifrado.Hb5hRkab_Z2qxri.webp"/><category>código</category><category>javascript</category><category>criptografía</category><category>ciberseguridad</category><author>JavGuerra</author></item><item><title>Sinclair QL SCR Viewer</title><link>https://javguerra.github.io/blog/ql-scr-viewer</link><guid isPermaLink="true">https://javguerra.github.io/blog/ql-scr-viewer</guid><description>Muestra pantallas del ordenador Sinclair QL</description><pubDate>Sat, 10 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/qlscrview.CzONMBZX_1QXhLE.webp&quot; alt=&quot;QL SCR Viewer&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#herramienta&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#retro&lt;/em&gt;, &lt;em&gt;#sinclair ql&lt;/em&gt;, &lt;em&gt;#software libre&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;El QL original tiene dos modos de pantalla, el modo de 256×256 pixels a 8 colores, y el modo de 512×256 pixels a 4 colores.&lt;/p&gt;
&lt;p&gt;La aplicación Sinclair QL SCR Viewer es un HTML que permite cargar en el navegador un archivo de imagen en estos formatos ubicado en local o en remoto, mediante un botón INPUT, para mostrar su contenido sin que ocurran errores de CORS, y sin usar un servidor.&lt;/p&gt;
&lt;p&gt;La imagen resultante puede descargarse en formato PNG con un tamaño de 1024×768 pixels.&lt;/p&gt;
&lt;p&gt;Se escribió un &lt;a href=&quot;https://sinclairqles.wordpress.com/2024/02/10/ql-scr-viewer-en-linea/&quot;&gt;artículo para QBlog&lt;/a&gt; con más información de cuál es la estructura de codificación de las pantallas en estos dos modos que puedes consultar.&lt;/p&gt;
&lt;p&gt;El desarrollo se ha llevado a cabo a ratos, durante una semana, y se ha hecho uso de la IA &lt;a href=&quot;https://www.phind.com/&quot;&gt;Phind&lt;/a&gt; para consultas técnicas que han sido de gran utilidad. La aplicación acrtualmente está en la versión 1.0.&lt;/p&gt;
&lt;p&gt;Hice uso de GitHub pages para alojar el desarrollo y también la aplicación que está disponible en:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/Sinclair-QL-SCR-viewer/&quot;&gt;&lt;button&gt;QL SCR Viewer&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;objetivo-de-la-aplicación&quot;&gt;Objetivo de la aplicación&lt;/h2&gt;
&lt;p&gt;Hagamos un poco de arqueología. En los tiempos del QL (años 80) era muy normal cargar y salvar a y desde memoria de pantalla las imágenes que querían mostrarse. Solía usarse para mantener al usuario atento con una pantalla colorida mientras terminaba la carga del programa desde algún medio de almacenamiento. ¡Esto podía demorar minutos!&lt;/p&gt;
&lt;p&gt;Dado que las imágenes de pantalla del QL son datos con estructura, pero sin cabecera, es complicado poder visualizarlas en un PC si no se lleva a cabo una conversión, y eso es justamente lo que hace esta aplicación, además de permitir descargar la pantalla en formato PNG.&lt;/p&gt;
&lt;p&gt;La idea era crear una herramienta que no dependiera de ningún sistema host, para que pudiera ser usada en cualquier sistema operativo actual. Emplear HTML + JavaScript era una opción interesante que permitía hacer uso de la aplicación en local, pero también ofrecer la aplicación como un servicio en línea.&lt;/p&gt;
&lt;h2 id=&quot;características&quot;&gt;Características&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Maneja pantallas en modos 8 y 4.&lt;/li&gt;
&lt;li&gt;Detecta automáticamente el modo de pantalla.&lt;/li&gt;
&lt;li&gt;Permite el cambio de modo de la imagen cargada.&lt;/li&gt;
&lt;li&gt;Funciona en local evitando errores de CORS.&lt;/li&gt;
&lt;li&gt;Descarga la imagen visualizada en PNG.&lt;/li&gt;
&lt;li&gt;Es responsive.&lt;/li&gt;
&lt;li&gt;Es accesible.&lt;/li&gt;
&lt;li&gt;Detecta errores de carga.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;info-sobre-el-funcionamiento-de-la-aplicación&quot;&gt;Info sobre el funcionamiento de la aplicación&lt;/h2&gt;
&lt;p&gt;El desarrollo inicialmente se centró en el &lt;em&gt;parser&lt;/em&gt; o analizador sintáctico que debía «entender» los dos modos. Mediante un botón de carga y un evento asociado se accede al fichero, y luego se procesa.&lt;/p&gt;
&lt;p&gt;Igualmente se asocian eventos al botón de cambiar de modo y al botón de descargar archivos. Estos eventos llaman a sus correspondientes funciones.&lt;/p&gt;
&lt;p&gt;El código ha sido optimizado para poder funcionar en local sin que se generen errores de CORS (Cross-Origin Resource Sharing en inglés), una funcionalidad de los navegadores que ayudan a evitar problemas relacionados con la seguridad de la información.&lt;/p&gt;
&lt;p&gt;Para visualizar correctamente la imagen se hace uso de una función que revisa los datos cargados y determina si la imagen está en modo 8 o en modo 4 y, si corresponde, cambia el modo de visualización.&lt;/p&gt;
&lt;p&gt;A la hora de visualizar la imagen se han empelado dos canvas, uno donde se dibuja la imagen y otro que contiene este primer canvas que lo muestra en la escala adecuada para que se vea completo y proporcional en cualquier dispositivo. La proporción de la imagen es 4:3 y el tamaño de la imagen es de 1024x768.&lt;/p&gt;
&lt;p&gt;Se ha elegido esta resolución porque es múltiplo de las resoluciones de ambos modos. De hecho, para representar correctamente las imágenes de los modos 8 y 4, un pixel de una imagen en modo 8 ocupará cuatro pixeles de ancho y tres de alto en la imagen resultante, y un pixel de una imagen en modo 4 ocupará dos píxeles de ancho y tres píxeles de alto en la imagen resultante.&lt;/p&gt;
&lt;p&gt;La representación de color de los modos se realiza de la siguiente forma: el modo 8 usa cuatro bits por pixel para representar cada color (GFRB - Green, Flash, Red, Blue), con una profundidad de color de 8 (negro, azul, rojo, magenta, verde, cian, amarillo, blanco). Hay un bit que no se usa, que corresponde al flash (F) o parpadeo, una característica que tiene este ordenador. El modo 4 usa 2 bits por pixel (GR - Green, Reed), con una profundidad de color de 4 (negro, rojo, verde, blanco). Pues bien, para poder mostrar los colores en formato RGB, si un bit R, G o B está a cero, el valor de su componente RGB será 0, si es 1, el valor de su componente RGB será 255. En el modo 4, para obtener el valor de B, si los valores G y R están a 1, el valor B será 1, y el valor de su componente, 255, en caso contrario, será 0.&lt;/p&gt;
&lt;p&gt;La pantalla del QL clásica tiene un tamaño de 32.768 bytes en ambos modos. Al cargar la imagen esto se comprueba, así como si el archivo está vacío o si no se ha podido acceder al medio.&lt;/p&gt;
&lt;p&gt;Con el botón de intercambio de modo, podemos cambiar el modo de visualización de la imagen, caso que puede ser de utilidad si la detección automática no terminó de funcionar correctamente. Esto se hace sin necesidad de volver a acceder a la imagen, aprovechando los datos que están almacenados en el &lt;em&gt;buffer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La descarga en PNG permite obtener una imagen que se guardará con el formato nombre + sufijo + extensión. El &lt;code&gt;nombre&lt;/code&gt; corresponde al nombre del archivo original. La extensión será &lt;code&gt;_QL8&lt;/code&gt; o &lt;code&gt;_QL4&lt;/code&gt; según corresponda, y la extensión será &lt;code&gt;.png&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Para el desarrollo se ha tenido en cuenta el uso accesible de la aplicación, mediante la incorporación de etiquetas WAI-ARIA en el código.&lt;/p&gt;
&lt;h2 id=&quot;saber-más&quot;&gt;Saber más&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.github.io/Sinclair-QL-SCR-viewer/&quot;&gt;QL SCR Viewer en línea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sinclairqles.wordpress.com/2024/02/10/ql-scr-viewer-en-linea/&quot;&gt;Artículo sobre QL SCR Viewer para QBLog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/Sinclair-QL-SCR-viewer&quot;&gt;Repositorio de QL SCR Viewer en GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/sinclair-ql&quot;&gt;Info sobre Sinclair QL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/qlscrview.CzONMBZX_1QXhLE.webp"/><category>web</category><category>html</category><category>javascript</category><category>herramienta</category><category>código</category><category>retro</category><category>sinclair ql</category><category>software libre</category><author>JavGuerra</author></item><item><title>Accediendo a la API de Mastodon</title><link>https://javguerra.github.io/blog/api-mastodon</link><guid isPermaLink="true">https://javguerra.github.io/blog/api-mastodon</guid><description>Cómo obtener y mostrar las publicaciones de esta red social</description><pubDate>Wed, 18 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/mastodon.Dc7cm57i_1rPUNx.webp&quot; alt=&quot;Logo Mastodon&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#api&lt;/em&gt;, &lt;em&gt;#servidor&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;En este artículo vamos a ver cómo se puede acceder a la API de Mastodon, un servicio que nos permite, entre otras cosas, obtener las últimas publicaciones de un usuario concreto.&lt;/p&gt;
&lt;p&gt;Recientemente la he usado para mostrar, en el apartado &lt;a href=&quot;/social&quot;&gt;social&lt;/a&gt; de esta página, las publicaciones que escribo en la red social, empleando JavaScript del lado del cliente en Astro, es decir, que en una página .astro he incluido un script que lee y muestra las publicaciones actualizadas de mi cuenta de Mastodon.&lt;/p&gt;
&lt;p&gt;Me centraré en la parte de JavaScript y no tanto en la integración con Astro, ya que, de esta forma, será posible aprovechar la información para que pueda ser usada en otros frameworks o aplicaciones propias.&lt;/p&gt;
&lt;p&gt;El lector debe conocer las funciones avanzadas de JavaScript como asincronía y llamadas a APIs para seguir correctamente esta entrada.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;note&quot;&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Este artículo ha sido publicado también en &lt;a href=&quot;https://ifgeekthen.nttdata.com/s/post/accediendo-a-la-api-de-mastodon-MCKLT5EQTUINBVBMVGH7W6S2MYXM&quot;&gt;IfGeekThen&lt;/a&gt;, el blog de NTT Data, el 18 de marzo de 2026.&lt;/span&gt;&lt;/p&gt;
&lt;h1 id=&quot;api-de-mastodon&quot;&gt;API de Mastodon&lt;/h1&gt;
&lt;p&gt;Realizaré la consulta a la &lt;a href=&quot;https://docs.joinmastodon.org/api/&quot;&gt;API de Mastodon&lt;/a&gt; mediante la función &lt;code&gt;fetch&lt;/code&gt; de JavaScript.&lt;/p&gt;
&lt;p&gt;Las consultas a la API no requieren autenticación (aunque es posible), por lo que podemos acceder a ella sin ningún tipo de token, pero voy a necesitar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La url de la instancia de Mastodon, es decir el servidor.&lt;/li&gt;
&lt;li&gt;El id de la cuenta de usuario que quiero consultar.&lt;/li&gt;
&lt;li&gt;El número que indique la cantidad de publicaciones que quiero obtener.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cuando tengamos estos datos, podremos construir el &lt;code&gt;endpoint&lt;/code&gt; o url de la API de Mastodon, que será la siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://&amp;lt;server&amp;gt;/api/v1/accounts/&amp;lt;accountId&amp;gt;/statuses?limit=&amp;lt;limit&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Donde:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;server&amp;gt;&lt;/code&gt; es el nombre de dominio de la instancia de Mastodon, por ejemplo &lt;code&gt;mastodon.social&lt;/code&gt; o la de tu propia instancia.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;accountId&amp;gt;&lt;/code&gt; es el id de la cuenta que queremos consultar, por ejemplo &lt;code&gt;1234567890&lt;/code&gt;. Este id se obtendría de la url de la cuenta, ej.: &lt;code&gt;https://mastodon.social/@usuario&lt;/code&gt;, como se verá enseguida.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;limit&amp;gt;&lt;/code&gt; es el número de publicaciones que queremos consultar, por ejemplo &lt;code&gt;10&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para obtener el id de la cuenta, debo usar la siguiente url:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://&amp;lt;server&amp;gt;/api/v1/accounts/lookup?acct=&amp;lt;username&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Donde hay que sustituir &lt;code&gt;&amp;lt;server&amp;gt;&lt;/code&gt; por el nombre de la instancia de Mastodon y &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; por el nombre de usuario de la cuenta que queremos consultar.&lt;/p&gt;
&lt;p&gt;Obtengo un json con el id de la cuenta, entre otros datos, como por ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1234567890&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;username&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;usuario&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si queremos consultar las 10 últimas publicaciones de la cuenta ficticia &lt;code&gt;@usuario&lt;/code&gt;, que tiene el id ficticio: &lt;code&gt;1234567890&lt;/code&gt;, en la instancia de Mastodon &lt;code&gt;mastodon.social&lt;/code&gt;, tendríamos que usar la siguiente url:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;https://mastodon.social/api/v1/accounts/1234567890/statuses?limit=10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;fetch&quot;&gt;Fetch&lt;/h2&gt;
&lt;p&gt;Ya tenemos formado el endpoint de la API de Mastodon, y, para llevar a cabo la consulta, usaré la función &lt;code&gt;fetch&lt;/code&gt; de JavaScript, que permite realizar peticiones HTTP, y obtener el resultado como un objeto &lt;code&gt;json&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; server&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;https://mastodon.social&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; profileId&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1234567890&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; limit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; route&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/api/v1/accounts/${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;profileId&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/statuses?limit=${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;limit&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getLatestPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;route&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(route);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;response.ok) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(response.statusText);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(error);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como se aprecia, se trata de una función asíncrona con una estructura de lo más común, que se ejecutará de manera independiente, y cuando se haya terminado de ejecutar, me permitirá seguir con la ejecución del código.&lt;/p&gt;
&lt;p&gt;Para llamar a la función, uso:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; posts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getLatestPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(route);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con &lt;code&gt;await&lt;/code&gt;, se espera a que la función &lt;code&gt;getLatestPosts&lt;/code&gt; termine de ejecutarse, y luego es posible usar el array &lt;code&gt;posts&lt;/code&gt; para mostrar las publicaciones en nuestra página, siempre que no se haya producido ningún error.&lt;/p&gt;
&lt;h2 id=&quot;mostrando-las-publicaciones&quot;&gt;Mostrando las publicaciones&lt;/h2&gt;
&lt;p&gt;Allí donde vamos a mostrar las publicaciones, voy a usar un elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; con el &lt;code&gt;id=&quot;posts&quot;&lt;/code&gt; para definir una lista de publicaciones, un &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, y un elemento &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; para cada publicación.&lt;/p&gt;
&lt;p&gt;Incluyo el siguiente código HTML en la página:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  Cargando...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Y luego, mediante el script de JavaScript, sustituiré el contenido del elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; con las publicaciones obtenidas y formateadas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; displayPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; postsElement&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;posts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&amp;lt;p&amp;gt;No se encontraron posts.&amp;lt;/p&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;h2&amp;gt;Últimas publicaciones&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; isReblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; isReblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; contentIsEmpty&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;trim&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; hasMedia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;media_attachments&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;media_attachments&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; multimediaLink&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;small&amp;gt;Incluye contenido multimedia &amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&amp;gt;👁️ Ver en origen →&amp;lt;/a&amp;gt;&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;lt;li class=&quot;post&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;isReblog&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} &amp;lt;small&amp;gt;♻️ Republicado &amp;lt;/small&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; contentIsEmpty&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;              ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;              :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &amp;lt;small&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;              📢 ${&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;created_at&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;es-ES&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, {dateStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, timeStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;short&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &amp;lt;/small&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      }).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  `&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}   &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vamos por partes.&lt;/p&gt;
&lt;p&gt;Primero obtengo el elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; con el id &lt;code&gt;posts&lt;/code&gt; del DOM, y lo guardo en una variable &lt;code&gt;postsElement&lt;/code&gt; para poder referirme a él en el script.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; postsElement&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;posts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compruebo que hay publicaciones y que el array &lt;code&gt;posts&lt;/code&gt; no esté vacío. Si no es así, defino el contenido del elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; con el siguiente código:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&amp;lt;p&amp;gt;No se encontraron posts.&amp;lt;/p&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si hemos obtenidos publicaciones, hago uso de la siguiente estructura:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;h2&amp;gt;Últimas publicaciones&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        // código para mostrar cada publicación&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    `&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  `&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Con la función &lt;code&gt;map&lt;/code&gt; puedo iterar sobre cada elemento del objeto &lt;code&gt;posts&lt;/code&gt; y acceder a cada una de las publicaciones, y luego puedo juntar todos los elementos formateados en una cadena de texto mediante la función &lt;code&gt;join&lt;/code&gt;. El resultado se incluirá en el elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; con el id &lt;code&gt;posts&lt;/code&gt; mediante el método &lt;code&gt;innerHTML&lt;/code&gt; de &lt;code&gt;postElement&lt;/code&gt;. Es decir, obtengo cada publicación, esta se formatea, y se concatena o añade a la cadena de texto que conforma el contenido del elemento &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;; las publicaciones.&lt;/p&gt;
&lt;h2 id=&quot;pintando&quot;&gt;Pintando…&lt;/h2&gt;
&lt;p&gt;Para formatear las publicaciones, voy a usar una estructura de elementos &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; por cada publicación, como dije, y un elemento &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; para enlazar a la publicación original. Lo que quiero conseguir se parece a esto:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  Este es un ejemplo de una publicación en Mastodon.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; href&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;https://mastodon.social/@usuario/109292343224519197&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;18 sep 2024, 1:23:45&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;De cada publicación obtengo el contenido de la publicación, y el enlace a la publicación. Con esta información defino una serie de variables:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; isReblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post.reblog &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; isReblog &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post.reblog &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; contentIsEmpty&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost.content &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost.content.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;trim&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; hasMedia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost.media_attachments &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost.media_attachments.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; multimediaLink&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;small&amp;gt;Incluye contenido multimedia &amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&amp;gt;👁️ Ver en origen →&amp;lt;/a&amp;gt;&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Como las publicaciones pueden ser republicaciones, es decir, publicaciones compartidas de otros usuarios o propias, compruebo si este es el caso.&lt;/p&gt;
&lt;p&gt;Si es una republicación, obtengo su contenido, sino, obtengo el contenido de la publicación original.&lt;/p&gt;
&lt;p&gt;Compruebo si el texto de la publicación está verdaderamente vacío, es decir, si no contiene, por ejemplo, alguna etiqueta HTML.&lt;/p&gt;
&lt;p&gt;Compruebo también si la publicación tiene contenido multimedia.&lt;/p&gt;
&lt;p&gt;Por último, si la publicación tiene contenido multimedia, preparo el enlace a la publicación original, y si no lo tiene, dejo el aviso vacío.&lt;/p&gt;
&lt;p&gt;Seguidamente, formateo el texto de la publicación mediante el siguiente código:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ${isReblog &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} &amp;lt;small&amp;gt;♻️ Republicado &amp;lt;/small&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; contentIsEmpty &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost.content &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; href&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;${originalPost.url}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        📢 ${&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(originalPost.created_at).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;es-ES&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {dateStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, timeStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;short&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;})}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;small&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;li&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;¿Se trata de una republicación?, entonces publico el texto de la republicación con el aviso de &lt;code&gt;♻️ Republicado&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;En caso contrario, compruebo si el texto de la publicación está vacío y si tiene contenido multimedia.&lt;/p&gt;
&lt;p&gt;Si ambas condiciones se cumplen, entonces publico el aviso de ver &lt;code&gt;👁️ Ver en origen →&lt;/code&gt; con su enlace, ya que será una publicación sin texto pero con video o imagen…&lt;/p&gt;
&lt;p&gt;Si no se cumple alguna o ambas condiciones, entonces publico el contenido de la publicación y el aviso de ver &lt;code&gt;👁️ Ver en origen →&lt;/code&gt; con su enlace, pues o bien la publicación tiene contenido, tiene texto y contenido multimedia o sólo texto.&lt;/p&gt;
&lt;p&gt;Para mostrar la fecha, uso la función &lt;code&gt;toLocaleString&lt;/code&gt; de JavaScript, que me permite obtener la fecha en formato local.&lt;/p&gt;
&lt;p&gt;Es posible llamar a la función &lt;code&gt;displayPosts&lt;/code&gt; mediante:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;displayPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(posts);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Siendo &lt;code&gt;posts&lt;/code&gt; el objeto de publicaciones en json obtenido de la API de Mastodon.&lt;/p&gt;
&lt;h2 id=&quot;una-advertencia&quot;&gt;Una advertencia&lt;/h2&gt;
&lt;p&gt;Si bien las instancias de Mastodon se encargan de limpiar las publicaciones de los usuarios ante potenciales peligros, no estaría de más implementar una función propia que se ocupe de limpiar el contenido de las publicaciones antes de hacer uso de &lt;code&gt;originalPost.content&lt;/code&gt; para evitar sorpresas por la inclusión de etiquetas o atributos dañinos que pudieran llegar de publicaciones de instancias de Mastodon poco confiables.&lt;/p&gt;
&lt;h1 id=&quot;el-código-completo&quot;&gt;El código completo&lt;/h1&gt;
&lt;p&gt;El código siguiente incluye el contenido mostrado hasta ahora en el artículo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;html&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;DOCTYPE&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; lang&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;es&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; charset&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;viewport&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;width=device-width, initial-scale=1.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Publicaciones de Mastodon&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;link&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; rel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; href&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;style.css&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;Mastodon&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;h1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;posts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Cargando...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    // Sustituye los valores siguientes para adaptarlo a tu propio uso&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; server&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;https://mastodon.social&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; profileId&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;1234567890&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; limit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; route&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/api/v1/accounts/${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;profileId&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}/statuses?limit=${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;limit&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    async&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getLatestPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;route&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        try&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; response&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fetch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(route);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;response.ok) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(response.statusText);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; response.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;json&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (error) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            console.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(error);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    function&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; displayPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; postsElement&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;posts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posts &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; posts.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ===&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&amp;lt;p&amp;gt;No se encontraron posts.&amp;lt;/p&amp;gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      postsElement.innerHTML &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;lt;h2&amp;gt;Últimas publicaciones&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; isReblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; null&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; isReblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reblog&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; post&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; contentIsEmpty&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&amp;gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;trim&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; hasMedia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;media_attachments&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;media_attachments&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; multimediaLink&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&amp;lt;small&amp;gt;Incluye contenido multimedia &amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&amp;gt;👁️ Ver en origen →&amp;lt;/a&amp;gt;&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;          return&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &amp;lt;li class=&quot;post&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;              ${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;isReblog&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                ?&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; `${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;} &amp;lt;small&amp;gt;♻️ Republicado &amp;lt;/small&amp;gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; contentIsEmpty&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hasMedia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                  ?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                  :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; multimediaLink&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;              &amp;lt;a href=&quot;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &amp;lt;small&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                  📢 ${&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Date&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;originalPost&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;created_at&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;toLocaleString&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;es-ES&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, {dateStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;medium&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, timeStyle: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;short&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;                &amp;lt;/small&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;              &amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          }).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;join&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      `&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    document.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;DOMContentLoaded&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; () &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; posts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; getLatestPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(route);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;      displayPosts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(posts);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No olvides sustituir los valores de &lt;code&gt;server&lt;/code&gt;, &lt;code&gt;profileId&lt;/code&gt; y &lt;code&gt;limit&lt;/code&gt; con los que correspondan a tu propio perfil de Mastodon o el del perfil que desees consultar.&lt;/p&gt;
&lt;h1 id=&quot;cargando-las-publicaciones&quot;&gt;Cargando las publicaciones&lt;/h1&gt;
&lt;p&gt;Aquí confluye todo. Mediante el evento asociado a la carga de la página &lt;code&gt;DOMContentLoaded&lt;/code&gt;, que se incluye al final del script, se inicia la petición asíncrona a la API de Mastodon con &lt;code&gt;getLatestPosts(route)&lt;/code&gt; y se muestran las publicaciones con &lt;code&gt;displayPosts(posts)&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;estilos&quot;&gt;Estilos&lt;/h1&gt;
&lt;p&gt;Para que el contenido se vea correctamente, es recomendable definir algunos estilos en el archivo &lt;code&gt;style.css&lt;/code&gt;. Un ejemplo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;css&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.invisible&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  display&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;inline-block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  font-size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  line-height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  position&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;absolute&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.invisible&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; img&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.invisible&lt;/span&gt;&lt;span style=&quot;color:#85E89D&quot;&gt; svg&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  border&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !important&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  height&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !important&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  margin&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !important&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  padding&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !important&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  width&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !important&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;.ellipsis:after&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  content&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;…&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Los estilos aquí mostrados son los que usa el propio Mastodon para presentar las publicaciones en su página.&lt;/p&gt;
&lt;p&gt;La clase &lt;code&gt;.invisible&lt;/code&gt; se aplica a los elementos que quiero que no se vean. Esto es necesario para evitar saltos de línea y espacios en blanco en el contenido de las publicaciones debido a su formateo original.&lt;/p&gt;
&lt;p&gt;Se incluye también la clase &lt;code&gt;.invisible&lt;/code&gt; para imágenes y vectores SVG. Si bien no se usa en este ejemplo, pueden ser de utilidad si decides mostrar el contenido multimedia de las publicaciones.&lt;/p&gt;
&lt;p&gt;Por su parte, la clase &lt;code&gt;.ellipsis&lt;/code&gt; se usa para mostrar puntos suspensivos &lt;code&gt;…&lt;/code&gt; al final de los enlaces acortados.&lt;/p&gt;
&lt;p&gt;A partir de estos estilos es posible aplicar estilos propios al contenido mostrado.&lt;/p&gt;
&lt;h1 id=&quot;experimenta-por-tu-cuenta&quot;&gt;Experimenta por tu cuenta&lt;/h1&gt;
&lt;p&gt;Como has podido comprobar a lo largo de este artículo, acceder a la API de Mastodon es un proceso sencillo que nos permite integrar el contenido de una cuenta en nuestros propios proyectos mediante código JavaScript. Desde la construcción del endpoint y la gestión de la respuesta asíncrona con fetch, hasta el formateo final de los datos considerando casos como las republicaciones o el contenido multimedia, has visto los fundamentos para crear tu propio visor de publicaciones.&lt;/p&gt;
&lt;p&gt;Te animo a que tomes el código completo, lo adaptes con tus propios datos y experimentes modificando la lógica de displayPosts y el css para personalizar aún más la presentación. Y si te surgen dudas o mejoras, no dudes en explorar la documentación oficial de la API, donde encontrarás muchas más posibilidades.&lt;/p&gt;
&lt;h1 id=&quot;saber-más&quot;&gt;Saber más&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://es.wikipedia.org/wiki/Mastodon_(red_social)&quot;&gt;Mastodon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.joinmastodon.org/api/&quot;&gt;Mastodon API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ejemplo de uso: &lt;a href=&quot;/social&quot;&gt;Social&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/mastodon.Dc7cm57i_1rPUNx.webp"/><category>javascript</category><category>código</category><category>api</category><category>servidor</category><author>JavGuerra</author></item><item><title>Visor para banco de preguntas</title><link>https://javguerra.github.io/blog/visor-preguntas</link><guid isPermaLink="true">https://javguerra.github.io/blog/visor-preguntas</guid><description>Aplicación web para recorrer y estudiar exámenes a través de sus preguntas y respuestas</description><pubDate>Thu, 12 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/visor-preguntas.BQ4EG9V__1YC5uz.webp&quot; alt=&quot;Screenshot&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#herramienta&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Recientemente me presenté a una certificación en mi trabajo, y contábamos con un banco de preguntas y respuestas para repasar. Es frecuente también que, en nuevos exámenes se incluyan preguntas de exámenes anteriores, por lo que decidi prepararme una aplicación para estudiar y aprender las respuestas a las preguntas. En esta entrada verás cómo funciona y podrás acceder al código para descargarlo.&lt;/p&gt;
&lt;h2 id=&quot;el-programa-visor&quot;&gt;El programa visor&lt;/h2&gt;
&lt;p&gt;El programa visor se ejecuta en un navegador web, y sirve para mostrar, de forma consecutiva o aleatoriamente, un conjunto de preguntas y respuestas para estudiarlas. Para ello:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Usa &lt;code&gt;←&lt;/code&gt; / &lt;code&gt;→&lt;/code&gt; para navegar por las preguntas.&lt;/li&gt;
&lt;li&gt;Pulsa &lt;code&gt;S&lt;/code&gt; para mostrar/ocultar la solución.&lt;/li&gt;
&lt;li&gt;Pulsa &lt;code&gt;R&lt;/code&gt; para barajar las preguntas.&lt;/li&gt;
&lt;li&gt;Recarga la página para ordenarlas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mediante este programa es posible repasar las respuestas a las preguntas de los exámenes si mantienes activada la función de mostrar solución, reteniendo de esta forma la respuesta correcta, o bien recorrer las preguntas para intentar acertar las respuestas y ver inmediatamente el resultado mostrando/ocultando la solución a la pregunta.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/JavGuerra/visor-preguntas&quot;&gt;&lt;button&gt;Descargar el visor de preguntas&lt;/button&gt;&lt;/a&gt; | &lt;a href=&quot;https://javguerra.github.io/visor-preguntas/&quot;&gt;&lt;button&gt;Ver el programa visor en linea&lt;/button&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;El programa requiere que esté habilitado el soporte JavaScript en el navegador.&lt;/p&gt;
&lt;p&gt;Eres libre de usarlo, modificarlo y redistribuirlo bajo las condiciones de la licencia es GPL v.3.&lt;/p&gt;
&lt;h2 id=&quot;estructura-de-los-datos&quot;&gt;Estructura de los datos&lt;/h2&gt;
&lt;p&gt;Al abrir la aplicación, esta importa un fichero llamado &lt;code&gt;bancoDePreguntas.js&lt;/code&gt; que contiene:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cada una de las preguntas del banco de preguntas&lt;/li&gt;
&lt;li&gt;Las respuestas posibles asociadas a cada pregunta&lt;/li&gt;
&lt;li&gt;El número de respuesta correcta de entre las respuestas&lt;/li&gt;
&lt;li&gt;El número de examen al que corresponde la pregunta (opcional)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La estructura de los datos es la siguiente:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;window.bancoDePreguntas &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;pregunta&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Texto de la pregunta&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;opciones&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;Respuesta 1.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;Respuesta 2.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;Respuesta 3.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;Respuesta 4.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;correcta&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;examen&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  ...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;otras preguntas aquí&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;El valor &lt;code&gt;correcta&lt;/code&gt; indica la opción correcta de ente las opciones posibles. En el ejemplo, la primera opción es la 0 y la cuarta es la 3 (índice 0).&lt;/p&gt;
&lt;p&gt;Cada pregunta debe tener, al menos, dos respuestas posibles.&lt;/p&gt;
&lt;h2 id=&quot;bancos-de-preguntas&quot;&gt;Bancos de preguntas&lt;/h2&gt;
&lt;p&gt;Se pueden incorporar nuevas preguntas al banco de preguntas o también intercambiar el fichero &lt;code&gt;bancoDePreguntas.js&lt;/code&gt; con otras temáticas de estudio, en ese caso:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El fichero &lt;code&gt;bancoDePreguntas.js&lt;/code&gt; debe estar en la carpeta donde se encuentre el programa &lt;code&gt;visor.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;El nuevo banco de preguntas debe tener el nombre &lt;code&gt;bancoDePreguntas.js&lt;/code&gt;, por lo que se deberá renombar el fichero del banco de preguntas actual.&lt;/li&gt;
&lt;li&gt;El banco de preguntas debe tener al menos una pregunta con sus correspondientes opciones, e indicar la respuesta correcta.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;todo&quot;&gt;ToDo&lt;/h2&gt;
&lt;p&gt;Como todo programa, puede ser mejorado. Aquí algunas propuestas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Añadir un título, no obligatorio, al banco de preguntas en bancoDePreguntas.js.&lt;/li&gt;
&lt;li&gt;Desordenar las posibles respuestas.&lt;/li&gt;
&lt;li&gt;Añadir un selector interactivo de examen.&lt;/li&gt;
&lt;li&gt;Opción para mantener o no la solución a las preguntas al cambiar de pregunta.&lt;/li&gt;
&lt;li&gt;Opción para mostrar el resultado tras un tiempo determinado.&lt;/li&gt;
&lt;li&gt;Añadir notas no obligatorias a las preguntas.&lt;/li&gt;
&lt;li&gt;Opción para indicar que una pregunta no debe ser mostrada, aunque esté en el banco de preguntas.&lt;/li&gt;
&lt;li&gt;Seleccionar uno o varios exámenes para mostrar, excluyendo el resto, o bien seleccionar exámenes a excluir, mostrando el resto.&lt;/li&gt;
&lt;li&gt;Incluir un fichero de configuración para personalizar el visor.&lt;/li&gt;
&lt;li&gt;Hoja de estilos externa para posibilitar el cambio de diseño del visor.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;consideración&quot;&gt;Consideración&lt;/h2&gt;
&lt;p&gt;Para su desarrollo básico se ha empleado la IA Copilot, y posteriormente ha sido modificado manualmente para añadir nuevas funcionalidades, para que sea accesible y para que se adapte a la ventana del dispositivo donde es abierto.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.github.io/visor-preguntas/&quot;&gt;Programa visor en linea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/visor-preguntas&quot;&gt;Repositorio GitHub para descargar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/visor-preguntas.BQ4EG9V__1YC5uz.webp"/><category>javascript</category><category>html</category><category>css</category><category>código</category><category>herramienta</category><author>JavGuerra</author></item><item><title>De Thunder a Postman</title><link>https://javguerra.github.io/blog/conversor-thunder-postman</link><guid isPermaLink="true">https://javguerra.github.io/blog/conversor-thunder-postman</guid><description>Conversor universal para migrar colecciones API sin perder estructura</description><pubDate>Thu, 02 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/thunder-postman.JGQ6N9Pq_ZW8Q9F.webp&quot; alt=&quot;Logos Thunder Client, Postman y Bruno&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#api&lt;/em&gt;, &lt;em&gt;#json&lt;/em&gt;, &lt;em&gt;#herramienta&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Necesitaba migrar colecciones de API desde &lt;strong&gt;Thunder Client&lt;/strong&gt; (una extensión de VS Code) a &lt;strong&gt;Bruno&lt;/strong&gt; (cliente API), pero Bruno no importa directamente colecciones de Thunder Client. Sin embargo, Bruno sí importa colecciones de Postman. Así que creé este script que convierte cualquier colección exportada de Thunder Client al formato estándar de &lt;strong&gt;Postman Collection v2.1.0&lt;/strong&gt;, permitiendo importarla en Bruno (o Postman) sin perder carpetas, autenticación, archivos ni estructura. En esta entrada te explico cómo funciona el script.&lt;/p&gt;
&lt;h2 id=&quot;qué-es-bruno&quot;&gt;¿Qué es Bruno?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.usebruno.com/&quot;&gt;Bruno&lt;/a&gt; es un cliente de API de código abierto, offline y respetuoso con la privacidad. A diferencia de otras herramientas, no requiere cuenta, no sincroniza tus colecciones en la nube y todos los datos se guardan localmente en tu ordenador. Es rápido, ligero y perfecto para equipos que priorizan la seguridad y el control de sus propios archivos.&lt;/p&gt;
&lt;h2 id=&quot;planteamiento&quot;&gt;Planteamiento&lt;/h2&gt;
&lt;p&gt;Thunder Client exporta las colecciones en un formato JSON propio. Postman y Bruno usan otro formato diferente. El script actúa como un “traductor” que lee el JSON de Thunder Client, lo interpreta y genera un JSON válido para Postman, conservando:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Las peticiones (GET, POST, PUT, DELETE, etc.)&lt;/li&gt;
&lt;li&gt;Las carpetas y subcarpetas&lt;/li&gt;
&lt;li&gt;Los headers, autenticación y cuerpos de las peticiones&lt;/li&gt;
&lt;li&gt;Los archivos adjuntos en formularios&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Puedes descargar el script desde el: &lt;a href=&quot;https://github.com/JavGuerra/conversor-thunder-postman&quot;&gt;&lt;button&gt;Repositorio del conversor&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;dificultades-de-la-conversión&quot;&gt;Dificultades de la conversión&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Estructura inconsistente del JSON de Thunder Client&lt;/strong&gt;&lt;br&gt;
Las exportaciones no siguen un formato fijo: las peticiones pueden estar en &lt;code&gt;requests&lt;/code&gt;, en &lt;code&gt;items&lt;/code&gt;, en &lt;code&gt;tests&lt;/code&gt; o en arrays con nombres personalizados como &lt;code&gt;requests_carpeta_auth&lt;/code&gt;. El script tuvo que aprender a buscar en cualquier lugar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Carpetas anidadas sin un identificador claro&lt;/strong&gt;&lt;br&gt;
Thunder Client a veces usa &lt;code&gt;parentId&lt;/code&gt;, otras veces &lt;code&gt;_parentId&lt;/code&gt;, o simplemente anida objetos. Reconstruir la jerarquía a cualquier nivel requirió una función recursiva robusta.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Variables en URLs&lt;/strong&gt;&lt;br&gt;
Thunder Client permite &lt;code&gt;{{variables}}&lt;/code&gt; en las URLs. Si intentas parsear la URL con &lt;code&gt;new URL()&lt;/code&gt;, el script falla. Hubo que detectar y proteger estos casos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Autenticación dispersa&lt;/strong&gt;&lt;br&gt;
La autenticación puede venir en un bloque &lt;code&gt;auth&lt;/code&gt; o directamente en los headers. Además, hay que soportar Bearer, Basic y API Key (que puede ir en header o en query param).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Archivos en formdata&lt;/strong&gt;&lt;br&gt;
Los archivos no se representan como strings simples, sino como objetos con ruta o strings especiales (&lt;code&gt;@/ruta&lt;/code&gt;). Hay que identificarlos y convertirlos al formato que espera Postman.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Headers con espacios&lt;/strong&gt;&lt;br&gt;
Algunos headers exportados tenían espacios al inicio o final del nombre, lo que provocaba errores en Bruno. Hubo que limpiarlos con &lt;code&gt;trim()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BOM en archivos Windows&lt;/strong&gt;&lt;br&gt;
Los archivos exportados desde Windows incluyen una marca de orden de bytes (BOM) invisible que rompe el parseo JSON. Hubo que detectarla y eliminarla.&lt;/p&gt;
&lt;h2 id=&quot;el-script-paso-a-paso&quot;&gt;El script paso a paso&lt;/h2&gt;
&lt;h3 id=&quot;1-lee-el-archivo-de-entrada&quot;&gt;1. Lee el archivo de entrada&lt;/h3&gt;
&lt;p&gt;El script recibe como parámetro el archivo JSON exportado desde Thunder Client. Verifica que el archivo existe y que es un JSON válido. Si el archivo tiene BOM (marca de orden de bytes típica de Windows), lo elimina automáticamente para evitar errores.&lt;/p&gt;
&lt;h3 id=&quot;2-extrae-todas-las-peticiones&quot;&gt;2. Extrae todas las peticiones&lt;/h3&gt;
&lt;p&gt;Busca las peticiones en &lt;strong&gt;cualquier lugar&lt;/strong&gt; del JSON: en la raíz, dentro de carpetas, en arrays con nombres personalizados, etc. No importa cómo haya estructurado Thunder Client la exportación.&lt;/p&gt;
&lt;h3 id=&quot;3-extrae-la-estructura-de-carpetas&quot;&gt;3. Extrae la estructura de carpetas&lt;/h3&gt;
&lt;p&gt;Identifica las carpetas y subcarpetas, detectando sus identificadores (&lt;code&gt;folderId&lt;/code&gt;, &lt;code&gt;parentId&lt;/code&gt;) para reconstruir la jerarquía original, incluyendo &lt;strong&gt;subcarpetas anidadas a cualquier nivel&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;4-convierte-cada-petición-individualmente&quot;&gt;4. Convierte cada petición individualmente&lt;/h3&gt;
&lt;p&gt;Para cada petición, traduce:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;URL&lt;/strong&gt;: La segmenta en partes (host, path, query params) para Bruno, pero respeta las variables &lt;code&gt;{{variable}}&lt;/code&gt; sin intentar parsearlas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Headers&lt;/strong&gt;: Los mantiene y limpia espacios accidentales.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autenticación&lt;/strong&gt;: Soporta Bearer Token, Basic Auth y API Key (tanto en header como en query param).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cuerpo (body)&lt;/strong&gt;: Maneja JSON (con resaltado de sintaxis), formularios multipart (con detección automática de archivos) y urlencoded.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;5-construye-la-colección-postman&quot;&gt;5. Construye la colección Postman&lt;/h3&gt;
&lt;p&gt;Reconstruye la jerarquía completa usando recursividad: carpetas raíz, subcarpetas y peticiones en su lugar correspondiente. Si la exportación no incluye identificadores, usa un método alternativo como respaldo.&lt;/p&gt;
&lt;h3 id=&quot;6-guarda-el-resultado&quot;&gt;6. Guarda el resultado&lt;/h3&gt;
&lt;p&gt;Escribe el archivo JSON en el formato estándar de Postman Collection v2.1.0, listo para importar.&lt;/p&gt;
&lt;h3 id=&quot;7-muestra-estadísticas&quot;&gt;7. Muestra estadísticas&lt;/h3&gt;
&lt;p&gt;Al finalizar, informa sobre cuántas peticiones y carpetas se han convertido.&lt;/p&gt;
&lt;h2 id=&quot;el-resultado-características-principales-destacadas&quot;&gt;El resultado: características principales destacadas&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Qué hace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jerarquía completa&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Respeta carpetas y subcarpetas anidadas a cualquier nivel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Búsqueda exhaustiva&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encuentra peticiones estén donde estén en el JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Autenticación múltiple&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bearer, Basic y API Key (header o query)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Soporte para archivos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Detecta y convierte campos de tipo file en formularios&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compatibilidad con Bruno&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Segmenta el host y limpia rutas para importación perfecta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resaltado JSON&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configura los cuerpos JSON para que se vean con colores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manejo robusto&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Valida archivos, limpia BOM, muestra errores claros&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sin dependencias&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usa solo módulos nativos de Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;ejemplo-de-uso&quot;&gt;Ejemplo de uso&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; convertir-thunder-a-postman.js&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; prueba-thunder.json&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; coleccion-postman.json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Salida esperada:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;✅ Conversión completada con éxito.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;🚀 Fichero generado: coleccion-postman.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;📊 Peticiones: 24 | Carpetas: 7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;limitaciones-del-script&quot;&gt;Limitaciones del script&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Variables de colección&lt;/strong&gt;: No se importan automáticamente (deben recrearse a mano)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scripts pre-request y tests&lt;/strong&gt;: No se convierten (la API es compatible, pero hay que copiarlos manualmente)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autenticación avanzada&lt;/strong&gt;: OAuth 2.0, AWS Signature y Digest no están soportados&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/conversor-thunder-postman&quot;&gt;Repositorio desde donde descargar el conversor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.usebruno.com/&quot;&gt;Cliente Bruno&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/thunder-postman.JGQ6N9Pq_ZW8Q9F.webp"/><category>api</category><category>json</category><category>herramienta</category><category>código</category><category>javascript</category><category>node.js</category><author>JavGuerra</author></item><item><title>Oracle SQL Literal Converter</title><link>https://javguerra.github.io/blog/osqlc</link><guid isPermaLink="true">https://javguerra.github.io/blog/osqlc</guid><description>Sanitizando SQL para Oracle via web local o por línea de comandos</description><pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/osqlc.e18iygQz_1cPFJ7.webp&quot; alt=&quot;Captura de pantalla de Oracle SQL Literal Converter&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#herramienta&lt;/em&gt;, &lt;em&gt;#sql&lt;/em&gt;, &lt;em&gt;#oracle&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#responsive&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#bbdd&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Cuando trabajas con bases de datos Oracle a través de herramientas de administración como SQL*Plus, SQL Developer, Toad o PL/SQL Developer, es casi inevitable chocarse antes o después con el mismo obstáculo frustrante: la gestión de literales de texto con caracteres especiales.&lt;/p&gt;
&lt;p&gt;Quien haya ejecutado alguna vez un INSERT o UPDATE con un texto como “Ibáñez &amp;amp; Asociados” sabrá exactamente de qué hablo. Por un lado, el símbolo del ampersand (&amp;amp;) hace que SQL*Plus se detenga pidiendo interactiva y molestamente el valor para una “variable de sustitución” &amp;amp;Asociados. Por otro lado, los caracteres con acentos, la ñ, los signos de apertura (¿, ¡) o los símbolos de moneda suelen corromperse si el cliente SQL y la base de datos no comparten exactamente la misma configuración NLS o codificación de caracteres.&lt;/p&gt;
&lt;p&gt;Para solucionar este dolor de cabeza, he desarrollado OSQLC (Oracle SQL Literal Converter).&lt;/p&gt;
&lt;p&gt;Puedes descargar el script o acceder a la página web desde el: &lt;a href=&quot;https://github.com/JavGuerra/oracle-sql-literal-converter&quot;&gt;&lt;button&gt;Repositorio del conversor&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;También puedes acceder directamente al conversor web desde: &lt;a href=&quot;https://javguerra.github.io/oracle-sql-literal-converter/&quot;&gt;Oracle SQL Literal Converter&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;cómo-funciona-la-sanitización&quot;&gt;¿Cómo funciona la sanitización?&lt;/h2&gt;
&lt;p&gt;La solución técnica más limpia en Oracle consiste en aislar los caracteres problemáticos y reemplazarlos por su función nativa chr(N) equivalente (basada en el juego de caracteres ISO-8859-1 / Latin-1), concatenándolos con el resto de la cadena.&lt;/p&gt;
&lt;p&gt;OSQLC analiza el script SQL y realiza esta transformación de forma transparente. Por ejemplo, convierte esta sentencia propensa a errores:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; clientes (nombre, direccion) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Ibáñez &amp;amp; Asociados&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;C/ Ramón y Cajal, nº 45&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En este otro código, seguro y portátil para cualquier entorno Oracle:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; clientes (nombre, direccion) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;VALUES&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;Ib&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; chr(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;225&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; chr(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;241&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;ez &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; chr(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;38&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos; Asociados&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;C/ Ram&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; chr(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;243&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;n y Cajal, n&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; chr(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;186&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos; 45&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Además, el motor de procesado de OSQLC incluye características avanzadas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Respeto estricto de comentarios: Preserva intactos los comentarios de línea (–) y de bloque (/* … */) sin alterar su contenido.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Soporte para Cita Alternativa (q’…’): Procesa correctamente la sintaxis Alternative Quoting Mechanism de Oracle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Control de saltos de línea: Convierte los retornos de carro (\n y \r) en chr(10) y chr(13), evitando que se rompa la sintaxis en literales multilínea.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;dos-versiones-para-cada-tipo-de-flujo-de-trabajo&quot;&gt;Dos versiones para cada tipo de flujo de trabajo&lt;/h2&gt;
&lt;p&gt;Para hacer la herramienta lo más versátil posible, la he estructurado en dos modalidades complementarias:&lt;/p&gt;
&lt;h3 id=&quot;1-versión-cli-nodejs&quot;&gt;1. Versión CLI (Node.js)&lt;/h3&gt;
&lt;p&gt;Pensada para desarrolladores, automatizaciones o integración en canalizaciones CI/CD y scripts de despliegue. Te permite procesar archivos .sql directamente desde la terminal con un comando sencillo:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; osqlc.js&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; mi_script.sql&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; script_sanitizado.sql&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-versión-web-htmljs-standalone&quot;&gt;2. Versión Web (HTML/JS Standalone)&lt;/h3&gt;
&lt;p&gt;Diseñada para un uso diario, rápido y visual desde cualquier navegador. Se trata de una interfaz web con estilo oscuro que funciona de forma 100% local (client-side).&lt;/p&gt;
&lt;p&gt;No requiere servidores, no instala nada y garantiza la privacidad total, ya que el código SQL jamás sale de tu navegador.&lt;/p&gt;
&lt;p&gt;Entre sus características destacan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Drag &amp;amp; Drop: Arrastra directamente tus archivos .sql a la zona de carga.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Validación inteligente: Verifica que la extensión sea .sql o .txt y analiza el contenido en busca de palabras clave de SQL (como INSERT, SELECT, UPDATE), lanzando avisos si detecta un archivo incorrecto por error.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Edición y descarga directa: Puedes pegar código a mano o descargar el archivo convertido con un solo clic.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ventajas&quot;&gt;Ventajas&lt;/h2&gt;
&lt;p&gt;Con OSQLC, lo que antes requería reemplazar caracteres a mano de forma tediosa o lidiar con parámetros de sesión como SET DEFINE OFF, ahora se resuelve en un instante. Ya sea automatizando despliegues en la consola o arrastrando un archivo en la web, la sanitización queda cubierta de punta a punta.&lt;/p&gt;
&lt;p&gt;¿Te has encontrado con este problema en Oracle alguna vez? ¡Espero que la herramienta te sea tan útil en tu día a día como a mí!&lt;/p&gt;
&lt;h2 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h2&gt;
&lt;p&gt;Conoce todas las características de OSQLC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/oracle-sql-literal-converter&quot;&gt;Repositorio del conversor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.github.io/oracle-sql-literal-converter/&quot;&gt;Web de Oracle SQL Literal Converter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/osqlc.e18iygQz_1cPFJ7.webp"/><category>herramienta</category><category>sql</category><category>oracle</category><category>html</category><category>css</category><category>javascript</category><category>node.js</category><category>responsive</category><category>web</category><category>bbdd</category><category>código</category><author>JavGuerra</author></item><item><title>Conceptos Full Stack Web Developer</title><link>https://javguerra.github.io/blog/conceptos-fswd</link><guid isPermaLink="true">https://javguerra.github.io/blog/conceptos-fswd</guid><description>Ejemplo de maquetación HTML y CSS</description><pubDate>Sat, 23 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/conceptos-fswd.CgRI9xye_Zl0Fl1.webp&quot; alt=&quot;Conceptos full stack&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Maquetación elaborada con HTML 5, CSS 3 y JavaScript Vanilla que incluye formulario y es accesible y responsive.&lt;/p&gt;
&lt;h2 id=&quot;conceptos-fswd&quot;&gt;Conceptos FSWD&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Práctica final del Ramp-up del Bootcamp de FSWD&lt;/strong&gt;&lt;br&gt;
Repositorio en GitHub: &lt;a href=&quot;https://github.com/JavGuerra/conceptos-fswd&quot;&gt;JavGuerra / conceptos-fswd&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;la-página&quot;&gt;La página&lt;/h3&gt;
&lt;p&gt;Esta página corresponde a la práctica final del ramp-up del &lt;a href=&quot;/blog/beca-santander-fswd&quot;&gt;bootcamp sobre Full Stack Web Developer&lt;/a&gt; que estoy realizando en este momento.&lt;/p&gt;
&lt;p&gt;En ella se muestran algunos conceptos aprendidos en esta primera fase, e incluye «algo más» de mi propia cosecha. A continuación algunas de estas mejoras.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/conceptos-fswd/index.html&quot;&gt;&lt;button&gt;Acceder a la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;14-características-destacables-de-esta-página-web&quot;&gt;14 características destacables de esta página web&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CSS transpilado con &lt;a href=&quot;https://es.wikipedia.org/wiki/Sass&quot;&gt;Sass&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Usa Vanilla JS (JavaScript puro).&lt;/li&gt;
&lt;li&gt;La web implementa los criterios del estándar XHTML (revisado con &lt;a href=&quot;https://html5.validator.nu/&quot;&gt;Nu Html Checker&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;El diseño es adaptable (&lt;a href=&quot;https://es.wikipedia.org/wiki/Dise%C3%B1o_web_adaptable&quot;&gt;&lt;em&gt;responsive&lt;/em&gt;&lt;/a&gt;) según el dispositivo.&lt;/li&gt;
&lt;li&gt;Usa la librería y los iconos de &lt;a href=&quot;https://icons.getbootstrap.com/&quot;&gt;Bootstrap Icons&lt;/a&gt; y las fuentes de letra de &lt;a href=&quot;https://fonts.google.com/&quot;&gt;Google Fonts&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Aplica un &lt;a href=&quot;https://blog.hubspot.es/marketing/efecto-parallax&quot;&gt;efecto Paralax&lt;/a&gt; a la portada (&lt;em&gt;hero&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Implementa el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;Open Graph&lt;/a&gt; (&lt;em&gt;head&lt;/em&gt;) para la correcta inserción de la web en redes sociales.&lt;/li&gt;
&lt;li&gt;Es compatible con &lt;em&gt;Progessive Web Aplication&lt;/em&gt; (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Progressive_web_apps&quot;&gt;PWA&lt;/a&gt;) a través de fichero &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Manifest&quot;&gt;manifest.json&lt;/a&gt;, por lo que la página puede ser instalada en dispositivos móviles como una web app.&lt;/li&gt;
&lt;li&gt;Implementa técnicas de seguridad en el formulario:
&lt;ul&gt;
&lt;li&gt;Hace uso de un &lt;a href=&quot;https://es.wikipedia.org/wiki/Honeypot&quot;&gt;&lt;em&gt;Honeypod&lt;/em&gt;&lt;/a&gt;, mediante el campo “hp”, para evitar el SPAM.&lt;/li&gt;
&lt;li&gt;Hace uso de un campo oculto “dato” para evitar ataques por &lt;a href=&quot;https://es.wikipedia.org/wiki/Cross-site_scripting&quot;&gt;XSS&lt;/a&gt; y &lt;a href=&quot;https://es.wikipedia.org/wiki/Cross-site_request_forgery&quot;&gt;CRSF&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Es accesible (revisado con el complemento &lt;a href=&quot;https://wave.webaim.org/&quot;&gt;WAVE&lt;/a&gt;):
&lt;ul&gt;
&lt;li&gt;Emplea párrafos y etiquetas contextuales sólo visibles para lectores de pantalla.&lt;/li&gt;
&lt;li&gt;Hace uso de etiquetas &lt;a href=&quot;https://en.wikipedia.org/wiki/WAI-ARIA&quot;&gt;WAI-ARIA&lt;/a&gt; para describir eventos interactivos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;El fichero README.md tiene sintáxis de marcado ligero &lt;a href=&quot;https://es.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Dispone de un código QR para acceso rápido a la web a través de dispositivos móviles.&lt;/li&gt;
&lt;li&gt;Ha sido probado en los navegadores web &lt;strong&gt;Firefox&lt;/strong&gt; y &lt;strong&gt;Chrome&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Web alojada en &lt;a href=&quot;https://github.com/JavGuerra/conceptos-fswd&quot;&gt;Github&lt;/a&gt; pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;acceder-a-la-página-web&quot;&gt;Acceder a la página web&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/conceptos-fswd/img/qrcode.svg&quot; alt=&quot;icono&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/conceptos-fswd/index.html&quot;&gt;&lt;button&gt;Ir a la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/conceptos-fswd.CgRI9xye_Zl0Fl1.webp"/><category>portfolio</category><category>web</category><category>código</category><category>html</category><category>css</category><category>javascript</category><author>JavGuerra</author></item><item><title>Buscaminas en JavaScript</title><link>https://javguerra.github.io/blog/buscaminas</link><guid isPermaLink="true">https://javguerra.github.io/blog/buscaminas</guid><description>Pequeño juego online para manejo de eventos</description><pubDate>Thu, 28 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/buscaminas.BEDLb0fd_265uBE.webp&quot; alt=&quot;Buscaminas&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#bootstrap&lt;/em&gt;, &lt;em&gt;#jquery&lt;/em&gt;, &lt;em&gt;#juego&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Programé &lt;a href=&quot;https://javguerra.github.io/BuscaminasJS/index.html&quot;&gt;Buscaminas en JavaScript&lt;/a&gt; como un juego atípico que no consiste en evitar las minas, como estamos acostumbrados en los juegos de escritorio del mismo nombre, sino en hacerlas estallar.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/BuscaminasJS/index.html&quot;&gt;&lt;button&gt;Jugar a Buscaminas&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Una vez se genera el tablero con las dimensiones que deseemos, tendremos una serie de intentos para acertar la posición de las minas. Cada fallo cuenta, así como cada acierto. Termina la partida cuando se han superado el número de fallos posibles o cuando se encuentran todas las minas.&lt;/p&gt;
&lt;p&gt;Realicé este juego durante una semana, como práctica de programación de la asignatura de Desarrollo Web en Entorno Cliente de Formación Profesional de Grado Superior de Desarrollo de Aplicaciones Web (DAW).&lt;/p&gt;
&lt;p&gt;La aplicación, programada en JavaScript, usa Bootstrap y JQuery, es &lt;em&gt;cross-browser&lt;/em&gt; y compatible con navegadores antiguos, tiene diseño &lt;em&gt;responsive&lt;/em&gt;, cumple con los estándares W3C, de accesibilidad web y de accesibilidad de contenidos dinámicos (WAI-ARIA).&lt;/p&gt;
&lt;p&gt;Como ejercicio de programación, es un buen ejemplo de manejo de eventos en JavaScript para interactuar con las casillas del tablero.&lt;/p&gt;
&lt;h2 id=&quot;te-apetece-una-partidita&quot;&gt;¿Te apetece una partidita?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/BuscaminasJS/index.html&quot;&gt;&lt;button&gt;Jugar a Buscaminas&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/JavGuerra/BuscaminasJS&quot;&gt;Ver el codigo fuente en Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;PS.: La ayuda depara alguna sorpresa… pero intenta jugar sin hacer trampa.&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/buscaminas.BEDLb0fd_265uBE.webp"/><category>portfolio</category><category>web</category><category>código</category><category>css</category><category>html</category><category>javascript</category><category>bootstrap</category><category>jquery</category><category>juego</category><author>JavGuerra</author></item><item><title>Carousel con Bootstrap</title><link>https://javguerra.github.io/blog/galeria-carousel</link><guid isPermaLink="true">https://javguerra.github.io/blog/galeria-carousel</guid><description>Una pequeña galería de fotos de ejemplo</description><pubDate>Fri, 29 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/galeria-vnzla.-8Rqrg6B_Z1gNkrA.webp&quot; alt=&quot;Galería Venezuela&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#viaje&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#bootstrap&lt;/em&gt;, &lt;em&gt;#fotografía&lt;/em&gt;, &lt;em&gt;#edición&lt;/em&gt;, &lt;em&gt;#venezuela&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Las primeras veces que viajé a Venezuela quedé impactado por su belleza y las gentes que allí conocí. Me inspiró para realizar esta &lt;a href=&quot;https://badared.com/javguerra/daw/galeria/&quot;&gt;galería de fotos&lt;/a&gt; de ejemplo para la asignatura de Diseño de Interfaces Web de Formación Profesional de Grado Superior de Desarrollo de Aplicaciones Web (DAW).&lt;/p&gt;
&lt;p&gt;La galería muestra un carousel de imágenes con Boortrap y JavaScript, es &lt;em&gt;responsive&lt;/em&gt; y cumple con los estándares web y de accesibilidad.&lt;/p&gt;
&lt;p&gt;Es un buen ejercicio para mostrar las posibilidades del diseño web con HTML y CSS.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://badared.com/javguerra/daw/galeria/&quot;&gt;&lt;button&gt;visita la galería de fotos&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La foto de esta entrada es un montaje que realicé con Gimp tomando como base las tres fotos de la galería componiendo con ellas un collage y aplicando filtros de envejecido.&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/galeria-vnzla.-8Rqrg6B_Z1gNkrA.webp"/><category>portfolio</category><category>web</category><category>viaje</category><category>código</category><category>css</category><category>html</category><category>javascript</category><category>bootstrap</category><category>fotografía</category><category>edición</category><category>venezuela</category><author>JavGuerra</author></item><item><title>Summer Quiz</title><link>https://javguerra.github.io/blog/summer-quiz</link><guid isPermaLink="true">https://javguerra.github.io/blog/summer-quiz</guid><description>Un juego que obtiene sus preguntas a través de una API</description><pubDate>Tue, 21 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/summer-quiz.CeOcInKG_1DP5P4.webp&quot; alt=&quot;Summer Quiz&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#juego&lt;/em&gt;, &lt;em&gt;#accesibilidad&lt;/em&gt;, &lt;em&gt;#responsive&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;«Fun 10-question quiz to test your knowledge». &lt;strong&gt;Práctica final del módulo de JavaScript avanzado del Bootcamp de FSWD&lt;/strong&gt;, por Alejandro Rodríguez y Javier Guerra.&lt;/p&gt;
&lt;h1 id=&quot;el-juego&quot;&gt;El juego&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/summer-quiz/&quot;&gt;&lt;button&gt;Acceder al juego&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El &lt;a href=&quot;/blog/beca-santander-fswd&quot;&gt;bootcamp de FSWD&lt;/a&gt; que estoy realizando, consta de varios módulos. El de JavaScript avanzado termina ahora, y este es el ejercicio final de esta fase de mi formación.&lt;/p&gt;
&lt;p&gt;Se trata de un ejercicio que comprende todos los conceptos generales aprendidos, y que, como siempre, incluye alguna que otra cosa más allá del enunciado.&lt;/p&gt;
&lt;h1 id=&quot;enunciado&quot;&gt;Enunciado&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;El ejercicio consiste en elaborar una SPA que consulte una API de preguntas y respuestas y que cuente con tres partes: 1. bienvenida y gráficas de estadísticas, 2. mostrar diez preguntas, una a una, con sus respectivas opciones de respuesta, y 3. página de resultado.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Conceptualmente hablando, las estadísticas de la parte 1 bien podrían aparecer en la fase 3, la de resultados, pero este es, en resumidas cuentas, el enunciado.&lt;/p&gt;
&lt;p&gt;Algunas características destacables del enunciado son que la aplicación se debe ejecutar en una sola página web (SPA), que realiza consultas a una API, que guarda las puntuaciones en localStorage y que muestra estadísticas. Esta última parte, aunque accesoria, pues no se ha visto en el bootcamp, supuso un reto interesante, ya que ha dado para escribir varias entradas previas en este blog: &lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;, &lt;a href=&quot;/blog/contador-resultados&quot;&gt;Creación de un contador de resultados&lt;/a&gt;, &lt;a href=&quot;/blog/grafica-lineas&quot;&gt;Gráfica de lineas dinámica con SVG&lt;/a&gt; y &lt;a href=&quot;/blog/carga-svg&quot;&gt;Cargar SVG dinámicamente&lt;/a&gt;, todas ellas técnicas incluidas en el ejercicio.&lt;/p&gt;
&lt;p&gt;Es un buen ejercicio para practicar, e igualmente espero que puedas disfrutarlo jugándolo. Este ejercicio lo he llevado a cabo con el apoyo del compañero Alejando.&lt;/p&gt;
&lt;h1 id=&quot;características-destacables&quot;&gt;Características destacables&lt;/h1&gt;
&lt;h2 id=&quot;operativa-de-la-aplicación&quot;&gt;Operativa de la aplicación&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Aplicación de una sola página (SPA).&lt;/li&gt;
&lt;li&gt;Integración de 25 preguntas propias en un JSON. Usa una en cada partida.&lt;/li&gt;
&lt;li&gt;Hace uso de localStorage pata guardar y leer las puntuaciones.&lt;/li&gt;
&lt;li&gt;Gráficas dinámicas en SVG de elaboración propia y uso de DOM para su gestión.
&lt;ul&gt;
&lt;li&gt;Gráfica de líneas para mostrar estadísticas. Manejo del id ‘theline’.&lt;/li&gt;
&lt;li&gt;Contador visual para mostrar el resultado final del quiz. Manejo del id ‘hand’.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Animaciones CSS de gráfica de líneas y personajes.&lt;/li&gt;
&lt;li&gt;Carga de las gráficas &lt;strong&gt;SVG&lt;/strong&gt; al inicio de la app con &lt;code&gt;fetch&lt;/code&gt; para hacer uso de los &lt;code&gt;id&lt;/code&gt; que incorporan y poder así hacer cambios dinámicos. Con &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; esto no funcionaría.&lt;/li&gt;
&lt;li&gt;Los posibles errores se muestran a través de una ventana modal &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Usa JavaScript puro (Vanilla JS) sin &lt;em&gt;frameworks&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Recopila librería de funciones propia en el fichero &lt;code&gt;js/functions.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Repositorio compartido en Github y web alojada en Github pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;usabilidad&quot;&gt;Usabilidad&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;La web implementa los criterios del estándar XHTML (revisado con &lt;a href=&quot;https://html5.validator.nu/&quot;&gt;Nu Html Checker&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;El diseño es adaptable (&lt;em&gt;responsive&lt;/em&gt;) según el dispositivo.&lt;/li&gt;
&lt;li&gt;Es accesible (revisado con el complemento del navegador &lt;a href=&quot;https://wave.webaim.org/&quot;&gt;WAVE&lt;/a&gt;):
&lt;ul&gt;
&lt;li&gt;Hace uso de etiquetas &lt;strong&gt;WAI-ARIA&lt;/strong&gt; para describir eventos interactivos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tiene temática coherente y un cuidado aspecto visual trabajado con CSS.&lt;/li&gt;
&lt;li&gt;Interfaz en inglés acorde al contenido de la API.&lt;/li&gt;
&lt;li&gt;Emplea un ‘spin’ asíncrono para informar al usuario de que se está gestionado la consultas.&lt;/li&gt;
&lt;li&gt;Los botones no se activan hasta que terminan los procesos asíncronos: cargas, consultas…&lt;/li&gt;
&lt;li&gt;La selección de las opciones de cada pregunta se hace a través de botones de radio cuyo aspecto modificado con CSS simula el aspecto de botones de selección.&lt;/li&gt;
&lt;li&gt;Muestra barra de puntuaciones medias y barra de progreso del cuestionario.&lt;/li&gt;
&lt;li&gt;Implementa el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;&lt;em&gt;Open Graph&lt;/em&gt;&lt;/a&gt; (en el &lt;code&gt;head&lt;/code&gt;) para la correcta inserción de la web en RRSS.&lt;/li&gt;
&lt;li&gt;Es compatible con &lt;em&gt;Progessive Web Aplication&lt;/em&gt; (PWA) a través de fichero manifest.json, por lo que la página puede ser instalada en dispositivos móviles como una web app.&lt;/li&gt;
&lt;li&gt;Se dispone de un código QR para acceso rápido a la web a través de dispositivos móviles.&lt;/li&gt;
&lt;li&gt;Ha sido probada con los navegadores web Firefox y Chrome.&lt;/li&gt;
&lt;li&gt;Extra: La consola del navegador muestra ayuda con las respuestas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/summer-quiz/assets/img/qrcode.svg&quot; alt=&quot;QR Code&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/summer-quiz/&quot;&gt;&lt;button&gt;Acceder al juego&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/summer-quiz&quot;&gt;Repositorio / Codigo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/contador-resultados&quot;&gt;Creación de un contador de resultados&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/grafica-lineas&quot;&gt;Gráfica de lineas dinámica con SVG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/carga-svg&quot;&gt;Cargar SVG dinámicamente&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/summer-quiz.CeOcInKG_1DP5P4.webp"/><category>portfolio</category><category>web</category><category>código</category><category>html</category><category>css</category><category>javascript</category><category>juego</category><category>accesibilidad</category><category>responsive</category><author>JavGuerra</author></item><item><title>Tienda 8 bits</title><link>https://javguerra.github.io/blog/tienda-8-bits</link><guid isPermaLink="true">https://javguerra.github.io/blog/tienda-8-bits</guid><description>Proyecto de graduación del Bootcamp Full Stack Web Developer</description><pubDate>Fri, 18 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/tienda-8-bits.BGpB2fQx_Znqyrs.webp&quot; alt=&quot;Banner tienda 8 bits&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#formación&lt;/em&gt;, &lt;em&gt;#becas&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#express&lt;/em&gt;, &lt;em&gt;#react&lt;/em&gt;, &lt;em&gt;#mongodb&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#accesibilidad&lt;/em&gt;, &lt;em&gt;#responsive&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Durante el año 2022 cursé el &lt;a href=&quot;/blog/beca-santander-fswd&quot;&gt;Bootcamp de Desarrollo Web Full Stack&lt;/a&gt; que &lt;a href=&quot;https://www.becas-santander.com/es/index.html&quot;&gt;Becas Santander&lt;/a&gt; llevó a cabo en colaboración con &lt;a href=&quot;https://www.universia.net/es/empleo&quot;&gt;Fundación Universia&lt;/a&gt;, &lt;a href=&quot;https://www.indracompany.com/&quot;&gt;Indra&lt;/a&gt; y &lt;a href=&quot;https://www.thebridge.tech/&quot;&gt;The Bridge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;&lt;button&gt;Ir a la aplicación on-line&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El día 17 de noviembre finalizó la formación con un acto de entrega de diplomas on-line en el que tuve ocasión de mostrar mi proyecto final «Tienda 8 bits» junto con Alex, otro de mis compañeros, quien también expuso su proyecto.&lt;/p&gt;
&lt;p&gt;A parte de los compañeros y los profesores, asistieron al evento Alejandra Cuenca y Diego Díaz por parte de The Bridge, Cristina Soriano por Minsait/Indra, y Beatriz Arribas y Carlos Sánchez por Universia.&lt;/p&gt;
&lt;h2 id=&quot;video&quot;&gt;Video&lt;/h2&gt;
&lt;p&gt;El evento se llevó a cabo de forma presencial y on-line, y de él he rescatado el video de mi presentación que comparto a continuación.&lt;/p&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Video de presentación&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/tienda.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://youtu.be/XlswjqhxJZ8&quot;&gt;&lt;button&gt;Ver el video en YouTube&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;descripción-técnica&quot;&gt;Descripción técnica&lt;/h2&gt;
&lt;h3 id=&quot;back-end&quot;&gt;Back end&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Tecnologías empleadas&lt;/strong&gt;: Node.js + Express + MongoDB + Mongoose&lt;br&gt;
&lt;strong&gt;Módulos&lt;/strong&gt;: compression, cors, helmet, dotenv, nodemon, mongoose-paginator-v2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Características destacadas de la API&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emplea módulos ESM.&lt;/li&gt;
&lt;li&gt;Está preparada para el versionado de la API.&lt;/li&gt;
&lt;li&gt;Está preparada para el uso de BBDD MongoDB local o en remoto (config.js).&lt;/li&gt;
&lt;li&gt;Preserva la seguridad del acceso a la API con el uso del módulo helmet.&lt;/li&gt;
&lt;li&gt;Devuelve las rutas de los enlaces a las fotos y logos dinámicamente.&lt;/li&gt;
&lt;li&gt;Cuenta con documentación de la API.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;front-end&quot;&gt;Front end&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Tecnologías empleadas&lt;/strong&gt;: React + Vite, axios, react-router-dom, react-hook-form&lt;br&gt;
&lt;strong&gt;Módulos propios&lt;/strong&gt;: setSpin, inactiveBtn, compareTwoObjects&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Características destacadas de la App&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El diseño es adaptable (responsive) según el dispositivo.&lt;/li&gt;
&lt;li&gt;CSS propio. No usa frameworks.&lt;/li&gt;
&lt;li&gt;Es accesible (revisado con el complemento &lt;a href=&quot;https://wave.webaim.org/&quot;&gt;WAVE&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Utiliza fuentes de Google Font en los títulos para preservar la accesibilidad.&lt;/li&gt;
&lt;li&gt;Implementa el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;Open Graph&lt;/a&gt; para la correcta inserción de la web en RRSS.&lt;/li&gt;
&lt;li&gt;Es compatible con Progessive Web Aplication (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Progressive_web_apps&quot;&gt;PWA&lt;/a&gt;) a través de fichero &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Manifest&quot;&gt;manifest.json&lt;/a&gt;, por lo que la página puede ser instalada en dispositivos móviles como una web app.&lt;/li&gt;
&lt;li&gt;Ha sido probada con los navegadores web Firefox y Chrome.&lt;/li&gt;
&lt;li&gt;Tratamiento de imágenes con software libre: Gimp e InkScape.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;fuentes&quot;&gt;Fuentes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Wikipedia&lt;/li&gt;
&lt;li&gt;Enciclopedia «Mi Computer», editorial Delta, 1984.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;licencias&quot;&gt;Licencias&lt;/h3&gt;
&lt;p&gt;Sobre el código fuente: &lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/LICENSE&quot;&gt;GNU GENERAL PUBLIC LICENSE Version 3&lt;/a&gt;&lt;br&gt;
Sobre el contenido de la web: &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0/es/&quot;&gt;(CC) BY-SA 3.0&lt;/a&gt;&lt;br&gt;
Sobre las fotos: Son propiedad de sus respectivos autores.&lt;br&gt;
Sobre las fuentes de letra: &lt;a href=&quot;https://fonts.google.com/&quot;&gt;Google Fonts&lt;/a&gt;&lt;br&gt;
Sobre los iconos: &lt;a href=&quot;https://heroicons.com/&quot;&gt;Heroicons&lt;/a&gt;&lt;br&gt;
Material usado sin ánimo de lucro bajo criterios didácticos y formativos.&lt;/p&gt;
&lt;h3 id=&quot;acceder-a-la-aplicación&quot;&gt;Acceder a la aplicación&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/JavGuerra/tienda-8-bits/0d3d3a968787a438379d003fe31aaede91011e40/qrcode.svg&quot; alt=&quot;Código QR&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;&lt;button&gt;Ir a la aplicación on-line&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://javguerra.badared.com/proyecto/tienda8bits/&quot;&gt;Aplicación on-line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api-tienda8bits.up.railway.app/&quot;&gt;Documentación de la API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/enunciado.pdf&quot;&gt;Enunciado de la práctica en PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits&quot;&gt;Repositorio en GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/XlswjqhxJZ8&quot;&gt;Video de la presentación en YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/presentacion.pdf&quot;&gt;Presentación en PDF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Artículos informativos elaborados por el autor relacionados con esta práctica&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/populate-paginate-fitrado&quot;&gt;Usando populate con paginate y filtrando los resultados&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/rutas-dinamicas-imagenes-mongodb&quot;&gt;Generar enlaces dinámicos de imágenes almacenadas en MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/ordenacion-react&quot;&gt;Ordenando resultados en React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/spinner-loader-asincrono&quot;&gt;Spinner loader asíncrono&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/tienda-8-bits.BGpB2fQx_Znqyrs.webp"/><category>portfolio</category><category>web</category><category>formación</category><category>becas</category><category>node.js</category><category>express</category><category>react</category><category>mongodb</category><category>javascript</category><category>accesibilidad</category><category>responsive</category><author>JavGuerra</author></item><item><title>Códice</title><link>https://javguerra.github.io/blog/codice</link><guid isPermaLink="true">https://javguerra.github.io/blog/codice</guid><description>Mi git-blog sobre programación y formación TIC</description><pubDate>Wed, 21 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/codice.CdsWx0aT_ZlfDvy.webp&quot; alt=&quot;Códice&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#astro&lt;/em&gt;, &lt;em&gt;#ssg&lt;/em&gt;, &lt;em&gt;#tailwind&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;, &lt;em&gt;#typescript&lt;/em&gt;, &lt;em&gt;#zod&lt;/em&gt;, &lt;em&gt;#node.js&lt;/em&gt;, &lt;em&gt;#markdown&lt;/em&gt;, &lt;em&gt;#responsive&lt;/em&gt;, &lt;em&gt;#accesibilidad&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Hacia tiempo que quería darle un giro a mi anterior &lt;a href=&quot;/blog/hola-mundo&quot;&gt;git-blog elaborado con Jekill&lt;/a&gt;. Hace un mes me topé con &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;, un SSG en JavaScript/TypeScript bajo Node.js, que cuenta con una excelente documentación, y que además incluye un tutorial para hacer un blog. Esto terminó de decidirme para realizar el cambio que ahora presento.&lt;/p&gt;
&lt;h1 id=&quot;retos&quot;&gt;Retos&lt;/h1&gt;
&lt;p&gt;Para llevar a cabo el desarrollo de un nuevo blog personalizado, se me presentaban dos retos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Realizar la aplicación para que fuera operativa al menos con la mayoría de funcionalidades que ya tenía en el anterior blog.&lt;/li&gt;
&lt;li&gt;Migrar las entradas del blog anterior a la nueva estructura de la aplicación, lo que además implicaba repensar esta estructura.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;la-aplicación&quot;&gt;La aplicación&lt;/h2&gt;
&lt;p&gt;Elaborar la aplicación fue realmente sencillo. Siempre hay atascos, pero con la documentación, el tutorial, el Discord de Astro, los videos de YouTube y la IA, fueron subsanándose. El proyecto ha sido el mejor aprendizaje posible.&lt;/p&gt;
&lt;p&gt;Tres cosas me han llevado algo de tiempo:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Extender la colección de posts usando el esquema RSS.&lt;/li&gt;
&lt;li&gt;Utilizar el componente «Image» de Astro.&lt;/li&gt;
&lt;li&gt;JavaScript/TypeScript no funciona como se espera usando transiciones.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Lo relativo a la colección es lógico, porque estaba usando conceptos nuevos y aprendiendo a usar la &lt;a href=&quot;https://zod.dev/&quot;&gt;biblioteca Zod&lt;/a&gt; para definir y validar el esquema de los datos de las colección de entradas del blog. Zod permite validar el &lt;code&gt;frontmatter&lt;/code&gt; o cabecera de cada post para que no falte nada. La idea era partir del esquema &lt;code&gt;rssSchema&lt;/code&gt; y extenderlo para que incluyese algunos datos no contemplados, como por ejemplo el &lt;code&gt;coverImage&lt;/code&gt; o los &lt;code&gt;tags&lt;/code&gt; (&lt;em&gt;Ver fichero /src/content/config.ts&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Pero confieso que el uso del componente Image me ha dado algún quebradero de cabeza, posiblemente relacionado con el schema mencionado, pues no me ha sido posible usar indistintamente imágenes con rutas relativas o rutas absolutas en los encabezados de las entradas. El problema tiene que ver con el atributo &lt;code&gt;src&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Si bien Image permite indicar una ruta relativa (/public) o remota (https), cuando se trata de usar la carpeta /src/assets surgen los problemas. La solución pasa por importar las imágenes, pero ¿qué ocurre cuando se ha de importar una colección de imágenes, para, por ejemplo, el listado de los proyectos del portafolio?&lt;/p&gt;
&lt;p&gt;Mi opción consiste en crear un arreglo con todas las imágenes importadas usando &lt;code&gt;import.meta.glob()&lt;/code&gt;, y luego acceder a cada elemento del arreglo referenciado por su ruta, como se muestra aquí:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; portfolio &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;@/content/_portfolio.json&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// proyectos con sus respectivas rutas de imagenes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; images&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;glob&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;@/assets/portfolio/*&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, { eager: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; projects&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; portfolio.projects.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;project&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; image&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; images[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;`/src/assets/portfolio/${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;project&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;img&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}`&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Record&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;any&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;project, image }; &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// a cada proyecto se le añade la imagen importada&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;projects.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;project&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Image&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{project.image.default} &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;alt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{project.alt} &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;inferSize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Este ejemplo simplificado mostrará la lista de imágenes asociadas a los proyectos.&lt;/p&gt;
&lt;h2 id=&quot;la-migración&quot;&gt;La migración&lt;/h2&gt;
&lt;p&gt;&lt;img __ASTRO_IMAGE_=&quot;{&amp;quot;alt&amp;quot;:&amp;quot;Códice versión Jekill&amp;quot;,&amp;quot;src&amp;quot;:&amp;quot;@/assets/img/codice-jekill.png&amp;quot;,&amp;quot;index&amp;quot;:0}&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Versión previa del blog en Jekill&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Tras conseguir que todo funcionase, llegó el turno de la migración, que pensaba que sería complicada, pero sólo fue laboriosa.&lt;/p&gt;
&lt;p&gt;Haciendo uso del filtrado de contenido del IDE fui cambiando los enlaces de Jekill de las referencias entre las distintas entradas, y creando el nuevo encabezado (&lt;code&gt;frontmatter&lt;/code&gt;) de cada entrada escrita en Markdown.&lt;/p&gt;
&lt;p&gt;A medida que este cambio se iba realizando fue necesario ir adaptando los estilos de texto haciendo uso de &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt; y su plugin &lt;a href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot;&gt;Typography&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Por último, como decidí incluir las transiciones de Astro, me topé con un problema curioso. Para activar o desactivar el menú hamburguesa uso JavaScript. La primera vez que se usa, funciona, pero en los siguientes casos, deja de hacerlo. Lo mismo ocurre con el botón «Volver».&lt;/p&gt;
&lt;p&gt;He tenido que hacer una comprobación para recargar siempre el evento click en ambos casos. Ver /src/components/Hamburger.astro y /src/components/ButtonLink.astro respectivamente.&lt;/p&gt;
&lt;p&gt;Lo mejor de todo es que ha sido divertido hacerlo, y conocer Astro, esta nueva y muy potente herramienta que creo que va a dar mucho juego. Quedan por delante innumerables mejoras y actualizaciones, por lo que la diversión continúa.&lt;/p&gt;
&lt;h1 id=&quot;características&quot;&gt;Características&lt;/h1&gt;
&lt;p&gt;La aplicación cuenta con las siguientes secciones: portada, sobre mi, porfolio, blog, temas y enlaces recomendados. Hace uso de las características avanzadas de Astro, y también:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Incluye RSS de contenidos&lt;/li&gt;
&lt;li&gt;Enlaza con la API de Mastodon&lt;/li&gt;
&lt;li&gt;Implementa sitemap para SEO&lt;/li&gt;
&lt;li&gt;Incluye estadísticas del sitio&lt;/li&gt;
&lt;li&gt;Integra Disqus para comentarios&lt;/li&gt;
&lt;li&gt;Implementa un buscador&lt;/li&gt;
&lt;li&gt;Usa tema de color claro/oscuro automático&lt;/li&gt;
&lt;li&gt;Realiza transiciones de página&lt;/li&gt;
&lt;li&gt;Es accesible&lt;/li&gt;
&lt;li&gt;Es responsive&lt;/li&gt;
&lt;li&gt;Usa TypeScript&lt;/li&gt;
&lt;li&gt;Contiene etiquetado Open Graph&lt;/li&gt;
&lt;li&gt;Es compatible con PWA&lt;/li&gt;
&lt;li&gt;Consigue una calificación de carbono «A» (&lt;a href=&quot;https://www.websitecarbon.com/website/javguerra-github-io/&quot;&gt;ver&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;licencias&quot;&gt;Licencias&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sobre los contenidos (entradas del blog): &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0/deed.es&quot;&gt;CC BY-SA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sobre el código fuente: &lt;a href=&quot;https://github.com/JavGuerra/tienda-8-bits/blob/main/LICENSE&quot;&gt;GNU GENERAL PUBLIC LICENSE Version 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Iconos: &lt;a href=&quot;https://www.svgrepo.com/collection/solar-linear-icons/&quot;&gt;Solar Linear Icons&lt;/a&gt; en SVG Repo&lt;/li&gt;
&lt;li&gt;Tipografía: &lt;a href=&quot;https://www.fontsquirrel.com/fonts/blogger-sans&quot;&gt;Blogger_Sans-Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;saber-más&quot;&gt;Saber más&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/api-mastodon&quot;&gt;Accediendo a la API de Mastodon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JavGuerra/javguerra.github.io&quot;&gt;Repositorio en GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/hola-mundo&quot;&gt;git-blog anterior elaborado con Jekill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://es.wikipedia.org/wiki/Generador_de_sitios_est%C3%A1ticos&quot;&gt;SSG&lt;/a&gt;, &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; y &lt;a href=&quot;https://es.wikipedia.org/wiki/Astro_(framework)&quot;&gt;Astro en Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt; y &lt;a href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot;&gt;Typography&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zod.dev/&quot;&gt;Biblioteca Zod&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/es/tutorial/0-introduction/&quot;&gt;Construye tu primer blog con Astro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://youtu.be/sOXW0ZnJxbQ?si=yLRwfY4lyOMaHypc&quot;&gt;Curso de Astro, por Fazt, en Youtube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ir-a-la-página&quot;&gt;Ir a la página&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://javguerra.github.io/&quot;&gt;&lt;img src=&quot;/assets/img/qr.svg&quot; alt=&quot;Código QR&quot;&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://javguerra.github.io/&quot;&gt;https://javguerra.github.io/&lt;/a&gt;&lt;/p&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/codice.CdsWx0aT_ZlfDvy.webp"/><category>portfolio</category><category>web</category><category>código</category><category>astro</category><category>ssg</category><category>tailwind</category><category>javascript</category><category>typescript</category><category>zod</category><category>node.js</category><category>markdown</category><category>responsive</category><category>accesibilidad</category><author>JavGuerra</author></item><item><title>Batman para QL</title><link>https://javguerra.github.io/blog/batman-ql</link><guid isPermaLink="true">https://javguerra.github.io/blog/batman-ql</guid><description>Web del lanzamiento de un remake para QL del conocido juego de los 80.</description><pubDate>Fri, 06 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://javguerra.github.io/_astro/batmanql.DQI2tAmB_ZOVqUQ.webp&quot; alt=&quot;Banner del lanzamiento de Batman para QL&quot; style=&quot;max-width: 100%; height: auto;&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Etiquetas:&lt;/strong&gt; &lt;em&gt;#sinclair ql&lt;/em&gt;, &lt;em&gt;#portfolio&lt;/em&gt;, &lt;em&gt;#web&lt;/em&gt;, &lt;em&gt;#código&lt;/em&gt;, &lt;em&gt;#html&lt;/em&gt;, &lt;em&gt;#css&lt;/em&gt;, &lt;em&gt;#javascript&lt;/em&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;El 10 de mayo de 2025 fue lanzado «Batman QL», un remake del «Batman» de 1986 de Jon Ritman y Bernie Drummond para el retro-ordenador &lt;a href=&quot;/blog/sinclair-ql&quot;&gt;Sinclair QL&lt;/a&gt; a cargo de Joan Gayón. Yo hice mi parte elaborando la landing page del lanzamiento que presento en esta entrada.&lt;/p&gt;
&lt;p&gt;Joan es un compañero de nuestro grupo de aficionados en torno a esta máquina, y su juego ha causado sensación, siendo, hoy por hoy, la mejor versión de este clásico para un ordenador de los 80, y el mejor juego para QL de todos los tiempos, tanto por su jugabilidad como por sus gráficos.&lt;/p&gt;
&lt;h1 id=&quot;la-página-de-lanzamiento&quot;&gt;La página de lanzamiento&lt;/h1&gt;
&lt;p&gt;Visita la página para conocer más sobre este juego.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://badared.com/badaman/ql/batman&quot;&gt;&lt;button&gt;Acceder a la página web&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;características&quot;&gt;Características&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiidioma&lt;/strong&gt;. La web está disponible tanto en español como inglés. Un fichero index.php determina, en función del navegador, si el visitante habla español o no, y redirige a una u otra página.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;En sintonía con el aspecto del juego&lt;/strong&gt;. El menú de la página simula el menú del juego, y el colorido y la temática son afines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responsive&lt;/strong&gt;, Se adapta a distintos dispositivos como móviles (&lt;em&gt;movile first&lt;/em&gt;), tabletas y pantallas de ordenador.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accesible&lt;/strong&gt;. funciona en lectores de pantalla por voz.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Icono para moviles&lt;/strong&gt;. Es compatible con &lt;em&gt;Progessive Web Aplication&lt;/em&gt; (&lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Progressive_web_apps&quot;&gt;PWA&lt;/a&gt;) a través de fichero &lt;a href=&quot;https://developer.mozilla.org/es/docs/Web/Manifest&quot;&gt;manifest.json&lt;/a&gt;, por lo que la página puede ser instalada en dispositivos móviles como una web app.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Información para redes sociales&lt;/strong&gt;, Implementa el protocolo &lt;a href=&quot;https://ogp.me/&quot;&gt;Open Graph&lt;/a&gt; para la correcta inserción de la web en redes sociales.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sin frameworks&lt;/strong&gt;. No emplea frameworks de JavaScript o CSS, sino código propio, haciendo más liviana la carga.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estadísticas&lt;/strong&gt;. La web enlaza un servicio de estadísticas de visitas.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;la-presentación&quot;&gt;La presentación&lt;/h1&gt;
&lt;p&gt;Además de en las redes sociales, tanto el juego como la página fueron presentados el día 17 de mayo de 2025 en el &lt;a href=&quot;/blog/mhc&quot;&gt;Museo de Historia de la Computación&lt;/a&gt;, con un significativo alcance para lo que supone una comunidad como esta.&lt;/p&gt;
&lt;p&gt;Se hicieron eco del lanzamiento las principales web del sector, como Amigawave, Indie Retro News, El Mundo del Spectrum, Computer Emuzone, Spectrum Computing, El Spectrumero, Retroinvaders, Perfect Pixel, Vintage is the new old, spectrumandretronews, Modern Retro Gaming News, De Vuego, Retro8bitshop, Planet Sinclair, entre otras.&lt;/p&gt;
&lt;p&gt;En la primera semana se recibieron más de 1.200 visitas al Blog y la web desde 42 países, más de 3.300 visitas a los posts en foros retro, y se contabilizaron más de 700 descargas.&lt;/p&gt;
&lt;p&gt;Ver la &lt;a href=&quot;/assets/doc/Batman-presenta.pdf&quot;&gt;presentación del juego en PDF&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;el-juego&quot;&gt;El juego&lt;/h1&gt;
&lt;p&gt;Puedes obtener información sobre el juego, sus características y modo de uso en su &lt;a href=&quot;https://badared.com/badaman/ql/batman&quot;&gt;web&lt;/a&gt; o en su &lt;a href=&quot;https://badared.com/badaman/ql/batman/assets/doc/Batman-es.pdf&quot;&gt;manual&lt;/a&gt; disponible para descarga, y también en el artículo &lt;a href=&quot;https://sinclairqles.wordpress.com/2025/05/10/batmanql-joan-gayon-2025/&quot;&gt;Batman, Joan Gayón (2025)&lt;/a&gt; en nuestro blog sobre QL.&lt;/p&gt;
&lt;p&gt;Te adelanto que se trata de una copia fiel pixel a pixel del original, mejorada con mayor colorido, Si autor lo ha llevado a cabo como un reto personal y un homenaje que ha presentado grandes desafíos técnicos.&lt;/p&gt;
&lt;p&gt;Dispones de una versión preparada para emulador en Windows que puedes descargar.&lt;/p&gt;
&lt;h1 id=&quot;enlaces&quot;&gt;Enlaces&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://badared.com/badaman/ql/batman&quot;&gt;Acceder a la página web del juego&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://batmanql.goatcounter.com/&quot;&gt;Estadísticas de acceso público&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/assets/doc/Batman-presenta.pdf&quot;&gt;Presentación del juego en PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/sinclair-ql&quot;&gt;Info sobre Sinclair QL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://javguerra.github.io/_astro/batmanql.DQI2tAmB_ZOVqUQ.webp"/><category>sinclair ql</category><category>portfolio</category><category>web</category><category>código</category><category>html</category><category>css</category><category>javascript</category><author>JavGuerra</author></item></channel></rss>