Reputation: 217
I'm having trouble getting a div ('.option-other') within a parent group ('.other-row') to show/hide when the corresponding option of the select element ('.select-toggle') is selected. Right now if "other" is selected from either question set 1 or 2 it will show both of the '.option-other' divs. I tried using .parent() and .closest() as described in this solution, but can't seem to figure out the proper way to utilize it for this use case.
$(".select-toggle").change(function() {
var oth = false;
$(".select-toggle option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
if (oth) $('.option-other').show();
else $('.option-other').hide();
// tried this method as well but still doesnt work
// if (oth) $(this).closest('.other-row').children('.option-other').show();
// else $(this).closest('.other-row').children('.option-other').hide();
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
Upvotes: 1
Views: 556
Reputation: 5171
// you wrote:
// tried this method as well but still doesnt work
// if (oth) $(this).closest('.other-row').children('.option-other').show();
// else $(this).closest('.other-row').children('.option-other').hide();
You're close, but $.children
only selects direct children of each .other-row
. Since .option-other
is inside .col
inside .other-row
, $.children
can't see it. Use $.find
instead.
// your original code:
var oth = false;
$(".select-toggle option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
This sets one visibility value for the entire page: if at least one "other" option is selected, anywhere, show all the text inputs. The change
event is fired for the <select>
that actually changed, so focus your efforts there:
var oth = false;
$(this).children("option:selected").each(function() {
if ($(this).val() == "other") oth = true;
});
if (oth) $(this).closest('.other-row').find('.option-other').show();
else $(this).closest('.other-row').find('.option-other').hide();
This works, but it could be cleaner. Showing or hiding an element based on a boolean is a common enough requirement that jQuery has a function for it: $.toggle
. You can replace the if/else
lines with
$(this).closest('.other-row').find('.option-other').toggle(oth);
Your $.each
loop does one thing: set oth
if there exists at least one selected <option>
with a value of "other"
. You can get the same logic as a one-liner by using an attribute selector:
var oth = ($(this).find('option:checked[value="other"]').length !== 0);
(I changed :selected
to :checked
because you're already filtering on option
elements, and :selected
has a performance penalty.)
The final version:
$(".select-toggle").change(function() {
var oth = ($(this).find('option:checked[value="other"]').length !== 0);
$(this).closest('.other-row').find('.option-other').toggle(oth);
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like" />
</div>
</div>
</div>
Vanilla JS version:
document.querySelectorAll('.select-toggle').forEach(el => {
el.addEventListener('change', evt => {
const oth = evt.target.querySelector('option:checked[value="other"]');
evt.target
.closest('.other-row')
.querySelector('.option-other')
.style.display = (oth ? '' : 'none');
});
// trigger change event programmatically
const event = document.createEvent('HTMLEvents');
event.initEvent('change', true, false);
el.dispatchEvent(event);
});
Upvotes: 1
Reputation: 416
Here is a solution that is a little clunky but I did it relatively quick. It's kind of a work around for having to know which of your two selectors with the same class had been selected.
Here is a working example using your code.
$(".select-toggle").change(function () {
var oth = false;
$(".select-toggle option:selected").each(function () {
if ($(this).val() == "otherFood") {
oth = true;
$('.option-other-food').show();
} else {
$('.option-other-food').hide();
};
if ($(this).val() == "otherDrink") {
oth = true;
$('.option-other-drink').show();
} else {
$('.option-other-drink').hide();
};
});
}).change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Question set 1 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you eat?</label>
<select class="select-toggle" multiple>
<option>Pizza</option>
<option>Cake</option>
<option value="otherFood">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other-food">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like"/>
</div>
</div>
</div>
<!-- Question set 2 -->
<div class="wrapper other-row">
<div class="col">
<div class="form-group">
<label>What stuff do you drink?</label>
<select class="select-toggle" multiple>
<option>Water</option>
<option>Soda</option>
<option value="otherDrink">Other</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group option-other-drink">
<label>Other</label>
<input type="text" placeholder="what other stuff do you like"/>
</div>
</div>
</div>
Cheers!
Upvotes: 0