I did not manage to pass i as parameter from onready() into setInterval(), so meanwhile I parsed the loop:
function myFunc() {
myWidgets[0].onready = function(){
setInterval( function(){
var pVal = $('#Pv1').text();
myWidgets[0].setValue(pVal);
}, 1000);
};
myWidgets[1].onready = function(){
setInterval( function(){
var pVal = $('#Pv2').text();
myWidgets[1].setValue(pVal);
}, 1000);
};
myWidgets[2].onready = function(){
setInterval( function(){
var pVal = $('#Pv3').text();
myWidgets[2].setValue(pVal);
}, 1000);
};
How can I add i as parameter?
the following did not work , i is undefined in the internal function in setInterval:
myWidgets[i].onready = function(i){
setInterval( function(i){
var j = i + 1;
var pVal = $('#Pv' + j).text();
myWidgets[i].setValue(pVal);
}, 1000);
};
You could use enclosure to make the current value of i accessible throught onready:
for (var i=0;i<3;i++) {
(function(x){
myWidgets[x].onready = function(){
setInterval(function(){
var pVal = $('#Pv' + (x+1) ).text();
myWidgets[x].setValue(pVal);
}, 1000);
}
})(i);
}
Without an enclosure, the reason why it fails to use the current value of i is that it won't use the value at the current step of the loop. Rather than that, it will use the value of i when onready occurs, which is already maxed as the loop is over.
You could simply use a function enclosure.
for (var i=0; i<3; i++) {
(function(i) {
myWidgets[i].onready = function() {
setInterval(function(){
var pVal = $('#Pv'+(i+1)).text();
myWidgets[i].setValue(pVal);
}, 1000);
};
})(i);
}
Try this. The case you are referring to is closure
myWidgets = [];
for(var i = 0; i < 3; i++) {
myWidgets[i].onready = (function(i){
return function(){setInterval( function(){
var pVal = $('#Pv' + (i+1) ).text();
myWidgets[i].setValue(pVal);
console.log(i)
}, 1000);}
})(i);
}
What you can do, but i dont know if it is the answer on your question.
for(var i = 0; i < 3; i++) {
myWidgets[i].onready = function(){
setInterval( function(){
var pVal = $('#Pv' + (i+1) ).text();
myWidgets[i].setValue(pVal);
}, 1000);
};
}
It has everything to do with scopes and callback. Your solution does not work because the callback function of onReady does not know the context, for example does not know the i.
You can make this better with jQuery. (each widget has a class myWidget)
$('.myWidget').ready(function () {
var element = $(this); // is the widget of your code.
setTimeout(function () { element.val(element.val()*1 + 1); });
});
You need to read the documentation of the APIs you are trying to use.
https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval
will tell you this:
Syntax
var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
var intervalID = window.setInterval(code, delay);
Borrowing code from the answer by #Haneev it can be written as follows.
I am using j as formal parameter to make it obvious it is not using i from the outer scope.
for(var i = 0; i < 3; i++) {
myWidgets[i].onready = function(){
setInterval( function(j){
var pVal = $('#Pv' + (j+1) ).text();
myWidgets[j].setValue(pVal);
}, 1000, i);
};
}
Related
I want to print a heading tag only after a paragraph tag is loaded. Below is my Javascript code. See the plunker for more clarification: http://embed.plnkr.co/aheHkSQUBft5A4Z3wkie/preview
function changeText(cont1, cont2, speed){
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30);
clearInterval(Otimer);
});
$(document).ready(function() {
changeText($("h2"), $(".h2"), 30);
clearInterval(Otimer);
});
I would do something like this (please not that ES6 Promises aren't supported by Internet Explorer, but there are shims to use Promises with old browsers too).
You'll have to fill out the parts commented to get it to work though:
var Otimer;
/*#TODO: refactor show() function to use ES6 Promises (eventually with shims) */
function show(Ocontent) {
var i = 0;
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
if (Otimer === undefined) {
Otimer = setInterval(show, speed); // Remember to fulfill the promise and remove the interval once it's finished
}
// return the promise
};
function changeText(p1, p2, speed) {
var Otext = p1.text();
var Ocontent = Otext.split("");
return show(Ocontent);
};
$(function () {
changeText($("p"), $(".p2"), 30).then(function() { // We call changeText the second time after the promise return by changeText() is fulfilled and the show() function has finished
Otimer = undefined;
changeText($("h2"), $(".h2"), 30);
});
});
first of all, variable declaring inside of function is scoped variable, which You cannot access from outside of the function.
so the line clearInterval(Otimer); never works.
the code below is fixed code of the scope issue and using callback to implement what you want.
function changeText(cont1, cont2, speed, cb) {
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i++;
}else{
clearInterval(Otimer)
if(cb) cb()
}
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30, function(){
changeText($("h2"), $(".h2"), 30);
});
});
http://plnkr.co/edit/xowItFUWqI79obi4ZVNV?p=preview
Lets see this script, that it's a simple carrousel
$script = {
init: function(){
this.heros(3000);
},
heros: function (time) {
var t;
var $hero = $('.hero');
var $images = $('.hero > div');
$hero.data('current', 0);
var $bullets = $('<div>').addClass('bullets');
for ( var i = 0; i<$images.length; i++ ) {
var $item = $('<span>');
$item.on('click', function () {
clearTimeout(t);
play( $(this).index() );
});
if(i==0) { $item.addClass('active') }
$bullets.append( $item );
}
var play = function (current) {
if(current==undefined) {
current = $hero.data('current');
}
var nextMargin;
if ( (current+1) == $images.length ) {
nextMargin = 0 ;
$hero.data('current',0);
} else {
nextMargin = (current + 1 )*100;
$hero.data('current', (current + 1));
}
$images.eq(0).css('marginLeft', -nextMargin + '%');
$bullets.find('span').eq($hero.data('current')).addClass('active').siblings().removeClass('active');
clearTimeout(t);
t = setTimeout(play, time);
}
$hero.append($bullets);
t = setTimeout(play, time);
},
}
The thing is that it works great, but only if there's just one .hero element.. if there are multiple the bullets mix up and it doesn't respect the .length
I know that option one should be rewrite it again, but Does anyone of you sees a quick fix that would make it reusable?
A single fiddle: https://jsfiddle.net/6z8n5pnq/
A multiple fiddle: https://jsfiddle.net/6z8n5pnq/1/
-EDIT-
I tried:
Defining a previous function, that is called on init
preheros: function(time) {
var self = this;
$('.heros').each(function(){
self.heros($(this), time);
});
},
And editing The begining of heros:
heros: function ($hero, time) {
var t;
/*var $hero = $('.hero');*/
var $images = $hero.find('>div');
but no success...
any idea?
-EDIT-
GOD, it's $('.hero').each not $('.heros').each it was working!
The easiest way to do this is to isolate context for each .hero component by using $(selector).each function. Slightly corrected your fiddle https://jsfiddle.net/6z8n5pnq/2/
function apply($hero, time){
var t;
var $images = $hero.children('div');
//all your logic here...
}
$script = {
init: function () {
this.heros(3000);
},
heros: function (time) {
$('.hero').each(function(){
apply($(this), time);
});
},
}
I want to set interval between clicks with this code. This is the script :
var inputs = document.getElementsByClassName('class-name');
for(var i=0; i<inputs.length;i++) {
inputs[i].click();
}
You can either set a bunch of time outs
var inputs = document.getElementsByClassName('class-name');
for (var i = 0; i < inputs.length; i++) {
(function(i){
setTimeout(function () {
inputs[i].click();
}, 1000 * i);
})(i);
}
or you can just use an interval
(function() {
var inputs = document.getElementsByClassName('class-name'),
current = 0,
timer = window.setInterval(
function () {
var input = inputs[current];
if (input) {
input.click();
current++;
} else {
window.clearInterval(timer);
}
}
,1000);
}());
Try this:
var inputs = document.getElementsByClassName('class-name');
for (var i = 0; i < inputs.length; i++) {
(function(i){
// to get the actual value of i
setInterval(function () {
inputs[i].click();
}, 1000);
})(i);
}
Regarding to servers API, i should limit requests to 3 per second.
Here is my code:
groups.forEach(function (group) {
Api.simpleRequest(uri).then(function (res){
// processing result
}, function(err) {
// error handling
});
});
What i tried to do:
1.
for (var i=0; i < groups.length; i++) {
(function (index){
setTimeout(function() {
Api.simpleRequest(url).then() //...
}, 1000);
})(i);
};
Tried to use WinJS.Promise.timeout(1000) as then continue of my promise.
Both options does not work for me.
Just found working solution, but with setInterval() instead of setTimeout()
var i = 0;
var length = groups.length - 1;
var timer = setInterval(function() {
Api.simpleRequest(uri).then() //...
if (i == groups.length) {
clearInterval(timer);
};
i++;
});
i have a loop function that in first 5 seconds it runs social1() and in second 5 seconds it runs social2() then loop ...
i have 2 hover functions too
i need clear all active timeouts because when i hover on images (.social1 & .social2), i can see that multiple timeouts are running
how to fix this?
function social1() {
$('.social1').fadeTo(500, 1);
$('.social2').fadeTo(500, 0.5);
timeout = setTimeout(function() {
social2();
}, 5000);
}
function social2() {
$('.social1').fadeTo(500, 0.5);
$('.social2').fadeTo(500, 1);
timeout = setTimeout(function() {
social1();
}, 5000);
}
$(document).ready(function ()
{
social1();
$('.social1').hover(
function () {
window.clearTimeout(timeout);
social1();
},
function () {
timeout = setTimeout(function() {
social2();
}, 5000);
}
);
$('.social2').hover(
function () {
window.clearTimeout(timeout);
social2();
},
function () {
timeout = setTimeout(function() {
social1();
}, 5000);
}
);
__EDIT__
To manage a collection of timeouts (and intervals), you could use following snippet.
This will allow to clear any timeouts or intervals set anywhere in code, although, you have to set this snippet before setting any timeout or interval. Basically, before processing any javascript code or external script which uses timeout/interval.
JS:
;(function () {
window.timeouts = {},
window.intervals = {},
window.osetTimeout = window.setTimeout,
window.osetInterval = window.setInterval,
window.oclearTimeout = window.clearTimeout,
window.oclearInterval = window.clearInterval,
window.setTimeout = function () {
var args = _parseArgs('timeouts', arguments),
timeout = window.osetTimeout.apply(this, args.args);
window.timeouts[args.ns].push(timeout);
return timeout;
},
window.setInterval = function () {
var args = _parseArgs('intervals', arguments),
interval = window.osetInterval.apply(this, args.args);
window.intervals[args.ns].push(interval);
return interval;
},
window.clearTimeout = function () {
_removeTimer('timeouts', arguments);
},
window.clearInterval = function () {
_removeTimer('intervals', arguments);
},
window.clearAllTimeout = function () {
_clearAllTimer('timeouts', arguments[0]);
},
window.clearAllInterval = function () {
_clearAllTimer('intervals', arguments[0]);
};
function _parseArgs(type, args) {
var ns = typeof args[0] === "function" ? "no_ns" : args[0];
if (ns !== "no_ns")[].splice.call(args, 0, 1);
if (!window[type][ns]) window[type][ns] = [];
return {
ns: ns,
args: args
};
}
function _removeTimer(type, args) {
var fnToCall = type === "timeouts" ? "oclearTimeout" : "oclearInterval",
timerId = args[0];
window[fnToCall].apply(this, args);
for (var k in window[type]) {
for (var i = 0, z = window[type][k].length; i < z; i++) {
if (window[type][k][i] === timerId) {
window[type][k].splice(i, 1);
if (!window[type][k].length) delete window[type][k];
return;
}
}
}
}
function _clearAllTimer(type, ns) {
var timersToClear = ns ? window[type][ns] : (function () {
var timers = [];
for (var k in window[type]) {
timers = timers.concat(window[type][k]);
}
return timers;
}());
for (var i = 0, z = timersToClear.length; i < z; i++) {
_removeTimer(type, [timersToClear[i]]);
}
}
}());
How to use it:
Set timeout(s)/interval(s) as usual:
var test1 = setTimeout(function(){/**/, 1000);
var test2 = setTimeout(function(){/**/, 1000);
Then you could use to clear both:
clearAllTimeout(); // clearAllInterval(); for intervals
This will clear both timeouts (test1 & test2)
You can use some namespaces to clear only specific timers, e.g:
// first (optional) parameter for setTimeout/setInterval is namespace
var test1 = setTimeout('myNamespace', function(){/**/, 1000); // 'myNamespace' is current namespace used for test1 timeout
var test2 = setTimeout(function(){/**/, 1000); // no namespace used for test2 timeout
Again, clearAllTimeout(); will clear both timeouts. To clear only namespaced one, you can use:
clearAllTimeout('myNamespace'); // clearAllInterval('myNamespace'); for namespaced intervals
This will clear only test1 timeout
You could for some reason wish to delete non namespaced timeouts only. You could then use:
clearAllTimeout('no_ns'); // clearAllInterval('no_ns'); for non namespaced intervals only
This will clear only test2 timeout in this example
See jsFiddle DEMO
__END of EDIT__
Old post specific to opening question here:
You could try that:
var timeouts = [];
timeouts.push(setTimeout(function() {
social2();
}, 5000));
timeouts.push(setTimeout(function() {
social1();
}, 5000));
//etc...
function clearAllTimeouts(){
for(var i = 0, z = timeouts.length; i < z; i++)
clearTimeout(timeouts[i]);
timeouts = [];
}
UPDATED following David Thomas comment
var timeouts = {'social' : [], 'antisocial' : []};
//a social timeout
timeouts.social.push(setTimeout(function() {
social1();
}, 5000));
//an anti-social timeout
timeouts.antisocial.push(setTimeout(function() {
antisocial1();
}, 5000));
function clearTimeouts(namespace){
for(var i = 0, z = timeouts[namespace].length; i < z; i++)
clearTimeout(timeouts[namespace][i]);
timeouts[namespace] = [];
}
//usage e.g
clearTimeouts("social");
//Incase if you are looking for full fledged code
var dict = {};
function checkForIntervals(id){
var index = index;
var result = findOrAddProperty(id);
if(result.length != 0){
clearTimeoutsFor(id);
}
dict[id].push(setTimeout(function(){alertFunc(id,index);}, 60000));
};
// to clear specific area timeout
function clearTimeoutsFor(namespace){
for(var i = 0, z = dict[namespace].length; i < z; i++)
clearTimeout(dict[namespace][i]);
dict[namespace] = [];
}
to clear all timeouts
function clearAllTimeOuts(){
for (key in dict) {
for(var i = 0, z = dict[key].length; i < z; i++)
clearTimeout(dict[key][i]);
dict[key] =[];
}
};
function findOrAddProperty(str){
var temp = [];
for (key in dict) {
if(key == str){
if (dict.hasOwnProperty(key)) {
temp = dict[key];
break;
}
}
}
if(temp.length == 0){
dict[str] = [];
}
return temp;
};
function alertFunc(id,index) {
jQuery(document).ready(function($) {
do the ajax call here after 1 min
});
};