-1

I'm trying to get the parent of the parent (div) of the li-element which I click and change/remove it's class but I don't know how to tell JS that it should get the specific li class that I click. Sorry for this simple question I'm fairly new to JS.

<!DOCTYPE html>
<html>
<body>

<p>List:</p>

<div class="div">
<ul>
  <li class="lis">Coffee</li>
  <li class="lis">Tea</li>
  <li class="lis">Water</li>
</ul>
</div>

<script>

let li = document.getElementsByClassName("lis")

li.click() = function() {
  var x = li.parentElement.parentElement.classList.value
  if(x.classList.contains("div")) {
    x.remove.classList("div")
  }
}

</script>

</body>
</html>
CBroe
  • 91,630
  • 14
  • 92
  • 150
AtomicElmo
  • 13
  • 2
  • 1
    Umm ... Why not add the click listener to the div itself? See also https://stackoverflow.com/questions/10693845/what-do-queryselectorall-and-getelementsby-methods-return , and how [event listeners are attached](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener). – Teemu Jan 18 '21 at 09:17
  • 2
    there are two or three syntax error here AtomicElmo - click should be onclick and getElementsByClassName returns an array-like object and I suspect you cannot really assign a click listener to that HTMLCollection as whole...it's classList.remove and not remove.classList... – rags2riches-prog Jan 18 '21 at 09:23

5 Answers5

1

<script>

var elements = document.getElementsByClassName("lis");

var myFunction = function(e) {
    x = e.target.innerHTML;
    e.target.parentElement.parentElement.innerHTML=x
};

for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click', myFunction, false);
}


</script>
Akaqlonist
  • 115
  • 3
  • This might work, but it looks like it substantially changes what the code does. The original just removes a class from the `
    `, but this moves markup around. Try to change the code provided by people in questions as little as possible, as it makes the answer a lot easier to follow.
    – Blieque Jan 18 '21 at 11:04
0

You can use .closest() to select the closest div and after that, you can remove the class from that element.

Try below working code -

var elements = document.getElementsByClassName("lis");

var myFunction = function() {
  var x = this.closest('.div')
  if (x) {
    this.closest('.div').classList.remove("div")
    console.log('Div Element Class Removed!');
  }
};

for (var i = 0; i < elements.length; i++) {
  elements[i].addEventListener('click', myFunction, false);
}
<!DOCTYPE html>
<html>

<body>

  <p>List:</p>

  <div class="div">
    <ul>
      <li class="lis">Coffee</li>
      <li class="lis">Tea</li>
      <li class="lis">Water</li>
    </ul>
  </div>
</body>

</html>
Shubham Baranwal
  • 2,492
  • 3
  • 14
  • 26
0

I recommend to delegate to the nearest static container

Also you had remove.classList - that should be classList.remove

Here I give an ID to the UL and test if the LI clicked has the lis class

document.getElementById("ul").addEventListener("click",function(e) {
  const tgt = e.target.closest("li")
  if (tgt.classList.contains("lis")) {
    tgt.closest("div").classList.remove("div")
  }
})
.div { background-color:red }
<p>List:</p>

<div class="div">
<ul id="ul">
  <li class="lis">Coffee</li>
  <li class="lis">Tea</li>
  <li class="lis">Water</li>
</ul>
</div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0

I came up with another good solution that let's me add and remove the div class, the parent of specified li elements. I added an extra div to make sure it always gets the certain parent that I've specified with .closest(body > div) and used a for loop to make the array that it creates select one certain li element, the one I currently click on.

<!DOCTYPE html>
<html>
<body>

<p>List:</p>

<div class="div">
<ul>
  <li class="lis">Coffee</li>
  <li class="lis">Tea</li>
  <li class="lis">Water</li>
</ul>
</div>

<div>
  <ul>
    <li class="l">Coffee</li>
    <li class="l">Tea</li>
    <li class="l">Water</li>
  </ul>
  </div>



<script>

let lists = document.getElementsByClassName("lis");
let divs = document.getElementsByTagName("div");

for (let list of lists) {
list.addEventListener("click", () => {
    list.closest("body > div")
for (let div of divs) {
div.addEventListener("click", () => {
if (div.classList.contains("div")) {
    div.classList.remove("div")
} else {
    div.classList.add("div")
    }
   })
  }
 })
}

</script>

<style>

  .div {
    color: brown;
    font-size: larger;
  }
</style>

</body>
</html>
AtomicElmo
  • 13
  • 2
-1
var li = document.getElementsByClassName("lis");

for (var i=0; i<li.length; i++) {

    li[i].onclick = function() {
        var el = this.parentElement.parentElement;

        if (el.className == "div") {
            el.className = "";
        }
    }
}
Faisal
  • 127
  • 1
  • 7
  • Please explain your code. Also there are more recommended methods than onclick and setting the className string - for example what happens if there is more than one class or if we wrap something, breaking parentElement.parentElement – mplungjan Jan 18 '21 at 09:38
  • this solution suites with the question above. since there is no class name other than that, there is no problem with using the `className` string. And as it’s mentioned in the question, the only mentioned and wanted method is `onclick`, I don’t think that other method is wanted. – Faisal Jan 18 '21 at 23:39