The html variable in my JavaScript code , doesn't display to the screen after my questions loop through the page. I get this error message , TypeError: divOutput is null. After all of my questions loops through
Here is the HTML
<!DOCTYPE html>
<html>
<head>
<title>JavaScript ES2015 Practice</title>
<script type="text/javascript" src="js/output.js"></script>
</head>
<body>
<div id="text">
</div>
</body>
The Javascript code
var quizQuestions;
var quizAnswers;
var correctAnswers;
var wrongAnswers;
var html;
var response;
const questions = [
{
question:"What is the captial of Georgia [type quit to quit]",
answer:"atlanta"
},
{
question:"What is the captial of New York [type quit to quit]",
answer:"albany"
},
{
question:"What is the captial of Texas [type quit to quit]",
answer:"austin"
}
];
const print = (message) =>{
let divOutput = document.getElementById("text");
divOutput.innerHTML = message;
}
for(let i = 0; i < questions.length; i++){
quizQuestions = questions[i].question;
quizAnswers = questions[i].answer;
response = prompt(quizQuestions);
if(response === quizAnswers){
correctAnswers++;
}else{
wrongAnswers++;
}
html = `You got ${correctAnswers} questions right`; //this doesn't display to the screen
} // end of for loop
print(html);
move your script in the onload callback so the script will be executed after
all of the objects in the document are in the DOM, and all the images
and sub-frames have finished loading.
then you can get divOutput
window.onload=function(){
//your script code;
}
the script should be :
window.onload = function () {
var quizQuestions;
var quizAnswers;
var correctAnswers = 0;
var wrongAnswers = 0;
var html;
var response;
const questions = [
{
question: "What is the captial of Georgia [type quit to quit]",
answer: "atlanta"
},
{
question: "What is the captial of New York [type quit to quit]",
answer: "albany"
},
{
question: "What is the captial of Texas [type quit to quit]",
answer: "austin"
}
];
const print = (message) => {
let divOutput = document.getElementById("text");
divOutput.innerHTML = message;
}
for (let i = 0; i < questions.length; i++) {
quizQuestions = questions[i].question;
quizAnswers = questions[i].answer;
response = prompt(quizQuestions);
if (response === quizAnswers) {
correctAnswers++;
} else {
wrongAnswers++;
}
html = `You got ${correctAnswers} questions right`; //this doesn't display to the screen
} // end of for loop
print(html);
}
also,i modified this:
var correctAnswers = 0;
var wrongAnswers = 0;
to make it work more legitimately
Related
So I have an area in my js quiz where it displays the question. I would like to know how I can centre that area and put a box around it, to make it look fancy. Would be great if someone can help.
Thanks (code and screenshot of the area I would like to be entered is below).
// This initialises a request to the trivia database API
var xmlhttp = new XMLHttpRequest();
var url = "//opentdb.com/api.php?amount=25&category=21&type=multiple";
var score = 0;
var livesTaken = 0;
var question;
var type;
var correctAnswer;
var incorrect1;
var incorrect2;
var incorrect3;
// This requests the data
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var jsondata = JSON.parse(this.responseText);
getData(jsondata);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
// This function is used to extract the received data
function getData(data) {
// This is the question:
question = data.results[0].question;
// This is the question type eg. multiple choice
type = data.results[0].type;
// This is the correct answer
correctAnswer = data.results[0].correct_answer;
// These are the three incorrect answers
incorrect1 = data.results[0].incorrect_answers[0];
incorrect2 = data.results[0].incorrect_answers[1];
incorrect3 = data.results[0].incorrect_answers[2];
// randomly select answer and other options and place in array
// then display elements from array on the buttons
var randoms = []; // an array to store unique random numbers
var random;
// loop runs four times...
for (i = 0; i < 4; i++) {
// generates a random number between 0 and 3
random = Math.floor(Math.random() * 4);
// checks if random number already in array...
while (randoms.includes(random)) {
// generates another random number
random = Math.floor(Math.random() * 4);
}
// adds random number to array
randoms.push(random);
}
var options = [];
console.log(randoms);
options[randoms[0]] = correctAnswer;
options[randoms[1]] = incorrect1;
options[randoms[2]] = incorrect2;
options[randoms[3]] = incorrect3;
console.log(options);
// This displays the question and answer options
document.getElementById("trivia").innerHTML = question;
for (i = 0; i < options.length; i++) {
let btn = document.createElement("button");
let br = document.createElement("br");
btn.classList.add("trivia-btn"); // We're adding the class here
btn.setAttribute("onclick", `checkAnswer("${options[i]}", this)`);
btn.innerHTML = options[i];
document.getElementById("trivia").append(br, btn); // You can now use the trivia div as a container for the generated button and your br
//document.getElementsByClassName("trivia-btn").disabled = false;
}
}
function checkAnswer(selected, element) {
document.querySelectorAll(".trivia-btn").forEach((e) => {
e.disabled = true
});
console.log("User selected: " + selected);
console.log("The correct answer is: " + correctAnswer);
if (selected == correctAnswer) {
score++;
console.log("You got it right!");
element.style.background = "green";
setTimeout(function () {
getNewQuestion();
}, 2000);
} else {
livesTaken++;
console.log("Sorry, that's incorrect");
element.style.background = "red";
if (livesTaken == 3) {
quizFailed();
} else {
setTimeout(function () {
getNewQuestion();
}, 10);
}
}
console.log(score)
console.log(livesTaken)
}
function getNewQuestion() {
document.getElementById("score").style.display = "block";
document.getElementById("score").style.float = "right";
document.getElementById("trivia").style.float = "left";
document.getElementById("score").style.align = "right";
document.getElementById("score").innerHTML = "score:" + score;
document.getElementById("trivia").style.display = "block";
document.getElementById("endingText").style.display = "none";
// This requests the data
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var jsondata = JSON.parse(this.responseText);
getData(jsondata);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
getNewQuestion()
function quizFailed() {
document.getElementById("endingText").style.display = "block"
document.getElementById("score").style.display = "none"
document.getElementById("trivia").style.display = "none"
document.getElementById("endingText").innerHTML = "You have run out of lives, you scored " + score + " pretty bad ngl" + " <button onClick = getNewQuestion() >click to restart</button>"
score = 0;
livesTaken = 0;
}
document.getElementById("score")
.trivia-btn {
background-color: "blue";
padding: 0.7rem 2rem;
color: black;
margin-top: 0.4rem;
}
<html>
<head>
<link rel="stylesheet" href="Sport.css">
<title>Sport Quiz (Medium)</title>
<meta charset="utf-8" />
<script src="Sport.js"></script>
<div id="trivia"></div>
<div id ="endingText"></div>
<div id ="score"></div>
<div id ="exittext"></div>
</head>
<body>
</body>
</html>
I would like this to be centred in the middle of the page.
Are you trying to achieve something like this?
If that is the case then you could simply change the styling of the trivia div by removing the float and adding text-align: center;. The only thing this would break is the positioning of your score.
That could be solved by adding this styling to the #score div
position: absolute;
top: 10px;
right: 10px;
But without proper context that might clash with other things on your page?
If this is not what you meant, just let me know. :-)
Remove this property document.getElementById("trivia").style.float = "left";
add this property document.getElementById("trivia").style.textAlign = "center";
I am using the p5.js library, and I am working on a speech recognition - text to speech project. Kind of a chatbot.
Input is voice input which becomes a string.
I am outputting the result from a txt file, using a markov chain. Output is a string contained in a div.
My question is:
Is there a way to hide/show the div containing my input/output (.myMessage and .robotMessage) in intervals?
I want the whole screen first showing only the input when I am talking, then input disappears and only output showing, then when the computer voice finishes speaking my input is shown in the screen and so on...
Here some parts of the code, let me know if it is clear enough.
//bot
function setup() {
noCanvas();
//reads and checks into the text file
for (var j = 0; j < names.length; j++) {
var txt = names[j];
for (var i = 0; i <= txt.length - order; i++) {
var gram = txt.substring(i, i + order);
if (i == 0) {
beginnings.push(gram);
}
if (!ngrams[gram]) {
ngrams[gram] = [];
}
ngrams[gram].push(txt.charAt(i + order));
}
}
//voice recognition
let lang = 'en-US';
let speechRec = new p5.SpeechRec(lang, gotSpeech);
let continuous = true;
let interim = false;
speechRec.start(continuous, interim);
//text-to-speach
speech = new p5.Speech();
speech.onLoad = voiceReady;
function voiceReady() {
console.log('voice ready');
}
//input-ouput
function gotSpeech() {
if (speechRec.resultValue) {
var p = createP(speechRec.resultString);
p.class('myMessage');
}
markovIt();
chooseVoice();
speech.speak(answer);
}
}
and
function markovIt() {
var currentGram = random(beginnings);
var result = currentGram;
for (var i = 0; i < 100; i++) {
var possibilities = ngrams[currentGram];
if (!possibilities) {
break;
}
var next = random(possibilities);
result += next;
var len = result.length;
currentGram = result.substring(len - order, len);
}
var answer = result;
window.answer = answer;
var p2 = createP(answer);
p2.class('robotMessage');
}
how the HTML looks
<div class="container">
<div class="myMessage"></div>
<div class="robotMessage"></div>
</div>
Use select() to get a document element by its id, class, or tag name. e.g:
let my_div = select("myMessage");
Change the style of an element by style().
e.g hide:
my_div.style("display", "none");
e.g. show:
my_div.style("display", "block");
See also Toggle Hide and Show
I'm doing the "Learn JavaScript Properly" track on http://javascriptissexy.com/how-to-learn-javascript-properly/.
It took me forever, but I finally figured out how to get to the next question, but the choices don't change.
However, when I hard code the "questionIndex" the question and choices work fine.
Anyway here's my code (I know it's a bit messy, I'm a beginner):
http://jsfiddle.net/utfwae8d/1/
HTML:
<div id="container">
<div id="quiz"></div>
<div id="choices"></div>
<input type="button" value="Next">
</div>
JavaScript:
var allQuestions = [{
question: "Who is the best in the world?",
choices: ["CM Punk", "John Cena", "Daniel Bryan", "Roman Reigns"],
correctAnswer: 0
},
{
question: "Who is the current WWE World Champion?",
choices: ["John Cena", "Brock Lesnar", "Triple H"],
correctAnswer: 1
},
{
question: "Where is Toronto located?",
choices: ["Ontario", "California", "Georgia", "Texas"],
correctAnswer: 0
},
{
question: "What is the largest California city?",
choices: ["Los Angeles", "San Fransico", "San Deigo", "Anahiem"],
correctAnswer: 0
}];
var quiz = document.getElementById('quiz');
var choicesContainer = document.getElementById('choices');
var nextButton = document.querySelector('[type=button]');
var correctAnswers = 0;
var questionIndex = 0;
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
var choicesNum = allQuestions[questionIndex].choices.length;
var correctAnswer = allQuestions[questionIndex].correctAnswer;
var choices;
for (var i = 0; i < choicesNum; i++) {
choices = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choices + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
nextButton.addEventListener('click', function () {
questionIndex++;
quiz.textContent = allQuestions[questionIndex].question;
});
}
showQuiz();
The button's click handler is not updating the answers, it's only updating the question.
I've separated the code into two functions: one that shows the quiz, and one that shows the answers.
var quiz = document.getElementById('quiz');
var choicesContainer = document.getElementById('choices');
var nextButton = document.querySelector('[type=button]');
var questionIndex = 0;
function showAnswers() {
choicesContainer.innerHTML = "";
var choicesNum = allQuestions[questionIndex].choices.length;
for (var i = 0; i < choicesNum; i++) {
var choice = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choice + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
}
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
}
showQuiz();
showAnswers();
nextButton.addEventListener('click', function () {
questionIndex++;
showQuiz();
showAnswers();
});
Your issue is in the eventlistener method. I have modified your code as below and it works.
nextButton.addEventListener('click', function () {
var newChoicesHTML="";
var newChoices;
questionIndex++;
choicesNum = allQuestions[questionIndex].choices.length;
quiz.textContent = allQuestions[questionIndex].question;
for (var i = 0; i < choicesNum; i++) {
newChoices = allQuestions[questionIndex].choices[i];
newChoicesHTML+= "<input type='radio' name='choice'>" + newChoices + "</input></br>";
}
choicesContainer.innerHTML = newChoicesHTML;
});
Basically the issue is on event change you are updating your question but not the answers.
Your showQuiz function is doing 3 things:
setting the question text
setting the answer list
adding an event listener to the button
When the button is clicked, your code updates the question text but doesn't update the answer list. So I pulled adding the event listener out (it only needs to be executed once) and then made the button click call showQuiz again. Also I added a line to blank out the previous choices.
function showQuiz() {
var currentQuestion = allQuestions[questionIndex].question;
quiz.textContent = currentQuestion;
var choicesNum = allQuestions[questionIndex].choices.length;
var correctAnswer = allQuestions[questionIndex].correctAnswer;
var choices;
choicesContainer.innerHTML = '';
for (var i = 0; i < choicesNum; i++) {
choices = allQuestions[questionIndex].choices[i];
choicesHTML = "<input type='radio' name='choice'>" + choices + "</br>";
choicesContainer.innerHTML += choicesHTML;
}
}
nextButton.addEventListener('click', function () {
questionIndex++;
showQuiz();
});
Good Evening,
I am having trouble setting up the onkeyup event. I am trying to get it to fire an objects method when a user enters text into the text field. It does not seem to find the object.
I have cut down on the code and have made the following sample:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script>
var ReportModule = new function () {
function ReportObj(id, title) {
this.id = id;
this.title = title;
this.result = "";
this.empno = "";
this.UpdateEmpno = function (empNo, resultBoxID) {
this.empno = empNo;
$(resultBoxID).update("Result: " + empNo);
};
};
var ReportObjArray = new Array();
var test1 = new ReportObj("box1", "First object");
var test2 = new ReportObj("box2", "Second object");
ReportObjArray.push(test1);
ReportObjArray.push(test2);
this.Initialize = function () {
for (i = 0; i < ReportObjArray.length; i++) {
var container = document.createElement("div");
container.id = ReportObjArray[i].id;
container.textContent = ReportObjArray[i].title;
$('#Container').append(container);
var empnoInput = document.createElement("input");
empnoInput.type = "text";
empnoInput.id = ReportObjArray[i].id + "_Empno";
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
ReportObjArray[i].UpdateEmpno(empnoInput.value,empnoInput.id); // <-------- Undefined here
};
$('#' + ReportObjArray[i].id).append(empnoInput);
var container2 = document.createElement("div");
container2.id = ReportObjArray[i].id + "_result";
container2.style.border = "1px solid black";
container2.style.width = "100px";
container2.textContent = "Result:";
$('#' + container.id).append(container2);
};
};
}
</script>
</head>
<body onload="ReportModule.Initialize()">
<div id="Container"></div>
</body>
</html>
Update: It works when searching for the object in the ReportObjArray and matching the correct object. However, I was wondering if there was a more efficient way instead of having to look through the array each time.
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
var target_id = document.getElementById(event.target.id).id;
for (j = 0; j < ReportObjArray.length; j++) {
if (target_id = ReportObjArray[j].id) {
ReportObjArray[j].UpdateEmpno(document.getElementById(event.target.id).value,empnoInput.id);
break;
}
}
};
Wrap your for loop code in a closure:
for (i = 0; i < ReportObjArray.length; i++) {
(function(i) {
// code
})(i);
}
Working JS Fiddle:
http://jsfiddle.net/23vkS/
My function that lists the question and choices won't work. I keep getting the error code document.getElementById(...) is null or not an object. The syntax appears to be correct.
I want the questions and choices to appear in the same divs. I do not want to list all my questions at once. When the user completes a question, they then move on to the next question which will appear in exactly the same divs as the first question until all the questions have been seen.
<script>
var questions = new Array();
questions[0] = 'Is there a difference between a jungle and a rain forest?'
questions[1] = 'What is the world\'s most common religion?',
questions[2] = 'What is the second largest country (in size) in the world?';
var choices = new Array();
choices[0] = ['No difference', 'Some difference', 'Completely different'],
choices[1] = ['Christianity', 'Buddhism', 'Hinduism', 'Islam'],
choices[2] = ['USA', 'China', 'Canada', 'Russia'];
var answers = new Array();
answers[0] = ['Some difference'],
answers[1] = ['Christianity'],
answers[2] = ['Canada'];
var score = 0;
i= 0;
var listQuestion = function(){
if( i < questions.length ){
document.getElementById("myDiv1").innerHTML = '<p>'+questions[i]+'</p>';
for (k=0; k<choices[i].length; k++){
document.getElementById("myDiv2").innerHTML ='<p><input type = "radio" name = "questionchoice">'+choices[i][k]+'</p>';
}
document.getElementById("myDiv3").innerHTML = '<p><button onClick = "getRadioValue()">Check</button></p> <br>';
};
};
var getRadioValue = function(){
for ( var h = 0; h < document.getElementsByName('questionchoice').length; h++ ){
var value = '';
if (document.getElementsByName('questionchoice')[h].checked==true){
value = document.getElementsByName('questionchoice')[h].value;
score+=1
}
}
if (value== answers[i]){
document.getElementById("myDiv4").innerHTML ="That is correct. </br><button input type = 'submit' onClick = 'loadContent()'> Next Question</button>";
}
else {
document.getElementById("myDiv4").innerHTML ="That is incorrect. </br><button input type = 'submit' onClick = 'loadContent()'> Next Question</button>";
}
i++;
};
var whatIsScore = function(){
return score;
}
window.onload = listQuestion();
</script>
</head>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
<div id="myDiv4"></div>
</body>
Here is the full code:
<!DOCTYPE html>
<html>
<head>
<script>
var questions = new Array();
questions[0] = 'Is there a difference between a jungle and a rain forest?';
questions[1] = 'What is the world\'s most common religion?',
questions[2] = 'What is the second largest country (in size) in the world?';
var choices = new Array();
choices[0] = ['No difference', 'Some difference', 'Completely different'],
choices[1] = ['Christianity', 'Buddhism', 'Hinduism', 'Islam'],
choices[2] = ['USA', 'China', 'Canada', 'Russia'];
var answers = new Array();
answers[0] = ['Some difference'],
answers[1] = ['Christianity'],
answers[2] = ['Canada'];
var score = 0;
i= 0;
var listQuestion = function(){
if(i<questions.length){
document.getElementById("myDiv1").innerHTML = '<p>'+questions[i]+'</p>';
var choicesOutput=[];//new Array()
for (var k=0; k<choices[i].length; k++){
choicesOutput.push(
'<p><input type = "radio" name ='
+' "questionchoice">'+choices[i][k]+'</p>');
}
document.getElementById("myDiv2").innerHTML =choicesOutput.join("");
document.getElementById("myDiv3").innerHTML =
'<p><button onClick = "getRadioValue()">Check</button></p> <br>';
}
};
var getRadioValue = function(){
var value = '';
for (var h = 0;
h < document.getElementsByName('questionchoice').length; h++){
if (document.getElementsByName('questionchoice')[h]
.checked==true){
value = document.getElementsByName('questionchoice')[h].value;
score++;
}
}
if (value== answers[i]){
document.getElementById("myDiv4").innerHTML =
"That is correct. </br><button input type = "
+"'submit' onClick = 'loadContent()'> Next Question</button>";
}
else {
document.getElementById("myDiv4").innerHTML ="That is incorrect. "
+"</br><button input type = 'submit' onClick = 'loadContent()'> N"
+"ext Question</button>";
}
i++;
};
var whatIsScore = function(){
return score;
};
function loadContent(){
document.getElementById("myDiv4").innerHTML="";
listQuestion();
}
window.onload = listQuestion;
</script>
</head>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
<div id="myDiv3"></div>
<div id="myDiv4"></div>
</body>
</html>