Javascript output during function loop - javascript

Is there an easy way to output content when inside a Javascript loop, rather than have it display on screen after the loop has completed.
Code e.g:
var c = 0;
while (c <=1000 ){ //100000
run();
c++;
}
function run() {
console.log(c);
$('#data').append(c);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<div id="data"></div>
It outputs to console straight away (during loop) but on screen does not.
Hoping someone can assist.
Thanks!

Are you wanting to write it to the webpage?
If so then you can write it to a div using the InnerHTML
document.getElementById("yourDivID").innerHTML = yourString;

Your browser's Javascript engine is too fast thus you cannot see the changes in real time. So set a timer and slow down the process.
Run the below code and see the magic happens...
var c = 0;
$(document).ready(function () {
run();
});
function run() {
var timer = setInterval(function () {
//console.log(c);
$('#data').append(c + "\n");
if (c++ == 1000) {
clearInterval(timer);
}
}, 12); //set time in milliseconds
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data"></div>
These are the changes made to your code :
Removed the while loop and replaced it with setInterval()
Added $(document).ready() function to make sure the run() is executed after the DOM is fully loaded.

Try using clousres and setTimeout:
function run(c) {
console.log(c);
$('#data').append(c + ', ');
}
$(function() {
for (var c = 1; 999 > c; c++) {
(function(c) {
setTimeout(function() {
run(c);
}, 1);
})(c);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="data"></div>

Related

setInterval() halts while code is executing

I was under the impression that setInterval(function, delay) would schedule a call to function every delay milliseconds. It would repeatedly do this until clearInterval() was called. However, it seems I'm missing something.
I have the following sample page. The intent is simple: have the text switch from Loading -> Loading. -> Loading.. every second. Here's a sample of the loop working as expected:
$(document).ready(function(){
$('#loading_icon').html("Loading");
loop = setInterval(function() {
updateText();
}, 1000);
});
function updateText() {
loadingText = $('#loading_icon').html();
$('#loading_icon').html(loadingText == "Loading" ? "Loading." :
loadingText == "Loading." ? "Loading.." :
"Loading");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="loading_icon">Loading</div>
Nothing to it. The issue is that it doesn't execute this code so long as JavaScript is doing anything else. I've set the up following example:
$(document).ready(function(){
$('#loading_icon').html("Loading");
loop = setInterval(function() {
updateText();
}, 1000);
for(i = 0; i < 100000; i++)
var a = fib(i); // Just an arbitrary method to simulate work
});
function fib(n){
var a=1,b=0,t;while(n>=0){t=a;a=a+b;b=t;n--;}return b;
}
function updateText() {
loadingText = $('#loading_icon').html();
$('#loading_icon').html(loadingText == "Loading" ? "Loading." :
loadingText == "Loading." ? "Loading.." :
"Loading");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="loading_icon">Loading</div>
Ideally, the text would be changing while we were doing all this work (that's the whole reason I'm writing this "loading" feature, after all). However, it seems that no calls to updateText() are being called until JS has nothing better to do.
What am I missing here? Is there any way to accomplish what I'm after?
Your understanding of setInterval() seems to be correct. It should not be halting code outside of its callback function. Most likely your code is getting caught up somewhere else.
As for accomplishing what you're trying to do, your solution should work but it's not a very elegant way of manipulating the DOM. I see that you're using jQuery, which has pretty robust animation functionality. I would look into using something like this.
Yes, it still works - the problem is that your loop over fib is running first, then setInterval is running later. You can decrease the loop length to see it working perfectly:
$(document).ready(function() {
$('#loading_icon').html("Loading");
loop = setInterval(function() {
updateText();
}, 1000);
for (i = 0; i < 100000; i++)
var a = fib(i); // Just an arbitrary method to simulate work
});
function fib(n) {
var a = 1,
b = 0,
t;
while (n >= 0) {
t = a;
a = a + b;
b = t;
n--;
}
return b;
}
function updateText() {
loadingText = $('#loading_icon').html();
$('#loading_icon').html(loadingText == "Loading" ? "Loading." :
loadingText == "Loading." ? "Loading.." :
"Loading");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="loading_icon">Loading</div>
Unfortunately, you can't make an extremely long loop and a setInterval run at exactly the same time.

Countdown in JS

I'm trying to have, on a registered.php page, a countdown that shows a timer that starts from 3 secs and goes down second by second, redirecting to another page in the end.
However, when I load the page in my browser i'm redirected to the other page in an instant. Can someone help me figure out why?
The registration was successful, you will be redirected in <span id="num"></span> seconds.
<script>
$(document).ready(function (){
for (var i = 3; i>0; i--) {
setTimeout(function () {
$("#num").html(i);
},1000);
}
window.location.replace("login.html");
});
</script>
Since this is a redirection page, you might not want to include the whole jQuery library for this bit of code:
var remaining = 3;
function countdown() {
document.getElementById('num').innerHTML = remaining;
if (!remaining--) {
window.location.replace("login.html");
}
setTimeout(countdown, 1000);
}
window.onload = countdown;
JS Fiddle Demo
Proper way:
$(document).ready(function () {
var i = 3;
$("#num").html(i);
setInterval(function () {
if(i==0){window.location.replace("login.html");}
i--;
$("#num").html(i > -1 ? i : 0);
}, 1000);
});
setInterval would execute every second the function, but with the code you had, you just set setTimeout to execute after a second, but it didn't stop you from looping further. So you immediately had three timeouts set and then redirected.
$(document).ready(function () {
var timer = 3;
var clearTime = setInterval(function(){
$("#num").html(timer--);
if(timer == 0){
window.clearInterval(clearTime);
window.location.replace("login.html");
}
},1000);
});

JQuery not executing within a For loop

Im a JQuery noob trying to write a simple jQuery code to get a text to blink three times. My initial code was as follows:
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
}
});
But since I probably meddled in forces I could not comprehend, the above code made the text blink only once. I read up on closures and got convinced that the below code could make a change. Unfortunately, it doesnt.
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
(function (i) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
})(i);
}
});
Can anyone tell me whats going on here?
You need make use of the animation queue
var $welcome = $("#welcome").click(function () {
var i = 1;
//clear previous animations
$welcome.stop(true, true);
while (++i < 10) {
$welcome.fadeOut("slow").fadeIn("slow");
}
});
Demo: Fiddle
Fading in and out takes some time, and you have to wait for your animation to be over before you can run the next one.
The provided answers solve your problem since jQuery is clever enough to bufferize your animation queue, but it may creates even more confusion for begginers, and also if you want to do something else between the fading animations, you can't rely on it anymore.
You then have to write your code on what is called an asynchronous recursive way (woah). Simply trying to understand that snippet may help you a lot with javascript general programming.
function blink(nbBlinks) {
// Only blink if the nbBlinks counter is not zero
if(nbBlinks > 0) {
$('#welcome').fadeOut('slow', function() {
// Do stuff after the fade out animation
$(this).fadeIn('slow', function() {
// Now we're done with that iteration, blink again
blink(nbBlinks-1);
})
});
}
}
// Launch our blinking function 10 times
blink(10);
This works perfectly. Demo http://jsfiddle.net/X5Qy3/
$("#welcome").click(function () {
for (var x = 0; x < 3; x += 1) {
$("#welcome").fadeOut("slow");
$("#welcome").fadeIn("slow");
}
});
Also, if you know how many times you want to do something. You should use a For Loop. While Loops are for when you don't know how many times you want it to run.
Set in queue
$("#welcome").click(function () {
var i = 1;
//clear animations whcih are running at that time
$(this).stop(true, true);
while (++i < 10) {
$(this).fadeOut("slow").fadeIn("slow");
}
});
You can not use jQuery delay function inside a looping/iteration hence you have to user closures:
$(document).ready(function(){
$(".click1").click(function () {
for (i=0;i<=10;i++) {
setTimeout(function(x) {
return function() {
$("#wrapper").fadeOut("slow", function () { $("#wrapper").fadeIn("slow"); })();
};
}(i), 1000*i);
}
});
});
<div id="wrapper"></div><div class="click1">click</div>
You can later change the count how many times you want to blink the <div>.

How to create a looped animation with JQuery

I have been sitting on this for a few hours and cannot figure this out. I am trying to create an slideshow (3 slides) that loops endlessly. Each slide is a li inside #slideshow. I have walked through this with a debugger and all variables get set correctly, but I don't understand why the animations dont actually happen. I have this which ends up displaying all images on the page:
$(document).ready(function() {
$slideshow = $('#slideshow');
$slideshowItems = $slideshow.find('li');
$slideshowItems.hide();
nextI = function(x) {
if ((x+1) < $slideshowItems.length) {
return x+1;
}
else {
return 0;
}
}
animation = function(i) {
$slideshowItems.eq(i).fadeIn(500).delay(1000).fadeOut(500, animation(nextI(i)));
}
animation(0);
If I do:
$slideshowItems.eq(0).fadeIn(500).delay(1000).fadeOut(500,
$slideshowItems.eq(1).fadeIn(500).delay(1000).fadeOut(500,
$slideshowItems.eq(2).fadeIn(500).delay(1000).fadeOut(500));
This works as expected, but it seems ugly and does not loop.
Any idea why I can't get this to work? I feel it is something with my expectations of how JQuery/ JS modifies the DOM or the sequence that the browser uses to execute animations. Thank you for the help!
var $slideshowItems = $('#slideshow').find('li'),
i = 0;
(function loop() {
$slideshowItems.eq( i ).fadeIn(500).delay(1000).fadeOut(500, loop);
i = ++i % $slideshowItems.length;
})();
JSFIDDLE DEMO
You should specify a callback method but your "animation(nextI(i))" returns nothing, so nothing remains to do after the fade out is complete.
Something like this I think will work:
var animation = function(i) {
$slideshowItems.eq(i).fadeIn(500).delay(1000).fadeOut(500, function (){
animation(nextI(i));
});
}
I would try setting that as a function and then using setInterval:
setInterval(function(){
$slideshowItems.eq(0).fadeIn(500).delay(1000).fadeOut(500, function() {
$slideshowItems.eq(1).fadeIn(500).delay(1000).fadeOut(500, function() {
$slideshowItems.eq(2).fadeIn(500).delay(1000).fadeOut(500);
});
});
}, 6000); // 6000 milliseconds before loops

How do you display a message once a JavaScript function restarts?

I'm wanting to know how to put a message in every time the timer starts over. And here is my code thus far:
<head>
<script type="text/javascript">
var c=10;
var t;
var timer_is_on=0;
function timedCount() {
document.getElementById('txt').value = c;
c = c - 1;
if (c == 0)
c = 10;
}
function doMining() {
if (!timer_is_on) {
timer_is_on = true;
t = setInterval(function () {
timedCount();
}, 1000);
}
}
</script>
<SPAN STYLE="float:left">
<form>
<input type="button" value="Mining" onClick="doMining()">
<input type="text" id="txt">
</form>
</SPAN>
2 easy steps:
Create a place for your message to show up (i.e. another web element)
In your conditional, when your counter reaches 0, update the message element's value
Here's an example:
<div id='message'></div>
Then, access that element and append your message or modify your method using DOM traversal (preferably using a javascript framework such as dojo or jquery but you can also do it manually):
if (c == 0) {
var _message = document.createTextNode("Timer has finished!");
document.getElementById('message').appendChild(_message);
c = 10;
}
Also, don't put a SPAN around a form. Try a "div" instead. Span's are meant for styling in-line document elements.
Edit: I'm assuming when you say "start over" you mean when the c = 0 or the timer has run 10 times. When it "starts over" could also mean when the method is re-called by the timer (i.e. every 1 second, in which case you'd just put the update code at the top of the function)
You are already catching this event in your "if (c == 0)". Just add the extra code you need there?
You need to better define what it means to start over. Try pulling it out into its own method so you can work with it separately.
<script type="text/javascript">
var c=10;
var t;
var timer_is_on=0;
function timedCount() {
document.getElementById('txt').value = c;
c = c - 1;
if (c == 0)
startOver();
}
function startOver() {
alert("Starting Over, Fool!");
c = 10;
clearTimeout(t);
timer_is_on=0;
doMining();
}
function doMining() {
if (!timer_is_on) {
timer_is_on = true;
t = setInterval(function () {
timedCount();
}, 1000);
}
}
</script>

Categories