Reputation: 1
I've added an event listener via event bubbling to a parent element. On click, the function duplicates the source and inserts the clone after the source. After the source is cloned, I don't want it to be triggered again. What is the best way to accomplish this?
<script>
// declare handler
function clickHandler(e) {
if (e.target.matches('.list__item') ||
e.target.matches('.list__item *')) {
console.log(e.target.innerHTML);
const child = document.getElementById(e.target.id);
console.log(child.id)
//Get source element
const source = child.closest('.list__item');
console.log(source);
// Create clone
var clone = source.cloneNode(true);
console.log(clone)
// Update clone ID
clone.id = 'elem2';
console.log(clone.id)
// Inject clone into the DOM
source.after(clone);
}
}
// reference to list
const list = document.querySelector('.list');
// add a single listener to list
list.addEventListener('click', clickHandler);
</script>
I haven't found a solution that addresses functions called via event bubbling.
Upvotes: 0
Views: 26
Reputation: 371193
It sounds like each list__item
has an ID. One approach would be, whenever an element is duplicated, add that ID to a Set, and check that the ID isn't in the Set before duplicating.
Because duplicate IDs in the same document is invalid HTML, consider using something else to indicate the uniqueness of an element - such as a data attribute.
const dupeIdsAdded = new Set();
function clickHandler(e) {
if (!e.target.matches('.list__item') &&
!e.target.matches('.list__item *')) {
return;
}
const li = e.target.closest('.list__item');
const { id } = e.target.dataset;
if (dupeIdsAdded.has(id)) return;
dupeIdsAdded.add(id);
const clone = li.cloneNode(true);
li.after(clone);
}
document.querySelector('.list').addEventListener('click', clickHandler);
<ul class="list">
<li class="list__item" data-id="x">one</li>
<li class="list__item" data-id="y">two</li>
</ul>
Upvotes: 2