¿Cómo mostrar el spinner de carga en jQuery?

412

En Prototype puedo mostrar una imagen de "cargando ..." con este código:

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

function showLoad () {
    ...
}

En jQuery , puedo cargar una página de servidor en un elemento con esto:

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

pero, ¿cómo adjunto una flecha de carga a este comando como lo hice en Prototype?

Edward Tanguay
fuente

Respuestas:

793

Hay un par de maneras. Mi forma preferida es adjuntar una función a los eventos ajaxStart / Stop en el elemento mismo.

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

Las funciones ajaxStart / Stop se activarán cada vez que realice alguna llamada Ajax.

Actualización : a partir de jQuery 1.8, la documentación indica que .ajaxStart/Stopsolo debe adjuntarse document. Esto transformaría el fragmento anterior a:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });
nickf
fuente
48
Probablemente sea demasiado global para una carga simple en un DIV.
montrealist
363
demasiado global? ¿Cuántos mensajes diferentes de "espera" quieres?
nickf
23
de esta manera, desafortunadamente, no puede controlar la carga del posicionamiento div en caso de que no quiera mostrar solo una ventana de carga modal, sino mostrarla cerca del elemento que espera que se cargue el contenido ajax en ...
glaz666
10
ajaxStart y ajaxStop son eventos jQuery para que pueda asignarles un espacio de nombres: stackoverflow.com/questions/1191485/… docs.jquery.com/Namespaced_Events
David Xia
10
Si usa jQuery> = 1.9, adjunte los eventos ajaxStart y ajaxStop a $ (documento). jquery.com/upgrade-guide/1.9/…
Domenic
213

Para jQuery utilizo

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});
kr00lix
fuente
13
funciona para mí, el html debería tener algo como: <div id = 'loader'> <img src = "spinner.gif" /> </div>
yigal
77
Este fue el más limpio para mí. En lugar de ajaxSetup, coloqué beforeSend: y complete: dentro de $ ajax ({... instrucción.
kenswdev
44
No sé lo que vale, pero jQuery menciona en su documentación que no se recomienda usar .ajaxSetup () . enlace
pec
Observe aquí que beforeSendse llama antes de cada llamada, mientras que ajaxStartse dispara solo cuando se llama al primer método ajax. Del mismo modo ajaxStop, se llama cuando finaliza la última llamada ajax. Si tiene más de una solicitud simultánea, el fragmento de esta respuesta no funcionará correctamente.
nickf
No funciona para mí si la llamada ajax se agota (Firefox 28 para Mac).
osa
48

Simplemente puede usar la .ajaxfunción jQuery y usar su opción beforeSendy definir alguna función en la que pueda mostrar algo como un cargador de div y, en la opción de éxito, puede ocultar ese cargador de div.

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();
    }
});

Puedes tener cualquier imagen Spinning Gif. Aquí hay un sitio web que es un gran generador de cargadores AJAX de acuerdo con su esquema de color: http://ajaxload.info/

Buscador
fuente
16
El successno se llamará si hay un error, pero "siempre recibirá una completedevolución de llamada, incluso para las solicitudes sincrónicas", de acuerdo con jQuery Ajax Eventos .
LeeGee
23

Puede insertar la imagen animada en el DOM justo antes de la llamada AJAX, y hacer una función en línea para eliminarla ...

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

Esto asegurará que su animación comience en el mismo marco en solicitudes posteriores (si eso es importante). Tenga en cuenta que las versiones antiguas de IE pueden tener dificultades con la animación.

¡Buena suerte!

Josh Stodola
fuente
13
Sugerencia: precargue el spinner.gif en un div con la pantalla configurada en none. De lo contrario, es posible que tenga un poco de efecto de giro retrasado ya que el spinner aún se descarga.
uriDium
buen consejo, mucho más simple que usar el complemento de otra persona
Gordon Thompson
¡Agradable! pero querida, una cosa más que quiero mostrar spinner durante 2 segundos, incluso la página ya se ha cargado.
Ambos FM
55
@BothFM ¿Porque la gente disfruta esperando cosas ...?
Josh Stodola
21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

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

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

Brent
fuente
Podrías tener problemas de tiempo allí, ¿no?
Tim Büthe
2
@UltimateBrent Creo que te equivocaste. ¿Por qué showLoad () no es una devolución de llamada? JavaScript cargará contenido de forma asincrónica. showLoad () funcionará incluso antes de cargar el contenido si estoy en lo correcto.
Jaseem
2
@Jaseem Yo también uso un método similar y en realidad se basa en llamadas asíncronas. Colocaría showLoad en algún lugar antes de la llamada ajax, pero el objetivo es mostrar una ruleta, dejar que JS inicie la llamada y matar la ruleta en una devolución de llamada después de que se haya completado el AJAX.
Nenotlep
17

Si está usando $.ajax(), puede usar algo como esto:

$.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
fuente
11

Use el complemento de carga: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});
Nathan Bubna
fuente
10
¿Un complemento para esta tarea simple? Esa no es realmente una buena solución, ¿verdad? ¿Quién quiere cargar 100 scripts en una página?
Jaseem
2
Convenido. Comprima y concatene, si desea un mejor rendimiento.
Nathan Bubna
99
En desacuerdo: separe y modularice, reutilice el código, si desea poder mantener su trabajo y que otros también lo hagan. ¿Qué posibilidades hay de que su usuario tenga una conexión tan pobre que su cliente no pueda cargar un complemento ni su código?
LeeGee
@NathanBubna El enlace está muerto
SpringLearner
"¿Qué posibilidades hay de que su usuario tenga una conexión tan pobre que su cliente no pueda cargar un complemento y su código?" Bastante bueno, diría.
Andrew Oxenburgh
9

Variante: tengo un icono con id = "logo" en la parte superior izquierda de la página principal; un gif giratorio se superpone en la parte superior (con transparencia) cuando 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() {}
});
Pablo
fuente
9

Terminé con dos cambios en la respuesta original .

  1. A partir de jQuery 1.8, ajaxStart y ajaxStop solo se deben adjuntar a document. Esto hace que sea más difícil filtrar solo algunas de las solicitudes de ajax. Soo ...
  2. Cambiar a ajaxSend y ajaxComplete hace posible interspectar la solicitud actual de ajax antes de mostrar la ruleta.

Este es el código después de estos cambios:

$(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
fuente
Buena solución. ajaxCompleteparece dispararse prematuramente cuando las solicitudes se vuelven a intentar, por lo que he usado una combinación de ajaxSendy ajaxStopfunciona muy bien.
Mahn
@SchweizerSchoggi: Hay otros temas que responden esa pregunta, ¡usa la búsqueda!
Emil Stenström
8

También quiero contribuir a esta respuesta. Estaba buscando algo similar en jQuery y esto es lo que finalmente terminé usando.

Obtuve mi spinner de carga de http://ajaxload.info/ . Mi solución se basa en esta respuesta simple en http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Básicamente, su marcado HTML y CSS se verían así:

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

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

Y luego codificas para jQuery se vería así:

<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>

Es tan simple como eso :)

Brendan Vogt
fuente
8

Simplemente puede asignar una imagen de cargador a la misma etiqueta en la que luego cargará contenido mediante una llamada Ajax:

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

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

También puede reemplazar la etiqueta span con una etiqueta de imagen.

Umesh kumar
fuente
1
Será difícil administrar la IU de esta manera. Es posible que necesitemos estilos completamente diferentes para el texto de "carga" y el mensaje final. Podemos utilizar el método de devolución de llamada mencionado anteriormente para manejar este problema
Jaseem,
6

Además de establecer valores predeterminados globales para eventos ajax, puede establecer el comportamiento de elementos específicos. ¿Tal vez solo cambiar su clase sería suficiente?

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

Ejemplo de CSS, para ocultar #myForm con una ruleta:

.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
fuente
1
Esta debería ser la respuesta seleccionada en mi opinión. Gracias @LeeGee.
Nam G VU
Muy buena respuesta
Raskolnikov
4

Tenga en cuenta que debe usar llamadas asíncronas para que funcionen los hilanderos (al menos eso es lo que provocó que el mío no se mostrara hasta después de la llamada ajax y luego desapareció rápidamente cuando la llamada había terminado y quitó el hilandero).

$.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
fuente
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
fuente
El camino más corto sería insertar una etiqueta de imagen con una imagen descargada de ajaxload.info con fondo transparente
Izabela Skibinska
2

He usado lo siguiente con jQuery UI Dialog. (¿Tal vez funciona con otras devoluciones de llamada ajax?)

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

Contiene un gif animado de carga hasta que su contenido se reemplaza cuando se completa la llamada ajax.

Quinn Commandado
fuente
2

Esta es la mejor manera para mí:

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
fuente
Correcto, y puede usarlo junto con el complemento mencionado en esta respuesta si lo desea ...
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
fuente
2

Este es un complemento muy simple e inteligente para ese propósito específico: https://github.com/hekigan/is-loading

andcl
fuente
¡Muy agradable! Especialmente si echas un vistazo a las demostraciones ... Desactiva los elementos DOM, In Tag, Full Overlay, Element Overlay ... proporciona todo lo que necesitas. Y puede combinar fácilmente Superposición completa con esta respuesta para que funcione al instante.
Matt
1

Hago esto:

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);
                        }
             });

fuente
1

Creo que tienes razón. Este método es demasiado global ...

Sin embargo, es un buen valor predeterminado para cuando su llamada AJAX no tiene ningún efecto en la página en sí. (guardar en segundo plano, por ejemplo). (siempre puede desactivarlo para una determinada llamada ajax pasando "global": falso - consulte la documentación en jquery

Cuando la llamada AJAX está destinada a actualizar parte de la página, me gusta que mis imágenes de "carga" sean específicas de la sección actualizada. Me gustaría ver qué parte se actualiza.

Imagina lo genial que sería si pudieras simplemente escribir algo como:

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

Y esto mostraría una "carga" en esta sección. A continuación se muestra una función que escribí que también maneja la visualización de "carga", pero es específica del área que está actualizando en ajax.

Primero, déjame mostrarte cómo usarlo

<!-- 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});
 })

Y esta es la función: un comienzo básico que puede mejorar como desee. Es muy flexible.

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);
};
chico mograbi
fuente
1

Si planea usar un cargador cada vez que realiza una solicitud de servidor, puede usar el siguiente patrón.

 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 en particular usa el complemento jajaxloader (que acabo de crear)

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

abadejo
fuente
1

Mi código ajax se ve así, en efecto, acabo de comentar async: línea falsa y aparece el spinner.

$.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();
        }
      });

Estoy mostrando el spinner dentro de una función antes del código ajax:

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

Para Html, he usado una clase de fuente impresionante:

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

Espero que ayude a alguien.

Jaggan_j
fuente
0

Siempre puede usar el complemento jQuery Block UI que hace todo por usted e incluso bloquea la página de cualquier entrada mientras se carga el ajax. En caso de que el complemento no funcione, puede leer sobre la forma correcta de usarlo en esta respuesta. Echale un vistazo.

SamyCode
fuente