What is the best way to incorporate child nodes when selecting dynamically generated elements through JavaScript?

Currently, I have buttons being dynamically generated on the page using plain JavaScript.

For example:

<button class="c-config__option c-config__option--button c-config__option--pack" data-index="0">
    Item 1
    <span>Subtext</span>
</button>
<button class="c-config__option c-config__option--button c-config__option--pack" data-index="1">
    Item 2
    <span>Subtext</span>
</button>
...

When targeting the parent class (.c-config__wrapper) and using event.target to access the buttons, clicking on the span within the button changes the target from the button to the span itself.

How can I ensure that the parent button continues to remain the target when using plain JavaScript? Alternatively, how do I include the span as a target along with the button?

Answer №1

The documentation on MDN highlights the presence of a method within the event object called composedPath. This method stores an array of objects where listeners will be triggered, excluding nodes in shadow trees if the shadow root was created with its ShadowRoot.mode set to closed.

While this functionality appears to function correctly in Chrome, the extent of support for this method across different browsers is not clearly outlined in the documentation.

Further examination of the event object unveiled the existence of a property named event.path, which holds the same path array – at least in Chrome. Strangely, no information can be found regarding event.path in any documented source.

In light of this ambiguity, some sources recommend using

var eventPath = event.path || (event.composedPath &&
  event.composedPath());
instead of solely relying on
var eventPath =
  event.composedPath();
.


If your browser does indeed support it, you have the option to traverse through the path of the clicked element and verify whether it is a child of a button or the button itself.

The following code snippet exemplifies this procedure and retains a reference to the button element for future usage:

document.getElementById('wrapper').addEventListener('click', function() {
  // actual element clicked
  console.log(event.target);

  var buttonClicked = false;
  var button;

  var eventPath = event.composedPath();
  for (let i = 0; i < eventPath.length; i++) {
    if (eventPath[i].tagName && eventPath[i].tagName.toLowerCase() === 'button') {
      buttonClicked = true;
      button = eventPath[i];
      break;
    }
  }

  if (buttonClicked) {
    console.log(button);
    console.log('button was clicked');
  }
})
<div id="wrapper">
  <button class="c-config__option c-config__option--button c-config__option--pack" data-index="0">
    Item 1
    <span>Subtext</span>
</button>
  <button class="c-config__option c-config__option--button c-config__option--pack" data-index="1">
    Item 2
    <span>Subtext</span>
</button>
</div>

An alternative approach involves replicating jQuery.closest by utilizing the solution presented in this Stack Overflow post: DOM / pure JavaScript solution to jQuery.closest() implementation?

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When using REACT to fetch data from an API, the absence of an 'Access-Control-Allow-Origin' header may result in access issues

I am working on a project that involves retrieving products from a company's API. After reaching out to the company, they provided me with the following information: CORS allowed origins for local development is "http://localhost:1229" To adhere t ...

Developing an interactive form for instant price calculations

I'm currently tackling a project that involves developing an order form capable of computing the price of a door in real-time. However, I am having trouble deciding on the best approach to take. The form will include the following inputs: Frame (Dr ...

Rotate the image as you swipe left or right with Angular's ng-swipe-left and ng-swipe-right features

I am currently utilizing angular's ng-swipe-left and ng-swipe-right to detect swipe events on touch devices. My goal is to rotate an image based on the speed and direction of the swipe while it is still in progress. However, I am facing a challenge as ...

Apply design to a dynamically generated JavaScript id using Stylus

Currently, I am utilizing a jquery datepicker widget, and my goal is to customize the CSS for its input field. However, it seems that the id assigned to that field is dynamically generated upon page load: <input type="text" id="dp1382434269539" style= ...

The HTTP request arrives with no content within the body

I am in the process of developing a basic client-server application using Node and Express. The goal is for the program to receive a JSON input on the client-side, perform some operations, and then send data to the server-side. Currently, I am able to sen ...

Invoking Angular component method using vanilla JavaScript

For my web application, I am utilizing Angular and require Bluetooth functionality on a specific page. I am implementing loginov-rocks/bluetooth-terminal (https://github.com/loginov-rocks/bluetooth-terminal) for establishing the Bluetooth connection, which ...

JQuery Script Perform an Action - Pause - Execute Another Action

I'm working on a function that involves running some jQuery code, pausing for around 5 seconds, and then executing something else. Here's an example of what I'm trying to achieve: function myFunc() { var str1 = 'This is the starti ...

multiple simultaneous ajax calls being triggered

I am currently working on creating 4 cascading dropdowns, where the options in each dropdown repopulate based on the selection made in the previous one. To achieve this functionality, I decided to implement an Ajax call. The call takes the parameters, det ...

Developing an interactive Breadcrumb component using Vue.js in the latest version, Vue 3

Struggling to develop a dynamic Breadcrumb-Component in Vue.js 3. After hours of research, I haven't found a suitable solution due to outdated methods or lack of flexibility. As a beginner in frontend development, I am unsure about the best library to ...

Obtain the identification address for a group of items

I have a JSON object containing place IDs, and I am attempting to retrieve the corresponding addresses for each ID. This is the code snippet I'm using: <div id="places" class="places"></div> <script> function initialize() { j ...

What could be causing my code to become unresponsive when using a for loop compared to a loop with a specific

After spending a solid 4 hours on it, I finally managed to figure it out. There were no errors popping up, so I resorted to using the debug feature which unfortunately didn't provide much insight. Without any error messages to guide me, I wasn't ...

My AngularJS ng-show functionality is not functioning as expected. I have already reviewed the syntax and still encountering issues

Having trouble with my ng-show, it's not functioning as expected <div class="form-group"> <label class="control-label col-sm-4">NotesTest:</label> <div class="col-sm-4"> <textarea class="form-control ...

Using jQuery to send LocalStorage data to an email address with the help of PHP

Currently, I am in the process of developing a basic eCommerce/checkout system. My goal is to utilize localStorage data and transfer it to PHP using jQuery or any other method that is convenient. However, when I attempted to send the email, I only received ...

Transforming the shopping cart with redux-saga

Hey there! I've been working on implementing a shopping cart feature using redux-saga. The current code seems to be functioning properly, but I have some concerns about the way I'm handling the cart state. It looks like I might be mutating the ca ...

Looking for assistance in setting up a personalized slideshow to automatically play on its

Recently, I have taken responsibility for a project that was initiated by someone else. The website contains a customized slideshow on its homepage. To meet the client's requirements, I have already made some alterations to the appearance and feel of ...

Mongoose encounters an issue: MissingSchemaError is thrown because the Schema has not been registered for the model

Encountering a perplexing error that I can't seem to resolve. I HAVE NAMED THE REF EXACTLY AS THE MODEL: MissingSchemaError: Schema hasn't been registered for model "ParticipantStatus". Here are the models in question: ParticipantStatus model: c ...

Exploring Bootstrap4: Interactive Checkboxes and Labels

My form design relies on Bootstrap, featuring a checkbox and an associated label. I aim to change the checkbox value by clicking on it and allow the label text to be edited by clicking on the label. The issue I'm facing is that both elements trigger t ...

executing jQuery toggle on freshly generated content

I have a webpage that I designed using jQuery. Within this page, there is a table with rows assigned specific color classnames (e.g., tr class="yellowclass"). Users can filter the rows by clicking checkboxes to show/hide tables of different colors. The i ...

Selecting Texture Coordinates

My goal is to pinpoint where a user has clicked on a texture of an object to trigger a response by redrawing the texture. I've been able to achieve this by rendering my objects with a color-coded texture onto a separate render target and using gl.rea ...

Enhancing the content of a field - React

Seeking assistance with populating an input field with a generated password in my React component. Currently, the password is showing as undefined. MainComponent.js - primary React component class MainComponent extends React.Component { state = { p ...