Reputation: 47
I am changing the default look of radio buttons on a form. In order to do this, I've added a span tag after the input tag with jQuery. This works fine for the radio buttons that are rendered on pageload. However, the form uses conditionals to hide two questions which do not get the span added after the input because they don't exist until they're conditionally shown. The form has a js hook that fires when new fields are conditionally added which I am hooking into. My problem is, if a user conditionally reveals both questions, this span element is added multiple times when I only need it added once.
I've tried to check for duplicate span tags to remove after creating the new ones, but I have not got it to work. I tried saving the newly created radio buttons in a nodelist and loop through them, but that ended up adding as many span tags as the length of the nodelist.
<!-- here is the html, the span is needed after the input tag -->
<div class="radio">
<label>
<input type="radio">
</label>
</div>
// Adds the span to the hidden elements as they are revealed
$(document).on('cf.add', function() {
if ($('.caldera-forms-conditional-field .radio input[type=radio] .radiomark').length == 0) {
$(".caldera-forms-conditional-field .radio input[type=radio]").after("<span class='radiomark'></span>");
}
});
It is adding the span as needed, but the problem is that when that js hook fires again, it adds additional span tags to each radio button. If a user changes an answer on a radio button that triggers the hook, it adds more span tags. Is there a way to check for multiple span tags and remove the duplicates?
Upvotes: 3
Views: 308
Reputation: 171669
No need to use a conditional to check for length. You can use has()
and not()
combination to filter only labels that don't have the radiomark
and use append()
$('div.radio label').not(':has(.radiomark)').append('<span class="radiomark"></span>')
.radiomark:after { content: 'Radio Mark'; color: red}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="radio">
<label>
<input type="radio">
</label>
</div>
Upvotes: 1
Reputation: 3579
You are using a descendant (space between selectors) selector. It looks for any elements that are children of or lower sub-elements. Instead, you are placing the span after the input within the same parent. What you want is the adjacent sibling selector (+) to prevent adding additional spans if the span already exists. The sibling selector looks for elements that have the same parent as the input element and come after the input element
E.g.
<div class="radio"><!-- this is an element -->
<label><!-- this is both a child and descendant of the div.radio element -->
<input type="radio"><!-- this is a descendant of the div.radio element -->
</label>
</div>
However,
<div class="radio">
<label>
<input type="radio"> <!-- This is the element you are looking for -->
</label>
</div>
After the script is called once,
<div class="radio">
<label>
<input type="radio">
<span class="radiomark"></span><!-- This element gets added, it is a sibling of the input element -->
</label>
</div>
So, use + to look for the sibling:
$(document).on('cf.add', function() {
if ($('.caldera-forms-conditional-field .radio input[type=radio] + .radiomark').length == 0) {
$(".caldera-forms-conditional-field .radio input[type=radio]").after("<span class='radiomark'></span>");
}
});
Upvotes: 1