views:

3155

answers:

2

I'm creating an HTML editor, similar to this one I'm typing in right now with the output below. I'm using an iframe and dumping the $htmlTextBox.val() into the body of the iframe.

I'm trying to create a stylesheet inside the iframe so that it looks as good as it works.

Thanks in advance!

$htmlTextBox.keyup(function(){
    SetPreview();
});   

function SetPreview()
{
    var doc = $preview[0].contentWindow.document;
    var $body = $("body", doc);

    $body.html($htmlTextBox.val());
}
+2  A: 

Whilst you can interact with an iframe's document.styleSheets, the old-school reliable way is either to have the stylesheet there in the first place (by writing an iframe-src to point to an empty document with the desired stylesheet), or put it in place with document.write(). For example:

<body>
    <iframe></iframe>
    <script type="text/javascript">

        var d= frames[0].document;
        d.open();
        d.write(
            '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional //EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;'+
            '<html><head><style type="text/css">'+
            'body { font-size: 200%; }'+
            '<\/style><\/head><body><\/body><\/html>'
        );
        d.close();

        d.body.innerHTML= '<em>Hello</em>';
    </script>
</body>

(This will also set the iframe document to Standards Mode, assuming that's what you want.)

bobince
I went the route with basic page with the stylesheet included in the <head>. $(document).ready(function(){ SetPreview(); }); does not set the iframe body in Chrome, Safari, or FireFox, but it works in IE...
hunter
just some background, I'm setting the Preview on page load and then on each keyup in the TextArea
hunter
jQuery's document.ready only requires the main document to be loaded, it doesn't have to wait for the iframe content to load. So it can be a race condition to see whether the iframe document's <body> loads before ‘ready’, and hence whether document.body is available yet.
bobince
(Which is why the otherwise quite ugly document.write() approach is often used.)
bobince
I will give that a shot. Is there a way to ensure that the iframe is finished loading from the containing document? IE7 worked as expected, which was a shock. That actually makes me think that it should not have worked.
hunter
The plain old ‘document.onload’ event waits for iframes (and images) to be loaded. Because this is usually not what's wanted, jQuery tries to bind on the ‘DOMContentLoaded’ event instead. But IE doesn't support this event, so on that browser jQuery falls back to the slower, later ‘onload’ option.
bobince
(Actually ‘onreadystatechange’, but it's effectively the same thing.)
bobince
writing to the document worked great! I also make it only do the d.write the 1st time and each request after only sets the HTML. Thanks!
hunter
A: 

Pulled this code below from jHtmlArea source. Funny thing is, the feature was there and I didn't realize it. I came across this SO Question when I was trying to figure out how to implement it. :)

This isn't really "jQuery" but it works. I'm guesing something with append isn't working with iframe so they did it old school. Bobince's answer looks good too, and might be more reliable? So far, this seems to work ok.

var e = edit.createElement('link'); 
e.rel = 'stylesheet'; 
e.type = 'text/css'; 
e.href = options.css; 
this.iframe[0].contentWindow.document.getElementsByTagName('head')[0].appendChild(e);

EDIT: I think the reason this works is if it is sameDomain (including creating iframe in js) Otherwise the usual browser security blocks will prevent you from manipulating iframe dom.

See How to apply CSS to iFrame

Jason
where were you last year?
hunter