web-dev-qa-db-fra.com

jQuery Ajax attend que toutes les images soient chargées

J'essaie d'effectuer un appel Ajax avec jQuery qui fonctionne bien. J'utilise l'événement de réussite pour afficher les données. Il semble toutefois que le succès se déclenche dès que le fichier HTML externe est chargé. S'il y a de grandes images, elles continuent à se charger une fois montrées. Existe-t-il un moyen d'afficher le contenu une fois que tout est complètement chargé? Voici le code:

$('#divajax').html('<br><div style="text-align: center;"><img src="res/ajax-loader.gif"></div>');
$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
          $('#divajax').html(data);
    }
});
35
robs

Le plugin que @alex a écrit ne m'a pas fonctionné pour une raison quelconque ... Je ne pouvais pas comprendre pourquoi. Mais son code m'a inspiré pour proposer une solution plus légère qui fonctionne pour moi. Il utilise des promesses jQuery. Veuillez noter que contrairement au plugin de @alex, cela ne tente pas de rendre compte des images d’arrière-plan sur des éléments, mais uniquement des éléments img.

// Fn to allow an event to fire after all images are loaded
$.fn.imagesLoaded = function () {

    // get all the images (excluding those with no src attribute)
    var $imgs = this.find('img[src!=""]');
    // if there's no images, just return an already resolved promise
    if (!$imgs.length) {return $.Deferred().resolve().promise();}

    // for each image, add a deferred object to the array which resolves when the image is loaded (or if loading fails)
    var dfds = [];  
    $imgs.each(function(){

        var dfd = $.Deferred();
        dfds.Push(dfd);
        var img = new Image();
        img.onload = function(){dfd.resolve();}
        img.onerror = function(){dfd.resolve();}
        img.src = this.src;

    });

    // return a master promise object which will resolve when all the deferred objects have resolved
    // IE - when all the images are loaded
    return $.when.apply($,dfds);

}

Ensuite, vous pouvez l'utiliser comme ceci:

$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
        $('#divajax').html(data).imagesLoaded().then(function(){
            // do stuff after images are loaded here
        });
    }
});

J'espère que c'est utile pour quelqu'un.

Notez qu'en utilisant le code ci-dessus, si l'une des images se trompe (par exemple parce que l'URL était incorrecte), la promesse est malgré tout résolue et l'erreur est ignorée. C’est peut-être ce que vous voulez, mais, selon votre situation, vous voudrez peut-être abandonner ce que vous faites si le chargement d’une image échoue. Dans ce cas, vous pouvez remplacer la ligne onerror comme suit:

img.onerror = function(){dfd.reject();}

Et attrapez l'erreur comme ceci:

$('#divajax').html(data).imagesLoaded().done(function(){
    // do stuff after all images are loaded successfully here
}).fail(function(){
    // do stuff if any one of the images fails to load
});
46
Daniel Howard

Vous pouvez utiliser mon plugin jQuery, waitForImages ...

$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {

         $('#divajax').html(data).hide().waitForImages(function() {
             $(this).show();
         });

    }
});

Cela chargera le contenu dans votre élément, le masquera, puis le reverra une fois les éléments img descendants chargés.

17
alex

Vous pouvez lier quelque chose aux événements de chargement pour savoir quand ils sont terminés:

$('<img>').bind('load', function() {
    $(this).appendTo('body');
});

Ou vous pouvez utiliser ce plugin .

10
Lyle Pratt

cela déclenche séparément sur chaque chargement img:

$('img').on('load', function() {
      // do something
});

j'ai utilisé:

var loaded = 0;
$('img').on('load', function() {
   loaded++;
   if(loaded == $('img').length){
      // do something
   }
});
4
Aureliano Far Suau

Vous pouvez utiliser imagesloaded plugin fonctionnant avec JavaScript et jQuery, essayer d'utiliser la fonction de rappel dans ajax success sur le contenu chargé et masquer tout le contenu sans que la fonction de rappel imagesloaded ne se déclenche (voir exemple de code ci-dessous)

$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
        var $divajax = $('#divajax').html(data).hide();
        $divajax.imagesLoaded(function() {
             $divajax.show();
         });

    }
});
1
Girish

Essayez ce code. Ça fonctionne bien.

 $. ajax ({
 url: "../api/listings" ,
 type: 'GET', 
 success: function (html) {
 $ ('# conteneur' ) .append (html); 
 $ ('# conteneur img'). on ('charger', fonction () {console.log ('images chargées')}). 
}; 
} ); 
0
Duy Phan

J'ai un petit bug quand aucune image n'est trouvée par le plugin de la solution de Daniel.

Juste au cas où d'autres trouveraient le même problème:

Changement:

// if there's no images, just return an already resolved promise
if (!$imgs.length) {return $.Deferred.resolve().promise();}

À :

// if there's no images, just return an already resolved promise
    if (!$imgs.length) {
        var dfd = $.Deferred();
        return dfd.resolve().promise();
    }
0
Milton Pena

Regardez dans l'utilisation de .load () de jquery 

Qui a une description de:

L'événement de chargement est envoyé à un élément lorsqu'il a été chargé avec tous les sous-éléments. Cet événement peut être envoyé à tout élément associé à une URL: images, scripts, cadres, iframes et objet window.

0
AlanFoster
$('#divajax').html('<br><div style="text-align: center;"><img src="res/ajax-loader.gif"></div>').load(function() {
$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
          $('#divajax').html(data);
    }
});
});
0
sv_in