Kyle_Pearce
Kyle_Pearce

Reputation: 121

HTML & CSS - DOM traversal

I have the HTML:

<div class="dropdown">
  <button class="dropbtn">Game Design</button>
  <div class="dropdown-content">
    <a id="GameIdea" href="GameIdea.html">Link 1</a>
    <a id="GameMechanics" href="GameMechanics.html">Link 2</a>
    <a id="GameCharacters" href="GameCharacters.html">Link 3</a>
    <a id="Inspiration" href="Inspiration.html">Link 3</a>
  </div>
</div>

And the JavaScript:

var anchor = document.getElementById(pathShort); //e.g. pathShort == GameIdea
var anchorParent = anchor.parentNode;
var button = anchorParent.previousSibling;
button.classList.add("active");

The issue is this - I don't want the anchor element:document.getElementById(pathShort);

I want the button element, therefore as you can see I use anchor.parentNode; to get the div that the anchor is in, and then anchorParent.previousSibling; to get the element beside the div, before not after.

In my mind I thought this would work but in console I get the error Cannot read property 'add' of undefined, therefore the variable button must be effectively null or empty, meaning my method of DOM traversal prior to the 'add' call has not worked.

Upvotes: 1

Views: 165

Answers (3)

Boric
Boric

Reputation: 872

The previousSibling method was returning an empty text node (containing nothing but white space), which is not an element and does not have a classList property. previousSibling returns the previous node whether it is an element or not. You can change it to previousElementSibling to get the button element, because it returns only the previous element, ignoring other types of nodes.

var pathShort = "GameIdea";
var anchor = document.getElementById(pathShort);
var anchorParent = anchor.parentNode;
var button = anchorParent.previousElementSibling;
button.classList.add("active");
<div class="dropdown">
  <button class="dropbtn">Game Design</button>
  <div class="dropdown-content">
    <a id="GameIdea" href="GameIdea.html">Link 1</a>
    <a id="GameMechanics" href="GameMechanics.html">Link 2</a>
    <a id="GameCharacters" href="GameCharacters.html">Link 3</a>
    <a id="Inspiration" href="Inspiration.html">Link 3</a>
  </div>
</div>

Upvotes: 5

Andriy
Andriy

Reputation: 15442

Try this:

const pathShort = 'GameIdea';
const anchor = document.getElementById(pathShort);
const anchorParent = anchor.parentElement;
const button = anchorParent.previousElementSibling;
button.classList.add("active");
<div class="dropdown">
  <button class="dropbtn">Game Design</button>
  <div class="dropdown-content">
    <a id="GameIdea" href="GameIdea.html">Link 1</a>
    <a id="GameMechanics" href="GameMechanics.html">Link 2</a>
    <a id="GameCharacters" href="GameCharacters.html">Link 3</a>
    <a id="Inspiration" href="Inspiration.html">Link 3</a>
  </div>
</div>

when you access HTML DOM node's properties like parentNode or previousSibling you will get also non HTML nodes like Text nodes, in your code each new line creates an empty Text node, thus you get it instead of desired element.

Upvotes: 0

Angel
Angel

Reputation: 114

You can use...

var button = document.querySelector(".dropbtn")

This will get the first element with the class dropbtn (The button element in this case).

If you're trying to add a class within the button element. I'd recommend you;

button.setAttribute("class", "dropbtn ANY-OTHER-CLASS")

Upvotes: 1

Related Questions