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);
}
Related
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;
}
}
}
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.
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 trying to get the image to change based on one second timer, but the image stays one the first object in the array
the code I have so far is
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Lab 8 - Jackhammer Man</title>
<script type="text/javascript">
var jackhammers = new Array();
jackhammers[0] = "<img src='Images/jackhammer0.gif'>";
jackhammers[1] = "<img src='Images/jackhammer1.gif'>";
jackhammers[2] = "<img src='Images/jackhammer2.gif'>";
jackhammers[3] = "<img src='Images/jackhammer2.gif'>";
jackhammers[4] = "<img src='Images/jackhammer4.gif'>";
jackhammers[5] = "<img src='Images/jackhammer5.gif'>";
jackhammers[6] = "<img src='Images/jackhammer6.gif'>";
jackhammers[7] = "<img src='Images/jackhammer7.gif'>";
jackhammers[8] = "<img src='Images/jackhammer8.gif'>";
jackhammers[9] = "<img src='Images/jackhammer9.gif'>";
jackhammers[10] = "<img src='Images/jackhammer10.gif'>";
var curJackhammer;
function bounce() {
var img = document.getElementsByTagName("img");
var i = 0 ;
for (i = 0; i<10;i++) {
if(jackhammers[i].src == img.src) {
if(i === jackkhammers.length) {
img.src = jackhammers[0].src;
break;
}
img.src = jackhammers[i+1].src;
break;
}
}
}
</script>
</head>
<body>
<img onMouseOver="setInterval(function(){bounce},1000);" onMouseOut="clearInternval(fuction(){bounce};" src="Images/jackhammer0.gif" id="hammer" name="hammerman" alt="Jackhammer Man">
</body>
</html>
The issue I'm coming across is the mouseover event will not activate, I am having trouble finding the error in my code as the debuggers I have aren't finding any. Any help trying to get the mouseover function of the image changing ever so often would be appreciated.
you have a typo if(i === jackkhammers.length)
jackhammers[x] has no src property so to get its value use it without .src
instead of
onMouseOver="setInterval(function(){bounce},1000);"
write:
onMouseOver="setInterval(function(){bounce();},1000);"
var img = document.getElementsByTagName("img");
This returns a NodeList, or an array of elements. You need to access the index of this element with [0]
Or better yet, use querySelector which returns the first element in a NodeList
You keep referring to the src property of items in the jackhammers array:
img.src = jackhammers[0].src;
even though items in that array are strings, not objects.
Also, there's a typo here:
if(i === jackkhammers.length) {
These kinds of errors would be immediately visible the with dev tools of your browser of choise. Put a breakpoint to where you suspect things go wrong and start investigating variables and your assumptions while stepping through the code.
See here: http://www.creativebloq.com/javascript/javascript-debugging-beginners-3122820
Updated code changed a few things around based on some advice from my mentor.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Lab 8 - Jackhammer Man</title>
<script type="text/javascript">
var jackhammers = new Array(11);
jackhammers[0] = "Images/jackhammer0.gif";
jackhammers[1] = "Images/jackhammer1.gif";
jackhammers[2] = "Images/jackhammer2.gif";
jackhammers[3] = "Images/jackhammer3.gif";
jackhammers[4] = "Images/jackhammer4.gif";
jackhammers[5] = "Images/jackhammer5.gif";
jackhammers[6] = "Images/jackhammer6.gif";
jackhammers[7] = "Images/jackhammer7.gif";
jackhammers[8] = "Images/jackhammer8.gif";
jackhammers[9] = "Images/jackhammer9.gif";
jackhammers[10] = "Images/jackhammer10.gif";
var curJackhammer = 0;
var direction;
var begin;
function bounce(){
if(curJackhammer == 10)
curJackhammer = 0;
else
++curJackhammer;
document.getElementsByTagName("img")[0].src = jackhammers[curJackhammer].src;
if(curJackhammer == 0)
direction = "up";
else if(curJackhammer == 10)
direction = "down";
document.getElementsByTagName("img")[0].src = jackhammers[curJackhammer];
}
function startBouncing(){
if (begin)
clearInterval (begin);
begin = setInterval("bounce()",90);
}
</script>
</head>
<body>
<h1>Jackhammer Man</h1>
<p><img onMouseOver="startBouncing();" onMouseOut="clearInterval(begin);" src="Images/jackhammer0.gif" height="113" width="100" alt="Image of a man with a jackhammer." /></p>
</body>
</html>
>
Used firebug to step into code, works once I set into it but simply putting a mouse over nothing happens.
I need some help because my callback function, parseMovie() is only being called once! Despite being in a for loop which iterates it twice. I am using a free Rottentomatoes API
The output only returns one ID, and not two ID's!
And runs parseMovie() only once and returns the movie ID with the last movie.
Does anyone have a fix for this script running problem?
HTML CODE
<!doctype html>
<html class="no-js">
<head>
<title>Movies</title>
<link rel="stylesheet" href="css/main.css">
<script src="js/main.js"></script>
</head>
<body>
<form name="input">
<p> Actor/Actress Name: <input type="text" name="fullName"> </p>
<p> Movie 1 <input type="text" name="movie"> </p>
<p> Movie 2 <input type="text" name="movie"> </p>
<p><input type="button" value="Search movies" onclick="getMovies()"></p>
<p><textarea name="output" readonly> </textarea> </p>
</form>
</body>
</html>
JAVASCRIPT
//api key
var APIKEY = "qf54ubt95fea9n7jytr5xh6h";
var movieID = new Array();
var actor = new Array();
var actorName = "Jennifer Lawrence";
var movieTitle;
var output;
function callScript(call) {
var script = document.createElement('script');
script.setAttribute("src", call);
document.body.appendChild(script);
}
function getMovies() {
for (var x=0; x<2; x++) {
movieTitle = document.getElementsByName('movie')[x].value;
movieTitle= cleanMovieTitle(movieTitle);
var movieURL = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=";
callScript(movieURL + movieTitle + "&page_limit=10&page=1&apikey=" + APIKEY + "&callback=parseMovie");
}
}
function cleanMovieTitle(movie) {
movie = movie.trim();
movie = movie.replace(/ /g, "+");
return movie;
}
function parseMovie(data) {
var titleData = data.movies;
for (var t=0; t<titleData.length; t++) {
movieID[movieID.length] = titleData[t].id;
aCast = titleData[t].abridged_cast;
sample = [];
for (var person = 0; person < aCast.length; person++) {
sample[sample.length] = aCast[person].name;
}
actor[actor.length] = sample;
}
for (var arry = 0; arry < actor.length; arry++) {
if (actor[arry].indexOf(actorName) >= 0) {
output = movieID[arry];
break;
} else {
alert("spelling error of some sort! Error 404");
}
}
document.input.output.value = output;
}
Your statement var titleData = data.movies; is wrong, because the data returned by the API contains an array of movies.
You have to iterate through data.movies to get the data for the other movies (and not only the first one).
See the raw JS code and JSON data returned by the API: api.rottentomatoes.com
Three things that strike me as odd that might be causing the problem.
Using for…in for an array is considered bad practice, especially when there's a native forEach method and a polyfill for ie8-
cleanMovieTitle isn't doing anything because it doesn't return a value. If you were passing it an array or object, it would pass by reference and it would be altered, but that is considered bad practice for the exact reason that it's not working. You're passing a value, the function modifies that value within the function's scope, then does nothing with it. You need to return the string and set movieTitle = cleanMovieTitle(movieTitle); So maybe the API isn't returning for one of the titles because it hasn't been cleaned. See Passing by Reference or by Value.
The callback may be is getting called again before it finishes running. Not sure on this one, but you could check by flooding the loop with console.logs and seeing whether it's the case.
Edit
So I just ran your script on this page and I'm getting an error on document.input.output.value = output; As expected, parseMovies runs twice when I remove this line. What's document.input?