Imagina que estás utilizando un elemento select para navegar entre páginas. Por regla general, el select volverá a su opción por defecto tras cargar otra vez la página. En este artÃculo veremos cómo mantener la opción que ha seleccionado el usuario, asegurándonos de que cualquier página que haya escogido el usuario permanezca seleccionada incluso una vez haya aterrizado en la nueva. Para verlo, crearemos un proyecto con algunas páginas estáticas. ¡Empecemos!
Estructura del proyecto
La estructura del proyecto es tal que asÃ:Â
animals.html
cars.html
index.html
motorcycles.html
plants.html
assets/Â Â Â
  css/     Â
     style.css  Â
  img/     Â
     down.svg  Â
  js/     Â
     main.jsÂ
El HTMLÂ
Dentro de cada página HTML habrá un elemento select.Â
<select class="myselect"> <option data-url="index.html">All</option> <option data-url="animals.html">Animals</option> <option data-url="cars.html">Cars</option> <option data-url="motorcycles.html">Motorcycles</option> <option data-url="plants.html">Plants</option> </select>
Â
Cada opción está asociada a una página estática. El enlace a cada página se almacena en el atributo data-url.Â
En un caso real nuestro menú select tendrÃa que contener las categorÃas de todas las publicciones del blog. Asà que imaginemos que, al seleccionar la opción All, aparecen todas las publicaciones del blog. Luego, si seleccionamos la opción Animals, aparecerán las publicaciones que pertenecen a la categorÃa Animales, y asà sucesivamente.Â
El atributo data-url podrÃa contener una url absoluta en lugar de una relativa, como esta:Â
<option data-url="http://yoursite.com/category/animals">Animals</option>
El CSSÂ
Por defecto, existen limitaciones en el navegador con respecto a los estilos que podemos aplicar a un elemento select. Con eso en mente, vamos a agregar unas cuantas reglas CSS que mejorarán la apariencia del select en todos los navegadores:Â
.myselect { -webkit-appearance: none; -moz-appearance: none; appearance: none; width: 100%; max-width: 400px; padding: 6px 12px; border-radius: 4px; border: 1px solid #cbd1d8; font-size: 1rem; line-height: 1.5; background: #fff url(../img/down.svg) no-repeat center right 12px / 18px 18px; transition: all .2s ease-in-out; } /*IE*/ .myselect::-ms-expand { display: none; } .myselect:focus { outline: 0; border-color: #7bbaff; box-shadow: 0 0 0 3px rgba(0, 121, 250, .3); }
Â
El JavaScriptÂ
Cada vez que se selecciona una opción, debe cargarse la página relacionada y la opción de destino debe marcarse como seleccionada. Para ello tenemos que hacer lo siguiente:
- Recuperar la URL de la página relacionada con la opción seleccionada y forzar una redirección a esta página.    Â
- Recorrer todas las opciones, tomar su atributo data-url, y comprobar si este valor es parte de la url de la página o no. Si es asÃ, marcamos la opción relacionada como seleccionada y saltamos fuera del bucle.Â
Aquà está el código requerido:Â
const select = document.querySelector(".myselect"); const options = document.querySelectorAll(".myselect option"); // 1 select.addEventListener("change", function() { const url = this.options[this.selectedIndex].dataset.url; if(url) { location.href = url; } }); // 2 for(const option of options) { const url = option.dataset.url; if(location.href.includes(url)) { option.setAttribute("selected", ""); break; } }
Â
Como he dicho antes, en un proyecto real, el valor del atributo data-url podrÃa ser una url absoluta. En tal escenario, podemos actualizar la segunda parte de nuestro código de la siguiente manera:Â
// 2 for(const option of options) { const url = option.dataset.url; if(url === location.href) { option.setAttribute("selected", ""); break; } }
Â
Ojo, en lugar de agregar el atributo selected a la opción correspondiente a través de JavaScript, podrÃamos haberlo establecido estáticamente en el HTML. Entonces, por ejemplo, en la página Animals podrÃamos haber agregado el atributo selected a la opción Animals. Sin embargo, este no es un enfoque flexible porque en un sitio dinámico todas las opciones (que podrÃan contener categorÃas de publicaciones) posiblemente compartirán la misma página / plantilla.