0

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.

Chris M
  • 1
  • 1

1 Answers1

2

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>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • @CertainPeformance Thanks for the quick response. It worked perfectly! I also implemented your suggestion to use a data attribute as a unique identifier. Thanks again! – Chris M Nov 27 '22 at 04:36