简体   繁体   中英

How to show specific text if one specific checkbox is checked among bunch of unique checkboxes

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";
  });
});

Try it!

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