Creating a delay in for-loop iterations - javascript

I've written the following function with hopes to add 1px onto the top margin to animate a window sliding out of the page.
Currently it works fine and removes the window from the page, However I'm having problems creating the delay interval in each iteration of the for loop. I've thought about using setTimeout(), but with this I cant just break; the for loop I have to call a function,
Any ideas?
function slideOut() {
var obj = document.getElementById("cInstructs");
var orig = 66;
for(i=0; i<2000; i++) {
orig++;
obj.style.marginTop = orig+"px";
}
};
Thanks in advance!

A suggestion would be to check the jQuery .slideDown() function- http://api.jquery.com/slideDown/

var i;
function incrAndDelay(i) {
setTimeout(...);
i+=1;
return i;
}
function slideOut() {
var obj = document.getElementById("cInstructs");
var orig = 66;
for(i=0; i<2000; incrAndDelay(i)) {
orig++;
obj.style.marginTop = orig+"px";
}
};
Still have to call a function but not in the loop body.

var intId;
function slideOut() {
clearInterval(intId);
var count = 0;
var obj = document.getElementById("cInstructs");
var orig = 66;
intId = setInterval(function(){
orig++;
obj.style.marginTop = orig+"px";
if((++count == 2000)){
clearInterval(intId);
}
}, 100);
}

Related

Having real trouble combining 2 JS

I am struggling combining two JS into one… I try and try in the JSFiddle but can not really understand the console erros…
I am trying to have a background-color that changes combined with a changing background .svg in a div…
$(document).ready(function() {
//Initializing
var i = 0;
var images = []; //array
var time = 3000; // time in millie seconds
//images
images[0] = "url(http://www.cyrill-kuhlmann.de/verve/img/logo_1.svg)";
images[1] = "url(http://www.cyrill-kuhlmann.de/verve/img/logo_2.svg)";
images[2] = "url(http://www.cyrill-kuhlmann.de/verve/img/logo_3.svg)";
images[3] = "url(http://www.cyrill-kuhlmann.de/verve/img/logo_4.svg)";
//function
function changeImage() {
var el = document.getElementById('header');
el.style.backgroundImage = images[i];
if (i < images.length - 1) {
i++;
} else {
i = 0;
}
setTimeout('changeImage()', time);
}
window.onload = changeImage;
$(function setbackground() {
window.setTimeout( "setbackground()", 2000);
var index = Math.round(Math.random() * 4);
var ColorValue = "FA89CB";
if(index == 1)
ColorValue = "FAED96";
if(index == 2)
ColorValue = "D27DFA";
if(index == 3)
ColorValue = "6CFA64";
if(index == 4)
ColorValue = "8370FA";
document.getElementsByTagName("body")[0].style.backgroundColor = "#" + ColorValue;
});
});
Here's my fiddle:
http://jsfiddle.net/gmck02ru/1/
does somebody have a clue – i guess I am not really understanding what I am doing here so far...
Help please!
The issue is because the syntax you've used to define the setbackground() function is incorrect. You've placed it inside a jQuery object. That function is also never called. You should define it as a standalone function and invoke it when the page loads.
In addition there's a few improvements you can make to the logic.
Use addEventListener() over setting the onclick or other onX event properties.
Declare the elements of the array at the same time as you define the array itself.
Use an array to hold the background colours instead of hard-coding an if statement.
Use the modulo operator when incrementing the counter to save having to write logic to reset to 0
If you want to repeatedly update the background colour, as you do for the images, place the setTimeout() call within the setbackground() function.
Use document.body directly instead of getting it by tag name
$(document).ready(function() {
let i = 0;
let images = [
"url(http://www.cyrill-kuhlmann.de/verve/img/logo_1.svg)",
"url(http://www.cyrill-kuhlmann.de/verve/img/logo_2.svg)",
"url(http://www.cyrill-kuhlmann.de/verve/img/logo_3.svg)",
"url(http://www.cyrill-kuhlmann.de/verve/img/logo_4.svg)"
];
let backgroundColours = ['#FAED96', '#D27DFA', '#6CFA64', '#8370FA']
function changeImage() {
let el = document.getElementById('header');
el.style.backgroundImage = images[i];
i = ++i % (images.length - 1)
setTimeout(changeImage, 3000);
}
changeImage();
function setbackground() {
let index = Math.round(Math.random() * 4);
document.body.style.backgroundColor = backgroundColours[index];
setTimeout(setbackground, 2000);
}
setbackground();
});
Working jsFiddle - see the demo in the fiddle as the images are on an insecure domain so cannot be called from SO.

How can I reuse a function properly?

I try to make 3 basic slideshow.
I made this code for the first one and wanted to use it on the other 2 as well with the New slideS() method and with some parameter changing.But it's not working,even the first function is'nt working if I put parameter in it.
Can somebody explain me why is this not working and how to fix it?Thanks beforehand!
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
setTimeout("slideS()", 1500);
}
slideS(img)
You could do something like this, using an object oriented approach:
function SlideShow(el, imagesArray, msDelay) {
this.el = el;
this.images = imagesArray;
this.delay = (msDelay) ? msDelay : 1000;
this.timer = null;
this.Run = function () {
var self = this;
var index = 0;
this.timer = setInterval(function(){
self.el.src = self.images[index++ % self.images.length];
}, this.delay);
}
this.Stop = function() {
this.timer = null;
}
}
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var delay = 1500;
var ss = new SlideShow(img, imgArr, delay);
ss.Run();
...
ss.Stop();
Would that work for you? Then you are using pure functions and an object that can be used to start, stop, and manage any slide show.
I think you want like:
Remove setTimeout. And use setInterval:
setInterval(function(){
slideS(img)
},1500)
You could use a closure over the element and the array and use setInterval instead of setTimeout.
function slide(id, array) {
function swap() {
image.src = array[i];
i++;
i %= array.length;
}
var image = document.getElementById(id),
i = 0;
setInterval(swap, 1500);
}
slide('image1', ['http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/', 'http://lorempixel.com/400/200/']);
<image id="image1"></image>
I assume it works when the function doesn't take a parameter?
Then, the reason it would work with no parameter, but stop working with a parameter, is that the setTimeout tries to recursively call the function but doesn't pass a parameter. So you'd change that to
setTimeout(() => {slideS(a);}, 1500);
But then when you try to run multiple instances of this concurrently, you'll get into trouble because your'e using global variables. You'll need to use something more local (perhaps closures?) for your lcv, for example.
try this... you are making mistake at some places
var img = document.getElementById("asd");
var imgArr = ["1.jpg", "3.png", "3.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
setTimeout(() => slideS(a), 1500);
/* you need to pass function to setTimeout and pass refrence of image that's 'a' */
// or use function instead of arrow function
setTimeout(function() { slides(a) }, 1500);
}
slideS(img)
hope this helps..
You have to use setInterval instead of setTimeout
var img = document.getElementById("asd");
var imgArr = ["https://i.stack.imgur.com/lgt0W.png", "https://i.stack.imgur.com/X0fKm.png", "https://i.stack.imgur.com/YfPSD.png"];
var i = 0;
function slideS(a) {
a.src = imgArr[i];
if (i < imgArr.length - 1) {
i++;
} else {
i = 0;
}
}
slideS(img); //initial call to start it without having to wait for 1500 ms to pass
setInterval(function() {
slideS(img);
}, 1500);
<img id="asd">

Change img src every second using Jquery and Javascript

I have been trying to write a script that changes an image src every two seconds based on a list.
So, everything is inside a forloop that loops over that list:
$(document).ready(function() {
var lis = {{dias|safe}}; <----- a long list from django. This part of the code works fine.
for (i=0; i<lis.length; i++){
src_img = lis[i][1];
var timeout = setInterval(function(){
console.log(src_img)
$("#imagen").attr("src", src_img);
}, 2000)
}
});
It doesn't work, the console logs thousands of srcs that correspond to the last item on the list. Thanks a lot for your help.
you don't need to run cycle in this case, you just save "pointer" - curentImage and call next array item through function ever 2 sec
var curentImage = 0;
function getNextImg(){
var url = lis[curentImage];
if(lis[curentImage]){
curentImage++;
} else {
curentImage = 0;
}
return url;
}
var timeout = setInterval(function(){
$("#imagen").attr("src", getNextImg());
}, 2000)
var curentImage = 0;
var length = lis.length;
function NewImage(){
var url = lis[curentImage];
if(curentImage < length){
currentImage++;
}
else{
currentImage = 0;
}
return url;
}
var timeout = setInterval(function(){
$("#imagen").attr("src", getNextImg());
}, 2000)
PS: Better than the previous one, Checks for lis length and starts from first if you reach end.
You need something like this
$(document).ready(function() {
var index = 0;
setInterval(function(){
src_img = lis[index++ % lis.lenght][1]; // avoid arrayOutOfBounds
$("#imagen").attr("src", src_img);
}, 2000)
});

get interval ID from else statement when set in IF

I am attempting to create a responsive slider, that will change to a simple set of dot points when in mobile mode (< 940).
The issue I am facing is in my else statement I am unable to clearintervals that were made in the if statement, because t comes up as undefined. I have resorted to using
for (var i = 1; i < 99999; i++) window.clearInterval(i); to clear the interval which works, but I don't like it because it's ugly and cumbersome, is there another way of accomplishing this?
$(document).ready(function() {
function rePosition() {
//get responsive width
var container_width = $('.container').width();
//Slider for desktops only
if(container_width >= 940) {
//get variables
var slide_width = $('.slider_container').width();
var number_of_slides = $('.slider_container .slide').length;
var slider_width = slide_width*number_of_slides;
//set element dimensions
$('.slide').width(slide_width);
$('.slider').width(slider_width);
var n = 1;
var t = 0;
$('.slider_container').hover(function() {
clearInterval(t);
}, function() {
t = setInterval(sliderLoop,6000);
});
var marginSize = i = 1;
//Called in Doc Load
function sliderLoop(trans_speed) {
if (trans_speed) {
var trans_speed = trans_speed;
}
else
{
var trans_speed = 3000;
}
if (i < number_of_slides) {
marginSize = -(slide_width * i++);
}
else
{
marginSize = i = 1;
}
$('.slider').animate({ marginLeft: marginSize }, trans_speed);
}
t = setInterval(sliderLoop,6000);
$('.items li').hover(function() {
$('.slider').stop();
clearInterval(t);
var item_numb = $(this).index();
i = item_numb;
sliderLoop(500);
}, function() {
t = setInterval(sliderLoop,6000);
});
}
else
{
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
$('.slider').stop(true, true);
$('.slider').css('margin-left', '0px');
//rearrange content
if($('.slider .slide .slide_title').length < 1) {
$('.items ul li').each(function() {
var item_numb = $(this).index();
var content = $(this).text();
$('.slider .slide:eq(' + item_numb + ')').prepend('<div class="title slide_title">' + content + '</div>')
});
}
}
}
rePosition();
$(window).resize(function() {
rePosition();
});
});
Teemu's comment is correct. I'll expand on it. Make an array available to all of the relevant code (just remember that globals are bad).
$(document).ready(function() {
var myIntervalArray = [];
Now, whenever you create an interval you will need to reference later, do this:
var t = setInterval();//etc
myIntervalArray.push(t); //or just put the interval directly in.
Then to clear them, just loop the array and clear each interval.
for (var i=0; i<myIntervalArray.length; i++)
clearInterval(myIntervalArray[i]);
}
Umm, wouldn't t only be defined when the if part ran... as far as I can tell, this is going to run and be done... the scope will be destroyed. If you need to maintain the scope across calls, you'll need to move your var statements outside of reposition(), like so:
$(document).ready(function() {
var t = 0;
...
function rePosition() { ... }
});

Loop is more important than rest?

I want to execute simple code when user click on my button:
First: change my cursor to 'wait'
Next: execute loop
When loop is finished: change cursor back to 'default'
I wrote this code:
HTML:
<button type="button" id="gogogo">Go!</button>
<div id="progress">0</div>
JS:
var progress = document.getElementById('progress');
document.getElementById('gogogo').onclick = (function(){
document.body.style.cursor = 'wait';
for(var ii = 0; ii < 30000; ii += 1){
progress.textContent = ii;
}
document.body.style.cursor = 'default';
});
Live code here: http://jsfiddle.net/4Bz27/2/
And something is wrong. Loop execute first, and after that happen cursor changing.
Is it possible or any way related to asynchronous?
You are performing a blocking operation. This will certainly cause slow script warnings at some point. You can solve this by making the loop asynchronous:
var progress = document.getElementById('progress');
document.getElementById('gogogo').onclick = (function(){
document.body.style.cursor = 'wait';
var index = 0,
updater;
updater = function() {
progress.textContent = index++;
if (index < 30000) {
setTimeout(updater, 50);
} else {
document.body.style.cursor = 'default';
}
};
updater();
});
Your styles are applied only after the call stack has finished. You can separate this into two different call stacks by running the second half of the function from a setInterval like this:
var progress = document.getElementById('progress');
document.getElementById('gogogo').onclick = (function(){
document.body.style.cursor = 'wait';
setTimeout(function(){
for(var ii = 0; ii < 30000; ii += 1){
progress.textContent = ii;
}
document.body.style.cursor = 'default';
}, 0);
});
RequestAnimationFrame Way
jsFiddle here
(function (W) {
W.onload = function () {
var D = W.document,
a = 0,
c = D.getElementById('progress');
function b() {
c.innerText = a + 1;
a++;
if (a < 500) {
requestAnimationFrame(b);
} else {
D.body.style.cursor = 'default';
}
}
function start() {
D.body.style.cursor = 'wait';
b()
}
D.getElementById('gogogo').onclick = start;
}
})(window)
This way you use less resources and so your complex link modification does not slow down other open websites.
Your Loop is happening too fast for any result to be shown.
Everything is done but in about < 1ms.
You could use timeouts to delay what's being shown so that you can see what's happening.
Edit: here is the JsFiddle Link:
http://jsfiddle.net/4Bz27/9/
var progress = document.getElementById('progress');
var restoreCursor= function () {
document.body.style.cursor = 'default';
}
document.getElementById('gogogo').onclick = (function(){
document.body.style.cursor = 'wait';
var ii = 0;
// this is a immediately executed function
//that calls itself with a small timeout
(function goLoop(){
progress.textContent = ii;
if(ii<30000){
ii++;
setTimeout(goLoop,10);
}else {
restoreCursor();
}
})();
});
replace your jsFiddle by that and you're good to go.
personnally for better performance i would iterate over each frame.
like this:
var ii =0;
(function goLoop(){
progress.textContent = ii;
if(ii>3000) {
ii++;
requestAnimationFrame(goLoop);
})();

Categories

Resources