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

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);
}

Related

issue: image carousel skips 1st image

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
);
}
})();

Multiple countdowns jQuery and organize them depending the time left

I want to create a website with multiple countdowns activated by a click, some of them have different time, others the same. I need to organize them depending the time left. When one finish I need to return it to his original countdown value, so you can click again.
To understand better (I don't need the effects, I made them only for the example): http://i.imgur.com/lvcwbqm.gif
I have this: http://jsfiddle.net/m19aojmu/
Each countdown works independently of the others.
HTML
<div class="element" id="el1"><b>Elm 1</b> <span class="timeout">10</span> segundos</div>
<div class="element" id="el2"><b>Elm 2</b> <span class="timeout">100</span> segundos</div>
<div class="element" id="el3"><b>Elm 3</b> <span class="timeout">5</span> segundos</div>
Javascript
function timer(selector) {
var self = $(selector);
var sec = parseInt(self.find('span.timeout').text());
var interval = setInterval(function() {
sec--;
if (sec >= 0) {
self.find('span.timeout').text(sec);
} else {
clearInterval(interval);
}
}, 1000);
}
$("body").on('click', '.element', function() {
timer(this);
});
While each countdown have a different id (el1, el2, el3 ...) I don't know to detect which of them finished, therefore I don't know how to add a class when it start and end.
About the ubication, what should I do? Different classes for each location with position absolute?
I know it's a lot, but some help will be great.
Thank you very much.
Agusitn you code its like 95% correct, but you are setting the .text() into the sec variable wich is 0 or -1
Lets change the code a little bit
First lets take the actual value of the span DOM Element.
var actualTime = $('span.timeout').html();
console.log("the actual value when click is " + actualTime)
Later on the if statement we check when the actual span text its equal to 0
else if($(this).find('span').text() <= 0) {
console.log(sec)
var text = self.find('span.timeout').text(actualTime);
console.log(actualTime)
clearInterval(interval);
}
and when the .text() its === to 0, we set the actualTime variable to get back to the actual time.
here is the JsFiddle

How do I stop a image gallery from running onClick?

I have a site that has an image gallery that changes images every few seconds using JavaScript; however, I want to know how to STOP the images from changing when a user clicks on one of the images.
So far, the images are rotating as planned, but I can't seem to get the "onClick" scripting to STOP the rotation when the user clicks on an image. I don't need to have an alert popup or need it to do anything, I just need it to STOP the image rotation when someone clicks on one of the pictures.
Here's the HTML code I have:
else (getValue=='STOP')
{
alert("STOPPED");
}
That won't do what you probably want it to do. It should be:
else if (getValue=='STOP')
{
alert("STOPPED");
}
First of all, you missed out on the keyword "IF" in one of the lines of your code.
However, the way to create a terminable repetitive action is to setInterval and then use clearInterval to terminate the repetition.
semaphore = setInterval(somefunction, someinterval);
clearInterval(semaphore);
Example (I wrote this off-the-cuff, so there might be some errors, but you shd get the idea):
<img src="./images/image1.jpg" id="imageGallery" name="imageGallery"
onclick="chooseImg(this)" />
<script>
var turn = setInterval(function(){imgTurn()},5000);
var images = function2CreateImgArray();
var imageN = 0;
function chooseImg(img){
clearInterval(turn);
function2DisplayImg(imageN); // or do whatever
}
function imgTurn(){
if (imageN++ >= images.length) imageN = 0;
function2DisplayImg(imageN++);
}
</script>
You could replace the setInterval with setTimeout.
var turn = setTimeout(function(){imgTurn()},5000);
But then you need to use clearTimeout to stop it:
clearTimeout(turn);
But if you use setTimeout, you would need to setTimeout for the next image display, so you would not even need to clearTimeout to stop the rotation.
<img src="./images/image1.jpg" id="imageGallery" name="imageGallery"
onclick="chooseImg(this)" />
<script>
setTimeout(function(){imgTurn()},5000);
var images = function2CreateImgArray();
var imageN = 0;
var turn = 1;
function chooseImg(img){
turn = 0;
function2DisplayImg(imageN); // or do whatever
}
function imgTurn(){
if (turn==0) return;
if (imageN++ >= images.length) imageN = 0;
function2DisplayImg(imageN++);
}
</script>

Chrome doesn't always repeat events with JavaScript setInterval()

I want to display several images of the same size at the same position, one at a time, with a 5s interval between each change. To do so I've used jQuery.Timer, that uses setInterval() to call some show_next_image() function every 5s.
It actually does work with IE, Opera, Safara, Firefox and.. partly with Google Chrome. It's not working with Google Chrome if I open a new window and directly type my website URL: it'll show the second image and stop. And with any other situation (reload, from another link, not right after opening a new window) it'll badly work: one can see the back image before the front image is shown.
Thus I'm wondering whether I've done something wrong with my JavaScript source. What I do is I use a front and a back image. When I want to show the next image, the back img source is set to the new image, and the front image is faded out while the back one is faded in through jQuery. You can check it out at http://www.laurent-carbon.com/ (in French). The two img are identified with bg1 and bg2.
var images = ["/img/IMG_0435bg.jpg", "/img/IMG_0400bg.jpg", "/img/maisonnette 2.jpg", "/img/IMG_0383bg.jpg", "/img/IMG_0409bg.jpg", "/img/IMG_0384bg.jpg"];
var idx = 1;
var waitTime = 5000; // ms
$(document).ready(function() {
$("#bg2").hide();
$.timer(waitTime, load_next);
$.preLoadImages(images);
});
function load_next(timer) {
var toshow = images[idx];
idx++;
idx %= images.length;
back_image().attr('src', toshow);
swap_images();
}
function front_image() {
return (idx % 2 == 0) ? $("#bg1") : $("#bg2");
}
function back_image() {
return (idx % 2 == 0) ? $("#bg2") : $("#bg1");
}
function swap_images() {
back_image().fadeOut('slow');
front_image().fadeIn('slow');
}
Thanks,
Ceylo
Ok I've worked out a solution .... without the use of plugins.
Demo
http://jsfiddle.net/morrison/PvPXM/9/show
source
http://jsfiddle.net/morrison/PvPXM/9/
This approach is a lot cleaner and removes the problem I had while viewing your page in chrome: the animation getting out of sync and flashing.
The only thing you have to do in the HTML is wrap the two images in a <div id="fadeBox" style="position:relative"></div>
$(function() {
var images = [
"http://www.laurent-carbon.com/img/IMG_0435bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0400bg.jpg",
"http://www.laurent-carbon.com/img/maisonnette 2.jpg",
"http://www.laurent-carbon.com/img/IMG_0383bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0409bg.jpg",
"http://www.laurent-carbon.com/img/IMG_0384bg.jpg"
];
var idx = 1;
var max = images.length;
var easing = "swing";
var waitTime = 5000; // ms
var fadeTime = 2000; // ms
var fadeShow = function(fadeTime, fadeDelay) {
var $topImage = $("#fadeBox img:last");
$topImage.fadeTo(fadeDelay, 1, function() {
$topImage.fadeTo(fadeTime, 0, easing, function() {
$topImage
.fadeTo(0, 1)
.insertBefore("#fadeBox img:first")
.attr("src", images[++idx == max ? idx = 0 : idx]);
fadeShow(fadeTime, fadeDelay);
});
});
};
fadeShow(fadeTime, waitTime);
});
Hope this helps
PS thanks to Levi for cleaning the code up a bit.
Answer: http://jsfiddle.net/morrison/RxyZY/
Notes:
You are trying to reinvent the wheel. You are creating a simple slideshow. There are numerous plugins to do exactly this and much more. I used jQuery cycle in my example, which is extremely customizable.
You should wrap your stuff up in a function, creating an expression. In my example, the (function($){}(jQuery)) is what does the trick. It scopes your variables to the function, rather than the global namespace.

How to display a blinking / flashing link in html

I am in need a link that will flash every 500 milleseconds, for a duration of 5 seconds...
I remember long ago having a link like this, but deleted it because one could only click it when it was visible. Is there a workaround for that?
Try this:
<script type="text/javascript">
var col = new String();
var x=1;var y;
function blink()
{
if(x%2)
{
col = "rgb(255,0,0)";
}else{
col = "rgb(255,255,255)";
}
aF.style.color=col;x++;if(x>2){x=1};setTimeout("blink()",500);
}
</script>
<body onload="blink()">
<a id="aF" href="http://www.google.com"><b>*Google!*</b><br>
There is a JavaScript function in Script.aculo.us to do that : Have a look on Effect.Pulsate
There is CSS
text-decoration: blink
but that will blink your link all the time, you would need some javascript to change the style after 5 seconds.
Remember to always keep usability for all users in mind. Especially if you're making something flash at a certain frequency. Just be careful.
'A' quick JQuery UI version...
Links need CLASS 'flasher', and an ID
Will start on mouseover...and stop on mouseout.
Also add the secondarycolor as a hover to the 'A' link...it will help mask the initial interval delay at start.
var flashInterval;
var flasherId;
var firstColor = '#EF7F2C';
var secondaryColor = '#3296C8';
var flashTime = 300;
jQuery('a.flasher').mouseover(function() {
if(flasherId){ jQuery('#'+flasherId).animate({ color:firstColor},0); }//stop any previous flashing link
flasherId = jQuery(this).attr('id');//get id of current link
//set interval
flashInterval = setInterval(function(){ jQuery('#'+flasherId).animate({ color:secondaryColor},flashTime).animate({ color:firstColor},flashTime); },flashTime*2);
}).mouseout(function() {
clearInterval(flashInterval);//clear interval
jQuery('#'+flasherId).animate({ color:firstColor},0);//reset flasher
flasherId = '';//clear flasher var
});

Categories