简体   繁体   中英

How to use JavaScript to Alter CSS for Multiple Elements

I am trying to use JavaScript to change the background color of an element after being selected, and also to make sure that only one element at a time has the particular background color. Once the user selects on a different element I would like the previous element that was selected to be replaced by a different background color. Currently I am only able to toggle individual elements by selecting on EACH element. I need to be able to select on an element and apply the new background color, then have JavaScript change the background color of the previously active element to a different color (one less click).

What I am trying to do is very similar to modern navbars or list items where only one element at a time is “active” and has a background color that is different than the other elements in the same div, row, etc.

Notes about my work I am utilizing bootstrap and have no desire to use jQuery for this particular project.

CSS:

<!DOCTYPE html>
<html lang="en">
    <head>
        <style>
            h4 {
                border: 1px solid black;
                border-radius: 8px;
                padding: 10px 2px 10px 2px;
                margin: 20px 20px 0px 20px;
                background-color: #F0F0F0;
                border-color: #F8F8F8;
                color: #505050;
                cursor: pointer;
            }

            .active {
                background-color: #99E6FF;
            }
        </style>
    </head>
</html>

HTML:

<div id="pTwoRowOne">
    <div class="row">
        <div class="col-md-4 row row-centered">
            <h4 id="techBio" class="test">Biology</h4>
        </div>
        <div class="col-md-4 row row-centered">
            <h4 id="techCart" class="test">Cartography</h4>
        </div>
        <div class="col-md-4 row row-centered">
            <h4 id="techChem" class="test">Chemistry</h4>
        </div>
    </div>
</div>

JavaScript:

document.getElementById("techBio").onclick=function() {
    document.getElementById("techBio").classList.toggle('active');
}

document.getElementById("techCart").onclick=function() {
    document.getElementById("techCart").classList.toggle('active');
}

document.getElementById("techChem").onclick=function() {
    document.getElementById("techChem").classList.toggle('active');
}

An example can be seen here: http://jsbin.com/fugogarove/1/edit?html,css,js,output

If clarification is needed let me know.

Yup, pretty straightforward.

Assumptions

  1. You're not trying to support IE8, since you're using classList
  2. You're okay with housing your elements as variables as opposed to repeatedly querying the DOM.

Example

JSBin

Code

I rewrote your JavaScript to make it a little bit cleaner and to DRY it up a bit:

var techs = [].slice.call(document.querySelectorAll('#pTwoRowOne h4'));

function set_active(event) {
  techs.forEach(function(tech){
    if (event.target == tech) { return; }
    tech.classList.remove('active');
  });
  event.target.classList.toggle('active');
}

techs.forEach(function(item) {
  item.addEventListener('click', set_active);
});

Some explanation

[].slice.call(document.querySelectorAll('#pTwoRowOne h4')); – We're using this to change the output from a NodeList to an Array . This allows us to use forEach later. querySelectorAll returns a NodeList that contains all elements matching the CSS selector. You can probably replace that with a better CSS selector depending on your environment.

addEventListener is a much nicer way than the iterative add via onclick += to bind an event listener. It's also the recommended way (as far as I know) in ECMA5 and later.

By setting the element queries as variables, you'll be able to keep the reference in memory instead of polling the DOM every time to alter elements. That'll make your JavaScript marginally faster, and it's again just a nicer, cleaner version of the code which it produces.

updates

I reworked the JS to make more sense.

Assuming you only ever have one active element, you can find it using document.querySelector() - if you can have multiples you can use document.querySelectorAll() and iterate through them.

Simple case:

 function activate(event) { var active=document.querySelector('.active'); // activate the clicked element (even if it was already active) event.target.classList.add('active'); // deactivate the previously-active element (even if it was the clicked one => toggle) if (active) active.classList.remove('active'); } document.getElementById("techBio").addEventListener("click",activate); document.getElementById("techCart").addEventListener("click",activate); document.getElementById("techChem").addEventListener("click",activate); 
 h4 { border: 1px solid black; border-radius: 8px; padding: 10px 2px 10px 2px; margin: 20px 20px 0px 20px; background-color: #F0F0F0; border-color: #F8F8F8; color: #505050; cursor: pointer; } .active { background-color: #99E6FF; } 
 <div id="pTwoRowOne"> <div class="row"> <div class="col-md-4 row row-centered"> <h4 id="techBio" class="test">Biology</h4> </div> <div class="col-md-4 row row-centered"> <h4 id="techCart" class="test">Cartography</h4> </div> <div class="col-md-4 row row-centered"> <h4 id="techChem" class="test">Chemistry</h4> </div> </div> </div> 

You can do something like this:

[].slice.call(document.querySelectorAll(".test")).forEach(function(element) {
  element.addEventListener('click', function(event) {
    if (activeElement = document.querySelector(".test.active")) {
      activeElement.classList.remove("active");
    };
    event.target.classList.add('active');
  });
});

Basically, first we remove the active class from the active element, then we add it to the target.

JSBin

Another similar yet simpler way to do it: jsBin ;)

var H4 = document.getElementsByClassName("test"), act;

[].forEach.call(H4, function(el){
    el.addEventListener("click", function(){
       if(act) act.classList.remove("active");
       return (this.classList.toggle("active"), act=this);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM