I have a parent container with a number of elements, it's not a well defined number of elements, it's generated by using an API once the user starts typing something in an input field. Also these elements are parents to other elements. (I'll give an example below)
The idea is that once the user clicks that element, I want to display an overlay with more information about that specific element. Sounds good, but the things I've tried didn't work so far.
I tried to add an event listener onto the container. Consider this basic HTML template.
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span>X</span></li>
<li><span>Item 4</span><span>X</span></li>
</ul>
<form>
<input type="text" id="test">
</form>
So here we have an UL which is the parent element and LI are its children. However, LI are also parents to the span tags that are supposedly showing some vital information so I cannot remove those tags. The input field is here just to add something dyamically, to mimik the way my API works.
So like I said, I have tried to add an event listener on the UL parent >>
const items = ul.querySelectorAll('li');
items.forEach(item => item.addEventListener('click', function(e) {
console.log(this);
}));
});
});
Then I tried to add an event listener to each of the items, but instead of logging one item at a time as I click them, it's logging one, two, three and so forth. I feel that I'm missing something here and I don't know what it is. Can you guys help me out?
Later edit: I found this solution but it doesn't seem very elegant to me and it's prone to bugs if I change stuff later on (like add more children etc).
ul.addEventListener('click', e => {
const items = ul.querySelectorAll('li');
if(e.target.tagName === 'LI' || e.target.parentElement.tagName === 'LI') {
if(e.target.tagName === 'LI') {
e.target.remove();
} else if(e.target.parentElement.tagName === 'LI') {
e.target.parentElement.remove();
}
}
});
You can use the function Element.closest() to find a parent element.
const ul = document.querySelector('ul');
ul.addEventListener('click', e => {
let li = e.target.closest('LI');
li.remove();
});
document.forms.newitem.addEventListener('submit', e => {
e.preventDefault();
let newitem = document.createElement('LI');
newitem.innerText = e.target.test.value;
ul.appendChild(newitem);
});
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span><em>X</em></span></li>
<li>Item 4 X</li>
</ul>
<form name="newitem">
<input type="text" name="test">
</form>