I am trying to show a random div with setinterval() - javascript

I am getting - Uncaught TypeError: Cannot read property 'style' of null
when I try to run the following:
<script type="text/javascript">
function startRotation() {
setInterval(resetAllDivs(), 20000);
}
function resetAllDivs(){
var i;
for(i=1; i<=15; i++) {
document.getElementById("img"+i).style.display = "none";
}
displayRandom();
}
function displayRandom(){
var n=Math.round(Math.random()*3)
document.getElementById("img"+n).style.display = "block";
document.getElementById("img"+n).style.width = "64%";
}
</script>
I am calling startRotation() above my closing using:
document.addEventListener('DOMContentLoaded',function(){startRotation()});
The error points to the line:
document.getElementById("img"+i).style.display = "none";
Any ideas?

A few things to note, some of them have be pointed out in the comments already, but I'll reiterate.
setInterval expects a function reference as its first parameter, you're passing in the return result of a call to resetAllDivs(), which is undefined. Really you've got
setInterval(undefined, 20000);
which won't work. You want
setInterval(resetAllDivs, 20000);
Next, this line will get you a random number between 0 - 3, which I don't think is what you were after. It's why you sometimes you'll try document.getElementById('img0'), which returns null.
Math.round(Math.random()*3)
Instead, this will get you a number between 1 - 15:
Math.floor((Math.random() * 15) + 1);
Here is a working example. Timing reduced to half a second instead of 20.
DEMO
function startRotation() {
resetAllDivs();
setInterval(resetAllDivs, 500);
}
function resetAllDivs(){
for (var i = 1; i <= 15; i++) {
document.getElementById("img" + i).style.display = "none";
}
displayRandom();
}
function displayRandom(){
var n = Math.floor((Math.random() * 15) + 1);
document.getElementById("img" + n).style.display = "block";
document.getElementById("img" + n).style.width = "64%";
}
startRotation();
div {
width: 50px;
height: 50px;
background-color: red;
}
div:nth-child(even) {
background-color: blue;
}
<div id="img1"></div>
<div id="img2"></div>
<div id="img3"></div>
<div id="img4"></div>
<div id="img5"></div>
<div id="img6"></div>
<div id="img7"></div>
<div id="img8"></div>
<div id="img9"></div>
<div id="img10"></div>
<div id="img11"></div>
<div id="img12"></div>
<div id="img13"></div>
<div id="img14"></div>
<div id="img15"></div>
This code could definitely be refactored into something smarter. I'd also advise using setTimeout over setInterval, as you gain more control.

One of your document.getElementById("img"+i) is returning a null value, wich means that the element doesn't exist or wasn't created before your resetAllDvis() functions runs.
You should use:
Math.floor((Math.random() * 15) + 1);
to return a random number between 1 and 15.
Make sure you have images with id's from id="img1" to id="img15".

Related

How do I see the console.log in this code?

var hexBeat;
function clarity() {
setInterval(function() {
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
hexBeat = randomNumber(1, 25);
console.log(hexBeat);
}
}, 1000)
}
while (hexBeat <= 20) {
document.querySelector("#nachoCheddar01").style.backgroundColor = "green";
document.querySelector("#nachoCheddar01").style.left = "200px";
}
<html>
<body>
<button onClick="clarity()" style="z-index:1">click for random number in console</button>
<div id="nachoCheddar01" style="z-index: -1; box-sizing:border-box;border:3px solid green;background-color: blue;position:absolute;top:1%;height:100px;width:200px;">NachoCheddar01</div>
<div id="nachoCheddar02" style="">NachoCheddar02</div>
<div id="nachoCheddar03" style="">NachoCheddar03</div>
<div id="nachoCheddar04" style="">NachoCheddar04</div>
</body>
</html>
I am trying to log hexBeat, then based on that I would like to move the rectangle to the right on the screen every time there is a random number less than or equal to 20, and also change its color. But right now I'm failing to get the console.log(hexBeat)
I tried declaring the variable outside of any function. I'm trying to use that variable, hexBeat inside another function, and I have had success declaring my variables like that. Although, I'm using intervals, and I'm not sure if there is a better way to approach moving the rectangle every time there is a random number less than or equal to 20.
You can update your code like this:
HTML:
<html>
<body>
<button onClick="clarity()" style="z-index:1">click for random number in console</button>
<div class="wrapper">
<div id="nachoCheddar01" style="z-index: -1; box-sizing:border-box;border:3px solid green;background-color: blue;position:absolute;top:1%;height:100px;width:200px;">NachoCheddar01</div>
<div id="nachoCheddar02" style="">NachoCheddar02</div>
<div id="nachoCheddar03" style="">NachoCheddar03</div>
<div id="nachoCheddar04" style="">NachoCheddar04</div>
</div>
</body>
</html>
CSS:
.wrapper {
position: relative;
}
#nachoCheddar01 {
position: absolute;
}
JAVASCRIPT:
var hexBeat;
function clarity() {
setInterval(function() {
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
hexBeat = randomNumber(1, 25);
if (hexBeat <= 20) {
console.log(hexBeat);
document.querySelector("#nachoCheddar01").style.backgroundColor = "green";
document.querySelector("#nachoCheddar01").style.left = `${document.querySelector("#nachoCheddar01").offsetLeft + 200}px`;
}
}, 1000)
}

Using setTimeout in a for loop

Why does setTimeout not work inside a for loop? I'm trying to have a class added to each frame one at a time and every three seconds I need to remove it from the current one and add it to the next. When It gets to frame-6 I need it to wait ten seconds before removing the class. Then I need it all to repeat. But its just adding the class to them all straight away and then not removing them.
for(i = 1; i < 6; i++){
jQuery('.frame-'+i).addClass('color');
if(i < 6){
setTimeout(function(){
jQuery('.frame-'+i).removeClass('color');
}, 3000);
}else if(i = 6){
setTimeout(function(){
jQuery('.frame-'+i).removeClass('color');
i = 1;
}, 10000);
}
}
.color{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="frame-1">one</div>
<div class="frame-2">two</div>
<div class="frame-3">three</div>
<div class="frame-4">four</div>
<div class="frame-5">five</div>
<div class="frame-6">six</div>
There are 2 issues with your code. Firstly, you're expecting the timeouts to execute before the next one is created, which is wrong. You're creating them all at the same time. Secondly, you're reusing the i variable inside the timeouts, so when they fire it's 6, for all of them.
However, you can make a recursive function to handle all of this, like this...
function timeoutHandler(i) {
// if no value is passed, set i = 1
if (!i) i = 1;
// if i < 6 then create a setTimeout for 3 seconds
// when we remove the class and call the function again with i + 1
if (i < 6) {
setTimeout(function() {
$(".frame-" + i).removeClass("color");
timeoutHandler(++i);
}, 3000);
}
// else (i == 6) setTimeout for 10 seconds
// when we remove the class and stop
else {
setTimeout(function() {
$(".frame-" + i).removeClass("color");
}, 10000);
}
}
// add class to initialise - should really do this in html
for(i = 1; i < 7; i++) {
$(".frame-" + i).addClass("color");
}
// start
timeoutHandler();
.color{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="frame-1">one</div>
<div class="frame-2">two</div>
<div class="frame-3">three</div>
<div class="frame-4">four</div>
<div class="frame-5">five</div>
<div class="frame-6">six</div>

Looping Arrays to Change Background Image of Div

I am trying to create a loop of an array that changes the background of a div only one single loop. The code is as follows;
var ImagesF = [];
ImagesF[0]="images/image1.png";
ImagesF[1]="images/image2.png";
ImagesF[2]="images/image3.png";
var i = 1;
var index = 0;
var iterations = 0;
var interval = setInterval(autoImgB(), 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [i] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
The code is being called like, onclick="autoImgB(ImagesF, 'DIV')"It seems to be trying to work and it does change the first image, however then it doesn't seem to be passing the arguments to the next iteration, what am I doing wrong?
-- UPDATE --
I have attempted to add the following code to pass the argument as originally passed during the function call autoImgB(ImagesF, 'DIV'), however I get an error that states, "arr1 is undefined".
var index = 0;
var iterations = 0;
var interval = setInterval(function() {
autoImgB(arr1, id);
}, 2000);
function autoImgB(arr1, id){
var url = 'url(' + arr1 [index] + ')';
if(index >= arr1.length) {
index = 0;
iterations++;
}
document.getElementById(id).style.backgroundImage = url;
if (iterations >= 2) {
clearInterval(interval);
} else {index++}
}
-- UPDATE 2 --
#Andy, requested that I post my nested DIV's for further help, the DIV structure within the contain are as depicted;
var ImagesF = [];
ImagesF[0]="image1.png";
ImagesF[1]="image2.png";
ImagesF[2]="image3.png";
var n = 0;
function autoImgB(arr1) {
var url = 'url(' + arr1 [n] + ')';
if (n < arr1.length) {
document.getElementById('DIV3').style.backgroundImage = url;
setTimeout(autoImgB, 2000, arr1, ++n);
console.log(url,n)
}
}
.DIV1{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 2;
}
.DIV2{
position:absolute;
top: 0px;
left: 0px;
width:100%;
height:100%;
background-image:url('');
background-color: none;
display: none;
z-index: 1;
}
.DIV3{
position:absolute;
top: 40px;
left: 417px;
width:105px;
height:130px;
background-image:url('');
background-color: none;
display: block;
z-index: 2;
}
<div class="holder">
<div class="DIV1" id="DIV1"></div>
<div class="DIV2" id="DIV2"></div>
<div class="DIV3" id="DIV3"></div>
</div>
<button style="cursor:pointer" onclick="autoImgB(ImagesF)">Press</button>
What I would like for this to do is be able to call it by ID within the function, eg: autoImgB(ImagesF, 'DIV3').
OK. So the main issue is that you are calling the function immediately rather than passing a reference to the function to setInterval.
var interval = setInterval(autoImgB, 2000);
The other problem is that you aren't passing any arguments to the function. There are two ways to do that. The first is to pass them as additional arguments after the time:
var interval = setInterval(autoImgB, 2000, ImagesF, 0);
The second is to call the function itself within the setInterval callback:
var interval = setInterval(function () {
autoImgB(ImagesF, 0);
}, 2000);
The other issue is that it's not clear what your HTML looks like. You appear to be getting an element with a particular id but are passing in div as the argument. So either you have an element like <div id="div"></div> or something else is going on. You should probably take a closer look at that.
That said you can shorten your code considerably if you use setTimeout instead of setInterval, as you only need to do the minimum of checks, and there's no need to clear the timer at any point. Just check to see if the index is less than the array length and call the function again.
var div = document.querySelector('div');
function autoImgB(arr, i) {
if (i < arr.length) {
div.style.backgroundImage = 'url("' + arr[i] + '")';
setTimeout(autoImgB, 2000, arr, ++i);
}
}
autoImgB(ImagesF, 0);
Here's some working code with setTimeout.
setInterval expects a function as its first parameter
var interval = setInterval(function() {
autoImgB(ImagesF, 'DIV');
}, 2000);
The only thing which is wrong in the code you've created is that you pass the return value of the autoImgB function which is undefined into the setInterval function, but the setInterval function only accepts a function or a code string.
Documentation for setInterval
I've created a example based on your code to show you how it'll work.

Cannot set property innerHTML of null on appended child (div)

Before I learn some Unity I wanted to be able to create a simple Javascript game out of my own knowledge. So, I started experimenting with a timer and it worked. Then I wanted to add a div element to my HTML document and have its text change in response to the timer. So I wrote this code:
var counter = 0;
var seconds = 0;
$(document).ready(function(e) {
var element = document.createElement("div");
element.id = "text2";
document.getElementById("canvas").appendChild(element);
function gameActions() {
document.getElementById("canvas").innerHTML = seconds;
if (seconds == 1) document.getElementById("text2").innerHTML = "second";
else document.getElementById("text2").innerHTML = "seconds";
counter++;
if (counter % 50 == 0) {
seconds++;
}
}
setInterval(gameActions, 20);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="canvas" class="imgcenter" style="width: 500px; height: 400px; background-color: #eeffee;">
</div>
Basically I'm intending to change the text of the "parent" div which displays the number of seconds passed after the html page is fully loaded. But before that, I'm trying to create a div with id text2 to add it inside the div parent.This div should display the word "seconds" depending on the time (basically display "second" when the seconds variable is 1, and "seconds" when not)
Where "imgcenter" is only CSS to specify auto margin. The error is that, whenever I run this on Chrome, I get:
Uncaught TypeError: Cannot set property 'innerHTML' of null
Am I correct to assume the div is not being added? Am I missing a step in the addition? Please let me know what you think the error is, thank you
This code:
var element = document.createElement("div");
element.id = "text2";
document.getElementById("canvas").appendChild(element);
… puts the element you are trying to target inside the canvas div.
This code:
document.getElementById("canvas").innerHTML = seconds;
… destroys everything in that element and replaces it with the HTML in the seconds variable.
Am I correct to assume the div is not being added?
No. The div is added, but then you destroy it before trying to do anything with it.
In your line document.getElementById("canvas").innerHTML = seconds; you are replacing your complete innterHTML of canvas. By that your element text2 is removed again.
If you want to show the unit independently from the seconds in it's own element, you should create an element unitfor example like this:
var counter = 0;
var seconds = 0;
$(document).ready(function (e) {
var element = document.createElement("div");
var unit = document.createElement("div"); // create a second element unit
element.id = "text2";
unit.id = "unit"; // asign the id unit
document.getElementById("canvas").appendChild(element);
document.getElementById("canvas").appendChild(unit);
function gameActions() {
document.getElementById("unit").innerHTML = seconds; // replace the unit with the valuen of seconds
if (seconds == 1) document.getElementById("text2").innerHTML = "second";
else document.getElementById("text2").innerHTML = "seconds";
counter++;
if(counter % 50 == 0) {
seconds++;
}
}
setInterval(gameActions, 20);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="canvas" class="imgcenter" style="width: 500px; height: 400px; background-color: #eeffee;">
</div>
You are removing the element you added when you replace the inner HTML of the canvas. It would be better if you just updated the entire contents with the entire string instead of creating a separate element. I would also wrap it in an IIFE so that the variables don't leak into the global scope.
(function () {
var counter = 0;
var seconds = 0;
var canvas = document.getElementById("canvas");
function gameActions() {
canvas.innerHTML = seconds + " second" + (seconds > 1 ? "s" : "");
counter++;
if (counter % 50 == 0) {
seconds++;
}
}
$(function() {
setInterval(gameActions, 20);
});
})();
http://jsfiddle.net/1unn153b/

jQuery when data reach 0 alert

I have this code:
jQuery/JavaScript
$(document).ready(function () {
function min() {
var number = parseInt($('span').html());
return number - 30;
}
function add() {
var number = parseInt($('span').html());
return number + 31;
}
$("#container").click(function () {
$('span').text(min());
});
$("#box").click(function () {
$('span').text(add());
});
var time = parseInt($('b').html());
if (time <= 0) {
alert("AAAAA");
};
});
CSS
#container{
background: #00ff00;
width: 500px;
height:500px;
}
#box{
background: black;
width: 100px;
height:100px;
color: white;
cursor: pointer;
}
HTML
<div id="container">
<span> 60 </span>
<div id="box"> </div>
</div>
when you click on you text in change for +31 and -30 so you will got 61 because default is 60 and but if you click on text in span will change for -30 only and it will display 30 i wish to alert when text in span reach 0 i made this but didn't work.
does any one know how to fix it?
I think that I'm not understanding completely to you. Maybe this the next link can help you.
You have some errors, check the solution.
$(document).ready(function(){
var $span = $('span');
function min() {
var number = parseInt($span.html());
return number - 30;
}
function add() {
var number = parseInt($span.html());
return number + 31;
}
$("#container").click(function(){
$('span').text(min());
checkTime();
});
$("#box").click(function(){
$('span').text(add());
checkTime();
});
function checkTime() {
debugger
var time = parseInt($span.html());
if (time <= 0) {
alert("AAAAA");
};
}
});
Please next time publish your problem in JSfiddle or similar.
I think you're selector to get the span is incorrect. You also need to execute the check after you decrement the value.
$(document).ready(function(){
function min() {
var number = parseInt($('span').html());
return number - 30;
}
function add() {
var number = parseInt($('span').html());
return number + 31;
}
$("#container").click(function(){
$('span').text(min());
CheckValue();
});
$("#box").click(function(){
$('span').text(add());
});
function CheckValue() {
var val = parseInt($('#container > span').html());
if (val <= 0) {
alert("AAAAA");
}
}
);

Categories