stop method for function - javascript

I have small function that adds class to elements in array every 100ms
var index = 0;
var $pcs = $('.participant');
var setWinCls = {
start: function(i){
if(i>0){
$pcs.eq(i-1).removeClass('winner');
}
if(i == $pcs.length){
i=0;
}
$pcs.eq(i).addClass('winner');
setTimeout(function() { setWinCls.start(i+1) },100);
},
stop: function () {
...
}
};
I'm trying to define stop method with will stop adding class on elements and stops on last added element or element I will point. Any suggestions?
I tried use return false but it didn't helped.

Add a flag (stopped) to setWinCls, and use the stop method to change it to true. As long as stopped is false, the setTimeout will be called:
var $pcs = $('.participant');
var setWinCls = {
stopped: false, // the flag
start: function(i) {
if (i > 0) {
$pcs.eq(i - 1).removeClass('winner');
}
if (i == $pcs.length) {
i = 0;
}
$pcs.eq(i).addClass('winner');
// if stopped is false, setTimeout will be called
this.stopped || setTimeout(function() {
setWinCls.start(i + 1)
}, 100);
},
stop: function() {
this.stopped = true; // changing stopped to true
}
};

Related

Images navigation infinite loop

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.

Resume a function after clearInterval

I have this code:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0;
var timer = setInterval(function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
clearInterval(timer);
}
});
$el.mouseout({
timer;
});
});
I want to suspend the function on mouseover and resume it on mouse out but I cant get the latter right. How can I resume it?
Thank you.
There are two ways:
Set a flag that the function being called by the interval checks, and have the function not do anything if it's "suspended."
Start the interval again via a new setInterval call. Note that the old timer value cannot be used for this, you need to pass in the code again.
Example of #1:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0,
suspend = false; // The flag
var timer = setInterval(function() {
if (!suspend) { // Check it
$el.removeClass("current").eq(++c % tot).addClass("current");
}
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
suspend = true; // Set it
},
mouseleave: function(e) {
suspend = false; // Clear it
}
});
});
Example of #2:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0,
timer = 0;
// Move this to a reusable function
var intervalHandler = function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
};
// Probably best to encapsulate the logic for starting it rather
// than repeating that logic
var startInterval = function() {
timer = setInterval(intervalHandler, 3000);
};
// Initial timer
startInterval();
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
clearInterval(timer); // Stop it
}
mouseleave: function(e) {
startInterval(); // Start it
}
});
});
Checkout these prototypes:
//Initializable
function Initializable(params) {
this.initialize = function(key, def, private) {
if (def !== undefined) {
(!!private ? params : this)[key] = (params[key] !== undefined) ? params[key] : def;
}
};
}
function PeriodicJobHandler(params) {
Initializable.call(this, params);
this.initialize("timeout", 1000, true);
var getTimeout = function() {
return params.timeout;
};
var jobs = [];
function Job(params) {
//expects params.job() function
Initializable.call(this, params);
this.initialize("timeout", getTimeout(), true);
this.initialize("instant", false);
var intervalID = undefined;
this.start = function() {
if (intervalID !== undefined) {
return;
}
if (this.instant) {
params.job(true);
}
intervalID = setInterval(function() {
params.job(false);
}, params.timeout);
};
this.stop = function() {
clearInterval(intervalID);
intervalID = undefined;
};
}
this.addJob = function(params) {
jobs.push(new Job(params));
return jobs.length - 1;
};
this.removeJob = function(index) {
jobs[index].stop();
jobs.splice(index, 1);
};
this.startJob = function(index) {
jobs[index].start();
};
this.stopJob = function(index) {
jobs[index].stop();
};
}
Initializable simplifies member initialization, while PeriodicJobHandler is able to manage jobs in a periodic fashion. Now, let's use it practically:
var pjh = new PeriodicJobHandler({});
//It will run once/second. If you want to change the interval time, just define the timeout property in the object passed to addJob
var jobIndex = pjh.addJob({
instant: true,
job: function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}
});
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0;
var timer = setInterval(function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
jobIndex.stop();
}
});
$el.mouseout({
jobIndex.start();
});
});
With Javascript, it is much easy and efficient.
You can change the interval in setInterval function.
It is checking whether suspend variable is false or true, here suspend variable is setting to true, if mouseEnter function is called and set to false if mouseLeave function is called.
var displayMsg = document.getElementById('msg').innerHTML;
var i = 0;
var suspend = false;
var sequence = setInterval(update, 100);
function update() {
if (suspend == false) {
var dispalyedMsg = '';
dispalyedMsg = displayMsg.substring(i, displayMsg.length);
dispalyedMsg += ' ';
dispalyedMsg += displayMsg.substring(0, i);
document.getElementById('msg').innerHTML = dispalyedMsg;
i++;
if (i > displayMsg.length) {
i = 0;
}
}
}
document.getElementById('msg').addEventListener('mouseenter', mouseEnter);
document.getElementById('msg').addEventListener('mouseleave', mouseLeave);
function mouseEnter() {
suspend = true;
}
function mouseLeave() {
suspend = false;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#msg {
width: 680px;
height: 100px;
border: 1px solid #ccc;
padding-left: 15px;
}
</style>
</head>
<body>
<div id="msg">
Today is only 15% discount. Hurry up to grab. Sale will end sooooooooooooon!!!!
</div>
<div id="output"></div>
<script src="marquee.js"></script>
</body>
</html>

How do I add a pause function to this pageChange timer?

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

Uncaught insert function argument is not a string

The console is showing errors on lines 5 and 8. The error is "Uncaught insert function argument is not a string." Any help would be greatly appreciated. Thanks!
$(function() {
var animation = false;
function typed(term, message, delay, finish) {
animation = true;
var da = 0;
term.set_prompt('');
var interval = setInterval(function() {
term.insert(message[da++]);
if(da > message.length) {
clearInterval(interval);
setTimeout(function() {
term.set_command('')
term.set_prompt(message + ' ');
animation = false;
finish && finish();
}, delay);
}
}, delay);
}
$('#fyeah').terminal(function(cmd, term) {
var finish = false;
}, {
name: 'test',
greetings: null,
onInit: function(term) {
var msg = "testing";
typed(term, msg, 150, function() {
finish = true;
});
},
keydown: function(e) {
if (animation) {
return false;
}
}
});
});
There are three cases when message[da++] "is not a string":
message is the empty string
(old) IE do not support bracket notation for getting single characters of strings, better use the .charAt() method
in the last iteration of your loop, da == message.length - it ends only when da is already greater than the length. Yet, the indices are zero-based and run from 0 to length-1.
To fix it, use
// init
var da = 0;
var interval = setInterval(function() {
if (da < message.length) {
term.insert(message.charAt(da++)); // maybe better move the incrementing
// out, to the end of the loop
} else {
clearInterval(interval);
// teardown / callback
}
}, delay);

countdown timer stops at zero i want it to reset

I am trying to figure out a way to make my countdown timer restart at 25 all over again when it reaches 0. I dont know what I am getting wrong but it wont work.
Javascript
window.onload = function() {
startCountDown(25, 1000, myFunction);
}
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
//write out count
countDownObj.innerHTML = i;
if (i == 0) {
//execute function
fn();
//stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
},
pause
);
}
//set it going
countDownObj.count(i);
}
function myFunction(){};
</script>
HTML
<div id="countDown"></div>
try this, timer restarts after 0
http://jsfiddle.net/GdkAH/1/
Full code:
window.onload = function() {
startCountDown(25, 1000, myFunction);
}
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
// write out count
countDownObj.innerHTML = i;
if (i == 0) {
// execute function
fn();
startCountDown(25, 1000, myFunction);
// stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
}, pause);
}
// set it going
countDownObj.count(i);
}
function myFunction(){};
​
I don't see you resetting the counter. When your counter goes down to 0, it executes the function and return. Instead, you want to execute the function -> reset the counter -> return
You can do this by simply adding i = 25 under fn() :
function startCountDown(i, p, f) {
var pause = p;
var fn = f;
var countDownObj = document.getElementById("countDown");
countDownObj.count = function(i) {
// write out count
countDownObj.innerHTML = i;
if (i == 0) {
// execute function
fn();
i = 25;
// stop
return;
}
setTimeout(function() {
// repeat
countDownObj.count(i - 1);
},
pause
);
}
// set it going
in #Muthu Kumaran code is not showing zero after countdown 1 . you can update to this:
if (i < 0) {
// execute function
fn();
startCountDown(10, 1000, myFunction);
// stop
return;
}
The main reason for using setInterval for a timer that runs continuously is to adjust the interval so that it updates as closely as possible to increments of the system clock, usually 1 second but maybe longer. In this case, that doesn't seem to be necessary, so just use setInterval.
Below is a function that doesn't add non–standard properties to the element, it could be called using a function expression from window.onload, so avoid global variables altogether (not that there is much point in that, but some like to minimise them).
var runTimer = (function() {
var element, count = 0;
return function(i, p, f) {
element = document.getElementById('countDown');
setInterval(function() {
element.innerHTML = i - (count % i);
if (count && !(count % i)) {
f();
}
count++;
}, p);
}
}());
function foo() {
console.log('foo');
}
window.onload = function() {
runTimer(25, 1000, foo);
}

Categories

Resources