New to javascript and such, trying to create a loop for fading logos using jquery.
I've got it cycling through them just fine. But i tried to make the loop continuous; so that when it reached the last logo it went back to the beginning, by resetting my for-counter to 0 every time it reached the last logo. This resulted in an infinite loop i think that crashed my browser. So i did a quick google and discovered the window.setInterval(...) timer function.
My problem is, now that firing the looping code relies on timing, i can't figure out how to calculate the interval time. For reference here's the code that fades the logos in and out (before trying to loop it):
$(document).ready(function (){
var fadeDuration = 1000;
var timeBetweenFade = 2000;
var totalTimePerChange = fadeDuration + timeBetweenFade;
var totalLogos = $('.logo').length;
var currentLogo;
var i;
for(i = 0; i < totalLogos; i++)
{
currentLogo = "#img" + i;
if(i == 0){
$(currentLogo).fadeIn(fadeDuration).delay(timeBetweenFade).fadeOut(fadeDuration);
}
else{ //general case
$(currentLogo).delay(totalTimePerChange * i).fadeIn(fadeDuration).delay(timeBetweenFade).fadeOut(fadeDuration);
}
}
});
I tried to get the time a complete loop took in a couple of ways:
$(document).ready(function (){
//..declarations..
window.setInterval( function() {
//..FOR LOOP HERE..
}, i*(fadeDuration + timeBetweenFade + fadeDuration));
});
//I also tried..
$(document).ready(function (){
//..declarations..
var timeTakenToLoop;
var startLoopTime;
window.setInterval( function() {
startLoopTime = new Date().getTime();
//...FOR LOOP HERE..
timeTakenToLoop = new Date().getTime() - startLoopTime;
}, timeTakenToLoop);
});
But in both cases I get logos starting to overlap as the function calls timing is wrong. Could someone with a bit more experience suggest what the best approach would be?
Oh and just in case anyone needs it to understand the javascript, here's the html to match..
<div id="img0" class="logo">
<img src="{% static "CSS/Images/phone_icon.gif" %}"/>
</div>
<div id="img1" class="logo">
<img src="{% static "CSS/Images/email_icon.gif" %}"/>
</div>
<div id="img2" class="logo">I can fade too</div>
Simple jQuery approach, no setTimeout and no setInterval.
var loop = function(idx, totalLogos) {
var currentLogo = "#img" + idx;
$(currentLogo)
.delay(currentLogo)
.fadeIn(fadeDuration)
.delay(currentLogo)
.fadeOut(fadeDuration, function(){
loop( (idx + 1) % totalLogos, totalLogos);
});
}
loop(0, $('.logo').length);
See it here.
Related
I'm a beginner in JS, and I can't figure out what's wrong with my attempted slideshow. I understand this may seem like a repeat, and I've found a different, working way, to display a slideshow in JS, but I am simply confused about what is wrong with my code. Every single version of slideshow code I've seen sets all of the image urls in HTML and then hides them and only displays one of them using JS, but why wouldn't mine, with image urls simply set in an array, work?
<img id="sideimg" src="images/image1.jpg" alt="penguin" />
<script>
next();
var next=function(){
for(var i=0;i<3;i++){
var slide=document.getElementById("sideimg");
var slides=["images/image1.jpg","images/image2.jpg","images/image3.jpg"]
slide.src=slides[i];
timeOut();
if(i>=3){
i=0;
};
};
var timeOut=function(){
setTimeout(next,1000);
}
};
</script>
Order of functions is not right in your sample
You also need i to be defined outside the function and there is no need for the for loop
The following works for me in chrome
<img id="sideimg" src="images/image1.jpg" alt="penguin" />
<script>
var i = 0
var timeOut=function(){
setTimeout(next,1000);
}
var next=function(){
var slide=document.getElementById("sideimg");
var slides=["images/image1.jpg","images/image2.jpg","images/image3.jpg"]
slide.src=slides[i];
timeOut();
i++;
if(i>=3){
i=0;
};
};
next();
</script>
We could also define i within next as follows using IIFE (immediately invoked function expression). It is also better to declare slides and slide outside the function that is invoked every interval.
<img id="sideimg" src="images/image1.jpg" alt="penguin" />
<script>
var timeOut=function(){
setTimeout(next,1000);
}
var next=function(){
var i = 0;
var slides=["images/image1.jpg","images/image2.jpg","images/image3.jpg"];
var slide=document.getElementById("sideimg");
return function() {
slide.src=slides[i];
timeOut();
i++;
if(i>=3){
i=0;
};
};
}();
next();
</script>
Try moving the array OUTSIDE of the loop:
var next=function(slides){
var slide=document.getElementById("sideimg");
var slides=["images/image1.jpg","images/image2.jpg","images/image3.jpg"]
for(var i=0;i<3;i++){
slide.src=slides[i];
...
};
Here is another possibility (WARNING: I haven't actually tried it):
How do I add a delay in a JavaScript loop?
<img id="sideimg" src="images/image1.jpg" alt="penguin" />
<script type="text/javascript">
var slides=["images/image1.jpg","images/image2.jpg","images/image3.jpg"]
var slide=document.getElementById("sideimg");
var i = 0;
var loop = function () {
sideimg.src=slides[i]; // Display current image
i++;
if (i >= slides.length)
i = 0;
setTimeout(function () { // call setTimeout when the loop is called
loop(); // .. again which will trigger another
}, 1000)
};
};
</script>
};
I have been trying to loop traffic light images in JavaScript. I'm not sure what to do, can someone give advice.
A slight modification to your code. Here is a working sample.
I removed the dvi.count counter as it creates more confusion, We need to maintain the counters outside the function. I changed the logic to pass around the index of the image in the array starting from 0.
var image = new Array("red.jpg", "redamber.jpg", "green.jpg", "amber.jpg");
var timeout;
function stopIt() {
clearTimeout(timeout);
}
function changeimage (images, index) {
var dvi = document.getElementById(images);
if(image.length <= index)
index = 0;
dvi.src = image[index];
dvi.alt = image[index];
timeout = setTimeout('changeimage("' + images + '",' + (index + 1) + ')', 1000);
}
<body onload="changeimage('changer',0)">
<div>
<img src="t1" alt="test1" id="changer" />
</div>
</body>
I have made 3 changes to your code
Fixed the typeo div.count to dvi.count
Corrected the indenting and braces round the if statement (Not strictly necessary, but makes the code way more readable)
Replaced your nasty use of a string parameter in setTimeout to be a function reference
function changeimage(images){
var dvi=document.getElementById(images);
if(!dvi.count || dvi.count == image.length ){
dvi.count=0;
}
dvi.src=image[dvi.count];
dvi.alt=image[dvi.count];
dvi.count=dvi.count+1;
timeout=setTimeout(function(){
changeimage(images);
},3500);
}
Live example: https://jsfiddle.net/Lofug2hf/1/
FOr some reason my code is not executing properly. i am trying to program a slideshow with javascript. Im using a for loop to pull and populate the src files from a created array and change the pic every 3 seconds. THe page loads and the first pic is present but when the interval occurs the first pic dissapears and nothing falls in its place. What am I doing wrong?
<img name="mainSlide" id="mainSlide" src="images/mainPagePhotos/facebook-20131027-180258.png" alt="">
var mainSlidePics = ("facebook-20131027-180258.png","IMG_9694116683469.jpg","IMG_28452769990897.jpg");
window.onload = setInterval("mainSlide();", 3000);
function mainSlide() {
for(i=0; i<mainSlidePics.length; i++ ) {
document.images.mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
}
}
Have you tried getting the Id first?
var mainSlide = document.getElementById("mainSlide");
mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
also a forloop is a loop that finishes its loops even in one call.
try
var i = 0;
window.onload = setInterval("mainSlide(i);", 3000);
mainSlide(int j){
mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[i];
setInterval("mainSlide(j++);", 3000);
}
First you have to correctly declare the array.
Then you have to move the counter variable outside the function triggered by setInterval.
Then pass the reference of the function to setInterval.
<img name="mainSlide" id="mainSlide" src="images/mainPagePhotos/facebook-20131027-180258.png" alt="">
<script type="text/javascript">
var mainSlidePics = ["facebook-20131027-180258.png","IMG_9694116683469.jpg","IMG_28452769990897.jpg"];
var position = 0;
function changePic() {
position = (position+1) % mainSlidePics.length;
document.images.mainSlide.src = "images/mainPagePhotos/" + mainSlidePics[position];
}
window.onload = function() {
setInterval(changePic, 3000);
};
</script>
Code below (the divs are shaded in my real example, I want to sequentially decrease their opacity to 0 so each disappears, in order.
I tried to doing this without using setTimeout, but all of the divs disappeared simultaneously - its good to know that the part of the code that changes the opacity works, but I cant seem to get them to work sequentially.
When I try to use setTimeout (which I presume I am implementing incorrectly),nothing happens!
Any help would be really appreciated with this, I'm fairly new to JavaScript and haven't touched it in a while and tutorials haven't been able to help me.
<body>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
<div id="div4"></div>
<script type="text/javascript">
// the divs that we want to cycle through are named here.
var divs = ["#div1", "#div2", "#div3", "#div4"];
var divsLength = divs.length;
for (var i = 0; i < divsLength; i++) {
setTimeout(function(){
$(divs[i]).fadeTo(1000, 0, function() {
});
},1500);
};
</script>
</body>
Here's a way you should be able to do this without setTimeout:
function doFade(items, index) {
$(items[index]).fadeTo(1000, 0, function() {
doFade(items, index + 1);
});
}
doFade(divs, 0);
If you're targetting browsers that support ES5 (most modern versions do), then you can further simplify doFade:
function doFade(items, index) {
$(items[index]).fadeTo(1000, 0, doFade.bind(this, items, index + 1));
}
working jsfiddle
You can use a recursive function to do that kind of thing, something like that :
function seqFade($el){
$el.first().fadeOut(500, function(){ //Take the first element and fade it out
seqFade($el.slice(1)); //Recall the function when complete with the same set of element minus the first one.
})
}
seqFade($('div')); //Call the function
http://jsfiddle.net/L2fvdfy2/
In your code, it could look like that :
function seqFade($el){
$el.first().fadeOut(500, function(){
seqFade($el.slice(1));
})
}
seqFade($('#div1, #div2, #div3, #div4'));
It's because when the timeout finally fires the variable "i" only has the last index value. Also the loop will start all the timeouts at almost the same time.
There are other ways to accomplish it but this might work with minimal changes to your code.
Try this:
<script type="text/javascript">
var divs = ["#div1", "#div2", "#div3", "#div4"];
var divsLength = divs.length;
for (var i = 0; i < divsLength; i++) {
setTimeout((function(index) {
return function(){
$(divs[index]).fadeTo(1000, 0, function() { });
}
)(i)),1500 + (i * 1500));
};
</script>
</body>
This will create an instance of the function with it's own copy of the index when it was called. Also increasing the timeout of each timeout will have them execute sequentially.
try this:
// the divs that we want to cycle through are named here.
var divs = ["#div1", "#div2", "#div3", "#div4"];
(function fade(i) {
$(divs[i]).fadeTo(1000, 0, function() {
setTimeout(function() {fade(++i);}, 500);
});
})(0);
for (var i = 1; i <= divsLength; i++) {
setTimeout(function(){
$(divs[i]).fadeTo(1000, 0, function() {
});
},1000*i);
lets try this
So far I created an array with 11 images, initialized the counter, created a function, created a for loop but here is where I get lost. I looked at examples and tutorial on the internet and I can see the code is seeming simple but I'm not getting something basic here. I don't actually understand how to call the index for the images. Any suggestions. Here is the code.
<script type="text/javascript">
var hammer=new Array("jackhammer0.gif",
"jackhammer1.gif",
"jackhammer2.gif",
"jackhammer3.gif",
"jackhammer4.gif",
"jackhammer5.gif",
"jackhammer6.gif",
"jackhammer7.gif",
"jackhammer8.gif",
"jackhammer9.gif",
"jackhammer10.gif")
var curHammer=0;
var numImg = 11;
function getHammer() {
for (i = 0; i < hammer.length; i++)
{
if (curHammer < hammer.length - 1) {
curHammer = curHammer +1;
hammer[i] = new Image();
hammer[i].src="poses/jackhammer" +(i+1) + ".gif";
var nextHammer = curHammer + 1;
nextHammer=0;
{
}
}
}
}
setTimeout("getHammer()", 5000);
</script>
</head>
<body onload = "getHammer()";>
<img id="jack" name="jack" src = "poses/jackhammer0.gif" width= "100" height ="113" alt = "Man and Jackhammer" /><br/>
<button id="jack" name="jack" onclick="getHammer()">Press button</button>
Following on what Paul, said, here's an example of what should work:
var hammer=["jackhammer0.gif","jackhammer1.gif","jackhammer2.gif","jackhammer3.gif",
"jackhammer4.gif","jackhammer5.gif","jackhammer6.gif","jackhammer7.gif",
"jackhammer8.gif","jackhammer9.gif","jackhammer10.gif"];
var curHammer=0;
function getHammer() {
if (curHammer < hammer.length) {
document.getElementById("jack").src= "poses/" + hammer[curHammer];
curHammer = curHammer + 1;
}
}
setTimeout("getHammer()", 5000);
The big missing element is that you need to call getElementById("jack") to get a reference to the DOM Image so that you can change it's source. If you're using jQuery or most other JS frameworks, just type $("#jack") to accomplish the same.
I don't understand the need for the for loop at all, just increment the index value [curHammer] each time you click, and reset if it passes your max index length (in this case 11).
Pseudo-Code:
currentHammer = -1
hammers = [ "a1.jpg", "a2.jpg", "a3.jpg"]
getHammer()
{
currentHammer = currentHammer + 1;
if(currentHammer > 2)
currentHammer = 0;
image.src = hammers[currentHammer];
}
a) are you just trying to show an animated gif? If so, why not use Adobe's Fireworks and merge all those gifs into a single gif?
b) you know that the way you have it the display is going to go crazy overwriting the gif in a circle right?
c) you might want to put a delay (or not). If so, make the load new gif a separate function and set a timeout to it (or an interval).
Also, you are being redundant. How about just changing the src for the image being displayed?:
var jackHammer = new Array();
for (var i=0;i<11;i++) { //pre-loading the images
jackHammer[i] = new image();
jackHammer[i].src = '/poses/jackHammer'+i.toString()+'.gif';
} //remember that "poses" without the "/" will only work if that folder is under the current called page.
for (var i=0;i<11;i++) { //updating the image on
document.getElementById('jhPoses').src = jackHammer[i].src;
}
on the document itself,
< img id='jhPoses' src='1-pixel-transparent.gif' width='x' height='y' alt='poses' border='0' />