Javascript how to show certain number results from all in per session? - javascript

I've created a simple js quiz app. But I want to show a certain number questions per quiz session from all questions. For example, I will add 20 questions in my question array. But in all session, it will show any 10 results only randonmy from all questions. How can I do it ?
Here's my code snippet:
var total_seconds = 1220 * 1;
var c_minutes = parseInt(total_seconds / 60);
var c_seconds = parseInt(total_seconds % 60);
var timer;
function CheckTime() {
document.getElementById("quiz-time-left1").innerHTML = '<i class="fa fa-clock-o"></i> ' +c_minutes +'m'+':'+ c_seconds+'s' ;
if (total_seconds <= 0) {
score();
} else {
total_seconds = total_seconds - 1;
c_minutes = parseInt(total_seconds / 60);
c_seconds = parseInt(total_seconds % 60);
timer = setTimeout(CheckTime, 1000);
}
}
timer = setTimeout(CheckTime, 1000);
const quizData = [{
question: "Which language runs in a web browser?",
a: "Java",
b: "C",
c: "Python",
d: "JavaScript",
correct: "d",
}, {
question: "What does CSS stand for?",
a: "Central Style Sheets",
b: "Cascading Style Sheets",
c: "Cascading Simple Sheets",
d: "Cars SUVs Sailboats",
correct: "b",
}, {
question: "What does HTML stand for?",
a: "Hypertext Markup Language",
b: "Hypertext Markdown Language",
c: "Hyperloop Machine Language",
d: "Helicopters Terminals Motorboats Lamborginis",
correct: "a",
}, {
question: "What year was JavaScript launched?",
a: "1996",
b: "1995",
c: "1994",
d: "none of the above",
correct: "b",
}, ];
const quiz = document.getElementById("quiz");
const answerElements = document.querySelectorAll(".answer");
const questionElement = document.getElementById("question");
const a_text = document.getElementById("a_text");
const b_text = document.getElementById("b_text");
const c_text = document.getElementById("c_text");
const d_text = document.getElementById("d_text");
const submitButton = document.getElementById("submit");
let currentQuiz = 0;
let score = 0;
const deselectAnswers = () => {
answerElements.forEach((answer) => (answer.checked = false));
};
const getSelected = () => {
let answer;
answerElements.forEach((answerElement) => {
if (answerElement.checked) answer = answerElement.id;
});
return answer;
};
const loadQuiz = () => {
deselectAnswers();
const currentQuizData = quizData[currentQuiz];
questionElement.innerText = currentQuizData.question;
a_text.innerText = currentQuizData.a;
b_text.innerText = currentQuizData.b;
c_text.innerText = currentQuizData.c;
d_text.innerText = currentQuizData.d;
};
loadQuiz();
submitButton.addEventListener("click", () => {
const answer = getSelected();
if (answer) {
if (answer === quizData[currentQuiz].correct) score++;
currentQuiz++;
let asd = quizData.length - score;
let ssrate = (1220 - Math.floor(total_seconds));
let ggg = "";
if (ssrate < 12)
ggg = "good morning";
else if (ssrate < 16)
ggg = "ghfgdfgh ning";
else if (ssrate < 24)
ggg = "asaasasasa ng";
let avg = Math.round( score * 100 / quizData.length);
document.getElementById("myProgress").value = avg ;
if (currentQuiz < quizData.length) loadQuiz();
else {
// stop timer
clearInterval(timer);
quiz.innerHTML = "<h2>Total Question : " + quizData.length + "<br>" + "Correct Ans : " + score + " <br> Wrong Ans : " + asd + " <br> Average : " + avg + " % <br> Time Usage : " + ssrate + " Seconds <br> Average : " + ggg + " % <br><br> <br><br> <button onclick='location.reload()'>Play Again</button></h2>"
}
}
});
* {
box-sizing: border-box;
}
body {
background-color: #b8c6db;
background-image: linear-gradient(315deg, #b8c6db 0%, #f5f7fa 100%);
font-family: "Poppins", sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.quiz-container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 10px 2px rgba(100, 100, 100, 0.1);
width: 600px;
max-width: 95vw;
overflow: hidden;
}
.quiz-header {
padding: 4rem;
}
h2 {
padding: 1rem;
text-align: center;
margin: 0;
}
ul {
list-style-type: none;
padding: 0;
}
ul li {
font-size: 1.2rem;
margin: 1rem 0;
}
ul li label {
cursor: pointer;
}
button {
background-color: #8e44ad;
color: #fff;
border: none;
display: block;
width: 100%;
cursor: pointer;
font-size: 1.1rem;
font-family: inherit;
padding: 1.3rem;
}
button:hover {
background-color: #732d91;
}
button:focus {
outline: none;
background-color: #5e3370;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"/>
<div id="quiz-time-left1" ></div>
<div class="quiz-container" id="quiz">
<div class="quiz-header">
<h2 id="question">Question is loading...</h2>
<ul>
<li> <input type="radio" name="answer" id="a" class="answer" /> <label for="a" id="a_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="b" class="answer" /> <label for="b" id="b_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="c" class="answer" /> <label for="c" id="c_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="d" class="answer" /> <label for="d" id="d_text">Answer...</label> </li>
</ul>
</div> <button id="submit">Submit</button>
</div>
<progress id='myProgress' value='' max='100'>
Look at this one: This is my quiz code where is almost 4 questions. But when I run or play this code, it show all questions. But I want to show only any 2 questions randomly among all. How can I do it ?

Figure out how to randomly sort an array: How to randomize (shuffle) a JavaScript array? I went with this answer for a fast sorting algorithm.
Your goal here is the shuffle the source array, and pull the initial 10 off of it. This can be done by sorting a copy of the original array and slicing it to 10 items.
Now, add:
const randomizedQuestions = shuffle(quizData).slice(0, 10);
Change all references to quizData with randomizedQuestions.
Note: I also changed currentQuiz to currentQuestion (index), because the variable was confusing.
Full example
const
rand = n => Math.floor(Math.random() * n),
swap = (t, i, j) => { let q = t[i]; t[i] = t[j]; t[j] = q; return t; },
shuffle = (arr = []) => {
let copy = arr.slice(), last = copy.length, n;
while (last > 0) { n = rand(last); swap(copy, n, --last); }
return copy;
};
var total_seconds = 1220 * 1;
var c_minutes = parseInt(total_seconds / 60);
var c_seconds = parseInt(total_seconds % 60);
var timer;
function CheckTime() {
document.getElementById("quiz-time-left1").innerHTML = '<i class="fa fa-clock-o"></i> ' + c_minutes + 'm' + ':' + c_seconds + 's';
if (total_seconds <= 0) {
score();
} else {
total_seconds = total_seconds - 1;
c_minutes = parseInt(total_seconds / 60);
c_seconds = parseInt(total_seconds % 60);
timer = setTimeout(CheckTime, 1000);
}
}
timer = setTimeout(CheckTime, 1000);
const quizData = [{
question: "Which language runs in a web browser?",
a: "Java",
b: "C",
c: "Python",
d: "JavaScript",
correct: "d",
}, {
question: "What does CSS stand for?",
a: "Central Style Sheets",
b: "Cascading Style Sheets",
c: "Cascading Simple Sheets",
d: "Cars SUVs Sailboats",
correct: "b",
}, {
question: "What does HTML stand for?",
a: "Hypertext Markup Language",
b: "Hypertext Markdown Language",
c: "Hyperloop Machine Language",
d: "Helicopters Terminals Motorboats Lamborginis",
correct: "a",
}, {
question: "What year was JavaScript launched?",
a: "1996",
b: "1995",
c: "1994",
d: "none of the above",
correct: "b",
}, ];
const quiz = document.getElementById("quiz");
const answerElements = document.querySelectorAll(".answer");
const questionElement = document.getElementById("question");
const a_text = document.getElementById("a_text");
const b_text = document.getElementById("b_text");
const c_text = document.getElementById("c_text");
const d_text = document.getElementById("d_text");
const submitButton = document.getElementById("submit");
const randomizedQuestions = shuffle(quizData).slice(0, 10);
let currentQuestion = 0;
let score = 0;
const deselectAnswers = () => {
answerElements.forEach((answer) => (answer.checked = false));
};
const getSelected = () => {
let answer;
answerElements.forEach((answerElement) => {
if (answerElement.checked) answer = answerElement.id;
});
return answer;
};
const loadQuestion = () => {
deselectAnswers();
const currentQuestionData = randomizedQuestions[currentQuestion];
questionElement.innerText = currentQuestionData.question;
a_text.innerText = currentQuestionData.a;
b_text.innerText = currentQuestionData.b;
c_text.innerText = currentQuestionData.c;
d_text.innerText = currentQuestionData.d;
};
loadQuestion();
submitButton.addEventListener("click", () => {
const answer = getSelected();
if (answer) {
if (answer === randomizedQuestions[currentQuestion].correct) score++;
currentQuestion++;
let asd = randomizedQuestions.length - score;
let ssrate = (1220 - Math.floor(total_seconds));
let ggg = "";
if (ssrate < 12) ggg = "good morning";
else if (ssrate < 16) ggg = "ghfgdfgh ning";
else if (ssrate < 24) ggg = "asaasasasa ng";
let avg = Math.round(score * 100 / randomizedQuestions.length);
document.getElementById("myProgress").value = avg;
if (currentQuestion < randomizedQuestions.length) loadQuestion();
else {
// stop timer
clearInterval(timer);
quiz.innerHTML = "<h2>Total Question : " + quizData.length + "<br>" + "Correct Ans : " + score + " <br> Wrong Ans : " + asd + " <br> Average : " + avg + " % <br> Time Usage : " + ssrate + " Seconds <br> Average : " + ggg + " % <br><br> <br><br> <button onclick='location.reload()'>Play Again</button></h2>"
}
}
});
* {
box-sizing: border-box;
}
body {
background-color: #b8c6db;
background-image: linear-gradient(315deg, #b8c6db 0%, #f5f7fa 100%);
font-family: "Poppins", sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
margin: 0;
}
.quiz-container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 10px 2px rgba(100, 100, 100, 0.1);
width: 600px;
max-width: 95vw;
overflow: hidden;
}
.quiz-header {
padding: 4rem;
}
h2 {
padding: 1rem;
text-align: center;
margin: 0;
}
ul {
list-style-type: none;
padding: 0;
}
ul li {
font-size: 1.2rem;
margin: 1rem 0;
}
ul li label {
cursor: pointer;
}
button {
background-color: #8e44ad;
color: #fff;
border: none;
display: block;
width: 100%;
cursor: pointer;
font-size: 1.1rem;
font-family: inherit;
padding: 1.3rem;
}
button:hover {
background-color: #732d91;
}
button:focus {
outline: none;
background-color: #5e3370;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />
<div id="quiz-time-left1"></div>
<div class="quiz-container" id="quiz">
<div class="quiz-header">
<h2 id="question">Question is loading...</h2>
<ul>
<li> <input type="radio" name="answer" id="a" class="answer" /> <label for="a" id="a_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="b" class="answer" /> <label for="b" id="b_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="c" class="answer" /> <label for="c" id="c_text">Answer...</label> </li>
<li> <input type="radio" name="answer" id="d" class="answer" /> <label for="d" id="d_text">Answer...</label> </li>
</ul>
</div> <button id="submit">Submit</button>
</div>
<progress id='myProgress' value='' max='100'>

Related

RGB Color Game if block sometime work and sometime won't work

Hey I am try to create a RGB Color game, here I am facing a Issue that when I refers the tab then inside my randomDiv() function there is a If block(color_fix) which is sometime working and sometime won't working you can check through clicking on refresh tab button inside console, please solve this problem
let first_div = document.getElementById('first_div');
let h4 = document.querySelector('h4');
let h1 = document.createElement('h1');
let color_div = document.querySelector('#color_div');
let createDiv;
h4.style.alignItems = 'center';
h4.append(h1);
let valueRGB = rgb();
h1.innerText = valueRGB.toUpperCase();
h1.style.alignItems = 'center';
first_div.style.backgroundColor = rgb();
function rgb() {
let r = Math.floor(Math.random() * 255 + 0);
let g = Math.floor(Math.random() * 255 + 0);
let b = Math.floor(Math.random() * 255 + 0);
return (`rgb(${r}, ${g}, ${b})`);
}
function threeRandomNumber() {
let threeRandomNumber = Math.floor(Math.random() * 3 + 1);
return threeRandomNumber;
}
function divCreate() {
createDiv = document.createElement('div');
createDiv.classList = 'dynamacily_create_div';
createDiv.style.backgroundColor = `${rgb()}`;
return createDiv;
}
function randomDiv() {
let color_fix = threeRandomNumber();
console.log('outter Background ' + color_fix);
for (let i = 0; i < 3; i++) {
let div_fix = threeRandomNumber();
if (div_fix === 1) {
color_div.appendChild(divCreate());
console.log('outter Background inner' + color_fix);
if (color_fix === 1) {
createDiv.style.backgroundColor = valueRGB;
console.log(valueRGB);
console.log('inner Background ' + color_fix);
}
} else if (div_fix === 2) {
color_div.appendChild(divCreate());
console.log('outter Background inner' + color_fix);
if (color_fix === 2) {
createDiv.style.backgroundColor = valueRGB;
console.log(valueRGB);
console.log('inner Background ' + color_fix);
}
} else {
color_div.appendChild(divCreate());
console.log('outter Background inner' + color_fix);
if (color_fix === 3) {
createDiv.style.backgroundColor = valueRGB;
console.log(valueRGB);
console.log('inner Background ' + color_fix);
}
}
}
}
randomDiv()
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
body {
display: flex;
justify-content: center;
}
h4,
h5 {
color: #ffffff;
font-size: 40px;
}
#first_div {
width: 900px;
height: 200px;
border: 1px solid red;
display: flex;
align-items: center;
flex-direction: column;
}
#color_div {
height: 400px;
width: 100%;
background-color: black;
display: flex;
flex-direction: row;
justify-content: center;
}
.dynamacily_create_div {
width: 200px;
height: 200px;
border-radius: 25px;
margin: 10px;
border: 1px solid red;
}
<body>
<main>
<div id="first_div">
<h4>THE GREAT</h4>
<h5>GUESSING GAME</h5>
</div>
<div id="second_div">
<button id="newColor">New Color</button>
<button id="playAgain">Play Again</button>
<button id="tryAgain">Try Again</button>
<button id="correct">Correct</button>
<button id="easy">Easy</button>
</div>
<div id="color_div">
</div>
</main>
<script src="app.js"></script>
</body>
Some logical branches are ignored by you.
Both div_fix and color_fix are returned by threeRandomNumber().
div_fix can be any one of [1,2,3].
color_fix can be any one of [1,2,3]. They can be the same or not.
While div_fix===1 and color_fix===2 , code is missing.
While div_fix===1 and color_fix===3 , code is missing.
Please check and fix your problem.
if (div_fix === 1) {
color_div.appendChild(divCreate());
console.log('outter Background inner' + color_fix);
if (color_fix === 1) {
createDiv.style.backgroundColor = valueRGB;
console.log(valueRGB);
console.log('inner Background ' + color_fix);
}else{
// Here!! maybe color_fix === 2 or color_fix === 3, Do sth.
}
}

Parent height relative to child height with hidden: overflow

So, my parent container is quiz-container, the child of that is #quiz, the child of that is. slide. The quiz/slide needs to be absolute, or the Q/A will shuffle its way down the page as the next question button is clicked.
The quiz-container should automatically adjust its height based on the size of the #quiz or. slide question/answer so it appears correctly on the phone and so you don't need to scroll forever to click the next button. The button already moves relative to the height of the quiz-container, so that's what I want.
I tried to set a height in px then have it adjust itself with an
overflow: hidden;
but that didn't work.
<style type="text/css">
body {
font-size: 20px;
font-family: 'Work Sans', sans-serif;
color: #333;
font-weight: 300;
text-align: center;
background-color: #f8f6f0;
}
h1 {
font-weight: 300;
margin: 0px;
padding: 10px;
font-size: 20px;
background-color: #444;
color: #fff;
}
.section-description {
margin-bottom: 20px;
}
.question {
position: relative;
font-size: 30px;
margin-bottom: 10px;
}
.answers {
position: relative;
margin-bottom: 20px;
text-align: left;
display: inline-block;
}
.answers label {
display: block;
margin-bottom: 10px;
}
button {
position: absolute;
font-family: 'Work Sans', sans-serif;
font-size: 22px;
background-color: #279;
color: #fff;
border: 0px;
border-radius: 3px;
padding: 20px;
cursor: pointer;
margin-top: 30px;
margin-bottom: 0px;
z-index: 100;
clear: both;
display: block;
bottom: calc(0px + (100% - var(--slide-height)));
left: 60%;
transform: translateX(-10%);
}
button:hover {
background-color: #38a;
}
.slide {
position: absolute;
height: auto;
left: 0px;
top: 0px;
width: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.5s;
border: 5px purple solid;
}
.active-slide {
opacity: 1;
z-index: 2;
}
.quiz-container {
position: relative;
height: 600px;
overflow: hidden;
display: flex;
border: 5px red solid;
}
.previous {
/* styles for the second button */
position: absolute;
left: 30%; /* aligns element horizontally to center of parent */
transform: translateX(-10%); /* moves element to left by 50% of its own width */
bottom: calc(0px + (100% - var(--slide-height)));
}
#quiz > .slide {
position: absoluate;
height: min-content;
overflow: hidden;
border: 5px solid blue;
}
</style>
<h1>QUIZ</h1>
<div class="quiz-container">
<div id="quiz">
</div>
</div>
<div class="block"><button class="previous" id="previous" type="button">Previous Question</button><button id="next" type="button">Next Question</button><button id="submit" type="button">Submit Quiz</button></div>
<div id="results"> </div>
<div id="results"> </div>
<div id="category-scores"> </div>
<div id="raw-scores"> </div>
<script>
// variable for categories
const resultsContainer = document.getElementById('results');
const categoryScoresContainer = document.getElementById('category-scores');
const rawScoresContainer = document.getElementById('raw-scores');
const quizContainer = document.getElementById("quiz");
const submitButton = document.getElementById("submit");
(function() {
// Functions
function buildQuiz() {
// variable to store the HTML output
const output = [];
// for each question...
myQuestions.forEach((currentQuestion, questionNumber) => {
// variable to store the list of possible answers
const answers = [];
// and for each available answer...
for (letter in currentQuestion.answers) {
// ...add an HTML radio button
answers.push(
`<label id="quiz-container">
<input id="answers" type="radio" name="question${questionNumber}" value="${letter}">
${letter} :
${currentQuestion.answers[letter]}
</label>`
);
}
// add this question and its answers to the output
output.push(
`<div id="quiz-container" class="slide">
${currentQuestion.description ? `<div class="section-description">${currentQuestion.description}</div>` : ''}
<div class="question"> ${currentQuestion.question} </div>
<div class="answers"> ${answers.join("")} </div>
</div>`
);
});
// combine output list into one string of HTML and put it on the page
quizContainer.innerHTML = output.join("");
const nextButton = document.getElementById("next");
nextButton.addEventListener("click", function() {
const description = document.getElementById("description");
if (description) quizContainer.removeChild(description);
});
}
function showResults() {
// gather answer containers from our quiz
const answerContainers = quizContainer.querySelectorAll('.answers');
// keep track of user's answers
let numCorrect = 0;
// for each question...
myQuestions.forEach((currentQuestion, questionNumber) => {
// find selected answer
const answerContainer = answerContainers[questionNumber];
const selector = `input[name=question${questionNumber}]:checked`;
const userAnswer = (answerContainer.querySelector(selector) || {}).value;
// if answer is correct
if (userAnswer === currentQuestion.correctAnswer) {
// add to the number of correct answers
numCorrect++;
scores[currentQuestion.category]++;
//multiplies by 2 for final result
scores[currentQuestion.category]++;
}
});
//hide myQuestions
quizContainer.innerHTML = "";
// show number of correct answers out of total
resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.length}`;
categoryScoresContainer.innerHTML = `
<p>Word Knowledge = ${scores.wk/2} out of 18</p>
<p>Arithmetic Reasoning = ${scores.ar/2} out of 15</p>
<p>Paragraph Comprehension = ${scores.pc/2} out of 8</p>
<p>Mathmematics Knowledge = ${scores.mk/2} out of 13</p>`;
// hide previous, next and submit button, and make quiz read-only
const previousButton = document.getElementById("previous");
const nextButton = document.getElementById("next");
const submitButton = document.getElementById("submit");
previousButton.style.display = "none";
nextButton.style.display = "none";
submitButton.style.display = "none";
const inputElements = quizContainer.querySelectorAll("input");
inputElements.forEach(input => {
input.setAttribute("disabled", true);
});
//add restart button
const restartButton = document.getElementById("restart");
restartButton.style.display = "block";
restartButton.addEventListener("click", function() {
location.reload();
});
}
function showSlide(n) {
slides[currentSlide].classList.remove('active-slide');
slides[n].classList.add('active-slide');
currentSlide = n;
if (currentSlide === 0) {
previousButton.style.display = 'none';
} else {
previousButton.style.display = 'inline-block';
}
if (currentSlide === slides.length - 1) {
nextButton.style.display = 'none';
submitButton.style.display = 'inline-block';
} else {
nextButton.style.display = 'inline-block';
submitButton.style.display = 'none';
}
}
function showNextSlide() {
showSlide(currentSlide + 1);
}
function showPreviousSlide() {
showSlide(currentSlide - 1);
}
// Variables
const quizContainer = document.getElementById('quiz');
const resultsContainer = document.getElementById('results');
const submitButton = document.getElementById('submit');
const myQuestions = [{
category: "wk",
description: "<h2>PART I - WORD KNOWLEDGE. YOU WILL HAVE 7 MINUTES TO COMPLETE.</h2><br /><h4>THIS TEST HAS QUESTIONS ABOUT THE MEANING OF WORDS. EACH QUESTION HAS AN UNDERLINED WORD. YOU ARE TO DECIDE WHICH OF THE FOUR POSSIBLE ANSWERS MOST NEARLY MEANS THE SAME AS THE UNDERLINED WORD. THEN WRITE THE ANSWER ON THE APPROPRIATE SPACE ON YOUR ANSWER SHEET.</h4>",
question: "1. <b><u>SMALL</u></b> MOST NEARLY MEANS?",
answers: {
a: "STURDY",
b: "ROUND",
c: "CHEAP",
d: "LITTLE"
},
correctAnswer: "d"
},
{
category: "ar",
description: "<h2>PART II - ARITHMETIC REASONING - YOU WILL HAVE FOURTEEN (14) MINUTES:</h2><h4>THIS IS A TEST OF YOUR ABILITY TO SOLVE ARITHMETIC PROBLEMS. USE YOUR SCRATCH PAPER FOR ANY FIGURING YOU NEED TO DO.</h4>",
question: "1. TWO AUTOMOBILES START TOGETHER FROM THE SAME PLACE AND TRAVEL ALONG THE SAME ROUTE. THE FIRST AVERAGES 40 MPH. THE SECOND 55 MPH. HOW MANY MILES FURTHER ALONG THE ROUTE IS THE SECOND AUTO AT THE END OF THE 5TH HOUR?",
answers: {
a: "55 x 5",
b: "55 - 40",
c: "(55x5) - (40x5)",
d: "55/5 - 40/5"
},
correctAnswer: "c"
},
{
category: "pc",
description: "<h2>PART III - PARAGRAPH COMPREHENSION - YOU WILL HAVE SEVEN (7) MINUTES:</h2>",
question: "1. THE DUTY OF THE LIGHTHOUSE KEEPER IS TO KEEP THE LIGHT BURNING NO MATTER WHAT HAPPENS, SO THAT SHIPS WILL BE WARNED OF THE PRESENCE OF DANGEROUS ROCKS. IF A SHIPWRECK SHOULD OCCUR NEAR THE LIGHTHOUSE, EVEN THOUGH HE WOULD LIKE TO AID IN THE RESCUE OF IT'S CREW AND PASSENGERS, THE LIGHTHOUSE KEEPER MUST......",
answers: {
a: "STAY AT HIS LIGHT",
b: "RUSH TO THEIR AID",
c: "TURN OUT THE LIGHT",
d: "QUICKLY SOUND THE SIREN"
},
correctAnswer: "a"
},
{
category: "mk",
description: "<h2>PART IV - MATHEMATICS KNOWLEDGE - YOU WILL HAVE TWELVE (12) MINUTES:</h2>",
question: "1. WHICH OF THE FOLLOWING IS THE SMALLEST PRIME NUMBER GREATER THAN 200?",
answers: {
a: "201",
b: "205",
c: "211",
d: "214"
},
correctAnswer: "c"
},
];
// Kick things off
buildQuiz();
// Pagination
const previousButton = document.getElementById("previous");
const nextButton = document.getElementById("next");
const slides = document.querySelectorAll(".slide");
let currentSlide = 0;
let scores = {
wk: 0,
ar: 0,
pc: 0,
mk: 0,
};
// Show the first slide
showSlide(currentSlide);
// Event listeners
submitButton.addEventListener('click', showResults);
previousButton.addEventListener("click", showPreviousSlide);
nextButton.addEventListener("click", showNextSlide);
})();
</script>

2 buttons for color opacity changing (Javascript)

I am trying to solve problem with correct working of 2 buttons (I have called them btnleft and btnright). I will use them to change opacity/alpha channel for random color (for example hsl(x, y%, z%, 1) -> hsl(x, y%, z%, 0.8)).
a variable is for opacity value, btnleft is for changing opacity down and btnright for changing up. Main function alphaValue is not working when I click left/right button (and I do not see any error on WWW console).
HSLinStringAlpha is hsl(hue, saturation%, lumination%, opacity) notation.
Below I put my code (maybe too long, but working without opacity changing).
Thanks for any advice.
/* Nested functions with errors */
function colorChange() {
function randomColor() {
let Cmax = []; let Cmin = []; let Lum = []; let Delta = [];
let Hue = []; let Sat = [];
let HueAngle = Math.round(60 * Hue);
let SatInt = Math.round(100 * Sat);
let LumInt = Math.round(100 * Lum);
/* Here is probably some mistake (wrong method of made function?) */
function FullHSLCode() {
for (let i = 0; i < indexValue.length / 3; i++) {
HSLinString[i] = `hsl(${HueAngle[i]}, ${SatInt[i]}%, ${LumInt[i]}%)`;
}
return HSLinString;
}
FullHSLCode();
}
/* End of randomColor(), here I was tried to made closure */
randomColor();
var a = 1;
var HSLinStringAlpha = [`hsla(${HueAngle[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
/* alphaValue() doesn't work after move it outside randomColor() function - WWW console shows that HueAngle, SatInt, LumInt variables aren't accessible */
function alphaValue(HSLinStringAlpha, HueAngle, SatInt, LumInt, a) {
if (this.id !== "btn1") {
//if(button1.onclick === true) {
if (this.id === "btnleft") {
a -= 0.05;
} else if (this.id === "btnright") {
a += 0.05;
}
HSLinStringAlpha.push(`hsla(${HueAngle[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`);
HSLinStringAlpha.shift();
}
return HSLinStringAlpha;
}
alphaValue();
/*
let button1 = document.getElementById("btnleft");
let button2 = document.getElementById("btnright");
button1.disabled = false;
button2.disabled = false;
button1.addEventListener("click", alphaValue, false);
button2.addEventListener("click", alphaValue, false);
*/
}
to check which button is clicked you should not using
if (button1.onclick === true)
but use like
if (this.id === 'btnleft')
window.addEventListener("DOMContentLoaded", colorChange);
function colorChange() {
document.getElementById("btn1").addEventListener("click", randomColor, false);
function randomColor() {
let HEXColor = [];
let HSLColor = [];
let RGBinString = []; // defines color in rgb(num,num,num) style
let HEXinString = []; // defines color in hexadecimal style
let HSLinString = []; // defines color in hsl() style
/* Randomize r,g,b numbers of colors in rgb(num,num,num) style */
let indexValue = [];
let colorArray = [];
function RGBrandom() {
for(let j = 0; j <= 8; j++) {
indexValue[j] = Math.floor(Math.random() * 256);
colorArray.push(indexValue[j]);
}
for(i = 0; i < 3; i++) {
RGBinString[i] = `rgb(${indexValue[3*i]},${indexValue[3*i+1]},${indexValue[3*i+2]})`;
}
return RGBinString;
}
RGBrandom();
// Calculate hex code string from rgb code
function RGBtoHex(indexValue) {
const HEXcolorValue = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"];
for(let i = 0; i < indexValue.length; i++) {
if(indexValue[i] <= 15) {
HEXColor.push(0, HEXcolorValue[indexValue[i]]);
}
else {
HEXColor.push(HEXcolorValue[Math.floor(indexValue[i] / 16)], HEXcolorValue[(indexValue[i]) % 16]);
}
}
return HEXColor;
}
let HEXFullColor = RGBtoHex(indexValue);
function FullHEXCode() {
for(let j = 0; j < HEXFullColor.length / 6; j++) {
HEXFullColor[j] = HEXFullColor.slice(6 * j, 6 * j + 6);
HEXinString[j] = HEXFullColor[j].join("");
HEXinString[j] = `#${HEXinString[j]}`;
}
return HEXinString;
}
FullHEXCode();
let RGBArray = [];
function RGBvalueChange() {
for(let j = 0; j <= 8; j++) {
/* for Red indexes (j = 0, 3, 6, etc.) */
if(j % 3 === 0) {
RGBArray.push(indexValue[j] / 255);
}
/* for Green indexes (j = 1, 4, 7, etc.) */
else if((j + 2) % 3 === 0) {
RGBArray.push(indexValue[j] / 255);
}
/* for Blue indexes (j = 2, 5, 8, etc.) */
else {
RGBArray.push(indexValue[j] / 255);
}
}
return RGBArray;
}
RGBvalueChange();
let Cmax = [];
let Cmin = [];
let Lum = [];
let Delta = [];
let Hue = [];
let Sat = [];
let HuePercent = [];
let SatInt = [];
let LumInt = [];
for(let i = 0; i < indexValue.length / 3; i++) {
Cmin.push(Math.min(RGBArray[3 * i], RGBArray[3 * i + 1], RGBArray[3 * i + 2])); // 3 values
Cmax.push(Math.max(RGBArray[3 * i], RGBArray[3 * i + 1], RGBArray[3 * i + 2])); // 3 values
Lum.push((Cmax[i] + Cmin[i]) / 2); // 3 values
Delta[i] = Cmax[i] - Cmin[i]; // 3 values
if(Delta[i] === 0) {
Hue.push(0); //Hue[i] === 0;
Sat.push(0); //Sat[i] === 0;
}
else {
// Hue dependance from other parameters
if(Cmax[i] === RGBArray[3 * i]) {
Hue.push(((RGBArray[3 * i + 1] - RGBArray[3 * i + 2]) / Delta[i] + (RGBArray[3 * i + 1] < RGBArray[3 * i + 2] ? 6 : 0)));
}
else if(Cmax[i] === RGBArray[3 * i + 1]) {
Hue.push((RGBArray[3 * i + 2] - RGBArray[3 * i]) / Delta[i] + 2);
}
else if(Cmax[i] === RGBArray[3 * i + 2]) {
Hue.push((RGBArray[3 * i] - RGBArray[3 * i + 1]) / Delta[i] + 4);
}
else {
Hue.push(0);
}
Sat[i] = Lum[i] > 0.5 ? (0.5 * Delta[i]) / (1 - Lum[i]) : Delta[i] / (2 * Lum[i]);
Sat.push(Sat[i]);
}
HuePercent[i] = Math.round(60 * Hue[i]);
SatInt[i] = Math.round(100 * Sat[i]);
LumInt[i] = Math.round(100 * Lum[i]);
}
function FullHSLCode() {
for(let j = 0; j < indexValue.length / 3; j++) {
HSLinString[j] = `hsl(${HuePercent[j]}, ${SatInt[j]}%, ${LumInt[j]}%)`;
}
return HSLinString;
}
FullHSLCode();
var a = 1;
let HSLinStringAlpha = [`hsl(${HuePercent[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
let button1 = document.getElementById("btnleft");
let button2 = document.getElementById("btnright");
button1.disabled = false;
button2.disabled = false;
function alphaValue() {
if(this.id !== 'btn1') {
//if(button1.onclick === true) {
if(this.id === 'btnleft') {
a -= 0.05;
}
else {
a += 0.05;
}
//console.log(a)
HSLinStringAlpha[0] = [`hsl(${HuePercent[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
//HSLinStringAlpha.shift();
}
console.log(HSLinStringAlpha[0][0])
return HSLinStringAlpha;
}
button1.addEventListener("click", alphaValue, false);
button2.addEventListener("click", alphaValue, false);
document.querySelector("p").innerHTML = [`${a} `, HSLinStringAlpha];
// 3 random colors in every element (circle)
document.getElementById("color1").value = HEXinString[0];
document.getElementById("color2").value = HEXinString[1];
document.getElementById("color3").value = HEXinString[2];
document.getElementById("color4").value = RGBinString[0];
document.getElementById("color5").value = RGBinString[1];
document.getElementById("color6").value = RGBinString[2];
document.getElementById("color7").value = HSLinStringAlpha[0];
document.getElementById("color8").value = HSLinString[1];
document.getElementById("color9").value = HSLinString[2];
box1.style.backgroundColor = HSLinStringAlpha[0];
box2.style.backgroundColor = HSLinStringAlpha[0];
box3.style.backgroundColor = HSLinStringAlpha[0];
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
width: 100vw;
background-color: lightgray;
position: absolute;
}
.bigbox {
min-height: 320px;
width: 630px;
position: absolute;
}
.box {
height: auto;
width: 33%;
margin: 0 0 10px;
background-color: lightgray;
display: block;
position: relative;
float: left;
}
.colorbox {
height: 150px;
width: 150px;
margin: 5px auto;
border-radius: 50%;
background-color: #234523;
display: block;
}
.text {
height: auto;
width: 100%;
display: block;
float: left;
}
.shape {
height: 1.75em;
width: calc(100% - 3px);
margin: 0 auto 5px;
font-size: 18px;
text-align: left;
border: gray solid 1px;
display: block;
}
p {
display: inline-block;
margin: 10px 5px;
float:right;
}
.arrowbox {
height: 100%;
width: 100%;
margin: 0 auto;
font-size: 20px;
display: block;
float: left;
}
.buttons {
height: 100%;
width: 40%;
margin: 10px auto;
display: block;
float: left;
}
.testbutton {
height: 100%;
width: 40%;
font-size: 20px;
display: block;
float: left;
}
.arrowbutton {
height: 100%;
width: 30%;
font-size: 20px;
display: block;
float: left;
}
.buttonbox {
height: 3.5em;
width: 100%;
font-size: 20px;
display: block;
clear: both;
}
#btn1 {
height: 100%;
width: 8.5em;
margin: 0 auto;
font-size: 20px;
display: block;
}
<div class="container">
<div class="bigbox">
<div id="box4" class="box">
<div id="box1" class="colorbox"></div>
<div class="text">
<input type="text" id="color1" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
<input type="text" id="color4" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
<input type="text" id="color7" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
</div>
</div>
<div id="box5" class="box">
<div id="box2" class="colorbox"></div>
<div class="text">
<input type="text" id="color2" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color5" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color8" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
</div>
</div>
<div id="box6" class="box">
<div id="box3" class="colorbox"></div>
<div class="text">
<input type="text" id="color3" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color6" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color9" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
</div>
</div>
<div class="buttonbox">
<div class="arrowbox">
<p>Yes, it's almost something what I'm looking for, but...Yeah you need some extra options - click "TEST" button below.</p>
<div class="buttons">
<button id="btnleft" class="arrowbutton">◄</button>
<button id="btncenter" class="testbutton">RESET</button>
<button id="btnright" class="arrowbutton">►</button>
</div>
</div>
<button id="btn1" onclick="colorChange();">Click for color !!!</button>
</div>
</div>
</div>

Dynamically add values to form with javascript or jquery

I have created a calculator I use for counting carbs for my 7 y/o type 1 diabetic but as I add more values into my array the page is getting too long.
I'm looking for a way to start with a single select for the food name then select the weight and it calculates the carbs. Then have a button to dynamically add another row to the form in order to select a new food item and calculate the results of any further additions.
This is my functional code base:
<html><head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
#container{width: 200px; margin: 0 auto;}
label { font-size:20px; display: inline-block; width: 45%; text-align: right;}
input[type="text"][disabled] {width: 12%; background-color: white; color: black; font-weight: bolder;}
input[type="button"] {}
select {width: 15%}
</style></head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [['Banana',0.1428571429], ['Blackberry',0.1], ['Blueberry',0.1418918919], ['Carrots',0.09836065574], ['Cantaloupe',0.08], ['Cherry Tomato',0.05882352941], ['Cucumber',0.03653846154], ['Green apple',0.1373626374], ['Honeydew',0.09], ['Pear',0.15], ['Raspberry',0.12], ['Plum',0.11], ['Strawberry',0.075], ['Watermelon',0.075]];
function reset(){
var t=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
document.calc.elements[v].value=0;
}
}
function calculate(){
var t=0;
var tt=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
var a = "answer"+i;
if(isNaN(parseInt(document.calc.elements[v].value))) {
//document.calc.elements[a].value="";
} else {
tt=(parseInt(document.calc.elements[v].value))* myArray[i][1];
document.calc.elements[a].value=tt.toFixed(1);
t+=tt;
}
}
document.calc.answerTot.value=(t).toFixed(1)
}
document.write("<form name=\"calc\" action=\"post\">");
for (var i=0; i<myArray.length; i++) {
var vv = "val"+i;
var aa = "answer"+i;
document.write("<label>"+myArray[i][0]+":</label> <select name=\""+ vv +"\" onchange=\"calculate()\" >");
for (var j=0; j<301; j++) {
document.write("<option value=" +j+ ">" +j+ "</option>");
}
document.write("</select><input type=text name=" +aa+ " size=5 placeholder=\"Carbs\" disabled><br>");
}
document.write("<br><label for=\"answerTot\">Total carbs: </label> <input type=text name=answerTot size=5 disabled></br></br> <div style=\"text-align:center\"> <input type=button value=Calculate onClick=\"calculate()\"></br></br><input type=button value=Reset onClick=\"reset()\"></div>");
</script></body></html>
Hello there and welcome to StackOverflow!
Your code required a bit of rework and questions like that (more like a task than a question) aren't usually very successful around here.
Having said that, I wrote something that will hopefully help you, the nice thing about it being that if you want to add new types of food you'll only need to add them in the array and the js will take care of it.
Careful with the approximation to 1 digit though, you might lose some carbs in the calculation. Also, please check your carbs, see if I haven't modified anything by mistake.
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = "";
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) > 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inp = document.createElement("input");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
entry.appendChild(sel);
entry.appendChild(inp);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
* {
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 140px;
height: 20px;
margin: 5px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 240px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
<form name="calc" action="post" id="calculatorForm">
</form>
<div style="text-align:center" class="control">
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
If anyone wants to see the result, this is what I ended up with. I added a couple event listeners and made the weight value a select rather than an input. Thanks again #Paul for the assistance this is exactly what I was trying to accomplish!
<html>
<head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
{
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 145px;
height: 20px;
margin: 2px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 50px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
</style>
</head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = 0;
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) >= 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inpu = document.createElement("select");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
inpu.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
for (var j=0; j<301; j++){
inpu.options[inpu.options.length]=new Option(j,j)
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
inpu.addEventListener("change", function() {
calculate();
})
sel.addEventListener("change", function() {
calculate();
})
entry.appendChild(sel);
entry.appendChild(inpu);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
</script>
<form name="calc" action="post" id="calculatorForm"></form>
<div style="text-align:center" class="control"><br>
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
</body></html>
Here is a small application I came up with that could also suit your needs.
It consists of five files that should be located in the same directory.
Best of health for your child!
Features include:
adding and removing of new food types
adding and removing food to/from multiple lists
changing, increasing and decreasing count of fooditems in lists
manage (add,remove,rename) multiple lists
save and load data in your browser locally
export and import data through a text area to save your data externally.
layout support for both big screen and handheld devices
myCarbCalculator.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Carb Calculator</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="myCarbCalculator.css"></link>
<link rel="stylesheet" media="screen" href="myCarbCalculator-Screen.css"></link>
<link rel="stylesheet" media="handheld" href="myCarbCalculator-Handheld.css"></link>
<script type="text/javascript" src="myCarbCalculator.js"></script>
</head>
<body onload="init();">
<div id="root">
<div id="header">
<button id="btnSaveSettings">save Settings</button>
<button id="btnLoadSettings">load Settings</button>
<button id="btnImportSettings">import Settings</button>
<button id="btnExportSettings">export Settings</button>
<button id="btnResetSettings">reset Settings</button>
</div>
<div id="center">
<div id="content-main">
<div id="c_foodSelector">
<label for="selFoodSelector">select a type of food</label>
<select id="selFoodSelector"></select>
<button id="btnAddSelectedFoodToList">Add Food to List</button>
</div>
<div id="c_foodTable">
<div id="c_foodTableOptions">
<input id="p_foodTableName" value="Your List of Food Items"/>
<button id="btnRenameFoodTable">rename List</button>
<button id="btnNewFoodTable">new List</button>
</div>
<table id="foodTable" class="fill-width"></table>
</div>
</div>
<div id="content-additional">
<div id="c_results">
<label for="inputResultCarbs">Carbs Total</label>
<input id="inputResultCarbs" readonly="readonly"/>
</div/>
<div id="c_foodTableSelection">
<table id="foodTableSelection" class="fill-width"></table>
</div>
<div id="c_output">
<h3>Import/Export</h3>
<textarea id="p_output" class="fill-width"></textarea>
</div/>
</div>
</div>
<div id="footer">
<label for="p_newFoodName">Food Name</label><input id="p_newFoodName"/>
<label for="p_newFoodCarbs">Carb Value</label><input id="p_newFoodCarbs"/>
<button id="btnNewFood">add a new type of food</button>
<button id="btnDeleteSelectedFood">delete Selected type of food</button>
</div>
</div>
</body>
</html>
myCarbCalculator.js
var SAVEID = 'carbCalculatorSettings';
function MyCarbCalculator(){
var self = this;
this.settings = null;
this.initSettings = function(){
self.settings = {
'activeFoodList' : 'default',
'foodData' : {},
'foodList' : {
'default' : {
'label' : 'Your List of Food Items',
'list' : {},
'dateCreated' : '',
'dateChanged' : '',
'notes' : 'This is the default Food List'
}
}
};
};
this.clearContents = function(element){
while (element.firstChild) {
element.removeChild(element.firstChild);
}
};
this.formatDate = function(timestamp){
if(timestamp != ""){
var date = new Date(timestamp);
var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
];
var day = date.getDate();
var monthIndex = date.getMonth();
var year = date.getFullYear();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
return day + ' ' + monthNames[monthIndex] + ' ' + year + ' ' + hours + ':'+ minutes + ':'+ seconds;
}
return "---";
};
//////////////////////////////////////////////////////////////////
// Load and Save Data
//////////////////////////////////////////////////////////////////
this.resetSettings = function(){
self.initSettings();
self.updateView();
};
this.saveSettings = function(){
localStorage.setItem(SAVEID,JSON.stringify(self.settings));
};
this.loadSettings = function(){
var saveData = localStorage.getItem(SAVEID);
if(saveData != null && saveData.length > 0){
self.settings = JSON.parse(localStorage.getItem(SAVEID));
self.updateView();
}
else{
self.initSettings();
}
};
this.importSettings = function(){
localStorage.setItem(SAVEID,document.getElementById('p_output').value);
self.loadSettings();
};
this.exportSettings = function(){
document.getElementById('p_output').value = localStorage.getItem(SAVEID);
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.updateView = function(){
self.updateFoodSelector();
self.updateFoodTable();
self.updateFoodTableSelection();
self.updateResult();
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.newFood = function(){
var name = document.getElementById('p_newFoodName').value;
var carbs = document.getElementById('p_newFoodCarbs').value;
var id = Date.now();
self.settings.foodData[id] = {'name':name,'carbs':carbs};
self.updateFoodSelector();
};
this.removeSelectedFoodData = function(){
var foodSelector = document.getElementById('selFoodSelector');
var foodDataId = foodSelector.options[foodSelector.selectedIndex].value;
delete self.settings.foodData[foodDataId];
self.updateFoodSelector();
}
this.updateFoodSelector = function(){
var foodSelector = document.getElementById('selFoodSelector');
self.clearContents(foodSelector);
for(id in self.settings.foodData){
var food = self.settings.foodData[id];
var item = document.createElement("option");
item.value = id;
item.innerHTML = food.name + " (" + food.carbs + ")";
foodSelector.appendChild(item);
}
};
//////////////////////////////////////////////////////////////////
// Manage current Food Table
//////////////////////////////////////////////////////////////////
this.addSelectedFoodToTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var foodSelector = document.getElementById('selFoodSelector');
var selectedFoodId = foodSelector.options[foodSelector.selectedIndex].value;
var foodData = self.settings.foodData[selectedFoodId];
var foodItem = {'name':foodData.name,'carbs':foodData.carbs,'count':1};
foodList.list[Date.now()] = foodItem;
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodCount = function(id,value){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
foodList.list[id].count = value;
foodList.dateChanged = Date.now();
self.updateView();
};
this.removeFoodItem = function(id){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
delete foodList.list[id];
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
// update the List Name
var foodTableNameElement = document.getElementById('p_foodTableName');
foodTableNameElement.value = foodList.label;
// update the List itself
var foodTable = document.getElementById('foodTable');
self.clearContents(foodTable);
// create the Table Header
var row = document.createElement("tr");
foodTable.innerHTML =
"<tr><th>Name</th><th>Carbs/unit</th><th></th><th>Count</th><th></th></tr>";
for(id in foodList.list){
// create a table structure
var row = document.createElement("tr");
var elm1 = document.createElement("td");
var elm2 = document.createElement("td");
var elm3 = document.createElement("td");
var elm4 = document.createElement("td");
var elm5 = document.createElement("td");
var elm6 = document.createElement("td");
row.appendChild(elm1);
row.appendChild(elm2);
row.appendChild(elm3);
row.appendChild(elm4);
row.appendChild(elm5);
row.appendChild(elm6);
foodTable.appendChild(row);
// create input fields
var food = foodList.list[id];
var inputFoodId = document.createElement("input");
inputFoodId.id = "food-id-" + id;
inputFoodId.type = "hidden";
inputFoodId.value = id;
var inputFoodName = document.createElement("input");
inputFoodName.id = "food-name-" + id;
inputFoodName.setAttribute("readonly","readonly");
inputFoodName.value = food.name;
var inputFoodCarbs = document.createElement("input");
inputFoodCarbs.id = "food-carbs-" + id;
inputFoodCarbs.setAttribute("readonly","readonly");
inputFoodCarbs.style.width = "3em";
inputFoodCarbs.value = food.carbs;
var inputFoodCount = document.createElement("input");
inputFoodCount.id = "food-count-" + id;
inputFoodCount.setAttribute("data-id",id);
inputFoodCount.style.width = "3em";
inputFoodCount.value = food.count;
inputFoodCount.addEventListener("change",function(event){
var inputFoodCount = event.currentTarget;
var id = inputFoodCount.getAttribute("data-id");
var count = inputFoodCount.value;
self.updateFoodCount(id,count);
});
var btnDeleteFoodItem = document.createElement("button");
btnDeleteFoodItem.innerHTML = "remove";
btnDeleteFoodItem.setAttribute("data-id",id);
btnDeleteFoodItem.addEventListener("click",function(event){
var btnDeleteFoodItem = event.currentTarget;
var id = btnDeleteFoodItem.getAttribute("data-id");
self.removeFoodItem(id);
});
var btnCountUp = document.createElement("button");
btnCountUp.innerHTML = "+";
btnCountUp.setAttribute("data-id",id);
btnCountUp.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = ++ inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
var btnCountDown = document.createElement("button");
btnCountDown.innerHTML = "-";
btnCountDown.setAttribute("data-id",id);
btnCountDown.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = -- inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
// append input fields to the table row
elm1.appendChild(inputFoodId); // this one is invisible anyway
elm1.appendChild(inputFoodName);
elm2.appendChild(inputFoodCarbs);
elm3.appendChild(btnCountDown);
elm4.appendChild(inputFoodCount);
elm5.appendChild(btnCountUp);
elm6.appendChild(btnDeleteFoodItem);
}
};
//////////////////////////////////////////////////////////////////
// Calculate Results
//////////////////////////////////////////////////////////////////
this.calculateCarbsForList = function(listId){
var foodListData = self.settings.foodList[listId].list;
var total = 0;
for(id in foodListData){
var item = foodListData[id];
total = total + (item.carbs * item.count);
}
return total;
};
this.updateResult = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var inputResultCarbs = document.getElementById("inputResultCarbs");
inputResultCarbs.value = self.calculateCarbsForList(activeFoodListId);
};
//////////////////////////////////////////////////////////////////
// Food Table Handling
//////////////////////////////////////////////////////////////////
this.renameFoodTable = function(){
var activeTableId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeTableId];
var newName = document.getElementById('p_foodTableName').value;
foodList.label = newName;
foodList.dateChanged = Date.now();
self.updateView();
};
this.newFoodTable = function(){
var newTableName = document.getElementById('p_foodTableName').value;
var date = Date.now();
self.settings.foodList[date] = {
'label' : newTableName,
'list' : {},
'dateCreated' : date,
'dateChanged' : date,
'notes' : ''
}
self.settings.activeFoodList = date;
self.updateView();
};
this.updateFoodTableSelection = function(){
var foodTableSelection = document.getElementById('foodTableSelection');
self.clearContents(foodTableSelection);
var foodTableLists = self.settings.foodList;
foodTableSelection.innerHTML =
"<tr><th>Name</th><th>last Change</th><th>Carbs</th><th></th><th></th></tr>";
for(var tableId in foodTableLists){
var foodTable = foodTableLists[tableId];
var row = document.createElement("tr");
if(tableId == self.settings.activeFoodList){
row.classList.add("active");
}
var cell1 = document.createElement("td");
var cell2 = document.createElement("td");
var cell3 = document.createElement("td");
var cell4 = document.createElement("td");
var cell5 = document.createElement("td");
cell1.innerHTML = foodTable.label;
cell1.style.cursor = "help";
cell1.title = foodTable.notes;
cell2.innerHTML = self.formatDate(foodTable.dateChanged);
cell2.title = "created: " + self.formatDate(foodTable.dateCreated);
cell3.innerHTML = self.calculateCarbsForList(tableId);
var btnSelectFoodTable = document.createElement("button");
if(tableId == self.settings.activeFoodList)btnSelectFoodTable.disabled = 'disabled';
btnSelectFoodTable.innerHTML = "select";
btnSelectFoodTable.setAttribute("data-tableId",tableId);
btnSelectFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
self.settings.activeFoodList = button.getAttribute("data-tableId");
self.updateView();
});
cell4.appendChild(btnSelectFoodTable);
var btnDeleteFoodTable = document.createElement("button");
if(tableId == 'default')btnDeleteFoodTable.disabled = 'disabled';
btnDeleteFoodTable.innerHTML = "delete";
btnDeleteFoodTable.setAttribute("data-tableId",tableId);
btnDeleteFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
var tableId = button.getAttribute("data-tableId");
if(self.settings.activeFoodList = tableId){
self.settings.activeFoodList = "default";
};
delete self.settings.foodList[tableId];
self.updateView();
});
cell5.appendChild(btnDeleteFoodTable);
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
row.appendChild(cell5);
foodTableSelection.appendChild(row);
}
};
//////////////////////////////////////////////////////////////////
// Add global Events
//////////////////////////////////////////////////////////////////
document.getElementById("btnNewFood").addEventListener("click",this.newFood);
document.getElementById("btnSaveSettings").addEventListener("click",this.saveSettings);
document.getElementById("btnLoadSettings").addEventListener("click",this.loadSettings);
document.getElementById("btnResetSettings").addEventListener("click",this.resetSettings);
document.getElementById("btnImportSettings").addEventListener("click",this.importSettings);
document.getElementById("btnExportSettings").addEventListener("click",this.exportSettings);
document.getElementById("btnDeleteSelectedFood").addEventListener("click",this.removeSelectedFoodData);
document.getElementById("btnAddSelectedFoodToList").addEventListener("click",this.addSelectedFoodToTable);
document.getElementById("btnRenameFoodTable").addEventListener("click",this.renameFoodTable);
document.getElementById("btnNewFoodTable").addEventListener("click",this.newFoodTable);
//////////////////////////////////////////////////////////////////
// Initialize the Data on screen
//////////////////////////////////////////////////////////////////
self.loadSettings();
}
function init(){
var carCalculator = new MyCarbCalculator();
}
myCarbCalculator.css
body,html{
height:100%;
}
/* dont show borders on input fields if read only */
input:-moz-read-only {
border : none;
}
input:read-only {
border : none;
}
/* spacing elements out */
th{
text-align:left;
}
label,input,button,select{
white-space:nowrap;
margin-right: 1em;
}
button{
height:2.5em;
}
#c_results,#c_foodSelector,#c_output,#footer,#header{
padding:1em;
}
/* make result stand out */
#c_results #inputResultCarbs{
font-size: 2em;
color: #882222;
width:4em;
}
#c_results label[for="inputResultCarbs"]{
font-size: 1em;
padding-top:1em;
}
.fill-width{
width:100%;
}
table#foodTableSelection > tr.active{
background-color:yellow;
}
myCarbCalculator-Screen.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:row;
border-bottom: 1px solid black;
}
#footer{
display:flex;
flex-direction.row;
border-top: 1px solid black;
}
#center{
flex: 1 0;
display:flex;
flex-direction:row;
}
#content-main{
flex: 1 0 auto;
display:flex;
flex-direction: column;
}
#c_foodSelector{
border-bottom: 1px solid black;
}
#c_foodTable{
}
#content-additional{
flex: 0 1 30%;
display:flex;
flex-direction: column;
border-left: 1px solid black;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
myCarbCalculator-Handheld.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 3;
}
#footer{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 2;
}
#center{
flex: 1 0;
display:flex;
flex-direction:column;
order: 1;
}
#content-main{
display:flex;
flex-direction: column;
}
#c_foodSelector{
display:flex;
flex-direction:column;
border-bottom: 1px solid black;
}
#c_foodTable{
border-bottom: 1px solid black;
}
#content-additional{
display:flex;
flex-direction: column;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
/*******************************************
ADDITONAL STYLES ONLY FOR HANDHELD LAYOUT
*******************************************/
/* spacing out vertically */
label,input,button,select{
margin-bottom: 0.5em;
}
input[id^="food-name"]{
width:4em;
}
#header:before,#footer:before{
text-align:center;
font-size:1em;
font-weight:bold;
margin-bottom:0.5em;
}
#header:before{
content:'Options';
}
#footer:before{
content:'Foodtypes';
}
Technical Notes:
I am using pure Javascript and css. Some styles might not be compatible with older browsers like Internet Explorer prior to Edge.
Saving of data is handled through the browsers local storage.
Import and Export is handled through plain text in "Javascript Object Notation" (JSON).
The Application itself is written as a Javascript Class e.g. Function named MyCarbCalculator which is created and initialized through the bodies onload event and an init() function.
With this example application I'm trying to show how to use Javascript in a structured (pseudo object oriented) way and the power and flexibility of event listeners and unnamed functions e.g. the use of functions as parameters.
Also I am using CSS media descriptors to create a flexible layout that can be customized for both handheld devices and big screens. This is mostly done through the "flexbox" style which allows for very fluid layouts and offers great control over the positioning of elements.

Text fields reset when I add a new one

I have a form that starts off with one input and then I add additional inputs with the press of a button. However, whenever a new input is added, it clears whatever data was in the previous inputs. Here is what the code looks like:
Initial input with form:
<form id="grade_inputs" onkeyup="displayGrade()">
<div class="grade_input">Grade 1: <input class="grade" type="text" size="1" maxlength="3" placeholder="0"></div>
</form>
The displayGrade() method:
function displayGrade()
{
var average = calculateAverage();
var grade_label = document.getElementById("grade");
var grade_letter;
var grade_color;
if(average < 70)
{
grade_letter = "F";
grade_color = "#E60000";
}
else if(average < 80)
{
grade_letter = "C";
grade_color = "#FF7700";
}
else if(average < 90)
{
grade_letter = "B";
grade_color = "#FAC800";
}
else
{
grade_letter = "A";
grade_color = "#5AE000";
}
grade_label.innerHTML = grade_letter;
grade_label.style.color = grade_color;
}
The function that adds a new input:
function addGrade()
{
var grade_inputs_form = document.getElementById("grade_inputs");
grade_inputs_form.innerHTML += '<div class="grade_input">Grade ' + gradeCounter++ + ': <input class="grade" type="text" size="1" maxlength="3" placeholder="0"></div>';
displayGrade();
}
I'm adding the new inputs by appending to the innerHTML of the parent form. I'm not sure if this is the correct way of going about this, so any recommendations is appreciated! Thanks.
Use appendChild instead of innerHTML += as it will reinsert entire HTML again which will make you lose the data as well as binded events(Not inline binded events)..
The Node.appendChild() method adds a node to the end of the list of children of a specified parent node
Try this:
var gradeCounter = 2;
function calculateAverage() {
var average = 0;
var grades = document.getElementsByClassName("grade");
for (var i = 0; i < grades.length; i++) {
var gradeNumber = parseInt(grades[i].value);
if (!isNaN(gradeNumber))
average += parseInt(grades[i].value);
}
return average /= grades.length;
}
function displayGrade() {
var average = calculateAverage();
var grade_label = document.getElementById("grade");
var grade_letter;
var grade_color;
if (average < 70) {
grade_letter = "F";
grade_color = "#E60000";
} else if (average < 80) {
grade_letter = "C";
grade_color = "#FF7700";
} else if (average < 90) {
grade_letter = "B";
grade_color = "#FAC800";
} else {
grade_letter = "A";
grade_color = "#5AE000";
}
grade_label.innerHTML = grade_letter;
grade_label.style.color = grade_color;
}
function addGrade() {
var grade_inputs_form = document.getElementById("grade_inputs");
var div = document.createElement('div');
var new_grade = '<div class="grade_input">Grade ' + gradeCounter+++': <input class="grade" type="text" size="1" maxlength="3" placeholder="0"></div>';
div.innerHTML = new_grade;
var child = div.firstChild;
grade_inputs_form.appendChild(child);
displayGrade();
}
function removeGrade() {
}
body {
background-color: aliceblue
}
form {
margin-top: 20px;
margin-left: 20px;
font-size: 17pt;
}
h1 {
text-align: center;
font-family: "Avant Garde", sans-serif;
font-size: 40px;
text-decoration: underline;
}
button {
margin-left: 40px;
font-size: 14pt
}
input {
margin-bottom: 5px;
font-size: 14pt;
}
div.grade_input {
display: inline-block;
position: relative;
margin-left: 15px;
margin-right: 15px;
margin-bottom: 15px;
}
#buttons {
text-align: center;
margin-bottom: 30px;
}
#grade_tag {
margin-top: 15px;
margin-left: 30px;
font-family: "Avant Garde", sans-serif;
display: inline-block;
font-size: 24pt;
}
#grade {
margin-left: 6px;
font-size: 36pt;
color: #E60000;
font-family: "Avant Garde", sans-serif;
font-weight: bold;
}
::-webkit-input-placeholder {
color: #6A6A6A;
}
::-moz-placeholder {
color: #6A6A6A;
}
:-ms-input-placeholder {
color: #6A6A6A;
}
input:-moz-placeholder {
color: #6A6A6A;
}
<h1>Student Grade Calculator</h1>
<div id="buttons">
<button style="font-size: 24px;" onclick="addGrade()">Add Grade</button>
<button style="font-size: 24px;" onclick="removeGrade()">Remove Grade</button>
</div>
<form id="grade_inputs" onkeyup="displayGrade()">
<div class="grade_input">Grade 1:
<input class="grade" type="text" size="1" maxlength="3" placeholder="0">
</div>
</form>
<span id="grade_tag">Average grade: </span>
<span id="grade">F</span>
Fiddle here
Your problem is - Id is not same as class
var grade_label = document.getElementById("grade");
<input class="grade" type="text" size="1" maxlength="3" placeholder="0"></div>
you need to get element by classname rather than id.
Assuming that there will be multiple-grades of which you want to find out the average, then try
function displayGrade( )
{
var elements = document.getElementsByClassName( "grade" );
for ( var counter = 0; counter < elements.length; counter++ )
{
displayGradeForEach( elements[counter] );
}
}
function displayGradeForEach( grade_label )
{
var average = calculateAverage();
var grade_letter;
var grade_color;
if(average < 70)
{
grade_letter = "F";
grade_color = "#E60000";
}
else if(average < 80)
{
grade_letter = "C";
grade_color = "#FF7700";
}
else if(average < 90)
{
grade_letter = "B";
grade_color = "#FAC800";
}
else
{
grade_letter = "A";
grade_color = "#5AE000";
}
grade_label.innerHTML = grade_letter;
grade_label.style.color = grade_color;
}

Categories