2011-01-23 35 views
34

Sto provando a eseguire una chiamata Ajax con jQuery che funziona bene. Uso l'evento di successo per visualizzare i dati. Sembra tuttavia che il successo venga attivato non appena viene caricato il file HTML esterno. Se ci sono immagini di grandi dimensioni, continuano a caricarsi dopo che sono state mostrate. C'è un modo per visualizzare il contenuto dopo che tutto è stato caricato completamente? Ecco il codice:jQuery Ajax aspetta che tutte le immagini siano caricate

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

risposta

39

Il plugin che @alex ha scritto non ha funzionato per me per qualche motivo ... Non riuscivo a capire perché. Ma il suo codice mi ha ispirato a trovare una soluzione più leggera che funzioni per me. Usa le promesse di jquery. Si noti che a differenza del plugin @alex, questo non tenta di tenere conto delle immagini di sfondo sugli elementi, solo degli elementi 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); 

} 

Quindi è possibile utilizzare qualcosa di simile:

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

Speriamo che questo è utile per qualcuno.

Si noti che utilizzando il codice precedente, se uno degli errori delle immagini (ad esempio perché l'URL era sbagliato), la promessa viene comunque risolta e l'errore viene ignorato. Questo potrebbe essere ciò che desideri, ma, a seconda della situazione, potresti decidere di interrompere qualsiasi cosa tu stia facendo se un'immagine non viene caricata.Nel qual caso si potrebbe sostituire la linea onerror come segue:

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

E catturare l'errore come questo:

$('#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 
}); 
+0

Questo funziona benissimo! Grazie. –

+0

Questo funziona meravigliosamente. Grazie. – J82

+0

sembra che potrebbe creare una perdita di memoria. ogni volta che effettui una chiamata Ajax, crei un duplicato di ogni immagine sulla pagina in memoria e allega un evento a ciascun nuovo oggetto immagine, mantenendo l'oggetto immagine in memoria dopo che la funzione imagesLoaded è stata completata. Una volta caricati tutti gli oggetti immagine duplicati, quando vengono rimossi dalla memoria? Subito dopo l'esecuzione del callback dell'evento onload? –

0

considerare di usare .load di jQuery()

che ha una descrizione di:

L'evento carico viene inviato ad un elemento quando e tutto il sub- gli elementi sono stati completamente caricati. Questo evento può essere inviato a qualsiasi elemento associato a un URL: immagini, script, frame, iframe e l'oggetto finestra.

+0

la cosa è non posso spegnere le chiamate asincrone con carico e impostare la cache opzioni giusto? – robs

10

È possibile associare qualcosa per gli eventi di carico di sapere quando hanno finito:

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

Oppure si potrebbe usare this plugin.

+1

oh dio non hai idea di quanto mi abbia aiutato, stavo cercando una soluzione per ore ... grazie mille: D – Linas

+5

.on() è apparentemente raccomandato su .bind() ora – UpTheCreek

0
$('#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); 
    } 
}); 
}); 
-6

Credo che la migliore è di utilizzare questo

$(window).ready(function(){ //load your ajax}) 
+0

Questo metodo è più generale ma Lo trovo funziona benissimo! –

+6

Questo non funzionerà, poiché '$ (document) .ready()' e '$ (window) .load()' non sparano dopo la richiesta AJAX. – Andreyco

16

Si potrebbe utilizzare il mio plugin per jQuery, waitForImages ...

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

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

    } 
}); 

Questo caricherà la roba nel vostro elemento, nasconderlo e quindi mostrare nuovamente gli elementi img discendenti.

+0

un plugin davvero bello che risolve il problema della muratura – ajreal

+1

@alex, posso usarlo anche per append, in pratica sto facendo scorrere infinito e aggiungendo elementi al contenitore esistente insieme ad altre immagini – kobe

+0

@alex, grazie mille per il tuo plugin, io ha dato il mio contenitore div in append e funziona perfettamente – kobe

4

ciò fa scattare su ogni carico img separatamente:

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

ho usato :

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

Prova questo codice Funziona bene.

 
$.ajax({ 
    url: "../api/listings", 
    type: 'GET', 
    success: function (html) { 
     $('#container').append(html); 
     $('#container img').on('load', function(){console.log('images loaded')}); 
    }; 
}); 
1

È possibile utilizzare imagesloaded plugin che è il lavoro con JavaScript e jQuery, provare a utilizzare all'interno ajax success funzione di callback sul contenuto caricato, e nascondere tutti i contenuti, mentre imagesloaded funzione di callback non attiva, vedi sotto codice di esempio

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

    } 
}); 
0

Ho un piccolo bug quando nessuna immagine viene trovata dal plugin dalla soluzione di Daniel.

Nel caso in cui qualche altro ottenere lo stesso problema:

Cambio:

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

A:

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