Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

178
Visualizações
Styling isn't applying in Javascript

I'm trying to hide the text of a button and show a spinner in its place while processing something. However no styling is applied even though the classes get properly toggled to the right value as I see on the Developer Tools.

function toggleSpinner() {
    $('button span').toggleClass('display-none');
    $('button .fa-spinner').toggleClass('display-none');
}

function generateGrid(size) {
    let arr = getRandomNumbers(size);

    toggleSpinner(); // <--- HIDE TEXT SHOW SPINNER
    $('.grid').empty();

    let html = '';
    arr.forEach((element) => {
        html += '<div class="box">' + element.toLocaleString() + '</div>';
    });
    $('.grid').append(html);

    toggleSpinner(); // <--- HIDE SPINNER SHOW TEXT
}

And this is my HTML:

<button>
    <span>Generate Random Numbers</span>
    <i class="fas fa-spinner fa-spin display-none"></i>
</button>

Generating the grid sometimes takes like 3 seconds depending on the size of the grid and during that time, I would like to show the spinner on the button instead of the text.

More Info

The first time toggleSpinner() gets called, I expect the button to only display a spinning icon without the text. The second time toggleSpinner() gets called, I expect the spinning icon to go away and the button's text to show up again.

What's happening is that even though the classes get toggled, it's like the browser isn't repainting the page until everything is done so in effect, it's like toggleSpinner() gets called twice which results to the same classes from the beginning resulting in no changes to the button.

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

Changes to the DOM are not being rendered because generating the grid is blocking the event loop. Hence running generateGrid asynchronously should solve the issue. However just running it as an asynchronous function and waiting for it to finish (using await), or putting the code directly in a promise handler, risks putting processing in the microtask queue - which also blocks the event loop.

This example simulate "generating the grid" by simply running a loop for 3 seconds. It is called from a timer call with an additional callback argument to signal when it has done. The calling function, makeGrid returns a promise this is fulfilled when processing has completed:

"use strict";
function toggleSpinner() {
    $('button span').toggleClass('display-none');
    $('button .fa-spinner').toggleClass('display-none');
}

function makeGrid(size) {
    toggleSpinner(); // show spinner
    return new Promise( resolve => {
        setTimeout( generateGrid, 0, size, function() {
            toggleSpinner(); // hide spinner
            resolve();
        });
    });
}
function generateGrid( size, done) {
   // dummied code just to run synchonously for 3 seconds
    const end = Date.now() + 3000;
    while( Date.now() < end);
    done();  // callback when done
}


function test() {
   console.log( "calling makeGrid");
    makeGrid(1).then( ()=>console.log("makeGrid finished"));
}
.display-none {
   display: none;
}
.fa-spinner:before {
   content: "⏳";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" crossorigin></script>

<!-- body-html -->
<button>
    <span>Generate Random Numbers</span>
    <i class="fas fa-spinner fa-spin display-none"></i>
</button>
<p>
<button onclick="test()">test</button> <-- click here to test

about 4 years ago · Juan Pablo Isaza Relatório

0

It's rudamentary and there are probably better ways but one option is to take the first toggleSpinner out of the method and use a timeout, which then calls your generateGrid function. This gives the CSS and class toggles time to do their thing before the render blocking of the generateGrid happens.

function toggleSpinner() {
    $('button span').toggleClass('display-none');
    $('button .fa-spinner').toggleClass('display-none');
}

function getRandomNumbers(size) {
  return new Array(size).fill('foo')
}

function generateGrid(size) {
    let arr = getRandomNumbers(size);

    $('.grid').empty();

    let html = '';
    arr.forEach((element) => {
        html += '<div class="box">' + element.toLocaleString() + '</div>';
    });
    $('.grid').append(html);
    
    toggleSpinner()
}

$('button').on('click', () => {
  toggleSpinner()
  setTimeout(() => { generateGrid(100000); }, 1000)
  
})
.display-none { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>
    <span>Generate Random Numbers</span>
    <i class="fas fa-spinner fa-spin display-none">SPINNING</i>
</button>
<div class="grid"></div>

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda