Como mostrar o carregamento do spinner no jQuery?

412

No Prototype , posso mostrar uma imagem "loading ..." com este código:

var myAjax = new Ajax.Request( url, {method: 'get', parameters: pars, 
onLoading: showLoad, onComplete: showResponse} );

function showLoad () {
    ...
}

No jQuery , eu posso carregar uma página do servidor em um elemento com isso:

$('#message').load('index.php?pg=ajaxFlashcard');

mas como anexar um controle giratório de carregamento a este comando, como fiz no Prototype?

Edward Tanguay
fonte

Respostas:

793

Existem algumas maneiras. Minha maneira preferida é anexar uma função aos eventos ajaxStart / Stop no próprio elemento.

$('#loadingDiv')
    .hide()  // Hide it initially
    .ajaxStart(function() {
        $(this).show();
    })
    .ajaxStop(function() {
        $(this).hide();
    })
;

As funções ajaxStart / Stop serão acionadas sempre que você fizer uma chamada do Ajax.

Atualização : A partir do jQuery 1.8, a documentação afirma que .ajaxStart/Stopapenas deve ser anexado document. Isso transformaria o snippet acima em:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });
nickf
fonte
48
Isso provavelmente é global demais para uma carga simples em um DIV.
31510 montrealist
363
global demais? Quantas mensagens diferentes "aguarde" você deseja?
nickf
23
dessa maneira, infelizmente, você não pode controlar o carregamento do posicionamento div, caso não queira apenas mostrar uma janela de carregamento modal, mas mostre-a perto do elemento que está esperando o conteúdo do ajax ser carregado no ...
glaz666
10
ajaxStart e ajaxStop são eventos jQuery para que possa namespace eles: stackoverflow.com/questions/1191485/... docs.jquery.com/Namespaced_Events
David Xia
10
Se estiver usando jQuery> = 1.9, anexe os eventos ajaxStart e ajaxStop a $ (document). jquery.com/upgrade-guide/1.9/…
Domenic
213

Para jQuery eu uso

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});
kr00lix
fonte
13
funciona para mim, o html deve ter algo como: <div id = 'loader'> <img src = "spinner.gif" /> </div>
yigal
7
Este foi mais limpo para mim. Em vez de ajaxSetup, eu coloquei beforeSend: e complete: dentro da instrução $ ajax ({....
kenswdev
4
Não sei quanto vale, mas o jQuery menciona na documentação que o uso de .ajaxSetup () não é recomendado. link
pec
Observe aqui que beforeSendé chamado antes de cada chamada, enquanto que ajaxStarté acionado apenas quando o primeiro método ajax é chamado. Da mesma forma ajaxStop, é chamado quando a última chamada ajax termina. Se você tiver mais de uma solicitação simultânea, o trecho nesta resposta não funcionará corretamente.
nickf
Não funciona para mim se a chamada ajax atingir o tempo limite (Firefox 28 para Mac).
Osa
48

Você pode simplesmente usar a .ajaxfunção do jQuery e usar sua opção beforeSende definir alguma função na qual possa mostrar algo como uma div do carregador e, na opção de sucesso, pode ocultar essa div do carregador.

jQuery.ajax({
    type: "POST",
    url: 'YOU_URL_TO_WHICH_DATA_SEND',
    data:'YOUR_DATA_TO_SEND',
    beforeSend: function() {
        $("#loaderDiv").show();
    },
    success: function(data) {
        $("#loaderDiv").hide();
    }
});

Você pode ter qualquer imagem de GIF animado. Aqui está um site que é um ótimo gerador de carregador AJAX de acordo com o seu esquema de cores: http://ajaxload.info/

Buscador
fonte
16
Ele successnão será chamado se houver um erro, mas "você sempre receberá um completeretorno de chamada, mesmo para solicitações síncronas", de acordo com o jQuery Ajax Events .
precisa
23

Você pode inserir a imagem animada no DOM imediatamente antes da chamada AJAX e executar uma função em linha para removê-la ...

$("#myDiv").html('<img src="images/spinner.gif" alt="Wait" />');
$('#message').load('index.php?pg=ajaxFlashcard', null, function() {
  $("#myDiv").html('');
});

Isso garantirá que sua animação inicie no mesmo quadro em solicitações subsequentes (se isso for importante). Observe que as versões antigas do IE podem ter dificuldades com a animação.

Boa sorte!

Josh Stodola
fonte
13
Dica: pré-carregue o spinner.gif em uma div com a exibição definida como nenhuma. Caso contrário, você poderá obter um efeito de spinner atrasado, pois o spinner ainda é baixado.
precisa saber é
boa dica, muito mais simples do que usar alguém do plugin
Gordon Thompson
Agradável! mas, querida, mais uma coisa que eu quero exibir girador por 2 segundos, até a página já foi carregada.
Both FM
5
@BothFM Porque as pessoas gostam de esperar pelas coisas ...?
Josh Stodola
21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

function showResponse() {
    hideLoad();
    ...
}

http://docs.jquery.com/Ajax/load#urldatacallback

Brent
fonte
Você pode ter problemas de tempo lá, não é?
Tim Büthe
2
@UltimateBrent Eu acho que você entendeu errado. Por que showLoad () não é um retorno de chamada? O JavaScript carregará o conteúdo de forma assíncrona. showLoad () funcionará mesmo antes do conteúdo ser carregado, se eu estiver correto.
Jaseem 01/12/11
2
Jaseem @ Eu uso um método semelhante também e ele realmente depende de chamadas assíncronas. Eu colocaria showLoad em algum lugar antes da chamada ajax, mas o ponto principal é mostrar um botão giratório, deixar JS iniciar a chamada e matar o botão giratório em um retorno de chamada após a conclusão do AJAX.
Nenotlep
17

Se você estiver usando, $.ajax()pode usar algo como isto:

$.ajax({
        url: "destination url",
        success: sdialog,
        error: edialog,
        // shows the loader element before sending.
        beforeSend: function () { $("#imgSpinner1").show(); },
        // hides the loader after completion of request, whether successfull or failor.             
        complete: function () { $("#imgSpinner1").hide(); },             
        type: 'POST', dataType: 'json'
    });  
Amin Saqi
fonte
11

Use o plug-in de carregamento: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});
Nathan Bubna
fonte
10
Um plugin para esta tarefa simples? Essa não é realmente uma boa solução, é? Quem quer carregar 100 scripts em uma página?
Jaseem 01/12/11
2
Acordado. Comprima e concatene, se você quiser um melhor desempenho.
Nathan Bubna
9
Discordou: separe e modularize, reutilize o código, se você quiser manter seu trabalho e solicitar que outros o façam. Qual a chance de o usuário ter uma conexão tão ruim que o cliente não pode carregar um plug-in e seu código?
precisa
@NathanBubna O link está morto
SpringLearner
"Qual a chance de o usuário ter uma conexão tão ruim que o cliente não pode carregar um plug-in e seu código?" Muito bom, eu diria.
andrew oxenburgh
9

Variante: Eu tenho um ícone com id = "logo" no canto superior esquerdo da página principal; um gif giratório é então sobreposto (com transparência) quando o ajax está funcionando.

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#logo').css('background', 'url(images/ajax-loader.gif) no-repeat')
  },
  complete: function(){
     $('#logo').css('background', 'none')
  },
  success: function() {}
});
Paulo
fonte
9

Acabei com duas alterações na resposta original .

  1. A partir do jQuery 1.8, ajaxStart e ajaxStop só devem ser anexados document. Isso torna mais difícil filtrar apenas algumas das solicitações de ajax. Soo ...
  2. A mudança para ajaxSend e ajaxComplete possibilita a interseção da solicitação atual de ajax antes de mostrar o controle giratório.

Este é o código após estas alterações:

$(document)
    .hide()  // hide it initially
    .ajaxSend(function(event, jqxhr, settings) {
        if (settings.url !== "ajax/request.php") return;
        $(".spinner").show();
    })
    .ajaxComplete(function(event, jqxhr, settings) {
        if (settings.url !== "ajax/request.php") return;
        $(".spinner").hide();
    })
Emil Stenström
fonte
Solução agradável. ajaxCompleteparece disparar prematuramente quando os pedidos de repetição, então eu usei uma combinação de ajaxSende ajaxStope ele funciona muito bem.
Mahn
@SchweizerSchoggi: Existem outros tópicos que respondem a essa pergunta, use a pesquisa!
Emil Stenström
8

Eu também quero contribuir para esta resposta. Eu estava procurando por algo semelhante no jQuery e isso que acabei usando.

Eu recebi meu spinner de carregamento em http://ajaxload.info/ . Minha solução é baseada nesta resposta simples em http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Basicamente, sua marcação HTML e CSS ficariam assim:

<style>
     #ajaxSpinnerImage {
          display: none;
     }
</style>

<div id="ajaxSpinnerContainer">
     <img src="~/Content/ajax-loader.gif" id="ajaxSpinnerImage" title="working..." />
</div>

E então você codifica para o jQuery seria algo como isto:

<script>
     $(document).ready(function () {
          $(document)
          .ajaxStart(function () {
               $("#ajaxSpinnerImage").show();
          })
          .ajaxStop(function () {
               $("#ajaxSpinnerImage").hide();
          });

          var owmAPI = "http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=YourAppID";
          $.getJSON(owmAPI)
          .done(function (data) {
               alert(data.coord.lon);
          })
          .fail(function () {
               alert('error');
          });
     });
</script>

É tão simples quanto isso :)

Brendan Vogt
fonte
8

Você pode simplesmente atribuir uma imagem do carregador à mesma tag na qual posteriormente carregará o conteúdo usando uma chamada Ajax:

$("#message").html('<span>Loading...</span>');

$('#message').load('index.php?pg=ajaxFlashcard');

Você também pode substituir a tag span por uma tag de imagem.

Umesh kumar
fonte
1
Será difícil gerenciar a interface do usuário dessa maneira. Podemos precisar de estilos completamente diferentes para o texto de "carregamento" e a mensagem final. Podemos usar o método de retorno de chamada mencionado acima para lidar com esse problema
Jaseem 1/11/11
6

Além de definir padrões globais para eventos ajax, você pode definir o comportamento para elementos específicos. Talvez apenas mudar de classe fosse suficiente?

$('#myForm').ajaxSend( function() {
    $(this).addClass('loading');
});
$('#myForm').ajaxComplete( function(){
    $(this).removeClass('loading');
});

Exemplo de CSS, para ocultar #myForm com um girador:

.loading {
    display: block;
    background: url(spinner.gif) no-repeat center middle;
    width: 124px;
    height: 124px;
    margin: 0 auto;
}
/* Hide all the children of the 'loading' element */
.loading * {
    display: none;  
}
LeeGee
fonte
1
Esta deve ser a resposta selecionada na minha opinião. Obrigado @LeeGee.
Nam G VU
Resposta realmente boa
Raskolnikov
4

Observe que você deve usar chamadas assíncronas para que os giradores funcionem (pelo menos foi o que fez com que o meu não fosse exibido até depois da chamada ajax e depois desapareceu rapidamente quando a chamada terminou e removeu o girador).

$.ajax({
        url: requestUrl,
        data: data,
        dataType: 'JSON',
        processData: false,
        type: requestMethod,
        async: true,                         <<<<<<------ set async to true
        accepts: 'application/json',
        contentType: 'application/json',
        success: function (restResponse) {
            // something here
        },
        error: function (restResponse) {
            // something here                
        }
    });
Shane Rowatt
fonte
4
$('#loading-image').html('<img src="/images/ajax-loader.gif"> Sending...');

        $.ajax({
            url:  uri,
            cache: false,
            success: function(){
                $('#loading-image').html('');           
            },

           error:   function(jqXHR, textStatus, errorThrown) {
            var text =  "Error has occured when submitting the job: "+jqXHR.status+ " Contact IT dept";
           $('#loading-image').html('<span style="color:red">'+text +'  </span>');

            }
        });
Izabela Skibinska
fonte
Caminho mais curto seria inserir tag de imagem com uma imagem baixado ajaxload.info com fundo transparente
Izabela Skibinska
2

Eu usei o seguinte com o jQuery UI Dialog. (Talvez funcione com outros retornos de chamada ajax?)

$('<div><img src="/i/loading.gif" id="loading" /></div>').load('/ajax.html').dialog({
    height: 300,
    width: 600,
    title: 'Wait for it...'
});

O contém um gif de carregamento animado até que seu conteúdo seja substituído quando a chamada ajax for concluída.

Quinn Comendant
fonte
2

Esta é a melhor maneira para mim:

jQuery :

$(document).ajaxStart(function() {
  $(".loading").show();
});

$(document).ajaxStop(function() {
  $(".loading").hide();
});

Café :

  $(document).ajaxStart ->
    $(".loading").show()

  $(document).ajaxStop ->
    $(".loading").hide()

Documentos: ajaxStart , ajaxStop

Fred K
fonte
Direito, e você pode usá-lo em conjunto com o plugin mencionado em esta resposta se você quiser ...
Matt
2

Javascript

$.listen('click', '#captcha', function() {
    $('#captcha-block').html('<div id="loading" style="width: 70px; height: 40px; display: inline-block;" />');
    $.get("/captcha/new", null, function(data) {
        $('#captcha-block').html(data);
    }); 
    return false;
});

CSS

#loading { background: url(/image/loading.gif) no-repeat center; }
Peter Mortensen
fonte
2

Este é um plugin muito simples e inteligente para esse fim específico: https://github.com/hekigan/is-loading

andcl
fonte
Muito bom! Especialmente se você der uma olhada nas demos ... Desativar elementos DOM, In Tag, Overlay completo, Overlay de elemento ... fornece tudo o que você precisa. E você pode facilmente combinar a Sobreposição Completa com esta resposta para fazê-la funcionar instantaneamente.
Matt
1

Eu faço isso:

var preloaderdiv = '<div class="thumbs_preloader">Loading...</div>';
           $('#detail_thumbnails').html(preloaderdiv);
             $.ajax({
                        async:true,
                        url:'./Ajaxification/getRandomUser?top='+ $(sender).css('top') +'&lef='+ $(sender).css('left'),
                        success:function(data){
                            $('#detail_thumbnails').html(data);
                        }
             });

fonte
1

Eu acho que você está certo. Este método é muito global ...

No entanto - é um bom padrão para quando sua chamada AJAX não tiver efeito na própria página. (salvar em segundo plano, por exemplo). (você sempre pode desativá-lo para uma determinada chamada ajax passando "global": false - consulte a documentação em jquery

Quando a chamada AJAX se destina a atualizar parte da página, eu gosto que minhas imagens de "carregamento" sejam específicas da seção atualizada. Gostaria de ver qual parte é atualizada.

Imagine como seria legal se você pudesse escrever algo como:

$("#component_to_refresh").ajax( { ... } ); 

E isso mostraria um "carregamento" nesta seção. Abaixo está uma função que escrevi que lida com a exibição de "carregamento", mas é específica para a área que você está atualizando no ajax.

Primeiro, deixe-me mostrar como usá-lo

<!-- assume you have this HTML and you would like to refresh 
      it / load the content with ajax -->

<span id="email" name="name" class="ajax-loading">
</span>

<!-- then you have the following javascript --> 

$(document).ready(function(){
     $("#email").ajax({'url':"/my/url", load:true, global:false});
 })

E esta é a função - um começo básico que você pode aprimorar conforme desejar. é muito flexível.

jQuery.fn.ajax = function(options)
{
    var $this = $(this);
    debugger;
    function invokeFunc(func, arguments)
    {
        if ( typeof(func) == "function")
        {
            func( arguments ) ;
        }
    }

    function _think( obj, think )
    {
        if ( think )
        {
            obj.html('<div class="loading" style="background: url(/public/images/loading_1.gif) no-repeat; display:inline-block; width:70px; height:30px; padding-left:25px;"> Loading ... </div>');
        }
        else
        {
            obj.find(".loading").hide();
        }
    }

    function makeMeThink( think )
    {
        if ( $this.is(".ajax-loading") )
        {
            _think($this,think);
        }
        else
        {
            _think($this, think);
        }
    }

    options = $.extend({}, options); // make options not null - ridiculous, but still.
    // read more about ajax events
    var newoptions = $.extend({
        beforeSend: function()
        {
            invokeFunc(options.beforeSend, null);
            makeMeThink(true);
        },

        complete: function()
        {
            invokeFunc(options.complete);
            makeMeThink(false);
        },
        success:function(result)
        {
            invokeFunc(options.success);
            if ( options.load )
            {
                $this.html(result);
            }
        }

    }, options);

    $.ajax(newoptions);
};
guy mograbi
fonte
1

Se você planeja usar um carregador sempre que fizer uma solicitação do servidor, poderá usar o seguinte padrão.

 jTarget.ajaxloader(); // (re)start the loader
 $.post('/libs/jajaxloader/demo/service/service.php', function (content) {
     jTarget.append(content); // or do something with the content
 })
 .always(function () {
     jTarget.ajaxloader("stop");
 });

Este código, em particular, usa o plug-in jajaxloader (que acabei de criar)

https://github.com/lingtalfi/JAjaxLoader/

ling
fonte
1

Meu código ajax se parece com isso, com efeito, acabei de comentar async: false line e o spinner aparece.

$.ajax({
        url: "@Url.Action("MyJsonAction", "Home")",
        type: "POST",
        dataType: "json",
        data: {parameter:variable},
        //async: false, 

        error: function () {
        },

        success: function (data) {
          if (Object.keys(data).length > 0) {
          //use data 
          }
          $('#ajaxspinner').hide();
        }
      });

Estou mostrando o botão giratório dentro de uma função antes do código ajax:

$("#MyDropDownID").change(function () {
        $('#ajaxspinner').show();

Para HTML, usei uma classe incrível de fontes:

<i id="ajaxspinner" class="fas fa-spinner fa-spin fa-3x fa-fw" style="display:none"></i>

Espero que ajude alguém.

Jaggan_j
fonte
0

Você sempre pode usar o plugin jQuery da UI do bloco, que faz tudo por você, e até bloqueia a página de qualquer entrada enquanto o ajax está carregando. Caso o plug-in pareça não estar funcionando, você pode ler sobre a maneira correta de usá-lo nesta resposta. Confira.

SamyCode
fonte