Search code examples
javascripthtmlcssbuttonmultiple-columns

HTML - JS - multiple buttons that change css of table columns


I have a HTML document with a table in it

<table>
  <tr>
    <th class="street">Street</th>
    <th class="city">City</th>
    <th class="country">Country</th>
  </tr>
  <tr>
    <td class="street">street-1</td>
    <td class="city">city-1</td>
    <td class="country">country-1</td>
  </tr>
  <tr>
    <td class="street">street-2</td>
    <td class="city">city-2</td>
    <td class="country">country-2</td>
  </tr>
</table>

Now I am looking for a way to implement buttons. For example

<button id="button_street">TOGGLE STREET</button>
<button id="button_city">TOGGLE CITY</button>
<button id="button_country">TOGGLE COUNTRY</button>

If a button is pressed, the corresponding column in the table should be hidden. Even better (than hidden) it would be if I could change the css design with the buttons.

My (temporary) solution is quite cumbersome... It's a javascript solution that changes one class (visible) to another (hidden).

Spry.Utils.addLoadListener(function() {
    let buttonToggle = document.getElementById('button_street');
    buttonToggle.addEventListener('click', toggleClass);
    
    function toggleClass() {
        let collection = document.getElementsByClassName("street");
        for (var i=0; i<collection.length; i++) {
            collection[i].classList.toggle('street_design2');
        }
    }
}

This javascript must be repeated for each button.

where the css is the following:

.street {
    background-color: blue;
}

.street_design2 {
    background-color: red;
}

If I want to hide the "street-column" I can use display: none

  1. I haven't found any other javascript solution to address all elements with class street. Maybe there is a better solution?
  2. also it would be good if i could pass the function to an array like this:

const array = ["street", "city", "country"]

instead of repeating it for each button. Maybe there is a solution (a loop?)?


Solution

  • You can use document.querySelectorAll to address all elements with same tagName, class, etc, and then use .forEach() to add the EventListener to all elements at once for your case.

    function toggleClass(collection) {
      document.querySelectorAll('.' + collection).forEach(function(element) {
        element.classList.toggle(collection + '_design2');
      });
    }
    
    document.querySelectorAll('button').forEach(function(button) {
      button.addEventListener('click', function(e) {
        let collection = this.id.split('_').pop();
        
        toggleClass(collection);
      });
    });
    .street {
        background-color: blue;
    }
    
    .street_design2 {
        background-color: red;
    }
    
    .city_design2 {
      background-color: yellow;
    }
    
    .country_design2 {
      background-color: green;
    }
    <table>
      <tr>
        <th class="street">Street</th>
        <th class="city">City</th>
        <th class="country">Country</th>
      </tr>
      <tr>
        <td class="street">street-1</td>
        <td class="city">city-1</td>
        <td class="country">country-1</td>
      </tr>
      <tr>
        <td class="street">street-2</td>
        <td class="city">city-2</td>
        <td class="country">country-2</td>
      </tr>
    </table>
    
    <button id="button_street">TOGGLE STREET</button>
    <button id="button_city">TOGGLE CITY</button>
    <button id="button_country">TOGGLE COUNTRY</button>