2010-01-08 4 views
8

Estoy configurando el html del elemento del cuerpo en un iframe en una cadena str, luego quiero acceder a ese contenido en la siguiente línea (aquí solo uso una llamada de alerta para mostrar el contenido) pero las funciones html y append completado en el momento en que se invoca la declaración de alerta.¿Cómo puede hacer para que su código espere a que se completen las funciones html() y append()?

$(function(){ 
.... 
$("#notes-tab span.add_draft").bind("click", function(e){ 
    var str = ''; 
    $(this).parent().siblings(".tab-content").children(".para").each(function(ind) { 
     str += $(this).find('div:first').html(); 
    }); 
    var curr = $("#content_rte").contents().find("body").html(); 
    if (curr == ' ' || curr == '<br>') { 
     $("#content_rte").contents().find("body").html(str); 
    } 
    else { 
     $("#content_rte").contents().find("body").append(str); 
    } 
    alert($("#content_rte").contents().find("body").html()); 
}); 
}); 

Y, por supuesto, ni las funciones html ni las funciones para agregar reciben retrollamadas.

¿Podría alguien decirme cómo uno normalmente logra esperar a que se cambie el DOM antes de continuar?

+0

¿Se llama desde su función $ (documento) .ready()? –

Respuesta

-7

Realmente no hay ningún método directo para esperar que no sea el establecimiento de un tiempo de espera arbitraria antes de intentar recuperar el código HTML. El código para hacerlo sería:

// wait for 250 ms, then try and retrieve contents 
setTimeout(function() { 
    alert($("#content_rte").contents().find("body").html()); 
}, 250); 

Usted debe tratar de hacer que el tiempo de espera lo suficientemente pequeño como para pasar desapercibido, pero lo suficientemente grande como para permitir el contenido para actualizar, por lo que podría salirse con mucho menos de 250 ms.

+3

Mala respuesta, nunca sabrá qué valor elegir aquí. Esto funcionará para el 99% de sus clientes y fallará por ese 1% que realmente está trayendo la mayor parte del efectivo ... –

+3

Sí, respuesta terrible, a pesar de que puede funcionar en la mayoría de los casos. ¿Y las condiciones de carrera? (http://en.wikipedia.org/wiki/Race_condition) –

+0

Considere https://api.jquery.com/load-event/ – talabes

0

debes probar $ (ventana) .load (función()) en vez de document.ready también siempre puedes disparar el evento después de que lo anexes. De esta forma, los eventos solo se ejecutarán una vez que el apéndice se haya procesado correctamente.

window.load solo se ejecuta una vez que el dom ha cargado y luego todo el contenido dentro del dom también.

si eso no funciona para usted, entonces siempre podría tener un setTimeout() ejecutado en el documento. Listo o window.load y poner sus funciones/eventos allí y se cargará después de una cantidad específica de segundos.

usted podría intentar:

$(document).ready(function(){ 
    var curr = $("#content_rte").contents().find("body").html(); 
    if (curr == ' ' || curr == '<br>') { 
     $("#content_rte").contents().find("body").html(str); 
    } 
    else { 
     $("#content_rte").contents().find("body").append(str); 
    } 
}); 
$(window).load(function(){ 
    alert($("#content_rte").contents().find("body").html()); 
}); 
2

html y append tanto domManip llamada, que es un método sincrónico, por lo alert ni siquiera debería ejecutar hasta que esas llamadas han completado.

¿Está seguro de que los valores que espera se copian en las ubicaciones que espera?

+0

De acuerdo. @ Craig, ¿el apéndice se realiza con éxito? Además, append() devuelve jQuery. Puede obtener los contenidos html sin buscar una segunda vez. –

+0

Sí, con la escritura de append y html funciona correctamente, después de que la alerta muestre un espacio en blanco. No me di cuenta de que Anexar devolvió algo. – Craig

+0

@Craig, ¿puede publicar un enlace público a su página o una versión de la página que reproduce el problema? –

1

hay que esperar para el evento de carga dom modo que el iframe tiene tiempo para terminar de carga:

$(document).ready(function(){ 
    var str = '<div>HelloWorld</div>'; 
    var curr = $("#content_rte").contents().find("body").html(); 
    if (curr == ' ' || curr == '<br>') { 
     //$("#content_rte").contents().find("body").html(str); 
     $("#content_rte").contents().find("body").append(str); 
    } 
    else { 
     $("#content_rte").contents().find("body").append(str); 
    } 
    alert($("#content_rte").contents().find("body").html()); 
}); 
+0

Es probable que tenga que escuchar el evento preparado del iframe ("#content_rte"). Contents(). Ready (fuction() {...}); – jjacka

+0

no estaría listo, estaría listo para cargar, define la representación completa de los elementos de dom, la carga es a la vez elementos dom y contenido, eso es lo que necesitan –

0

Es necesario utilizar $(document).ready(function(){ }) o $(function(){ }) pero con elemento de documento de ese marco flotante.

Para ello, se puede poner el script en el HTML de la iframe

theIframeHTMLContent += '<script type="text/javascript" src="jquery.js"></script>' + 
         '<script type="text/javascript">' + 
          '$(function(){ alert("I\'m ready!"); });' + 
         '</script>'; 

$('body').append('<iframe id="cool"></iframe>'); 
$('#cool').html(theIframeHTMLContent); 

o se puede tratar de hacerlo en el elemento iframe DOM recién anexado en sí, sino del marco padre. Esto es diferente en todos los navegadores, pero el siguiente ejemplo DEBERÍA funcionar.

$('body').append('<iframe id="cool"></iframe>') 
var theFrame = $('#cool')[ 0 ]; 
var docEl = theFrame.contentDocument || theFrame.contentWindow || theFrame.document; 
$(docEl).ready(function(){ /* ready stuff */ }); 

Dime si me equivoco, como he dicho, no lo he probado.

11

Si está utilizando jQuery puede confiar en .closest() para averiguar si el elemento que acaba de crear tiene una etiqueta padre body, y si lo hace significa que se ha agregado al DOM.Puede escribir una función como la siguiente para que pueda realmente hacer algo cuando el elemento está listo:

callWhenReady: function (selector, callback, scope) { 
    var self = this; 
    if ($(selector).closest('body').length) { 
     callback.call(scope); 
    } else { 
     setTimeout(function() { 
      self.callWhenReady(selector, callback, scope); 
     }, 1); 
    } 
} 
+0

¡Me gusta esto! Debería agregar "' if (! $ (Selector) .length) return; '" al principio para evitar bucles infinitos cuando el selector no coincide con ningún elemento. – flu

0

que siguieron respuesta del grancalavera 's, pero he usado el lengh porque mi selector ya existe en el cuerpo. .. so:

var finalLength = $(selector).html().length + data.length; 
$(selector).html(data); //or $(selector).append(data); 
//... 
callWhenReady: function (selector, callback, finalLength, scope) { 
    var self = this; 
    if ($(selector).html().length === finalLength) { 
     callback.call(scope); 
    } else { 
     setTimeout(function() { 
      self.callWhenReady(selector, callback, scope); 
     }, 1); 
    } 
} 
Cuestiones relacionadas