Reputation: 45
Working on a form validation function which produces a list of empty fields and a list of incorrectly-filled fields. The script functions perfectly for text and text-areas. When I apply the following method to radio buttons:
$("input:radio[name]").each(function() {
$(this).removeClass("error"); // Remove previously-applied error class
if($(this).filter(":checked").length == 0) { // Make sure they chose an option.
emptys[j] = nameFix($(this).attr("name")); // Add to array, apply error class
$(this).addClass("error"); // increment placeholder and exit
j ++; // the function
return;
} else {
return;
}
}); // end radio each
unanswered radio groups produce 2 indices in emptys
and answered radio groups produce 1 index (I'm testing on a page where the user indicates whether tests were passed or failed).
The universally-accepted answers I've found so far all assume I will use specific attributes I've given the <input>
tags in my JS. The site I'm building will have dozens of various forms which will require validation, so I'm trying to produce a universally-applicable script to check their validity.
EDIT: sample of HTML
<tr>
<td class="borderRight">Methane Overpressure</td>
<td>Target Pressure (psi)</td>
<td>300</td>
<td>± 1.0</td>
<td class="input"><input type="text" name="Target-Pressure" class="num" size="2" maxlength="5"></td>
<td class="input"><input type="radio" name="Target-Pressure-Pass-or-Fail" value="1"> P</td>
<td class="input">F <input type="radio" name="Target-Pressure-Pass-or-Fail" value="0"></td>
</tr>
<tr>
<td class="borderRight">Magnet</td>
<td>Magnetic Field Strength (T)</td>
<td>4.5</td>
<td>± 0.5</td>
<td class="input"><input type="text" name="Magnetic-Field-Strength" class="num" size="2" maxlength="4"></td>
<td class="input"><input type="radio" name="Magnetic-Field-Strength-Pass-or-Fail" value="1"> P</td>
<td class="input">F <input type="radio" name="Magnetic-Field-Strength-Pass-or-Fail" value="0"></td>
</tr>
<tr>
<td rowspan="2" class="borderRight">Acceleration</td>
<td>Radio Frequency (MHz)</td>
<td>68</td>
<td>± 0.1</td>
<td class="input"><input type="text" name="Radio-Frequency" class="num" size="2" maxlength="5"></td>
<td class="input"><input type="radio" name="Radio-Frequency-Pass-or-Fail" value="1"> P</td>
<td class="input">F <input type="radio" name="Radio-Frequency-Pass-or-Fail" value="0"></td>
</tr>
Upvotes: 0
Views: 263
Reputation: 45
This is the snippet which successfully analyzed the radios by group and allowed the script to run to completion.
var rgroup = new Array();
$(":radio").each(function() {
rgroup[this.name] = true;
});
for (group in rgroup) {
if (!!$(":radio[name=" + group + "]:checked").length) {
$(":radio[name=" + group + "]").removeClass("error");
} else {
$(":radio[name=" + group + "]").addClass("error");
emptys[j] = nameFix(group);
j ++;
}
}
I don't know why I couldn't get David Thomas's answer to work, it was very well written. I have a suspicion it has to do with the $.unique pulling up every single radio button because, as charlieftl pointed out, I did give the different answers binary values (so that the server will have something to work with). Though my script did not even reach the point of building the error message (or even rejecting the submission). I imagine that I'll be able to extend this technique to checkboxes when I eventually build a form which uses them.
Thank you both for helping me through this, I am impressed with both the quality and speed of your aid. And now to clock out of work...
Upvotes: 0
Reputation: 253308
A simple approach (written prior to your appending your HTML in your question) is:
function checkForChecked() {
// use $.unique() to get the unique values from an array (created within),
// gets all inputs of type="radio" with a 'name' attribute,
// creates a map of those elements' names, uses 'get()' to make that a
// real array
var radioGroups = $.unique($('input[type="radio"][name]').map(function () {
return this.name;
}).get());
// iterates over the array of group names ('a' is the current array element)
radioGroups.forEach(function (a) {
// caching the radio-inputs of the current name:
var sel = $('input[type="radio"][name="' + a + '"]');
// gets the parent elements of those radios (here the 'label' elements),
// if there are no radio inputs checked we call the 'addClass' method,
// otherwise the 'removeClass' method, and add/remove the 'requiredStill'
// class. This can be adjusted to do otherwise as you need.
sel.parent()[sel.filter(':checked').length === 0 ? 'addClass' : 'removeClass']('requiredStill');
});
}
$('input').on('change', checkForChecked);
function checkForChecked() {
var radioGroups = $.unique($('input[type="radio"][name]').map(function () {
return this.name;
}).get());
radioGroups.forEach(function (a) {
var sel = $('input[type="radio"][name="' + a + '"]');
sel.parent()[sel.filter(':checked').length === 0 ? 'addClass' : 'removeClass']('requiredStill');
});
}
$('input').on('change', checkForChecked);
label {
display: block;
}
.requiredStill {
border: 1px solid #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<input type="radio" name="a" />a</label>
<label>
<input type="radio" name="a" />a</label>
<label>
<input type="radio" name="a" />a</label>
<label>
<input type="radio" name="b" />b</label>
<label>
<input type="radio" name="b" />b</label>
<label>
<input type="radio" name="b" />b</label>
<label>
<input type="radio" name="c" />c</label>
<label>
<input type="radio" name="c" />c</label>
<label>
<input type="radio" name="c" />c</label>
References:
addClass()
.[attribute="value"]
) selector.get()
.$.unique()
.map()
.parent()
.removeClass()
.Upvotes: 1
Reputation: 171679
Approach adding an error element for visual reference
var radios = $mainElem.find(':radio');
var radioNames={};
radios.each(function(){
radioNames[this.name] = true;
});
for( name in radioNames){
var radioGroup=$mainElem.find('[name=' + name + ']');
if( !radioGroup.filter(':checked').length ){
radioGroup.parent().append('<span class="error">Ooooops</span>');
}
}
Upvotes: 0