Wie zeige ich das Laden des Spinners in jQuery?

412

In Prototype kann ich ein "Laden ..." Bild mit diesem Code anzeigen:

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

function showLoad () {
    ...
}

In jQuery kann ich eine Serverseite folgendermaßen in ein Element laden:

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

Aber wie füge ich diesem Befehl einen Ladespinner hinzu, wie ich es in Prototype getan habe?

Edward Tanguay
quelle

Antworten:

793

Es gibt verschiedene Möglichkeiten. Meine bevorzugte Methode besteht darin, eine Funktion an die ajaxStart / Stop-Ereignisse des Elements selbst anzuhängen.

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

Die ajaxStart / Stop-Funktionen werden ausgelöst, wenn Sie Ajax-Aufrufe ausführen.

Update : Ab jQuery 1.8 heißt es in der Dokumentation, dass .ajaxStart/Stopnur an angehängt werden sollte document. Dies würde das obige Snippet in Folgendes umwandeln:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });
nickf
quelle
48
Das ist wahrscheinlich zu global für eine einfache Ladung in einen DIV.
Montrealist
363
zu global? Wie viele verschiedene "Bitte warten" -Nachrichten möchten Sie?
Nickf
23
Auf diese Weise können Sie das Laden der Div-Position leider nicht steuern, wenn Sie nicht nur ein modales
Ladefenster anzeigen
10
ajaxStart und ajaxStop sind jQuery-Ereignisse, sodass Sie sie als Namespace verwenden können: stackoverflow.com/questions/1191485/… docs.jquery.com/Namespaced_Events
David Xia
10
Wenn Sie jQuery> = 1.9 verwenden, hängen Sie die Ereignisse ajaxStart und ajaxStop an $ (document) an. jquery.com/upgrade-guide/1.9/…
Domenic
213

Für jQuery benutze ich

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});
kr00lix
quelle
13
funktioniert für mich, das HTML sollte so etwas wie haben: <div id = 'loader'> <img src = "spinner.gif" /> </ div>
yigal
7
Dieser war für mich am saubersten. Anstelle von ajaxSetup habe ich beforeSend: und complete: in die $ ajax ({... Anweisung.
kenswdev
4
Ich weiß nicht, was es wert ist, aber jQuery erwähnt in seiner Dokumentation, dass die Verwendung von .ajaxSetup () nicht empfohlen wird. Link
Pec
Beachten Sie hier, dass dies beforeSendvor jedem Aufruf aufgerufen wird, während ajaxStartes nur ausgelöst wird, wenn die erste Ajax-Methode aufgerufen wird. Ebenso ajaxStopwird es aufgerufen, wenn der letzte Ajax-Aufruf beendet ist. Wenn Sie mehr als eine Anfrage gleichzeitig haben, funktioniert das Snippet in dieser Antwort nicht richtig.
Nickf
Funktioniert bei mir nicht, wenn der Ajax-Anruf abläuft (Firefox 28 für Mac).
osa
48

Sie können einfach die .ajaxFunktion von jQuery verwenden und ihre Option verwenden beforeSendund eine Funktion definieren, in der Sie so etwas wie ein Loader-Div anzeigen können. Bei erfolgreicher Option können Sie dieses Loader-Div ausblenden.

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

Sie können jedes Spinning Gif-Bild haben. Hier ist eine Website, die ein großartiger AJAX Loader Generator gemäß Ihrem Farbschema ist: http://ajaxload.info/

Sucher
quelle
16
Das successwird nicht aufgerufen, wenn ein Fehler auftritt, aber "Sie erhalten completeauch bei synchronen Anforderungen immer einen Rückruf", so jQuery Ajax Events .
LeeGee
23

Sie können das animierte Bild direkt vor dem AJAX-Aufruf in das DOM einfügen und eine Inline-Funktion ausführen, um es zu entfernen ...

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

Dadurch wird sichergestellt, dass Ihre Animation bei nachfolgenden Anforderungen im selben Frame startet (falls dies wichtig ist). Beachten Sie, dass alte Versionen von IE möglicherweise Probleme mit der Animation haben.

Viel Glück!

Josh Stodola
quelle
13
Top Tipp: Laden Sie das spinner.gif in einem Div vor, dessen Anzeige auf none gesetzt ist. Andernfalls kann es zu einem verzögerten Spinner-Effekt kommen, da der Spinner noch herunterlädt.
UriDium
netter Tipp, viel einfacher als das Plugin eines anderen zu verwenden
Gordon Thompson
Nett! aber liebes, eine sache mehr, dass ich spinner für 2 sekunden anzeigen möchte, auch wenn die seite bereits geladen ist.
Beide FM
5
@BothFM Weil die Leute gerne auf Dinge warten ...?
Josh Stodola
21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

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

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

Brent
quelle
Sie könnten dort Zeitprobleme haben, nicht wahr?
Tim Büthe
2
@UltimateBrent Ich denke du hast es falsch verstanden. Warum ist showLoad () kein Rückruf? JavaScript lädt Inhalte asynchron. showLoad () funktioniert auch vor dem Laden des Inhalts, wenn ich korrekt bin.
Jaseem
2
@Jaseem Ich verwende auch eine ähnliche Methode und sie basiert tatsächlich auf asynchronen Aufrufen. Ich würde showLoad irgendwo vor dem Ajax-Aufruf platzieren, aber der springende Punkt ist, einen Spinner zu zeigen, JS den Anruf starten zu lassen und den Spinner in einem Rückruf zu töten, nachdem der AJAX abgeschlossen ist.
Nenotlep
17

Wenn Sie verwenden $.ajax(), können Sie Folgendes verwenden:

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

Verwenden Sie das Lade-Plugin: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});
Nathan Bubna
quelle
10
Ein Plugin für diese einfache Aufgabe? Das ist doch keine gute Lösung, oder? Wer möchte 100 Skripte auf eine Seite laden?
Jaseem
2
Einverstanden. Komprimieren und verketten Sie, wenn Sie eine bessere Leistung wünschen.
Nathan Bubna
9
Nicht einverstanden: Code trennen und modularisieren, wiederverwenden, wenn Sie Ihre Arbeit beibehalten möchten und dies auch von anderen tun lassen möchten. Wie hoch ist die Wahrscheinlichkeit, dass Ihr Benutzer eine so schlechte Verbindung hat, dass sein Client nicht so viel Plugin wie Ihren Code laden kann?
LeeGee
@ NathanBubna Der Link ist tot
SpringLearner
"Wie groß ist die Wahrscheinlichkeit, dass Ihr Benutzer eine so schlechte Verbindung hat, dass sein Client nicht so gut wie Ihr Code ein Plugin laden kann?" Ziemlich gut würde ich sagen.
Andrew Oxenburgh
9

Variante: Ich habe ein Symbol mit id = "logo" oben links auf der Hauptseite. Wenn Ajax arbeitet, wird ein Spinner-GIF (mit Transparenz) darüber gelegt.

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

Am Ende hatte ich zwei Änderungen an der ursprünglichen Antwort .

  1. Ab jQuery 1.8 sollten ajaxStart und ajaxStop nur noch an angehängt werden document . Dies macht es schwieriger, nur einige der Ajax-Anforderungen zu filtern. Soo ...
  2. Durch Umschalten auf ajaxSend und ajaxComplete kann die aktuelle Ajax-Anforderung überprüft werden, bevor der Spinner angezeigt wird.

Dies ist der Code nach diesen Änderungen:

$(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
quelle
Schöne Problemumgehung. ajaxCompletescheint vorzeitig zu feuern, wenn Anfragen erneut versucht werden, daher habe ich eine Kombination aus ajaxSendund verwendet ajaxStopund es funktioniert hervorragend.
Mahn
@SchweizerSchoggi: Es gibt andere Themen, die diese Frage beantworten. Verwenden Sie die Suche!
Emil Stenström
8

Ich möchte auch zu dieser Antwort beitragen. Ich suchte nach etwas Ähnlichem in jQuery und das, was ich schließlich benutzte.

Ich habe meinen Ladespinner von http://ajaxload.info/ erhalten . Meine Lösung basiert auf dieser einfachen Antwort unter http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Grundsätzlich würden Ihr HTML-Markup und CSS folgendermaßen aussehen:

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

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

Und dann würde Ihr Code für jQuery ungefähr so ​​aussehen:

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

So einfach ist das :)

Brendan Vogt
quelle
8

Sie können demselben Tag, auf dem Sie später Inhalte mit einem Ajax-Aufruf laden, einfach ein Loader-Image zuweisen:

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

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

Sie können das span-Tag auch durch ein Bild-Tag ersetzen.

Umesh Kumar
quelle
1
Es wird schwierig sein, die Benutzeroberfläche auf diese Weise zu verwalten. Möglicherweise benötigen wir völlig andere Stile für das "Laden" von Text und die endgültige Nachricht. Wir können die oben erwähnte
Rückrufmethode verwenden,
6

Sie können nicht nur globale Standardeinstellungen für Ajax-Ereignisse festlegen, sondern auch das Verhalten für bestimmte Elemente festlegen. Vielleicht würde es ausreichen, nur die Klasse zu wechseln?

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

Beispiel CSS, um #myForm mit einem Spinner auszublenden:

.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
quelle
1
Dies sollte aus meiner Sicht die ausgewählte Antwort sein. Danke @LeeGee.
Nam G VU
Wirklich gute Antwort
Raskolnikov
4

Beachten Sie, dass Sie asynchrone Anrufe verwenden müssen, damit Spinner funktionieren (zumindest hat dies dazu geführt, dass meine erst nach dem Ajax-Anruf angezeigt wurden und dann schnell wieder weggingen, da der Anruf beendet war und der Spinner entfernt wurde).

$.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
quelle
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
quelle
Der kürzeste Weg wäre, ein Bild-Tag mit einem von ajaxload.info heruntergeladenen Bild mit transparentem Hintergrund einzufügen
Izabela Skibinska
2

Ich habe Folgendes mit jQuery UI Dialog verwendet. (Vielleicht funktioniert es mit anderen Ajax-Rückrufen?)

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

Das enthält ein animiertes Lade-GIF, bis sein Inhalt ersetzt wird, wenn der Ajax-Aufruf abgeschlossen ist.

Quinn Comendant
quelle
2

Das ist der beste Weg für mich:

jQuery :

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

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

Kaffee :

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

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

Dokumente : ajaxStart , ajaxStop

Fred K.
quelle
Richtig, und Sie können es zusammen mit dem in dieser Antwort genannten Plugin verwenden , wenn Sie möchten ...
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
quelle
2

Dies ist ein sehr einfaches und intelligentes Plugin für diesen speziellen Zweck: https://github.com/hekigan/is-loading

andcl
quelle
Wirklich nett! Vor allem, wenn Sie sich die Demos ansehen ... DOM-Elemente deaktivieren, In Tag, Vollständige Überlagerung, Elementüberlagerung ... bietet alles, was Sie brauchen. Und Sie können Full Overlay ganz einfach mit dieser Antwort kombinieren , damit es sofort funktioniert.
Matt
1

Ich mache das:

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

quelle
1

Ich glaube, Du hast recht. Diese Methode ist zu global ...

Dies ist jedoch eine gute Standardeinstellung, wenn Ihr AJAX-Aufruf keine Auswirkungen auf die Seite selbst hat. (Hintergrund speichern zum Beispiel). (Sie können es jederzeit für einen bestimmten Ajax-Aufruf ausschalten, indem Sie "global" übergeben: false - siehe Dokumentation bei jquery

Wenn der AJAX-Aufruf einen Teil der Seite aktualisieren soll, möchte ich, dass meine "Lade" -Bilder spezifisch für den aktualisierten Abschnitt sind. Ich würde gerne sehen, welcher Teil aktualisiert wird.

Stellen Sie sich vor, wie cool es wäre, wenn Sie einfach etwas schreiben könnten wie:

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

Und dies würde ein "Laden" in diesem Abschnitt anzeigen. Unten ist eine Funktion, die ich geschrieben habe und die auch das "Laden" der Anzeige behandelt, die jedoch spezifisch für den Bereich ist, den Sie in Ajax aktualisieren.

Lassen Sie mich zunächst zeigen, wie man es benutzt

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

Und dies ist die Funktion - ein grundlegender Start, den Sie nach Belieben verbessern können. es ist sehr flexibel.

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);
};
Kerl Mograbi
quelle
1

Wenn Sie vorhaben, bei jeder Serveranforderung einen Loader zu verwenden, können Sie das folgende Muster verwenden.

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

Dieser Code verwendet insbesondere das Jajaxloader-Plugin (das ich gerade erstellt habe).

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

Leng
quelle
1

Mein Ajax-Code sieht so aus, tatsächlich habe ich gerade async auskommentiert: falsche Zeile und der Spinner wird angezeigt.

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

Ich zeige den Spinner innerhalb einer Funktion vor dem Ajax-Code:

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

Für HTML habe ich eine Klasse für großartige Schriftarten verwendet:

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

Hoffe es hilft jemandem.

Jaggan_j
quelle
0

Sie können jederzeit das Block UI jQuery-Plugin verwenden, das alles für Sie erledigt und sogar die Seite aller Eingaben blockiert, während der Ajax geladen wird. Falls das Plugin anscheinend nicht funktioniert, können Sie in dieser Antwort nachlesen, wie Sie es richtig verwenden können . Hör zu.

SamyCode
quelle