2010-01-08 7 views
8

Je mets le html de l'élément body dans un iframe à une chaîne str, puis je veux accéder à ce contenu sur la ligne suivante (ici en utilisant simplement un appel d'alerte pour afficher le contenu) mais les fonctions html et append n'est pas terminée au moment où la déclaration d'alerte est appelée.Comment faire pour que votre code attende les fonctions html() et append() pour terminer?

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

Et bien sûr, ni les fonctions html ni les fonctions append ne font appel à des rappels.

Quelqu'un pourrait-il me dire comment on fait normalement attendre que le DOM soit changé avant de continuer?

+0

Est-ce appelé depuis votre fonction $ (document) .ready()? –

Répondre

-7

Il n'y a vraiment pas de méthode directe d'attente autre que la fixation d'un délai arbitraire avant de tenter de récupérer le code HTML. Le code pour le faire serait:

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

Vous devriez essayer de faire le délai d'attente assez petit pour passer inaperçu mais assez grand pour permettre le contenu de mettre à jour, de sorte que vous pourriez sortir avec beaucoup moins de 250ms.

+3

Mauvaise réponse, vous ne saurez jamais quelle valeur choisir ici. Cela fonctionnera pour 99% de vos clients et échouera pour ce 1% qui apporte réellement la plupart de l'argent ... –

+3

Oui, réponse terrible, malgré cela peut fonctionner dans la plupart des cas. Qu'en est-il des conditions de course? (http://en.wikipedia.org/wiki/Race_condition) –

+0

Considérez https://api.jquery.com/load-event/ – talabes

0

vous devriez essayer $ (window) .load (function()) plutôt que document.ready aussi vous pouvez toujours déclencher l'événement après vos ajouts. De cette façon, l'événement (s) ne fonctionnera qu'une fois que l'append a été rendu avec succès. Le fichier window.load ne s'exécute qu'une fois que le dom a été chargé, puis tout le contenu de la dom. Si cela ne fonctionne pas pour vous, vous pouvez toujours avoir un setTimeout() exécuté sur document.ready ou window.load et y placer vos fonctions/événements et il se chargera après un certain nombre de secondes.

vous pouvez essayer:

$(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 et append à la fois appel domManip, qui est une méthode synchrone, donc alert ne doit pas exécuter même jusqu'à ce que ces appels ont terminé.

Êtes-vous sûr que les valeurs que vous attendez sont copiées dans les emplacements prévus?

+0

D'accord. @Craig, est-ce que l'append arrive avec succès? En outre, append() renvoie jQuery. Vous pouvez obtenir le contenu html sans chercher une deuxième fois. –

+0

Oui, avec l'ajout et l'écriture html fonctionnent correctement, après l'alerte affiche un blanc. Je ne me suis pas rendu compte ajourné quoi que ce soit. – Craig

+0

@Craig, êtes-vous en mesure d'afficher un lien public vers votre page ou une version de la page qui reproduit le problème? –

1

Vous devez attendre l'événement de charge de dom afin que le iframe a le temps pour terminer le chargement:

$(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

Vous devrez peut-être écouter l'événement ready de l'iframe ("#content_rte"). Contents(). Ready (fuction() {...}); – jjacka

+0

il ne serait pas prêt, il serait prêt à charger définit le rendu complet des éléments dom charge à la fois les éléments dom et le contenu c'est ce dont ils ont besoin –

0

Vous devez utiliser $(document).ready(function(){ }) ou $(function(){ }) mais avec l'élément de document qui iframe.

Pour ce faire, vous pouvez mettre votre script en vous pouvez essayer le HTML 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); 

Ou de le faire sur l'élément iframe DOM nouvellement joint lui-même, mais du cadre parent. Ceci est différent d'un navigateur à l'autre, mais l'exemple suivant DEVRAIT fonctionner. Dites-moi si je me trompe, comme je l'ai dit, je n'ai pas testé cela.

11

Si vous utilisez jQuery, vous pouvez compter sur .closest() pour déterminer si l'élément que vous venez de créer possède une balise parent body, et si c'est le cas, cela signifie qu'il a été ajouté au DOM.Vous pouvez écrire une fonction telle que ce qui suit pour vous permettre de faire réellement quelque chose quand votre élément est prêt:

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

J'aime ça! Vous devez ajouter "' if (! $ (Selector) .length) return; '" au début pour éviter les boucles infinies lorsque le sélecteur ne correspond à aucun élément. – flu

0

J'ai suivi réponse, mais j'utilisé le lengh du grancalavera parce que mon sélecteur existe déjà dans le corps. Est-ce que:

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); 
    } 
} 
Questions connexes