Tengo una lista de selección personalizada que hice con casillas de verificación y elementos de etiqueta. Luego agregué un pequeño script JS que cambia las opciones al hacer clic. Funciona perfectamente, excepto que no puede cerrarlo al hacer clic fuera de él o de sus elementos secundarios. Traté de usar el detector de eventos (comentado en el fragmento) para rastrear si el clic se hizo fuera y si es así, cambie el estado de la casilla de verificación en 'falso' y funcionó un poco, sin embargo, rompe la funcionalidad original de la casilla de verificación y no puedes ahora ciérrelo de cualquier forma excepto haciendo clic fuera de él. ¿Hay alguna manera de arreglar esto?
//SELECT FROM LIST function selectList(id) { let selected = document.getElementById('selected'); selected.innerHTML = id; } //BREAKS CHECKBOX //window.addEventListener('mouseup', function(event){ // let checkbox = document.getElementById('checkbox'); // if (event.target != checkbox && event.target.parentNode != checkbox){ // checkbox.checked = false; // } // }); .btn { display: block; width: 100px; height: 50px; text-align: center; color: white; background: black; border-radius: 15px; line-height: 50px; cursor: pointer; user-select: none; position: relative; } .btn:active { background: grey; } .btn ul { display: none; list-style: none; color: black; flex-direction: column; margin: 0; padding: 2.5px 5px; left: 0; top: 50px; background: grey; border-radius: 15px; position: absolute; } .btn ul li { display: block; width: 90px; height: 35px; line-height: 35px; background: black; border-radius: 15px; color: white; margin: 2.5px 0; } .btn ul li:active { background: grey; } /* CHECKBOX CHEKCED */ #checkbox:checked + .btn ul { display: flex; } <input type="checkbox" id="checkbox"> <label class="btn" for="checkbox"> <span id="selected">SELECT</span> <ul> <li onclick="selectList('Opt1')">Opt1</li> <li onclick="selectList('Opt2')">Opt2</li> <li onclick="selectList('Opt3')">Opt3</li> </ul> </label>Su estrategia usa css para diseñar el estado del menú desplegable según el valor de la opción de radio.
Por lo tanto, no hay un controlador de eventos en su lugar que ya capture ese punto en el tiempo y el único enfoque para cerrar el menú desplegable cuando hace clic afuera fue usar un controlador de eventos de clic en el documento principal y verificar que el elemento que desencadena el evento sea de tipo HTML. No es el mejor enfoque de hecho. (Edité la pregunta para usar un mejor enfoque... ahora hay un contenedor que tiene el dropdown de clases y event.target se verifica para tener un ancestro con dicha clase para entender si el clic se disparó desde el menú desplegable o fuera de él)
document.addEventListener('click', function(event){ if(event.target.closest('.dropdown') === null){ document.querySelector('#checkbox').checked = false; } });De todos modos, una vez allí, la lógica simplemente fuerza la opción de radio a desmarcarse y restaurar el estado de colapso del menú desplegable.
//SELECT FROM LIST function selectList(id) { let selected = document.getElementById('selected'); selected.innerHTML = id; } document.addEventListener('click', function(event){ if(event.target.closest('.dropdown') === null){ document.querySelector('#checkbox').checked = false; } }); //BREAKS CHECKBOX //window.addEventListener('mouseup', function(event){ // let checkbox = document.getElementById('checkbox'); // if (event.target != checkbox && event.target.parentNode != checkbox){ // checkbox.checked = false; // } // }); .btn { display: block; width: 100px; height: 50px; text-align: center; color: white; background: black; border-radius: 15px; line-height: 50px; cursor: pointer; user-select: none; position: relative; } .btn:active { background: grey; } .btn ul { display: none; list-style: none; color: black; flex-direction: column; margin: 0; padding: 2.5px 5px; left: 0; top: 50px; background: grey; border-radius: 15px; position: absolute; } .btn ul li { display: block; width: 90px; height: 35px; line-height: 35px; background: black; border-radius: 15px; color: white; margin: 2.5px 0; } .btn ul li:active { background: grey; } /* CHECKBOX CHEKCED */ #checkbox:checked + .btn ul { display: flex; } <div class="dropdown"> <input type="checkbox" id="checkbox"> <label class="btn" for="checkbox"> <span id="selected">SELECT</span> <ul> <li onclick="selectList('Opt1')">Opt1</li> <li onclick="selectList('Opt2')">Opt2</li> <li onclick="selectList('Opt3')">Opt3</li> </ul> </label> </div>