2010-11-01 23 views
6

Mi sitio usaba jquery.load() para navegar en una gran parte de la página. Realmente aprecio la capacidad de solamente incluir sólo una parte particular del contenido cargado, aquí el div con id = "content":Las secuencias de comandos que se ejecutan en jquery.ajax() páginas cargadas ejecutan document.ready demasiado pronto

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

Pero ahora tengo que ser capaz de ejecutar secuencias de comandos que forman parte de las páginas siendo cargado dinámicamente Jquery.load() elimina estas secuencias de comandos, pero jquery.ajax() no. Así que duplicó la funcionalidad parcial del contenido de jquery.load en una llamada AJAX como tal:

$.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") 
    ); 
    } 
}); 

El problema es que los scripts que se están cargando dinámicamente de la llamada AJAX no se están ejecutando de forma fiable. A veces no parecen tener ningún efecto, tal vez porque se están ejecutando demasiado pronto. Los scripts solo hacen manipulación de DOM en jquery, sin depender de imágenes o flash ni nada que no se haya cargado aún. Para evitar quedar atascado, tengo este truco horrible para que las cosas funcionen. En lugar de la secuencia de comandos cargado en AJAX simplemente usando:

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

tardo los 200 ms antes de ejecutar secuencias de comandos:

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

Alguien sabe cómo puedo hacer que esto funcione de forma fiable y sin codificación dura de un retraso? Supongo que es una condición de carrera entre el <script> y mi lógica cargar #content en un nuevo div, pero no estoy seguro de qué hacer al respecto.

+0

Puede realizar solicitudes sincrónicas para capturar datos. – dz1984

+0

Esa es una idea horrible. La IU del navegador se bloqueará mientras se ejecutan las solicitudes sincrónicas. –

Respuesta

7

Supongo que los scripts están manipulando los elementos DOM que está agregando a través de AJAX.

jQuery tiene una propiedad isReady que se establece una vez que el evento ready se ha activado en la página.

Cualquier llamada posterior a jQuery.ready(...) primero comprobará esta bandera isReady. Si el indicador se establece en verdadero, llamará al controlador de inmediato. Puedes ver por qué esto causaría problemas en tu código.

Una opción sería cargar la respuesta en un fragmento jQuery y analizar todas las etiquetas <script /> para su posterior ejecución.

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

¡Esto es genial, gracias! – Neo

+0

esto no funciona para mí. El problema parece ser que .find() no puede encontrar los scripts ... – ekkis

1

@Dan tiene la respuesta. Al cargar scripts mediante ajax, el documento isReady es verdadero. Esto significa que si esta es la etiqueta de script que es solicitada por su petición 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> 

En lugar de análisis utilizan JSON. Una propiedad tendrá HTML. Otra propiedad tendrá los scripts.

A continuación, puede hacer esto:

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

también si se carga con la función de secuencias de comandos listos rodea codificar creará un cierre. este cierre durará la vida de la página. Se crearán fugas de memoria cada vez que solicite esa secuencia de comandos sin actualizar su página

Cuestiones relacionadas