Chaining vanilla javascript traversal?

Tags: ,



My HTML looks like this:

<div class="panel">
    <div class="panel-heading"></div>
    <div class="panel-body"></div>
</div>

I am currently selecting the parent node of the panel-heading element like so:

e.target.parentNode

This leaves me with the panel class. All is well.

But now I would like to grab the panel-body at that point. Doing something like this unfortunately does not work:

e.target.parentNode.querySelector('.panel-body')

Is there a clean way to do this in vanilla javascript?

Answer

If you know the node’s class, you can always use document object:

var tgt = document.querySelector('.panel-body');

If you need to get nodes in the context of an event such as click, you can delegate.

  • Find node that is an ancestor of all of the nodes you wish to access.
    • ex. .panel
  • Register the event on that node.
    • ex. panel.addEventListener('click', callback)
  • During the bubbling phase, find the event.target by comparing it to the event.currentTarget (the node that is registered to the event)
    • ex. if(e.target !== e.currentTarget) {...

Click nodes and it’s tag and class will be displayed. Details are commented in snippet

Snippet

// Reference top element
var panel = document.querySelector('.panel');

// Register .panel on click event
panel.addEventListener('click', highlight);


function highlight(e) {

  // if the clicked node is not .panel
  if (e.target !== e.currentTarget) {

    // Get the clicked node's class
    var tgtClass = e.target.className;

    // Get the clicked node's tag
    var tgtTag = e.target.tagName;
  }

  /* Set the clicked node's tag and class 
  || as it's content.
  */
  e.target.textContent += ' ' + tgtTag + '.' + tgtClass;
}
[class*=panel] {
  border: 1px dashed blue;
  color: red;
}
<section class="panel">
  <hgroup class='panel-heading-group'>
    <h1 class="panel-heading">HEADING</h1>
    <h2 class='panel-sub-heading'>SUB-HEADING</h2>
  </hgroup>
  <main class="panel-body">
    <p>CONTENT A</p>
    <p>CONTENT B</p>
  </main>
  <footer class='panel-footer'>FOOTER</footer>
</section>


Source: stackoverflow