1

I need the browser to update my UI before a long(er) operation is done. Currently the browser is waiting until after everything is complete and then updating the UI, which means UI freezes for 1-2 seconds then updates.

So, user clicks button in UI, then this code executes:

$('#mybutton').click(function(e) {

e.preventDefault();// prevent the default anchor functionality

$('#mainctrldiv').css('display', 'none');
$('#otherctrldiv').css('display', 'block');

var img = $('<img id="spareimg" style="display:none;">');
img.attr('src', canvas.getActiveObject().toDataURL()); // This is causing the delay!
img.appendTo('body');
}

It's the canvas.getActiveObject().toDataURL() (a FabricJS function) that is taking the time. I want this to happen after the 2 divs have been visibly displayed to the user, to they don't notice. Need this to work in all commonly used browsers out there! (mobile as well as desktop).

Research suggested that reading the css display properties immediately after setting them would force the browser to repaint so I added in the following code straight after setting these properties but the delay still occurred:

$('#mainctrldiv').css('display');
$('#otherctrldiv').css('display');

Many thanks for any suggestions!

Alex Kerr
  • 956
  • 15
  • 44
  • What do you mean by `delay`? If the canvas is too large, converting it to a data `URL` might block the main thread for a noticeable amount of time. How exactly does the delay manifest? – XCS Apr 11 '16 at 16:47
  • Could toss a hidden, disabled checkbox at some point in the dom that can see both `#mainctrldiv` and `#otherctrldiv` and have css rules that toggle which gets `display:none` and `display:block` based on that checkbox being `:checked`. However, I have a feeling this has something to do with how jQuery is managing things, rather than strictly what it's trying to do. – abluejelly Apr 11 '16 at 16:53
  • `$('#mainctrldiv').css('display');` is incomplete. Did you mean `$('#mainctrldiv').css('display', 'block');` ? – XCS Apr 11 '16 at 17:04
  • @Cristy Thanks. As mentioned the delay is 1 - 2 seconds. The user clicks the button in the UI with ID '#mybutton' and the div swap over (one div being hidden the other shown) should be instant, but instead everything freezes - even the button becoming deselected freezes - until the canvas.getActiveObject().toDataURL() is complete. I know that's responsible because commenting it out fixes the problem. – Alex Kerr Apr 11 '16 at 19:29
  • @Cristy you wrote " If the canvas is too large, converting it to a data URL might block the main thread for a noticeable amount of time" - yes I know, that's why I'm posting here :) I need to delay the data URL conversion until after the divs have been updated (as per the flow of the code) but the browsers is combining all operations before it repaints, so I need a workaround! – Alex Kerr Apr 11 '16 at 19:31

1 Answers1

6

Try using setTimeout with zero delay, it will push these to the end of the thread. You can also try adding some delay if zero delay doesn't work for you. But I am not sure if that exact line is causing the issue, if it is post another question on how to optimise and decrease the time.

$('#mybutton').click(function(e) {
  e.preventDefault(); // prevent the default anchor functionality
  $('#mainctrldiv').css('display', 'none');
  $('#otherctrldiv').css('display', 'block');
  setTimeout(function() {
    var img = $('<img id="spareimg" style="display:none;">');
    img.attr('src', canvas.getActiveObject().toDataURL()); // This is causing the delay!
    img.appendTo('body');
  }, 0);
}

It's important to note that the function or code snippet cannot be executed until the thread that called setTimeout() has terminated.

Community
  • 1
  • 1
sabithpocker
  • 15,274
  • 1
  • 42
  • 75