I am making a quiz with my son to teach him HTML. But i'm having trouble with some JavaScript(no jquery or any other libraries). Everything works okay until the end. It's suppose to tell us how many are right and wrong, but instead we get undefined.
error reads:Uncaught TypeError: Cannot assign to read only property 'innerHTML' of Question 17 of 16
HTML
<body id="body">
<div id="pokeBallL"> </div>
<div id="pokeBallR"> </div>
<div id="spacer"> </div>
<h2 id="tstat"></h2>
<div id="test"> </div>
</body>
JavaScript
(function () {
"use strict";
/*global window,alert*/
var UIlogic = {
myStuff: function () {
var pos = 0, question, test, tstat, Myquestions, btnCheck, choice, choices, chA, chB, chC, chD, correct;
Myquestions = [
["What decade wear you born?","1980's","1990's","2000's","2010's","A"],
["What activity do you like more","Gaming","Camping","Travelling","Sleeping","A"],
["Pick a color","Black","Pink","Red","Blue","A"],
["Pick a number","22","42","4","7","A"],
["Choose a weapon","Battleaxe","Sword","Daggers","pen","A"],
["Pick an animal","Tiger","Monkey","Elephant","Human","A"],
["Pick a music genre","Rock","Hip-hop","Country","Folk","A"],
["How many legs do Butterflies have?","4 legs","6 legs","2 legs","3 legs","A"],
["How many stripes are on the American flag?","13","15","7","19","A"],
["Which is the nearest star?","Centauri A","Sol","Sirius","Proxima Centauri","A"],
["Longest river in the world is...?","Mississippi","Nile","Amazon","Ohio","A"],
["Pick one...","PS4","PC Master Race","XB One","Puny Apple","A"],
["Pop or Soda?","Pop","Both","Soda","Soft Drink","A"],
["What is your favorite creature","Amphibian","Mammal","Reptile","Avian","A"],
["Pick a squad position","Squad Leader","FTL","","Grenadier","A"],
["The Zombie apocalypse has begun! CHoose your path...","Get to lifeboat","Live inside mountains","Hold-up above gas station","Become Zombie","A"]
];
function _(x) {
return document.getElementById(x);
}
function renderQuestion() {
test = _("test");
tstat = _("tstat").innerHTML = "Question " +(pos + 1)+ " of " +Myquestions.length;//seems to have an issue here
if(pos >= Myquestions.length) {
test.innerHTML = "<h2>You got " +correct+ " out of " +Myquestions.length+ " questions correct!</h2>";
tstat.innerHTML = "<h2>Test completed</h2>";
pos = 0;
correct = 0;
return false;
}
question = Myquestions[pos][0];
chA = Myquestions[pos][1];
chB = Myquestions[pos][2];
chC = Myquestions[pos][3];
chD = Myquestions[pos][4];
test.innerHTML = "<h3>"+question+"</h3><hr />";
test.innerHTML += "<h4><input type='radio' name='choices' value='A'>"+chA+"</h4><br />";
test.innerHTML += "<h4><input type='radio' name='choices' value='B'>"+chB+"</h4><br />";
test.innerHTML += "<h4><input type='radio' name='choices' value='C'>"+chC+"</h4><br />";
test.innerHTML += "<h4><input type='radio' name='choices' value='D'>"+chD+"</h4><br />";
test.innerHTML += "<button id='btnCheck' class='btnClass'>Submit</button>";
btnCheck = document.getElementById("btnCheck");
btnCheck.addEventListener('click', checkAnswer, false);
}
renderQuestion();
function checkAnswer() {
choices = document.getElementsByName("choices");
for(var i = 0; i<choices.length; i++) {
if(choices[i].checked){
choice = choices[i].value;
}
}
if(choice == Myquestions[pos][5]) {//somewhere here doesn't seem right either.
correct++;
}
pos++;
renderQuestion();
}
}
};
window.onload = function () {
UIlogic.myStuff();
};
}());
separate this line
tstat = _("tstat").innerHTML = "Question " +(pos + 1)+ " of " +Myquestions.length;//seems to have an issue here
into this:
tstat = _("tstat");
tstat.innerHTML = "Question " +(pos + 1)+ " of " + (Myquestions.length + 1);
Demo
I got it... i changed
var correct;
to
var correct = 0;
turns out, the index wasn't counting because correct was reading NAN
Although, i should make a function to check the radios first before entering, a non-answer will answer correctly. This is what i made for that...
function checkAnswer() {
choices = document.getElementsByName("choices");
var found = 1;
for (var i = 0; i < choices.length; i++) {
if (choices[i].checked) {
choice = choices[i].value;
found = 0;
break;
}
}
if(found == 1)
{
alert("Please Select Radio");
return false;
}
if (choice === Myquestions[pos][5]) { //somewhere here doesn't seem right either.
correct++;
}
pos++;
renderQuestion();
}
Related
Ive been developing a Simon says game recently that adds to the score if you click the correct button which there are 3,
1) green 1
2) red 2
3) trick
I've noticed that when I run the game and click the appropriate buttons only one will add to the score whilst the other two subtract from it (Regardless of what the statement says). Im unsure why this is the case and was wondering if anyone had any insights). My thought is that the if functions don't seem to correlate to the new statement that is generated.
Any suggestions are appreciated,
var answers = [
"Simon says click red !",
"Simon says click green !",
"Simon says click 1 !",
"Simon says click 2 !",
"Click green",
"Click red",
"Click 1",
"Click 2!"
];
var score = 0;
var total = document.getElementById("score");
var statement = document.getElementById("instruct");
var randomStatement = answers[Math.floor(Math.random() * answers.length)];
function refresh(){
var randomStatement = answers[Math.floor(Math.random() * answers.length)];
statement.innerHTML = randomStatement;
}
function pressTrick(){
if(randomStatement === "Click green" || randomStatement === "Click red" || randomStatement === "Click 1" || randomStatement === "Click2!"){
score++;
total.style.color = "green";
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
} else {
total.style.color = "red";
score--;
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
}
}
function pressRed(){
if(randomStatement === "Simon says click red !" || randomStatement === "Simon says click 2 !"){
score++;
total.style.color = "green";
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
} else {
total.style.color = "red";
score--;
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
}}
function pressGreen(){
if(randomStatement === "Simon says click 1 !" || randomStatement === "Simon says click green !"){
score++;
total.style.color = "green";
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
} else {
total.style.color = "red";
score--;
total.innerHTML = "Total score: " + score;
setTimeout(refresh,900);
}}
function start(){
var i = 60;
var count = setInterval(timer,1000);
refresh();
function timer() {
var display = document.getElementById("timer");
var finished = document.getElementById("heading");
if(i < 1){
clearInterval(count);
finished.innerHTML = "Game Over! Your final Score is : " + score;
display.style.color = "red";
display.style.fontWeight = "bold";
document.body.style.backgroundColor = "black";
} else if(i <= 10) {
i--;
display.style.color = " red";
display.style.fontWeight = "bold";
display.innerHTML = i + " Seconds Left";
} else {
i--;
display.style.color = "green";
display.style.fontWeight = "bold";
display.innerHTML = i + " Seconds Left";
}}}
<html>
<head>
<title> Simon Says! </title>
<link rel = "stylesheet" href = "simonsays.css"/>
</head>
<body>
</br>
<h1> Test Your Reflexes! </h1>
<div id = "heading"; class = "h2"> Click on Simon to Begin! </div>
</br>
<img src = "boy.jpg" onclick = "start()"; onclick = "timer()"; onclick = "returnStatement";/>
</br>
<div id = "instruct" class="statement"></div>
</br>
<div class = "align">
<input type = "button" class = "button2" id = "button2" value = "1" onclick = "pressGreen()"; ></input>
<input type = "button" class = "button" id = "button" value = "2" onclick = "pressRed()"; ></input>
<input type = "button" class = "button3" id = "button3 " value = "Trick" onclick = "pressTrick()";></input>
</div>
</br>
<div id = "score" class = "score"><b> Score: </b></div>
<div id = "timer" class = "timer"><b> Time left: </b></div>
<script src = "simonsays.js"></script>
</body>
</html>
Thank you!
There's just one word too much: var. In
function refresh(){
var randomStatement = answers[Math.floor(Math.random() * answers.length)];
statement.innerHTML = randomStatement;
}
the var causes a new, local variable randomStatement to be defined, and the global randomStatement remains unchanged, so all comparisons in the rest of the program use the initial rather than the refreshed value of randomStatement. Drop the var here, and it works as expected.
Ive been trying to learn Javascript OOP so i made a quiz. However for some reason my html is not being populated with the questions and answers I made. I cannot figure out the problem. Any help would be greatly appreciated!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Edgy Quiz</title>
<link type="text/css" rel="stylesheet" href="style.css"/>
</head>
<body>
<h1>In a world where everyone is looking to stand out from the crowd</h1>
<h2>Does the extend of your own edginess confuse you?</h2>
<h3>Well this scientifically proven personality test was built for you!</h3>
<div class="grid">
<div id="quiz">
<h4>How edgy are you?</h4>
<hr style="margin-top: 20px">
<p id="question"></p>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
<button id="btn2"><span id="choice2"></span></button>
<button id="btn3"><span id="choice3"></span></button>
</div>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y.</p>
</footer>
</div>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
$(window).load(function() {
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
Question.prototype.correctAnswer = function(choice) {
return choice === this.answer;
}
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.isEnded = function() {
return this.questions.length === this.questionIndex;
}
Quiz.prototype.guess = function(answer) {
if (this.getQuestionIndex().correctAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
function populate() {
if(quiz.isEnded()) {
showScores();
}
else {
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
var choices = quiz.getQuestionIndex().choices;
for(var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
}
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function () {
quiz.guess(guess);
populate();
}
}
function showProgress () {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + "of " +
quiz.questions.length;
}
function showScores() {
var gameOverHtml = "<h1>Result</h1>";
gameOverHtml += "<h2 id='score'>Your score: ' + quiz.score + '</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHtml;
}
var questions = [
new Question ("How have you discovered this test?", ["I was bored browsing
online", "I want to see how edgy I am", "Im a friend doing it out of
Sympathy", "Im looking at this weirdo's portfolio"], "Im looking at this
weirdo's portfolio"),
new Question ("How edgy do you think you are?", ["Extremely edgy", "Im very
mainstream", "What does edgy even mean?", "I don't do labels"], "I don't do
labels"),
new Question ("Of these colors which is your favourite?", ["Blue", "Orange",
"Majenta", "Black"], ""),
new Question ("Could you bring yourself to hurt a living thing?", ["Only if
it hurt me first", "I hurt stuff for fun", "No never how could you im a
vegan", "I hurt myself all the time"], "I hurt myself all the time"),
new Question ("If someone tickled you how would you respond?", ["Tickle
fight", "Run away", "Punch them in the face", "Write a song"], "Write a
song"),
];
var quiz = new Quiz(questions);
populate();
});
I want to make a personality test.But i can get from questions.json only first questions,when i clicked the next questions button i am facing this error "Javascript Uncaught TypeError: Cannot read property 'length' of undefined"
var pos = 0, test, test_status, question, choice, choices, chA,chB,chC,totalCheck = 0;//değişkenler
var btn = document.getElementById("btn");
var ourData;
btn.addEventListener("click",function () {
var ourRequest = new XMLHttpRequest();
ourRequest.open('GET','questions.json');
ourRequest.onload = function () {
ourData = JSON.parse(ourRequest.responseText);
renderQuestion(ourData);
}
ourRequest.send();
})
var counters = [A=0,B=0,C=0];
function _(x){
return document.getElementById(x);//html dom
}
function renderQuestion(data){ //soru soran fonksiyon
test = _("test"); //dom ile test div ini seç
if(pos >= 4){
for(var i = 0;i<choices.length;i++){test.innerHTML += "<h2>Sonuç : "+data[i].soru+" dan "+ counters[i] +" kadar işaretledin</h2>";}// test divine sonucu yazdır
_("test_status").innerHTML = "Test Completed"; // "test_status" başlığına test bitti yazdır
pos = 0; // pos tekrar 0 yap
correct = 0; // dogru sayısını tekrar 0 yap;
return false; //false döndür
}
_("test_status").innerHTML = "Question "+(pos+1)+"of"+data.length; // "test_status başlığına hangi soruda olduğunu yazdır
question = data[pos].soru; // questions listesinden 0. yani soru kısmını question değişkenine ata
chA = data[pos].siklar1; // 1.cevap
chB = data[pos].siklar2; // 2.cevap
chC = data[pos].siklar3; // 3.cevap
test.innerHTML = "<h3>"+question+"</h3>"; //soruyu yazdır
test.innerHTML += "<input type='checkbox' name='choices' value='A'>"+chA+"<br>"; //1.cevabı yazdır
test.innerHTML += "<input type='checkbox' name='choices' value='B'> "+chB+"<br>"; //2.cevabı yazdır
test.innerHTML += "<input type='checkbox' name='choices' value='C'> "+chC+"<br><br>"; //3.cevabı yazdır
test.innerHTML += "<button class='button' onclick='checkAnswer()'> NEXT QUESTİONS >> </button>" //cevabı kontrol et fonksiyonunu cağır
}
function checkAnswer(){
choices = document.getElementsByName("choices"); // seçenekler domunu seç
if(choices[0].checked){
if(choices[1].checked || choices[2].checked){
findChecked(choices);
}
else{
counters[0]+=2;
}
}
else if(choices[1].checked){
if(choices[0].checked || choices[2].checked){
findChecked(choices);
}
else{
counters[1]+=2;
}
}
else if(choices[2].checked){
if(choices[0].checked || choices[1].checked){
counters[2]++;
}
else{
counters[2]+=2;
}
}
pos++; // pozisyonu 1 arttır
renderQuestion(); //render questionsu tekrar çağır
}
function findChecked(answers) {
for (var i = 0; i < answers.length; i++) {
if (answers[i].checked == true) {
counters[i]++;
totalCheck++;
}
}
}
window.addEventListener("load", renderQuestion, false);
I think you're calling renderQuestion without any parameter. So data.length might be throwing the error.
Without knowing which line is throwing the error for sure (hint: please provide the line number of the error as well), at a guess I'd say it's this line you're getting the error on
_("test_status").innerHTML = "Question "+(pos+1)+"of"+data.length;
So make sure data has a length attribute
I am writing a simple quiz application.
It was working fine until I try to edit the font for the selected radio buttonvar labelStyle = userpick.style.fontWeight;
Anyone able to spot the problem??
Also, if possibe, suggestion to improve the code?
I have made some new changes to the checkAnswer function
// define all the elements
var content = $("content");
var questionContainer = $("question");
var choicesContainer = $("choices");
var scoreContainer = $("score");
var submitBtn = $("submit");
//init variables
var currentQuestion = 0;
var score = 0;
var askingQuestion = true;
//shortcut for document.getElementById
function $(id){
return document.getElementById(id);
}
//askQuestion Function to load question into id = question
function askQuestion (){
var choices = quiz[currentQuestion].choices;
var choicesHtml = "";
//loop through chocies and create a radio button
for (var i = 0; i < choices.length; i++){
choicesHtml += "<input type = 'radio' name = 'quiz" + currentQuestion +
"' id = 'choice" + (i + 1) +
"' value ='" + choices[i] + "'>" +
"<label for ='choice" + (i + 1) + "'>" + choices[i] + "</label></br>";
}
//load the Question
questionContainer.textContent = "Q" + (currentQuestion + 1) + ". " + quiz[currentQuestion].question;
//load the choices
choicesContainer.innerHTML = choicesHtml;
//setup for the first time
if(currentQuestion === 0){
scoreContainer.textContent = "Score : 0 right answer out of " +
quiz.length + " possible.";
submitBtn.textContent = "Submit Answer";
}
}
//checkAnswer function to match user input with quiz.correctAnswer
function checkAnswer(){
//
if (askingQuestion){
submitBtn.textContent = "Next Question";
askingQuestion = false;
//determine if radio button is clicked
var userpick;
var correctIndex;
var radios = document.getElementsByName("quiz" + currentQuestion);
for (var i = 0 ; i < radios.length; i++){
if(radios[i].checked){
//if radio button is checked
userpick = radios[i].value;
}
if(radios[i].value == quiz[currentQuestion].correct){
correctIndex = i;
}
}
//if they got it right or wrong
var labelStyle = document.getElementsByTagName('label')[correctIndex].style;
labelStyle.fontWeight = "bold";
if (userpick == quiz[currentQuestion].correctAnswer) {
score++;
labelStyle.color = "green";
}else{
labelStyle.color = "red";
}
scoreContainer.textContent = "Score: "+ score + "right answers out of "+
quiz.length + " possible.";
}
function showFinalResults(){
content.innerHtml = "<h2> You've completed the quiz</h2" +
"<h2> Below are your results </h2>" +
"<h2>" + score + " out of " + quiz.length +
"questions, " + Math.round(score/quiz.length * 100) + "% </h2>";
}
}
window.addEventListener("load", askQuestion, false);
submitBtn.addEventListener("click", checkAnswer, false);
var quiz = [{"question": "Question 1: Grand Central Terminal, Park Avenue, New York is the world's",
"choices": ["A: largest railway station",
"B: highest railway station",
"C: longest railway station",
"D: None of the above"],
"correctAnswer": 0
},
{"question": "Question 2: Entomology is the science that studies",
"choices": ["A: Behavior of human beings",
"B: Insects",
"C: The origin and history of technical and scientific terms",
"D: The formation of rocks"],
"correctAnswer": 1
},
{"question": "Question 3: Friction can be reduced by changing from",
"choices": ["A: sliding to rolling",
"B: rolling to sliding",
"C: potential energy to kinetic energy",
"D: dynamic to static"],
"correctAnswer": 0
},
{"question": "Question 4: For seeing objects at the surface of water from a submarine under water, the instrument used is",
"choices": ["A: kaleidoscope",
"B: spectroscope",
"C: periscope",
"D: telescope"],
"correctAnswer": 2
},
{"question": "Question 5: Galileo was an Italian astronomer who",
"choices": ["A: developed the telescope",
"B: discovered four satellites of Jupiter",
"C: discovered that the movement of pendulum produces a regular time measurement",
"D: All of the above"],
"correctAnswer": 3
},
{"question": "Question 6: Habeas Corpus Act 1679",
"choices": ["A: states that no one was to be imprisoned without a writ or warrant stating the charge against him",
"B: provided facilities to a prisoner to obtain either speedy trial or release in bail",
"C: safeguarded the personal liberties of the people against arbitrary imprisonment by the king's orders",
"D: All of the above"],
"correctAnswer": 3
},
{"question": "Question 7: For galvanizing iron which of the following metals is used?",
"choices": ["A: Aluminium",
"B: Lead",
"C: Zinc",
"D: Copper"],
"correctAnswer": 2
}];
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head lang = "en">
<title> Quiz </title>
</head>
<body>
<div class = "page-header">
<h1>Simple Javascript Quiz</h1>
</div>
<div id = "content">
<h3 id = "question"> </h3>
<div id = "choices"> </div>
<button id = "submit">Submit</button>
<p id ="score"></p>
</div>
<script src = 'quiz2.js'></script>
</body>
</html>
userpick.style.fontWeight;
Cannot read property 'fontWeight' of undefined
That means that userpick.style is undefined.
Relevant code:
var userpick;
for (var i = 0; i < radios.length; i++)
if(radios[i].checked){
userpick = radios[i].value;
If no radio was checked, userpick.style.fontWeight would throw, but the error would be
Cannot read property 'style' of undefined
That means that there is some checked radio, so userpick is not undefined.
But userpick.style is undefined. And thats because the value of a radio is a string, and by default strings have no style property.
Probably, you want userpick to be the checked radio, not its value
var userpick;
for (var i = 0; i < radios.length && !userpick; ++i)
if(radios[i].checked)
userpick = radios[i];
However, let me introduce querySelector and the :checked pseudo-class:
var userpick = document.querySelector(".quiz" + currentQuestion + ":checked");
In this piece of your code:
var radios = document.getElementsByName("quiz" + currentQuestion);
for (var i = 0 ; i < radios.length; i++){
if(radios[i].checked){
//if radio button is checked
userpick = radios[i].value;
}
}
//if they got it right or wrong
var labelStyle = userpick.style.fontWeight;
You put the VALUE of the selected radio button in the userpick variable. The style object is only available on a DOM element. Which is not the value of said element.
If you do: userpick = radios[i]; instead, it will work.
There are a few problems.
var labelStyle = usepick.style.fontWeight;
fontWeight is a string type.
However, later, you try labelStyle.color = "green"
The color property doesn't exist in a string.
However, worse than that userpick is a string itself!
This is because userpick = radios[i].value - value is a string type.
Most Importantly - you are trying to set fontWeight or color of a radio button - there is no text node in a radio button, so it won't make any visible difference - you need to select the label associated with that button and set THAT font weight and color.
I need to create text box using JavaScript. I coded as below:
<script>
function _(x) {
return document.getElementById(x);
}
function popuptxt() {
var i = _("no_room").value;
for(a = 1; a <= i; a++) {
my_div.innerHTML = my_div.innerHTML + "Room number for " + a + "<br><input type='text' name='mytext'+ i><br>"
}
}
<script>
HTML file:
<input type="text" style="width:200px;" id="no_room" onChange="popuptxt()" required>
<div id="my_div"></div>
It displays number of textbox when I type a number, but I need to clear them when I type another number.
Just reset the content of you block each time :
<script>
function _(x) {
return document.getElementById(x);
}
function popuptxt() {
my_div.innerHTML = "";
var i = _("no_room").value;
for(a = 1; a <= i; a++) {
my_div.innerHTML = my_div.innerHTML + "Room number for " + a + "<br><input type='text' name='mytext'+ i><br>"
}
}
</script>
Just add my_div.innerHTML = ""; before the for loop in popuptxt(). That way it will be cleared each time its called.