Output two pieces of data if both statements are true - javascript

#JonoJames answered this question for me.
The HTML form we use has a set of checkboxes which are checked depending on which room is being hired. These boxes are named room1, room2 and room3. When one, two or all three boxes are checked, the cost of that rooms hire is put into corresponding, hidden, input boxes named room1value, room2value and room3value.
We later needed to add deposits for the room hire which we did by adding, for example, document.forms["bookform"].room1deposit.value = Rooms[0].deposit; to the function check() script for each of the rooms. This added the deposit for the room automatically and it worked fine.
However now, occasionally, a deposit may not be required, so we put a checkbox in the form that is checked when a deposit is required. This checkbox, which is called depositRequired, covers all three rooms. So if someone hires Room 1 and a deposit is required, boxes room1 and depositRequired are checked. Similarly, If the boxes for Room 2 and Room 3 are checked and a deposit is required, the depositRequired checkbox is selected too. If a room or rooms are hired and a deposit is not required, the required room boxes are checked but the depositRequired checkbox remains unselected.
We've tried ((document.forms["bookform"].room1value.checked) || (document.forms["bookform"].room1deposit.checked)), ((document.forms["bookform"].room1deposit.checked) && (document.forms["bookform"].room1value.checked)) to the if statements and we've tried adding and else if to the statements, separate if statements and variations of the above but we can't get anything to work.
Our current code is:
function Check() {
//room1
if (document.forms["bookform"].room1.checked)
{
document.forms["bookform"].room1value.value = Rooms[0].cost;
document.forms["bookform"].room1deposit.value = Rooms[0].deposit;
//console.log(Rooms[0].cost);
}else{
document.forms["bookform"].room1value.value ='';
document.forms["bookform"].room1deposit.value = '';
}
//room2
if (document.forms["bookform"].room2.checked)
{
document.forms["bookform"].room2value.value = Rooms[1].cost;
document.forms["bookform"].room2deposit.value = Rooms[1].deposit;
//console.log(Rooms[1].cost);
}else{
document.forms["bookform"].room2value.value ='';
document.forms["bookform"].room2deposit.value = '';
}
//room3
if (document.forms["bookform"].room3.checked)
{
document.forms["bookform"].room3value.value = Rooms[2].cost;
document.forms["bookform"].room3deposit.value = Rooms[2].deposit;
//console.log(Rooms[2].cost);
}else{
document.forms["bookform"].room3value.value ='';
document.forms["bookform"].room3deposit.value = '';
}
}
and the output boxes are:
<input type="hidden" name="room1value" readonly>
<input type="hidden" name="room1deposit" readonly>
<input type="hidden" name="room2value" readonly>
<input type="hidden" name="room2deposit" readonly>
<input type="hidden" name="room3value" readonly>
<input type="hidden" name="room3deposit" readonly>
How do we add the deposit if the deposit checkbox is checked and the specific room is checked?
For example, if Room 1 is checked the cost of the room is output to the room1value input box but the deposit cost for Room1 is output to the input box room1deposit only if the deposit required checkbox is checked else it remains blank.

In your attempts you have tried using room1value.checked and room1deposit.checked, but those are not check boxes, but the hidden inputs in which you want to write the amounts. Instead you should use depositRequired.checked.
So you would need a nested if, like this:
if (document.forms["bookform"].room1.checked) {
document.forms["bookform"].room1value.value = Rooms[0].cost;
if (document.forms["bookform"].depositRequired.checked) { // <--- Additional IF
document.forms["bookform"].room1deposit.value = Rooms[0].deposit;
}
} // ... etc
I would however also point out that you can shorten your code a bit, as it currently has a lot of repetition.
Secondly, it would be good if you would use a lower case first letter for your function check and array rooms, as an initial capital is commonly used for class names (constructors).
Here is how you could deal with all three groups in a single loop:
function check() { // <--- initial char lower case
let frm = document.forms["bookform"]; // avoid reading the document repetitively
for (let i = 1; i <= 3; i++) {
// Use dynamic properties all over...
frm[`room${i}value`].value = ""; // default
frm[`room${i}deposit`].value = ""; // default
if (frm[`room${i}`].checked) {
frm[`room${i}value`].value = rooms[i].cost; // lowercase
if (frm.depositRequired.checked) { // <--- Additional IF
frm[`room${i}deposit`].value = rooms[i].deposit; // lowercase
}
}
}
}

Related

Assign value from endpoint to checkbox

I am trying to assign values I get from an endpoint to a checkbox
Here is the object
{sendOtpEmail: true}
I had to do some searching inside the endpoint response to differentiate whether an email value comes back or a cell phone value comes back
Here is my code
TS
otpCellValue: any;
otpEmailValue: any;
getOTPChannel() {
this._loader.start();
this._subscriptions.push(this._corpService.getOTPChannel().subscribe((resp) => {
//get endpoint object
console.log(resp);
//get endpoint object parameter name
let keyNames = Object.keys(resp);
console.log(keyNames[0]);
//check for email keyword
if(keyNames[0].includes('Email')) {
console.log(resp.sendOtpEmail);
//get value
if(resp.sendOtpEmail == true) {
//email value is true so the otpEmailValue checkbox should be checked however it is not
this.otpEmailValue = 1;
this.otpCellValue = 0;
} else {
this.otpEmailValue = 0;
this.otpCellValue = 0;
}
}
this._loader.stop();
}, (error) => {
this._loader.stop();
this._errorService.openErrorPopup('Failed to get OPT channel.');
}));
}
HTML
<input type="radio" name="1" id="1" class="with-gap" [(ngModel)]="otpCellValue" [(value)]="otpCellValue">
<input type="radio" name="2" id="2" class="with-gap" [(ngModel)]="otpEmailValue" [(value)]="otpEmailValue">
I added comments to say what I am doing in the code above
So now I am stuck with why the email checkbox is not checked. Any ideas?
Those are not checkboxes but radio buttons. Assuming that you do want the radio buttons (which in your case it looks like it, because it would be one or the other), there are a few things that needs to be done.
Rather than having 2 properties to indicate which option is selected, you could have 1 property for that purpose.
So
this.otpEmailValue = 1;
this.otpCellValue = 0;
Becomes
this.contact = 'email'; // This line is now equivalent to the ones above
In the template, the radio button inputs, need to have the same name for them to behave as 1 input instead of 2, because after all, we only want 1 option selected. The ngModel directive now points to the value we want to bind, in our case, contact. And lastly, the value should be static. When the value of the property bound with ngModel matches the value of one of the radio buttons, it will select it.
So, after all those changes we get the following.
<input type="radio"
name="contact-option"
id="1"
class="with-gap"
[(ngModel)]="contact"
value="cell"> Cell
<input type="radio"
name="contact-option"
id="2"
class="with-gap"
[(ngModel)]="contact"
value="email"> Email
Demo

Checking checkboxes on webform via URL query string

I'm working on a registration form with several classes from which one can choose more than one (checkboxes). There is also a corresponding fee that is popped into a textbox for each class.
One also must select one membership category (radio buttons).
Each checkbox item has a unique ID and value. They are all named "courses[]". When the form is submitted, the values are sent to the registration desk via a php script that writes to a database and sends email (and all the courses' titles are under "Courses").
Here's the issue:
I want visitors of the website to be able to click on a link next to the class they want. The link is a URL query string that pre-fills the regform with the default membership category and also checks the checkbox next to the class. But so far it's only working for the radiobutton option of membership and not for the checkbox classes. I need to modify or replace the code to accommodate these checkboxes, but I need help.
The URL query string I am using looks like this (not a real URL):
https://domain.edu/summer.php?membership=Current&courses=ClassTitle_12345
Here's the pertinent script from the form page [loads after DOM]:
function getUrlParameters() {
var urlQuery = location.search;
urlQuery = urlQuery.replace('?', '');
if (urlQuery.indexOf('&') == -1) {
checkPreselectedMembership(urlQuery);
checkPreselectedMembership(urlQuery);
} else {
var params = urlQuery.split('&');
for (var i = 0; i < params.length; i++) {
checkPreselectedMembership(params[i]);
}
}
total();
}
function checkPreselectedMembership(param) {
var split = param.split('=');
if (split[0] == "membership") {
if (split[0].match(/^[0-9a-zA-Z_]{1,20}$/)) { // only allow numbers, letters, and the underscore
document.getElementById(split[1]).checked = true;
}
}
}
And here a snippet of the HTML:
<input name="courses[]" type="checkbox" id="class01" onClick="classFees();total();" value="ClassTitle1_12345" title="Check to select course">
Class Title 1</td>
$<input name="class01_fee" size="10" type="text" readonly title="class fee">
<input name="courses[]" type="checkbox" id="class02" onClick="classFees();total();" value="ClassTitle2_34568" title="Check to select course">
Class Title 2</td>
$<input name="class02_fee" size="10" type="text" readonly title="class fee">
I hope that I have been clear with my questions. Thank you.

How can I validate more than one checkbox on submission?

I have two sets of checkboxes, named pizzaBase and pizzaTopping. I want to validate my form so that on submission at-least 1 base and topping must be selected.
function main() {
var form = document.getElementById('formname');
form.addEventListener('submit', validate);
}
function validate(event) {
var form = document.getElementById('formname');
if(!form.pizzaBase.checked) {
alert("select a base");
event.preventDefault();
}
else if(!form.pizzaTopping.checked) {
alert("select topping");
event.preventDefault();
}
else {
return true;
}
}
Problems
Only first if statement works.
Form submits true if checkbox is checked and then unchecked before
submission.
Doesn't validate, doesn't work.
Where am I going wrong?
Thank you GG for pointing out JS is working, I have HTML below if someone wouldn't mind correcting me. I basically have two identical versions of the below code, one for bases and the other toppings.
**
HTML
**
<section>
<h2> Bases </h2>
<p><input type="checkbox" name="pizzaBase" data-price="1.00" data-human-desc = "Small" value="Small"> Small (£1.00) </p>
<p><input type="checkbox" name="pizzaBase"data-price="1.50" data-human-desc = "Medium" value="Medium"> Medium (£1.50) </p>
<p><input type="checkbox" name="pizzaBase" data-price="2.50" data-human-desc = "Large"value="Large"> Large (£2.50) </p>
<p><input type="checkbox" name="pizzaBase" data-price="3.50" data-human-desc = "XLarge"value="XLarge"> XLarge (£3.50) </p>
</section>
Not sure if I should ask a separate question here, but this is my messy HTML. Is it the sections? I was trying to split each set of check boxes (bases, toppings) into two separate sections so used this tag.
Any ideas?
When you have multiple inputs with the same name, form.elementName will be an array-like list of elements.
The list won't have a checked property. Each item within it will.
You need to loop over the list and check to see if any of the elements are checked.
function areAnyChecked(list) {
for (var i = 0; i < list.length; i++) {
if (list[i].checked) {
return true;
}
}
return false;
}
if(! areAnyChecked(form.pizzaBase)) {
...

Multiple Conditions to a checkbox

I have a table named, student_db which is like this :-
Name Gender Grade City
John Male 2 North
Dave Male 4 North
Garry Male 3 North
Chirsty Female 5 East
Monica Female 4 East
Andrew Male 3 East
Patrick Male 7 South
Maria Female 3 South
I need to select 3 students with this list, names of the students are taken as input. But there are some constraints :
1) 1 Female has to be selected.
2) A maximum of 2 persons from the same city can be selected.
3) Sum of the grade of the selected 3 persons cannot exceed 11.
4) Once three valid selections are made, rest of the checkboxes should freeze automatically.
5) If while selecting a person any of the constraint gets violated, that particular selections gets unchecked and a alert message is displayed to the user.
Is it possible to add so many constraints to a check box ??
EDIT
I have managed to add 2 constraints :-
1) If the grade sum exceeds 11, an alert message will get displayed.
2) Once three valid selections are made, rest checkboxes will get freezed.
This is what I've tried :-
<script src="http://code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(function() {
var max = 3;
var checkboxes = $('input[type="checkbox"]');
checkboxes.change(function() {
var current = checkboxes.filter(':checked').length;
checkboxes.filter(':not(:checked)').prop('disabled', current >= max);
});
});
</script>
<script>
function jsFunction(element) {
var sum = 0,i;
var elements = document.getElementsByClassName('chkbox');
for (i = 0; i<elements.length; i++) {
if (elements[i].checked) {
sum += parseInt(elements[i].value);
}
}
if (sum > 11) {
alert("11 maximum grade allowed !!");
element.checked = false;
}
}
</script>
<form name='checkbox1[]' method="post" action="select_student.php">
<label class="cb1" for="checkbox1"> </label>
<input type="hidden" name="checkbox1[]" id="check" value="null">
<?php
session_start();
mysql_connect("localhost", "my_db", "my_password") or die (mysql_error ());
mysql_select_db("my_db") or die(mysql_error());
$strSQL = "SELECT Name,Grade FROM student_db";
$rs = mysql_query($strSQL);
echo "<b><h2>List of Students :-</h2></b>";
while($row = mysql_fetch_array($rs)) {
$man = $row['Name'];
echo '<input type="checkbox" value="'.$row['Name'].'|'.$row['Grade'].'" class="chkbox" name="checkbox1[]" onchange="jsFunction(this)" />';
echo $man;
}
?>
<br>
<input type="submit" value="SUBMIT" id="button1" style= "height:40px; width:150px; font-weight: bold; font-size:10;">
</form>
The JS function is used to check whether the Grade sum is exceeding 11 or not and the jQuery Functions freezes other boxes once 3 valid selections are made. But I am unable to add other constraints.
Sorry for the delayed response! I got caught up in some other stuff yesterday and had to pick back up this morning . . . hopefully, this will help you out.
What you have is a pretty good start . . . here's a few changes that I would suggest:
1) First off, some HTML changes:
store off all of your student data (i.e., the "gender", "grade", and "city" values) as data attributes in the checkbox, like this:
<input type="checkbox" value="NAME_VALUE" class="chkbox" name="checkbox1[]"
data-gender="GENDER_VALUE" data-grade="GRADE_VALUE" data-city="CITY_VALUE"
onchange="jsFunction(this)" />
next, since you are already using jQuery, for clarity and easy of maintenance in the future, apply the onchange event listener dynamically, rather than hardcoding it into the input, like this:
<input type="checkbox" value="NAME_VALUE" class="chkbox" name="checkbox1[]"
data-gender="GENDER_VALUE" data-grade="GRADE_VALUE" data-city="CITY_VALUE" />
. . . and, in the script, after the page load:
$(".chkbox").on("change", jsFunction);
And, finally (just as a heads up), if you intend to us a <label> tag with a for attribute (e.g., you are showing one for your "hidden" input), you will need a matching id attribute in yout <input>, in order for them to be paired.
2) As for your scripting, I threw together the following that accomplishes all of the validation checks that you were looking for and standardizes some of your coding (you had a heavily mixed use of jQuery and vanilla JS).
var MAX_CHECKED = 3;
var MAX_GRADE = 11;
$("document").ready(function() {
$(".chkbox").on("change", jsFunction);
});
function jsFunction() {
var sum = 0;
var cities = [];
var elements = $(".chkbox");
var checkedElements = elements.filter(":checked");
checkedElements.each(function() {
sum += parseInt($(this).data("grade"), 10);
cities.push($(this).data("city"));
});
var uniqueCities = cities.filter(function(currentCity, cityIndex, cityArray) {
return (cityIndex === cityArray.indexOf(currentCity));
});
if (sum > MAX_GRADE ) {
alert(MAX_GRADE + " maximum grade allowed!!");
$(this).prop("checked", false);
}
else if (uniqueCities.length !== cities.length) {
alert("You may not select more than one student from each city!!");
$(this).prop("checked", false);
}
else {
if (checkedElements.length >= MAX_CHECKED) {
if (checkedElements.filter("[data-gender='Female']").length < 1) {
alert("At least one female student must be selected!!");
$(this).prop("checked", false);
}
else {
elements.filter(':not(:checked)').prop('disabled', true);
}
}
else {
elements.filter(':not(:checked)').prop('disabled', false);
}
}
}
Most of the code should be pretty straightforward . . . let me touch on a couple of the key or more complex parts . . .
Globals - I set your global variables (MAX_CHECKED and MAX_GRADE) up at the top and outside of any functions, so that they are accessible anywhere and easy to update (i.e., you don't have to search through the code to find them).
"Setup code" - I moved your setup code from the jQuery(function() { that you used to $("document").ready(function() { simply for readablity. :) They do the same thing.
Event binding the checkboxes - as I mentioned, I did this dynamically rather than inline, using $(".chkbox").on("change", jsFunction);. Additionally, you'll notice that I changed the selector. Since each checkbox is tagged with the "chkbox" class, I selected based on that, it is significantly faster than $('input[type="checkbox"]')
The validation logic - basically, you want to catch invalid entries as soon as possible and you have rules that fall into two categories: rules that can be checked before the maximum number of selections have been met and rules that require the maximum. The "max grade" and "unique cities" checks should be caught as soon as they are hit, but you must wait until you've hit the maximum selections before you can check for gender, since the user can always check a female student later on, if they have not yet hit the max.
uniqueCities - the function used to create this value isn't quite as straighforward as the rest of the code, so I'll clarify it a little. It is using the .filter method that is native to Arrays, to trim down the selections to only unique values. It does this by doing a callback which checks to see if the index of the current item (i.e., cityIndex) is the same as the index of the first instance of that value (i.e., currentCity) in the array (i.e., cityArray). If it is, then that value is added to the "filtered" array (i.e., uniqueCities).
"undisabling" - I added in an else statement that re-enables the checkboxes if the maximum number of selections have been made, but then one of them is unchecked. This will allow the user to change their mind, even if they had already hit the max, at some point.
A couple of extra notes
1) You need to change the value of Patrick's to "6" at the most, in order to check that the "at least one female" logic is working . . . currently, the lowest combination of all male students, from unique cities, is John, Garry, and Patrick, but their grade total is 12, so it triggers the "grade sum is too high" validation first. :)
2) While I didn't cover the code for this, you need to develop a version of this validation logic for your "Submit" button as well. If you don't, then someone could select two boys and hit "Submit" and the "at least one female" logic would never be triggered.
One way would be to put the "at least one female" validation in its own method and calling both from the "I just clicked on a checkbox" validation and in a "I just clicked on the submit button" validation. The main difference would be that, for the submit, you would not check to see if the max number of selections had been made, before triggering the "female" check. That would also be a good place to add an "at least one selection has been made" validation, as well.

Adding checkbox values with different input names

I have the following code which adds together checkboxes when they are selected and produces a total at the bottom of the page. This function uses the following code:
<script type="text/javascript">
function checkTotal() {
document.listForm.total.value = '';
var sum = 68.50;
for (i=0;i<document.listForm.choice.length;i++) {
if (document.listForm.choice[i].checked) {
sum = sum + parseFloat(document.listForm.choice[i].value);
}
}
document.listForm.total.value = sum.toFixed(2);
}
</script>
These checkboxes are within a form, and I need the form to send through to an email account. At the moment because all the checkboxes share the same input name 'choice' the PHP will only send the last checked box value.
I need to change the checkboxes input name code to name the different checkboxes 'choice1' 'choice2' 'choice3'. What would I have to change in the javascript to in order for the function to calculate all the checkboxes names 'choice1' 'choice2' 'choice3' etc rather than just adding together all checkboxes named'choice'? I have little Javascript and PHP knowledge so any help would be grateful. Thanks.
Rather than make the checkbox names unique, it would be better to append "[]" to their name. This will cause PHP to convert the values into an array, rather than just keep the last value.
So you would want a name of choice[] rather than choice.
You can also find some sample code in this answer.
The code below works ok (a self contained web page). The problem is how to get the array (group) of checkboxes when they're called different names. If you use jquery you could give them all the same class, then get hold of them by that class, but if you're using bare javascript then you can get the elements by Tag name ("input" in the case of the checkbox), and check each one has a name attribute that starts with "choice", inoring those that don't start with "choice", like buttons (also an input) or maybe other checkboxes with different names. It's a bit inefficient if the page is huge, unless you group the checkboxes some way.
To group them, you cold put them in a tag like
`<div id="checkboxes"> (checkboxes go here) </div>`
then use
`var cb = document.getElementById("checkboxes");`
`var arrInputs =cb.getElementsByTagName("input");`
for the line to get the arrInputs array. This would just get input type elements from within the Div. Hwever I dind't want to assume the page layout allows your checkboxes to be put in one div
Hope this helps
Doug
<script type="text/javascript">
function checkTotal() {
document.forms.listForm.total.value = '';
var sum = 68.50;
var frm=document.forms.listForm; // wasnt sure what your original listForm element was so I've put this form into a variable, frm
frm.total.value = '';
var arrInputs =document.getElementsByTagName("input"); // get all Input type elements on the form
for (i=0; i < arrInputs .length;i++) {
if (arrInputs[i].name.substr(0,6) == "choice") { // if the name starts with "choice"
if (arrInputs[i].checked) {
sum = sum + parseFloat(arrInputs[i].value);
}
}
}
frm.total.value = sum.toFixed(2);
}
</script>
</head>
<body>
<form name="listForm">
<a href='javascript:checkTotal()'>check</a><br>
<input type=checkbox name="choice1" value="1"><br>
<input type=checkbox name="choice2" value="2"><br>
<input type=checkbox name="choice3" value="3"><br>
<input type=checkbox name="choice4" value="4"><br>
<input type=checkbox name="choice5" value="5"><br>
<input type=checkbox name="choice6" value="6"><br>
<br>
<input type=text name=total value=""><br>
</form>
</body>
</html>

Categories