Home > Enterprise >  changing css style with javascript
changing css style with javascript

Time:09-30

I wrote a html with 3 radio buttons. Each radio button is contained in a div container. I would like that if a radio button is checked, the background of the div container containing the checked radio-button should become blue, and the background the div containing the other unchecked radio-buttons should be white. I tried to achieve that with javascript and css, but it does not work. Could someone please help me to write correctly this javascript ?.

<!DOCTYPE html>
<html>
<style>
  .stylingForCheckedRadioButton {
    color: white;
    background-color: blue;
    border-style: solid;
    border-width: thin;
    border-color: grey;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }

  .stylingForUnCheckedRadioButton {
    color: black;
    background-color: white;
    border-style: groove;
    border-width: thin;
    border-color: #DCDCDC;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }
</style>

<script type="text/javascript">
function checkValue(containerId) {
    const rbs = document.querySelectorAll('input[name = "radiobutton"]');
    let selectedValue;
    for (const rb of rbs) {
      if (rb.checked) {
        document.getElementById(containerId).style = "stylingForCheckedRadioButton";
      }else{
        document.getElementById(containerId).style  = "stylingForUnCheckedRadioButton";
      }
    }
  };

</script>
<body>

<h1>My Radio Buttons</h1>
<div class="stylingForUnCheckedRadioButton" id="container1">
  <input id="radiobuttonId1" type="radio" value="radiobuttonId1" name="radiobutton" onclick="checkValue('container1')">
  <label for="radiobuttonId1">Radio button 1</label>
</div>

<div class="stylingForUnCheckedRadioButton" id="container2">
  <input id="radiobuttonId2" type="radio" value="radiobuttonId2" name="radiobutton" onclick="checkValue('container3')">
  <label for="radiobuttonId2">Radio button 2</label>
</div>

<div class="stylingForUnCheckedRadioButton" id="container3">
  <input id="radiobuttonId3" type="radio" value="radiobuttonId3" name="radiobutton" onclick="checkValue('container3')">
  <label for="radiobuttonId3">Radio button 3</label>
</div>
</body>
</html>

CodePudding user response:

I recommend to read some topics on DRY.

const radios = document.querySelectorAll('.radio')

// Function to switch classes of containers
function handleRadioClick(e) {
  // Current container
  const container = e.target.parentNode
  
  // Remove previous classes
  for (let i = 0; i < radios.length; i  ) {
    radios[i].parentNode.classList.remove('container-checked')
    radios[i].parentNode.classList.add('container-unchecked')
  }
  
  // Add current classes
  container.classList.remove('container-unchecked')
  container.classList.add('container-checked')
}

// Listen for the click event on radios
for (let i = 0; i < radios.length; i  ) {
    radios[i].addEventListener('click', handleRadioClick, false);
}
  .container-checked {
    color: white;
    background-color: blue;
    border-style: solid;
    border-width: thin;
    border-color: grey;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }

  .container-unchecked {
    color: black;
    background-color: white;
    border-style: groove;
    border-width: thin;
    border-color: #DCDCDC;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }
  <div class="container-unchecked" id="container1">
    <input class="radio" id="btn1" type="radio" value="btn1" name="radio">
    <label for="btn1">Radio button 1</label>
  </div>

  <div class="container-unchecked" id="container2">
    <input class="radio" id="btn2" type="radio" value="btn2" name="radio">
    <label for="btn2">Radio button 2</label>
  </div>

  <div class="container-unchecked" id="container3">
    <input class="radio" id="btn3" type="radio" value="btn3" name="radio">
    <label for="btn3">Radio button 3</label>
  </div>

CodePudding user response:

this way...

const all_Radios = document.querySelectorAll('#container input[type=radio]');

set_Radios()  // for page initialization

all_Radios.forEach( btRadio => btRadio.oninput = set_Radios )

function set_Radios()
  {
  all_Radios.forEach( bt => 
    bt.closest('label').classList.toggle('checkedClass', bt.checked))
  }
#container > label {
  display          : block;
  color            : black;
  background-color : white;
  border-style     : groove;
  border-width     : thin;
  border-color     : #DCDCDC;
  margin-bottom    : 7px;
  width            : 10%;
  height           : 2em;
  border-radius    : 6px;
  min-width        : 10em;
  line-height     : 2em;
  }
#container > label.checkedClass {
  color            : white;
  background-color : blue;
  border-style     : solid;
  border-color     : grey;
  }
<h1>My Radio Buttons</h1>

<div id="container">
  <label>
    <input name="radiobutton" type="radio" value="xxx" >
    Radio button 1
  </label>  
  <label>
    <input name="radiobutton" type="radio" value="yyy" >
    Radio button 2
  </label>  
  <label>
    <input name="radiobutton" type="radio" value="zzz" >
    Radio button 3
  </label>  
</div>

CodePudding user response:

You can use the event.target to get the parentNode of the input element to set the style using classList.replace(). Each click reset the classes of the parent elements to unchecked, then if the event.target is checked e.target.checked, replace the unchecked class with the checked class.

const rbs = document.querySelectorAll('input[name = "radiobutton"]');

// callback function setSel passing in the event from the listener
function setSel(e) {
  // get parent element of the event target
  let par = e.target.parentNode
  // reset each input to unchecked before checking the event target
  rbs.forEach(item => item.parentNode.classList.replace('stylingForCheckedRadioButton', 'stylingForUnCheckedRadioButton'))
  // if the el is checked we replace the classList with  
  // the desired class that styles as checked
  e.target.checked ?
    par.classList.replace('stylingForUnCheckedRadioButton', 'stylingForCheckedRadioButton') :
    null
}

// loop over the input nodeList and add event to each node 
// in the list with a callback function 'setSel'
rbs.forEach(el => el.addEventListener('click', setSel))
.stylingForCheckedRadioButton {
  background-color: red;
}
<!DOCTYPE html>
<html>
<style>
  .stylingForCheckedRadioButton {
    color: white;
    background-color: blue;
    border-style: solid;
    border-width: thin;
    border-color: grey;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }
  
  .stylingForUnCheckedRadioButton {
    color: black;
    background-color: white;
    border-style: groove;
    border-width: thin;
    border-color: #DCDCDC;
    margin-bottom: 7px;
    width: 10%;
    height: 50px;
    border-radius: 6px;
  }
</style>

<script type="text/javascript">
</script>

<body>

  <h1>My Radio Buttons</h1>
  <div class="container stylingForUnCheckedRadioButton" id="container1">
    <input id="radiobuttonId1" type="radio" value="radiobuttonId1" name="radiobutton">
    <label for="radiobuttonId1">Radio button 1</label>
  </div>

  <div class="container stylingForUnCheckedRadioButton" id="container2">
    <input id="radiobuttonId2" type="radio" value="radiobuttonId2" name="radiobutton">
    <label for="radiobuttonId2">Radio button 2</label>
  </div>

  <div class="container stylingForUnCheckedRadioButton" id="container3">
    <input id="radiobuttonId3" type="radio" value="radiobuttonId3" name="radiobutton">
    <label for="radiobuttonId3">Radio button 3</label>
  </div>
</body>

</html>

CodePudding user response:

There are two main issues here. First, you should use the className attribute instead of style to change the element class. Secondly, in your function, JavaScript is setting the color of the divs based on the last value in the rbs nodeList. This means that your intended div will be styled according to whether or not the last radio button is checked. To change this, query the DOM for a list of all the divs then check each div according to its corresponding radio button based on index.

function checkValue() {
  const rbs = document.querySelectorAll('input[name = "radiobutton"]');
  rbs.forEach((rb, i) => {
    let div = document.getElementById(`container${i   1}`);
    div.className = rb.checked ? 'stylingForCheckedRadioButton' : 'stylingForUnCheckedRadioButton';
  })
};
.stylingForCheckedRadioButton {
  color: white;
  background-color: blue;
  border-style: solid;
  border-width: thin;
  border-color: grey;
  margin-bottom: 7px;
  width: 10%;
  min-width: 150px;
  height: 50px;
  border-radius: 6px;
}

.stylingForUnCheckedRadioButton {
  color: black;
  background-color: white;
  border-style: groove;
  border-width: thin;
  border-color: #DCDCDC;
  margin-bottom: 7px;
  width: 10%;
  min-width: 150px;
  height: 50px;
  border-radius: 6px;
}
<!DOCTYPE html>
<html>

<body>

  <h1>My Radio Buttons</h1>
  <div class="stylingForUnCheckedRadioButton" id="container1">
    <input id="radiobuttonId1" type="radio" value="radiobuttonId1" name="radiobutton" onclick="checkValue()">
    <label for="radiobuttonId1">Radio button 1</label>
  </div>

  <div class="stylingForUnCheckedRadioButton" id="container2">
    <input id="radiobuttonId2" type="radio" value="radiobuttonId2" name="radiobutton" onclick="checkValue()">
    <label for="radiobuttonId2">Radio button 2</label>
  </div>

  <div class="stylingForUnCheckedRadioButton" id="container3">
    <input id="radiobuttonId3" type="radio" value="radiobuttonId3" name="radiobutton" onclick="checkValue()">
    <label for="radiobuttonId3">Radio button 3</label>
  </div>
</body>

</html>

  • Related