I am trying to understand the setTimeout method and recursion.
I have a simple slidshow based on setTimeout recursion. And I want to stop and run it by clicking on two buttons stop and play. I tried many variants, but don't understand how to clear such recursion timeout and then when I click on play, this slider runs from the slide it was stopped.
Recursion slider:
let timer = setTimeout(function slider() {
for (let i = 0; i < images.length; i++) {
images[i].classList.add('hide');
}
currentSlide++;
if (currentSlide > images.length) {
currentSlide = 1;
}
images[currentSlide - 1].classList.remove('hide');
setTimeout(slider, 3000);
}, 0);
Buttons:
stopBtn.addEventListener('click', () => {
clearTimeout(timer);
});
playBtn.addEventListener('click', () => {
setTimeout(timer, 3000);
});
UPD: I've almost achieved the stop/play fuctionality, but when I click on play btn, slideshow continues in 2 slides. And whenever I click on play button the slideshow changes.
timer = setTimeout(function slider() {
for (let i = 0; i < images.length; i++) {
images[i].classList.add('hide');
}
images[currentSlide].classList.remove('hide');
if (currentSlide + 1 === images.length) {
currentSlide = 0;
} else {
currentSlide++;
}
let sllideSwhow = setTimeout(slider, 3000);
stopBtn.addEventListener('click', () => {
clearTimeout(sllideSwhow);
});
playBtn.addEventListener('click', () => {
slider();
});
}, 0);
Finally, I've managed to do it.
function slider() {
for (let i = 0; i < images.length; i++) {
images[i].classList.add('hide');
}
images[currentSlide].classList.remove('hide');
if (currentSlide + 1 === images.length) {
currentSlide = 0;
} else {
currentSlide++;
}
timer = setTimeout(slider, 3000);
}
slider();
stopBtn.addEventListener('click', () => {
clearTimeout(timer);
playing = 0;
});
playBtn.addEventListener('click', () => {
if (!playing) {
playing = 1;
slider();
}
});
Related
Making this super simple game. You hold the space bar and the timer starts, when you release the space bar it stops and if you have beaten your high score then it will update high score otherwise it resets the timer to 0 and keeps the high score the same. I can't get the high score to stay the same if the timer is under the high number. It changes every time
`use strict`;
let timer = document.getElementById(`number`);
let highScore = document.getElementById(`highNumber`);
let resetBtn = document.getElementById(`resetBtn`);
let timerNumber = 0;
startTimer();
function init() {}
function startTimer() {
document.addEventListener('keydown', (event) => {
if (event.code === 'Space') {
timer.textContent = timerNumber++;
}
});
}
document.addEventListener(`keyup`, (event) => {
if (timer.textContent > highScore.textContent) {
highScore.textContent = timerNumber;
timer.textContent = 0;
timer.textContent = 0;
timerNumber = 0;
}
if (timer.textContent < highScore.textContent) {
timer.textContent = 0;
timer.textContent = 0;
timerNumber = 0;
}
});
function reset() {
resetBtn.addEventListener(`click`, function () {
highScore.innerHTML = 0;
});
}
reset();
Don't add keyup or keydown event to document give it to the <html> tag :
document.querySelector("html").addEventListener('keydown', (event)=>{
//something
});
This is my code for right and left navigation.
How can I add infinite loop in this:
if (i < this.sindex) { //slide to right
_old.addClass('right');
setTimeout(function () {
_old.removeClass('right sel anim')
}, 300);
_new.removeClass('anim right').addClass('sel left');
setTimeout(function () {
_new.addClass('anim').removeClass('left')
}, 5);
} else if (i > this.sindex) { //slide to left
_old.addClass('left');
setTimeout(function () {
_old.removeClass('left sel anim')
}, 300);
_new.removeClass('anim left').addClass('sel right');
setTimeout(function () {
_new.addClass('anim').removeClass('right')
}, 5);
}
It's a sumogallery plugin which doesn't have infinite loop function.
Not sure if you are using any plugins. However, you can implement your own infinite navigation easily.
In order to loop infinitely in a non-blocking way you can use setTimeout and call your handler recursively.
Infinite loop implementation:
class InfiniteLooper {
constructor(arr, handler, options){
this.arr = arr;
this.index = 0;
this.options = options;
this.handler = handler;
this.t1 = null
this.t2 = null
}
recur() {
var that = this;
if(this.index < this.arr.length){
this.t1 = setTimeout(this.handler(this.arr[this.index]), 0);
this.index ++
if(this.options && this.options.circular && this.index == this.arr.length) {
this.index = 0;
}
this.t2 = setTimeout(function() {
that.recur()
}, 0);
}
}
run() {
this.recur()
}
stop() {
clearTimeout(this.t1)
clearTimeout(this.t2)
}
}
const array = [1,2,3,4,5]
const IL = new InfiniteLooper(array, console.log, {circular:true});
IL.run()
// Execute some more code
console.log('Non blocking!');
console.log('Do some math', 100*9);
const t = setInterval(()=>{
console.log('Do some more math in every 1 seconds', Math.random(1,4));
}, 1000)
// stop the loop after 10 sec
setTimeout(()=>{
IL.stop()
clearInterval(t)
}, 10000)
I wrote in detail here https://medium.com/#mukeshbiswas/looping-infinitely-in-a-non-blocking-way-2edca27bc478. See if this helps.
Below in the code is an array of pages which is shuffled and then each of them is displayed in an iframe for a certain amount of time. I want to be able to start/stop the pageChange function using a button or a mouse click. Can anyone help me with this? Below is the working code, or check this fiddle: http://jsfiddle.net/xaa1qccm/ (Thanks to Nobe4)
var pages=[];
pages[0]="http://example.com/";
pages[1]="http://www.iana.org/domains/reserved";
pages[2]="http://en.wikipedia.org/wiki/Main_Page";
pages[3]="http://en.wikipedia.org/wiki/Randomness";
var shuffle = function(array){
var shuffledPages = [];
while(array.length){
shuffledPages.push(array.splice(Math.floor(array.length*Math.random()),1));
}
return shuffledPages;
}
var time = 3300;
var currentIndex = 0;
function pageChange() {
if(currentIndex == 0){
pages = shuffle(pages);
console.log(pages);
currentIndex = pages.length;
}
currentIndex--;
document.getElementById("frame").src=pages[currentIndex];
console.log(currentIndex);
setTimeout(function() { pageChange(); }, time);
};
pageChange();
A variable which can be set to determine if the rotator is running, and setting that to true or false:
var isRunning = true;
....
<button onclick="isRunning = false">stop</button>
<button onclick="isRunning = true">start</button>
And check that inside your method:
function pageChange() {
if(isRunning){
...
}
setTimeout(function() { pageChange(); }, time);
};
Live example: http://jsfiddle.net/xaa1qccm/1/
You may add a start/stop variable so as to check the status :
[...]
var time = 3300;
var currentIndex = 0;
var stop = 0;
function pageChange() {
if(currentIndex == 0){
pages = shuffle(pages);
console.log(pages);
currentIndex = pages.length;
}
if (stop == 0)
{
currentIndex--;
document.getElementById("frame").src=pages[currentIndex];
console.log(currentIndex);
setTimeout(function() { pageChange(); }, time);
}
};
function startStop()
{
if (stop == 0){
stop = 1;
}
else{
stop = 0;
pageChange();
}
}
[...]
And then you call startStop() on the click event of the button you want
Edit : Here is a jsfiddle
Code:
var n = 360; // 6 min of waiting after blocked
function countDown() {
n--;
if (n > 0) {
setTimeout(countDown, 1000);
}
$("span#waitcount").html(document.createTextNode(n));
}
var count = 50; // Count of tokens when reached 0 block the page
var counter = document.getElementById('counter');
var clickDisabled = false;
$('.slotMachineButton').click(function() {
if (clickDisabled)
return;
setTimeout(function() {
count--;
counter.innerHTML = count;
if (count === 0) {
$.blockUI({message: '<h1>Thank you for Playing!!!<br>Please wait for 6 munites to be able to play again.</h1>'});
setTimeout(function() {
$.unblockUI({
onUnblock: function() {
alert('Game has been resumed!!!');
}
});
}, 10000);
setTimeout(countDown, 1000);
}
});
clickDisabled = true;
setTimeout(function() {
clickDisabled = false;
}, 3000);
}
Goal:
When the token count reaches 0 return it to original value to start again another count, because whenever the count reaches zero it goes -1 and keeps going.
When 6 min waiting is over start another waiting, I dont know if I got the code right for this part but please do check.
If you want to keep your code and you don't follow the suggestions in the the comments, then to this:
var n = 360, // 6 min of waiting after blocked
count = 50, // Count of tokens when reached 0 block the page
counter = document.getElementById('counter'),
clickDisabled = false;
function countDown(){
if(n > 0){
setTimeout(countDown, 1000);
} else {
n = 360;
clickDisabled = false
}
$("span#waitcount").html(document.createTextNode(n));
n--;
}
$('.slotMachineButton').click(function () {
if (clickDisabled) {
return;
}
setTimeout(function () {
counter.innerHTML = count;
if (count === 0) {
$.blockUI({ message: '<h1>Thank you for Playing!!!<br>Please wait or 6 munites to be able to play again.</h1>' });
setTimeout(function () {
$.unblockUI({
onUnblock: function () {
clickDisabled = true;
alert('Game has been resumed!!!');
setTimeout(countDown, 10);
}
});
}, 1000);
count = 50;
}
count--;
});
clickDisabled = true;
setTimeout(function () {
clickDisabled = false;
}, 100);
});
Bud you should realy look for a diffrent aproach. I changed the timer values for testing.
I have tried for loops, etc, but i am having trouble running this function only twice
function play() {
setInterval(function(){
var next = $(".furniture .active, .pets .active").next("img");
var i = 0;
var current = next.prev("img");
current.removeClass("active").addClass("current")
next.removeClass("current").addClass("active");
if (!next.length) {
next = $(".furniture img:first");
};
}
}, 3000);
}
play();
You probably want something like this:
function play(timeout) {
setTimeout(function() {
...
}, timeout);
}
play(3000);
play(6000);
var counter = 0;
play();
function play()
{
counter = counter + 1;
var next = $(".furniture .active, .pets .active").next("img");
var i = 0;
var current = next.prev("img");
current.removeClass("active").addClass("current")
next.removeClass("current").addClass("active");
if (!next.length) {
next = $(".furniture img:first");
};
}
if (counter < 2)
{
setTimeout(play(), 3000);
}
}