2

I wanted to make a dynamic table view where a button was clicked to reveal a Table Row however, I get an error when I try to change the text of the button.

window.onload = () => {
  const buttons = document.getElementsByTagName("button")
  console.log(buttons)
  const info = document.getElementsByTagName("tr")
  // let a = 1

  for (let elem in info) {
    if (info.id != "info") continue
    else info.splice(info.indexOf(elem), 1)
  }


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

    buttons[i].addEventListener("click", function onClick(a = 1) {
      if (a % 2 == 0) {
        info[i].style.visibility = "hidden"
        buttons[i].innerText = "View More" // wrong
      } else {
        info[i].style.visibility = "visible"
        buttons[i].innerText = "View Less" // wrong
      }
      a++
    })
  }
}
<button>Show Contents</button>

<table>
  <tr id="info" style="visibility:hidden;">
    <td width="80%">
      <p style="width:80%;text-align:center; margin-left:1%">
        The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity
        of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution
        projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
      </p>
    </td>
</table>

Error:

Uncaught TypeError: Cannot set properties of undefined (setting 'innerText') at HTMLButtonElement.onClick

isherwood
  • 58,414
  • 16
  • 114
  • 157
  • 1
    Does this answer your question? [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Lennholm Jan 02 '22 at 13:00
  • The problem is about `closure inside loops` like previously commented. Also, on the first loop, you are using the wrong variable `info.id != "info"` should be `info[elem].id != "info"`. It's not good idea assume the same index of `tr` and `button`, since if you add buttons or another table on your page, the indexes maybe will change! – Manuel Romeiro Jan 02 '22 at 14:56
  • The thing is it just sorting out those different tr, the remaining tr count is equal to the button count @ManuelRomeiro – Dhiraj Baid Jan 02 '22 at 17:55
  • Another problem is that your variable `a` is never 1 or any other number because the first argument of a click handler is always an `event`. – jefi Jan 02 '22 at 18:45

1 Answers1

2

Suggestions:

  • Use "display" style, instead of "visibility", to don't let the space occupied on the page when it's not visible;
  • It's not good idea have multiple elements with the same id (like "info"), because that breaks the rules of HTML;
  • To show and hide, use read directly info from css, instead of use a auxiliary variable;
  • The document.getElementsByTagName returns an object, not an array. The way to navigate is using the classic way.

Next, your code with some fixes:

window.onload = () => {
  const buttons = document.getElementsByTagName("button")
  //console.log(buttons)
  const info = document.getElementsByTagName("tr")
  // let a = 1
  let newInfo = [];
  for (let i = 0; i < info.length; i++) {
    if (info[i].id === "info"){
      newInfo.push(info[i]);
    }
  }


  for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("click", function onClick() {
    if (newInfo[i].style.visibility !== "hidden") {
      newInfo[i].style.visibility = "hidden"
      // Suggestion: use "display" style, instead of "visibility", to don't let the space ocupied on the page, when it's not visible
      //newInfo[i].style.display = "none"
      buttons[i].innerText = "View More" // wrong
    }
    else {
      newInfo[i].style.visibility = "visible"
      buttons[i].innerText = "View Less" // wrong
      //newInfo[i].style.display = ""
    }
  }) 
  }
}
<button>Show Contents</button>
<table>
<tr id="info" style="visibility:hidden;">
  <td width="80%">
    <p style="width:80%;text-align:center; margin-left:1%">
    1 - The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
    </p>
  </td>
</table>
<button>Show Contents</button>
<table>
<tr id="info" style="visibility:hidden;">
  <td width="80%">
    <p style="width:80%;text-align:center; margin-left:1%">
    2 - The Planetarium is located on the first floor of the Science Centre. The planetarium has a shape of a sphere, 16.30 meters in diameter, the dome could also be used for extreme-wide-projections and other enhanced multi-media shows. It has a seating capacity of 140 the digital theatre of Planetarium facilitates the observation of planets, moon, stars, nebula, displayed on full dome through an advance technology and thus Astronomy Secrets will be shared with the students and general public. High resolution projectors operated through Digester 3 technology with digital audio system will provide a dazzling shows and that would be unforgettable experience. The shows will be in 3 languages Gujarati, Hindi and English.
    </p>
  </td>
</table>
Manuel Romeiro
  • 1,002
  • 12
  • 14