Як показати завантажувальний спінер у jQuery?


412

У прототипі я можу показати "завантажуюче ..." зображення з цим кодом:

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

function showLoad () {
    ...
}

У jQuery я можу завантажити серверну сторінку в елемент із цим:

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

але як я можу долучити до цієї команди спінер завантаження, як це було зроблено в прототипі?

Відповіді:


793

Є кілька способів. Мій кращий спосіб - приєднати функцію до подій ajaxStart / Stop на самому елементі.

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

Функції ajaxStart / Stop запускаються кожного разу, коли ви здійснюєте будь-які дзвінки Ajax.

Оновлення : Станом на jQuery 1.8, у документації зазначено, що .ajaxStart/Stopслід додавати лише до document. Це перетворить описаний вище фрагмент на:

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

48
Це, мабуть, занадто глобально для одного простого завантаження в DIV.
Монреаліст

363
занадто глобальний? скільки різноманітних повідомлень "будь ласка, зачекай" ти хочеш?
nickf

23
таким чином, на жаль, ви не можете контролювати позиціонування завантажувальних файлів у випадку, якщо ви не хочете просто показати модальне вікно завантаження, але показати його біля елемента, який очікує завантаження вмісту ajax ...
glaz666

10
ajaxStart і ajaxStop є події JQuery , так що ви можете їх простір імен: stackoverflow.com/questions/1191485 / ... docs.jquery.com/Namespaced_Events
David Xia

10
Якщо ви використовуєте jQuery> = 1.9, прикріпіть події ajaxStart та ajaxStop до $ (document). jquery.com/upgrade-guide/1.9 / ...
Доменік

213

Для jQuery я використовую

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

13
працює для мене, у html має бути щось на кшталт: <div id = 'loader'> <img src = "spinner.gif" /> </div>
yigal

7
Цей був для мене найчистішим. Замість ajaxSetup я поставив передSend: і завершити: всередині $ ajax ({... заява.
kenswdev

4
Не знаєте, що це варто, але jQuery в своїй документації зазначає, що використання .ajaxSetup () не рекомендується. посилання
pec

Зауважте тут, що beforeSendвикликається перед кожним викликом, тоді ajaxStartяк спрацьовує лише тоді, коли викликається перший метод ajax. Так само для цього ajaxStop, він викликається, коли завершується останній виклик ajax. Якщо у вас є кілька одночасних запитів, фрагмент у цій відповіді не працюватиме належним чином.
nickf

Не працює для мене, якщо час виклику Ajax закінчується (Firefox 28 для Mac).
osa

48

Ви можете просто скористатись .ajaxфункцією jQuery і скористатися її опцією beforeSendта визначити деяку функцію, в якій ви можете показати щось на зразок завантажувача div, а при успішному варіанті ви можете приховати цей div 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();
    }
});

Ви можете мати будь-яке зображення обертового Gif. Ось веб-сайт, який є чудовим генератором завантажувачів AJAX відповідно до вашої кольорової гами: http://ajaxload.info/


16
successЧи не буде викликатися , якщо є помилка, але «ви завжди отримаєте completeзворотний виклик, навіть для синхронних запитів,» в відповідно до JQuery Ajax подій .
LeeGee

23

Ви можете вставити анімоване зображення в DOM безпосередньо перед викликом AJAX і виконати вбудовану функцію для його видалення ...

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

Це дозволить переконатися, що ваша анімація починається в тому ж кадрі при наступних запитах (якщо це має значення). Зауважте, що старі версії IE можуть мати проблеми з анімацією.

Удачі!


13
Верхня порада: попередньо завантажте spinner.gif у розділ, у якому дисплей не встановлений. В іншому випадку ви можете отримати трохи затримку ефекту спінеру, оскільки спінер все ще завантажує.
uriDium

чудова порада, набагато простіше, ніж використовувати чужий плагін
Гордон Томпсон,

Приємно! але дорогий, ще одне, що я хочу відображати спінер протягом 2 секунд, навіть якщо сторінка вже завантажена.
Обидва FM

5
@BothFM Тому що людям подобається чекати речей ...?
Джош Стодола

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

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

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


У вас можуть виникнути проблеми з термінами, чи не так?
Тім Б’юте

2
@UltimateBrent Я думаю, ти неправильно зрозумів. Чому showLoad () не є зворотним дзвоном? JavaScript завантажує вміст асинхронно. showLoad () буде працювати навіть перед завантаженням вмісту, якщо я правильний.
Jaseem

2
@Jaseem Я також використовую подібний метод, і він фактично покладається на виклики async. Я б розмістив showLoad десь перед викликом Ajax, але вся справа в тому, щоб показати спінер, нехай JS починає дзвінок і вбиває спінер у зворотній виклик після завершення AJAX.
Ненотлеп

17

Якщо ви використовуєте, $.ajax()ви можете використовувати щось подібне:

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

Скористайтеся плагіном для завантаження: http://plugins.jquery.com/project/loading

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

10
Один плагін для цього простого завдання? Це насправді не гарне рішення? Хто хоче завантажити 100 скриптів на сторінку?
Jaseem

2
Домовились. Стисніть і з'єднайте, якщо хочете кращої продуктивності.
Натан Бубна

9
Не погоджуючись: розділіть та модулюйте, повторно використовуйте код, якщо ви хочете підтримувати свою роботу та дозволити цьому робити й інших. Яка ймовірність того, що ваш користувач має таке погане з'єднання, що їх клієнт не може завантажити плагін, а також ваш код?
LeeGee

@NathanBubna Посилання мертве
SpringLearner

"Яка ймовірність того, що ваш користувач має таке погане з'єднання, що їх клієнт не може завантажити плагін, а також ваш код?" Дуже добре, я б сказав.
andrew oxenburgh

9

Варіант: у мене піктограма з id = "логотипом" у верхньому лівому куті головної сторінки; потім gif gif накладається зверху (з прозорістю), коли ajax працює.

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

9

Я закінчив дві зміни оригінальної відповіді .

  1. Станом на jQuery 1.8, ajaxStart та ajaxStop слід приєднувати лише до document . Це ускладнює фільтрацію лише деяких запитів ajax. Так ...
  2. Перехід на ajaxSend і ajaxComplete дає змогу перехрестити поточний запит ajax перед тим, як показувати спінер.

Це код після цих змін:

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

Гарний спосіб подолання. ajaxCompleteздається, спрацьовує передчасно , коли запити повторити, тому я використовував комбінацію ajaxSendі ajaxStopі він прекрасно працює.
Ман

@SchweizerSchoggi: Є інші теми, які відповідають на це питання, використовуйте пошук!
Еміль Стенстрем

8

Я також хочу внести свій внесок у цю відповідь. Я шукав щось подібне в jQuery, і це я в кінцевому підсумку використовував.

Я отримав свій спінер із завантаження від http://ajaxload.info/ . Моє рішення засноване на цій простій відповіді на веб- сторінці http://christierney.com/2011/03/23/global-ajax-loading-spinners/ .

В основному ваша розмітка HTML і CSS виглядатимуть так:

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

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

І тоді ви код для jQuery виглядатиме приблизно так:

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

Це так просто, як це :)


8

Ви можете просто призначити зображення завантажувача тому самому тегу, на який пізніше ви завантажите вміст за допомогою дзвінка Ajax:

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

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

Ви також можете замінити тег span тегом зображення.


1
Керувати інтерфейсом користувача буде важко таким чином. Нам можуть знадобитися абсолютно різні стилі для "завантаження" тексту та остаточного повідомлення. Для вирішення цієї проблеми ми можемо використовувати метод зворотного виклику
Jaseem

6

Окрім встановлення глобальних значень за замовчуванням для подій ajax, ви можете встановити поведінку для конкретних елементів. Можливо, достатньо було б просто змінити свій клас?

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

Приклад CSS, щоб приховати #myForm за допомогою спінера:

.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
На мій погляд, це повинна бути обрана відповідь. Дякую @LeeGee.
Нам Г ВУ

Дійсно чудова відповідь
Раскольников

4

Зауважте, що ви повинні використовувати асинхронні дзвінки для того, щоб спінери працювали (принаймні, саме це спричинило показ моїх, поки не відбувся виклик Ajax, а потім швидко пішов, коли виклик закінчився і вилучив спінер).

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

            }
        });

Найкоротшим способом було б вставити тег зображення із зображенням, завантаженим з ajaxload.info з прозорим фоном
Ізабела Скибінська

2

Я використовував наступне з діалогом інтерфейсу jQuery. (Можливо, це працює з іншими зворотними дзвінками Ajax?)

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

Він містить анімований gif завантаження до тих пір, поки його вміст не буде замінено після завершення дзвінка ajax.


2

Це найкращий спосіб для мене:

jQuery :

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

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

Кава :

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

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

Документи: ajaxStart , ajaxStop


Правильно, і ви можете використовувати його разом із плагіном, згаданим у цій відповіді, якщо хочете ...
Метт

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

Це дуже простий і розумний плагін для цієї конкретної мети: https://github.com/hekigan/is-loading


Дійсно приємно! Особливо, якщо ви подивитеся на демонстрацію ... Вимкнення елементів DOM, в тезі, повне накладання, накладання елементів ... воно забезпечує все необхідне. І ви можете легко поєднати повну накладку з цією відповіддю, щоб миттєво працювали.
Метт

1

Я роблю це:

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

Я думаю, ти маєш рацію. Цей метод занадто глобальний ...

Однак - це гарний дефолт, коли ваш дзвінок AJAX не впливає на саму сторінку. (фонове збереження, наприклад). (ви завжди можете вимкнути його для певного виклику ajax, передавши "global": false - див. документацію на jquery

Коли виклик AJAX призначений для оновлення частини сторінки, мені подобається, що мої "завантажувальні" зображення мають специфічний характер для оновленого розділу. Я хотів би побачити, яка частина оновлена.

Уявіть, як було б круто, якби ви могли просто написати щось на кшталт:

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

І це показало б "завантаження" на цьому розділі. Нижче наведена функція, яку я написав, що також обробляє "завантажувальний" дисплей, але він характерний для області, яку ви освіжаєте в аяксе.

Спочатку дозвольте показати вам, як ним користуватися

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

І це функція - базовий старт, який ви можете покращити за своїм бажанням. він дуже гнучкий.

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

Якщо ви плануєте використовувати завантажувач щоразу, коли ви робите запит на сервер, ви можете використовувати наступну схему.

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

Цей код, зокрема, використовує плагін jajaxloader (який я щойно створив)

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


1

Мій код Ajax виглядає так, фактично я щойно прокоментував асинхронізацію: помилкова лінія і спінер з'являється.

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

Я показую спінер у функції перед кодом ajax:

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

Для Html я використовував дивовижний клас шрифту:

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

Сподіваюся, це комусь допоможе.


0

Ви завжди можете використовувати плагін jQuery Block UI, який робить все за вас, і він навіть блокує сторінку будь-якого вводу під час завантаження ajax. У випадку, якщо плагін, здається, не працює, ви можете прочитати про правильний спосіб його використання у цій відповіді. Перевір.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.