Below it's my code with a quiz of 4 questions and with a "Submit" button in the last question and I tried to add some code that on Submit it will show an alert with the results of the quiz about how many questions I got correct.
But there are some errors with my code that when I press Submit it doesn't show results of the quiz and it still shows me "Select an option", even that I've selected an option from the question and I've added an if statement to Submit button so it will check if any option is selected or not, but even If I select any option it still shows me that alert ?
let question1 = document.getElementById('pytja1');
let question2 = document.getElementById('pytja2');
let question3 = document.getElementById('pytja3');
let question4 = document.getElementById('pytja4');
let result = document.getElementById('bot-submit');
let nextButtons = document.querySelectorAll('.bot');
for (let i = 0; i < nextButtons.length; i++) {
let nextQuestion = nextButtons[i];
nextQuestion.onclick = function() {
if (validateForm(i + 1)) {
switchToNextQuestion(this);
}
}
}
function switchToNextQuestion(nextQuestion) {
let parentId = nextQuestion.parentNode.id;
if (parentId === 'pytja1') {
question1.style.display = 'none';
question2.style.display = 'block';
} else if (parentId === 'pytja2') {
question2.style.display = 'none';
question3.style.display = 'block';
} else if (parentId === 'pytja3') {
question3.style.display = 'none';
question4.style.display = 'block';
}
}
function validateForm(elementNumber) { // elementnumber gets radio name from multiple questions
let radios = document.getElementsByName("q" + elementNumber);
let formValid = false;
let i = 0;
while (!formValid && i < radios.length) {
if (radios[i].checked) formValid = true;
i++;
}
if (!formValid) alert("Select one option");
return formValid;
}
let questions = [{
question: "I am a ?",
userAnswers: ["Male", "Female", "Other"],
correctAnswers: 0,
},
{
question: "Football has letters ?",
userAnswers: [8, 5, 6],
correctAnswers: 0,
},
{
question: "VW stands for ?",
userAnswers: ["BMW", "Volkswagen", "Audi"],
correctAnswers: 1,
},
{
question: "What year is it ?",
userAnswers: [2017, 2015, 2019],
correctAnswers: 2,
}
];
function submitAnswer(elementNumber) {
let radios = document.getElementsByName("q" + elementNumber);
let formValid = false;
let i = 0;
while (!formValid && i < radios.length) {
if (radios[i].checked) formValid = true;
i++;
}
if (!formValid) alert("Select one option");
return formValid;
for (i = 0; i < questions.length; i++) {
let correctAnswerIndex = questions[i].correctAnswers;
if (correctAnswerIndex === userAnswers[i]) {
score++;
}
}
if (score != total) {
alert("You got " + score + " out " + total)
}
if (score === total) {
alert("Congratulation your score " + score + " out of " + total);
}
let results = document.getElementById('results')
alert("you")
}
document.getElementById("bot-submit").addEventListener("click",
function(e) {
e.preventDefault();
})
form {
width: 100%;
position: relative;
float: left;
padding-top: 50px;
}
.quiz {
margin: 0px auto;
width: 250px;
height: 100px;
position: absolute;
top: 60px;
left: 42%;
}
.quest1,
.quest2,
.quest3,
.quest4 {
background-color: cadetblue;
font-size: 22px;
}
.questions1 {
margin-left: 28px;
background-color: cyan;
width: 220px;
padding: 10px;
font-size: 20px;
}
.questions2 {
background-color: red;
}
.questions3 {
background-color: greenyellow;
}
.questions4 {
background-color: olivedrab;
}
.bot {
margin-top: 10px;
}
#pytja2,
#pytja3,
#pytja4 {
margin-left: 28px;
display: none;
width: 220px;
padding: 10px;
font-size: 20px;
}
<form id="quiz-form">
<div di="results"></div>
<div class="quiz">
<div id="pytja1" class="questions1">
<span class="quest1">I am a ?</span><br/>
<input type="radio" name="q1" value="male" id="correct"> Male<br/>
<input type="radio" name="q1" value="female" id="correct2"> Female<br/>
<input type="radio" name="q1" value="other" id="correct3"> Other<br/>
<input class="bot" type="button" value="Next" "/>
</div>
<div id="pytja2 " class="questions2 ">
<span class="quest2 ">Football has letters ?</span><br/>
<input type="radio " name="q2 " value="8 " class="correct "> 8<br/>
<input type="radio " name="q2 " value="5 "> 5<br/>
<input type="radio " name="q2 " value="6 "> 6<br/>
<input class="bot " type="button " value="Next ""/>
</div>
<div id="pytja3" class="questions3">
<span class="quest3">VW stands for ?</span><br/>
<input type="radio" name="q3" value="BMW" /> BMW <br/>
<input type="radio" name="q3" value="Volkswagen" class="correct" /> Volkswagen<br/>
<input type="radio" name="q3" value="Audi" /> Audi<br/>
<input class="bot" type="button" value="Next" "/>
</div>
<div id="pytja4 " class="questions4 ">
<span class="quest4 ">What year we are ?</span><br/>
<input type="radio " name="q4 " value="2017 " /> 2017<br/>
<input type="radio " name="q4 " value="2015 " /> 2015<br/>
<input type="radio " name="q4 " value="2019 " class="correct " /> 2019<br/>
<input id="bot-submit " type="submit " value="Submit " onclick="submitAnswer(); "/>
</div>
</div>
</form>
As mentioned above, your code has some errors but I have written snippets that will achieve your aim with shorter syntax.
//Javascript code
let questionss = [{
question: "I am a ?",
options: ["Male", "Female", "Other"],
correctAnswers: 'Male',
},
{
question: "Football has letters ?",
options: [8, 5, 6],
correctAnswers: 8,
},
{
question: "VW stands for ?",
options: ["BMW", "Volkswagen", "Audi"],
correctAnswers: 'Volkswagen',
},
{
question: "What year is it ?",
options: [2017, 2015, 2019],
correctAnswers: 2019,
}
];
let questionText = document.getElementById('cd-questions');
let optiontext = document.querySelectorAll('.optiontext');
let options = document.querySelectorAll('.options');
let nextBtn = document.getElementById('next-btn');
let currentQuestion = 0;
var score = 0;
var checkedStatus = false;
setQuestion(currentQuestion); // set default question
nextBtn.addEventListener('click', e => {
e.preventDefault();
if (valForm()) setQuestion(currentQuestion); //validates and next question
});
function setQuestion(currentQuestion) {
questionText.innerText = questionss[currentQuestion].question; //set current question to the DOM
for (let i = 0; i < 3; i++) {
options[i].value = questionss[currentQuestion].options[i]; //set options value for current question
optiontext[i].innerText = questionss[currentQuestion].options[i]; //set options for current question
}
}
function valForm() {
for (let i = 0; i < 3; i++) {
if (options[i].checked) {
let userans = options[i].value;
if (questionss[currentQuestion].correctAnswers == userans) {
score++;
}
options[i].checked = false;
if (currentQuestion < questionss.length - 1) {
currentQuestion++;
if (currentQuestion == questionss.length - 1) {
nextBtn.innerText = 'Submit';
}
} else {
alert('Your total score is ' + score);
currentQuestion = 0;
nextBtn.innerText = 'Start';
}
return true;
}
}
if (checkedStatus == false) {
alert('please choose an answer');
setQuestion(currentQuestion);
}
return false;
}
<form>
<div id="cd-questions"></div>
<input class="options" name="answer" type="radio" />
<span class="optiontext"></span>
<input class="options" name="answer" type="radio" />
<span class="optiontext"></span>
<input class="options" name="answer" type="radio" />
<span class="optiontext"></span>
<div>
<button id="next-btn">Next</button>
</div>
</form>
I'm happy it worked. I want to believe your other question is from the second loop.
for (let i = 0; i < 3; i++) {
if (options[i].checked) { //iterates through the radio buttons for the checked option
let userans = options[i].value; // get the value of the checked
if (questionss[currentQuestion].correctAnswers == userans) {
score++; //increment score by 1 if the chosen answer is the correct answer
}
options[i].checked = false; //reset button to avoid next question being checked by
default.
if (currentQuestion < questionss.length - 1) {
currentQuestion++; // increment current question index
if (currentQuestion == questionss.length - 1) {
nextBtn.innerText = 'Submit'; // Changed submit button text if it's the last question.
}
} else {
alert('Your total score is ' + score);
currentQuestion = 0;
nextBtn.innerText = 'Start';
}
return true; // return true which was tested when the function was involked before nexting the question.
}
}
I hope that helps.
Related
How can I divide "tasks" from input into categories? The filtered gallery is fine, I found a lot of tutorials on W3school, but I did not find anywhere how I can add them from a direct input, probably using option-id.
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function addClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
function removeClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
<form id="FORM">
<label for="jmeno">Assigned task</label>
<input type="text" id="homework" required />
<label for="category">Category</label>
<select name="selectCategory" id="category">
<option value="">---</option>
<option value="School" id="school">School</option>
<option value="Work" id="work">Work</option>
</select>
<input type="submit" value="Add" />
</form>
<h2>TASK TO</h2>
<div id="myBtnContainer">
<button class="btn active" onclick="filterSelection('all')"> All</button>
<button class="btn" onclick="filterSelection('school')"> To school</button>
<button class="btn" onclick="filterSelection('work')"> To work</button>
</div>
Something like this should work.
let taskForm = document.tasks;
taskForm.onsubmit = e => {
e.preventDefault();
let taskData = new FormData(taskForm);
let category = taskData.get("category");
let result = document.querySelector(".tasks");
let task = document.createElement('div');
let filterTask = document.querySelector('input[name="filter"]:checked');
task.appendChild(document.createTextNode(taskData.get("task")));
task.dataset.group = category;
task.classList.add("task");
task.style.display = ["all", category].includes(filterTask.value) ? "block" : "none";
result.appendChild(task);
}
let showTasks = document.getElementsByName("filter");
showTasks.forEach(el => {
el.addEventListener("click", e => {
tasks = document.querySelectorAll(".task");
tasks.forEach(task => {
task.style.display = ["all", task.dataset.group].includes(e.target.value) ? "block" : "none";
});
});
});
input[type="radio"] {
opacity: 0;
position: fixed;
width: 0;
}
input[type="radio"] ~ label {
display: inline-block;
background-color: #ddd;
padding: 5px 20px;
font-family: sans-serif, Arial;
font-size: 16px;
border: 2px solid #444;
border-radius: 4px;
}
input[type="radio"] ~ label:hover {
background-color: #dfd;
}
input[type="radio"]:checked + label {
background-color: #bfb;
border-color: #4c4;
}
<div>
<form name="tasks">
<label for="name">Assigned Task</label>
<input name="task" type="text" required />
<label for="category">Category</label>
<select name="category">
<option value="school" selected>School</option>
<option value="work">Work</option>
</select>
<input type="submit" value="Add" />
</form>
<h3>Task To</h3>
<input name="filter" id="all" type="radio" value="all" checked />
<label for="all">All</label>
<input name="filter" id="school" type="radio" value="school" />
<label for="school">School</label>
<input name="filter" id="work" type="radio" value="work" />
<label for="work">Work</label>
<h2>Tasks</h2>
<div class="tasks"></div>
</div>
You can style the added tasks using their .task selector in CSS.
Note that if you want to animate while showing and hiding your tasks, instead of changing the display property consider playing with opacity and visibility properties.
I am working on a little dice game, where the user can lock specific die. But I can't get it to work with if else statements. How do I "roll" the dice only where the checkboxes are unchecked?
const btnRoll = document.querySelector('.btn_roll');
btnRoll.addEventListener('click', () => {
roll();
});
function roll() {
const dice1 = document.querySelector('.dice1');
const dice2 = document.querySelector('.dice2');
const dice3 = document.querySelector('.dice3');
if (!document.getElementById('dice-1').checked) {
randomOne = Math.floor(Math.random() * 6) + 1;
dice1.src = `img/dice-${randomOne}.png`;
console.log(!document.getElementById('dice-1').checked);
} else if (!document.getElementById('dice-2').checked) {
randomTwo = Math.floor(Math.random() * 6) + 1;
dice2.src = `img/dice-${randomTwo}.png`;
} else if (!document.getElementById('dice-3').checked) {
randomThree = Math.floor(Math.random() * 6) + 1;
dice3.src = `img/dice-${randomThree}.png`;
} else {
console.log('no checkboxes are selected');
}
}
<form id="dices">
<input type="checkbox" id="dice-1" name="dice-1" value="dice-1" />
<img src="img/dice-5.png" alt="Dice" class="dice1" id="dice-1" />
<input type="checkbox" id="dice-2" name="dice-2" value="dice-2" />
<img src="img/dice-5.png" alt="Dice" class="dice2" id="dice-2" />
<input type="checkbox" id="dice-3" name="dice-3" value="dice-3" />
<img src="img/dice-5.png" alt="Dice" class="dice3" id="dice-3" />
<input type="checkbox" id="dice-4" name="dice-4" value="dice-4" /> 5.png" alt="Dice" class="dice6" id="dice-6" />
</form>
<br />
<button class="btn_roll">roll</button>
You are using "else-if" statements which effectively short-circuits your logic when one of them runs. Replace "else-if" with "if":s only.
(I replaced the last "else"-statement with an "if"-statement which is the negation of the other if-statements, since we can't do an else here.)
function roll() {
const dice1 = document.querySelector('.dice1');
const dice2 = document.querySelector('.dice2');
const dice3 = document.querySelector('.dice3');
const firstDiceChecked = document.getElementById('dice-1').checked
const secondDiceChecked = document.getElementById('dice-2').checked
const thirdDiceChecked = document.getElementById('dice-3').checked
if (!firstDiceChecked) {
randomOne = Math.floor(Math.random() * 6) + 1;
dice1.src = `img/dice-${randomOne}.png`;
console.log(!document.getElementById('dice-1').checked);
}
if (!secondDiceChecked) {
randomTwo = Math.floor(Math.random() * 6) + 1;
dice2.src = `img/dice-${randomTwo}.png`;
}
if (!thirdDiceChecked) {
randomThree = Math.floor(Math.random() * 6) + 1;
dice3.src = `img/dice-${randomThree}.png`;
}
if (!firstDiceChecked && !secondDiceChecked && !thirdDiceChecked) {
console.log('no checkboxes are selected');
}
}
I would use a div with a background image instead of swapping the src of an actual image object.
You can simplify this with a loop and targeting the parent of the checkbox to get the die image.
document.querySelector('.btn-roll').addEventListener('click', rollDice);
function rollDice(e) {
let checked = document.querySelectorAll('#dice .die-wrapper input:checked');
Array.from(checked).forEach(cb => {
let die = cb.parentElement.querySelector('.die');
let roll = getRandomIntInclusive(1, 6);
die.className = 'die die-' + roll;
die.setAttribute('data-roll', roll);
});
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
if (arguments.length === 1) { max = min; min = 0; }
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
.die-wrapper {
display: inline-block;
}
.die {
display: inline-block;
width: 32px;
height: 32px;
background-position: center;
background-repeat: no-repeat;
}
.die-1 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=1'); }
.die-2 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=2'); }
.die-3 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=3'); }
.die-4 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=4'); }
.die-5 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=5'); }
.die-6 { background-image: url('https://place-hold.it/32x32/f00/000.png&bold&text=6'); }
<form id="dice">
<div class="die-wrapper">
<input type="checkbox" name="die-1" value="dice-1" />
<div class="die die-1"></div>
</div>
<div class="die-wrapper">
<input type="checkbox" name="die-2" value="dice-2" />
<div class="die die-1"></div>
</div>
<div class="die-wrapper">
<input type="checkbox" name="die-3" value="dice-3" />
<div class="die die-1"></div>
</div>
</form>
<br />
<button class="btn-roll">Roll</button>
Using Unicode glyphs for display of die faces...
document.querySelector('.btn-roll').addEventListener('click', rollDice);
function rollDice(e) {
let checked = document.querySelectorAll('#dice .die-wrapper input:checked');
Array.from(checked).forEach(cb => {
let die = cb.parentElement.querySelector('.die');
let roll = getRandomIntInclusive(1, 6);
die.className = 'die die-' + roll;
die.setAttribute('data-roll', roll);
});
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
if (arguments.length === 1) {
max = min;
min = 0;
}
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
.die-wrapper {
display: inline-block;
}
.die {
display: inline-block;
height: 2em;
}
.die::after {
font-size: 3em;
line-height: 0.75em;
}
.die-1::after { content: '\2680'; }
.die-2::after { content: '\2681'; }
.die-3::after { content: '\2682'; }
.die-4::after { content: '\2683'; }
.die-5::after { content: '\2684'; }
.die-6::after { content: '\2685'; }
<form id="dice">
<div class="die-wrapper">
<input type="checkbox" name="die-1" value="dice-1" />
<div class="die die-1"></div>
</div>
<div class="die-wrapper">
<input type="checkbox" name="die-2" value="dice-2" />
<div class="die die-1"></div>
</div>
<div class="die-wrapper">
<input type="checkbox" name="die-3" value="dice-3" />
<div class="die die-1"></div>
</div>
</form>
<br />
<button class="btn-roll">Roll</button>
const checkboxes = [
document.getElementById("dice-1")
document.getElementById("dice-2")
document.getElementById("dice-3")
document.getElementById("dice-4")
document.getElementById("dice-5")
];
let allChecked = true;
for (const checkbox of checkboxes) {
if (!checkbox.checked) allChecked = false;
}
if (allChecked) {
roll();
}
This question already has answers here:
How to get the selected radio button value using js
(19 answers)
Closed 5 years ago.
I have a set of dynamically generated radio buttons against each data of the list but I am not able to get the checked radio button value. Please help!!
function displayList()
{
var arr=["Apple", "Banana", "Grapes"];
var list
var output="";
var output2="";
var output3="";
var output4="";
for(var i=0; i<arr.length; i++)
{
list=arr[i];
output+= '<input type="checkbox" value='+list+' name="box2">' + ' ' + list+' '+'<br><br>';
output2+= 'yes:<input type="radio" value="yes" name="box2'+i+'">'+'no:<input type="radio" value="yes" name="box2'+i+'">'+'<br><br>';
output3+= '<button type="button" id="myBtn" onclick="displayCardList()" >Add Prompt</button>'+'<br><br>';
//onclick="myfunction()"
output4+= '<button type="button" id="mySaveBtn" onclick="addEntity()" >Save </button>'+'<br><br>';
document.getElementById("List").innerHTML=output;
document.getElementById("radioBtn").innerHTML=output2;
document.getElementById("myBtn").innerHTML=output3;
}
}
<html>
<body onload="displayList()">
<div class="row">
<div class="col-sm-4"><div style="font-size:16px" id="List"> </div></div>
<div class="col-sm-4"><div style="font-size:16px" id="radioBtn"></div></div>
<div class="col-sm-4"><div id="myBtn"></div></div>
</div>
</body>
</html>
But first, let me separate content
I recommend using template tag to separate JavaScript from HTML, as you should always do.
You can then insert as many items using that template, as you wish. As you can see below it's quite tedious using pure JavaScript. I'd recommend using Handlebars.
var getRadioValue = function(name) {
var radios = document.getElementsByName(name);
for (var i = 0, length = radios.length; i < length; ++i) {
if (radios[i].checked) {
return radios[i].value
}
}
return null;
};
var Actions = {
addPrompt: function(i) {
var value = getRadioValue('fruit-fresh-' + i);
if (value == "no") {
prompt('Why is ' + fruits[i] + ' not fresh? Explain:');
}
else if (value == "yes") {
alert('We are glad that ' + fruits[i] + ' is fresh! Good job!');
}
else {
alert('Please, check the corresponding value for ' + fruits[i] + ' freshness!');
}
},
save: function(i) {
alert('Saving: ' + fruits[i]);
},
generateMarkupForFruit: function(i, fruitName) {
var template = document.querySelector('#fruits-template');
var row = document.importNode(template.content, true);
var fruitId = 'fruit-' + i,
fruitField = row.querySelector('.fruit'),
fruitLabel = row.querySelector('.fruit-label');
fruitField.value = fruitName;
fruitField.setAttribute('id', fruitId);
fruitLabel.textContent = fruitName;
fruitLabel.setAttribute('for', fruitId);
var yesId = 'fruit-yes-' + i,
noId = 'fruit-no-' + i,
groupId = 'fruit-fresh-' + i,
yesField = row.querySelector('.yes'),
yesLabel = row.querySelector('.yes-label'),
noField = row.querySelector('.no'),
noLabel = row.querySelector('.no-label');
yesField.setAttribute('name', groupId);
yesField.setAttribute('id', yesId);
yesLabel.setAttribute('for', yesId);
noField.setAttribute('name', groupId);
noField.setAttribute('id', noId);
noLabel.setAttribute('for', noId);
var addPromptBtn = row.querySelector('.add-prompt-btn'),
saveBtn = row.querySelector('.save-btn');
addPromptBtn.addEventListener('click', Actions.addPrompt.bind(null, i));
saveBtn.addEventListener('click', Actions.save.bind(null, i));
return row;
}
};
var fruits = ["Apple", "Banana", "Grapes"];
var table = document.querySelector('#fruits');
for (var i = 0; i < fruits.length; ++i)
{
var row = Actions.generateMarkupForFruit(i, fruits[i]);
table.appendChild(row);
}
#fruits {
width: 100%;
border-collapse: collapse;
}
#fruits td,
#fruits th {
border: solid 1px;
padding: 0.25em;
}
#fruits th {
color: #fff;
background: #000;
}
#fruits .actions {
text-align: center;
}
#fruits .actions .save-btn {
font-weight: bold;
}
<table id="fruits">
<tr>
<th>Fruit</th>
<th>Is fruit fresh?</th>
<th>Actions</th>
</tr>
</table>
<template id="fruits-template">
<tr>
<td>
<input type="checkbox" class="fruit">
<label class="fruit-label"></label>
</td>
<td>
<input type="radio" class="yes" value="yes">
<label class="yes-label">Yes</label>
<input type="radio" class="no" value="no">
<label class="no-label">No</label>
</td>
<td class="actions">
<button type="button" class="add-prompt-btn">Add Prompt</button>
<button type="button" class="save-btn">Save</button>
</td>
</tr>
</template>
I made a program when you enter form field number, you can insert a plus input box if you fell, whem remove. A problem is that we have a for loop, where you can gather elements which the "validate" class is (these form fields). onblur event to add functions, but I can not solve that added new elements to the program take into account. I tried and I did arrays that included new elements into an array, but since the for loop is therefore outside the event, if you add it, you can do nothing happens.
If anyone can help that in that case, it wont solve this, I really appreciate it!
(A code is supplied, only a test, specifically focuses on this problem.)
function onlyNumber(e) {
var x = e.keyCode;
if ((x >= 49 && x <= 57) || x === 9 || x === 8 || x === 46 || (x >= 97 && x <= 105)) {
return true;
} else {
e.preventDefault();
}
}
function initOnlyNumber() {
var el = document.querySelectorAll('.onlynumber');
for (var i = 0; i < el.length; i++) {
el[i].addEventListener('keydown', onlyNumber, false);
}
}
var childNumber = document.querySelector('.childNumber');
childNumber.onkeyup = function() {
var childNumberValue = childNumber.value;
var childrens = document.querySelector('.childrens');
var inputLengths = document.querySelectorAll('.kids');
var inputLength = '';
var element = '';
for (var i = 0; i < inputLengths.length; i++) {
var inputLength = inputLengths.length;
var element = inputLengths[i];
}
var arrayElement = [];
for (var i = inputLength; i < childNumberValue; i++) {
var newElement = document.createElement('input');
newElement.classList.add('kids');
newElement.classList.add('validate');
newElement.setAttribute('name', 'child-' + (i + 1));
newElement.setAttribute('data-name', 'child-' + (i + 1));
childrens.appendChild(newElement);
}
if (inputLength == 1) {
if (childNumberValue == '') {
childrens.removeChild(childrens.lastChild);
}
}
if (childNumberValue > 0) {
for (var i = inputLength; i > childNumberValue; i--) {
childrens.removeChild(childrens.lastChild);
}
}
}
var validates = document.querySelectorAll('.validate');
for (var i = 0; i < validates.length; i++) {
var validate = validates[i];
validate.onblur = function(event) {
obj = this;
console.log(obj);
}
}
window.onload = function() {
initOnlyNumber();
}
body {
margin: 20px;
padding: 0;
}
*:link,
*:hover,
*:visited,
*:focus {
outline: none;
}
input:-webkit-autofill {
color: #fff;
-webkit-box-shadow: 0 0 0px 1000px #4caf50 inset;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input {
background-color: #4caf50;
border: 1px solid #555;
color: #fff;
padding: 10px;
width: 50px;
}
.childrens {
display: inline-block;
}
.childrens input {
display: inline-block;
margin-left: 15px;
}
.childNumber {
background-color: #555;
}
<form action="">
<input class="validate onlynumber" name="name" type="text">
<br />
<br />
<input class="validate onlynumber" name="email" type="text">
<br />
<br />
<input class="validate onlynumber" name="tax" type="text">
<br />
<br />
<input class="validate onlynumber" name="phone" type="text">
<br />
<br />
<input class="childNumber onlynumber" name="childNumber" type="text" maxlength="1">
<div class="childrens"></div>
</form>
I need a form with multiple steps where the first step restricts options in the successive steps.
So below is an example of use:
User selects from 4 global options
If user selects option 1
Then the user can only select 8 options (no more no less) from a multiple choice box.
If user select option 2
Then the user can only select 10 options (no more no less) from a multiple choice box.
Same is the case with options 3 and 4
After all these selections, this form has to show a final price based on the options user selected in the FIRST STEP. No matter what choices were selected in successive steps.
When this form shows final price, user has to click SUBMIT button and send this result with all these options through an email.
Can someone help me in figuring out the javascript required to do this? Most important thing right now for me is to figure out 'restrictions codes' in multiple items choice boxes.
This is the form I was thinking about:
<form action="" id="menuform" onsubmit="return false;">
<fieldset>
<legend>Select one of this four menus</legend>
<label >Menu Option</label>
<input type="radio" name="selectedmenu" value="Menu1"
onclick="calculateTotal()" />
Menu 1 - serves 8 courses ($20)
<input type="radio" name="selectedmenu" value="Menu2"
onclick="calculateTotal()" />
Menu 2 - serves 12 courses ($25)
<input type="radio" name="selectedmenu" value="Menu3"
onclick="calculateTotal()" />
Menu 3 - serves 16 courses ($35)
<input type="radio" name="selectedmenu" value="Menu4"
onclick="calculateTotal()" />
Menu 4 - serves 30 courses ($75)
<label >Filling</label>
<select id="filling" name='filling'
onchange="calculateTotal()">
<option value="dish1">Dish 1 ($1)</option>
<option value="dish2">Dish 2 ($5)</option>
<option value="dish3">Dish 3 ($5)</option>
(more...)
</select>
<br/>
<div id="totalPrice"></div>
</fieldset>
</form>
Then, for Javascript code I was trying with this to store and return some values but my problem is how to force to select an exact number of options in the SECOND STEP:
var menu_prices = new Array();
menu_prices["Menu1"]=20;
menu_prices["Menu2"]=25;
menu_prices["Menu3"]=35;
menu_prices["Menu4"]=75;
function getMenuPrice()
{
var menuPrice=0;
var theForm = document.forms["menuform"];
var selectedMenu = theForm.elements["selectedmenu"];
for(var i = 0; i < selectedMenu.length; i++)
{
if(selectedMenu[i].checked)
{
menuPrice = menu_prices[selectedMenu[i].value];
break;
}
}
return menuPrice;
}
function getTotal()
{
var menuPrice = getMenuPrice() + getOtherOptionsPrices();
document.getElementById('totalPrice').innerHTML =
"Total Price For Menu $"+menuPrice;
}
Structure your HTML markup carefully, which helps you to target elements via JavaScript easily. Especially, using data-attributes on radio buttons for quantity and price which could be then easily retrieved in respective event handlers. Something like this:
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ($20)</span>
</label>
...
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ($1)</option>
...
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
Identify and select all elements that you'll need:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
Add event listeners to your radio buttons, select, and the submit button:
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
Code the actual event handlers:
// When radio buttons are selected, update parameters for limit
function handleLimit(e) { updateParameters(e.target); }
// When options are selected in the dropdown,
// check against the limit and reset the selection if it exceeds
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
// When submit button is clicked,
// check the count of selection against the limit, and
// show appropriate error message
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
And then code all the helper functions used in the handlers above:
function updateParameters(elem) {
// update the limit based on quantity data attribute on radio
fillingsAllowed = elem.getAttribute('data-qty');
// show the amount based on price data-attribute
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
// show the hint on legend of fieldset for selecting options
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
// iterate options and get count of selected ones
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
// iterate options and get selected values in an array
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
// remove selection from all options, and
// re-select based on the array used in the previous function
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
Everything put together, the demo looks like this:
Fiddle: https://jsfiddle.net/abhitalks/L813qudw/
Snippet:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementById('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
fillings.addEventListener('change', handleFillings);
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var options = fillings.options, count = 0;
for (var i=0; i < options.length; i++) {
if (options[i].selected) count++;
}
return count;
}
function getSelectedValues() {
var options = fillings.options, values = [0];
for (var i=0; i < options.length; i++) {
if (options[i].selected) values.push(options[i].value);
}
return values;
}
function resetSelect() {
var options = fillings.options;
for (var i=0; i < options.length; i++) {
options[i].selected = false;
if (currentSelection.indexOf(options[i].value) != -1) {
options[i].selected = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset > label { display: block; margin: 4px 0px; }
fieldset input, fieldset span { vertical-align: middle; }
fieldset > select { width: 100%; font-family: monospace; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ($20)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ($25)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ($35)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ($75)</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<select id="fillings" name="fillings" size="6" multiple>
<option value="1">Dish 1 ($1)</option>
<option value="2">Dish 2 ($5)</option>
<option value="3">Dish 3 ($5)</option>
<option value="4">Dish 4 ($1)</option>
<option value="5">Dish 5 ($5)</option>
<option value="6">Dish 6 ($5)</option>
</select>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>
...how can I change <option> and use <input type="checkbox">
instead for the SECOND STEP?
In order to use checkboxes instead of select, no major changes are required.
Changed mark-up:
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ($5)</span>
</label>
...
JavaScript changes:
Adding the event-handlers for checkboxes instead of select, would require just iterating over those:
(just like the radios already done)
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
In all the helper functions, remove the variable declaration for options:
(as it is now no longer required)
var options = fillings.options
And, In all the helper functions,
change: options.length and options[i].selected
to, fillings.length and fillings[i].checked respectively.
That's it.
Fiddle 2: https://jsfiddle.net/abhitalks/hp88wdfc/
Snippet 2:
var menuform = document.getElementById('menuform'),
radios = document.getElementsByName('selectedmenu'),
fillings = document.getElementsByName('fillings'),
fillingsPrompt = document.getElementById('fillingsPrompt'),
totalPrice = document.getElementById('totalPrice'),
result = document.getElementById('result'),
fillingsAllowed = 0, currentSelection = [], currency = '$'
;
// listen to events
menuform.addEventListener('submit', handleSubmit);
for (var i = fillings.length; i--; ) {
fillings[i].addEventListener('change', handleFillings);
}
for (var i = radios.length; i--; ) {
radios[i].addEventListener('change', handleLimit);
}
// event handlers
function handleLimit(e) { updateParameters(e.target); }
function handleFillings(e) {
var count = getSelectedCount();
if (count > fillingsAllowed) { resetSelect(); }
else { currentSelection = getSelectedValues(); }
}
function handleSubmit(e) {
var count = getSelectedCount();
e.preventDefault();
if (count != fillingsAllowed) {
result.textContent = 'Must select exactly ' + fillingsAllowed + ' fillings!';
} else {
result.textContent = 'Ok. ';
}
}
// fire initial update based on the first radio
updateParameters(radios[0]);
// helper functions
function updateParameters(elem) {
fillingsAllowed = elem.getAttribute('data-qty');
totalPrice.textContent = 'Amount: ' + currency + elem.getAttribute('data-price');
fillingsPrompt.textContent = 'Select ' + fillingsAllowed + ' fillings';
}
function getSelectedCount() {
var count = 0;
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) count++;
}
return count;
}
function getSelectedValues() {
var values = [0];
for (var i=0; i < fillings.length; i++) {
if (fillings[i].checked) values.push(fillings[i].value);
}
return values;
}
function resetSelect() {
for (var i=0; i < fillings.length; i++) {
fillings[i].checked = false;
if (currentSelection.indexOf(fillings[i].value) != -1) {
fillings[i].checked = true;
}
}
}
fieldset {
margin: 1vw; font-family: monospace;
display: inline-block; width: 40vw; vertical-align: top;
}
legend { color: #d33; padding: 0px 4px; }
legend::before { content: '[ '; }
legend::after { content: ' ]'; }
fieldset:first-of-type > label { display: block; margin: 4px 0px; }
fieldset:nth-of-type(2) > label {
display: inline-block; width: 45%;
}
fieldset input, fieldset span { vertical-align: middle; }
input[type=submit] { margin-top: 12px; }
#totalPrice, #result {
height: 24px; line-height: 24px;
background-color: #dde; padding: 4px;
font-family: monospace;
}
#result { color: #d33; font-family: monospace; }
<form action="" method="post" id="menuform" name="menuform">
<fieldset>
<legend>Select menu option</legend>
<label>
<input type="radio" name="selectedmenu" checked
value="menu01" data-qty='3' data-price='20' />
<span>1 - serves 3 courses ($20)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu02" data-qty='4' data-price='25' />
<span>2 - serves 4 courses ($25)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu03" data-qty='5' data-price='35' />
<span>3 - serves 5 courses ($35)</span>
</label>
<label>
<input type="radio" name="selectedmenu"
value="menu04" data-qty='6' data-price='75' />
<span>4 - serves 6 courses ($75)</span>
</label>
</fieldset>
<fieldset>
<legend id='fillingsPrompt'>Select fillings</legend>
<label>
<input type='checkbox' name='fillings' value="1" />
<span>Dish 1 ($5)</span>
</label>
<label>
<input type='checkbox' name='fillings' value="2" />
<span>Dish 2 ($5)</span>
</label>
<label>
<input type='checkbox' name='fillings' value="3" />
<span>Dish 3 ($5)</span>
</label>
<label>
<input type='checkbox' name='fillings' value="4" />
<span>Dish 4 ($5)</span>
</label>
<label>
<input type='checkbox' name='fillings' value="5" />
<span>Dish 5 ($5)</span>
</label>
<label>
<input type='checkbox' name='fillings' value="6" />
<span>Dish 6 ($5)</span>
</label>
</fieldset>
<fieldset>
<legend>Checkout</legend>
<div id="totalPrice"></div>
<input type="submit" value="Submit" />
</fieldset>
<fieldset>
<legend>Messages</legend>
<p id="result"></p>
</fieldset>
</form>
<hr>