I have a <ul>
list with some <li>
elements inside, and I've added a click
event listener for each of these elements to move the clicked item to the top of the list.
function add_event_listeners() {
let elements = my_list.getElementsByTagName('li');
for (let item of elements) {
item.addEventListener("click", send_to_top);
}
}
function send_to_top() {
this.parentElement.children[0].insertAdjacentElement('beforebegin', this);
}
This code works fine until I remove or add a new li
to the list, all the event listeners get removed, and the clicks after that don't work.
What's the proper event listener to use to detect that a new element has been added or removed from the list? So I can use it to run the add_event_listeners()
function after that?
Based on the HTMLCollection documentation on MDN:
An
HTMLCollection
in the HTML DOM is live; it is automatically updated when the underlying document is changed. For this reason it is a good idea to make a copy (eg. usingArray.from
) to iterate over if adding, moving, or removing nodes.
Can anyone help with a code sample of how to do that?
CodePudding user response:
Somehow mine works by just refactoring the code, see below:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul id="lists">
<li >
<div>List #1</div>
<button >Send to top</button>
</li>
<li >
<div>List #2</div>
<button >Send to top</button>
</li>
<li >
<div>List #3</div>
<button >Send to top</button>
</li>
<li >
<div>List #4</div>
<button >Send to top</button>
</li>
</ul>
<script>
const listsEl = document.getElementById('lists');
const addEventListeners = () => {
const sendUpBtnEls = document.querySelectorAll('.btn-send-up');
sendUpBtnEls.forEach((sendUpBtnEl) => {
sendUpBtnEl.addEventListener('click', (e) => {
const listItemEl = e.target.closest('.list-item');
listsEl.firstElementChild.insertAdjacentElement(
'beforebegin',
listItemEl,
);
});
});
};
addEventListeners();
</script>
</body>
</html>
CodePudding user response:
I was avoiding using the MutationObserver
to capture any changes in the HTML of the list because I thought it would be complicated and performance-consuming.
I was able to manage that using this code:
const observer = new MutationObserver( () => authors_list__add_listeners() );
observer.observe(my_list, { childList: true });