Reputation: 1716
I have this JS function, which should check if there is a firstChild on the element, if there isnt a paragraph should be created with the || document.createElement("p"), but i get an error, Cannot read firstChild property of null
EDIT: shouldnt have the "if(element) on the code, i was about ot try something with that, but it was not there when i had the error
function update(element,content,klass) {
var p = element.firstChild || document.createElement("p");
p.textContent = content;
element.appendChild(p);
if(klass) {
p.className = klass;
}
}
complete JS file
var button = document.getElementById("button");
var rainbow = ["red","orange","yellow","green","blue","indigo","violet"];
//// dom references ////
var $question = document.getElementById("question");
var $score = document.getElementById("score");
var $feedback = document.getElementById("feedback");
function update(element,content,klass) {
var p = element.firstChild || document.createElement("p");
p.textContent = content;
element.appendChild(p);
if(klass) {
p.className = klass;
}
}
var score = 0;
var quiz = {
"name": "Super Hero Name Quiz",
"description": "How many super heroes can you name",
"question": "What is the real name of ",
"questions": [
{"question" : "Superman", "answer": "Clarke Kent"},
{"question" : "Batman" , "answer": "Bruce Wayne"},
{"question" : "Wonder Woman", "answer": "Dianna Prince"}
]
}
function play(quiz){
for(var i= 0,question,answer,max=quiz.questions.length;i<max;i++){
question = quiz.questions[i].question;
answer = ask(question);
check(answer,i);
}
gameOver();
}
play(quiz);
function ask(question){
update($question,quiz.question + question)
return prompt("Enter your awnser");
}
function check(answer,index){
if(answer === quiz.questions[index].answer){
update($feedback,"Correct!","right");
score++;
}
else{
update($feedback,"Wrong!","wrong");
}
}
function gameOver(){
update($question,"Game Over, you scored " + score + "points");
}
Html file
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="A quiz game for ninjas">
<meta name="author" content="DAZ">
<title>Quiz Ninja</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<h1>Quiz Ninja!</h1>
<p>Score: <strong id="score">0</strong></p>
</header>
<script src="js/scripts.js"></script>
<section id="question">
<p>Question:</p>
</section>
<section id="feedback">
<p>Feedback</p>
</section>
</body>
</html>
Not sure why i get NULL on $question and $feedback
Upvotes: 0
Views: 993
Reputation: 3577
In javascript, null.someFunction
does not return undefined and instead throws a TypeError: null is not an object (evaluating 'null.someFunction')
. This is because Javascript cannot get properties of nonexistent variables. This is the same with undefined.someFunction
.
The ||
operator returns the first truthy value that it's given, truthy meaning not null
or undefined
or 0
. However, to find their value it must first evaluate them. Because your code tries to get element.firstChild
first, it fails because element is null or undefined. The ||
operator does not get to run if element.firstChild fails.
Instead, you can check if element is defined before using it.
var p;
if(element)
p = element.firstChild || document.createElement("p");
else
p = document.createElement("p");
To condense this down into one line, you can use a ternary operator
var p = element ? element.firstChild : false || document.createElement("p");
Now you'll probably have the error where element
is not defined at
element.appendChild(p);
This is because you removed the if statement in your edit.
Another thing, the Javascript file is loaded and executed the moment it finds the script tag. That means it can't find your sections because they haven't been loaded yet. To fix this, move the script to the bottom after everything it needs before it loads:
<section id="question">
<p>Question:</p>
</section>
<section id="feedback">
<p>Feedback</p>
</section>
<script src="js/scripts.js"></script>
Then, the tags will be loaded and put in the page and the script will be run and find the tags.
Another option to fix this is using Jquery's $(document).ready(function(){})
If you wrap all your code in
$(document).ready(function(){
// your code
});
Jquery will wait for the page to fully load before running your code.
Upvotes: 1
Reputation: 6698
Either $question
or $feedback
is null. Check your markup and make sure that there is an element defined with id='question'
, and an element defined with id='feedback'
.
Also, the logic in your update
function seems a little out of order. You are checking whether your element
is null or not, but doing that after you access one of the element
's properties. This might better serve you:
function update(element,content,klass) {
if(element) {
var p = element.firstChild || document.createElement("p");
element.appendChild(p);
p.textContent = content;
if(klass) {
p.className = klass;
}
}
}
Upvotes: 0