Bagaimana cara menunjukkan pemuatan pemintal di jQuery?

412

Dalam Prototipe saya dapat menampilkan gambar "memuat ..." dengan kode ini:

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

function showLoad () {
    ...
}

Di jQuery , saya bisa memuat halaman server ke dalam elemen dengan ini:

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

tetapi bagaimana cara melampirkan pemintal pemuatan ke perintah ini seperti yang saya lakukan pada Prototipe?

Edward Tanguay
sumber

Jawaban:

793

Ada beberapa cara. Cara yang saya sukai adalah melampirkan fungsi ke ajaxStart / Stop events pada elemen itu sendiri.

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

Fungsi ajaxStart / Stop akan menyala setiap kali Anda melakukan panggilan Ajax.

Pembaruan : Pada jQuery 1.8, dokumentasi menyatakan bahwa .ajaxStart/Stophanya boleh dilampirkan document. Ini akan mengubah cuplikan di atas menjadi:

var $loading = $('#loadingDiv').hide();
$(document)
  .ajaxStart(function () {
    $loading.show();
  })
  .ajaxStop(function () {
    $loading.hide();
  });
nickf
sumber
48
Itu mungkin terlalu global untuk satu beban sederhana ke dalam DIV.
montrealist
363
terlalu global? berapa banyak pesan "harap tunggu" yang Anda inginkan?
nickf
23
dengan cara ini, sayangnya Anda tidak dapat mengontrol pemuatan posisi div jika Anda tidak ingin hanya menampilkan jendela pemuatan modal, tetapi tunjukkan di dekat elemen yang menunggu konten ajax dimuat ...
glaz666
10
ajaxStart dan ajaxStop adalah acara jQuery sehingga Anda dapat menamainya : stackoverflow.com/questions/1191485/… docs.jquery.com/Namespaced_Events
David Xia
10
Jika menggunakan jQuery> = 1.9, lampirkan peristiwa ajaxStart dan ajaxStop ke $ (dokumen). jquery.com/upgrade-guide/1.9/…
Domenic
213

Untuk jQuery saya gunakan

jQuery.ajaxSetup({
  beforeSend: function() {
     $('#loader').show();
  },
  complete: function(){
     $('#loader').hide();
  },
  success: function() {}
});
kr00lix
sumber
13
bekerja untuk saya, html harus memiliki sesuatu seperti: <div id = 'loader'> <img src = "spinner.gif" /> </div>
yigal
7
Yang ini terbersih untuk saya. Alih-alih ajaxSetup, saya menempatkan sebelumKirim: dan lengkapi: di dalam $ ajax ({... statement.
kenswdev
4
Tidak tahu apa nilainya, tetapi jQuery menyebutkan dalam dokumentasi itu bahwa menggunakan .ajaxSetup () tidak disarankan. tautan
pec
Perhatikan di sini yang beforeSenddipanggil sebelum setiap panggilan, sedangkan ajaxStartdipicu hanya ketika metode ajax pertama dipanggil. Demikian juga untuk ajaxStop, itu dipanggil ketika panggilan ajax terakhir selesai. Jika Anda memiliki lebih dari satu permintaan bersamaan, snippet dalam jawaban ini tidak akan berfungsi dengan baik.
nickf
Tidak berfungsi untuk saya jika panggilan ajax habis (Firefox 28 untuk Mac).
Osa
48

Anda bisa menggunakan fungsi jQuery .ajaxdan menggunakan opsi beforeSenddan mendefinisikan beberapa fungsi di mana Anda dapat menampilkan sesuatu seperti loader loader dan pada opsi sukses Anda dapat menyembunyikan div loader tersebut.

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

Anda dapat memiliki gambar Gif Berputar. Berikut adalah situs web yang merupakan Generator Loader AJAX yang hebat sesuai dengan skema warna Anda: http://ajaxload.info/

Pencari
sumber
16
Tidak successakan dipanggil jika ada kesalahan, tetapi "Anda akan selalu menerima completepanggilan balik, bahkan untuk permintaan sinkron," menurut jQuery Ajax Events .
LeeGee
23

Anda dapat memasukkan gambar animasi ke dalam DOM tepat sebelum panggilan AJAX, dan melakukan fungsi sebaris untuk menghapusnya ...

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

Ini akan memastikan animasi Anda dimulai pada frame yang sama pada permintaan berikutnya (jika itu penting). Perhatikan bahwa versi lama IE mungkin mengalami kesulitan dengan animasi.

Semoga berhasil!

Josh Stodola
sumber
13
Kiat teratas: Preload spinner.gif dalam div dengan tampilan tidak disetel. Kalau tidak, Anda mungkin mendapatkan sedikit efek pemintal yang tertunda karena pemintal masih mengunduh.
uriDium
tip yang bagus, jauh lebih sederhana daripada menggunakan plugin orang lain
Gordon Thompson
Bagus! tapi sayang, satu hal lagi yang saya ingin tampilkan spinner selama 2 detik bahkan halaman sudah dimuat.
Keduanya FM
5
@ Keduanya karena orang senang menunggu sesuatu ...?
Josh Stodola
21
$('#message').load('index.php?pg=ajaxFlashcard', null, showResponse);
showLoad();

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

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

Brent
sumber
Anda bisa memiliki masalah waktu di sana, bukan?
Tim Büthe
2
@UlebihanBrent Saya pikir Anda salah. Mengapa showLoad () bukan panggilan balik? JavaScript akan memuat konten secara tidak sinkron. showLoad () akan berfungsi bahkan sebelum konten dimuat jika saya benar.
Jaseem
2
@Jaseem Saya menggunakan metode yang sama juga dan itu sebenarnya bergantung pada panggilan async. Saya akan menempatkan showLoad di suatu tempat sebelum panggilan ajax tetapi intinya adalah untuk menunjukkan pemintal, biarkan JS memulai panggilan, dan bunuh pemintal dalam panggilan balik setelah AJAX selesai.
Nenotlep
17

Jika Anda menggunakan, $.ajax()Anda dapat menggunakan sesuatu seperti ini:

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

Gunakan plugin pemuatan: http://plugins.jquery.com/project/loading

$.loading.onAjax({img:'loading.gif'});
Nathan Bubna
sumber
10
Satu plugin untuk tugas sederhana ini? Itu bukan solusi yang bagus bukan? Siapa yang ingin memuat 100 skrip pada satu halaman?
Jaseem
2
Sepakat. Kompres dan gabungkan, jika Anda menginginkan kinerja yang lebih baik.
Nathan Bubna
9
Disagreed: terpisah dan modularise, gunakan kembali kode, jika Anda ingin dapat mempertahankan pekerjaan Anda dan meminta orang lain melakukannya juga. Bagaimana peluang pengguna Anda memiliki koneksi yang buruk seperti itu klien mereka tidak dapat memuat plugin serta kode Anda?
LeeGee
@NathanBubna Tautannya sudah mati
SpringLearner
"Bagaimana kemungkinan pengguna Anda memiliki koneksi yang buruk seperti itu klien mereka tidak dapat memuat plugin serta kode Anda?" Cukup bagus menurut saya.
andrew oxenburgh
9

Varian: Saya memiliki ikon dengan id = "logo" di kiri atas halaman utama; spinner gif kemudian dilapis di atas (dengan transparansi) saat ajax bekerja.

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

Saya berakhir dengan dua perubahan pada balasan asli .

  1. Pada jQuery 1.8, ajaxStart dan ajaxStop hanya boleh dilampirkan document. Ini membuat lebih sulit untuk memfilter hanya beberapa permintaan ajax. Soo ...
  2. Beralih ke ajaxSend dan ajaxComplete memungkinkan untuk memotong permintaan ajax saat ini sebelum menampilkan pemintal.

Ini adalah kode setelah perubahan ini:

$(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
sumber
Penanganan yang bagus. ajaxCompletetampaknya menyala sebelum waktunya ketika permintaan coba lagi, jadi saya telah menggunakan kombinasi ajaxSenddan ajaxStopdan itu berfungsi dengan baik.
Mahn
@SchweizerSchoggi: Ada topik lain yang menjawab pertanyaan itu, gunakan pencarian!
Emil Stenström
8

Saya juga ingin berkontribusi untuk jawaban ini. Saya sedang mencari sesuatu yang serupa di jQuery dan ini yang akhirnya saya gunakan.

Saya mendapatkan pemintal pemuatan dari http://ajaxload.info/ . Solusi saya didasarkan pada jawaban sederhana ini di http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

Pada dasarnya markup dan CSS HTML Anda akan terlihat seperti ini:

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

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

Dan kemudian Anda kode untuk jQuery akan terlihat seperti ini:

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

Sesederhana itu :)

Brendan Vogt
sumber
8

Anda cukup menetapkan gambar pemuat ke tag yang sama di mana Anda nanti akan memuat konten menggunakan panggilan Ajax:

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

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

Anda juga dapat mengganti tag rentang dengan tag gambar.

Umesh kumar
sumber
1
Akan sulit untuk mengelola UI dengan cara ini. Kita mungkin perlu gaya yang sama sekali berbeda untuk teks "memuat" dan pesan akhir. Kita dapat menggunakan metode panggilan balik yang disebutkan di atas untuk menangani masalah ini
Jaseem
6

Selain mengatur standar global untuk acara ajax, Anda dapat mengatur perilaku untuk elemen tertentu. Mungkin mengubah kelas saja sudah cukup?

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

Contoh CSS, untuk menyembunyikan #myForm dengan pemintal:

.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
sumber
1
Ini harus menjadi jawaban yang dipilih dalam pandangan saya. Terima kasih @ LeeGee.
Nam G VU
Benar-benar jawaban yang bagus
Raskolnikov
4

Perhatikan bahwa Anda harus menggunakan panggilan asinkron agar pemintal bekerja (setidaknya itulah yang menyebabkan tambang tidak muncul hingga setelah panggilan ajax dan kemudian dengan cepat pergi setelah panggilan selesai dan melepas pemintal).

$.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
sumber
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
sumber
Cara terpendek adalah menyisipkan tag gambar dengan gambar yang diunduh dari ajaxload.info dengan latar belakang transparan
Izabela Skibinska
2

Saya telah menggunakan yang berikut dengan Dialog UI jQuery. (Mungkin bekerja dengan panggilan balik ajax lainnya?)

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

Ini berisi gif pemuatan animasi sampai isinya diganti ketika panggilan ajax selesai.

Rekomendasi Quinn
sumber
2

Ini cara terbaik bagi saya:

jQuery :

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

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

Kopi :

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

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

Documents: ajaxStart , ajaxStop

Fred K
sumber
Benar, dan Anda dapat menggunakannya bersama dengan plugin yang disebutkan dalam jawaban ini jika Anda mau ...
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
sumber
2

Ini adalah plugin yang sangat sederhana dan cerdas untuk tujuan khusus itu: https://github.com/hekigan/is-loading

dancl
sumber
Benar-benar bagus! Terutama jika Anda melihat demo ... Nonaktifkan elemen DOM, Dalam Tag, Hamparan Penuh, Hamparan Elemen ... ini menyediakan semua yang Anda butuhkan. Dan Anda dapat dengan mudah menggabungkan Hamparan Penuh dengan jawaban ini untuk membuatnya bekerja secara instan.
Matt
1

Saya melakukan ini:

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

sumber
1

Saya pikir kamu benar. Metode ini terlalu global ...

Namun - ini adalah standar yang baik untuk saat panggilan AJAX Anda tidak berpengaruh pada halaman itu sendiri. (save latar misalnya). (Anda selalu dapat mematikannya untuk panggilan ajax tertentu dengan mengirimkan "global": false - lihat dokumentasi di jquery

Ketika panggilan AJAX dimaksudkan untuk menyegarkan bagian dari halaman, saya suka gambar "memuat" saya untuk spesifik ke bagian yang di-refresh. Saya ingin melihat bagian mana yang disegarkan.

Bayangkan betapa kerennya jika Anda bisa menulis sesuatu seperti:

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

Dan ini akan menunjukkan "memuat" pada bagian ini. Di bawah ini adalah fungsi yang saya tulis yang menangani tampilan "memuat" juga tetapi khusus untuk area yang Anda refresh di ajax.

Pertama, izinkan saya menunjukkan kepada Anda bagaimana menggunakannya

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

Dan ini adalah fungsinya - awal dasar yang dapat Anda tingkatkan sesuai keinginan. ini sangat fleksibel.

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);
};
orang mograbi
sumber
1

Jika Anda berencana untuk menggunakan loader setiap kali Anda membuat permintaan server, Anda dapat menggunakan pola berikut.

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

Kode ini khususnya menggunakan plugin jajaxloader (yang baru saja saya buat)

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

ling
sumber
1

Kode ajax saya terlihat seperti ini, pada dasarnya, saya baru saja berkomentar async: baris palsu dan pemintal muncul.

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

Saya menunjukkan pemintal dalam suatu fungsi sebelum kode ajax:

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

Untuk Html, saya telah menggunakan kelas font yang mengagumkan:

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

Semoga ini bisa membantu seseorang.

Jaggan_j
sumber
0

Anda selalu dapat menggunakan plugin Blok UI jQuery yang melakukan segalanya untuk Anda, dan itu bahkan memblokir halaman dari setiap input saat ajax sedang memuat. Jika plugin tampaknya tidak berfungsi, Anda dapat membaca tentang cara yang tepat untuk menggunakannya dalam jawaban ini. Coba lihat.

SamyCode
sumber