Ya expliqué cómo consumir la API de Wikipedia por separado. Hoy veremos un ejemplo de un buscador de Wikipedia.
Lo he hecho con mi framework Javascript favorito hasta el momento: VueJS. Encima de VueJS corre VuetifyJS que simplemente proporciona componentes con el estilo Material Design.
Vamos allá.
Ya ni sé por qué le decimos a cualquier cosa “app” pero no encuentro otro nombre para nombrar las cosas. En fin, si quieres ver el proyecto terminado aquí dejo un link a codepen.
Bueno, vamos a explicar cosa por cosa.
Quise hacerla como el buscador de Google pero al final salió otra cosa y, como me gustó, así la dejé. Puse una imagen de Wikipedia, abajo un campo para introducir texto, luego un botón para obtener un artículo aleatorio y finalmente un seleccionador de idiomas.
Si en la app cambiamos el idioma, veremos que la leyenda de Artículo aleatorio y Comienza a escribir cambian. Así se ve en español:
Así en inglés:
Lo mismo para otros idiomas. Cabe aclarar que saqué todo del traductor de Google jaja, así que puede que haya errores. En fin, eso no importa; lo que importa es cómo se cambia el texto.
Para ello, tenemos que remontarnos a los idiomas soportados. Puse estos:
data: () => {
return {
idiomas: [{
abreviacion: "es",
idioma: "Español"
},
{
abreviacion: "en",
idioma: "English"
}, {
abreviacion: "de",
idioma: "Deutsch"
}, {
abreviacion: "fr",
idioma: "Français"
}, {
abreviacion: "ru",
idioma: "русский"
}, {
abreviacion: "it",
idioma: "italiano"
},
],
}
},
Y entonces, en los valores calculados de la app puse estos métodos:
computed: {
rutaArticuloAleatorio() {
if (!this.idiomaSeleccionado) return "";
return `https://${this.idiomaSeleccionado.abreviacion}.wikipedia.org/wiki/Special:Random`;
},
rutaArticulo() {
if (!this.idiomaSeleccionado || !this.resultadoSeleccionado) return "";
return `https://${this.idiomaSeleccionado.abreviacion}.wikipedia.org/?curid=${this.resultadoSeleccionado.pageid}`;
},
leyendaArticuloAleatorio() {
if (!this.idiomaSeleccionado) return "";
return {
"es": "Artículo aleatorio",
"en": "Random article",
"de": "Zufälliger Artikel",
"fr": "Article aléatoire",
"ru": "Случайная статья",
"it": "Articolo casuale",
}[this.idiomaSeleccionado.abreviacion];
},
labelBusqueda() {
if (!this.idiomaSeleccionado) return "";
return {
"es": "Comienza a escribir",
"en": "Start typing",
"de": "Beginnen Sie zu tippen",
"fr": "Commencez à taper",
"ru": "Начните вводить текст",
"it": "Inizia a digitare",
}[this.idiomaSeleccionado.abreviacion];
},
},
Por el momento fijémonos en los dos últimos. Dependiendo del idioma seleccionado, regresan un valor. Es decir, es un objeto y accedemos a una de sus propiedades. Dicha propiedad puede ser “es”, “en”, etcétera.
Lo mismo aplica para la URL de búsqueda. Podemos ver que utilizamos el poder de las backticks en Javascript para regresar una URL dependiendo del idioma seleccionado.
¿y en qué momento seleccionamos un idioma por defecto? en el método mounted del ciclo de vida de nuestra aplicación:
mounted() {
this.idiomaSeleccionado = this.idiomas[0];
},
Seleccionamos el primer idioma que encontremos, ya después el usuario podrá elegir otro, y cuando eso pase, todo se refrescará automáticamente gracias a la reactividad de VueJS.
La parte más importante de la aplicación. Detecta cuando empezamos a escribir y busca.
Con watch, vigilamos cuando cambie “busqueda”. En caso de que cambie y de que tenga un valor que no sea falso, buscaremos. Como vemos llamamos al método buscar.
watch: {
busqueda(termino) {
termino && this.buscar(termino);
},
},
Ok. Una vez que detectamos los cambios, hacemos un debounce. Un debounce es algo así (al menos en js) como llamar a una función una única vez, en el intervalo dado. Para no complicarme las cosas utilicé lodash.
Explicando de mejor manera, si no hiciéramos un debounce, la función se llamaría el número de veces que el usuario escribiera. Si quería buscar “hola”, la función se llamaría con “h”, luego con “ho”, y así, 4 veces.
Al usuario no le importaba buscar “h” ni “ho” o “hol”, sino “hola”, pero sin querer llamó a la función 4 veces. Esto cargaría al servidor. Para ello, hacemos que sin importar cuántas veces se llame la función, sólo se llame después de medio segundo (500 milisegundos).
De esta manera, el usuario podrá buscar y su búsqueda regresará en 500 milisegundos; cosa que ni notará.
Cuando buscamos, simplemente llamamos a la url de la api y le concatenamos el valor de la búsqueda. Esperamos a que hayan resultados y primeramente eliminamos las etiquetas HTML, luego hacemos un JSON.parse para decodificar la cadena en formato JSON y finalmente establecemos los resultados de la búsqueda a respuesta.query.search.
methods: {
baseUrl() {
return `https://${this.idiomaSeleccionado.abreviacion}.wikipedia.org/w/api.php?action=query&list=search&srprop=snippet&format=json&origin=*&utf8=&srsearch=`
},
buscar: _.debounce(function() {
let url = `${this.baseUrl()}${encodeURIComponent(this.busqueda)}`;
let esto = this;
fetch(url)
.then(function(respuesta) {
return respuesta.text().then(function(texto) {
return esto.quitarHTML(texto);
});
})
.then(function(jsonValido) {
let respuesta = JSON.parse(jsonValido),
resultados = respuesta.query.search;
esto.resultadosBusqueda = resultados;
});
}, 500),
quitarHTML(html) {
return html.replace(/<\/?[^>]+>/gi, '');
}
VueJS detectará el cambio y entonces mostrará la lista de resultados:
Cuando hacemos click, el objeto clickeado pasa a ser el valor de la variable resultadoSeleccionado.
Como dijimos arriba, el resultado pasa a ser parte de nuestra app. Y para ello lo mostramos en la vista:
<template style="text-align:justify;" v-if="resultadoSeleccionado">
<br>
<span class="headline">{{resultadoSeleccionado.title}}</span>
<p>{{resultadoSeleccionado.snippet}}...</p>
<v-btn target="_blank" :href="rutaArticulo" flat color="light-green"><v-icon>open_in_new</v-icon></v-btn>
</template>
Utilizamos v-if para ocultarlo en caso de que no seleccionen nada. Mostramos el título y el snippet. También un botón que en realidad es un link, y que dirige al enlace que tenga la variable rutaArticulo. Esta variable ya fue vista anteriormente, allá arriba.
Igualmente sólo es un link-botón definido así:
<v-btn target="_blank" :href="rutaArticuloAleatorio" flat color="light-green">{{leyendaArticuloAleatorio}} <v-icon>cached</v-icon></v-btn>
Cuyo href es la variable rutaArticuloAleatorio que ya vimos más arriba.
Sólo hace falta mencionar la equis que aparece en la barra de búsqueda, cuya función es limpiar el campo de texto. Viene por defecto en el componente, así que no hace falta explicarla.
Espero que haya explicado todo y que no queden dudas. De todos modos, puedes dejar un comentario si algo no quedó claro. Aquí dejo el código fuente, pues es la mejor manera de estudiar el funcionamiento. Nos vemos luego.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.
Ver comentarios