JavaScript: Display array items after 3 seconds one a time - javascript

I have the code segment:
var i = 0;
(function loop() {
text_objects[i].displayText();
if (++i < text_objects.length) {
setTimeout(loop, 3000);
}
})();
Which is supposed to display the contents of an array one at a time, separated by 3 seconds. However, when I run the program, I only get the first item, and it sort of just freezes there, without updating and showing the rest of the items in the array.
What am I doing wrong?

As correctly mentioned by #nnnnnn,
loop() is a named function expression, and the reference loop should be in scope within the function
Also your code works fine.
var i = 0;
var test = function(value){
this.text = value;
}
test.prototype.displayText = function(){
document.write(this.text + "<br/>");
}
var text_objects = [];
for (var j = 0; j<10; j++){ text_objects.push(new test(j)); }
(function loop() {
text_objects[i].displayText();
if (++i < text_objects.length) {
setTimeout(loop, 3000);
}
})();
Alternate approach:
var i = 0;
function loop() {
document.write(i + "<br/>")
if (++i < 5) {
setTimeout(loop, 3000);
}
}
loop();

This works fine. Not sure if this is what you expect?
var i = 0;
Array.prototype.displayText = function(i) {
console.log(this[i]);
};
var text_objects = ['1', '2', '3'];
(function loop() {
text_objects.displayText(i);
if (++i < text_objects.length) {
setTimeout(loop, 3000);
}
})();

Following is my approach to the answer. Hope I helped!
var i = 0;
function loop() {
text_objects[i].displayText();
i = i + 1;
if (i < text_objects.length) {
setTimeout(loop, 3000);
};
};
setTimout(loop, 3000);

Related

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">

java script Foreach loop

Javascript
function myFunction() {
for (i = 0; i < 5000;) {
setTimeout(function() {
document.getElementById("demo").innerHTML = i;
}, i);
i += 500;
}
}
HTML
<body onload="myFunction()">
<div id="demo"></div>
How to increase " i " every 5ms and print it in #demo every time it changes
I am trying to make a look that increases the value of ( i ) once every 5ms, and prints it out in # demo.
Right now, the value 5000 immediately prints out as soon as I run the script for some reason, as opposed to increasing by 500 every time.
Thanks in advance.
You can change myFunction to:
var i = 0;
function myFunction() {
var timerId = setInterval(function(){
if(i >= 5000)
{
clearInterval(timerId);
}
document.getElementById("demo").innerHTML = i;
i +=500;
}, 5);
}
this should work.
var i=0;
function looper(){
setTimeout(function(){
console.log(i+" data");
i=i+500;
if(i<5000)
looper();
}, i);
}
looper();
function myFunction() {
var i = 0;
var max = 5000;
var step = 500;
var intervalMs = 5;
var interval = setInterval(function() {
// clear interval if one step before max value
if (i >= max-step) {
clearInterval(interval);
}
// increment i by step
i+=step;
// set inner html of div
document.getElementById("demo").innerHTML = i;
}, intervalMs)
}
Plunkr: https://plnkr.co/edit/IfkGOpjUnf4sKpN4iCZ4?p=preview
If you want your code to look similar to what you have, you can use an IIFE:
function myFunction() {
for (i = 0; i <= 5000;i += 500) {
(function(index) {
setTimeout(function() {
document.getElementById("demo").innerHTML = index;
}, index);
})(i);
}
}
<body onload="myFunction()">
<div id="demo"></div>
</body>
You are having an issue with the closure not saving a reference to your timeout. Subsequent arguments after the second are passed into the callback function as arguments.
Here we are passing i as the third argument
setTimeout(fn, delay, i)
Then in the callaback we have access to the i, we are reassigning it to x within the scope of the callback.
function myFunction() {
for (i = 0; i <= 5000; i = i + 500) {
setTimeout(function(x) {
document.getElementById("demo").innerHTML = x;
}, i, i);
}
}
myFunction()
<div id="demo"></div>
function myFunction(max, ii = 0) {
document.getElementById('demo').innerHTML = ii
if (ii < max) {
setTimeout(myFunction, 500, max, ii + 500)
}
}
myFunction(5000)
<div id="demo"></div>
**
<div id="demo"></div>
<script>
function myFunction() {
var i = 0;
var setClock = function() {
if (i < 5000) {
local = i;
i += 500;
setTimeout(function() {document.getElementById("demo").innerHTML = local; setTimeout(setClock, 500);},
500);
}
}
setClock();
}
**
you should wrap scripts in tags
the javascript Closures. You should know that because of the Closures, second parameters for all setTimeout() are 5000, which is the i's final value. You can avoid the Closure by the codes I showed or erase the impact of Closure by below codes:
<div id="demo"></div>
<script>
function myFunction() {
var local;
for (i = 0; i < 5000; i+= 500) {
local = i;
setTimeout((function(interval){
return function() {document.getElementById("demo").innerHTML = interval;} ;
})(local), (function(interval){return interval})(local));
}
}

Displaying image from array in Javascript in setTimeInterval method

I am having little bit difficulty time pausing the image, so it gets rendered. I have images stored in even index in an array (for example: 2, 4, 6). And using for loop, I want to change the image every 2 seconds. On the load of the HTML page, I call onLoad = executeOnLoad() in HTML. The image changes from default to the image that is in sixth index, but after that it is not changing. It stays on that same index although, the console says the i is changing.
function executeOnLoad(){
for(var i = 0; i < 7; i++){
if (i%2 == 0) {
console.log("started.."+i);
displayImage(i);
}
}
}
function displayImage(i){
console.log("displaying...." + i);
document.getElementById("initial_image").src = contentArray[i];
}
window.setInterval("executeOnLoad()", 1000);
This is the console output that repeats every 1 sec but image is not changing:
started..0
displaying....0
started..2
displaying....2
started..4
displaying....4
started..6
displaying....6 < ---- The image here is displayed but, not changing to other..
I appreciate your help. Thanks.
I've created a fiddle for you that shows even numbers.
I've used the if statement instead of the for loop you had because that would run all the loop in one go.
See it working here:
var contentArray = ["0.png","1.png","2.png","3.png","4.png","5.png","6.png","7.png","8.png"]
var i = 0;
var numberOfImagesToDisplay = 6;
var speedOfAnimation = 1000;
function executeOnLoad(){
if(i <= numberOfImagesToDisplay){
if (i%2 == 0) {
displayImage(i);
i = i+2;
} else {
i++;
}
} else {
i=0;
displayImage(i);
}
}
function displayImage(img){
document.getElementById("initial_image").src = "http://www.marcelogil.com/fiddle/jsloop/" + contentArray[img];
}
window.setInterval("executeOnLoad()", speedOfAnimation);
<img src="http://www.marcelogil.com/fiddle/jsloop/0.png" id="initial_image" />
There is no pause in your code. That loop just runs through all of your images and therefore only the last one will "stick".
You can fix this by using settimeout:
console.clear();
document.body.innerHTML = '';
//START
var contentArray = [
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg',
'https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg',
'https://pixabay.com/static/uploads/photo/2016/01/14/01/41/image-view-1139204_960_720.jpg',
'https://i.vimeocdn.com/video/552738927_1280x720.jpg'
]
var initImg = document.createElement("img");
initImg.id = "initial_image";
initImg.src = '';
document.body.appendChild(initImg);
function executeOnLoad() {
for (var i = 0; i < 7; i++) {
if (i % 2 == 0) {
(function (a) {
setTimeout(function () {
console.log("started.." + a);
displayImage(a);
}, 1000 * (a + 1))
})(i);
}
}
}
function displayImage(i) {
console.log("displaying...." + i, contentArray[i]);
document.getElementById("initial_image").src = contentArray[i];
}
executeOnLoad();
See this code, with some small changes. The interval does not have a loop inside it, but a single action. Each time the setInterval callback is called (i.e every one second) it goes one step further, until reaching the maximum desired length (which is 7, but should probably be contentArray.length) and then the interval clears itself. Clearing the interval is possible thanks to saving a refernce to it when declaring it (var interval = window.setInterval(...) and using the clearInterval method.
var i = 0, interval;
function executeOnLoad(){
i++;
if (i%2 == 0) {
console.log("started.."+i);
displayImage(i);
}
if (i >= 7) {
clearInterval(interval);
}
}
function displayImage(i){
console.log("displaying...." + i);
document.getElementById("initial_image").src = contentArray[i];
}
interval = window.setInterval(executeOnLoad, 1000);
Check this:
var i = 0;
var contentArray = [];
contentArray.push('https://img.utdstc.com/icons/256/beautiful-life-quotes-android.png');
contentArray.push('https://img.utdstc.com/icons/monospace-android.png');
contentArray.push('https://img.utdstc.com/icons/cloud-print-android.png');
contentArray.push('https://img.utdstc.com/icons/120/desire-the-game-for-couples-android.png');
function displayImage(){
console.log("displaying...." + i);
if(i < ((contentArray.length) - 1)){
i++;
}else{
i = 0;
}
document.getElementById("initial_image").src = contentArray[i];
window.setTimeout( displayImage, 4000);
}
displayImage();
<img id="initial_image"/>
See a working example on JSFiddle

Delay time between each clicks on class

I have some loop like below..which clicks all buttons
for(var i = 1;i<document.querySelectorAll(".myclass").length;i++){
document.querySelectorAll(".myclass")[i].click();
console.log("hi");
};
but I want to add sleep function that delays each loop like sleep(2000); , Is there any function in javascript like that ?
I tried below code , but does not work
for(var i = 1;i<document.querySelectorAll(".myclass").length;i++){
setTimeout(function() {
document.querySelectorAll(".myclass")[i].click();
console.log("hi");
}, (3 * 1000));
};
var myVar = setInterval(myTimer, 2000);
var divIndex = 0;
function myTimer() {
if(divIndex < document.querySelectorAll(".myclass").length){
document.querySelectorAll(".myclass")[divIndex].click();
console.log(divIndex);
}else {
clearInterval(myVar);
}
divIndex++;
}
<div class='myclass'></div>
<div class='myclass'></div>
<div class='myclass'></div>
<div class='myclass'></div>
Create the new function as give and call that function inside your loop.
function sleep(milliseconds) {
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds) {
}
}
for (i = 0; i < 3; i++) {
console.log(i);
sleep(5000);
}

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