Button click event image hiding is delayed

  • Context: JavaScript 
  • Thread starter Thread starter Bob Walance
  • Start date Start date
  • Tags Tags
    Html Image Javascript
Click For Summary
SUMMARY

The forum discussion addresses the issue of delayed image hiding in a web application due to the use of a blocking sleep function within a JavaScript event handler. The user initially implemented a sleep function to manage timing but discovered that it prevents the browser from updating the display until the function completes. The solution provided involves replacing the sleep function with an asynchronous approach using setTimeout, allowing the image to hide immediately while other processes continue. This method ensures that the user interface remains responsive and updates as intended.

PREREQUISITES
  • Understanding of JavaScript event handling
  • Familiarity with asynchronous programming concepts
  • Knowledge of the Document Object Model (DOM) manipulation
  • Experience with the setTimeout function in JavaScript
NEXT STEPS
  • Learn about JavaScript Promises and async/await syntax
  • Explore the use of the AudioScheduledSourceNode and its events in the Web Audio API
  • Investigate the tone.js library for audio synthesis and manipulation
  • Study best practices for managing asynchronous operations in JavaScript
USEFUL FOR

Web developers, particularly those working with JavaScript and audio applications, as well as anyone looking to improve their understanding of asynchronous programming and event-driven design in web environments.

Bob Walance
Insights Author
Gold Member
Messages
84
Reaction score
55
TL;DR
The style.visibility = 'hidden' image attribute is not taking effect until end of sleep function
My webpage project has a button labeled 'Harmonics' with a mouse-click event. I want an image to be hidden as soon as the button is clicked, however this doesn't happen.

Here's a snippet of the html. It doesn't matter what order the two Javascript functions are called. The 'hidden' attribute for the image does not take effect until the sleep function completes.

gwd.Harmonics = function(event) {
document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
sleep(2000); // delay for 2000ms

Can anyone tell me if this can be fixed so that the image is hidden as soon as the button is clicked?
 
Technology news on Phys.org
PeterDonis said:
Why is the sleep function there at all?
I'm just using a sleep function here to simply demonstrate the issue. The real project is playing a tone and I need to know when the tone has ended. There is an event-driven mechanism for this but it is unreliable so I'm using a simple date/time-based timer in order to know when to start the next tone.
 
Bob Walance said:
I'm just using a sleep function here to simply demonstrate the issue.
Unfortunately, the issue you are running up against, at least as I understand how the Javascript engine works, is simple: your function is an event handler and Javascript doesn't update the browser display to reflect any changes the event handler makes until after the handler returns. So you can't put any kind of time delay tracking mechanism in an event handler because it delays updating the browser display.

Bob Walance said:
There is an event-driven mechanism for this but it is unreliable
How so?
 
PeterDonis said:
Unfortunately, the issue you are running up against, at least as I understand how the Javascript engine works, is simple: your function is an event handler and Javascript doesn't update the browser display to reflect any changes the event handler makes until after the handler returns. So you can't put any kind of time delay tracking mechanism in an event handler because it delays updating the browser display.
PeterDonis said:
How so?
1 - I was afraid of that. That's really how it appears to be behaving. Darn.
2 - I think that the audioContext tone generation 'onend' event issue is related to "Javascript doesn't update the browser display..." operation that you pointed out.

My app's purpose is to demonstrate the difference, musically, between equal-temperament tuning and simple harmonics of an instrument note (nature). The part of the app that plays one tone or chord works perfectly. When I need a sequence of tones (e.g. in a musical scale) then I run into these issues.

I have a complete application written and working in Python, but I can't distribute the Python code here. That's why I'm attempting to get it to work in a web browser.
 
Bob Walance said:
2 - I think that the audioContext tone generation 'onend' event issue is related to "Javascript doesn't update the browser display..." operation that you pointed out.
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/ended_event

Bob Walance said:
My app's purpose is to demonstrate the difference, musically, between equal-temperament tuning and simple harmonics of an instrument note (nature). The part of the app that plays one tone or chord works perfectly. When I need a sequence of tones (e.g. in a musical scale) then I run into these issues.
Perhaps you might be better off using the tone.js module I showed you on another thread.

Bob Walance said:
I have a complete application written and working in Python, but I can't distribute the Python code here. That's why I'm attempting to get it to work in a web browser.
Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.
 
pbuk said:
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/
Perhaps you might be better off using the tone.js module I showed you on another thread.

Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.

pbuk said:
There is no AudioContext onend event. Perhaps you are thinking of the AudioScheduledSourceNode ended event: https://developer.mozilla.org/en-US/docs/Web/API/AudioScheduledSourceNode/ended_eventPerhaps you might be better off using the tone.js module I showed you on another thread.Programming for the web is very different from programming in Python, you need to completely change your mindset to write asynchronous, event driven code rather than the blocking code you are used to.

I did look at tone.js but I don't think it'll do what I want. For example, I need to play two major chords:
A + C# + E
and
440Hz + 550Hz + 660Hz

They both sound close but the latter is much sweeter sounding. The beat frequency produced between the C# and the fifth harmonic of 110Hz is very obvious when it's juxtaposed with the natural major third interval.
 
jedishrfu said:
Maybe this will work:

https://www.codegrepper.com/code-ex...+to+reload+page+on+button+click+in+javascript

It's likely an ugly solution, but from it, you might find a better way.

Thanks. I'm aware of this and am utilizing it to make repeated musical scales more reliable (I'm not sure where the real issue is there).

I should have been a software engineer. Their life is SO much easier overall. They can just sit at their computers all day sipping their Daiquiris while us EEs have to go into the lab and inhale lead fumes.
 
  • #10
Sadly, you have a romanticized view of software engineers. Yes, we can code but a lot of time is spent tracking down your own or other people's misguided coding mistakes, and some can be downright impossible to find in a timely fashion.

So revel in the fact that you are a talented engineer learning the ropes of programming.
 
  • Like
Likes   Reactions: Bob Walance
  • #11
There is actually no sleep function in javascript. And if you keep javascript busy in a different fashion, all other activity is on hold as @PeterDonis already pointed out. Moreover, if you keep javascript busy for too long (a couple of seconds), the browser will complain that a script is causing trouble and ask if you want to kill it.

If you do want to sleep, then the relevant function is setTimeout, which takes a callback that will be called after a time. During this time all other activity resumes and the browser will display anything that was changed.

If you want to wait for it and continue what you were doing, then you can use:
Code:
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
gwd.Harmonics = async function(event) {
  document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
  await sleep(2000); // delay for 2000ms
  // Other processing
}
Note that the sleep is implemented using setTimeout, and all other activity will resume during this time so your element will immediately become invisible.
 
Last edited:
  • Love
Likes   Reactions: Bob Walance
  • #12
I like Serena said:
If you want to wait for it and continue what you were doing, then you can use:
Code:
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
gwd.Harmonics = async function(event) {
  document.getElementsByClassName('gwd-img-17a0')[0].style.visibility = 'hidden'; // hide the image
  await sleep(2000); // delay for 2000ms
  // Other processing
}
Note that the sleep is implemented using setTimeout, and all other activity will resume during this time so your element will immediately become invisible.
YES! Your solution works perfectly. I was just about to give up and try a different approach, but you completely solved my problem.

Thank you very much, liker of Serena.
 
  • Like
Likes   Reactions: I like Serena

Similar threads

  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 2 ·
Replies
2
Views
5K
  • · Replies 8 ·
Replies
8
Views
3K