How to get fields via children or childnodes - javascript

I need to get the children of the Section block. Namely fields and rabiobuttons. Next, check them for fullness. How to do it. I tried to get through childNodes, children but nothing worked.
In this case, I want to get the context of the section block and check the fields
Such sections, I need to validate section by section and until the previous one is filled, I do not validate the next one.
const formStepTwo = document.getElementById("formStepTwo");
const Section = document.querySelectorAll(".Section");
formStepTwo.addEventListener("change", () => {
//console.log( Section.item(0))
let count = Array.from(Section).forEach((i) => {
let context = i.children;
context.item()
console.log( this.querySelectorAll(".input[type=radio]"))
//console.log(context.forEach());
});
});
<form class="stepTwo-profile" id="formStepTwo">
<p class="stepTwo-profile-title">Демография</p>
<div class="Section">
<label for="age"
>Возраст пациента<input
type="number"
class="stepTwo-profile-item-textAge"
name="age"
min="0"
max="80"
maxlength="2"
id="age"
/></label>
<p class="stepTwo-profile-item-smTitle">Пол</p>
<label for="male">
<input type="radio" name="gender" id="male" value="male" />Мужской
<span class="stepTwo-profile-item-radionbtn"></span
></label>
<label for="female">
<input type="radio" name="gender" id="female" value="female" />Женский
<span class="stepTwo-profile-item-radionbtn"></span>
</label>
</div>
</div>
</form>

You can actually check for input fields by targeting 'label' since they directly wrap over the input tag. Targeting through .Section can get a bit tricky, but is doable.
Another alternative is to directly target input fields using querySelectorAll('input') and then check for their type.
I've added example of both in the code snippet :
const formStepTwo = document.getElementById("formStepTwo");
const labels = document.querySelectorAll("label");
formStepTwo.addEventListener("change", () => {
let count = Array.from(labels).forEach((i) => {
let children = i.children;
Array.from(children).forEach((node) => {
if(node.nodeName.toLowerCase() === 'input') {
switch(node.type) {
case 'number' : validateNumberField(node);
break;
case 'radio' : validateRadio(node);
break;
// add more cases as required
default:
console.log('add default');
}
}
});
});
});
// Can also be done by targeting input directly
const input = document.querySelectorAll('input');
formStepTwo.addEventListener("change", () => {
Array.from(input).forEach((node) => {
if(node.nodeName.toLowerCase() === 'input') {
switch(node.type) {
case 'number' : validateNumberField(node);
break;
case 'radio' : validateRadio(node);
break;
// add more cases as required
default:
console.log('add default');
}
}
});
});
function validateNumberField(node) {
console.log('validating number field');
// add your validation
}
function validateRadio(node) {
console.log('validation radio button');
// add your validation for radio
}
<form class="stepTwo-profile" id="formStepTwo">
<p class="stepTwo-profile-title">Демография</p>
<div class="Section">
<label for="age"
>Возраст пациента<input
type="number"
class="stepTwo-profile-item-textAge"
name="age"
min="0"
max="80"
maxlength="2"
id="age"
/></label>
<p class="stepTwo-profile-item-smTitle">Пол</p>
<label for="male">
<input type="radio" name="gender" id="male" value="male" />Мужской
<span class="stepTwo-profile-item-radionbtn"></span
></label>
<label for="female">
<input type="radio" name="gender" id="female" value="female" />Женский
<span class="stepTwo-profile-item-radionbtn"></span>
</label>
</div>
</div>
</form>

Maybe this helps you:
const formStepTwo = document.getElementById("formStepTwo");
const sections = [...document.querySelectorAll(".Section")];
formStepTwo.addEventListener("input", () => {
sections.forEach(s=>{
const inps=[...s.querySelectorAll("input,select")].filter(el=>el.type!=="radio"||el.checked);
console.log(inps.map(el=>el.name+":"+el.value))
});
});
<form class="stepTwo-profile" id="formStepTwo">
<p class="stepTwo-profile-title">Демография</p>
<div class="Section">
<label for="age"
>Возраст пациента<input
type="number"
class="stepTwo-profile-item-textAge"
name="age"
min="0"
max="80"
maxlength="2"
id="age"
/></label>
<p class="stepTwo-profile-item-smTitle">Пол</p>
<label for="male">
<input type="radio" name="gender" id="male" value="male" />Мужской
<span class="stepTwo-profile-item-radionbtn"></span
></label>
<label for="female">
<input type="radio" name="gender" id="female" value="female" />Женский
<span class="stepTwo-profile-item-radionbtn"></span>
</label>
</div>
</form>
The script goes through all sections (currently there is only one ;-)) and collects all input values. (Radio buttons are only picked up if they are "checked".)

Related

How capture the input radio value in javascript?

For example I have the next options in html, define the global name and different id to each input radio:
<form id="mokepon-form">
<input type="radio" name="mokepon" id="hipodoge">
<label for="hipodoge">Hipodoge</label>
<input type="radio" name="mokepon" id="capipego">
<label for="capipego">Capipego</label>
<input type="radio" name="mokepon" id="ratigueya">
<label for="ratigueya">Ratigueya</label>
<button type="submit">Seleccionar</button>
</form>
To read the value I read the selector, the global name and the checked attribute and then read the id property, you can use the value property as well.
const chooseMokepon = (e) => {
e.preventDefault();
const $selectedMokepon = document.querySelector('input[name=mokepon]:checked');
const { id: mokeponValue } = $selectedMokepon;
if (!mokeponValue) return;
console.log(mokeponValue);
}
$mokeponForm.addEventListener('submit', e => chooseMokepon(e));
You might use this snippet:
let submitBtn = document.querySelector('button[type="submit"]');
submitBtn.addEventListener('click', function(event){
event.preventDefault();
let selectedOption = document.querySelector('input[type="radio"][name="mokepon"]:checked');
if(selectedOption && selectedOption.value){
console.log('Selected: ' + selectedOption.value);
}
});
<form id="mokepon-form">
<input type="radio" name="mokepon" id="hipodoge" value="hipodoge">
<label for="hipodoge">Hipodoge</label>
<input type="radio" name="mokepon" id="capipego" value="capipego">
<label for="capipego">Capipego</label>
<input type="radio" name="mokepon" id="ratigueya" value="ratigueya">
<label for="ratigueya">Ratigueya</label>
<button type="submit">Seleccionar</button>
</form>

JAVASCRIPT , HTML enabling input field based on radio button choice

I tried to have two input option enable based on the radio button choice, but only one option is enabling not matter which option I choose. Eg- If I choose sheetcake, instead of having input option for sheetcake, I have the input option of roundcake. I am new in javascript and any advice will be much appreciated. Thank You. ( I tried to run the code in snippet and it works fine but I run the same code in browser and only one input box is working no matter what, I tried to run in 3 different browsers and got the same error, I don't know what is the issue and where I made a mistake. Thank You in advance.
const sheetcake = document.getElementById("sheetcake");
const roundcake = document.getElementById("roundcake");
var caketype = document.getElementsById("caketype");
function CakeChoice(choice){
if (choice == sheetcake){
document.getElementById("SheetLength").disabled=false;
document.getElementById("SheetWidth").disabled=false;
document.getElementById("RoundRadius").disabled=true;
}
else {
document.getElementById("SheetLength").disabled=true;
document.getElementById("SheetWidth").disabled=true;
document.getElementById("RoundRadius").disabled=false;
}
}
<div id="caketype">
<label class="caketype required">Cake Type:</label> <br>
<input type="radio" id="sheetcake" name="caketype" value="0" required onclick="CakeChoice(sheetcake)">
<label>Sheet Cake</label><br>
<input type="radio" id="roundcake" name="caketype" value="0" required onclick="CakeChoice(roundcake)">
<label>Round Cake</label>
</div>
<br>
<div id="CakeDimensions" >
<label>Cake size (cm)</label><br>
<input type="number" id="SheetLength" value="0" min="30" max="60" required disabled>
<label class="form-label required">cm Length</label><br>
<input type="number" id="SheetWidth" value="0" min="30" max="45" required disabled>
<label class="form-label required">cm Width</label>
</div>
<br>
<div id="round">
<label>Cake size</label><br>
<input type="number" id="RoundRadius" min="15" max="30" disabled required>
<label class="form-label required">cm Radius</label>
</div>
<br><br>
<div id="cakelayers">
<label class="form-label required">How many layers?</label><br>
<input type="radio" id="OneLayer" name="CakeLayers" value="1layer" required>
<label for="OneLayer">One Layer</label><br>
<input type="radio" id="TwoLayers" name="CakeLayers" value="2layers" required>
<label for="TwoLayers">Two Layers</label><br>
<input type="radio" id="ThreeLayers" name="CakeLayers" value="3layers" required>
<label for="ThreeLayers">Three Layers</label>
</div>
<br><br>
May I suggest a slightly alternative approach which avoids having irrelevant disabled options that some users might be trying to activate.
Instead of disabling the irrelevant options, manipulating the display styles of the two sets of option for cake dimensions (by javascript) allows for only the relevant one to be available for interaction. This lets you make the relevant size option only appear when a type has been chosen (and toggles between them if the user changes their mind).
As you have fairly complex markup for each option, I've added extra divisions containing each group. The ids for the relevant divisions, rectangle and round are used to create references to each grouping in the javascript allowing access to their style.display property, which can be toggled.
const sheetcake = document.getElementById("rectangle");
const roundcake = document.getElementById("round");
sheetcake.style = "display: none";
round.style = "display: none";
function CakeChoice(choice){
if (choice == 'sheetcake'){
sheetcake.style = "display: block";
roundcake.style = "display: none";
} else {
sheetcake.style = "display: none";
roundcake.style = "display: block";
}
}
<div id="caketype">
<label class="caketype required">Cake Type:</label> <br>
<input type="radio" id="sheetcake" name="caketype" value="0" required onclick="CakeChoice('sheetcake')">
<label>Sheet Cake</label><br>
<input type="radio" id="roundcake" name="caketype" value="0" required onclick="CakeChoice('roundcake')">
<label>Round Cake</label>
</div>
<br>
<div id="CakeDimensions" >
<div id="rectangle">
<label>Cake size (cm)</label><br>
<input type="number" id="SheetLength" value="0" min="30" max="60" required>
<label class="form-label required">cm Length</label><br>
<input type="number" id="SheetWidth" value="0" min="30" max="45" required>
<label class="form-label required">cm Width</label>
</div>
<div id="round">
<label>Cake size</label><br>
<input type="number" id="RoundRadius" min="15" max="30" required>
<label class="form-label" "required">cm Radius</label>
</div>
</div>
<br>
<div id="cakelayers">
<label class="form-label required">How many layers?</label><br>
<input type="radio" id="OneLayer" name="CakeLayers" value="1layer" required>
<label for="OneLayer">One Layer</label><br>
<input type="radio" id="TwoLayers" name="CakeLayers" value="2layers" required>
<label for="TwoLayers">Two Layers</label><br>
<input type="radio" id="ThreeLayers" name="CakeLayers" value="3layers" required>
<label for="ThreeLayers">Three Layers</label>
</div>
<br>
I've made some minor refactoring to your HTML then removed a bit of replication to your javascript, reducing the dependencies on Ids. This will make it more flexible should you add more options for dimensions or round. I've also illustrated adding the event listeners via javascript.
//Get all the radio buttons in the element with ID caketype and itterate them
document.querySelectorAll("#caketype input[type=radio]").forEach(function(item) {
//Add an on click event listener
item.addEventListener("click", function() {
//Is Sheet cake chosen from the clicked element
let isSheetCake = this.value === "sheetcake";
//Set out disabled AND required attributes based on the above
//Get the input elements in the fieldset and itterate instead of being bound by id
document.querySelectorAll("#CakeDimensions input").forEach(function(element) {
element.disabled = !isSheetCake;
element.required = isSheetCake;
});
//Do the same for round, but invert the logic
document.querySelectorAll("#round input").forEach(function(element) {
element.disabled = isSheetCake;
element.required = !isSheetCake;
});
//Bonus: lets set a class to indicate that group is disabled
//.classList.toggle() ,adds or removes a class, in this case
// based on a truthy value
document.getElementById("CakeDimensions").classList.toggle("disabled", !isSheetCake);
document.getElementById("round").classList.toggle("disabled", isSheetCake);
});
});
fieldset {
border: none;
padding: 0.5em;
margin: 0;
}
.disabled {
color: #EEE;
}
<!-- Ive Given the radio buttond values, which you are going to want if you send this to a server-->
<!-- Also encapsulated the radio button group with a fieldset which is more semantic-->
<!-- Inline Javascript has been removed -->
<!-- Labels have been associated with their form elements with the "for" attribute-->
<fieldset id="caketype">
<label class="caketype required">Cake Type:</label> <br>
<input type="radio" id="sheetcake" name="caketype" value="sheetcake" required>
<label for="sheetcake">Sheet Cake</label><br>
<input type="radio" id="roundcake" name="caketype" value="roundcake" required>
<label for="roundcake">Round Cake</label>
</fieldset>
<fieldset id="CakeDimensions">
<label>Cake size (cm)</label><br>
<input type="number" id="SheetLength" value="0" min="30" max="60" required disabled>
<label class="form-label required">cm Length</label><br>
<input type="number" id="SheetWidth" value="0" min="30" max="45" required disabled>
<label class="form-label required">cm Width</label>
</fieldset>
<fieldset id="round">
<label>Cake size</label><br>
<input type="number" id="RoundRadius" min="15" max="30" disabled required>
<label class="form-label required">cm Radius</label>
</fieldset>
Between Jon P's and Dave Pritlove's answers it looks like the basics are already covered. Tihs answer will focus on the following:
Event delegation: A programming paradigm in which event bubbling is used to leverage control of an unlimited number of elements by binding an ancestor element to listen for events and delegate which elements react to events and which elements are excluded.
HTMLFormElement interface: Part of the The HTML DOM API, that has terse syntax and unique features:
Referencing a form:
<form id="UI"></form>
const UI = document.forms.UI
/*or*/
const UI = document.forms[0] // the first of one or more forms.
Referencing all form controls✻ within UI with the .elements property:
<input id='i1' name='IO'> <button name='btn'></button> <input id='i2' name='IO'>
const fC = UI.elements;
// Reference by #id
const I1 = fC.i1 // first input by #id
// Refernce by [name]
const B = fC.btn // button by [name]
// HTMLFormsControlCollection of all tags with [name='IO']
const io = fC.IO // an array-like object of both inputs
const ioArray = [...io] // convert into an array
[for] attribute & .labels property association: Besides the [for] attribute & form control #id association, there's another type of association we can establish:
<label for='A'></label><input id='A'><label for='A'>I'm the 2nd label</label>
const IO = UI.elements; // collect all of #UI form controls
const a = IO.A; // reference the input
const Alabels = a.labels; // collect all label associated to input via [for] to #id
Alabels[1].textContent; // get the text of the 2nd label
// result: "I'm the 2nd label"
Here's a list of other properties used in the example below:
.checkValidity()
Event.target
.classList
The example has a step progression:
Pick a type
Pick a size
Choose how many layers
Step 2 is disabled until step 1 is completed.
Step 3 is disabled until the user enters valid data in step 2.
✻form controls: <button>, <fieldset>, <input>, <object>, <output>, <select>, <textarea>
const form = document.forms.cake;
form.onchange = cakeStep1;
form.addEventListener('input', cakeStep2);
function cakeStep1(e) {
const IO = this.elements;
const picked = e.target;
const radios = [...IO.type];
const l = IO.L;
const w = IO.W;
const d = IO.D;
const sSet = IO.sizeSet;
if (picked.name == 'type') {
radios.forEach(r => r.labels[0].classList.remove('active'));
picked.labels[0].classList.add('active')
sSet.disabled = false;
if (picked.id == 'sheet') {
d.disabled = true;
d.labels[0].classList.add('disabled');
l.disabled = false;
l.labels[0].classList.remove('disabled');
w.disabled = false;
w.labels[0].classList.remove('disabled');
} else {
d.disabled = false;
d.labels[0].classList.remove('disabled');
l.disabled = true;
l.labels[0].classList.add('disabled');
w.disabled = true;
w.labels[0].classList.add('disabled');
}
}
}
function cakeStep2(e) {
const IO = this.elements;
const origin = e.target;
const l = IO.L;
const w = IO.W;
const d = IO.D;
const lSet = IO.layerSet;
if (origin.name == 'size') {
if (IO.sheet.checked && l.checkValidity() == true && w.checkValidity() == true) {
lSet.disabled = false;
} else if (IO.round.checked && d.checkValidity() == true) {
lSet.disabled = false;
} else {
lSet.disabled = true;
}
}
}
html {
font: 2ch/1.2 'Segoe UI'
}
header {
margin-bottom: -12px;
padding: 0;
}
label {
display: block;
width: 18ch;
margin-bottom: 4px;
}
[type='radio'] {
display: inline-block;
vertical-align: baseline;
height: 1.5ex;
margin: 0;
}
[type='number'] {
display: :inline-block;
width: 10ch;
float: right;
text-align: center
}
.active {
font-weight: 900;
text-decoration: underline;
}
.disabled {
opacity: 0.4
}
<form id='cake'>
<header>
<h2>Cake Order</h2>
</header>
<fieldset name="typeSet">
<legend>Type</legend>
<label for='sheet'><input id="sheet" name="type" type="radio" value="sheet"> Sheet Cake</label>
<label for='round'><input id="round" name="type" value="round" type="radio"> Round Cake</label>
</fieldset>
<fieldset name="sizeSet" disabled>
<legend>Size (cm)</legend>
<label for='L' class='disabled'>Length: <input id="L" name='size' type="number" min="30" max="60" placeholder='30-60cm' required></label>
<label for='W' class='disabled'>Width: <input id="W" name='size' type="number" min="30" max="45" placeholder='30-45cm' required></label>
<label for='D' class='disabled'>Diameter: <input id="D" name='size' type="number" min="15" max="40" placeholder='15-40cm' required></label>
</fieldset>
<fieldset name="layerSet" disabled>
<legend>Layers</legend>
<select id='layers' name='layers'>
<option selected>Number of Layers</option>
<option value='1'>1 Layer</option>
<option value='2'>2 Layers</option>
<option value='3'>3 Layers</option>
</select>
</fieldset>
</form>

Link Radiobox button to Input

I have 2 radio button, each valued Yes and No respectively and 1 textbox.. If I checked on No button, the input textbox will open. If checked on Yes, textbox will disabled.
This code is working fine but I want to delete content that input to the textbox if the user checked Yes
function ismcstopu() {
var chkNo = document.getElementById("radio2_ismcstop");
var mcnostopreason = document.getElementById("mcnostopreason");
mcnostopreason.disabled = chkNo.checked ? false : true;
if (!mcnostopreason.disabled) {
mcnostopreason.focus();
} else {
mcnostopreason.val('');
}
}
<input type="radio" class="form-check-input" id="radio1_ismcstop" name="ismcstop" onclick="ismcstopu()" value="Yes">Yes
<input type="radio" class="form-check-input" id="radio2_ismcstop" name="ismcstop" onclick="ismcstopu()" value="No">No
<label for="mcnostopreason">If No, Reason:</label>
<input class="inputstyle-100" type="text" id="mcnostopreason" name="mcnostopreason" value="" disabled>
.val is a jQuery construct but you are using DOM
Here is a better version using eventListener
Change the document.getElementById("container") to whatever container you have (your form for example)
Note: It is often better to test true than to test false
I also added labels to the radios so we can click the yes or no too
document.getElementById("container").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.name === "ismcstop") {
const mcnostopreason = document.getElementById("mcnostopreason");
mcnostopreason.disabled = tgt.value === "Yes";
if (mcnostopreason.disabled) {
mcnostopreason.value = '';
} else {
mcnostopreason.focus();
}
}
})
<div id="container">
<label><input type="radio" class="form-check-input" id="radio1_ismcstop" name="ismcstop" value="Yes">Yes</label>
<label><input type="radio" class="form-check-input" id="radio2_ismcstop" name="ismcstop" value="No">No</label>
<label for="mcnostopreason">If No, Reason:
<input class="inputstyle-100" type="text" id="mcnostopreason" name="mcnostopreason" value="" disabled>
</label>
</div>
jQuery version
$("[name=ismcstop]").on("click", function() {
if (this.name === "ismcstop") {
const $mcnostopreason = $("#mcnostopreason");
$mcnostopreason.prop("disabled", this.value === "Yes");
if ($mcnostopreason.is(":disabled")) {
$mcnostopreason.val("");
} else {
$mcnostopreason.focus();
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label><input type="radio" class="form-check-input" id="radio1_ismcstop" name="ismcstop" value="Yes">Yes</label>
<label><input type="radio" class="form-check-input" id="radio2_ismcstop" name="ismcstop" value="No">No</label>
<label for="mcnostopreason">If No, Reason:
<input class="inputstyle-100" type="text" id="mcnostopreason" name="mcnostopreason" value="" disabled>
</label>
mcnostopreason is not a jQuery object. therefore you could do: var mcnostopreason = $("#mcnostopreason");
Or you could just change mcnostopreason.val('') to mcnostopreason.value = '' ( this will mean you don't need to change anything else)

Passing arrays through checkbox input values?

I am trying to get the intersection of two arrays when the user selects them but I don't know how to pass an entire array through an input value.
Here is my script:
var checkedValue = document.querySelector('.leaflet-control-layers-selector:checked').value;
result = _.intersection(checkedValue);
console.log(checkedValue);
document.getElementById("AllMuseums").value = AllMuseums;
document.getElementById("MPaid").value = MPaid;
document.getElementById("MFree").value = MFree;
document.getElementById("MResto").value = MResto;
Here are my inputs:
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="AllMuseums" checked><span>All Museums</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MPaid" value="MPaid"><span id="icons1">Paid Admission</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MFree" value="MFree"><span id="icons2">Free Admission</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MResto" value="MResto"><span id="icons3">Restaurants</span></div>
</label>
And here are my arrays:
var AllMuseums=[Naturhistoriska,Junibacken,ArkDes,Fjarilshuset,Tekniska,Polismuseet,Skansen,Bergrummet,Vikingaliv,Vasa,Nordiska,Nobel,Moderna],
MPaid=[Junibacken,Fjarilshuset,Tekniska,Polismuseet,Skansen,Bergrummet,Vikingaliv,Vasa,Nordiska,Nobel],
MFree=[Naturhistoriska,ArkDes,Moderna],
MResto=[Naturhistoriska,Junibacken,ArkDes,Fjarilshuset,Tekniska,Skansen,Bergrummet,Vikingaliv,Vasa,Nordiska,Nobel,Moderna],
So there is a solution : https://jsfiddle.net/ajxeyqo4
inputs :
first input tag add value
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="AllMuseums" value="AllMuseums" checked><span>All Museums</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MPaid" value="MPaid"><span id="icons1">Paid Admission</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MFree" value="MFree"><span id="icons2">Free Admission</span></div>
</label>
<label>
<div><input type="checkbox" class="leaflet-control-layers-selector" id="MResto" value="MResto"><span id="icons3">Restaurants</span></div>
</label>
<button onclick='test()'>
test
</button>
And your scripts :
function test(){
var AllMuseums=['Naturhistoriska','Junibacken','ArkDes','Fjarilshuset','Tekniska','Polismuseet','Skansen','Bergrummet','Vikingaliv','Vasa','Nordiska','Nobel','Moderna'],
MPaid=['Junibacken','Fjarilshuset','Tekniska','Polismuseet','Skansen','Bergrummet','Vikingaliv','Vasa','Nordiska','Nobel'],
MFree=['Naturhistoriska','ArkDes','Moderna'],
MResto=['Naturhistoriska','Junibacken','ArkDes','Fjarilshuset','Tekniska','Skansen','Bergrummet','Vikingaliv','Vasa','Nordiska','Nobel','Moderna'];
var checkedValue = document.querySelectorAll('.leaflet-control-layers-selector:checked');
var a =[]
_.map(checkedValue, function(value) {
a.push(eval(value.value));
});
var result = _.intersection(...a);
console.log(JSON.stringify(result))
}

How can I produce an alert if three out of nine checkboxes are checked?

I have nine checkboxes linked to nine images and three of them use the name 'correct' using the code shown below.
<div class="nine">
<label for="correct1"><img class="picture1" src="picture1.jpg"/></label>
<input type="checkbox" class="chk" id="correct1" name="correct"/>
</div>
The remaining six are unnamed using the code shown below.
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" class="chk" id="incorrect4"/>
</div>
I currently have the following code to produce an alert if the three checkboxes with the name "correct" are checked but it isn't working.
<script>
var i, correct = document.getElementsByName('correct');
for (i = 0; i <= correct.length; i++) {
if (correct[i].checked) {
alert('correct');
return true;
}
}
alert('incorrect');
return false;
</script>
Can anyone help me with this?
Loop over all of the checkboxes, checking their state. Once this is done, create a variable "correct" and initialize it to true. Then go to each state in the variable and, if you find that its name isn't "correct" and it is checked or its name is "correct" and it isn't correct, set the variable to false. Then check if the variable is true and, if it is, display the alert.
View an example here: https://repl.it/GxsE/9
Using ES6:
const correctInputs = [...document.querySelectorAll('input[name="correct"]')];
const alertIfThree = () => {
const checkedCorrectInputs = correctInputs.filter(input => input.checked);
if (checkedCorrectInputs.length > 2) {
alert('Alert');
}
};
correctInputs.forEach(input => input.addEventListener('click', alertIfThree));
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
document.querySelectorAll('input[name="correct"]') gets all inputs with name "correct".
[...CODE] is spread operator, it converts code from previous point to array.
correctInputs.forEach(input => input.addEventListener('click', alertIfThree)) adds click event listener to each of them. That event listener is function alertIfThree().
alertIfThree() filters out those input elements that are not checked and produces alert if there are more than 2 of them.
EDIT
In response to your comment:
// jshint esnext: true
const inputs = [...document.querySelectorAll('input[name="correct"], input[name="incorrect"]')];
const alertIfCorrect = () => {
const checkedInputs = inputs.filter(input => input.checked),
noIncorrectCheckedInputs = checkedInputs.find(input => input.name === 'incorrect') === undefined;
if (checkedInputs.length > 2 && noIncorrectCheckedInputs) {
alert('Alert');
}
};
inputs.forEach(input => input.addEventListener('click', alertIfCorrect));
<p>Correct:
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
<input type="checkbox" name="correct"/>
</p>
<p>Incorrect:
<input type="checkbox" name="incorrect"/>
<input type="checkbox" name="incorrect"/>
<input type="checkbox" name="incorrect"/>
</p>
const is ES6 constant. "The value of a constant cannot change through re-assignment, and it can't be redeclared".
[...CODE_HERE] is so called spread syntax. Here, it turns what it contains after ellipsis into an array. Other way to do it would be to use Array.from().
() => { and input => CODE_HERE are arrow functions. They are ES6's syntactic sugar for function declaration.
What stands before => are parameters. () stands for 0 parameters. If you wanted function that takes few parameters, those braces would need to have those few parameters inside them. For one parameter, parameter's name can replace braces altogether (like in second code in this bullet point).
What stands after => is either expression or group of statements. Statements are surrounded by curly brackets ({}). If you omit them, you are writing an expression that your function will return. For example input => input.checked is equivalent to function(input) { return input.checked; }.
filter() and find() are methods of array prototype. They respectively filter and search an array using condition defined in a function that is passed to them as a parameter. Read more by following those two links.
If you need something else explained, let me know. Those functions and structures here are pretty... fresh, so you can just not know them yet.
I put this in a JSfiddle and it works for me. I just wrapped your JS in a function and added an onclick event.
<div class="nine">
<label for="correct1"><img class="picture1" src="picture1.jpg"/></label>
<input type="checkbox" class="chk" id="correct1" name="correct"onclick="validate()"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" class="chk" id="incorrect4" onclick="validate()"/>
</div>
<script type=text/javascript">
function validate()
{
var i, correct = document.getElementsByName('correct');
for (i = 0; i <= correct.length; i++) {
if (correct[i].checked) {
alert('correct');
return true;
}
}
alert('incorrect');
return false;
}
</script>
It will require some javascript. You will need o check the checkboxes each time one changes. So to start with you will need to check your checkboxes, assuming they have an assigned class of 'chk'. This can be done with a querySelector.
Each time a checkbox changes, the function 'check_checkboxes()' is called. This function will see for each checkbox with name='correct' if it is checked and then increment 'count'
var checkboxes = document.querySelectorAll(".chk");
var correct = document.querySelectorAll("[name=correct]");
function check_checkbox() {
var count = 0;
[].forEach.call(correct, function(item) {
if (item.checked) {
count++;
}
});
if (count >= 3) {
alert("count of 3 or more");
}
}
[].forEach.call(checkboxes, function(item) {
item.addEventListener("change", function() {
check_checkbox();
}, false);
});
<div class="nine">
<label for="correct1"><img class="picture1" src="http://placehold.it/40x40"/></label>
<input type="checkbox" class="chk" id="correct1" name="correct" />
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="http://placehold.it/40x40"/></label>
<input type="checkbox" class="chk" id="incorrect4" />
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="http://placehold.it/40x40"/></label>
<input type="checkbox" class="chk" id="incorrect4" name="correct" />
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="http://placehold.it/40x40"/></label>
<input type="checkbox" class="chk" id="incorrect4" />
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="http://placehold.it/40x40"/></label>
<input type="checkbox" class="chk" id="incorrect4" name="correct" />
</div>
Check the loop. Use for (i = 0; i < correct.length; i++) { instead for (i = 0; i <= correct.length; i++) {
var i, correct = document.getElementsByName('correct');
var correct_answers = [];
function validate(){
correct_answers = [];
for (i = 0; i < correct.length; i++) {
var element = correct[i].getAttribute("id");
var checked = correct[i].checked;
correct_answers.push({element,checked});
}
}
function show(){
document.getElementById('results').innerHTML ="";
for(var e=0;e<correct_answers.length;e++){
var box = document.createElement('div');
box.innerHTML = correct_answers[e].element+ " " + correct_answers[e].checked+ "<br>";
document.getElementById('results').appendChild(box);
}
}
<div class="nine">
<label for="correct1"><img class="picture1" src="picture1.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="correct1" name="correct"/>
</div>
<div class="nine">
<label for="correct2"><img class="picture1" src="picture1.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="correct2" name="correct"/>
</div>
<div class="nine">
<label for="correct3"><img class="picture1" src="picture1.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="correct3" name="correct"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="incorrect4"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="incorrect5"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="incorrect6"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="incorrect7"/>
</div>
<div class="nine">
<label for="incorrect1"><img class="picture4" src="picture4.jpg"/></label>
<input type="checkbox" onclick="validate()" class="chk" id="incorrect8"/>
</div>
<button onclick="show();">show results</button>
<div id="results"></div>
Use document.querySelectorAll('input[name]=correct') in your code.

Categories

Resources