2010-11-01 6 views
6

Il mio sito utilizzava jquery.load() per eseguire la navigazione su una grande porzione della pagina. Ho davvero apprezzato la capacità di solo includere solo una parte specifica del contenuto caricato, qui il div con id = "content":Gli script in esecuzione in jquery.ajax() pagine caricate eseguono document.ready troppo presto

$(frame_selector).load(url +" #content", function(response, status, xhr) {...}); 

Ma ora ho bisogno di essere in grado di eseguire script che fanno parte delle pagine essere caricato dinamicamente. Jquery.load() elimina questi script, ma non lo è jquery.ajax(). Così ho duplicato la funzionalità parziale contenuto di jquery.load in una chiamata AJAX come tale:

$.ajax({ 
    url: url, 
    dataType: 'html', 
    success: function(data, textStatus, XMLHttpRequest) { 
     // Only include the response within the #content id element. 
     $(frame_selector).html(jQuery("<div>") 
      .append(data) 
      .find("#content") 
    ); 
    } 
}); 

Il problema è che gli script che vengono dinamicamente caricati dalla chiamata AJAX non sono in esecuzione in modo affidabile. A volte non sembrano avere alcun effetto, forse perché stanno correndo troppo presto. Gli script stanno solo manipolando DOM in jQuery, non facendo affidamento su immagini o flash o su qualcosa che non dovrebbe essere ancora caricato. Per evitare di rimanere bloccato ho questo orribile trucco per far funzionare le cose. Invece dello script AJAX-caricato utilizzando solo:

$(document).ready(function() {...}); // unreliable 

ho ritardare l'200ms di script prima di eseguire:

$(document).ready(window.setTimeout(function() {...}, 200)); // HATE THIS 

Qualcuno sa come posso fare questo lavoro in modo affidabile senza codificare un ritardo? Sto indovinando che è una condizione di competizione tra il <script> e la mia logica per caricare #content in un nuovo div, ma non sono sicuro di cosa fare al riguardo.

+0

È possibile richiedere sincrono per acquisire i dati. – dz1984

+0

Questa è un'idea orribile. L'interfaccia utente del browser verrà bloccata mentre le richieste sincrone sono in esecuzione. –

risposta

7

Presumo che gli script stiano facendo la manipolazione sugli elementi DOM che si aggiungono tramite AJAX.

jQuery ha una proprietà isReady impostata quando l'evento ready è stato attivato sulla pagina.

Eventuali chiamate successive a jQuery.ready(...) controllano prima questo flag isReady. Se il flag è impostato su true, chiamerà immediatamente il gestore. Puoi capire perché questo potrebbe causare problemi nel tuo codice.

Un'opzione sarebbe quella di caricare la risposta in un frammento jQuery e analizzare tutti i tag <script /> per l'esecuzione successiva.

var ajaxResponse = $(html); 
var scripts = ajaxResponse.find('script'); 

// Move your scripts into a new element 
var tempScripts = $().append(scripts); 

// Append your content, followed by your script tags 
$(document).append(ajaxResponse); 
$(document).append(tempScripts); 
+0

questo è fantastico, grazie! – Neo

+0

questo non funziona per me. Il problema sembra essere che .find() non riesce a trovare gli script ... – ekkis

1

@Dan ha la risposta. Quando si caricano script tramite ajax, il documento isReady è true. Ciò significa che se questo è il tag script che viene richiesto dalla vostra richiesta ajax:

<script type="text/javascript"> 
    if (jQuery.isReady) { 
     $('body').append("<div id='new_content'>Document Ready</div>"); 
    } 
    else { 
     $('body').append("<div id='new_content'>Document Not Ready</div>"); 
    } 
</script> 

Invece di analisi utilizzano JSON. Una proprietà terrà HTML. Un'altra proprietà manterrà le sceneggiature.

Poi si può fare questo:

$(document).append(ajaxResponse.html); 
$(document).append(ajaxResponse.script); 

Anche se si carica gli script con la funzione pronta circostante si codifica si creerà una chiusura. questa chiusura durerà tutta la vita della pagina. Perdite di memoria verranno create ogni volta che si richiede lo script senza aggiornare la pagina