I have been tried to write a custom inspired element with an input field where the user can write and a list that appears and disappears based on input's focus.
const unitsList = {lenght:{fm:"femtometers (fm)",pm:"picometers (pm)",nm:"nanometers (nm)",um:"micrometers (μm)",mm:"millimiters (mm)",cm:"centimiters (cm)",dm:"decimeters (dm)",m:"meters (m)",dam:"decameters (dam)",hm:"hectometers (hm)",km:"kilometers (km)",in:"inchs (in)",ft:"foots (ft)",yd:"yards (yd)",mi:"miles (mi)"}}
let groups = ['lenght', ]
function $$(id) {
return document.querySelectorAll(id);
}
function s$(id) {
return document.querySelector(id);
}
$$('ul').forEach(selector => {
for (group of groups) {
for (unit in unitsList[group]) {
selector.insertAdjacentHTML('beforeend', `<li onclick="console.log('${unit}')">${unitsList[group][unit]}</li>`);
}
}
})
$$('.customSelectorInput').forEach(input => {
input.addEventListener('focus', () => {
$$('ul').forEach(() => {
s$(`#${input.parentNode.id} > ul`).hidden = false;
})
})
})
$$('.customSelectorInput').forEach(input => {
input.addEventListener('blur', () => {
$$('ul').forEach(() => {
s$(`#${input.parentNode.id} > ul`).hidden = true;
})
})
})
ul {
position: absolute;
list-style: none;
padding-left: 10px;
margin: 5px;
background-color: lightgray;
padding: 5px;
border-radius: 5px;
height: 100px;
overflow-y: scroll;
}
li {
margin: 2px 0;
padding: 5px;
}
li:hover {
background-color: grey;
}
<div class="inputContainer">
<div id="inSelector">
<input type="text" class="customSelectorInput">
<ul hidden id="inList"></ul>
</div>
</div>
The problem is that the input loses focus when the user clicks on the list and that happens before the onclick is able to work.
I have tried several methods, including but not limited to event.stopPropagation(), disabling useCapture or refocusing the input on a list's click event handler but nothing seems to work.
I'd really appreciate someone's help.