Odpowiedzi:
Możesz to zrobić na różne sposoby. Może to być subtelny, jak mały status na stronie z napisem „Ładowanie ...”, lub tak głośny, jak cały element wyszarzający stronę podczas ładowania nowych danych. Podejście, które przyjmuję poniżej, pokaże ci, jak osiągnąć obie metody.
Zacznijmy od uzyskania ładnej animacji „ładowania” ze strony http://ajaxload.info, której będę używać
Stwórzmy element, który możemy pokazać / ukryć za każdym razem, gdy wysyłamy żądanie ajax:
<div class="modal"><!-- Place at bottom of page --></div>
Następnie nadajmy mu nieco stylu:
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
}
/* When the body has the loading class, we turn
the scrollbar off with overflow:hidden */
body.loading .modal {
overflow: hidden;
}
/* Anytime the body has the loading class, our
modal element will be visible */
body.loading .modal {
display: block;
}
W porządku, przejdź do jQuery. Ta kolejna część jest naprawdę bardzo prosta:
$body = $("body");
$(document).on({
ajaxStart: function() { $body.addClass("loading"); },
ajaxStop: function() { $body.removeClass("loading"); }
});
Otóż to! Dołączamy niektóre zdarzenia do elementu ciała za każdym razem, gdy uruchamiane są zdarzenia ajaxStart
lub ajaxStop
zdarzenia. Kiedy rozpoczyna się zdarzenie ajax, dodajemy do treści klasę „loading”. a po zakończeniu zdarzeń usuwamy z treści klasę „ładującą”.
Zobacz to w akcji: http://jsfiddle.net/VpDUG/4952/
.ajaxStop()
i .ajaxStart()
powinna być dołączana tylko do dokumentu. docs
Jeśli chodzi o rzeczywisty ładowany obraz, sprawdź tę stronę, aby znaleźć wiele opcji.
Jeśli chodzi o wyświetlanie DIV z tym obrazem, gdy rozpoczyna się żądanie, masz kilka możliwości:
A) Ręcznie pokaż i ukryj obraz:
$('#form').submit(function() {
$('#wait').show();
$.post('/whatever.php', function() {
$('#wait').hide();
});
return false;
});
B) Użyj ajaxStart i ajaxComplete :
$('#wait').ajaxStart(function() {
$(this).show();
}).ajaxComplete(function() {
$(this).hide();
});
Za pomocą tego elementu element pokaże / ukryje się dla każdego żądania. Może być dobry lub zły, w zależności od potrzeby.
C) Użyj poszczególnych oddzwonień dla konkretnego żądania:
$('#form').submit(function() {
$.ajax({
url: '/whatever.php',
beforeSend: function() { $('#wait').show(); },
complete: function() { $('#wait').hide(); }
});
return false;
});
Oprócz tego, co zasugerowali Jonathan i Samir (obie doskonałe odpowiedzi btw!), JQuery ma wbudowane zdarzenia, które będą uruchamiane dla ciebie podczas tworzenia żądania ajax.
Jest ajaxStart
wydarzenie
Pokaż komunikat ładowania przy każdym uruchomieniu żądania AJAX (i żadne nie jest już aktywne).
... i to jest brat, ajaxStop
wydarzenie
Dołącz funkcję do wykonania po zakończeniu wszystkich żądań AJAX. To jest wydarzenie Ajax.
Razem stanowią świetny sposób na wyświetlenie komunikatu o postępie, gdy dowolna aktywność ajax ma miejsce w dowolnym miejscu na stronie.
HTML:
<div id="loading">
<p><img src="loading.gif" /> Please Wait</p>
</div>
Scenariusz:
$(document).ajaxStart(function(){
$('#loading').show();
}).ajaxStop(function(){
$('#loading').hide();
});
.ajaxStart
może być dołączone tylko do dokumentu, tj. $(document).ajaxStart(function(){}).
Możesz pobrać animowany plik GIF obracającego się koła z Ajaxload - trzymaj go gdzieś w swojej heirarchii plików na swojej stronie. Następnie wystarczy dodać element HTML z poprawnym kodem i usunąć go, gdy skończysz. Jest to dość proste:
function showLoadingImage() {
$('#yourParentElement').append('<div id="loading-image"><img src="path/to/loading.gif" alt="Loading..." /></div>');
}
function hideLoadingImage() {
$('#loading-image').remove();
}
Następnie wystarczy użyć tych metod w wywołaniu AJAX:
$.load(
'http://example.com/myurl',
{ 'random': 'data': 1: 2, 'dwarfs': 7},
function (responseText, textStatus, XMLHttpRequest) {
hideLoadingImage();
}
);
// this will be run immediately after the AJAX call has been made,
// not when it completes.
showLoadingImage();
Ma to kilka ostrzeżeń: po pierwsze, jeśli masz dwa lub więcej miejsc, w których można wyświetlić obraz ładowania, będziesz musiał sprawdzić, ile połączeń jest uruchomionych jednocześnie, i ukryć się tylko wtedy, gdy są wszystko gotowe. Można to zrobić za pomocą prostego licznika, który powinien działać w prawie wszystkich przypadkach.
Po drugie, ukryje to tylko ładowanie obrazu podczas udanego wywołania AJAX. Aby obsłużyć stany błędów, trzeba przyjrzeć się $.ajax
, co jest bardziej skomplikowane niż $.load
, $.get
i tym podobne, ale o wiele bardziej elastyczny zbyt.
showLoadingImage
przed rozpoczęciem i hideLoadingImage
po zakończeniu. Powinno być dość proste. Może być konieczne wstawienie jakiegoś setTimeout
wywołania, aby upewnić się, że przeglądarka rzeczywiście renderuje nowy <img>
tag - widziałem kilka przypadków, w których nie przeszkadza to, dopóki JavaScript nie zakończy działania.
Doskonałe rozwiązanie Jonathona pęka w IE8 (animacja wcale się nie wyświetla). Aby to naprawić, zmień CSS na:
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('http://i.stack.imgur.com/FhHRx.gif')
50% 50%
no-repeat;
opacity: 0.80;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);
filter: alpha(opacity = 80)};
jQuery zapewnia przechwytywanie zdarzeń, gdy żądania AJAX zaczynają się i kończą. Możesz podłączyć się do nich, aby pokazać swój moduł ładujący.
Na przykład utwórz następujący div:
<div id="spinner">
<img src="images/spinner.gif" alt="Loading" />
</div>
Ustaw to display: none
w swoich arkuszach stylów. Możesz go stylizować w dowolny sposób. Możesz wygenerować ładny obraz ładujący na Ajaxload.info , jeśli chcesz.
Następnie możesz użyć czegoś takiego jak poniżej, aby wyświetlać się automatycznie podczas wysyłania żądań Ajax:
$(document).ready(function () {
$('#spinner').bind("ajaxSend", function() {
$(this).show();
}).bind("ajaxComplete", function() {
$(this).hide();
});
});
Po prostu dodaj ten blok Javascript na końcu strony przed zamknięciem tagu body lub w dowolnym innym miejscu.
Teraz, ilekroć wysyłasz żądania Ajax, #spinner
div zostanie wyświetlony. Po zakończeniu żądania zostanie ono ponownie ukryte.
Jeśli używasz Turbolinks z szynami, oto moje rozwiązanie:
To jest CoffeeScript
$(window).on 'page:fetch', ->
$('body').append("<div class='modal'></div>")
$('body').addClass("loading")
$(window).on 'page:change', ->
$('body').removeClass("loading")
To jest SASS CSS oparty na pierwszej doskonałej odpowiedzi Jonathana Sampsona
# loader.css.scss
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, 0.4)
asset-url('ajax-loader.gif', image)
50% 50%
no-repeat;
}
body.loading {
overflow: hidden;
}
body.loading .modal {
display: block;
}
Tak jak Mark H powiedział, że blockUI jest drogą.
Dawny.:
<script type="text/javascript" src="javascript/jquery/jquery.blockUI.js"></script>
<script>
// unblock when ajax activity stops
$(document).ajaxStop($.unblockUI);
$("#downloadButton").click(function() {
$("#dialog").dialog({
width:"390px",
modal:true,
buttons: {
"OK, AGUARDO O E-MAIL!": function() {
$.blockUI({ message: '<img src="img/ajax-loader.gif" />' });
send();
}
}
});
});
function send() {
$.ajax({
url: "download-enviar.do",
type: "POST",
blablabla
});
}
</script>
Obs .: Mam plik ajax-loader.gif na http://www.ajaxload.info/
Z całym szacunkiem dla innych postów, masz tutaj bardzo proste rozwiązanie, używając CSS3 i jQuery, bez użycia jakichkolwiek dodatkowych zasobów zewnętrznych ani plików.
$('#submit').click(function(){
$(this).addClass('button_loader').attr("value","");
window.setTimeout(function(){
$('#submit').removeClass('button_loader').attr("value","\u2713");
$('#submit').prop('disabled', true);
}, 3000);
});
#submit:focus{
outline:none;
outline-offset: none;
}
.button {
display: inline-block;
padding: 6px 12px;
margin: 20px 8px;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
background-image: none;
border: 2px solid transparent;
border-radius: 5px;
color: #000;
background-color: #b2b2b2;
border-color: #969696;
}
.button_loader {
background-color: transparent;
border: 4px solid #f3f3f3;
border-radius: 50%;
border-top: 4px solid #969696;
border-bottom: 4px solid #969696;
width: 35px;
height: 35px;
-webkit-animation: spin 0.8s linear infinite;
animation: spin 0.8s linear infinite;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
99% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
99% { transform: rotate(360deg); }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="submit" class="button" type="submit" value="Submit" />
Spowoduje to, że przyciski znikną, a następnie pojawi się animacja „ładowania” na ich miejscu, a na koniec wyświetli się komunikat o powodzeniu.
$(function(){
$('#submit').click(function(){
$('#submit').hide();
$("#form .buttons").append('<img src="assets/img/loading.gif" alt="Loading..." id="loading" />');
$.post("sendmail.php",
{emailFrom: nameVal, subject: subjectVal, message: messageVal},
function(data){
jQuery("#form").slideUp("normal", function() {
$("#form").before('<h1>Success</h1><p>Your email was sent.</p>');
});
}
);
});
});
Większość rozwiązań, które widziałem, wymaga od nas zaprojektowania nakładki ładującej, ukrycia jej, a następnie odsłonięcia w razie potrzeby, lub pokazania gifa lub obrazu itp.
Chciałem opracować solidną wtyczkę, w której za pomocą zwykłego wywołania jQuery mogę wyświetlić ekran ładowania i zerwać go po zakończeniu zadania.
Poniżej znajduje się kod. To zależy od niesamowitej czcionki i jQuery:
/**
* Raj: Used basic sources from here: http://jsfiddle.net/eys3d/741/
**/
(function($){
// Retain count concept: http://stackoverflow.com/a/2420247/260665
// Callers should make sure that for every invocation of loadingSpinner method there has to be an equivalent invocation of removeLoadingSpinner
var retainCount = 0;
// http://stackoverflow.com/a/13992290/260665 difference between $.fn.extend and $.extend
$.extend({
loadingSpinner: function() {
// add the overlay with loading image to the page
var over = '<div id="custom-loading-overlay">' +
'<i id="custom-loading" class="fa fa-spinner fa-spin fa-3x fa-fw" style="font-size:48px; color: #470A68;"></i>'+
'</div>';
if (0===retainCount) {
$(over).appendTo('body');
}
retainCount++;
},
removeLoadingSpinner: function() {
retainCount--;
if (retainCount<=0) {
$('#custom-loading-overlay').remove();
retainCount = 0;
}
}
});
}(jQuery));
Wystarczy umieścić powyższe w pliku js i dołączyć go do całego projektu.
Dodanie CSS:
#custom-loading-overlay {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
background: #000;
opacity: 0.8;
filter: alpha(opacity=80);
}
#custom-loading {
width: 50px;
height: 57px;
position: absolute;
top: 50%;
left: 50%;
margin: -28px 0 0 -25px;
}
Wezwanie:
$.loadingSpinner();
$.removeLoadingSpinner();
Zauważ, że podczas korzystania z ASP.Net MVC z using (Ajax.BeginForm(...
ustawieniem ajaxStart
nie będzie działać.
Użyj, AjaxOptions
aby rozwiązać ten problem:
(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))
Na https://www.w3schools.com/howto/howto_css_loader.asp jest to 2-etapowy proces bez JS:
1. Dodaj ten kod HTML w miejscu, w którym chcesz pokrętło: <div class="loader"></div>
2. Dodaj ten CSS, aby rzeczywista przędzarka:
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
$("#loader").toggle();
przed długim żądaniem uruchomienia animacji i wykonać kolejne wywołanie w funkcji wywołania zwrotnego żądania, aby je ukryć.
Używam CSS3 do animacji
/************ CSS3 *************/
.icon-spin {
font-size: 1.5em;
display: inline-block;
animation: spin1 2s infinite linear;
}
@keyframes spin1{
0%{transform:rotate(0deg)}
100%{transform:rotate(359deg)}
}
/************** CSS3 cross-platform ******************/
.icon-spin-cross-platform {
font-size: 1.5em;
display: inline-block;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin2 2s infinite linear;
}
@keyframes spin2{
0%{transform:rotate(0deg)}
100%{transform:rotate(359deg)}
}
@-moz-keyframes spin2{
0%{-moz-transform:rotate(0deg)}
100%{-moz-transform:rotate(359deg)}
}
@-webkit-keyframes spin2{
0%{-webkit-transform:rotate(0deg)}
100%{-webkit-transform:rotate(359deg)}
}
@-o-keyframes spin2{
0%{-o-transform:rotate(0deg)}
100%{-o-transform:rotate(359deg)}
}
@-ms-keyframes spin2{
0%{-ms-transform:rotate(0deg)}
100%{-ms-transform:rotate(359deg)}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-md-6">
Default CSS3
<span class="glyphicon glyphicon-repeat icon-spin"></span>
</div>
<div class="col-md-6">
Cross-Platform CSS3
<span class="glyphicon glyphicon-repeat icon-spin-cross-platform"></span>
</div>
</div>