setTimeout functions double even when cleared first - javascript

I have images in the img/ directory (1-13.jpg) and I need to loop through them. the #next_container is supposed to stop(); the loop if it already start();ed and change the src to the next(); image then start(); it again, but when I click on #next_container it runs the next(); function as expected but for some reason stop(); doesn't stop the old timeout and I end up with two start(); functions running which causes the images to change faster and when it's stop();ed the #next_container is supposed to only get the next(); image but for some reason the loop start();s. the same happens for #prev_container.
HTML code:
<div class="container">
<img id="imgs" src="img/1.jpg" onload="start();">
<div id="next_container" style="display: none;">
<span id="next">❱</span>
</div>
<img id="player" src="" style="display: none;">
<div id="prev_container" style="display: none;">
<span id="prev">❰</span>
</div>
<p id="count">1 / 13</p>
</div>
JavaScript code:
// the images array holds sources for all the images
function next(){
var element = document.getElementById("imgs");
var num = Number(element.src.split("/").slice(-1)[0].split(".")[0]);
if (num == images.length){
element.src = "img/1.jpg";
document.getElementById("count").innerHTML = "1 / 13";
} else {
num++;
element.src = images[num-1];
document.getElementById("count").innerHTML = num.toString()+" / 13";
}
}
function prev(){
var element = document.getElementById("imgs");
var num = Number(element.src.split("/").slice(-1)[0].split(".")[0]);
if (num == 1){
element.src = "img/13.jpg";
document.getElementById("count").innerHTML = "13 / 13";
} else {
num--;
element.src = images[num].src;
document.getElementById("count").innerHTML = num.toString()+" / 13";
}
}
function start(){
window.timeout = setTimeout("next()", 3000);
document.getElementById("player").src = "img/pause.png";
document.getElementById("player").onclick = function(){ stop(); };
document.getElementById("next_container").onclick = function(){ stop(); next(); start(); };
document.getElementById("prev_container").onclick = function(){ stop(); prev(); start(); };
}
function stop(){
clearTimeout(window.timeout);
document.getElementById("player").src = "img/play.png";
document.getElementById("player").onclick = function(){ start(); };
document.getElementById("next_container").onclick = function(){ next(); };
document.getElementById("prev_container").onclick = function(){ prev(); };
}

Because the onload fires for each image you load. Example showing it.
function start() {
console.log("I AM CALLED");
}
function loadNext () {
document.querySelector("img").src = "http://placekitten.com/400/300"
}
window.setTimeout(loadNext, 2000);
<img src="http://placekitten.com/200/300" onload="start()" />
So you call next(); start();, next changes the source so it will cause the "onload="start()" to fire and than you call start(). There is your two timers. Remove the start() after the next and prev calls.

Related

How to make clearInterval() work in JavaScript

I want to make an element (id=runner) move across the page by n pixels after a mouseover event, then stop at a certain position (left = 2000px), using setInterval() to repeatedly call move_left(), then clearInterval() when left == 200px. I can make the element move, but when I look in developer tools it never stops - left continues to increase. I am pretty new to JavaScript/HTML/CSS. How do I make it stop?
Relevant code:
<script>
function runner_go()
{
var load_time = performance.now();
const go = setInterval(move_left,20);
}
function move_left()
{
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position,10) + 17 + "px";
if (parseInt(runner_position,10) > 2000)
{
clearInterval(go);
}
}
</script>
</head>
<body style="background-color:gray;" onmouseover = "runner_go();">
<div>
<h1>Running!</h1>
</div>
<img src="images/runner_l.png" alt ="running man" style="position:relative; visibility:hidden;" id = "runner"/>
</body>
You need to create the var 'go' outside the method cause of the scope, also if you let on the 'body' the 'onmouseover' it will set the interval everytime.
Try this code to test:
<head>
<script>
let go = null;
function runner_go()
{
var load_time = performance.now();
go = setInterval(move_left,20);
}
function move_left()
{
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position,10) + 17 + "px";
if (parseInt(runner_position,10) > 2000)
{
clearInterval(go);
}
}
</script>
</head>
<body style="background-color:gray;" onclick = "runner_go();">
<div>
<h1>Running!</h1>
</div>
<img src="images/runner_l.png" alt ="running man" style="position:relative; visibility:hidden;" id = "runner"/> </body>
Problem -
You declared the interval variable as a constant within another function which is not accessible by the move_left function
So just move your interval variable to global scope (outside the function) and it should work
let go;
function runner_go() {
var load_time = performance.now();
go = setInterval(move_left, 20);
}
function move_left() {
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position, 10) + 17 + "px";
if (parseInt(runner_position, 10) > 2000) {
clearInterval(go);
}
}
sample on how intervals and clearIntervals work
let interval, i = 1;
function start() {
interval = setInterval(log, 1000);
}
function log() {
if (i >= 5) clearInterval(interval);
console.log(`Test ${i}`);
i++
}
start();

2 Javascript Timeouts occur simultaneously

I have 2 Javascript Timeouts which should make an animation, but the happen simultaneously, even if they have as timeout 1s.
JavaScript:
$( document ).ready(function() {
let filter = document.querySelector('.filter');
let body = document.querySelector('body');
setTimeout(moveRight, 1000);
setTimeout(scaleRotate, 1000);
function moveRight() {
filter.style.marginLeft="10%";
body.style.overflow = "hidden";
}
function scaleRotate() {
let deg = 90;
filter.style.webkitTransform = 'rotate('+deg+'deg)';
filter.style.width = "100vh";
}
});
HTML
<div class="header">
<div class="filter"></div>
<div class="header-text ml-5">
<h2 class="font-weight-bold">Andrei Bunea</h2>
<h3 class="mt-3">full stack developer</h3>
</div>
</div>
You set them similar delay. If you want scaleRotate to work 1 second after moveRight, you can set scaleRotate timer in moveRight timer:
setTimeout(moveRight, 1000);
function moveRight() {
console.log("moveRight");
setTimeout(scaleRotate, 1000);
}
function scaleRotate() {
console.log("scaleRotate");
}

Image change onclick Javascript, can I add a timer to change as well?

Edit: is there anyway to have the interval only kick in if the user has not clicked? example: I set a interval of 20 seconds, but if the user had clicked the first image at 15 seconds, the next image only shows up for the remaining 5 seconds. I need a timer -or- a click but not both. Thanks!
So I have the javascript below that currently works onclick. Can it be modified to also add a timer? So if they don't click on the first image, I can set a timer to go to image 2.. then to image 3.. and so on. Thx for your efforts!
<img alt="" src="image1.gif" style="height: XXXpx; width: XXXpx" id="imgClickAndChange" onclick="changeImage()" />
<script language="javascript">
function changeImage() {
if (document.getElementById("imgClickAndChange").src == "image1.gif")
{
document.getElementById("imgClickAndChange").src = "image2.gif";
}
else
{
document.getElementById("imgClickAndChange").src = "image3.gif";
}
}
</script>
You can use setInterval to call the changeImage function at intervals.
This should work:
<script language="javascript">
function changeImage() {
var img = document.getElementById("imgClickAndChange");
img.src = (img.src == 'image1.gif') ? 'image2.gif' : 'image3.gif';
}
// auto-trigger every 1 second, change 1000 as needed
setInterval(changeImage, 1000);
</script>
Note: Modified the code to make it smaller.
use setInterval
setInterval(function() { changeImage(); }, 3000);
Try using this snippet below it picks a random image after a set time -
<script type="text/javascript" language="javascript">
var intTimer=0;
function ImageRotate()
{
intTimer = self.setInterval("GenerateRandom()",3000);
}
function GenerateRandom()
{
var intNumber = 10;
var intRandom = 0;
intRandom = Math.floor(Math.random() * intNumber + 1);
document.getElementById("ImageRandom1").src =
"Pictures1/Image" + intRandom + ".JPG";
}
</script>
Put your images in to array and than with setInterval call your function like this
jsBin Demo
Edited! updated
var i = 0,
element = document.getElementById("imgClickAndChange"),
images = ["image1.gif", "image2.gif", "image3.gif"],
timer = setInterval(changeImage, 25000);
function changeImage() {
element.src = images[(i >= images.length) ? (i = 0) : i++];
}
element.addEventListener("click", function() {
changeImage();
clearInterval(timer);
timer = setInterval(changeImage, 25000);
}, false);

Display diffrent image depending on timer

I'm trying to display a different image depending on the timer's result and can't find a way through. So far I have a start and stop button, but when I click stop, I want to use the value the timer is on and display an image(on alertbox or the webpage itself) depending on that value.
if( timer =>60){
img.src("pizzaburnt.jpg");
}elseif (timer <=30){
img.src("pizzaraw.jpg");
}
else{
img.src("pizzaperfect.jpg
}
///Time
var check = null;
function printDuration() {
if (check == null) {
var cnt = 0;
check = setInterval(function () {
cnt += 1;
document.getElementById("para").innerHTML = cnt;
}, 1000);
}
}
//Time stop
function stop() {
clearInterval(check);
check = null;
document.getElementById("para").innerHTML = '0';
}
**HTML**
<td>
Timer :<p id="para">0</p>
</td>
Any advice or dicussion would be great, thanks.
Something like this would work better and it's more compact:
var img = document.getElementById("image");
var imageSrcs = ['pizzaRaw.jpg', 'pizzaPerfect.jpg', 'pizzaBurnt.jpg'];
var imageIndex = 0;
var interval = setInterval(animate, 30000); //change image every 30s
var animate = function() {
//change image here
//using jQuery:
img.src(imageSrcs[imageIndex]);
imageIndex++; //move index for next image
if (imageIndex == imageSrcs.length) {
clearInterval(interval); //stop the animation, the pizza is burnt
}
}
animate();
Reason you wouldn't want to use an increment variable and a 1 second timer is because your just conflating your logic, spinning a timer, and making a bit of a mess when all you really want is the image to change every 30 seconds or whenever.
Hope this helps.
You need an <img> tag in your HTML like this:
<html>
<body>
Timer: <p id="para">0</p>
Image: <img id="image" />
</body>
</html>
And the Javascript code will be like:
var handle;
var timerValue = 0;
var img = document.getElementById( "image" );
var para = document.getElementById("para");
function onTimer() {
timerValue++;
para.innerHTML = timerValue;
if ( timerValue >= 60 ) {
img.src( "pizzaburnt.jpg" );
}else if ( timer <= 30 ) {
img.src( "pizzaraw.jpg" );
} else {
img.src("pizzaperfect.jpg" );
}
}
function start () {
if ( handle ) {
stop();
}
timerValue = 0;
setInterval( onTimer, 1000 );
}
function stop () {
if ( handle ) {
clearInterval ( handle );
}
}
Please make sure that these 3 files are in the same directory as your HTML file:
pizzaburnt.jpg
pizzaraw.jpg
pizzaperfect.jpg

Show Div on Mouseover after three second

I want on first click it will show after 3 seconds but after the first click when I clicked it will shown before 3 seconds:
function Func1()
{
document.getElementById('div1').style.visibility = "visible" ;
}
function Func1Delay()
{
setTimeout("Func1()", 3000);
}
function Func2Delay()
{
document.getElementById('div1').style.visibility = "hidden" ;
}
Your English or description is very poor, but from what I understand, you want something like this :
var div = document.getElementById('div1'),t;
function changeStyle(element,prop,value){
element.style[prop] = value;
}
function showDiv(){
changeStyle(div,'opacity','1');
}
function hideDiv(){
changeStyle(div,'opacity','0');
}
div.addEventListener('mouseover',function(){
t = setTimeout(showDiv,3000);
},false);
div.addEventListener('mouseout',function(){
clearTimeout(t);
hideDiv();
},false);​
Here's a demo : http://jsfiddle.net/gion_13/TSVA5/
You have to hover the "invisible" div and it will show after 3 seconds.
this works for me
the markup:
<input type="button" value="clickme" onmouseout="ClearIntv()" onmouseover="DelayShow('showMe',5000)" />
<div id="showMe" style="display:none;background-color:red;width:50px;height:50px;">
</div>
the script:
var intv;
function DelayShow(timeOutMs) {
var elm = document.getElementById("showMe");
var now = new Date().getTime();
var end = now + timeOutMs;;
intv = setInterval(function () {
now = new Date().getTime();
if (now >= end) {
elm.style.display = "block";
clearInterval(intv);
}
}, 500);
}
function ClearIntv() {
clearInterval(intv);
}
Activates the counter on MouseOver, and cancels on MouseOut

Categories