I am having some problems regarding the jquery event handler function. I couldn't understand how can I set it in the correct way. I will explain my problem, I have three checkboxes: 3D, TRI-Planar, and MPR. And when users check the 3D option the following two checkboxes appear Volume and Sur. In my HTML page, I am passing below first inputs which have a class = desire_viewer to create three checkboxes, and below class= method_selection to create two checkbox vol and sur. After going through some StackOverflow posts, I have created the below script and somehow it works but not 100% accurately. For example: when I click checkboxes it doesn't appear but when I unclick it then it appears and again if I click it then it disappears and again unclicks and it will go up and down twice and then it dissaper so weird.
<input type="checkbox" name="Viewers" id="v1" value="3D"><label for="v1">3D</label>
<input type="checkbox" name="Viewers" id="v2" value="TRI-Planar"><label for="v2">TRI-Planar</label>
<input type="checkbox" name="Viewers" id="v3" value="MPR"><label for="v3">MPR</label>
<input type="checkbox" name="Render" id="r1" value="Vol" ><label for="r1">Vol</label>
<input type="checkbox" name="Render" id="r2" value="Sur" ><label for="r2">Sur</label>
<script>
ID_3D_render_selection = "#v1"
ID_tri_planar = "#v2"
ID_mpr_selection = "#v3"
ID_vol_selection = "#r1"
ID_sur_selection = "#r2"
ID_desire_viewer = '.desire_viewer'
var tri_arr = []
$(document).ready(function(){
$(ID_desire_viewer).click(function() {
var value = $("input[name='Viewers']:checked").val();
console.log(value)
if (value == "3D") {
console.log($(ID_3D_render_selection).click(function() {
$('#select_render_method').slideToggle("slow");
}));
} else if (value == "TRI-Planar") {
console.log($(ID_tri_planar).click(function() {
$('#TRI_PLANAR_OPTIONS').slideToggle("slow");
}));
$( "#btn1" ).change(function() {
var tri_myFile = $('#btn1').prop('files');
tri_arr.push(tri_myFile)
});
$( "#btn2" ).click(function() {
tri_processFile(tri_arr)
});
<!-- console.log(value)-->
} else if (value == "MPR") {
console.log($(ID_mpr_selection).click(function() {
$('#MPR_OPTIONS').slideToggle("slow");
}));
<!-- console.log(value)-->
}
<!-- console.log(value)-->
});
});
</script>
What kind of output do I expect? I expect when the user clicks the 3D checkbox then below two checkboxes should appear with option vol and sur and if again the user clicks vol then it's an option should appear and vice-versa for sur. Furthermore, if users select TRI-Planar or MPR checkboxes then their specific options should appear using the .slidetogle option. For better understanding: I have posted pictures where I click on the TRI-PLANAR checkbox but the option didn't appear when I unclick it then it appears.
I hope someone can help me to solve this problem. Thank you.
CodePudding user response:
Try this
$('input["type=checkbox"]').attr("checked",'false');
i hope it was useful !
CodePudding user response:
Problem 1:
var value = $("input[name='Viewers']:checked").val();
The selector will match all 3 of your checkboxes. But what will the .val()
of 3 elements look like? Quoting the docs for .val()
:
Get the current value of the first element in the set of matched elements.
So you're only ever going to get one of your checkbox values, the first checked one. Try it:
$('.desire_viewer').on('click', function() {
console.log($('.desire_viewer:checked').val());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" name="Viewers" value="3D">3D
<input type="checkbox" name="Viewers" value="TRI-Planar">TRI-Planar
<input type="checkbox" name="Viewers" value="MPR">MPR
So how do you check if a particular checkbox is checked? As you can imagine this is a pretty common problem and there are a lot of duplicates here, eg:
- Getting all selected checkboxes in an array
- Get checkboxes (with the same name) as array
- Send same name multiple checkbox values via ajax
You need to iterate over each of the inputs, like so:
$('.desire_viewer').on('click', function() {
console.log('These are now checked:');
$('.desire_viewer:checked').each(function(i) {
console.log(i, ':', $(this).val());
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" name="Viewers" value="3D">3D
<input type="checkbox" name="Viewers" value="TRI-Planar">TRI-Planar
<input type="checkbox" name="Viewers" value="MPR">MPR
Note that inside the loop, $(this)
represents the current jQuery object in the loop.
So in your case, your code might look something like:
$('.desire_viewer').on('click', function() {
$('.desire_viewer:checked').each(function(i) {
var val = $(this).val();
if (value == "3D") {
// Do stuff ...
} else if (value == "TRI-Planar") {
// Do other stuff ...
} else if (value == "MPR") {
// Do other different stuff ...
}
});
});
Problem 2:
$( "#btn1" ).change(function() {
This adds an event handler to your button. From this point on, any time that button is changed this handler will notice, and that function code will fire.
That's fine and will work. The problem is where it is added - when a checkbox is clicked. If the user decides they made a mistake and UNticks the TRI-Planar
checkbox, guess what happens? Another identical event handler will be added to the button. And the best part? They will both fire! The handler function, whatever it is, will run 2x, in parallel. They don't overwrite each other, they all stack up, and they all run.
The (simplest) solution is to add event handlers independent of user interaction or other changes on the page, so they can only be bound once. If the code that runs is somehow dependent on where/when it would be triggered, set that up in the handler. Eg if this button change should only do something if TRI-Planar
is checked, have the button event handler check if that is true before doing anything. Eg:
$("#btn1").change(function() {
// Maybe this should only happen if a certain checkbox is checked
$('.desire_viewer:checked').each(function(i) {
var val = $(this).val();
if (value == "TRI-Planar") {
// Do stuff
}
});
});
// Rest of your code - handlers are independent of user interaction and
// will only be bound once.
$('.desire_viewer').on('click', function() {
// ...
Note another option is to add handlers wherever you like, and use .off()
to remove them, so you can dynamically add/remove them throughout your code. For simple applications I don't think this extra complexity is necessary.
There are lots of questions here about this too:
- Is it correct to put an event inside an event?
- jQuery click events firing multiple times
- why is jQuery click event firing multiple times
Minor suggestion:
It looks like this is part of a bigger applicaton, and it looks like you're trying to reduce code repetition with variables like ID_desire_viewer = '.desire_viewer'
etc. That's a good start but since those represent jQuery selectors, you may as well go just a tiny bit further and cache the actual selector.
Every time you do something like $(ID_desire_viewer)
jQuery scans the whole DOM again to find matches. For small applications/pages you probably won't notice the performance hit doing that, but it is good practice to avoid it in case your app grows, and just in terms of read- and maintain-ability, DRY, etc.
To avoid that, save the results of the first search by doing:
let $viewers = $('.desire_viewer');
// Then you can do:
$viewers.on('click', function() { ...
Some references about that: