Change body background image with jQuery - javascript

I decided to make a function that changes the body background image after every 10 seconds.
function Background()
{
var Background_Stage;
switch(Background_Stage)
{
case 0:
{
$('body').css.('background', '#000 url(../../Styles/Callum_Project1/Images/BACKGROUND_1_TEST.png) no-repeat');
Background_Stage++;
setInterval(function(){Background()},10000);
}
case 1:
{
$('body').css.('background', '#000 url(../../Styles/Callum_Project1/Images/BACKGROUND_2_TEST.png) no-repeat');
Background_Stage++;
setInterval(function(){Background()},10000);
}
case 2:
{
$('body').css.('background', '#000 url(../../Styles/Callum_Project1/Images/BACKGROUND_2_TEST.png) no-repeat');
Background_Stage = 0;//Reset
setInterval(function(){Background()},10000);
}
}
}
However hen I did something like this
<body onload="Background()"></body>
It doesn't seem to do anything, this might be a dumb thing to ask for help with but this is the first I did when I was learning JavaScript, I should say that I used jQuery for most of this.

There's a few problems with your code:
The value of Background_Stage won't persist between calls to Background, and in any case, you never assign a value to Background_Stage.
Use setTimeout rather than setInterval. setTimeout will call the function once at the end of the allotted time. setInterval will keep calling the same function again and again until explicitly cancelled. The way you have it, you'll end up with lots of concurrent setIntervals running.
You don't need the '.' between css and the following parenthesis.
Finally, try not to repeat yourself, meaning that if you find yourself typing out more or less the same statements over and over, then you can probably make the code cleaner. Something like:
(function()
{
var bgCounter = 0,
backgrounds = [
"../../Styles/Callum_Project1/Images/BACKGROUND_1_TEST.png",
"../../Styles/Callum_Project1/Images/BACKGROUND_2_TEST.png",
"../../Styles/Callum_Project1/Images/BACKGROUND_3_TEST.png"
];
function changeBackground()
{
bgCounter = (bgCounter+1) % backgrounds.length;
$('body').css('background', '#000 url('+backgrounds[bgCounter]+') no-repeat');
setTimeout(changeBackground, 10000);
}
changeBackground();
})();
Now changing the background URLs or adding more is a simple job of editing the backgrounds array.

You can also try this:
function Background(){
var imgs = [
"../../Styles/Callum_Project1/Images/BACKGROUND_1_TEST.png",
"../../Styles/Callum_Project1/Images/BACKGROUND_2_TEST.png",
"../../Styles/Callum_Project1/Images/BACKGROUND_3_TEST.png"
],
len = imgs.length,
idx = -1;
setInterval(function(){
idx = (idx+1)%len;
$("body").css("background", "#000 url("+imgs[idx]+")");
}, 10000);
}

Every time you call background, you instantiate a new local variable called Background_Stage with a value of undefined. This doesn't match any of your switch options.
You need to declare the variable outside of your function (so it persists between calls to the function) and give it a starting value.

Your Backgroud_Stage is not initialized
Your setInterval placement will cause very serious problems
There's also invalid syntax.
Overall, your code can be simpler like this:
var Stage = 0;
setInterval(function() {
var bg = '#000 url(../../Styles/Callum_Project1/Images/BACKGROUND_'+(Stage+1)+'_TEST.png) no-repeat';
document.body.style.background = bg;
Stage = ++Stage % 3;
}, 10000);

Related

JavaScript function parameter error

I have this simple slideshow set up and it all works fine if I remove the parameters and add the class and speed manually.
If I use parameters to set the class and speed, it fails. With the first image getting the current class applied and then the dom seems to go crazy.
‘undefined’ pops up a lot although there are no errors in console.
Any help would be appreciated. Thanks
let pos = 0;
window.addEventListener("load", function(event) {
testIt('current', 5000);
});
function testIt(_class, _speed) {
const testPara = document.querySelectorAll('.bg_imgs');
let i;
for(i = 0; i < testPara.length; i++) {
testPara[i].classList.remove(_class);
}
pos++;
if(pos > testPara.length) {pos = 1;}
testPara[pos-1].classList.add(_class);
setTimeout(_class, _speed); }
It looks like you're sending the wrong parameters to setTimeout. It should take the form setTimeout(function, time), but instead, you're passing it what I assume is a string.
setTimeout(function() { testIt(_class, _speed); }, _speed);
should work
SetTimeout takes a function as its first param. If you are trying to delay the recursion try:
setTimeout(() => testIt(_class, _speed), _speed)
Thought window.requestAnimationFrame would be a better solution. More info on animation frame

Using Javascript Varibles Without Calling Functions In Them

I am currently devolving a little slideshow, thing that automatically moves fades in and out the background-images. (opacity as well.)
My issue is that I am trying to use variables to store code to run, as setTimeout is stubborn, and won't run with anything in parentheses in it. (as well I need to use them, or my code will get really messy..ier)
What I currently have is
imgID = 0;
// window.setInterval(nextSLIDE, 1000);
nextSLIDE();
function nextSLIDE( step2 ) {
slideVAR = "slide" + imgID;
window.setTimeout(imgIDchange(), 50);
test2 = window.setTimeout(changeOpacityNINE);
tes5t = window.setTimeout(changeOpacity8, 100); // If you are wondering about the irradical names, that is because I made them all non-unique earlier, and I got lazy, so I made them unique..
test4 = window.setTimeout(changeOpacity7, 200);
test6 = window.setTimeout(changeOpacity6, 300);
tes6t = window.setTimeout(changeOpacity5, 400);
twest = window.setTimeout(changeOpacity4, 500);
testt = window.setTimeout(changeOpacity3, 600);
testyt = window.setTimeout(changeOpacity2, 700);
teswt = window.setTimeout(changeOpacity1, 800);
}
function imgIDchange() {
imgID = imgID + 1;
}
function changeOpacity( opacity ) {
document.getElementById("headerIMG").style.opacity = opacity;
}
var changeOpacityNINE = changeOpacity(0.9);
var changeOpacity8 = changeOpacity(0.8);
var changeOpacity7 = changeOpacity(0.7);
var changeOpacity6 = changeOpacity(0.6);
var changeOpacity5 = changeOpacity(0.5);
var changeOpacity4 = changeOpacity(0.4);
var changeOpacity3 = changeOpacity(0.3);
var changeOpacity2 = changeOpacity(0.2);
var changeOpacity1 = "changeOpacity(0.1);"
var FULL = changeOpacity(1)
And I am looking for a way to make it either
A) Work, and not run the varibles.
B) Or find some sort of other Work around..
If my design is that horrific, and makes your eyes bleed feel free to tell me how I can redo it, but I would rather not redo it all in general. (I am rather lazy..)
If I understand you correctly, you want to call setTimeout with a function and pass arguments to it?
If so, you can simply add the arguments to the end of your setTimeout call. So if you wanted to call
changeOpacity(0.5);
after 1000 ms, then you would use setTimeout like this:
setTimeout(changeOpacity, 1000, 0.5);
With setTimeout, the arguments are as follows:
setTimeout(callback,delay,args);
so you can simply do:
setTimeout(changeOpacity,*DELAY*,0.7); // etc...

Understanding JavaScript setTimeout and setInterval

I need a bit of help understanding and learning how to control these functions to do what I intend for them to do
So basically I'm coming from a Java background and diving into JavaScript with a "Pong game" project. I have managed to get the game running with setInteval calling my main game loop every 20ms, so that's all ok. However I'm trying to implement a "countdown-to-begin-round" type of feature that basically makes a hidden div visible between rounds, sets it's innerHTML = "3" // then "2" then "1" then "GO!".
I initially attempted to do this by putting setTimeout in a 4-iteration for-loop (3,2,1,go) but always only displayed the last iteration. I tried tinkering for a bit but I keep coming back to the feeling that I'm missing a fundamental concept about how the control flows.
I'll post the relevant code from my program, and my question would be basically how is it that I'm writing my code wrong, and what do I need to know about setTimeout and setInterval to be able to fix it up to execute the way I intend it to. I'm interested in learning how to understand and master these calls, so although code examples would be awesome to help me understand and are obviously not unwelcome, but I just want to make it clear that I'm NOT looking for you to just "fix my code". Also, please no jQuery.
The whole program would be a big wall of code, so I'll try to keep it trimmed and relevant:
//this function is called from the html via onclick="initGame();"
function initGame(){
usrScore = 0;
compScore = 0;
isInPlay = true;
//in code not shown here, these objects all have tracking variables
//(xPos, yPos, upperBound, etc) to update the CSS
board = new Board("board");
ball = new Ball("ball");
lPaddle = new LPaddle("lPaddle");
rPaddle = new RPaddle("rPaddle");
renderRate = setInterval(function(){play();}, 20);
}
.
function initNewRound(){
/*
* a bunch of code to reset the pieces and their tracking variables(xPos, etc)
*/
//make my hidden div pop into visibility to display countdown (in center of board)
count = document.getElementById("countdown");
count.style.visibility = "visible";
//*****!!!! Here's my issue !!!!*****//
//somehow i ends up as -1 and that's what is displayed on screen
//nothing else gets displayed except -1
for(var i = 3; i >= 0; i--){
setInterval(function(){transition(i);}, 1000);
}
}
.
//takes initNewRound() for-loop var i and is intended to display 3, 2, 1, GO!
function transition(i){
count.innerHTML = (i === 0) ? "Go" : i;
}
.
//and lastly my main game loop "play()" just for context
function play(){
if(usrScore < 5 && compScore < 5){
isInPlay = true;
checkCollision();
moveBall();
moveRPaddle();
if(goalScored()){
isInPlay = false;
initNewRound();
}
}
}
Thanks a bunch for your advise, I'm pretty new to JavaScript so I really appreciate it.
Expanding on cookie monster's comment, when you use setInterval in a loop, you are queueing up method executions that will run after the base code flow has completed. Rather than queue up multiple setInterval executions, you can queue up a single execution and use a variable closure or global counter to track the current count. In the example below, I used a global variable:
var i = 3 // global counter;
var counterInterval = null; // this will be the id of the interval so we can stop it
function initNewRound() {
// do reset stuff
counterInterval = setInterval(function () { transition() }, 1000); // set interval returns a ID number
}
// we don't need to worry about passing i, because it is global
function transition() {
if (i > 0) {
count.innerHTML = i;
}
else if (i === 0) {
count.innerHTML = "Go!";
}
else {
i = 4; // set it to 4, so we can do i-- as one line
clearInterval(counterInterval); // this stops execution of the interval; we have to specify the id, so you don't kill the main game loop
}
i--;
}
Here is a Fiddle Demo
The problem is in this code:
for(var i = 3; i >= 0; i--){
setInterval(function(){transition(i);}, 1000);
}
When the code runs, it creates a new function 3 times, once for each loop, and then passes that function to setInterval. Each of these new functions refers to the variable i.
When the first new function runs it first looks for a local variable (in it's own scope) called i. When it does not find it, it looks in the enclosing scope, and finds i has the value -1.
In Javascript, variables are lexically scoped; an inner function may access the variables defined in the scope enclosing it. This concept is also known as "closure". This is probably the most confusing aspect of the language to learn, but is incredibly powerful once you understand it.
There is no need to resort to global variables, as you can keep i safely inside the enclosing scope:
function initNewRound(){
var i = 3;
var count = document.getElementById("countdown");
count.style.visibility = "visible";
var interval = setInterval(function(){
//this function can see variables declared by the function that created it
count.innerHTML = i || "Go"; //another good trick
i-=1;
i || clearInterval(interval); //stop the interval when i is 0
},1000);
}
Each call to this function will create a new i, count and interval.

Self-created fadeIn() function not working correctly

I am trying to create the fadeIn() function using Javascript. I am having trouble, when I click the fadeIn button, it does not perform a fadeIn animation, instead I have to click it several times to fadeIn. Would anyone know how I can fix this issue?
jsFiddle
// Created a jQuery like reference
function $(selector) {
if (!(this instanceof $)) return new $(selector); // if new object is not defined, return new object
this.selector = selector; // setting selector attribute
this.node = document.querySelector(this.selector); // finds single element from the DOM
};
var fInFrom = 0, fOutFrom = 10;
$.prototype.fadeIn = function() {
var target = this.node,
newSetting = fInFrom / 10;
// Set Default styles for opacity
target.style.display = 'block';
target.style.opacity = newSetting;
// fadeInFrom will increment by 1
fInFrom++;
var loopTimer = setTimeout('this.fadeIn', 50);
if (fInFrom === 10) {
target.style.opacity = 1;
clearTimeout(loopTimer);
fInFrom = 0;
return false;
}
return this;
}
$('#fadeIn').node.addEventListener('click', function() {
$('#box').fadeIn();
});
This line is your problem:
setTimeout('this.fadeIn', 50)
That will set a timeout to evaluate the expression this.fadeIn in the global scope in approximately 50 milliseconds from the current time. There's two problems with that:
It's in the global scope; this is window, not an instance of $, so this.fadeIn is undefined.
Even if it were resolved correctly, you're only evaluating this.fadeIn; you're not calling it. You would need to use this.fadeIn() for it to do anything. (If you do that with the current code, this will reveal your first problem.)
To solve this, pass not a string but a function that does what you want it to do. You might naïvely do this:
setTimeout(function() {
this.fadeIn();
}, 50);
Unfortunately, while we now have lexical scoping for variables, this in JavaScript is dynamic; we have to work around that. Since we do have lexical scoping for variables, we can utilize that: [try it]
var me = this; // store the current value of this in a variable
var loopTimer = setTimeout(function() {
me.fadeIn();
}, 50);
After that's solved, you might want to look into:
Not using global variables to hold the fade state. Even after that fix, running two fade animations at once on different elements won't work as expected. (Try it.)
Only setting the timeout if you need to; right now, you always set it and then clear it if you don't need it. You might want to only set it if you need it in the first place.

Javascript - Need to use clearInterval outside setInterval function

Basically, what I have is a setInterval inside a function. What I want to do is, control it's behavior from outside.
Here's what I have -
function wheee() {
var i = 1;
slideee = setInterval(function() {
sliderContent.style.marginLeft = margin(i);
if(i < imagesNoOneLess) {
i++;
} else {
i = 0;
}
}, 5000); }
Now, I want to clear the interval from outside the wheee() function. How can I do that?
I also want to run the interval again, from outside. How?
Global variables are not dangerous, but a pretty way of coding it if you only have one slider is to use an object literal to simulate a singleton object.
var Slider= {
slider: null,
Start: function(i) {
this.slider = setInterval(function() {
// Slider code
console.log('running: ' + i);
i++;
}, 1000);
},
Stop: function() {
window.clearTimeout(this.slider);
}
};
Slider.Start(1); // Start the slider
Slider.Stop(); // Stop the slider
Well the way you've got the code now, it'll probably just work, because you didn't declare "slideee" with var.
As long as you somehow export the return value from setInterval() you're OK. You can either make that variable explicitly global (better than having it be implicit), or else have your "wheee" function return the value to its caller.
Set the scope of slideee to be out of wheee.
Use objects in order to keep the global scope clean.

Categories

Resources