'JavaScript click event not occurring while busy
I seem to have a concurrency problem of some kind trying to get a click event to occur. The problem is that I am running an animation using setInterval, but the stop button is not triggering, probably because the JavaScript is busy. If I click on the "stop" button really fast over and over I can get it to stop. The code looks like this:
var timer_id = null;
function play(){
timer_id = setInterval( function(){
time_second++;
if( time_second == 60 ){
time_minute++;
time_second = 0;
}
render();
}, 1000 / time_compression_factor );
console.log( "timer id: " + timer_id );
}
function stop(){
console.log( "stopped" );
if( timer_id != null );
clearInterval( timer_id );
timer_id = null;
}
function drawVCRControls(){
var width_timeslice = 7 + 3;
var ul_x = 20 + 120 * width_timeslice + 15;
var ul_y = viewportHeight - 40;
var pathPlayBack = "m 20 0 l 10 -8 l 0 16 Z";
var pathStop = "m 35 -8 l 16 0 l 0 16 l -16 0 Z";
var pathPlayForward = "m 57 0 l 0 -8 l 10 8 l -10 8 Z";
var pathStepBack = "m 12 20 l 10 -8 l 0 16 Z m 13 -8 l 5 0 l 0 16 l -5 0 Z";
var pathPause = "m 35 12 h 6 v 16 h -6 Z m 10 0 h 6 v 16 h -6 Z ";
var pathStepForward = "m 57 12 h 5 v 16 h -5 Z m 8 0 l 10 8 l -10 8 Z";
createPath( "vcrPlayBack", ul_x, ul_y, pathPlayBack, 1, "orangered", "orange", 1, 0 );
createPath( "vcrStop", ul_x, ul_y, pathStop, 1, "orangered", "orange", 1, 0 );
createPath( "vcrPlayForward", ul_x, ul_y, pathPlayForward, 1, "orangered", "orange", 1, 0 );
createPath( "vcrStepBack", ul_x, ul_y, pathStepBack, 1, "orangered", "orange", 1, 0 );
createPath( "vcrPause", ul_x, ul_y, pathPause, 1, "orangered", "orange", 1, 0 );
createPath( "vcrStepForward", ul_x, ul_y, pathStepForward, 1, "orangered", "orange", 1, 0 );
vcrPlayForward.addEventListener( "click", function(){
play();
}, false );
vcrStop.addEventListener( "click", function(){
stop();
}, false );
}
The render() call in the play() function draws a lot of stuff, so I think when it is busy drawing it is essentially ignoring the click event on the vcrStop button. I can see this because I have a console.log statement that records whenever stop() gets called and it is not getting called when I click the vcrStop button.
I know the handler is operating correctly because if I click the vcrStop button before starting the animation it gets logged to the console.
Note that if I run the interval at 1 second then everything works fine, but the shorter the interval is, the harder it is to stop the animation. For example if I use a 500ms interval I might have to click two or three times to stop it, but if I use a 100ms interval (the desired interval), I have to click really fast 10 times or more.
How can I solve this problem?
Solution 1:[1]
It would be helpful to have a JSFiddle for your specific problem, that would be very helpful.
I think your problem is exactly what you state - the script is busy. The thing is that JavaScript is executed in a single threaded manor. Thus, the click event can only be handled after the rendering is done. To make a cancellation of the rendering possible, you could split your rendering in several steps and call each in a chained callback, i.e., after the first one is done, call the second step of rendering if and only if the process was not cancelled.
Anyways, you mention that you have a console.log for the click. After the rendering is done, do you see the log's output?
Solution 2:[2]
Yes, you may be right, the render() may be blocking the click event to be triggered. But also the click event takes some time to triggered as it's a combination of mousedown and mouseup events. Which may be greater than your interval. You can try with mousedown event which I think takes lesser time than click to bubble.
Good luck
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Philipp |
| Solution 2 | Kishore Barik |
