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
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.
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;
}
}
}
Related
I know that the <script> element can have function show(shown, hidden) on it. but with the 2 pages ({document.getElementById(shown).style.display='block'; document.getElementById(hidden).style.display='none'; return false;) in that, I can't figure out how to make that page count more. Any help?
P.S. I am open to almost anything. I can't guarantee your answers will help, but I might be able to figure it out using your suggestions.
I have tried more things on the function show(shown, hidden, hidden, hidden) but that does not help.
I am stuck. I have researched anything I could find. I can't figure it out.
Please help me.
My specific code I want suggestions on is this:
<script>
function show(shown, hidden) {
document.getElementById(shown).style.display='block';
document.getElementById(hidden).style.display='none';
return false;
}
</script>
with some <div>s.
I know this is probably not helping you figure out how to help me, but I need to know. (I hate full-on JavaScript!)
<!doctype html>
<html lang="en">
<head>
<title>Multi but Single Page</title>
<meta charset="utf-8">
<style>
.templates {
display: none;
}
</style>
<script>
// we save all templates in an global Variable
var templateStack = [];
// https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
function getParameterByName(name, url) {
url = url || window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
window.addEventListener('load', function (e) {
// get all hidden template elements
var templates = document.getElementsByClassName('templates');
for (var i = 0, v; v = templates[i]; i++) {
// each Child Node is a new Page
for (var j = 0, x; x = v.childNodes[j]; j++) {
// at least if it's an element
if (x.nodeType === Node.ELEMENT_NODE) {
templateStack.push(x);
}
}
}
// uri support ?page=1 loads Page 2 and ?page=0 loads Page 1, default is 0
var pageIndex = getParameterByName('page') || '0';
// so we can test it with a Browser by just insert 'loadPage(1)'
loadPage(pageIndex);
});
function loadPage(index) {
// only valid indexes
if (index >= templateStack.length || index < 0) {
document.body.innerText = '404 Page not found';
return;
}
// clean everything in our page
document.body.innerHTML = '';
// append our fetched Page out of our Global Variable
document.body.appendChild(templateStack[index]);
}
</script>
</head>
<body>
<div class="templates">
<div>
<h3>Page 1</h3>
<p>
Welcome to Page 1
</p>
Load Page 2
</div>
<div>
<h1>Page 2</h1>
<p>
Our Page 2
</p>
Back to Page 1
</div>
</div>
</body>
</html>
I understand that you can use it with 2 pages but when you want to make more pages like 4-5 pages?
First you need an clear function (it will hide all the pages)
In the clear function get the body in dom and get all the childrens then make a foreach loop hiding all of them
Second you need an show function which will use the page as an parameter like "show('page1');" it will first call the clear function and then show the page1
Okay, so I'm trying to create a quiz application for revision purposes that asks a random question from a list of questions, takes a text input as the users answer to the question, and then compares it to the actual answer to the question. The code I have used is:
var keyList = Object.keys(htmlModule);
var ranPropName = keyList[ Math.floor(Math.random()*keyList.length) ];
var pageStart = function() {
document.getElementById("question").innerHTML = htmlModule[ranPropName][0];
document.getElementById("submit").onclick = answerValidation;
};
window.onload = pageStart;
var answerValidation = function(correctAnswer, userAnswer) {
correctAnswer = htmlModule[ranPropName][1];
userAnswer = document.getElementById("submit").value;;
if(userAnswer === correctAnswer) {
document.getElementById("rightWrong").style.backgroundColor = "green";
} else {
document.getElementById("rightWrong").style.backgroundColor = "red";
}
};
The variable htmlModule refers to the object in which the questions and their answers are stored. Each question and answer pair is stored inside an array that is the value of its property, the property simply being a key used to reference each pair e.g. htmlQ1, htmlQ2 etc.
The main problem I seem to be having is that my if statement comparing the actual answer and the user answer won't evaluate to true. I know this because the background colour of the div element rightWrong only ever turns red, even when I've definitely typed in a correct answer at which point it should turn green. My assumption is that either the text input isn't being stored for some reason, or the value of the variable ranPropName that uses Math.random() is changing due to the use of Math.method(), but I'm stuck as to how to remedy either potential problem. Thanks in advance for any replies.
Well, I started to visualize your quiz as you explained.
One thing is need to be changed is that you get userAnswer from the value of an element with Id submit which I assume most probably it's an button tag, so I write a working code sample as follow:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Title Goes Here</title>
</head>
<body>
<input type="text" id="rightWrong" />
<div id="question" />
<button id="submit">Submit</button>
</body>
<script>
var htmlModule = {
'htmlQ1': ['1+1=?', '2'],
'htmlQ2': ['2+2=?', '4']
};
var keyList = Object.keys(htmlModule);
var ranPropName = keyList[ Math.floor(Math.random()*keyList.length) ];
var pageStart = function() {
document.getElementById("question").innerHTML = htmlModule[ranPropName][0];
document.getElementById("submit").onclick = answerValidation;
};
window.onload = pageStart;
var answerValidation = function(correctAnswer, userAnswer) {
correctAnswer = htmlModule[ranPropName][1];
userAnswer = document.getElementById("rightWrong").value;
if(userAnswer === correctAnswer) {
document.getElementById("rightWrong").style.backgroundColor = "green";
} else {
document.getElementById("rightWrong").style.backgroundColor = "red";
}
};
</script>
</html>
Please share your html if you still face problems.
So, I am trying to write a do-while loop statement that prints out the statement of my loop, but my browser isn't printing my text. How can I edit my code to do so?
<!DOCTYPE html>
<html>
<head>
<title>9. Looping Statements in Javascript</title>
</head>
<body>
<h1>9. Looping Statements in Javascript</h1>
<div id="playlist"></div>
<div id="someResult"></div>
<script>
var playlist = [];
playlist[0] = "Willy Wesly";
playlist[1] = "Childish Gambino";
playlist[2] = "Chance The Rapper";
playlist[3] = "Travi$ Scott";
playlist[4] = "Yeezy";
// while
/*
var i = 0;
while (i < playlist.length) {
var element = document.createElement('div');
element.innerHTML = "Now Playing: " + playlist[i];
i++;
document.body.appendChild(element);
}
*/
// do - while
var someResult = false;
do {
var element = document.createElement('div');
element.innerHTML = 'Will print AT LEAST once!';
}
while(someResult);
</script>
</body>
</html>
You need to add the element to the document body.
var someResult = false;
do {
var element = document.createElement('div');
element.innerHTML = 'Will print AT LEAST once!';
//You need to add it to the body for it to show on the page
document.body.appendChild( element );
}
while(someResult);
JSFiddle showing this: http://jsfiddle.net/azgxh59q/
I need to fix this segment of code for a class and I have fixed a number of things but I'm not sure why it doesn't work. It is supposed to count the number of vowels in the phrase and return them as an alert. When I click on the button nothing appears.
Here's the html. It works fine but added in case I am missing something
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Vowels</title>
<link rel="stylesheet" href="../css/easy.css">
<script src="p3-vowels.js"></script>
</head>
<body>
<header>
<h1>Count Vowels</h1>
</header>
<main>
<label>Type a phrase here:
<input type='text' id='textBox'></input>
</label>
<button id='countBtn' type='button'>
Count Vowels (a,e,i,o,u)</button>
<div id='outputDiv'></div>
</main>
</body>
</html>
here is the JS. It doesn't seem to register the "on.click" at the end of the code
function countVowels() {
var textBox, phrase, i, pLength, letter, vowelCount;
textBox = document.getElementById('textBox');
phrase = textBox.value;
phrase = phrase.toLowerCase();
vowelCount = 0;
for (i = 0; i < phrase.length; i += 1) {
letter = phrase[i];
if (letter === 'a' || letter === 'e' || letter === 'i' || letter === 'o' || letter === 'u') {
vowelCount++;
}
}
alert(vowelCount + ' vowels');
var outArea = document.getElementById('outputDiv');
outArea.innerHTML = vowelCount + ' vowels in ' + phrase;
}
function init() {
alert('init vowels');
var countTag = document.getElementById('countBtn');
countTag.onclick = countVowels;
}
window.onload = init();
The problem is window.onload = init();, here you are calling init method and is assigning the value returned by init as the onload callback. So when the init method is called the countBtn is not yet added to the dom resulting in an error like Uncaught TypeError: Cannot set property 'onclick' of null.
What you really want is to call init on the load event, so you need to pass the reference to init function to onload
It should be
window.onload = init;
Demo: Fiddle
I'm completely new to javascript and a friend helped me with a problem, I know what it does but I can't really understand some parts, I've made some comments in the code with some questions I hope you can answer them.
<html>
<head>
<title>Uppgift 15</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script>
var resultat = 0;
function addera(){
var t1 = Math.round(object("t1").value);
if (t1 != 0){
resultat += t1;
object("t1").value = "";
}
else{
object("resultat").innerHTML = resultat; // where does "object" come from, what does innerHTML do?
}
}
function object(id){ // i dont get this at all what does this do is there any other way to return?
return document.getElementById(id);
}
</script>
</head>
<body>
<form>
<input id="t1">
<input type="button" onClick=addera() value="resultat">
<p id="resultat"></p>
</form>
</body>
</html>
The object function returns the html element with the specified ID, while innerHtml lets you edit the HTML associated to that element
The object() is already defined in your code, in which document.getElementById(id); will return the element with the specified ID.
The innerHTML property sets or returns the inner HTML of an element.
Here object("resultat").innerHTML = resultat;
Is same as
document.getElementById("resultat").innerHTML = resultat;
the object is returned from your object function your function simply gets element by id from dom and returns it
var resultat = 0;
function addera(){
var t1 = Math.round(object("t1").value);
if (t1 != 0){
resultat += t1;
object("t1").value = "";
}
else{
object("resultat").innerHTML = resultat; // object is returned from object function according to parameter of function the function takes this parameter as id
and selects the element from dom
}
}
function object(id){
return document.getElementById(id);
}