0

This code is a demonstration of two features, the checkboxes and the radios. A black-bordered box appears with two ways for you to change its style. Check on the checkbox to change the border to a 5px solid purple, uncheck it to go back to its initial 1px solid black. Use the radio buttons to change the background color of the box to either red, green or blue.

Pay special attention to the radio buttons. Red is set to "checked", meaning the box's color should have been set to red by default upon opening or refreshing this ask page, but it's not. Instead, there is no color, and in order to make the box turn red, you have to force it by clicking on the red radio dial. Compare that to the checkbox input, where the behavior of toggling between checked and unchecked parameters works as intended.

I've always thought that whatever item is labelled "checked" is automatically active, provided the check declarations are made within your Javascript. In the border checkbox toggle example (see border.addEventListener), the original fallback option was set to "initial," and in this case the box would go back to its 1px solid black style. However, the "initial" keyword did not work, for the entire border disappeared during my test, so I had to explicitly state "1px solid black" in that same line as an insurance measure.

My initial question was on why the "checked" feature works better on checkboxes instead of radios, but to be blunt, I need a better grasp on how the "checked" feature works when it comes to Javascript. How do I rewrite this code so that when I open this web page, the box will have automatically changed color to whatever value was set? If red was "checked", the box is already red, and so on.

function changeBorder() { const monitor = document.querySelector(".Screen"); const border = document.getElementById("ScreenBorder"); border.addEventListener("change", () => { border.checked ? monitor.style.border = "5px solid purple" : monitor.style.border = "1px solid black"; }); } function changeBG() { const screen = document.querySelector(".Screen"); const screenbackground = document.querySelectorAll('INPUT[name="r"]'); screenbackground.forEach(radio => { radio.addEventListener('click', () => { const bgColor = radio.value; screen.style.background = bgColor; }); }); } changeBorder(); changeBG();
DIV.Screen { border: 1px solid black; width: 256px; height: 256px; }
<DIV class="Screen"></DIV> <P> <INPUT type="radio" name="r" value="red" checked>Red <INPUT type="radio" name="r" value="blue">Blue <INPUT type="radio" name="r" value="green">Green </P> <P><INPUT id="ScreenBorder" type="checkbox" name="checkbox" />Violet Border</P>

3 Answers 3

3

You were adding handlers for the radio/checkbox, but did nothing to check their status on loading the document.

The actual value of a radio group can be acquired using document.querySelector([radio]:checked). For radio groups and checkboxes the you can use a input listener/handler.

I would suggest using event delegation for listening and handling events and using small functions for changing the background-/border properties on start and for the handling. Something like:

document.addEventListener(`input`, handle); load(); // apply the background/border values on start function load() { const radioValue = document.querySelector(`[name='r']:checked`).value; const cbValue = document.querySelector(`#ScreenBorder`).checked; setBackground(radioValue); setBorder(cbValue); } function setBorder(checked) { document.querySelector(".Screen") .style.border = checked ? `5px solid purple` : `5px solid transparent`; } function setBackground(radioValue) { document.querySelector(".Screen") .style.background = radioValue; } function handle(evt) { if (evt.target.name === `r` ) { return setBackground(evt.target.value); } if (evt.target.id === `ScreenBorder`) { return setBorder(evt.target.checked); } }
.Screen { border: 5px solid transparent; width: 50px; height: 50px; outline: 1px solid black; }
<!-- note: a label facilitates clicking --> <DIV class="Screen"></DIV> <P> <label><INPUT type="radio" name="r" value="red" checked>Red</label> <label><INPUT type="radio" name="r" value="blue">Blue</label> <label><INPUT type="radio" name="r" value="green">Green</label> </P> <P> <label> <INPUT id="ScreenBorder" type="checkbox" name="checkbox" />Violet Border </label> </P>

Sign up to request clarification or add additional context in comments.

Comments

2

Maybe this feels like going over the top after reading the answer from Gary (I would have suggested a similar solution). That said, here is a suggestion using JavaScript that is maybe useful in a more complex scenario.

JavaScript does not know the connection between the values of the form fields (radio buttons and checkboxes) and the state of the #Screen element. When the page is loaded you have to align the two states. My suggestion is to use a FormData object created from the controls form (the form element that wraps all the form fields). The object could be considered as the state of the page. And then make sure that the state of the #Screen is the same.

Please ask if there are things in the example that needs to be clarified.

document.addEventListener('DOMContentLoaded', e => { let controls = document.forms.controls; // Update the state of #Screen let data = new FormData(controls); [...data].forEach(arr => controlsStateHandler(arr[0], arr[1], true)); // Add event listeners for controls controls.addEventListener('change', e => { controlsStateHandler(e.target.name, e.target.value, e.target.checked); }); }); function controlsStateHandler(key, value, state){ switch(key){ case 'background': changeBackground(value); break; case 'border': changeBorder(value, state); break; } } function changeBorder(color, state) { let screen = document.querySelector("#Screen"); screen.classList.toggle(`border_${color}`, state); } function changeBackground(color) { let screen = document.querySelector("#Screen"); screen.style.background = color; }
div#Screen { border: 5px solid black; width: 256px; height: 256px; } div#Screen.border_violet { border: 5px solid violet; } div#Screen.border_orange { border: 5px solid orange; } div#Screen.border_violet.border_orange { border: 5px solid lime; }
<div id="Screen"></div> <form name="controls"> <p> <label><input type="radio" name="background" value="red" checked>Red</label> <label><input type="radio" name="background" value="blue">Blue</label> <label><input type="radio" name="background" value="green">Green</label> </p> <p> <label><input type="checkbox" name="border" value="violet">Violet Border</label> <label><input type="checkbox" name="border" value="orange">Orange Border</label> </p> </form>

2 Comments

I never knew you could mix colors together like that, Chrwahl. That said, this could be something I might implement in the future. EDIT: What does the ellipses in front of data mean?
1

Your function isn't doing anything regarding testing for checked upon load; but is only adding the event to do so. That is why it is not styled at load. It is set to checked as indicated by the fact that the radio button for color red is selected.

In addition, you don't really need to have a change event but can accomplish this in CSS only using :checked pseudo class, as shown in the snippet below. If you need to do more than style upon a radio selection and need the change event, there are many questions on how to determine which radio button in a name set is selected upon change event.

Also, if you want clicks on the text of the colors to change the radio buttons you need to add them as labels. See https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/radio. You need to use for to connect the label to the input. You can also nest the input within the label and not need the for. See https://css-tricks.com/html-inputs-and-labels-a-love-story/.

DIV.Screen { border: 1px solid black; width: 256px; height: 256px; } .Screen:has( + p > input[value="red"]:checked) { background-color: red; } .Screen:has( + p > input[value="blue"]:checked) { background-color: blue; } .Screen:has( + p > input[value="green"]:checked) { background-color: green; }
<DIV class="Screen"></DIV> <P> <INPUT type="radio" name="r" value="red" checked />Red <INPUT type="radio" name="r" value="blue" />Blue <INPUT type="radio" name="r" value="green" />Green </P> <P><INPUT id="ScreenBorder" type="checkbox" name="checkbox">Violet Border</P>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.