1

I'm currently having trouble understanding what's going on with this code

 $("#table").on("click", ".plusRow", function(event){
            var name = this.getAttribute("table-data");
            tableData.addData(name, 0, 1);
            displayTable();
        });

I understand that the first part should go something along the lines of

document.getElementById("table").addEventListener("click", function(event)

but im having trouble understanding where the ".plusRow" class should go, is it added onto the eventlistener? or how would this code be better translated back to regular Javascript.

potatorekt
  • 17
  • 2
  • You would have to make a second event listener with `document.getElementByClass("plusRow")` – Surreal Dec 08 '17 at 17:08
  • Possible duplicate of [What is DOM Event delegation?](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation) – Andreas Dec 08 '17 at 17:09
  • @Surreal Will that successfully target dynamic elements though? – ProEvilz Dec 08 '17 at 17:09
  • 1
    Possible duplicate of [Vanilla JavaScript Event Delegation](https://stackoverflow.com/questions/23508221/vanilla-javascript-event-delegation) – Pat Dec 08 '17 at 17:09
  • @Andreas OP post is regarding translating jQuery into vanilla Javascript. How is this in anyway a duplicate of event delegation/ – ProEvilz Dec 08 '17 at 17:10
  • @Surreal No, he doesn't need a second event listener – Andreas Dec 08 '17 at 17:10
  • @ProEvilz the current question posed is how to turn that delegate event binding into vanilla javascript. So any questions detailing how to do so, with an answer, would be inline with a duplicate. – Taplar Dec 08 '17 at 17:12
  • @ProEvilz The duplicate describes the process of event delegation with "vanilla JS" and that's exactly what the OP is looking for. It's not a "copy&paste this part and you're done" duplicate, but a "This is how it works. Now try to adapt it to your markup/problem" – Andreas Dec 08 '17 at 17:12
  • @Andreas I disagree. This is more of a 'where do I place this class in this function' as a pose to a 'how do I make sure this targets dynamic elements'. It's pretty obvious considering "`understanding where the ".plusRow" class should go`" – ProEvilz Dec 08 '17 at 17:14
  • 2
    The whole point of the delegate is to handle for dynamic elements. Why would you not think the user would want that in a direct translation of functionality from jQuery to javascript? – Taplar Dec 08 '17 at 17:15
  • Delegation would be a secondary goal, with the prime goal being the translation of jquery->vanilla. It just so happens they need delegation on one part of the script they're working with. So to make this question as a duplicate of a primary specific issue (delegation), would be incorrect. – ProEvilz Dec 08 '17 at 17:16
  • To bolster my explanation, this is why no one is marking this as a duplicate of 'how to target classes in vanilla javascript' despite that functionality being needed... they are secondary goals, and therefor, not a direct duplicate. Otherwise, why aren't you guys marking it as such? You **will** have to target classes in this.. so... ? – ProEvilz Dec 08 '17 at 17:19
  • 2
    There are only two pieces of jQuery to this question. The initial selector, and the delegate binding. Everything else is vanilla already. The OP has shown they already know how to do the id selector. That just leaves the delegate translation. I can't speak for why others haven't voted duplicate yet, but I haven't done so yet because there was this discussion on going in the comments. – Taplar Dec 08 '17 at 17:24

2 Answers2

0

This code snippets binds a listener on a single element (the table) and delegates it to its children which means that it will only run the event handler when it bubbles up to one or multiple elements that match the predicate (having a "plusRow" class).

With event delegation you could do:

let table = document.getElementById('table');
table.addEventListener('click', event => {
    const elem = event.target;
    if (elem.classList.contains('plusRow')) {
        const name = elem.getAttribute("table-data");
        tableData.addData(name, 0, 1);
        displayTable();
    }
});

Here we have to keep in mind that this code will always run when a child of the table is clicked but will only update the table when the target matches the predicate.

Without using event delegation you could do the following which will have similar results but behaves quite differently:

let tableElem = document.getElementById('table');
// To keep this simple we assume there is only one button
let button = tableElem.getElementsByClassName('plusRow')[0];

button.addEventListener('click', event => {
    const name = event.currentTarget.getAttribute("table-data");
    tableData.addData(name, 0, 1);
    displayTable();
})

This version will only ever run when the first child of the table with a class of "plusRow" is clicked. Please note that this is just an example because if there is no element with such class an exception will be raised when we try to bind the event listener.

oLeduc
  • 313
  • 1
  • 12
0

So I've come up with a dummy possible solution example using querySelector and querySelectorAll. Let me know if anyone sees an issue with the suggested solution.

function delegate(parentSelector, eventType, childSelector, callback) {
  //lookup the parent element
  var parent = document.querySelector(parentSelector);

  //put the event listener for the event on the parent
  parent.addEventListener(eventType, function(event) {
    //get the element that caused the event
    var element = event.target;
    //find all the children in the parent that match the child selector,
    //at this point in time
    var children = parent.querySelectorAll(childSelector);

    //if the element matches a child of the parent that matched the
    //childSelector, we want to do our callback
    for (var i = 0; i < children.length; i++) {
      if (children[i] === element) {
        callback();
        break;
      }
    }
  });
}

delegate('#table', 'click', '.addRow', function() {
  document.querySelector('#table').innerHTML += `
    <tr>
      <td>Something</td>
      <td><button class="addRow">Add Row</button></td>
    </tr>
  `;
});
<table id="table">
  <tr>
    <td>Something</td>
    <td><button class="addRow">Add Row</button></td>
  </tr>
</table>
Taplar
  • 24,788
  • 4
  • 22
  • 35