I’ve got these Bootstrap 5 cards I’m tying to use as selector objects in a user tags viewer. I need them to toggle when clicked. My click events are firing successively even though there are two different classes. I’m not sure why. I know how it’s doing it in a sense, but I’m not sure how to stop it.
(document).addEventListener("click", function(e) {
//
// Handle toggle clicks for tags in tag viewer
//
if (e.target.matches(".tag-list-item") || e.target.closest(".tag-list-item")) {
// add the token to tagsObj
var token = e.target.parentElement.getAttribute("data-token");
var tag = e.target.parentElement.getAttribute("data-tag");
var operation = e.target.parentElement.getAttribute("data-operation");
if (token !== null && tag !== null) {
if (!tagsObj.contains(token) && operation == "tag-list-item") {
tagsObj.add(token);
e.target.parentElement.classList.remove("tag-list-item");
e.target.parentElement.classList.add("tag-list-item-selected");
e.target.parentElement.setAttribute("data-operation", 'tag-list-item-selected');
while (e.target.parentElement.firstChild.nextSibling.firstChild) {
e.target.parentElement.firstChild.nextSibling.firstChild.remove();
}
// create selected content
e.target.classList.add("card-body");
e.target.classList.add("d-flex");
e.target.classList.add("align-items-center");
var checkDiv = document.createElement("div");
checkDiv.classList.add("tag-list-item-checkbox");
var checkI = document.createElement("i");
checkI.classList.add("icofont-checked")
checkDiv.append(checkI);
var tagDiv = document.createElement("div");
tagDiv.append(tag);
e.target.append(checkDiv);
e.target.append(tagDiv);
}
}
}
if (e.target.matches(".tag-list-item-selected") || e.target.closest(".tag-list-item-selected")) {
var token = e.target.parentElement.getAttribute("data-token");
var tag = e.target.parentElement.getAttribute("data-tag");
var operation = e.target.parentElement.getAttribute("data-operation");
if (token !== null && tag !== null) {
if (tagsObj.contains(token) && operation == 'tag-list-item-selected') {
// the parent element (card wrapper)
e.target.parentElement.classList.remove("tag-list-item-selected");
e.target.parentElement.classList.add("tag-list-item");
e.target.parentElement.setAttribute("data-operation", 'tag-list-item');
e.target.classList.remove("d-flex");
e.target.classList.remove("align-items-center");
// Remove elements
while (e.target.parentElement.firstChild.nextSibling.firstChild) {
e.target.parentElement.firstChild.nextSibling.firstChild.remove();
}
e.target.append(tag);
// remove the item from tagsObj
tagsObj.remove(token);
}
}
}
});
I’ll show you some code. I don’t think that’s the issue. The JavaScript is updated too. I fixed the problem on page load. But when I do a tag search in the modal it doesn’t work on results.
Here is the html before and after a search:
// unselected in modal before search (inserted with php)
<div class="card tag-list-item" data-token="17db77789e81cb9f5ae0cdfe286d66f8" data-tag="Lo-Fi (Hip-Hop)">
<div class="card-body tag-text-output">Lo-Fi (Hip-Hop)</div>
</div>
// selected in modal before search (inserted with php)
<div class="card tag-list-item-selected" data-token="c5fdc52d79e436f5374a48506c492865" data-tag="Boom Bap (Hip-Hop)">
<div class="card-body d-flex align-items-center">
<div class="tag-list-item-checkbox"><i class="icofont-checked"></i></div>
<div class="tag-text-output">Boom Bap (Hip-Hop)</div>
</div>
</div>
// unselected after search (inserted with JavaScript)
<div class="card tag-list-item" data-token="17db77789e81cb9f5ae0cdfe286d66f8" data-tag="Lo-Fi (Hip-Hop)">
<div class="card-body">Lo-Fi (Hip-Hop)</div>
</div>
// selected after search (inserted with JavaScript)
<div class="card tag-list-item-selected" data-token="c5fdc52d79e436f5374a48506c492865" data-tag="Boom Bap (Hip-Hop)">
<div class="card-body d-flex align-items-center">
<div class="tag-list-item-checkbox"><i class="icofont-checked"></i></div>
<div>Boom Bap (Hip-Hop)</div>
</div>
</div>
But, If I test e.target classList for d-flex it doesn’t output, so it might still be selecting the right element.
I’m getting error, cannot read properties of null .firstChild. In that while loop condition. So for some reason that method of clearing the .card div won’t work after doing a tag search. A work around would be to add an extra class to the content coming from JS and check for it, clear the DIV from a different nextSibling location… but why?