I have a custom select list which I did with checkbox and label elements. Then I added a little JS script that changes options on click. It works perfectly, except you can't close it on click outside of it or its child elements. I tried to use event listener(commented in snippet) to track if the click was done outside and if it is - change checkbox status on 'false' and it kinda worked, however, it breaks the original checkbox functionality and you can't now close it in any way except for clicking outside of it. Is there a way I can fix this?
//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 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>
CodePudding user response:
Your strategy uses css to style the state of the dropdown based on the radio option value.
So there's no event handler in place already catching that point in time and the only approach to close the dropdown when you click outside, was using a click event handler on the main document and check for the element triggering the event to be of type HTML. Not the best approach indeed. (I edited the question to use a better approach... there's a container having the class dropdown
now and event.target
gets checked for having an ancestor with such class to understand if the click was fired from the dropdown itself or outside of it)
document.addEventListener('click', function(event){
if(event.target.closest('.dropdown') === null){
document.querySelector('#checkbox').checked = false;
}
});
Anyway once there, the logic just force the radio option to unchecked and restore the dropdown collapse state.
//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 >
<input type="checkbox" id="checkbox">
<label 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>