Jak pokazać ładowanie spinnera w jQuery?


412

W Prototypie mogę pokazać obraz „ładowanie ...” za pomocą tego kodu:

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

function showLoad () {
    ...
}

W jQuery mogę załadować stronę serwera do elementu za pomocą:

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

ale w jaki sposób mogę dołączyć ładujący spinner do tego polecenia, tak jak w Prototypie?

Odpowiedzi:


793

Istnieje kilka sposobów. Moim preferowanym sposobem jest dołączenie funkcji do zdarzeń ajaxStart / Stop w samym elemencie.

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

Funkcje ajaxStart / Stop będą uruchamiane przy każdym wywołaniu Ajax.

Aktualizacja : Począwszy od jQuery 1.8, dokumentacja stwierdza, że .ajaxStart/Stopnależy tylko dołączyć document. Przekształci to powyższy fragment w:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });

48
Jest to prawdopodobnie zbyt globalne, aby wystarczyło jedno ładowanie do DIV.
montrealista

363
zbyt globalny? ile różnych wiadomości „proszę czekać” chcesz?
nickf

23
w ten sposób niestety nie można kontrolować pozycjonowania div div w przypadku, gdy nie chcesz po prostu wyświetlać modalnego okna ładowania, ale pokazuj je w pobliżu elementu czekającego na załadowanie zawartości ajax w ...
glaz666

10
ajaxStart i ajaxStop są zdarzeniami jQuery, więc możesz je nazwać przestrzenią: stackoverflow.com/questions/1191485/… docs.jquery.com/Namespaced_Events
David Xia

10
Jeśli używasz jQuery> = 1.9, dołącz zdarzenia ajaxStart i ajaxStop do $ (dokumentu). jquery.com/upgrade-guide/1.9/…
Domenic

213

Do jQuery używam

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});

13
działa dla mnie, HTML powinien mieć coś takiego: <div id = 'loader'> <img src = "spinner.gif" /> </div>
yigal

7
Ten był dla mnie najczystszy. Zamiast ajaxSetup, umieściłem beforeSend: i complete: wewnątrz $ ajax ({... statement.
kenswdev

4
Nie wiem, co jest warte, ale jQuery wspomina w dokumentacji, że użycie .ajaxSetup () nie jest zalecane. link
pec

Zauważ, że beforeSendjest wywoływane przed każdym wywołaniem, a ajaxStartwyzwalane jest tylko wtedy , gdy wywoływana jest pierwsza metoda ajax. Podobnie ajaxStopjest wywoływane, gdy kończy się ostatnie wywołanie ajax. Jeśli masz więcej niż jedno współbieżne żądanie, fragment kodu w tej odpowiedzi nie będzie działał poprawnie.
nickf

Nie działa dla mnie, jeśli upłynie limit czasu wywołania ajax (Firefox 28 dla komputerów Mac).
osa

48

Możesz po prostu użyć funkcji jQuery .ajaxi użyć jej opcji beforeSendi zdefiniować funkcję, w której możesz pokazać coś takiego jak div programu ładującego, a po sukcesie możesz ukryć tę div programu ładującego.

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

Możesz mieć dowolny obraz Spinning Gif. Oto strona internetowa, która jest świetnym generatorem AJAX Loader według twojego schematu kolorów: http://ajaxload.info/


16
successNie zostanie wywołana, gdy wystąpi błąd, ale „zawsze będziesz otrzymywać completezwrotnego, nawet dla synchronicznych żądań”, zgodnie z jQuery Ajax Events .
LeeGee,

23

Możesz wstawić animowany obraz do DOM tuż przed wywołaniem AJAX i wykonać funkcję wbudowaną, aby go usunąć ...

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

To sprawi, że twoja animacja rozpocznie się od tej samej klatki przy kolejnych żądaniach (jeśli to ma znaczenie). Pamiętaj, że starsze wersje IE mogą mieć problemy z animacją.

Powodzenia!


13
Najlepsza wskazówka: Załaduj spinner.gif w div z ustawieniem display na none. W przeciwnym razie możesz uzyskać nieco opóźniony efekt przędzarki, ponieważ przędzarka nadal pobiera.
uriDium

fajna wskazówka, znacznie prostsza niż korzystanie z wtyczki innej osoby
Gordon Thompson,

Miły! ale kochanie, jeszcze jedno, że chcę wyświetlać pokrętło przez 2 sekundy, nawet strona już się załadowała.
Zarówno

5
@BothFM Ponieważ ludzie lubią czekać na rzeczy ...?
Josh Stodola

21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

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

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


Możesz mieć problemy z synchronizacją, prawda?
Tim Büthe

2
@UltimateBrent Myślę, że źle zrozumiałeś. Dlaczego showLoad () nie jest wywołaniem zwrotnym? JavaScript wczytuje zawartość asynchronicznie. showLoad () będzie działał nawet przed załadowaniem zawartości, jeśli mam rację.
Jaseem,

2
@Jaseem Używam też podobnej metody i faktycznie polega ona na wywołaniach asynchronicznych. Umieściłem showLoad gdzieś przed wywołaniem ajax, ale chodzi o to, żeby pokazać pokrętło, pozwolić JS rozpocząć połączenie i zabić pokrętło w wywołaniu zwrotnym po zakończeniu AJAX.
Nenotlep 12.12.12

17

Jeśli używasz $.ajax(), możesz użyć czegoś takiego:

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

11

Użyj wtyczki ładującej: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});

10
Jedna wtyczka do tego prostego zadania? To nie jest naprawdę dobre rozwiązanie, prawda? Kto chce załadować 100 skryptów na stronie?
Jaseem,

2
Zgoda. Kompresuj i konkatenuj, jeśli chcesz uzyskać lepszą wydajność.
Nathan Bubna

9
Nie zgadzam się: oddziel i zmodularyzuj, ponownie wykorzystaj kod, jeśli chcesz mieć możliwość kontynuowania pracy i innych. Jaka jest szansa, że ​​użytkownik będzie miał tak słabe połączenie, że jego klient nie będzie mógł załadować wtyczki, a także kodu?
LeeGee,

@NathanBubna Link nie działa
SpringLearner,

„Jaka jest szansa, że ​​użytkownik będzie miał tak słabe połączenie, że jego klient nie będzie mógł załadować wtyczki, a także kodu?” Całkiem dobrze, powiedziałbym.
Andrew Oxenburgh

9

Wariant: Mam ikonę z id = „logo” w lewym górnym rogu strony głównej; spinner gif jest następnie nakładany na wierzch (z przezroczystością), gdy działa ajax.

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

9

Skończyłem z dwiema zmianami w oryginalnej odpowiedzi .

  1. Począwszy od jQuery 1.8, ajaxStart i ajaxStop powinny być dołączone tylko do document. Utrudnia to filtrowanie tylko niektórych żądań ajax. Soo ...
  2. Przełączenie na ajaxSend i ajaxComplete umożliwia interpekcję bieżącego żądania ajax przed wyświetleniem pokrętła.

To jest kod po tych zmianach:

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

Niezłe obejście. ajaxCompleteWydaje się przedwcześnie ogień, gdy żądania ponownie, więc użyłem kombinacji ajaxSenda ajaxStopi działa świetnie.
Mahn

@SchweizerSchoggi: Istnieją inne tematy, które odpowiadają na to pytanie, użyj wyszukiwania!
Emil Stenström,

8

Chcę również przyczynić się do tej odpowiedzi. Szukałem czegoś podobnego w jQuery i tego ostatecznie użyłem.

Mam ładujący spinner ze strony http://ajaxload.info/ . Moje rozwiązanie opiera się na tej prostej odpowiedzi pod adresem http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Zasadniczo twój znacznik HTML i CSS wyglądałyby tak:

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

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

A potem kod dla jQuery wyglądałby mniej więcej tak:

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

To takie proste :)


8

Możesz po prostu przypisać obraz modułu ładującego do tego samego znacznika, na którym później załadujesz zawartość za pomocą wywołania Ajax:

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

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

Możesz także zastąpić znacznik zakresu znacznikiem obrazu.


1
W ten sposób będzie trudno zarządzać interfejsem użytkownika. Możemy potrzebować zupełnie innych stylów do „ładowania” tekstu i końcowej wiadomości. Do obsługi tego problemu możemy użyć wyżej wspomnianej metody wywołania zwrotnego
Jaseem

6

Oprócz ustawiania globalnych wartości domyślnych dla zdarzeń ajax, możesz ustawić zachowanie określonych elementów. Może wystarczy zmiana klasy?

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

Przykład CSS, aby ukryć #myForm za pomocą pokrętła:

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

1
Moim zdaniem powinna to być wybrana odpowiedź. Dzięki @LeeGee.
Nam G VU

Naprawdę świetna odpowiedź
Raskolnikov

4

Zauważ, że musisz użyć asynchronicznych wywołań, aby błystki działały (przynajmniej to spowodowało, że moje wyświetlały się dopiero po wywołaniu ajax, a następnie szybko zniknęły, ponieważ połączenie zakończyło się i usunęło błystkę).

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

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

            }
        });

Najkrótszym sposobem byłoby wstawienie znacznika obrazu z obrazem pobranym z ajaxload.info z przezroczystym tłem
Izabela Skibinska

2

Użyłem następujących w oknie dialogowym interfejsu użytkownika jQuery. (Może to działa z innymi wywołaniami zwrotnymi ajax?)

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

Zawiera animowany gif ładujący, dopóki jego zawartość nie zostanie zastąpiona po zakończeniu wywołania ajax.


2

To dla mnie najlepszy sposób:

jQuery :

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

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

Kawa :

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

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

Dokumenty: ajaxStart , ajaxStop


Racja, możesz użyć go razem z wtyczką wymienioną w tej odpowiedzi, jeśli chcesz ...
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; }

2

Jest to bardzo prosta i inteligentna wtyczka do tego konkretnego celu: https://github.com/hekigan/is-loading


Bardzo miłe! Zwłaszcza jeśli spojrzysz na dema ... Wyłącz elementy DOM, W znaczniku, Pełna nakładka, Nakładka elementu ... zapewnia wszystko, czego potrzebujesz. I możesz łatwo połączyć Full Overlay z tą odpowiedzią, aby uzyskać natychmiastowe działanie.
Matt

1

Robię to:

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

1

Myślę, że masz rację. Ta metoda jest zbyt globalna ...

Jednak - jest to dobre ustawienie domyślne, gdy wywołanie AJAX nie ma wpływu na samą stronę. (na przykład zapisywanie w tle). (zawsze możesz go wyłączyć dla określonego wywołania ajax, przekazując „global”: false - zobacz dokumentację w jquery

Gdy wywołanie AJAX ma na celu odświeżenie części strony, podoba mi się, że moje „ładowanie” obrazów jest specyficzne dla odświeżonej sekcji. Chciałbym zobaczyć, która część jest odświeżana.

Wyobraź sobie, jak fajnie by było, gdybyś mógł po prostu napisać coś takiego:

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

Oznaczałoby to „ładowanie” w tej sekcji. Poniżej jest funkcja, którą napisałem, która obsługuje również wyświetlanie „ładowania”, ale jest specyficzna dla obszaru, który odświeżasz w ajax.

Najpierw pokażę ci, jak z niego korzystać

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

I to jest funkcja - podstawowy start, który możesz ulepszyć, jak chcesz. jest bardzo elastyczny.

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


1

Jeśli planujesz używać modułu ładującego za każdym razem, gdy wysyłasz żądanie serwera, możesz użyć następującego wzorca.

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

Ten kod w szczególności używa wtyczki jajaxloader (którą właśnie utworzyłem)

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


1

Mój kod ajax wygląda tak, w rzeczywistości właśnie skomentowałem async: false line i wyświetla się 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();
        }
      });

Pokazuję kod w funkcji przed kodem ajax:

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

Do HTML użyłem niesamowitej klasy czcionek:

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

Mam nadzieję, że to komuś pomoże.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.