Réponses:
Vous pouvez le faire de différentes manières. Cela peut être subtil comme un petit statut sur la page disant "Chargement ...", ou aussi fort qu'un élément entier grisant la page pendant le chargement des nouvelles données. L'approche que je prends ci-dessous vous montrera comment accomplir les deux méthodes.
Commençons par nous faire une belle animation de "chargement" de http://ajaxload.info que j'utiliserai
Créons un élément que nous pouvons afficher / masquer chaque fois que nous faisons une demande ajax:
<div class="modal"><!-- Place at bottom of page --></div>
Donnons-lui ensuite un peu de flair:
/* 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;
}
D'accord, sur la jQuery. Cette partie suivante est en fait très simple:
$body = $("body");
$(document).on({
ajaxStart: function() { $body.addClass("loading"); },
ajaxStop: function() { $body.removeClass("loading"); }
});
C'est ça! Nous attachons certains événements à l'élément body chaque fois que les événements ajaxStart
or ajaxStop
sont déclenchés. Lorsqu'un événement ajax démarre, nous ajoutons la classe "loading" au corps. et lorsque les événements sont terminés, nous supprimons la classe "loading" du corps.
Voyez-le en action: http://jsfiddle.net/VpDUG/4952/
.ajaxStop()
et .ajaxStart()
ne doit être attachée qu'au document. docs
En ce qui concerne l'image de chargement réelle, consultez ce site pour un tas d'options.
En ce qui concerne l'affichage d'un DIV avec cette image lorsqu'une demande commence, vous avez plusieurs choix:
A) Affichez et masquez manuellement l'image:
$('#form').submit(function() {
$('#wait').show();
$.post('/whatever.php', function() {
$('#wait').hide();
});
return false;
});
B) Utilisez ajaxStart et ajaxComplete :
$('#wait').ajaxStart(function() {
$(this).show();
}).ajaxComplete(function() {
$(this).hide();
});
En utilisant cela, l'élément sera affiché / masqué pour toute demande. Peut être bon ou mauvais, selon le besoin.
C) Utilisez des rappels individuels pour une demande particulière:
$('#form').submit(function() {
$.ajax({
url: '/whatever.php',
beforeSend: function() { $('#wait').show(); },
complete: function() { $('#wait').hide(); }
});
return false;
});
Parallèlement à ce que Jonathan et Samir ont suggéré (les deux excellentes réponses btw!), JQuery a des événements intégrés qu'il déclenchera pour vous lors d'une demande ajax.
Il y a l' ajaxStart
événement
Afficher un message de chargement chaque fois qu'une demande AJAX démarre (et qu'aucune n'est déjà active).
... et c'est frère, l' ajaxStop
événement
Attachez une fonction à exécuter à la fin de toutes les requêtes AJAX. Il s'agit d'un événement Ajax.
Ensemble, ils constituent un excellent moyen d'afficher un message de progression lorsqu'une activité ajax se produit n'importe où sur la page.
HTML:
<div id="loading">
<p><img src="loading.gif" /> Please Wait</p>
</div>
Scénario:
$(document).ajaxStart(function(){
$('#loading').show();
}).ajaxStop(function(){
$('#loading').hide();
});
.ajaxStart
ne peut être attaché qu'au document, c'est-à-dire. $(document).ajaxStart(function(){}).
Vous pouvez saisir un GIF animé d'un cercle tournant à partir d' Ajaxload - collez-le quelque part dans la hiérarchie des fichiers de votre site Web. Il vous suffit ensuite d'ajouter un élément HTML avec le code correct et de le supprimer lorsque vous avez terminé. C'est assez simple:
function showLoadingImage() {
$('#yourParentElement').append('<div id="loading-image"><img src="path/to/loading.gif" alt="Loading..." /></div>');
}
function hideLoadingImage() {
$('#loading-image').remove();
}
Il vous suffit alors d'utiliser ces méthodes dans votre appel 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();
Cela a quelques mises en garde: tout d'abord, si vous avez deux ou plusieurs endroits où l'image de chargement peut être affichée, vous devrez garder une trace du nombre d'appels en cours à la fois d'une manière ou d'une autre, et ne masquer que lorsqu'ils sont terminé. Cela peut être fait à l'aide d'un simple compteur, qui devrait fonctionner dans presque tous les cas.
Deuxièmement, cela ne masquera l'image de chargement que lors d'un appel AJAX réussi. Pour gérer les états d'erreur, vous devrez examiner $.ajax
ce qui est plus complexe que $.load
, $.get
etc., mais beaucoup plus flexible également.
showLoadingImage
avant de commencer et hideLoadingImage
après avoir terminé. Devrait être assez simple. Vous devrez peut-être coller une sorte d' setTimeout
appel pour vous assurer que le navigateur restitue bien la nouvelle <img>
balise - j'ai vu quelques cas où cela ne dérange pas jusqu'à ce que JavaScript soit terminé.
L'excellente solution de Jonathon se casse dans IE8 (l'animation ne s'affiche pas du tout). Pour résoudre ce problème, changez le CSS en:
.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 fournit des hooks d'événements pour le début et la fin des requêtes AJAX. Vous pouvez vous y connecter pour montrer votre chargeur.
Par exemple, créez le div suivant:
<div id="spinner">
<img src="images/spinner.gif" alt="Loading" />
</div>
Réglez-le display: none
dans vos feuilles de style. Vous pouvez le coiffer comme vous le souhaitez. Vous pouvez générer une belle image de chargement sur Ajaxload.info , si vous le souhaitez.
Ensuite, vous pouvez utiliser quelque chose comme le suivant pour le faire s'afficher automatiquement lors de l'envoi de demandes Ajax:
$(document).ready(function () {
$('#spinner').bind("ajaxSend", function() {
$(this).show();
}).bind("ajaxComplete", function() {
$(this).hide();
});
});
Ajoutez simplement ce bloc Javascript à la fin de votre page avant de fermer votre balise body ou où bon vous semble.
Maintenant, chaque fois que vous envoyez des demandes Ajax, le #spinner
div sera affiché. Une fois la demande terminée, elle sera à nouveau masquée.
Si vous utilisez Turbolinks With Rails, voici ma solution:
C'est le CoffeeScript
$(window).on 'page:fetch', ->
$('body').append("<div class='modal'></div>")
$('body').addClass("loading")
$(window).on 'page:change', ->
$('body').removeClass("loading")
Ceci est le CSS SASS basé sur la première excellente réponse de Jonathan Sampson
# 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;
}
Comme l'a dit Mark H, le blockUI est le chemin.
Ex.:
<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 .: J'ai reçu le ajax-loader.gif sur http://www.ajaxload.info/
Avec tout le respect que je dois aux autres articles, vous avez ici une solution très simple, utilisant CSS3 et jQuery, sans utiliser d'autres ressources ni fichiers externes.
$('#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" />
Cela ferait disparaître les boutons, puis une animation de "chargement" apparaîtrait à leur place et afficherait finalement juste un message de réussite.
$(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>');
});
}
);
});
});
La plupart des solutions que j'ai vues attendent de nous que nous concevions une superposition de chargement, la gardions cachée et ensuite la révélions si nécessaire, ou, montrons un gif ou une image etc.
Je voulais développer un plugin robuste, où avec un simple appel jQuery, je peux afficher l'écran de chargement et le démonter lorsque la tâche est terminée.
Voici le code. Cela dépend de Font awesome et 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));
Il suffit de mettre ce qui précède dans un fichier js et de l'inclure tout au long du projet.
Ajout 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;
}
Invocation:
$.loadingSpinner();
$.removeLoadingSpinner();
Notez que lorsque vous utilisez ASP.Net MVC, avec using (Ajax.BeginForm(...
, la définition de ajaxStart
ne fonctionnera pas.
Utilisez le AjaxOptions
pour surmonter ce problème:
(Ajax.BeginForm("ActionName", new AjaxOptions { OnBegin = "uiOfProccessingAjaxAction", OnComplete = "uiOfProccessingAjaxActionComplete" }))
Par https://www.w3schools.com/howto/howto_css_loader.asp , il s'agit d'un processus en 2 étapes sans JS:
1.Ajoutez ce HTML où vous voulez que le spinner: <div class="loader"></div>
2.Ajoutez ce CSS pour créer le véritable spinner:
.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();
avant d'effectuer la demande de longue durée pour démarrer l'animation et effectuer un autre appel dans la fonction de rappel de la demande pour la masquer.
J'utilise CSS3 pour l'animation
/************ 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>