hello everyone I can't get the radio input value here is my code :
the alert isn't running
I want to do a real time calculation that shows the total to pay and I couldn't handle the radio values I appreciate your help thanks :D
function transfer()
{
var vip=document.getElementByName('mercedes');
for (var i = 0, length = vip.length; i < length; i++)
{
if (vip[i].checked)
{
alert(vip[i].value);
break;
}
}
}
<div class="form-group">
<label for="f1-about-yourself">Mercedes VIP transfer*:</label> <br>
<input type="radio" name="mercedes" id="yes" value="yes"
onclick="transfer()">
<label for="yes">Yes:</label>
<input type="radio" name="mercedes" id="no" value="no" checked="" onclick="transfer()">
<label for="no">No:</label>
</div>
function transfer()
{
var vip=document.getElementsByName('mercedes');
for (var i = 0, length = vip.length; i < length; i++)
{
if (vip[i].checked)
{
alert(vip[i].value);
break;
}
}
}
<div class="form-group">
<label for="f1-about-yourself">Mercedes VIP transfer*:</label> <br>
<input type="radio" name="mercedes" id="yes" value="yes"
onclick="transfer()">
<label for="yes">Yes:</label>
<input type="radio" name="mercedes" id="no" value="no" onclick="transfer()">
<label for="no">No:</label>
</div>
In addition to the already given answer that did fix the OP's problem the OP might think about separation of markup and code, thus not using inline code within html element markup.
Making use of the html form element that then hosts specific form controls like input, button etc. is highly advised too. Making
use of the "DOM Level 0" form collection also is not outdated. Event delegation as provided with the next example for instance helps if there will be other controls added to a form dynamically - one does not need to take care about registering event handlers to each newly appended form control. And last, registering to 'change' events will capture every change to the radio collection ...
function isMercedesTransferType(elmNode) {
return ((elmNode.type === 'radio') && (elmNode.name === 'mercedes'));
}
function handleVipTransferChange(evt) {
var elmNode = evt.target;
if (isMercedesTransferType(elmNode) && elmNode.checked) {
console.log('handleVipTransferChange [name, value] : ', elmNode.name, elmNode.value);
}
}
function initializeVipTransfer() {
document.forms['mercedes-vip-transfer'].addEventListener('change', handleVipTransferChange, false);
}
initializeVipTransfer();
.as-console-wrapper { max-height: 100%!important; top: 70px; }
<form class="form-group" name="mercedes-vip-transfer">
<legend>Mercedes VIP transfer*:</legend>
<label>
<input type="radio" name="mercedes" value="yes">
<span>Yes</span>
</label>
<label>
<input type="radio" name="mercedes" value="no">
<span>No</span>
</label>
</form>
Another way of dealing with initializing the required form controls directly will be demonstrated hereby ...
function isMercedesTransferType(elmNode) {
return ((elmNode.type === 'radio') && (elmNode.name === 'mercedes'));
}
function handleVipTransferChange(evt) {
var elmNode = evt.target;
if (elmNode.checked) {
console.log('handleVipTransferChange [name, value] : ', elmNode.name, elmNode.value);
}
}
function initializeVipTransfer() {
var list = document.forms['mercedes-vip-transfer'].elements['mercedes'];
Array.from(list).filter(isMercedesTransferType).forEach(function (elmNode) {
elmNode.addEventListener('change', handleVipTransferChange, false);
});
}
initializeVipTransfer();
.as-console-wrapper { max-height: 100%!important; top: 70px; }
<form class="form-group" name="mercedes-vip-transfer">
<legend>Mercedes VIP transfer*:</legend>
<label>
<input type="radio" name="mercedes" value="yes">
<span>Yes</span>
</label>
<label>
<input type="radio" name="mercedes" value="no">
<span>No</span>
</label>
</form>
... and just in order to round it up, if there is an "up to date" DOM, one might consider making use of modern DOM queries via querySelector and/or querySelectorAll ...
function handleVipTransferChange(evt) {
var elmNode = evt.target;
if (elmNode.checked) {
console.log('handleVipTransferChange [name, value] : ', elmNode.name, elmNode.value);
}
}
function initializeVipTransfer() {
var list = document.querySelectorAll('#mercedes-vip-transfer [type="radio"][name="mercedes"]');
Array.from(list).forEach(function (elmNode) {
elmNode.addEventListener('change', handleVipTransferChange, false);
});
}
initializeVipTransfer();
.as-console-wrapper { max-height: 100%!important; top: 70px; }
<form class="form-group" id="mercedes-vip-transfer">
<legend>Mercedes VIP transfer*:</legend>
<label>
<input type="radio" name="mercedes" value="yes">
<span>Yes</span>
</label>
<label>
<input type="radio" name="mercedes" value="no">
<span>No</span>
</label>
</form>
Related
I need some help as I'm fairly new to JavaScript.
I wish to create a function that calculates a membership fee
I tried making a function in JavaScript that checks whether only one option has been selected, but I have no idea how to make it so that I can calculate the fee if a user is eligible for more than one or all discounts. There is no current JS for the age condition yet (between 60 and 80) as I am unsure how to do it.
function feeCalc() {
var ans = document.getElementById("answer");
if (document.getElementById('medicalCond-yes').checked) {
ans.value = calculate('medicalCond-yes');
}
if (document.getElementById('empstatus-yes').checked) {
ans.value = calculate('empstatus-yes');
}
if (document.getElementById('empstatus-no').checked) {
ans.value = calculate('empstatus-no');
}
if (document.getElementById('medicalCond-no').checked) {
ans.value = calculate('medicalCond-no');
}
}
function calculate(action) {
var standardRate = 10;
var ageRate = 0.1;
var medicalRate = 0.4;
var unemployedRate = 0.3;
var result;
switch (action) {
case 'medicalcond-yes':
discount = (standardRate * studentRate);
result = standardRate - discount;
break;
case 'empstatus-yes':
discount = (standardRate * unemployedRate);
result = standardRate - discount;
break;
case 'empstatus-no':
result = standardRate;
break;
case 'medicalcond-no':
result = standardRate;
break;
}
return result;
}
<div class="form">
<label>
Age
</label>
<input type="range" value="50" min="1" max="100" class="slider" id="age"/>
</div>
<div class="form">
<label>
Do you have any long-term medical conditions
that can affect daily life
</label>
<br/>
<input type="radio" name="status" value="yes" id="medicalCond-yes"/>Yes
<input type="radio" name="status" value="no" id="medicalCond-no"/>No
</div>
<div class="form">
<label>
Are you currently employed?
</label>
<br/>
<input type="radio" name="empstatus" value="yes" id="empstatus-yes"/>Yes
<input type="radio" name="empstatus" value="no" id="empstatus-no"/>No
</div>
<div class="form">
<label>
Membership Fee
</label>
<br/>
Total Fee:
<input type="text" id="answer" readonly/>
<input type="button" value="Calculate" onclick="feeCalc()"/>
</div>
Even though for the OP's problem it looks like over-engineering, the OP's provided code is nevertheless small enough in order to demonstrate the advantages of (more) generic approaches which are ...
Being forced to work with a clean HTML markup/structure as DOM and/or data base.
Decoupling (validation) code from very (business) case specific data like ... not depending anymore ...
on very specific DOM-element queries,
on "baked in" data for e.g. validation and edge case handling.
On long term base easier to maintain (in terms of changed business data) and to adapt to e.g. new discount options.
Especially the JavaScript code which implements a generic approach/behavior of cause is larger from the beginning than its very explicitly written competitor. But the former does not tend to grow or does not even need to get touched for new discount options or changed discount values. This part gets covered by cleaner more generic (hence reusable) substructures of the also generic calculator superstructure.
In addition such a generic component based approach automatically enables the usage of more than just one component at/within one and the same document.
function parseJson(str) {
let result;
try {
result = JSON.parse(str);
} catch (exc) {
result = null;
}
return result;
}
function getDevaluationFactorFromRange(formControl, range) {
let factor = 0;
range = parseJson(range);
if (range !== null) {
const controlValue = parseFloat(formControl.value);
Object
.entries(range)
.some(([devaluationKey, { min, max }]) => {
let isStopIteration = false;
if (
(controlValue >= parseFloat(min)) &&
(controlValue <= parseFloat(max))
) {
factor = parseFloat(devaluationKey);
isStopIteration = true;
}
return isStopIteration
});
}
return Number.isFinite(factor) ? factor : 0;
}
function getDevaluationFactor(formControl) {
const { dataset } = formControl;
let rawRange = dataset.devaluationRange ?? null;
let rawFactor = dataset.devaluationFactor ?? null;
let factor = (rawRange !== null)
? getDevaluationFactorFromRange(formControl, rawRange)
: 0;
factor = (
(factor === 0) && (rawFactor !== null) && parseFloat(rawFactor)
) || factor;
factor = Number.isFinite(factor) ? factor : 0;
if (factor !== 0) {
const { type } = formControl;
if ((type === 'radio') || (type === 'checkbox')) {
factor = formControl.checked ? factor : 0;
}
}
return factor;
}
function computeCurrentFee(rootNode, elmFee, baseFee) {
return Array
// array from `HTMLFormControlsCollection`
.from(rootNode.elements)
// calculate currrent fee from each form element's data
.reduce((currentFee, formControl) => {
return currentFee - (baseFee * getDevaluationFactor(formControl));
}, baseFee);
}
function updateCurrentValueAtBoundFeeContext(/*evt*/) {
const { rootNode, elmFee, baseFee } = this;
elmFee.value = computeCurrentFee(rootNode, elmFee, baseFee);
}
function displayCurrentValueAtBoundAgeContext(/*evt*/) {
const { elmRange, elmOutput } = this;
elmOutput.value = elmRange.value;
}
function initializeCurrentAgeDisplay(rootNode) {
const ageNode = rootNode.querySelector('[data-age-range]');
if (ageNode) {
const elmRange = ageNode.querySelector('input[type="range"]');
const elmOutput = ageNode.querySelector('output');
if (elmRange && elmOutput) {
const target = { elmRange, elmOutput };
const boundContextHandler =
displayCurrentValueAtBoundAgeContext.bind(target);
elmRange.addEventListener('input', boundContextHandler);
rootNode.addEventListener('reset', () =>
// decouple custom dom refresh from the system's one.
setTimeout(boundContextHandler, 0)
);
// display initial age value.
// // displayCurrentValueAtBoundAgeContext.call(target);
boundContextHandler();
}
}
}
function initializeMembershipFeeCalculator(rootNode) {
const DEFAULT_BASE_FEE = 10;
initializeCurrentAgeDisplay(rootNode);
const elmFeeValue = rootNode.querySelector('[data-fee-value]');
if (elmFeeValue) {
const baseFee = parseFloat(rootNode.dataset.baseFee);
const target = {
rootNode,
elmFee: elmFeeValue,
baseFee: Number.isFinite(baseFee) ? baseFee : DEFAULT_BASE_FEE,
};
const boundContextHandler =
updateCurrentValueAtBoundFeeContext.bind(target);
rootNode.addEventListener('input', boundContextHandler);
rootNode.addEventListener('reset', () =>
// decouple custom dom refresh from the system's one.
setTimeout(boundContextHandler, 0)
);
// compute initial fee value.
// // updateCurrentValueAtBoundFeeContext.call(target);
boundContextHandler();
rootNode.addEventListener('submit', evt => {
evt.preventDefault();
return false;
});
}
}
function main() {
document
.querySelectorAll('form[data-membership-fee-calculator]')
.forEach(initializeMembershipFeeCalculator);
}
main();
body, form {
margin: 0;
padding: 0;
}
form {
float: left;
width: 50%;
margin-top: -2px;
}
fieldset {
position: relative;
margin: 0 0 2px 0;
padding: 0 10px 2px 10px;
}
fieldset p {
margin: 1px 0 2px 0;
}
fieldset output {
color: #333;
font-weight: bolder;
}
label {
display: inline-block;
}
input[type="range"] {
width: 70%;
}
[data-age-range] output {
display: inline-block;
overflow: hidden;
max-width: 25%;
max-height: 1.2em;
position: relative;
top: 1px;
}
[type="reset"] {
position: absolute;
right: 4px;
top: -4px;
}
<form data-membership-fee-calculator data-base-fee="10">
<fieldset data-age-range>
<legend>
Age
</legend>
<input
type="range"
name="age" id="age"
value="50" min="1" max="100"
data-devaluation-range='{"0.1":{"min":60,"max":80}}'
/>
<output for="age">### not yet computed ###</output>
</fieldset>
<fieldset>
<p>
Do you have any long-term medical conditions
that can affect daily life?
</p>
<label>
<input
type="radio"
name="status"
value="yes"
data-devaluation-factor="0.4"
/>
<span class="label-copy">
Yes
</span>
</label>
<label>
<input type="radio" name="status" value="no" />
<span class="label-copy">
No
</span>
</label>
</fieldset>
<fieldset>
<p>
Are you currently employed?
</p>
<label>
<input
type="radio"
name="empstatus"
value="yes"
data-devaluation-factor="0.3"
/>
<span class="label-copy">
Yes
</span>
</label>
<label>
<input type="radio" name="empstatus" value="no" />
<span class="label-copy">
No
</span>
</label>
</fieldset>
<fieldset>
<legend>
Membership Fee
</legend>
<label>
<span class="label-copy">
Total Fee:
</span>
<output data-fee-value>### not yet computed ###</output>
</label>
<button type="reset">Restore base fee</button>
</fieldset>
</form>
<form data-membership-fee-calculator data-base-fee="20">
<fieldset data-age-range>
<legend>
Age
</legend>
<input
type="range"
name="age" id="age"
value="21" min="1" max="100"
data-devaluation-range=
'{"0.05":{"min":60,"max":69},"0.1":{"min":70,"max":79},"0.2":{"min":80,"max":120}}'
/>
<output for="age">### not yet computed ###</output>
</fieldset>
<fieldset>
<p>
Do you have any long-term medical conditions
that can affect daily life?
</p>
<label>
<input
type="radio"
name="status"
value="yes"
data-devaluation-factor="0.3"
/>
<span class="label-copy">
Yes
</span>
</label>
<label>
<input type="radio" name="status" value="no" />
<span class="label-copy">
No
</span>
</label>
</fieldset>
<fieldset>
<p>
Are you currently employed?
</p>
<label>
<input
type="radio"
name="empstatus"
value="yes"
data-devaluation-factor="0.3"
/>
<span class="label-copy">
Yes
</span>
</label>
<label>
<input type="radio" name="empstatus" value="no" />
<span class="label-copy">
No
</span>
</label>
</fieldset>
<fieldset>
<legend>
Membership Fee
</legend>
<label>
<span class="label-copy">
Total Fee:
</span>
<output data-fee-value>### not yet computed ###</output>
</label>
<button type="reset">Restore base fee</button>
</fieldset>
</form>
Instead of switch-case routing into a single branch, you probably want to check through all cases in one go.
function feeCalc() {
var ans = document.getElementById("answer");
ans.value = calculateRate();
}
function calculateRate() {
let discount = 0;
const age = Number(document.getElementById('age').value);
if (age >= 60 && age <= 80) {
discount += 0.1;
}
if (document.getElementById('medicalCond-yes').checked) {
discount += 0.4;
}
if (document.getElementById('empstatus-no').checked) {
discount += 0.3;
}
return 1 - discount;
}
<div class="form">
<label>
Age
</label>
<input type="range" value="50" min="1" max="100" class="slider" id="age"/>
</div>
<div class="form">
<label>
Do you have any long-term medical conditions
that can affect daily life
</label>
<br/>
<input type="radio" name="status" value="yes" id="medicalCond-yes"/>Yes
<input type="radio" name="status" value="no" id="medicalCond-no"/>No
</div>
<div class="form">
<label>
Are you currently employed?
</label>
<br/>
<input type="radio" name="empstatus" value="yes" id="empstatus-yes"/>Yes
<input type="radio" name="empstatus" value="no" id="empstatus-no"/>No
</div>
<div class="form">
<label>
Membership Fee
</label>
<br/>
Total Fee:
<input type="text" id="answer" readonly/>
<input type="button" value="Calculate" onclick="feeCalc()"/>
</div>
I have a series of randomly generated textbox and radio-button inputs. It's kinda like a Quiz, so what I would like to do is collect all of the inputs and send them to the server so it can evaluate them.
Now, to make it easier, I put all of the radio-button inputs to the end.
I use the following code to collect the inputs of the textbox-types:
$('#button_submit').click(function() {
var answer_list = '';
$('input:text').each(function(index,data) {
answer_list = answer_list + '$' + $(data).val();
}
...
}
This works perfectly, but after this, I don't know what to do. I could loop through the input:radio:checked elements and add the value of those to my string, which would work perfectly, except if the user decides to submit their answers while leaving one of the radio-button inputs empty. In that case, nothing gets added to the string and the server will be missing the answer to that question and it messes everything up.
So I need to add something to my string when the code realizes that there is a radio-button question, but no answer was chosen, but I have no idea how to do it.
Edit:
HTML example:
<div class="form-group" id="form-group-34">
<label class="control-label " for="question">What is 92848 × 71549?</label>
<input autofocus="true" class="form-control" id="input34" name="answer" size="20" type="text" value="">
</div>
<div class="form-group" id="form-group-35">
<label class="control-label " for="question">Is 194 divisible by 3?</label>
<br><input id="14-answer-0" name="14-answer" type="radio" value="1">
<label for="14-answer-0">Yes</label>
<br><input id="14-answer-1" name="14-answer" type="radio" value="0">
<label for="14-answer-1">No</label>
</div>
<div class="form-group" id="form-group-36">
<label class="control-label " for="question">Determine the day of the week for 1954 Jun 26!</label>
<br><input id="35-answer-0" name="35-answer" type="radio" value="1">
<label for="35-answer-0">Monday</label>
<br><input id="35-answer-1" name="35-answer" type="radio" value="2">
<label for="35-answer-1">Tuesday</label>
<br><input id="35-answer-2" name="35-answer" type="radio" value="3">
<label for="35-answer-2">Wednesday</label>
<br><input id="35-answer-3" name="35-answer" type="radio" value="4">
<label for="35-answer-3">Thursday</label>
<br><input id="35-answer-4" name="35-answer" type="radio" value="5">
<label for="35-answer-4">Friday</label>
<br><input id="35-answer-5" name="35-answer" type="radio" value="6">
<label for="35-answer-5">Saturday</label>
<br><input id="35-answer-6" name="35-answer" type="radio" value="0">
<label for="35-answer-6">Sunday</label>
</div>
But the problem is, that these questions are randomly generated. So there can be 5 simple textbox-type inputs, then 5 radio-button type ones, or there might be only 1 radio-button type question, and all of their attributes are generated dynamically, so I can't really put the radio-button group's name in the code, because I don't know it.
You could use this to see if they are all checked:
var allRadios = $('input[name="namevalue"][type=radio]').length;
var allCheckedRadios $('input[name="namevalue"][type=radio]').filter(function() {
return this.checked;
}).length;
if( allRadios == allCheckedRadios){
// do what you need
}
whatever your name is change "namevalue" to that. The same basic logic to get the values can be applied.
Note: performance gain for modern browsers on these selector forms above over $('input:radio') can be had.
EDIT From updated question:
Here I applied the techniques above to walk through each of the form groups looking for radio buttons, and if they exist throw an alert if none are checked within that group. You could also create and return a Boolean value if ANY of the groups have radio selections with none selected. "hasUncheckedRadios" will be either 0 if none are checked or 1 if one is checked - since radio buttons within a group only select one. You could use this logic in your validation to ensure that all of the groups have a valid checked radio button (IF they contain a radio that is);
function checkRadios() {
var allGroups = $('.form-group');
allGroups.each(function() {
var allRadios = $(this).find('input[type=radio]').length;
var hasUncheckedRadios = $(this).find('input[type=radio]').filter(function() {
return this.checked;
}).length;
console.log('total:' + allRadios + ' checked:' + hasUncheckedRadios);
// if allRadios is > 0 then radios exist and hasUncheckedRadios == 0 none are checked
if (allRadios && !hasUncheckedRadios) {
alert("Form Group" + $(this).attr('id') + " has radio buttons unaswered");
}
});
}
$('#checkem').on('click', function() {
console.log('checking...');
checkRadios();
});
fiddle with it here: https://jsfiddle.net/MarkSchultheiss/nv7cjpr2/
I would iterate a bit more: https://jsfiddle.net/Twisty/ghc7u2ab/
HTML
<div class="form-group" id="form-group-34">
<label class="control-label " for="question">What is 92848 × 71549?</label>
<input autofocus="true" class="form-control" id="input34" name="answer" size="20" type="text" value="">
</div>
<div class="form-group" id="form-group-35">
<label class="control-label " for="question">Is 194 divisible by 3?</label>
<br>
<input id="14-answer-0" name="14-answer" type="radio" value="1">
<label for="14-answer-0">Yes</label>
<br>
<input id="14-answer-1" name="14-answer" type="radio" value="0">
<label for="14-answer-1">No</label>
</div>
<div class="form-group" id="form-group-36">
<label class="control-label " for="question">Determine the day of the week for 1954 Jun 26!</label>
<br>
<input id="35-answer-0" name="35-answer" type="radio" value="1">
<label for="35-answer-0">Monday</label>
<br>
<input id="35-answer-1" name="35-answer" type="radio" value="2">
<label for="35-answer-1">Tuesday</label>
<br>
<input id="35-answer-2" name="35-answer" type="radio" value="3">
<label for="35-answer-2">Wednesday</label>
<br>
<input id="35-answer-3" name="35-answer" type="radio" value="4">
<label for="35-answer-3">Thursday</label>
<br>
<input id="35-answer-4" name="35-answer" type="radio" value="5">
<label for="35-answer-4">Friday</label>
<br>
<input id="35-answer-5" name="35-answer" type="radio" value="6">
<label for="35-answer-5">Saturday</label>
<br>
<input id="35-answer-6" name="35-answer" type="radio" value="0">
<label for="35-answer-6">Sunday</label>
</div>
<button id="button_submit">Submit</button>
JQuery
$("#button_submit").click(function() {
var answer_list = {};
$(".form-group").each(function(i, v) {
console.log("Index:", i, "ID: [", $(v).attr("id"), "]");
answer_list[$(v).attr("id")] = {};
var ind = $(v).find("input");
$.each(ind, function(i2, el) {
console.log("Type of Element:", $(el).attr("type"));
switch ($(el).attr("type")) {
case "text":
answer_list[$(v).attr("id")][$(el).attr("id")] = ($(el).val() != "") ? $(el).val() : null;
break;
case "radio":
var isAnswered = false;
$(el).each(function(i3, rad) {
if ($(rad).is(":checked")) {
answer_list[$(v).attr("id")][$(rad).attr("name")] = $(rad).val();
isAnswered = true;
}
if (!isAnswered) {
answer_list[$(v).attr("id")][$(el).eq(0).attr("name")] = null;
}
});
break;
}
});
});
console.log(answer_list);
return false;
});
Possible Result
answer_list: {
form-group-34: {
input34: null
},
form-group-35: {
14-answer: 0
},
form-group-36: {
35-answer: null
}
}
This will iterate each group and look for an answer. If one is found, the value is added. If not, null is added as the result.
loop class group that has radio then use .prop("checked")
var frmGroup= 0, checked= 0;
$('.form-group').each(function(index) {
if ($(this).children('input:radio').length > 0) {
frmGroup++;
$(this).children('input:radio').each(function(index) {
if ($(this).prop("checked") == true) {
checked++;
}
});
}
});
if(frmGroup != checked)...
working example: https://jsfiddle.net/nsL3drz5/
I am trying to show a red circle with the "!" when the radio buttons are unchecked and to show a green circle when both are checked. After that I use a function to make the button submit or not according to the red/green circle.
I've tried many ways to tangle with the code but it doesn't want to show the green circle when it's checked any idea why ?
PS:
span3 (red circle )
span2 (green circle)
Basically I want to make my form validation by js not by php ...
HTML:
<label id="labelage">Age:</label>
<br>
<input type="radio" id="under_13" value="under_13" name="age">
<label for="under_13" class="light">Under 13</label>
<input type="radio" id="over_13" value="over_13" name="age">
<label for="over_13" class="light">13 or Older</label>
<div class="break"></div>
<div id="borderlabel">
<label id="labelage1">Gender:</label>
<input type="radio" id="male" value="male" name="gender">
<label for="male" class="light1">Male</label>
<input type="radio" id="female" value="female" name="gender">
<label for="female" class="light1">Female</label>
</div>
....
<button type="submit" id="signupb" name="register">Sign up
<div class="span3">!</div>
<div class="span2">✔</div>
</button>
JavaScript
$(".span1").hide();
$(".span2").hide();
$(".span3").hide();
function submit() {
if (!$('#male').is(':checked') || !$('#female').is(':checked')) {
$(".span3").show();
} else {
if (!$('#under_13').is(':checked') || !$('#over_13').is(':checked')) {
$(".span3").show();
} else {
$(".span2").show();
}
}
}
$("#signupb").on("mouseover", submit);
Your logic is off
Have the radio clicks also update the !
Do not call something submit
Cancel the submission if clicking anyway
Try this:
function checkRad() {
var ok = ($('#male').is(':checked') || $('#female').is(':checked')) &&
($('#under_13').is(':checked') || $('#over_13').is(':checked'))
$(".span3").toggle(!ok);
$(".span2").toggle(ok);
return ok;
}
$(function() {
$(".span1").hide();
$(".span2").hide();
$(".span3").hide();
$("#signupb").on("mouseover", checkRad)
.on("click", function(e) {
if (!checkRad()) e.preventDefault();
})
$("input[type=radio]").on("click", function() {
checkRad();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label id="labelage">Age:</label>
<br>
<input type="radio" id="under_13" value="under_13" name="age">
<label for="under_13" class="light">Under 13</label>
<input type="radio" id="over_13" value="over_13" name="age">
<label for="over_13" class="light">13 or Older</label>
<div class="break"></div>
<div id="borderlabel">
<label id="labelage1">Gender:</label>
<input type="radio" id="male" value="male" name="gender">
<label for="male" class="light1">Male</label>
<input type="radio" id="female" value="female" name="gender">
<label for="female" class="light1">Female</label>
</div>
....
<button type="submit" id="signupb" name="register">Sign up
<div class="span3">!</div>
<div class="span2">✔</div>
</button>
I would recommend using jQuery Validation plugin instead
It's bad practice to assign IDs to every input element, makes code harder to maintain. Consider accessing elements by name attribute.
Consider adding server-side validation as well against browser errors/malicious users.
Change your submit() function to:
function validateForm() {
$(".span2").hide();
$(".span3").hide();
var isError = false;
if (!$('#male').is(':checked') && !$('#female').is(':checked')) {
isError = true
} else if (!$('#under_13').is(':checked') && !$('#over_13').is(':checked')) {
isError = true;
}
if(isError){
$(".span3").show();
} else {
$(".span2").show();
}
}
$("#signupb").on("mouseover", validateForm);
DEMO
function toggle(source) {
checkboxes = document.getElementsByName('options[]');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
}
}
<form class="unsubscribe_form" action="process.php" method="post">
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-1" value="Option1">
<label for="checkbox-1-1"></label>Option 1
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-2" value="Option2">
<label for="checkbox-1-2"></label>Option 2
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-3" value="Option2">
<label for="checkbox-1-3"></label>Option 3
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-4" value="Option3">
<label for="checkbox-1-4"></label>Option 4
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-5" value="Option3">
<label for="checkbox-1-5"></label>Option 5
<input type="checkbox" class="unsubscribe-checkbox" id="checkbox-1-6" value="All" onClick="toggle(this)" />
<label for="checkbox-1-6"></label>All
<br>
<input type="submit" name="formSubmit" value="Unsubscribe" />
</form>
When I check the All checkbox, of course, it will mark all the checkboxes, but once I uncheck one checkbox, the All checkbox is still checked. This should be unchecked. How should I do that using JS?
You will need to add onchange event handlers to every checkbox and check inside if the "All" checkbox should be checked (all checkboxes are selected) or unchecked (at least one is deselected). For example like this:
var checkboxes = [].slice.call(document.getElementsByName('options[]')),
allCheckbox = document.querySelector('input[value="All"]');
checkboxes.forEach(function(checkbox) {
checkbox.onchange = function() {
if (!this.checked) {
allCheckbox.checked = false;
}
else {
var checked = checkboxes.filter(function(check) {
return check.checked;
});
if (checked.length === checkboxes.length) {
allCheckbox.checked = true;
}
}
};
});
function toggle(source) {
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
}
}
<form class="unsubscribe_form" action="process.php" method="post">
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-1" value="Option1">
<label for="checkbox-1-1"></label>Option 1
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-2" value="Option2">
<label for="checkbox-1-2"></label>Option 2
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-3" value="Option2">
<label for="checkbox-1-3"></label>Option 3
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-4" value="Option3">
<label for="checkbox-1-4"></label>Option 4
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-5" value="Option3">
<label for="checkbox-1-5"></label>Option 5
<input type="checkbox" class="unsubscribe-checkbox" id="checkbox-1-6" value="All" onClick="toggle(this)" />
<label for="checkbox-1-6"></label>All
</form>
Note that I converted checkboxes collection to array with [].slice.call in order to use convenient array methods. Simple for loops can be used instead.
I'd suggest the following:
function toggle() {
// getting a reference to all the 'name="option[]" elements:
var options = document.getElementsByName('options[]'),
// a reference to the 'all' checkbox:
all = document.getElementById('checkbox-1-6');
// if the changed checkbox is the 'all':
if (this === all) {
// we iterate over all the options checkboxes (using
// Array.prototype.forEach()):
Array.prototype.forEach.call(options, function(checkbox) {
// and we set their checked property to the checked property
// state of the 'all' checkbox:
checkbox.checked = all.checked;
});
} else {
// otherwise we set the 'all' checkbox to the state of
// the Boolean returned by Array.prototype.every(),
// which returns true if all checkboxes evaluate to
// the condition within the function, otherwise false:
all.checked = Array.prototype.every.call(options, function(checkbox) {
return checkbox.checked;
});
}
}
// getting a NodeList of all the elements of 'class="unsubscribe-checkbox"':
var options = document.querySelectorAll('.unsubscribe-checkbox');
// iterating over them, again with Array.prototype.forEach()
// and assigning a change event-listener, which will execute the
// name function:
Array.prototype.forEach.call(options, function(opt) {
opt.addEventListener('change', toggle);
});
function toggle() {
var options = document.getElementsByName('options[]'),
all = document.getElementById('checkbox-1-6');
if (this === all) {
Array.prototype.forEach.call(options, function(checkbox) {
checkbox.checked = all.checked;
});
} else {
all.checked = Array.prototype.every.call(options, function(checkbox) {
return checkbox.checked;
});
}
}
var options = document.querySelectorAll('.unsubscribe-checkbox');
Array.prototype.forEach.call(options, function(opt) {
opt.addEventListener('change', toggle);
});
<form class="unsubscribe_form" action="process.php" method="post">
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-1" value="Option1">
<label for="checkbox-1-1"></label>Option 1
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-2" value="Option2">
<label for="checkbox-1-2"></label>Option 2
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-3" value="Option2">
<label for="checkbox-1-3"></label>Option 3
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-4" value="Option3">
<label for="checkbox-1-4"></label>Option 4
<input type="checkbox" class="unsubscribe-checkbox" name="options[]" id="checkbox-1-5" value="Option3">
<label for="checkbox-1-5"></label>Option 5
<input type="checkbox" class="unsubscribe-checkbox" id="checkbox-1-6" value="All" />
<label for="checkbox-1-6"></label>All
<br>
<input type="submit" name="formSubmit" value="Unsubscribe" />
</form>
You may notice that I've removed the onClick attribute from the 'all' checkbox, in preference of unobtrusive JavaScript, where the event-handlers are assigned via the JavaScript itself (which ordinarily makes for more easily-maintained code, as the arguments to be passed to a given function are assigned in the code itself, rather than having to be separately updated in the HTML).
References:
Array.prototype.every().
Array.prototype.forEach().
document.getElementsByName().
document.getElementById().
document.querySelectorAll().
EventTarget.addEventListener().
Function.prototype.call().
When the user selects a radio button in the 2 categories Plan details and Plan Duration the input field should populate with the relevant data through JavaScript.
Please check the html markup and JavaScript below and suggest corrections or an alternate method that would work.
<h3 class="fltClear">Plan Details</h3>
<div id="spryradio1">
<dt>Plan Type: <span class="required">*</span></dt>
<dd>
<label>
<input type="radio" name="RadioGroup1" value="Silver" id="RadioGroup1_0" onClick="changeplanprice();" class="RadioGroup1" />
Silver</label>
<br>
<label>
<input type="radio" name="RadioGroup1" value="Gold" id="RadioGroup1_1" onClick="changeplanprice();" class="RadioGroup1" />
Gold</label>
<br>
<label>
<input type="radio" name="RadioGroup1" value="Platinum" id="RadioGroup1_2" onClick="changeplanprice();" class="RadioGroup1" />
Platinum</label>
<br>
<label>
<input type="radio" name="RadioGroup1" value="All-in-one" id="RadioGroup1_3" onClick="changeplanprice();" class="RadioGroup1" />
All-in-one</label>
<br>
<span class="radioRequiredMsg">Please make a selection.<span class="hint-pointer"> </span></span>
</dd>
</div>
<!--Plan Duration-->
<div id="spryradio2">
<dt>Plan Duration: <span class="required">*</span></dt>
<dd>
<label>
<input type="radio" name="RadioGroup2" value="Yearly" id="RadioGroup2_0" onClick="changeplanprice();" class="RadioGroup2" />
Yearly</label>
<br>
<label>
<input type="radio" name="RadioGroup2" value="Quaterly" id="RadioGroup2_1" onClick="changeplanprice();" class="RadioGroup2" />
Quaterly</label>
<br>
<label>
<input type="radio" name="RadioGroup2" value="Monthly" id="RadioGroup2_2" onClick="changeplanprice();" class="RadioGroup2" />
Monthly</label>
<br>
<label>
<input type="radio" name="RadioGroup2" value="Other" id="RadioGroup2_3" onClick="changeplanprice();" class="RadioGroup2" />
Other</label>
<br>
<span class="radioRequiredMsg">Please make a selection.<span class="hint-pointer"> </span></span>
</dd>
</div>
<!--Plan Price-->
<div>
<script>
function changeplanprice() {
var plantype=document.getElementByClassName('RadioGroup1').value;
var planduration=document.getElementByClassName('RadioGroup2').value;
if(plantype=="Silver") {
if(planduration=="Monthly") {
document.getElementById('Price').value='£ 39.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Quaterly") {
document.getElementById('Price').value='£ 79.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Yearly") {
document.getElementById('Price').value='£ 124.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Other") {
document.getElementById('Price').value='';
document.getElementById('Price').readOnly=false;
}
}
else if(plantype=="Gold") {
if(planduration=="Monthly") {
document.getElementById('Price').value='£ 49.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Quaterly") {
document.getElementById('Price').value='£ 99.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Yearly") {
document.getElementById('Price').value='£ 179.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Other") {
document.getElementById('Price').value='';
document.getElementById('Price').readOnly=false;
}
}
else if(plantype=="Platinum") {
if(planduration=="Monthly") {
document.getElementById('Price').value='£ 59.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Quaterly") {
document.getElementById('Price').value='£ 199.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Yearly") {
document.getElementById('Price').value='£ 279.98';
document.getElementById('Price').readOnly=true;
}
else if(planduration=="Other") {
document.getElementById('Price').value='';
document.getElementById('Price').readOnly=false;
}
} }
</script>
<div>
<dt><label for="Price">Plan Price:</label></dt>
<dd class="bg"><input type="text" name="Price" id="Price" size="80" class="input" readonly="readonly" />
</dd>
</div>
First suggestion that I will give is to have single
document.getElementById('Price').readOnly=true;
This will make your code more readable.
Second suggestion is that you can have 2 arrays one for plantype and other for planduration, and the radio-buttons instead of text, have array index as value.
This will not only make your code more readable, but also more manageable.
Suppose if you have to add one planduration, you will have to add the same condition for all plantypes, where there is a possibility of missing out one case.
Your function could use a little bit of cleanup, but there is one problem that I see. You are using document.getElementByClassName(' ... ').value;. This isn't correct. The function is actually document.getElementsByClassName (note Elements is plural). This function returns an array of all elements with that class name. So you cannot call .value directly on that. You would need to loop through the array of elements to find which element is checked and take the value of that.
Given that all the radio buttons of one group have the same name, and there is another function, document.getElementsByName, there is no reason to use getElementsByClassName.
I would change your function. This is tested and works, and is more easily scalable, in case you come up with new pricing options. All you would have to do is add on to the prices object:
function changeplanprice() {
var plantype;
var plantypes = document.getElementsByName('RadioGroup1');
for (var i=0; i < plantypes.length; i++) {
if (plantypes[i].checked)
plantype = plantypes[i].value;
}
var planduration;
var plandurations = document.getElementsByName('RadioGroup2');
for (i = 0; i < plandurations.length; i++) {
if (plandurations[i].checked)
planduration = plandurations[i].value;
}
if (plantype === undefined || planduration === undefined)
return;
document.getElementById('Price').readOnly = (planduration != "Other");
var prices = {
"Silver":{
"Monthly":"£ 39.98",
"Quarterly":"£ 79.98",
"Yearly":"£ 124.98",
"Other":""
},
"Gold":{
"Monthly":"£ 49.98",
"Quarterly":"£ 99.98",
"Yearly":"£ 179.98",
"Other":""
},
"Platinum":{
"Monthly":"£ 59.98",
"Quarterly":"£ 199.98",
"Yearly":"£ 279.98",
"Other":""
},
"All-in-one":{
"Monthly":"...", /* prices weren't provided for All-in-one in the example */
"Quarterly":"...",
"Yearly":"...",
"Other":""
}
};
document.getElementById('Price').value = prices[plantype][planduration];
}