I have a specific task to do, and I'm not sure what is the best way to do it.
I have around 60 unique checkboxes and when clicked, display some text on their right side (tied to that clicked checkbox).
I have done it with 64 specific eventListeners
, but I'm not sure that this is the best way: I would like to simplify the code.
So, for example, I have bunch of checkboxes in a label that is: test
, test1
, test2
and so on. And when I click on test
checkbox, that the text: "hello world" can appear, if test1
is checked, text: "One 2 three" can appear, if test2
is checked, text: "I've done it" can appear, but if none of them is selected, texts will not be displayed.
This is the code, one event listener I have now:
var forSale = document.querySelector('#for_sale');
var forSaleEmail = document.querySelector('#for_sale_email');
/*For Sale*/
forSale.addEventListener("click", function(){
if(forSale.checked === true){
forSaleEmail.style.display = 'block';
} else {
forSaleEmail.style.display = 'none';
}
});
Where the forSale
variable is a checkbox and forSaleEmail
is a text that should be displayed.
If you have any suggestions or you can tell me what to look for, it would be greatly appreciated.
HTML Code is as following:
<div><label>For Sale <input type="checkbox" id="for_sale"></label></div>
<div><span id="for_sale_email">
<p>
for sale
</p>
</span></div>
An option is event delegation, where you add one event handler to a parent/ancestor of all the input
's, and use the event property event.target
to detect the one that were clicked on, and simply toggle a class on its parents div
.
Combined with the CSS adjacent sibling selector +
it gets as simple as this
Note 1: Having a <p>
inside an inline element like a <span>
is not valid markup, so I removed it. If you need an extra, use another <span>
and give it similar style a <p>
has as default.
Note 2: id
needs to be unique so make sure you have that taken care of, and for your for_sale_email
it doesn't need to be, so I changed it to a class.
Note 3: If you want to "toggle" between the chosen input
's, I also added a code part that does that.
Stack snippet
document.querySelector('.inputs_parent').addEventListener('change', function(event) { // this will "hide" previous checked input var prev = this.querySelector('div.checked'); if (prev) { prev.classList.remove('checked'); prev.querySelector('input').checked = false; } // remove this "if" statement if won't use the above if (!prev || !prev.contains(event.target)) event.target.closest('div').classList.toggle('checked'); })
.for_sale_email { display: none; } div.checked + div .for_sale_email { display: inline-block; }
<div class="inputs_parent"> <div> <label>For Sale <input type="checkbox" id="for_sale1"> </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <div> <label>For Sale <input type="checkbox" id="for_sale2"> </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <div> <label>For Sale <input type="checkbox" id="for_sale3"> </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <div> <label>For Sale <input type="checkbox" id="for_sale4"> </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> </div>
If you can make a small markup change, you can actually accomplish this with CSS alone.
Stack snippet
.inputs_parent label:after { content: 'X'; display: inline-block; text-align: center; font-size: 12px; color: transparent; width: 12px; height: 12px; border: 1px solid black; margin-left: 5px; } .inputs_parent input, .inputs_parent .for_sale_email { display: none; } .inputs_parent input:checked + div label:after { color: black; } .inputs_parent input:checked + div + div .for_sale_email { display: inline-block; }
<div class="inputs_parent"> <input type="checkbox" id="for_sale1"> <div> <label for="for_sale1">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="checkbox" id="for_sale2"> <div> <label for="for_sale2">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="checkbox" id="for_sale3"> <div> <label for="for_sale3">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="checkbox" id="for_sale4"> <div> <label for="for_sale4">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> </div>
And this one toggle's the checked items, using an input type="radio"
.
Stack snippet
.inputs_parent label:after { content: 'X'; display: inline-block; text-align: center; font-size: 12px; color: transparent; width: 12px; height: 12px; border: 1px solid black; margin-left: 5px; } .inputs_parent input, .inputs_parent .for_sale_email { display: none; } .inputs_parent input:checked + div label:after { color: black; } .inputs_parent input:checked + div + div .for_sale_email { display: inline-block; }
<div class="inputs_parent"> <input type="radio" name="radio" id="for_sale1"> <div> <label for="for_sale1">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="radio" name="radio" id="for_sale2"> <div> <label for="for_sale2">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="radio" name="radio" id="for_sale3"> <div> <label for="for_sale3">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> <input type="radio" name="radio" id="for_sale4"> <div> <label for="for_sale4">For Sale </label> </div> <div> <span class="for_sale_email"> for sale </span> </div> </div>
Your code is totally fine, but you should definetly abstract it into a function:
function selectMessage(checkbockSelector, messageSelector) {
var checkbox = document.querySelector(checkboxSelector);
var message = document.querySelector(messageSelector);
checkbox.addEventListener("click", function(){
message.style.display = checkbox.selected ? 'block' : 'none';
});
}
So that you can just do:
selectMessage("#for_sale", "#for_sale_email");
If there are a lot of elements, it might be a good idea to change the HTML into a structure, that directly relates the labels with the input:
<div id="sale">
<label>For Sale</label>
<input type="checkbox" id="for_sale" class="withhint">
<span class="hint">
<p>for sale</p>
</span>
</div>
Then you can hide them with CSS by default:
.hint { display: none; }
And use javascript to apply the handler to all:
document.querySelectorAll(".withhint").forEach(function(input) {
const hint = input.parentElement.querySelector(".hint");
input.addEventListener("click", function() {
hint.style.display = input.checked ? "block" : "none";
});
});
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.