Function Won't Recurse - javascript

I am attempting to make a 'web player' that plays music when you click the play button, and displays how far along you are in the track on a bar. I have made a function that plays the audio and checks how far along the track you are to set the width of the playback bar, but for the life of me i can't get it to recurse. I know the function works, because the playback bar jumps to the correct position when you click the play button, but i cant seem to automate it. Here is the code:
function play(x) {
var audio = document.getElementById(x);
audio.play();
var progress = audio.currentTime;
var duration = audio.duration;
var percent = progress/duration;
var width = percent*100;
var progbar = document.getElementById("play-line-elapsed");
var width = width + "%";
progbar.style.width = width;
setTimeout(play("Bring-Out-Yer-Dead"), 5000);
}
const createClock = setInterval(play, 100);
I have tried while loops, do while loops, setTimeout and finally setInterval so far. I am also a complete beginner to javascript, so it'll probably be completely obvious when someone points it out to me. Thanks in advance

Here is the code that should work
function play(x) {
var audio = document.getElementById(x);
audio.play();
var progress = audio.currentTime;
var duration = audio.duration;
var percent = progress/duration;
var width = percent*100;
var progbar = document.getElementById("play-line-elapsed");
var width = width + "%";
progbar.style.width = width;
setTimeout(function () {play("Bring-Out-Yer-Dead")}, 5000);
}
const createClock = setTimeout(function () {play("Bring-Out-Yer-Dead")}, 100);
What you did was to create an interval that calls play every 0.1 seconds, without any arguments. I suppose that wouldn't work as the function requires an argument.
Your setTimeout at the end of play wouldn't work too, because you're just calling it. You should provide a function object (not very correct word, but you get it) to setTimout, not calling it. The way you did it is to call play and give its return value (which is undefined) to setTimout, which makes setTimeout do nothing.
The corrected code creates a timeout that calls play after 0.1 seconds, then play continues to call itself every 5 seconds.
You have to provide a 0 arity function to setTimeout/setInterval, meaning a function that accepts no arguments. I used an anonymous function for that, but you could write another function with no arguments and use it there.
But I think you would be better off using events. I haven't tested any of these, but these events seem promising for what you are trying to do.
https://www.w3schools.com/jsref/event_ondurationchange.asp
https://www.w3schools.com/jsref/event_onplaying.asp
https://www.w3schools.com/jsref/event_onplay.asp

Related

Wanting html/js canvas to update everytime it goes through my loop

I'm newer to js coding and I can't find any answers to my question. I'm working with the tag in html and trying to get my JS code to redraw the canvas when I want. I've tried using a simple while loop to do it, but that just goes through the while loop then draws the end result without showing the updates in between. My current code (below is using the setTimeout/clearTimeout calls, but it produces the same result. Not sure if this is even possible. Maybe it's just how I'm updating my canvas?
This is my code for calling my function to update my arrays I'm storing my data in and then update the canvas.
var done = false;
var count = 0;
while (!done) {
timer = setTimeout(updateGrid(grid), 500);
clearTimeout(timer);
done = stop(count, allDone);
count++;
}
The functions I'm using to draw on the canvas:
context = canvas.getContext("2d");
context.fillStyle = color;
context.fillRect(x, y, w, h);
Is there something I'm missing?
clearTimeout is nullifying your updateGrid timeout.
I think what you want is to use setInterval instead. But you can also use setTimeout and adjust the timeout time (500 * (i + 1) or something) and set up all your timeouts like that
while (!done) {
timer = setTimeout(updateGrid(grid), 500);
clearTimeout(timer); //this is nullifying the line above
done = stop(count, allDone);
count++;
}

Display a series of colors sequencially with JavaScript

I need to display a series of RGB colors inside my ASP.NET web page. I was hoping to accomplish this using an ASP Update Panel but the update has to take place in sequence without the user intervention, every 4 or 5 seconds.
My initial JavaScript code looks like this :
document.getElementById('div').style.backgroundColor = "rgb(0,0,255)";
Problem is getting the next RGB color combination to display.
I experimented with a wait 'loop' found here in another post :
wait(7000); //7 seconds in milliseconds
function wait(ms) {
var start = new Date().getTime();
var end = start;
while (end < start + ms) {
end = new Date().getTime();
}
}
Problem is that, it does not work. I tried with :
document.getElementById('fondRGB').style.backgroundColor = "rgb(0,0,255)";
wait(7000);
document.getElementById('fondRGB').style.backgroundColor = "rgb(128,128,128)";
wait(7000);
document.getElementById('fondRGB').style.backgroundColor = "rgb(0,0,0)";
but only the very first rgb color is ever honored?
running a blocking while loop in javascript is a really bad idea. There is only one thread so if you do that the user will not be able to interact with your application until your while loop is complete.
A better solution is to use setTimeout to run the timer asynchronously and call the callback when the timer is complete.
var el = document.getElementById('fondRGB')
function wait(ms, callback) {
setTimeout(callback, ms)
}
wait(7000, function(){
el.style.backgroundColor = "rgb(0,0,255)"
})
wait(14000, function(){
el.style.backgroundColor = "rgb(128,128,128)"
})
wait(21000, function(){
el.style.backgroundColor = "rgb(0,0,0)"
})
So even if that did work it wouldn't be what you want since the wait function is attempting to block the only execution thread which would just make the whole browser hang. The wait method you are looking for is called setTimeout and it works a little different than you are probably used to.
setTimout lets you specify a function and an amount of milliseconds before it will execute that function so in your case if you want to accomplish changing the background color every 7 seconds you would probably do something like this:
var colors = ['rgb(0,0,255)', 'rgb(128,128,128)', 'rgb(0,0,0)'];
for (var i = 0; i < colors.length; i++) {
setTimeout(function(color) {
document.getElementById('fondRGB').style.backgroundColor = color;
}.bind(null, colors[i]), i * 7000);
}
Sorry that the code got a little complex, look up closures if you are wondering why the .bind part is necessary (if you are not already familiar).

Turn a button into a loading circle animation

I would like to reproduce the animation below :
http://gph.is/1MILWlq
I found this but i would not have the progress bar (the loading time will not be defined) :
http://tympanus.net/Tutorials/CircularProgressButton/
How can I do it ?
You can add an event listener to temporarily replace it with an image and then have the callback of the ajax (or whatever happens) perform a replacement of it. In my example, I just used setTimeout to have it replace the button again after 3 seconds. Normally that functionality would go inside of the ajax callback (or whatever else it was waiting on):
Here's a jsFiddle example: https://jsfiddle.net/jetweedy/m0qpm1xh/2/
var myButton = document.getElementById('myButton');
var myParent = document.getElementById('myParent');
myButton.onclick = function() {
myParent.removeChild(myButton);
var myImage = document.createElement("img");
myImage.src = "http://chimplyimage.appspot.com/images/samples/classic-spinner/animatedCircle.gif";
myParent.appendChild(myImage);
setTimeout(function() {
myParent.removeChild(myImage);
myParent.appendChild(myButton);
}, 3000);
};
An alternative would be to write some JavaScript to gradually decrease/increase its size, position, color, and other properties while it processes whatever it's processing, and then (again, inside the callback) put a stop to all that (by ending a setInterval that you had initiated) after you're done.

setInterval works then hangs browser javascript

I'm wanting to animate an element using setInterval. I've put my code into an object with 2 functions one to initialize and one to animate using setInterval. When I try to run the code the animation works once then causes the browser to hang. The only thing I can think of is an infinite loop being created somewhere however I can't see anywhere in my code that would cause this.
What is causing the browser to crash, how can this be overcome ?
<div id='box' style='position:absolute;height:100px;width:100px;background-color:#44e'>box</div>
<script>
var box = {
init : function(elemId) {
box.elem = document.getElementById(elemId);
box.timer = setInterval;
box.tick = 0;
box.animate();
},
animate: function() {
if(box.tick < 100) {
box.elem.style.top = box.tick +'px';
box.elem.style.left = box.tick +'px';
box.tick++;
} else {
clearInterval(box.timer);
}
var timer = setInterval(box.animate, 50)
}
}
box.init('box');
</script>
setInterval sets up a function that will be called repeatedly by the browser until you cancel the interval timer. Your code isn't doing that, because the only call to clearInterval is using box.timer, which is never set to a timer handle (the return value from setInterval). So you end up scheduling thousands of calls (a new series every time animate is called) and bringing the browser to its kneeds.
At the very least, this:
var timer = setInterval(box.animate, 50)
should probably be:
box.timer = setInterval(box.animate, 50);
Or you may want setTimeout (which schedules only one call back).

JavaScript setTimeout Runs Twice

I am trying to make a function that starts in exact intervals to keep stanble update rate. The problem is that it seems to execute in 2 channels. This is the log:
timeElapsed=141; lastDraw=1314040922291
timeElapsed=860; lastDraw=1314040923151
timeElapsed=141; lastDraw=1314040923292
timeElapsed=860; lastDraw=1314040924152
timeElapsed=141; lastDraw=1314040924293
timeElapsed=860; lastDraw=1314040925153
timeElapsed=141; lastDraw=1314040925294
timeElapsed=860; lastDraw=1314040926154
timeElapsed=141; lastDraw=1314040926295
timeElapsed=859; lastDraw=1314040927154
timeElapsed=143; lastDraw=1314040927297
timeElapsed=858; lastDraw=1314040928155
timeElapsed=143; lastDraw=1314040928298
timeElapsed=858; lastDraw=1314040929156
timeElapsed=142; lastDraw=1314040929298
First, I exectute my function using
drawTimer = setTimeout(function(){ draw() }, 1);
and the function looks like this:
var draw = function(){
if(!running)
return;
var miliseconds = getCurrentMiliseconds();
var timeElapsed = miliseconds - lastDraw;
lastDraw = miliseconds;
console.log("timeElapsed=" + timeElapsed + "; lastDraw=" + lastDraw);
onDrawListener(timeElapsed);
if(timeElapsed < timeLapse)
miliseconds = timeLapse - timeElapsed;
else
miliseconds = 1;
drawTimer = setTimeout(function(){ draw() }, miliseconds);
}
It happens in both, Chrome and Firefox. Do you know what is it caused by? And... How to fix it?
P.S. Since everyone seems to be so confused about the running variable, here it is: it's a private parent object member that indicates whether the mechanism is still running or has stopped. It's set by other functions and is just there to make sure this function doesn't continue working after stop() is called.
-- update --
timeLapse is set to 1000 (1 time per seconds) and never changed again.
onDrawListener is set to this function:
function(timeElapsed){
canvas.clear();
moveSnake();
if(snake.body[0] == food){
food = getRandomFreePosition();
++snake.body.lenght;
}
drawBackground();
drawFood();
drawSnake();
}
to explain it: canvas is kinda the engine that takes care of callbacks, key listening and also has a few functions. Other than that seems kinda self-explaining. they do nothing other than some int algorithms and drawing in the canvas.
-- Figured out --
I understood that I should calculate time spent for current function and not since the last one started. My old method worked not in 2 channels but rather in long-short-long-short-long-... delayes
first of all you dont set the running bool and also when you enter the function immediately do a on clearTimeout on drawTimer.
clearTimeout(drawTimer);
In a loop like that, you should consider to write:
if(timeElapsed >= AMOUNT_OF_TIME)
{
// run code
}

Categories