Using HTML and Javascript, create a set of buttons that can dynamically change the CSS styles of specific

I am currently working on an HTML document that contains a table. The table structure is as follows:

<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>

My goal now is to implement buttons in the document, such as:

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

When a button is clicked, I want the corresponding column in the table to be either hidden or have its css design changed.

Currently, my solution involves using a somewhat cumbersome javascript method that toggles classes:

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 approach needs to be repeated for each button, but I'm wondering if there is a more efficient way to achieve this functionality across all elements with the same class.

In addition, I am exploring the possibility of passing functions to an array instead of repeating them individually for each button. Is there a more streamlined solution involving loops?

The relevant css styles are defined as follows:

.street {
    background-color: blue;
}

.street_design2 {
    background-color: red;
}

If I wish to hide the "street" column entirely, I can use display: none.

  1. So far, I haven't come across a javascript solution that addresses all instances of a specific class like "street". Is there a better alternative available?
  2. Moreover, I am interested in consolidating and optimizing the implementation by utilizing arrays and loops. Any insights into achieving this?

Answer №1

If you want to target all elements with the same tagName, class, etc., you can utilize document.querySelectorAll. By using .forEach(), you can easily add the EventListener to all elements simultaneously for your specific scenario.

function switchClass(elements) {
  document.querySelectorAll('.' + elements).forEach(function(item) {
    item.classList.toggle(elements + '_design2');
  });
}

document.querySelectorAll('button').forEach(function(btn) {
  btn.addEventListener('click', function(e) {
    let elements = this.id.split('_').pop();
    
    switchClass(elements);
  });
});
.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>

Answer №2

Utilize the data property to define the specific node to target, preventing potential conflicts in the future. The callback function will only be triggered for the designated button with the data-table-toggle property, reducing clashes with other buttons.

This code sets up an event listener for all buttons on a webpage that possess a custom data attribute called "data-table-toggle". Upon clicking one of these buttons, the tableToggle() function is invoked.

Within the tableToggle() function, the value of the "data-table-toggle" attribute of the clicked button is retrieved using this.getAttribute("data-table-toggle"). This value is then used to select all table rows containing a matching class attribute. This selection is performed through the document.querySelectorAll() method utilizing CSS selectors targeting elements with the specified class.

Subsequently, the function toggles the class of each selected table row between two different styles: the original class associated with the "data-table-toggle" attribute and a new class appended with "-_design2". This toggle effect is achieved using the classList.toggle() method.

Overall, this code enables dynamic styling modifications to table rows based on button clicks, creating a simple toggle effect.

<html>
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.2/axios.min.js" integrity="sha512-NCiXRSV460cHD9ClGDrTbTaw0muWUBf/zB/yLzJavRsPNUl9ODkUVmUHsZtKu17XknhsGlmyVoJxLg/ZQQEeGA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="script.js"></script>
    <style>
        table .street-_design2 {
            display:none;
        }   
        table .city-_design2 {
            display:none;
        }   
        table .country-_design2 {
            display:none;
        }   
    </style>
</head>
<body>
    <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 data-table-toggle="street">TOGGLE STREET</button>
        <button data-table-toggle="city">TOGGLE CITY</button>
        <button data-table-toggle="country">TOGGLE COUNTRY</button>
</body>
window.onload = function () {
Array.from(document.querySelectorAll("button")).forEach(function (element) {
    if (!element.getAttribute("data-table-toggle")) return;
    element.addEventListener('click', tableToggle);
});
function tableToggle() {
    const attribute = this.getAttribute("data-table-toggle");
    Array.from(document.querySelectorAll(`tr .${attribute}`)).forEach(function (selector) {
        selector.classList.toggle(`${attribute}-_design2`);
    })
}
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The ngbpopover feature does not seem to be applying the external CSS specified within the ng-template when the container attribute is set to "body"

I need my ngbpopover to display at the top of the parent element instead of below it. I added container="body" to ngbpopover which resolved this issue, but now the external CSS defined in ng-template is not being applied. <mat-tab-group animationDu ...

Discovering the following element containing an ID attribute with jQuery

Upon clicking a link, my goal is to locate the subsequent <section> with an ID attribute and retrieve its ID. In the provided code snippet and JavaScript function, the expected outcome upon clicking the link is for "section_3" to be logged in the co ...

Submit form only if the field value is valid

I created a form with an input field that captures the user's mobile number and validates it to ensure it begins with '0'. The validation process is functioning correctly, but I am encountering a problem when submitting the form. Even if the ...

The ajaxStart() and ajaxStop() methods are not being triggered

I'm currently working on a Q/A platform where users can click on specific questions to be redirected to a page dedicated for answers. However, when a user tries to answer a question by clicking the "Answer" link, certain background processes such as ...

Unable to select an element with numerous choices available

I am attempting to click on an element in the following manner, but I keep encountering an error message that says: Failed: Cannot read property 'click' of undefined Here is the code snippet causing the issue: 'use strict;' var Pre ...

AXIOS: Is it possible to send multiple data items in a single POST request to an API?

My form collects data, which is then sent to an API using the new FormData(). However, one of the items in the model contains multiple attributes in the MongoDB model. Since the form requires a 1-to-1 key-pair relationship, it can't be sent as an obje ...

Using flexbox with a Material UI Select Component: A guide for beginners

I am currently utilizing Material UI for a project and looking to create a dropdown with a unique layout featuring 2 columns: https://i.sstatic.net/l8Jio.png Here is an excerpt of my code in progress: <Select> <MenuItem>item 1</MenuItem& ...

Creating a "save as" button in HTML - a step by step guide

When browsing the internet, if you want to save an HTML page you are viewing, you typically go to the File menu and select Save As. Is it possible to add a small button at the bottom of an HTML page that performs the same action? Instead of navigating thr ...

"Converting circular structure into JSON" - Inserting BigQuery Data using Cloud Function in Node.js

I am currently facing an issue while attempting to load an array of JSON objects into a BigQuery Table from a Cloud Function built in NodeJS. Despite not having any circular references, I encountered the error message "Converting circular structure to JSON ...

I'm encountering an error when trying to pass multiple parameters in an AJAX request

I am trying to pass three parameters to my ajax code. Here is the snippet of my code: $(document).ready(function () { SearchText(); }); function SearchText() { $("#txt712").autocomplete({ source: function (request, resp ...

Is it possible to pass a variable from an Axios Response in the Composition API up to the root level?

I need to fetch the headings array from an axios.get call and utilize it at the root level within my Vue component. However, when I attempt to return it, I encounter this error: ReferenceError: headings is not defined Here is the script element in my Vue3 ...

How to effectively extend the window.onload event handling function?

I've encountered a scenario where I need to incorporate my function, foo, into the existing window.onload event. However, there is already another function called bar assigned to the window.onload. Unfortunately, I don't have access to modify how ...

Algorithm for converting a 2D voxel map into a line may encounter occasional difficulty in progressing

For my game, I am dealing with a 2D voxel map stored as a 2D array where 1 represents ground and 0 represents sky. In the map, areas marked as 1 (ground) are represented by green boxes https://i.sstatic.net/rG7N5.png The algorithm initiates at the leftmo ...

Looking for a way to assign the (file path to kml) to a variable in your code while utilizing geoxml3?

Is there a way to store the KML file in a variable before parsing it with myParser? Check out this link for more information: https://github.com/geocodezip/geoxml3 var myParser = new geoXML3.parser({map: map}); myParser.parse('/path/to/data.kml' ...

Is there a way to display the division symbol using PHP?

I have come across this question multiple times, but am yet to find a satisfactory resolution. Is there a way to output the division sign (÷) using PHP? Every time I attempt to echo it, the output is just showing a strange symbol . ...

Utilizing jQuery for dynamic horizontal positioning of background images in CSS

Is there a way to set only the horizontal background property? I've tried using background-position-x and it works in Chrome, Safari, and IE, but not in Firefox or Opera. Additionally, I would like to dynamically set the left value of the position. ...

Exploring the Power of jQuery's Vote-Object and Scope

This is a coding dilemma related to JavaScript. The reference to this particular website is not necessary and therefore does not pertain to meta. In my current project, I am developing a Greasemonkey script that automatically loads more answers onto the i ...

Transmit JSON data from the client to the MarkLogic Server device

Hello everyone, hope you are all doing well. I am a beginner in Marklogic and recently managed to set up a rest api on my local machine. Following the given example, I used curl to send/create documents in the database. Now, my query is how can I access/ ...

Preventing typing during onKeyDown event in React/JavaScript and other languages

One of the reasons why I opt to use onKeyDown is because the language for typing is Korean. With multiple inputs on the page, my aim is to prevent users from typing more than 20 bytes. //this function calculates the byte length const getByteLength = (s,b ...

Encountering an issue with a Discord bot causing it to malfunction and deviate from its intended

Initially, everything appears to be functioning properly with the bot. When I execute the ?listen command, it responds correctly with bot is collecting messages now.... However, the ?stop command does not seem to have any effect. Furthermore, when I try th ...