So for a school assignment I have to make an interactive quiz with javascript. That I did, the problem is that it is required for me to store all the questions in an external text file on local storage.
My questions are stored in an array of objects, and I add them to radio buttons with a 'for'-loop
I googled it, but I didn't find an answer that made it clear enough for me...
I understand that I can read files out, but I have no idea how I would add the questions to my existing for-loops
I'm still totally new to JS, and have no idea how to implement this
here's a code snippet, where i take the questions out of the array, and add them to the list with radio buttons
var i = 0;
var len = allQuestions.length;
function frageStellen(i){
var anzahlVarianten = allQuestions[i].choices.length;
for(var j = 0; j < anzahlVarianten; j++){
//create radio buttons
var option = document.createElement("li");
var variante = document.createElement("input");
variante.setAttribute('type', 'radio');
variante.setAttribute('name', 'gestellteFrage'+ i);
option.setAttribute('class', '.option');
//fragen-Inhalt
var inhalt = document.createTextNode(allQuestions[i].choices[j]);
myOptions.appendChild(option);
option.appendChild(variante);
option.appendChild(inhalt);
myQuestion.innerHTML = allQuestions[i].question;
}
}
Here is the link to the full code: http://jsfiddle.net/7HaCz/
please help!
Put this part of your code:
var jsonData = [{
question: "What is Javascript?",
choices: ["An ancient language", "A programming language", "A medieval manuscript", "An internet troll"],
correctAnswer: 1
}, {
question: "Where is Venice?",
choices: ["Peru", "Greece", "US", "Italy", "Congo"],
correctAnswer: 3
}, {
question: "What does RGB mean?",
choices: ["Red, Green, Blue", "Real Graphics Body", "SWAG"],
correctAnswer: 0
}, {
question: "How many strings has a guitar?",
choices: [3, 4, 5, 6, 7, 8],
correctAnswer: 3
}];
In a separate file, then follow this stackoverflow to JSON.parse(jsonData) to get the JSON data out of it again.
Related
I am new to Js, and i am coding a simple quiz app with HTML, CSS and JS to learn.
I am a mobile developer and use Flutter and Dart, dart is pretty similar to JS. On the quiz app, when someone presses the next button after an answered question, i want it to switch to the next question.
When the user presses the button nothing happens... In dart i would use the setState method, which forces the UI to reload with the updated changes. Is there an equivalent method in JS? I found that setState is used in ReactJS, however this is coded in vanilla Js.
I have an Array of 2 questions (which are maps containing the questiopn text, answer alternatives and correct answer). Then I have an integer variable which is the questionIndex. So first question the index i 0, and when the user presses the next button ( to go to the next question) it should increment by 1.
Here is the code for the button click:
function onClickNext() {
console.log("called");
currentQuestionIndex++;
}
the Array of questions:
const questions = [
{
question: "What is the capital of Sweden?",
"alt 1": "Stockholm",
"alt 2": "Gothenburg",
"alt 3": "Malmö",
"alt 4": "Linköping",
correctIndex: 0,
},
{
question: "What is the capital of England?",
"alt 1": "London",
"alt 2": "Manchester",
"alt 3": "Bournemouth",
"alt 4": "Cardiff",
correctIndex: 0,
},
];
And here are the dynamic HTML components (the question + answer alternatives, which are suppoosed to change when next is pressed, so it moves onto the next question.
document.getElementById("question").innerHTML =
questions[currentQuestionIndex]["question"];
button1.innerHTML = questions[currentQuestionIndex]["alt 1"];
button2.innerHTML = questions[currentQuestionIndex]["alt 2"];
button3.innerHTML = questions[currentQuestionIndex]["alt 3"];
button4.innerHTML = questions[currentQuestionIndex]["alt 4"];
Would be really thankful for some guidance, and also if someone knows a way to make my code more consise and efficiant.
Thank you!
Since Vanilla JS has no state listeners that will update the DOM automatically, you can program this yourself, for example:
function onClickNext() {
console.log("called")
currentQuestionIndex++
drawQuestionScreen()
}
function drawQuestionScreen(){
document.getElementById("question").innerHTML =
questions[currentQuestionIndex]["question"];
button1.innerHTML = questions[currentQuestionIndex]["alt 1"];
button2.innerHTML = questions[currentQuestionIndex]["alt 2"];
button3.innerHTML = questions[currentQuestionIndex]["alt 3"];
button4.innerHTML = questions[currentQuestionIndex]["alt 4"];
}
Just populate the question HTML anew after calling onClickNext so that the reassignment has an effect.
To make the code more concise, save the question at the current index in a variable first, instead of accessing through the index each time.
const questionDiv = document.getElementById("question");
const populateQuestion = () => {
const question = questions[currentQuestionIndex];
questionDiv.innerHTML = question.question;
button1.innerHTML = question["alt 1"];
button2.innerHTML = question["alt 2"];
button3.innerHTML = question["alt 3"];
button4.innerHTML = question["alt 4"];
}
// populate on pageload:
populateQuestion();
// and also on click:
function onClickNext() {
currentQuestionIndex++;
populateQuestion();
}
An even better approach would be to use an array for the buttons and answers instead of separate property and variable names. Consider naming the array of possible answers answers instead of alt, it'll probably make more sense at a glance.
const populateQuestion = () => {
const question = questions[currentQuestionIndex];
questionDiv.innerHTML = question.question;
question.answers.forEach((answer, i) => {
buttons[i].textContent = answer;
});
}
You should also consider using .textContent - only use .innerHTML when deliberately inserting HTML markup.
Here's the code I'm trying to get to work:
function checkAnswer(questionIndex) {
// This ID goes to a div storing the four buttons
var answersId = document.getElementById("answers");
//The four spans inside the buttons which has data-answer, targeting at their id. The id and data-answer are the same value.
var answer0 = document.getElementById("option0").getAttribute("data-answer");
var answer1 = document.getElementById("option1").getAttribute("data-answer");
var answer2 = document.getElementById("option2").getAttribute("data-answer");
var answer3 = document.getElementById("option3").getAttribute("data-answer");
answersId.addEventListener("click", function (event) {
if (event.target.hasAttribute("data-answer")) {
event.preventDefault;
if (answer0 == questionList[questionIndex].correctAnswer) {
console.log(answer0)
score++;
console.log(score)
console.log("This is option0")
}
else if (answer1 == questionList[questionIndex].correctAnswer) {
console.log(answer1)
score++;
console.log(score)
console.log("This is option1")
} else if (answer2 == questionList[questionIndex].correctAnswer) {
console.log(answer2)
score++;
console.log(score)
console.log("This is option2")
} else if (answer3 == questionList[questionIndex].correctAnswer) {
console.log(answer3)
score++;
console.log(score)
console.log("This is option3")
} else {
console.log(score)
}
}
});
}
This is sorta hard coded right now, but I want to make sure it actually works before optimizing it.
Basically, I have buttons for a multiple choice quiz, and the idea is that depending on the button clicked, they get a point for choosing the correct answer. In this case, the data-answer should match whatever the correct answer is. (If the correct answer is option1, then "option1" == "option1")
But no matter what button is clicked (in this case, the answer is indeed option1), it gives the point and gives the console.log for option 1, meaning that it constantly chooses that if statement even when I'm picking the other buttons.
It's just driving me crazy that the wrong answer, which is the else statement, isn't being recognized
or rather, it keeps recognizing the second if statement despite clicking the wrong answer. I think my logic is sound, it just isn't working right.
Do you know what I could be missing here?
Edit: Here's the questionList array being referenced, and the objects for each of those variables:
var question1 = {
text: "Commonly used data types do NOT include:",
choices: ["1 - Booleans", "2 - Alerts", "3 - Strings", "4 - Numbers"],
correctAnswer: "option1",
};
var question2 = {
text: "The condition of an if/else statement is enclosed within ______.",
choices: ["1 - Quotes", "2 - Curly Brackets", "3 - Parentheses", "4 - Square Brackets"],
correctAnswer: "option2",
};
var question3 = {
text: "Arrays in Javascript can be used to store ______.",
choices: ["1 - Numbers and strings", "2 - Other Arrays", "3 - Booleans", "4 - All of the above",],
correctAnswer: "option3",
};
var question4 = {
text: "String values must be enclosed within ______ when being assigned to variables.",
choices: ["1 - Quotes", "2 - Curly Brackets", "3 - Commas", "4 - Parentheses"],
correctAnswer: "option0",
};
var question5 = {
text: "A very useful tool used during development and debugging for printing content to the debugger is:",
choices: ["1 - Javascript", "2 - console.log", "3 - Terminal/bash", "4 - For loops"],
correctAnswer: "option1",
};
var questionList = [question1, question2, question3, question4, question5];
Edit 2:
Adding where I'm calling the function. This time I moved the eventlistener out of the checkAnswer() function and right before it is called.
document.getElementById("start-quiz").addEventListener("click", function (event) {
event.preventDefault;
event.stopPropagation;
countDown = 75;
countDownSpan.textContent = countDown;
document.querySelector("#description").style.display = "none";
document.querySelector("#start-quiz").style.display = "none";
contentId.style.textAlign = "left";
setTime();
createAnswers();
generateQA(0);
var answersId = document.getElementById("answers");
answersId.addEventListener("click", function (event) {
checkAnswer(0)
});
});
Edit 3:
If it helps, here is the link to the github page:
https://github.com/WarriorofZarona/Coding-Quiz
GitHub
I clearly didn't know how to explain myself in the title..
I have an array with information from a survey, the array is giving me the apps people say they use more and how they evaluated them.
From a list where you can choose the following apps:
WordExcelPower PointAccessPower Bi
You must rate each app by the following aspects:
UsabilityPerformanceMobile capabilityData movement
These functions can be evaluated as "1-Poor", "2-Average", "3-Good" or "4-N/A".
Also each person is divided by their continent: America, Asia, Europe, Africa, Oceania.
My Problem:
I need to separate people by their continent.
And by how they evaluated each of the apps:
People from America who rated as "Poor" Word in "Usability".
People from America who rated as "Poor" Word in "Performance".
People from America who rated as "Poor" Word in "Mobile capability".
People from America who rated as "Poor" Word in "Data movement".
I need to do this exact loop for each evaluation: poor, average, good and N/A.
And also for each app: Word, Excel, Power Point, Access, Power Bi.
And also by Continent: America, Asia, Europe, Africa, Oceania.
This is how my array looks (just an example of one person):
var results = [
{
"Author": "Person 1",
"Word Usability": "3",
"Word Performance": "2",
"Word Mobile capability": "1",
"Word Data movement": "4",
"Excel Usability": "3",
"Excel Performance": "2",
"Excel Mobile capability": "1",
"Excel Data movement": "4",
"PowerPoint Usability": "3",
"PowerPoint Performance": "2",
"PowerPoint Mobile capability": "1",
"PowerPoint Data movement": "4",
"Access Usability": "3",
"Access Performance": "2",
"Access Mobile capability": "1",
"Access Data movement": "4",
"PowerBi Usability": "3",
"PowerBi Performance": "2",
"PowerBi Mobile capability": "1",
"PowerBi Data movement": "4",
"Continent": "America"
},
...
]
What I did was to create various arrays and then looped them to separate people by Region, and by how they evaluated each app by each of the aspects marked before:
<script>
//I created arrays for each continent
var america = [],
europe = [],
asia = [],
africa = [],
oceania = [];
//And also separate the count of each "evaluation" from each aspect to rate the app
var americaWord_Usability1 = 0,
americaWord_Usability2 = 0,
americaWord_Usability3 = 0,
americaWord_Usability4 = 0;
var americaWord_Performance1 = 0,
americaWord_Performance2 = 0,
americaWord_Performance3 = 0,
americaWord_Performance4 = 0;
...
//I make the loop
for(var i=0;i<results.length;i++) {
var currentItem = results[i];
//depending their continent, I send each people to their correspondent array
if(currentItem.Continent == "America") {
america.push(currentItem);
}
...
}
//now I loop by region and send them depending their app and how they were evaluated in each aspect
for(var q=0;q<america.length;q++){
var currentItem = america[q];
if(currentItem["Word Usability"] == "1") {
americaWord_Usability1++;
} else if(currentItem["Word Usability"] == "2") {
americaWord_Usability2++;
} else if(currentItem["Word Usability"] == "3") {
americaWord_Usability3++;
} else {
americaWord_Usability4++;
}
if(currentItem["Word Performance"] == "1") {
americaWord_Performance1++;
} else if(currentItem["Word Performance"] == "2") {
americaWord_Performance2++;
} else if(currentItem["Word Performance"] == "3") {
americaWord_Performance3++;
} else {
americaWord_Performance4++;
}
...
}
</script>
With this method it all becomes a nightmare. It is a lot of code because I need to make an array for each continent and an array for each aspect to rate of each app!
My actual code is a little bit longer, there are much more aspects to rate and more apps. So my code became horribly long.
My question here is: Is there a better and easier way to achieve this?
Thanks in advance!
To make things easier, you could just create the arrays on the fly:
var userData = [];
for(var i=0;i<results.length;i++) {
var currentItem = results[i];
// If the subarray doesn't exist yet, create it
if (userData[currentItem.Continent] == null) userData[currentItem.Continent] = [];
// Push the data into the corresponding array
userData[currentItem.Continent].push(currentItem);
}
Now you will have an array that has all the users separated by continent. You can apply the same logic to going through your ratings, so for example:
// List all the possible keywords for ratings here
var ratingKeywords = ["Word Usability", "Excel Usability"];
// Empty arra for ratings
var ratings = [];
// Go through the continents
for (var continentName in userData) {
var continent = userData[continentName];
// Array for continent ratings
if (!ratings[continentName]) ratings[continentName] = [];
for (var u in continent) {
var user = continent[u];
for (var k in ratingKeywords) {
var keyword = ratingKeywords[k];
console.log(keyword);
var rating = user[keyword];
if (!ratings[continentName][keyword]) ratings[continentName][keyword] = [];
if (!ratings[continentName][keyword][rating.toString()]) ratings[continentName][keyword][rating.toString()] = 0;
ratings[continentName][keyword][rating.toString()]++;
}
}
}
This looks a bit clunky, but you won't need to hard-code anything. And if a new continent emerges (which probably won't happen because of the rising sea levels, please go vegan or reduce your meat consumption as soon as possible), this code should still work.
You will end up with an array that has the following structure, for example:
ratings["Europe"]["Word Usability"][5]: 400
(Note that you maybe shouldn't use for-in-loops, but... yeah)
you can use javascript filters instead. like following
ex:
filteredListwith1 = results.filter((item) => {
if(item.continent === 'America' && item['Word Usability'] === '1') {
return item;
});
americaBox_Usability1 = filteredListwith1.length;
same thing you can repeat for 2 and 3 as well.
I'm creating quiz game.
I have separate .js file with array of objects for questions,like this:
var questions = [
{
ask: "question",
choice1: "answer",
choice2: "answer",
choice3: "answer",
correct: "correct answer"
},
];
then i get random object from array:
let random = questions[Math.floor(Math.random() * questions.length)];
then i can send these object.properties to dom like this:
question.innerHTML = random.ask
answer1.innerHTML = random.choice1;
answer2.innerHTML = random.choice2;
answer3.innerHTML = random.choice3;
answer4.innerHTML = random.correct;
And everything works fine but i need to randomize these answers.In ways like this every time the correct answer is on same place but i need answers and correct answer to take random place in dom.
I'm stuck in this problem,trying every solution i can find on google but no success.
You can use the same logic to randomize choices. One of the ways this can be done is as below:
var questions = [
{
ask: "question",
choice1: "answer 1",
choice2: "answer 2",
choice3: "answer 3",
correct: "correct answer"
},
];
let random = questions[Math.floor(Math.random() * questions.length)];
console.log(random);
// Make an array of choices key
let choices = [];
Object.keys(random).forEach((item, index) => {
if(key !== "ask") {
choices.push(random[item]);
}
});
console.log(choices);
function getRandomAnswer() {
// Get a random number
let randomNum = Math.floor(Math.random() * choices.length);
// Store random answer in a variable
let answer = choices[randomNum];
// Remove used up answer from choices array
choices.splice(randomNum, 1);
return answer;
}
console.log("Random Answer: ", getRandomAnswer());
console.log("Random Answer: ", getRandomAnswer());
console.log("Random Answer: ", getRandomAnswer());
console.log("Random Answer: ", getRandomAnswer());
I have made a jsFiddle of this as well. You can optimize this as per your needs.
Hope it helps!
Straight to the point, I created a form letting user to insert 2 items (Option Name, Option Value)
The inserting number is dynamic such as:
**Option Name** **Option Value**
Color Red
Blue
Yellow
Size L
M
and I need to populate a table of the possibilities given by user like below:
**Color** **Size**
Red L
Red M
Blue L
Blue M ....etc
how can I write a javascript logic to do that? the worst problem is what if the user input 3 or 4 option name like adding material:cotton, chiffon sex: male, female?
It seems to be impossible or lots and lots of loop? I had been doing this for 2 weeks plus. Can anyone guide me through an easier way? I am almost stunned by this.
If you use a recursive function, you only need one loop and one if-else statement, no matter how many options there are:
var options = [{
name: "Color",
values: ["Red", "Blue"]
}, {
name: "Size",
values: ["M", "L"]
}, {
name: "Sex",
values: ["Male", "Female"]
}];
function list(options, result) {
if (options.length > 0) {
var option = options[0];
var remaining = options.slice(1);
for (var i = 0; i < option.values.length; i++) {
var current = result.slice(0);
current.push(option.values[i]);
list(remaining, current);
}
} else {
document.body.innerHTML += result.join(", ");
document.body.innerHTML += "<br/>";
}
}
list(options, []);
Fiddle available here.