issue: image carousel skips 1st image - javascript

I have an automatic image carousel in javascript for my html website. The carousel has 5 images. The carousel works well on the first round, but on the second round of images, the 1st image doesn't appear. I'm not sure why? Please help if you can
<script>
(function(){
var imgLen = document.getElementById('gallery');
var images = imgLen.getElementsByTagName('img');
var counter = 1;
if(counter <= images.length){
setInterval(function(){
images[0].src = images[counter].src;
console.log(images[counter].src);
counter++;
if(counter === images.length){
counter = 1;
}
},5000);
}
})();
</script>

It works the first time because your first image, which I'm assuming is the displayed image, starts with the correct source.
It appears that you are overwriting the source of this image with the other sources. After the first round, the original source of the first image is lost.
At the moment, your image sources are probably something like:
1,2,3,4,5
2,2,3,4,5
3,2,3,4,5
4,2,3,4,5
5,2,3,4,5
for the first round, which is alright. Once the second round starts however, and for subsequent rounds, it would go something like this:
2,2,3,4,5
3,2,3,4,5
4,2,3,4,5
5,2,3,4,5
The simplest solution would be to store the first image as a 6th image, which would work with your existing code.
An alternative solution would be to store image sources in a JavaScript variable and use those as sources instead of referencing other elements.

It seems that your first image in the set images[0] has its src attribute overwritten every time the setInterval runs, so its source value has been lost. This means it won't be readable again. Rather than using the 0th item in the set to be the display target for your slideshow, try giving it a unique classname (<img class="slideshowTarget" src="...">) and selecting it individually like:
var slideshowTargetImage = document.querySelector('.slideshowTarget');
Rather than using imgLen.getElementsByTagName('img'), try adding a classname to the images you want to cycle in (<img class="slideshowImage" src="...">) and select them with something like:
var images = document.querySelectorAll('.slideshowImage');
Next, you'll want the image list to contain the original image again, or it won't be available in your image list. You should put that item at the end, so it'll be in the correct position when it's time for your slideshow to loop.
<div class="slideshow">
<img class="slideshowTarget" src="0.jpg" />
<div class="slideshowPreloadImages" style="display: none;">
<img class="slideshowImage" src="1.jpg" />
<img class="slideshowImage" src="2.jpg" />
<img class="slideshowImage" src="3.jpg" />
<img class="slideshowImage" src="0.jpg" />
</div>
</div>
Next, you can simplify your logic for the loop into one statement that you can run after you set the source on your image. The %, or "modulo" operator causes the counter to wrap back around to zero as soon as it grows past images.length - 1.
counter = (counter + 1) % images.length;
All together!
(function(){
var slideshowTargetImage = document.querySelector('.slideshowTarget');
var images = document.querySelectorAll('.slideshowImage');
var counter = 0;
var cycleSlideshow = function(){
var nextImageSource = images[counter].src;
slideshowTargetImage.src = nextImageSource;
console.log('nextImageSource', nextImageSource);
counter = (counter + 1) % images.length;
};
if (images.length) { // we can now test whether it's 0/falsy, becacuse the target is not part of the set!
setInterval(
cycleSlideshow,
1000
);
}
})();

Related

Increment Number in Image Source On Click

Basically I want to create next and previous buttons for a JQuery Image Gallery I'm working on. Each button has an id of "next" and "prev" respectively. What I'm trying to do is change a number that is in the source of the main image in the gallery (which has an id of mainImg). I have been able to target the number within the source of each image but I can't seem to increment it correctly and then replace the current image's source number with the new, incremented number. I tried using a while loop, for loop, and if statement but none of them worked correctly. To see the gallery that I have so far, I have it uploaded here: http://tiger.towson.edu/~abarso2/463/projecta/index.html If you go into my script.js file you'll see a block commented out at the bottom. That is the function I have so far that targets the number within the image's source and parses it to an integer. Thanks in advance for any help.
Here's what I have currently:
(function(){
var mainImg = $('#mainImg').attr('src');
var mainImgStr = mainImg.charAt(mainImg.length - 5);
var mainImgNum = parseInt(mainImgStr);
$('#next').click(function(){
});
}());
This should solve your problem
$(function(){
var mainImg = $('#mainImg');
var slidshow = $('#slideShow');
$('#next').click(function(){
var src = mainImg.attr('src').replace('thumb','shot');
var next = $('img[src="' + src +'"]', slidshow).next();
if(next.length){
mainImg.attr('src',next.attr('src').replace('thumb','shot'));
}
});
$('#prev').click(function(){
var src = mainImg.attr('src').replace('thumb','shot');
var prev = $('img[src="' + src +'"]', slidshow).prev();
if(prev.length){
mainImg.attr('src',prev.attr('src').replace('thumb','shot'));
}
});
});
Here is the revised code. The regexp will work better. The user can click the next button multiple times but no image will be skipped as the main image will only go to the next if and when the next image is loaded. So if you click next quickly 5 times only the next image will show (not skipping 4 images).
(function(){
// replace all non digit characters from src
// only the last set of numbers so www.123.com/image7.jpg
// will give us 7
function getNumber(src){
return parseInt(src.replace(/[\d]+(?=[\/])/g,"")
.replace(/[^\d]/g,""),10);
}
// replaces last number of a source with the number provided
// www.123.com/imgage7.jpg will be www.123.com/image8.jpg
// if number 8 is given
function setNumber(src,num){
return src.replace(/[\d]+(?![\d])/g,num);
}
var $mainImg = $('#mainImg');
$('#next').click(function(){
var src= $mainImg.attr('src'),
mainImgNum = getNumber(src);
var $img=$(document.createElement("img"));
$img.data("checkNext",false);
$img.on("load",function(){
// image exsist, load it as main image src
if($img.data("checkNext")===true){
$img.remove();
}else{
$mainImg.attr('src',$img.attr('src'));
$("#prev").show(1000);
$img.data("checkNext",true);
$img.attr('src',setNumber($img.attr('src'),
new String(mainImgNum+2));
});
$img.on("error",function(){
if($img.data("checkNext")===true){
$("#next").hide(1000);
}
// clean up
$img.remove();
});
$img.attr('src',setNumber(src,new String(mainImgNum+1)));
});
}());

change image and caption

I am trying to work out a way to change the text that goes along with an image that is changed with javascript...
var x = 0;
var images = new Array(".jpg", ".jpg", ".jpg", ".jpg", ".jpg");
var i = setInterval(auto, 10000);
function auto() {
x++;
if (x == images.length) x = 0;
document.getElementById('bigImage').src = images[x];
}
function changeImage(img, imagetitle) {
document.getElementById('bigImage').src = img;
/* document.getElementById('mainimagetitle').innerHtml = imagetitle; */
}​​​
The commented part is how i suppose I could possibly change the text that goes with the image. How do i code the html. Should i use a with the id mainimagetitle?
If so, where and how do i add the different texts i want to show and hide?
As I see from your posting, this should do the job.
<img id="bigImage" src="img1.jpg" alt="" />
<div id="mainimagetitle"></div>
Be sure to add a (filled) src tag or you will get strange results in IE. As you start with the second image (x++ before the change) this will be no problem. Happy accident I think. ;-)
// Edit: Of course any element will do as long as you use the right id. But you didn't tell us what html you use (xhtml/html5/...).
You could potentially have another array that stores the captions for each of the images
var captions = ['Caption 1', 'Caption 2', ...];
Assuming the mainimagetitle is an id of a <p> element, you could do:
function changeImage(img, imagetitle) {
document.getElementById('bigImage').src = img;
document.getElementById('mainimagetitle').innerText = imagetitle;
}​​​
You can see the full example, based on your code here.

How can I add an event to an automated rotating image?

I'm using the following script and the later onclick-event. If I use the onclick my rotating banner loses it and starts displaying pictures at random intervals. I think I should override the "setTimeout" at the end of the first piece of code. Question is how exactly?
<script language="JavaScript" type="text/javascript">
<!--
var RotatingImage1_Index = -1;
var RotatingImage1_Images = new Array();
RotatingImage1_Images[0] = ["images/ban_image1.png","",""];
<!-- 15 Images in total-->
RotatingImage1_Images[14] = ["images/ban_image2.png","",""];
function RotatingImage1ShowNext(){
RotatingImage1_Index = RotatingImage1_Index + 1;
if (RotatingImage1_Index > 14)
RotatingImage1_Index = 0;
eval("document.RotatingImage1.src = RotatingImage1_Images[" + RotatingImage1_Index + "][0]");
setTimeout("RotatingImage1ShowNext();", 4000);}
// -->
</script>
<img src="images/ban_image1.png" id="ban_img1" name="RotatingImage1">
This part works as it should.
<div id="ban_next" align="left">
<a href="#" onclick="RotatingImage1ShowNext();return false;">
<img src="images/ban_next.png" id="ban_nxt1"></a></div>
This part works as well, but only correctly if I set the 'setTimeout' to '0'. I am sorry, I'm compleatly new to this. I was looking at this stackoverflow.com question, but I don't know how to implement that here.
I thank you in advance.
Edit:
The rotating image starts automaticly. It displays a new image every 4 seconds. The images have text on them, or better insider jokes. Readers should be tempted to read them, but if the automated rotation cought there antention, the have to keep that antention for a full minute to see all images. That's probably to long. So I thought to implement a button to overwrite the timer and show the next image 'on click'. But after the click the rotation-time should turn back to auto-rotation. That's the plan.
Thank you Prusse, for now it bedtime, I will try to grasp your answer tomorrow ;)
You don't need eval, just do document.RotatingImage1.src = RotatingImage1_Images[RotatingImage1_Index][0].
The described behavior happens because there is more then one timer firing. There is one set on the first time RotatingImage1ShowNext is called, more one each time its called from your onclick handler. To fix this declare a global for your timer and before another timeout is set clear it if set. Like:
var global_timerid;
function RotatingImage1ShowNext(){
//RotatingImage1_Index = RotatingImage1_Index + 1;
//if (RotatingImage1_Index > 14) RotatingImage1_Index = 0;
RotatingImage1_Index = (RotatingImage1_Index + 1) % RotatingImage1_Images.length;
//document.RotatingImage1.src = RotatingImage1_Images[RotatingImage1_Index][0];
document.getElementById('ban_img1').src = RotatingImage1_Images[RotatingImage1_Index][0];
if (global_timerid) clearTimeout(global_timerid);
global_timerid = setTimeout(RotatingImage1ShowNext, 4000);
}

Dynamically changing images in a div

I've five images and would like to display it in a same div one by one with interval of 2 sec. Can anyone please suggest any solution for this?
Simple javascript example:
var currentImage = 0;
var images = [
'a.jpg',
'b.jpg'
];
var imageElement = document.getElementById('yourImageTagId');
function nextImage(){
currentImage = (currentImage + 1) % images.length;
imageElement.src = images[currentImage];
}
var timeoutId = setTimeout(nextImage, 1000);
It expects you to have some html like this:
<img src="a.jpg" id="yourImageTagId" />
Jquery Cycle is really flexible... you could hook it up to whatever youve got already marked up pretty easily.
There are many ways to do this nowadays but one simple way is using the following jquery plugin:
http://jquery.malsup.com/cycle/
Here is a simple demo in action fading images one after the other.
http://jquery.malsup.com/cycle/basic.html
setTimeout
You can do something like this.
function selectData(currentIndex) {
// select current's element "display" to "none" and show next element
...
// schedule next change in two second
setTimeout("selectData(" + nextIndex + ");", 2000);
};
I assume all images are inside that div already and have style display:none

JavaScript Timed Image Swap Need Help

So in my script I have...
<script type="text/javascript">
var images = new Array();
var numImages = 3;
var index = 0;
function setupSwapper() {
for (i = 0; i < numImages; i++) {
images[i] = new Image(266, 217);
images[i].src = "images/image" + i + ".png";
}
setTimeout("swapImage()", 5000);
}
function swapImage() {
if (index >= numImages) {
index = 0;
}
document.getElementById('myImage').src = images[index].src
index++;
setTimeout("swapImage()", 5000);
}
</script>
And then I have <body onload="setupSwapper()"> to setup the body.
and <img width=266 height=217 id="myImage" name="myImage" src="images/image0.png"></img> elsewhere in my document.
Only the initial image (image0.png) is showing up. I'm probably blind from having looked at this so long. The images are not swapping.
Use FireBug or a similar tool for debugging what's going on:
Does the img DOM element in fact gets its src changed ?
Do you see any network activity trying to load the images ? does it succeed ?
Set up breakpoints in your code and see what happens in the debugger
BTW - You can use setInterval instead of setTimeout - it sets a repeating timer
You're missing the () in the definition of "setupSwapper".
Also it's setTimeout, not setTimeOut.
Finally, get rid of the "type" attribute on your <script> tag.
You might want to start "index" at 1 instead of 0.
The way to go:
setTimeout(swapImage, 5000);
[FORGET] the type attribute has nothing to do with it
[FORGET] the index has nothing to do with it
[OPTIONAL] remove "name" attribute from the image (useless)
[OPTIONAL] close image tags like <img />
Note: 2-5 is about correctness. Only the first one is important to get it work.
Get Firebug, use it's debugger to put breakpoints inside swapImage to see if it is hit after the timeout. Another way is to use the console.* apis to see what's happening(e.g. console.log).

Categories