JS validation for checkbox not working when put name [] - javascript

I have an JS validation for checkbox.
function ActionCcdCheck (theForm)
{
if (theForm.ccd_chk.checked)
{
theForm.ccd_pos[0].className = 'part';
theForm.ccd_pos[1].className = 'part';
theForm.ccd_pos[2].className = 'part';
theForm.ccd_pos[0].disabled = false;
theForm.ccd_pos[0].checked = false;
theForm.ccd_pos[1].disabled = false;
theForm.ccd_pos[1].checked = false;
theForm.ccd_pos[2].disabled = false;
theForm.ccd_pos[2].checked = false;
}
else
{
theForm.ccd_pos[0].disabled = true;
theForm.ccd_pos[1].disabled = true;
theForm.ccd_pos[2].disabled = true;
}
}
The checkbox
<td colspan="1" rowspan="2" width="35">CCD</td>
<td>Check</td>
<td><input type="checkbox" name="ccd_chk" value="yes" class="part" onclick="ActionCcdCheck (this.form);" onkeypress="FocusChange (this.form, 5, 4);"/> Yes</td>
<tr>
<td>Position</td>
<td>
<input type="checkbox" name="ccd_pos[]" value="front" class="part" onkeypress="FocusChange (this.form, 6, 3);"/> Front
<input type="checkbox" name="ccd_pos[]" value="back" class="part" onkeypress="FocusChange (this.form, 7, 2);"/> Back
<input type="checkbox" name="ccd_pos[]" value="fb" class="part" onkeypress="FocusChange (this.form, 8, 1);"/> FB
</td>
<tr>
Now I am facing problem when I put checkbox name like this name="ccd_pos[]". The JS validation not working. I use that because I want to submit multiple value of checkbox.
So anyone can give me an suggestions ? Thanks.

In your code:
theForm.ccd_pos[0]
is looking for a ccd_pos property of the form, there isn't one. What you need is something like:
theForm['ccd_pos[]'][0]
as form controls with the same name will be returned as a collection, so:
theForm['ccd_pos[]']
returns a collection of the three controls with name ccd_pos[]. Then use normal index names to access the various members of the collection.
Note that in javascript, dot notation is a shortcut to formal property access and can only be used where the name is complies with the rules for identifiers. Otherwise, you must use square bracket (formal) notation.
So your code can be something like:
var box, boxes = theForm.['ccd_pos[]'];
for (var i=0, iLen=boxes.length; i<iLen; i++) {
box = boxes[i];
if (theForm.ccd_chk.checked) {
box.className = 'part';
box.disabled = false;
box.checked = false;
} else {
box.disabled = true;
// and probably
box.className = '';
}
}

Related

How to create a html/javascript table that automatically selects radiobuttons?

I have only very basic html/javascript understanding.
I am trying to make what is probably only a slight modification to an existing code. Below is, first the original code, and then how I'd like to change it.
Original code:
A table gives the user a choice between left and right for several rows. The table enforces at most a single switch point from left to right going down the table, meaning that if the user chooses right at some row, the table automatically selects right for all rows below, and if the user chooses left at a given row, the table automatically selects left for all rows above. No switch point at all is allowed (meaning left is selected for all rows, or right is selected for all rows). A selection is required for each row (the app checks for this by default already).
{{ block content }}
<table class="table table-striped">
<colgroup>
<col width="45%">
<col width="10%">
<col width="45%">
</colgroup>
<tr>
<td align="right"><b>Option A</b></td>
<td></td>
<td align="left"><b>Option B</b></td>
</tr>
{{ for amount in player.right_side_amounts }}
<tr>
<td align="right">
<b>{{ player.left_side_amount }}</b> now
<td align="middle">
<input type="radio"
value="left"
name="{{ amount|json }}"
required>
<input type="radio"
name="{{ amount|json }}"
value="right" data-amount="{{ amount|json }}"
required>
</td>
<td align="left">
<b>{{ amount }} </b> next month
</tr>
{{ endfor }}
</table>
{{ formfield_errors 'switching_point' }}
<input type="hidden" name="switching_point" id="id_switching_point"
value="9999">
{{ next_button }}
{{ endblock }}
{{ block scripts }}
<script>
$(document).ready(function () {
$('input[type=radio]').change(
function () {
var clickedRadio = this;
var afterClickedRadio = false;
var radios = document.querySelectorAll('input[type=radio]');
for (i = 0; i < radios.length; ++i) {
var radio = radios[i];
if (radio === clickedRadio) {
afterClickedRadio = true;
continue;
}
if (!afterClickedRadio && clickedRadio.value === 'left' && radio.value === 'left') {
radio.checked = true;
}
if (afterClickedRadio && clickedRadio.value === 'right' && radio.value === 'right') {
radio.checked = true;
}
}
}
);
$('.otree-btn-next').click(function () {
var radios = document.querySelectorAll('input[type=radio]');
for (i = 0; i < radios.length; ++i) {
var radio = radios[i];
if (radio.value === 'right' && radio.checked) {
$('#id_switching_point').val(radio.dataset.amount);
break;
} else {
$('#id_switching_point').val(9999);
}
}
});
});
</script>
{{ endblock }}
This is how the original table looks:
original table
Modification:
Just as in the original, I'd like to have the table with a left/right choice, and enforce at most a single switch point. But, I'd like user to have the possibility to express indifference between the left and right choice at the switch point.
In other words, at the row the user chooses to switch from option A to option B, he could choose either "I prefer B" or "I am exactly indifferent between A and B".
I envision a table with three radio buttons per row, where the center button means “I am indifferent”. At whichever row the user chooses to switch ($17 in this image: what I envision) the user could select either the center button (which would express exact indifference) or the right button (which would express preference for option B). Regardless of whether the user chooses center or right button, all rows above would get checked for A, and all rows below would get checked for B. The center button can be selected at most once, since all rows below would be automatically selected right, and all rows above would be automatically selected left.
I think a second variable would need to be created relative to the original code, to record not just the switching point, but also whether the switching point occurred with indifference or strict preference.
Thank you so much for any help.
How's this? If I understood you correctly, then the rules are:
Selecting A checks all A inputs
Selecting B checks all B inputs
Selecting X will make all inputs below the X selection to be the opposite of the first checked input and everything above the X selection defaults to the first checked input selection. (If A, then B after the X. If B, then A after the X)
Prevents selecting more than one X. If more than X, the last checked X will prevail, the previous X changes according to rule 3.
In addition to those rules, I disabled the first and last middle inputs because you didn't say what happens if the first or last middle inputs are checked. Also, I added logic that prevents the user from checking any middle input before anything else is selected since you didn't say what happens in that situation either.
There are some edge cases I didn't code for, but this is more than enough to cover your rules.
https://jsfiddle.net/j1vas2x8/
<table>
<tr>
<th>A</th>
<th>X</th>
<th>B</th>
</tr>
<tr>
<td><input type="radio" name="r1[]" value="A"></td>
<!-- if the first middle selection is not disabled, then which column is the opposite of it? -->
<td><input type="radio" name="r1[]" value="X" disabled="disabled"></td>
<td><input type="radio" name="r1[]" value="B"></td>
</tr>
<tr>
<td><input type="radio" name="r2[]" value="A"></td>
<td><input type="radio" name="r2[]" value="X"></td>
<td><input type="radio" name="r2[]" value="B"></td>
</tr>
<tr>
<td><input type="radio" name="r3[]" value="A"></td>
<td><input type="radio" name="r3[]" value="X"></td>
<td><input type="radio" name="r3[]" value="B"></td>
</tr>
<tr>
<td><input type="radio" name="r4[]" value="A"></td>
<td><input type="radio" name="r4[]" value="X"></td>
<td><input type="radio" name="r4[]" value="B"></td>
</tr>
<tr>
<td><input type="radio" name="r5[]" value="A"></td>
<!-- if the last middle selection is not disabled, then what should should happen if it's selected last? -->
<td><input type="radio" name="r5[]" value="X" disabled="disabled"></td>
<td><input type="radio" name="r5[]" value="B"></td>
</tr>
</table>
var header_row = document.querySelectorAll('table tr th');
var column = {
'left': header_row[0].innerText,
'middle': header_row[1].innerText,
'right': header_row[2].innerText
};
var radios = document.querySelectorAll('input[type="radio"]');
var rows = document.querySelectorAll('table tr');
Array.from(radios).forEach(function(radio) {
radio.addEventListener('click', function(event) {
var is_more_than_one_middle_column_selected = document.querySelectorAll('input[type="radio"][value="' + column.middle + '"]:checked').length > 1;
if (is_more_than_one_middle_column_selected === true) {
// loops through all radio inputs with the middle column checked
Array.from(document.querySelectorAll('input[type="radio"][value="' + column.middle + '"]:checked')).forEach(function(input) {
if (input !== event.target) {input.checked = false;}
});
}
var current_row_index = Array.from(rows).findIndex(function(row) {
var current_input = Array.from(row.querySelectorAll('td input[type="radio"]')).find(function(input) {
return input === event.target;
});
return !!current_input;
});
var middle_selected_input_row_index = Array.from(rows).findIndex(function(row) {
return row.querySelector('input[type="radio"][value="' + column.middle + '"]')?.checked === true;
});
var is_middle_input_selected = middle_selected_input_row_index > -1;
let first_input_column = rows[1].querySelector('input[type="radio"]:checked')?.value || '';
// if the first input has not been checked but a middle input somewhere else has
if (!first_input_column && is_middle_input_selected === true) {
// uncheck the current input, and stop the script here; if script keeps going it will run into null errors
return event.target.checked = false;
}
for (var row_index = 1; row_index < rows.length; row_index++) {
// if the middle input is not checked yet
if (is_middle_input_selected === false) {
// whatever selection the current value, change all inputs to that
rows[row_index].querySelector('input[type="radio"][value="' + event.target.value + '"]').checked = true;
}
else if (is_middle_input_selected === true && row_index < middle_selected_input_row_index) {
// check the previous input to whatever the first checked input value was
rows[row_index].querySelector('input[type="radio"][value="' + first_input_column + '"]').checked = true;
}
else if (is_middle_input_selected === true && row_index > middle_selected_input_row_index) {
// check the previous input to whatever the first checked input value was
rows[row_index].querySelector('input[type="radio"][value="' + (first_input_column === column.left ? column.right : column.left) + '"]').checked = true;
}
// if the current input checked was the input that triggered this logic, and a there was more than one middle input that was checked
else if (row_index === current_row_index && is_more_than_one_middle_column_selected === true) {
// get the first checked input value
let first_input_column = rows[1].querySelector('input[type="radio"]:checked').value;
// check the previous input to whatever the first checked input value was
rows[row_index - 1].querySelector('input[type="radio"][value="' + first_input_column + '"]').checked = true;
}
}
});
});

A checkbox for selecting all checkboxes generated by CheckBoxFor

I am using CheckBoxFor to create a form of a bunch of checkboxes. I have added a class to these checkboxes but since CheckBoxFor doesn't add the class to the hidden false checkbox, I can't select groups of these generated checkboxes based upon it.
Here's a sample of the checkbox table that gets generated. When I hit the "Select All" checkbox (the top most one), I want all the checkboxes in that column to be selected. I do not want the whole table selected, just the column.
Some of the relevant HTML:
<td><input type="checkbox" name="selectAll" value="NBTC" /></td>
<td><input type="checkbox" name="selectAll" value="Contractors" /></td>
<td><input type="checkbox" name="selectAll" value="Coordinators" /></td>
<td><input type="checkbox" name="selectAll" value="NGO" /></td>
<td><input type="checkbox" name="selectAll" value="Public" /></td>
Example of the CheckBoxFor statements I'm using:
#Html.CheckBoxFor(m => m.NBTCGroup.NBTC_FA_Centroid, new {#class = "NBTC"}
This is the JS I was working with, but since the it's selecting based off the class, it doesn't work to select and unselect all as the false checkbox doesn't have the class added to it.
$(document).ready(function () {
$('input[name="selectAll"]').click(function () {
var source = $(this);
var sourceName = $(this).val();
if (sourceName == 'NBTC') {
var checkboxes = document.querySelectorAll('input[class="NBTC"]');
}
else if (sourceName == 'Contractors') {
var checkboxes = document.querySelectorAll('input[class="Contractors"]');
}
else if (sourceName == 'Coordinators') {
var checkboxes = document.querySelectorAll('input[class="Coordinators"]');
}
else if (sourceName == 'NGO') {
var checkboxes = document.querySelectorAll('input[class="NGO"]');
}
else if (sourceName == 'Public') {
var checkboxes = document.querySelectorAll('input[class="Public"]');
}
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i] != source)
checkboxes[i].checked = source.checked;
}
});
Anybody have any ideas on another way to do this?
From your code I assume you are adding NBTC, Contractors, etc classes to each group of checkboxes... you also have several selectAll checkboxes, for each group.
You can change your jQuery like this:
$('input[name="selectAll"]').click(function() {
var className = $(this).val(); // <-- get the group: NBTC, Contractors, etc
$('.' + className).prop('checked', this.checked);
// generates something like this: $('.NBTC').prop('checked', this.checked);
});
I have used this answer for check/uncheck logic.

How to assign reassign checkbox ng-model on ng-repeat

Please help me out. I have a checkboxes with models defined. I am displaying checkboxes and using the model to set if the checkbox is selected or not. Below is the code for setting the ng-model.
LoadValues(obj) {
vm.index = false;
vm.create = false;
vm.edit = false;
vm.delete = false;
vm.other = false;
var pList = obj.Functions;
var currentModule = obj.Name;
for (var i = 0; i < pList.length; i++) {
var currentItem = pList[i];
console.log(currentItem)
if (currentItem.search("Index") > 0) {
vm.index = true;
console.log(vm.index);
} else if (currentItem.search("Create") > 0) {
vm.create = true;
} else if (currentItem.search("Edit") > 0) {
vm.edit = true;
} else if (currentItem.search("Delete") > 0) {
vm.delete = true;
} else if (currentItem.search("Other") > 0) {
vm.other = true;
}
}
}
Below is the check boxes.
<tbody>
<tr ng-repeat="item in list">
<td>
{{item.Name}}
</td>
<td>
<input id="Index" type="checkbox" ng-model="vm.index" ng-click="EditRole(Right,item.Module,'Index')">
</td>
<td>
<input id="Create" type="checkbox" ng-model="vm.create" ng-click="EditRole(item.Role,'Create')">
</td>
<td>
<input id="Edit" type="checkbox" ng-model="vm.edit" ng-click="EditRole(item.Role,item.Module,'Edit')">
</td>
<td>
<input id="Delete" type="checkbox" ng-model="vm.delete" ng-click="EditRole(item.Role,item.Module,'Delete')">
</td>
<td>
<input id="Other" type="checkbox" ng-model="vm.other" ng-click="EditRole(item.Role,item.Module,'Other')">
</td>
</tr>
</tbody>
The problem is it assigns the same ng-model to all the items in the list. I have tried to find solutions nothing is helping. Your help would be very much appreciated.
i am reading my data from a json file. Below is some example data:
[
{"Role":"Staff","Admins":[{"Name":"Username","userRights":["UserEdit","UserCreate"]
}]
The easiest way to use ng-model on a checkbox is to pass it an abject. The code below converts an array of items into an object for the checkboxes.
I created a variable called $scope.userRights which contains all of the available options.
In the HTML we loop though each field displaying its name and then loop though all of the userRights.
The submit button then converts the object back into the array format we received.
HTML
<div ng:controller="MainCtrl">
<button ng-click="submit()">Submit</button>
<table>
<tr ng-repeat="field in fields">
<td ng-bind="field.Name"></td>
<td ng-repeat="right in userRights">
<label>
<input type="checkbox" ng-model="field.userRights[right]" /> {{right}}
</label>
</td>
</tr>
</table>
<pre ng-bind="fields | json"></pre>
</div>
JavaScript
app.controller('MainCtrl', function($scope) {
$scope.userRights = ["UserEdit","UserCreate","UserSomethingElse"];
$scope.fields = [
{"Name":"Username","userRights":["UserEdit","UserCreate"]},
{"Name":"Password","userRights":["UserEdit"]}
];
// Convert array to object
$scope.fields.forEach(function(field) {
var res = {};
field.userRights.forEach(function(right) {
res[right] = true;
});
field.userRights = res;
});
function objectValues(obj) {
var res = [];
var keys = Object.keys(obj);
for (var i=0; i<keys.length; i++) {
if (obj[keys[i]]) res.push(keys[i]);
}
return res;
}
// Convert object to array
$scope.submit = function() {
$scope.fields.forEach(function(field) {
field.userRights = objectValues(field.userRights);
});
};
});
Demo
Your ng-model has to be like so:
ng-model="item.index"
And then in your controller inside the for loop:
current_item.index = true;
Hope it helps =)

Using javascript to check if a radio button is selected and return a specific answer based on the selection

I am looking, in the cleanest way possible to be able to take a simple yes or no question and test for which answer has been chosen.
For instance in this case if a "yes" I want it to return a value of "Continue" into a specified area (a 3 column table which has a question in the first, the radio buttons in the second, and I want it to update and display the answer in the third).
My code for the JS stands thus far:
<script type="text/javascript">
var answer = 'place-holder';
var user_input;
function checkForm()
{
var substanceab = document.getElementById('Sub');
for (i = 0; i < substanceab.length; i++)
{
if(substanceab.length[i].checked)
{
user_input = substanceab.length[i].value;
}
}
if (user_input ="yes")
{
return answer = "Continue";
}
else if (user_input ="no")
{
return answer = "Provide Alternate Referral";
}
else
{
return;
}
};
function writeAns()
{
document.getElementById('answerwrite').innerHTML = checkForm[user_input];
};
</script>
and the Body text (minus the actual question):
<table class="table table-bordered">
<tr>
<td width="58%"><center><strong>Required:</strong></center></td>
<td width="19%"></td>
<td width="23%"><center><u><strong>___________</strong></u></center></td>
</tr>
<tr>
<td> <span class="sub depend"> <strong><i>_________</i> </strong></span></td>
<td> <span class="sub depend ans">
<form name="Substance">
<label class="radio inline">
<input type="radio" value="yes" name="substance" onclick="writeAns()">
yes </label>
<label class="radio inline">
<input type="radio" value="no" name="substance" onclick="writeAns()">
no </label> </form></span></td>
<div id="answerwrite"></div>
<script type="text/javascript">
document.write("<td>" + writeAns() + "</td>")
</script>
</tr></table>
Ok, fixed the 'funk' but like I said, more used to java than javascript, completely tougher syntax. I agree, I only used the ID thing to try and get this to work with a different method, but it never did. Now with some of the suggestions it is just giving me undefined everywhere. And while I agree this will eventually turn to jquery, I have NO clue how to work with it, hence figuring out this in javascript first.
A few things:
document.getElementByID()
will always return the first element, as ID's are supposed to be unique.
Instead, use:
document.getElementsByName('substance');
Next, in your loop, you are improperly referencing the array's members using the .length property. Try this instead:
for (i = 0; i < substanceab.length; i++)
{
if(substanceab[i].checked)
{
user_input = substanceab[i].value;
}
}
Finally, in javascript, the '=' opertator is always an assignment statement. To do comparisons, always use '==':
if (user_input == "yes")
{
return answer = "Continue";
}
else if (user_input =="no")
{
return answer = "Provide Alternate Referral";
}
else
{
return;
}
Also, try to avoid global variables whenever possible.
Here is the working code, refactored a bit:
<input type="radio" value="no" id= "Sub" name="substance" onclick="writeAns()">
function checkForm()
{
var user_input;
var substanceab = document.getElementsByName('substance');
for (i = 0; i < substanceab.length; i++)
{
if(substanceab[i].checked)
{
user_input = substanceab[i].value;
}
}
if (user_input == "yes")
{
return "Continue";
}
else if (user_input =="no")
{
return "Provide Alternate Referral";
}
else
{
return;
}
};
function writeAns()
{
document.getElementById('answerwrite').innerHTML = checkForm();
};
Very easy if you are using JQuery.
Ensure your elements have the same "name" attribute and use:
var RadioGroupResult = $('input[name="MyRadioGroupNameHere"]:checked').val();
Nice and simple.

How do I validate a group of textboxes using javascript?

I have group of check-boxes and corresponding text-boxes with them. I can get each checkbox one by one, but how do I get the group of textboxes so I can validate them?
Here is my javascript code below:
function validate_orderform(proform)
{
var flag=0;
for (var i = 0; i < proform.chk.length; i++) {
if (proform.chk[i].checked && proform.quant[i].value=="") {
flag=1;
}
}
if(flag==1){
return false;
}
return true;
}
and my html code:
<td><input type="checkbox" id="chk1" name="chk"></td>
<td><input type="text" size="10" id="quant1" name="quant1"></td>...and so on
If name of textboxes are different then you can access all textboxes by
var txtObjList = document.getElementsByTagName("input");
for(var i=0; i < txtObjList.length; i++){
if(txtObjList[i].getAttribute("type") == "text" && this.value != ""){
// success for i+1 textbox
}
}
Or you can give common class name to all textboxes and then can access by
var txtObjList = document.getElementsByClassName("classname");
for(var i=0; i < txtObjList.length; i++){
if(this.value != ""){
// success for i+1 textbox
}
}
Remember by using javascript library such as jquery, prototype your work will be simpler.
There are a couple of methods you could use, you could use document.getElementsByTagName to retrieve all of the input elements, check their type etc... It works but it's slow and potentially expensive depending on how complex your form is.
If you have a group of checkboxes and each one has it's own text box then you could group them, so add a common name to each type, e.g.
Entry 1:
<input type="checkbox" id="chk1" name="chk"/>
<input type="text" id="quant1" name="quant"/>
Entry 2:
<input type="checkbox" id="chk2" name="chk"/>
<input type="text" id="quant2" name="quant"/>
Then you can use the document.getElementsByName method, so in this instance the following would retrieve a collection of 2 objects for you're text boxes:
var myTextBoxes = document.getElementsByName("quant");

Categories

Resources