0

I'm trying to make a CSS Rotator(Loader) visible after pressing a button. Then processing something and afterwards hiding the Rotator. But it seems that while processing the display:block atribute is set but not visible (See console logs). How could I archive this? Thank you for your help!

Simplified code example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />           
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script>

        function test(){

            $('#loader').css("display","block");

            console.log($('#loader').css("display"));

            do_something();

            console.log($('#loader').css("display"));

            $('#loader').css("display","none");

            console.log($('#loader').css("display"));

        }

        function do_something(){
            for (var i=0; i<=10E9; i++){

            }
        }

        $(document).ready(function() {

            $('#loader').css("display","none"); 
            $('#test_btn').click(test);

        }); 
    </script>
</head>

<body>
    <div id="loader">Loader</div>
    <button id="test_btn">test</button>
</body>

</html>
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
starcd
  • 15
  • 2

2 Answers2

0

I just think your :

for (var i=0; i<=10E9; i++){
}

Make your page laggy since it's iterate a lot of time and can't update. Don't really know why.

But if you try to wait with a timer, it's working :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />           
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script>

        function test(){

            $('#loader').css("display","block");
            setTimeout(
        function() 
     {
        $('#loader').css("display","none");
            }, 1000
  );
           
             }



        $(document).ready(function() {

            $('#loader').hide(); 
            $('#test_btn').click(test);

        }); 
    </script>
</head>

<body>
    <div id="loader">Loader</div>
    <button id="test_btn">test</button>
</body>

</html>
  • Indeet - in real its looping through a big array do some operations. The loop takes some seconds to finish. That's why I need the Loader CSS... For simplification I used the: for (var i=0; i<=10E9; i++) – starcd Jan 08 '20 at 16:11
  • What happens is that the attribute is modified, but because 2 instructions later you perform a long task, the browser never has time to apply visual tweaks. – Artur Jan 08 '20 at 16:52
  • How can I give the browser the time for the visual tweaks? – starcd Jan 08 '20 at 17:17
0

Browser doesn't update the DOM or change styling until your JS execution halts (which we are achieving using setTimeout. see my code below). That means if you set some element.style.[...] = "...", it won't kick in until your code finishes running (either completely, or because the browser sees you're doing something that lets it intercept processing for a few ms).

JS:

function show() {
    $('#loader').css("display", "block");
}

function hide() {
    $('#loader').css("display", "none");
}

function newTest() {
    show();    
    setTimeout(() => {
        do_something();
        hide();
    }, 50);
}

function do_something() {
    for (var i = 0; i <= 1000; i++) {
        console.log('i ', i);
    }
}

$(document).ready(function () {
    $('#loader').css("display", "none");
    $('#test_btn').click(newTest);
});

Html:

<div id="loader">Loader</div>
<button id="test_btn">test</button>

I would suggest to read the answer given by @Mike 'Pomax' Kamermans Here

Abhishek Raj
  • 480
  • 4
  • 14
  • Time setTimeout does matter - In my Case tthe loader was OK with Timeout 0 on the first Click. But on the second click it was not. I increased the timeout to 1000 to had reliable DOM Update. But Thx for your helpful answer! – starcd Jan 10 '20 at 15:59
  • You are right @starcd, in case of setTimeout time 0, sometimes it is not working properly. – Abhishek Raj Jan 11 '20 at 03:49