tags:

views:

115

answers:

5

I'm setting the html of the body element in an iframe to a string str, then I want to access that content on the next line (here just using an alert call to display the content) but the html and append functions haven't completed by the time the alert statement is called.

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

});

And of course neither the html nor the append functions take callbacks.

Could someone tell me how one normally accomplishes waiting for the DOM to be changed before proceeding?

Many thanks.

A: 

you should try $(window).load(function()) rather than document.ready also you could always fire the event after your appends. that way the event(s) will only run once the append has successfully rendered.

the window.load only runs once the dom has loaded and then all content within the dom too.

if that doesnt work for you, then you could always have a setTimeout() run on the document.ready or window.load and put your functions/events in there and it will load after a specific amount of seconds.

you could try:

$(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());
});
Michael Stone
+1  A: 

There's really no direct method for waiting other than setting an arbitrary timeout before you attempt to retrieve the HTML. The code to do so would be:

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

You should try and make the timeout small enough to go unnoticed but large enough to allow for the contents to update, so you could get away with much less than 250ms.

cballou
OK, that worked, thanks :)Seems odd that that's he only way to do it but hey, it works.
Craig
+3  A: 

html and append both call domManip, which is a synchronous method, so alert shouldn't even execute until those calls have completed.

Are you sure that the values you expect are being copied into the locations you expect?

Jeff Sternal
Agreed. @Craig, does the append happen successfully?Also, append() returns jQuery. You can get the html contents without searching a 2nd time.
Brian Pan
Yes, bith the append and html write work successfully, after the alert shows a blank.I didn't realise append returned anything.
Craig
@Craig, are you able to post a public link to your page or a version of the page that reproduces the problem?
Jeff Sternal
@Jeff - IFRAME handling is tricky, I've experienced the same issue before. It's probably worth a completely separate question to resolve exactly why retrieval fails (pertinent to IFRAMEs and the jQuery library itself).
cballou
@cballou - now I'm getting curious! I see there have been some other questions related to jquery and iframes (like http://stackoverflow.com/questions/205087/jquery-ready-in-a-dynamically-inserted-iframe). Now to find some time ...
Jeff Sternal
+1  A: 

You need to wait for the dom load event so that the iframe has time to finish loading:

$(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());
});
jjacka
You may have to actually listen for the iframe's ready event ("#content_rte").contents().ready(fuction(){...});
jjacka
it wouldnt be ready it'd be load ready defines full rendering of dom elements load is both dom elements and content thats what they need
Michael Stone
A: 

You need to use $( document ).ready( function( ){ } ) or $( function( ){ } ) but with that iframe's document element.

To do this, you can put your script into the iframe's HTML

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 );

Or you can try to do it on the newly appended iframe DOM element itself, but from the parent frame. This is different across browsers, but the following example SHOULD work.

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

Tell me if I'm wrong, like I said, haven't tested this.

Dan Beam