Force a stylesheet onto a inframe's contents.

He has: 9 posts

Joined: Dec 2006

Hi, everyone.

I have a JavaScript function to output some XML to an iframe.

function constructMsgBody()
{
var message = msgsfile.getElementsByTagName("message")[msg]
.firstChild.nodeValue;

var writemsg = parent.frames['msgframe'];
writemsg.document.open();
writemsg.document.write(message);
writemsg.document.close();
}
'

This is fine in itself, but how can I get it to force a CSS stylesheet onto the contents of the iframe. I get the element from an XML document which has a CSS stylesheet referenced to it, but it is not applied like this, probably because I haven't expressely specified it. I have tried putting <?xml-stylesheet... at the top of the write out and similar things, but I cannot get it to work. Do I have to write out to a document rather than a iframe directly due to technical limitations of it? Or is there a way to force the iframe to use my stylesheet.

Thanks in advance.

Abhishek Reddy's picture

He has: 3,348 posts

Joined: Jul 2001

Rather than modifying the frame's contents with the [incode]document.write[/incode] function, use the DOM methods -- essentially as you would with an XML file.

Perhaps something like this (untested):

var writemsg = parent.frames['msgframe'];
var writedoc = writemsg.document;
var writebody = writemsg.getElementsByTagName("body")[0];
writebody.appendChild(writedoc.createTextNode(message));
'

Using the DOM functions ensures that the document tree remains sane, and so CSS can be applied by the browser. As you're only modifying the sub-tree of the body node in this script, you can specify the stylesheet to apply in the page's code itself.

However, note that you're only grabbing the nodeValue of the message, and in my example it is only appended as a text node. If you're trying to append a general node from the XML file into the iframe's DOM tree, then you need slightly different code.

Smiling

He has: 9 posts

Joined: Dec 2006

Thanks for your help. I tried that code, but nothing appears in my iframe. Do you think I have to use a general node instead of a text node. What was the method for a general node. [="Courier New"]createNode[/]?

Thanks again.

Here's the code I have:

    var message =   msgsfile.getElementsByTagName("message")[msg]
.firstChild.nodeValue;
    alert(message); //! bring up message in alert dialog !//
    var writemsg = parent.frames['msgframe'];
    var writedoc = writemsg.document;
    var writebody = writemsg.getElementsByTagName("body")[0];
    writebody.appendChild(writedoc.createTextNode(message));
'

If I understand correctly, I am getting the contents of the message tag from my XML document and appending under the body element of the iframe.
Although the message appears fine in my alert, it is not being placed in the iframe.

Abhishek Reddy's picture

He has: 3,348 posts

Joined: Jul 2001

My apologies, the code I provided was untested and contained an error. I referred to [incode]writemsg[/incode] instead of [incode]writedoc[/incode] in one place. Here is the amended, tested (on Firefox 2) version:

var writemsg = parent.frames['msgframe'];

var writedoc = writemsg.document;
var writebody = writedoc.getElementsByTagName("body")[0];
writebody.appendChild(writedoc.createTextNode(message));
'

A text node is what you should use here as [incode]message[/incode] is just a string, not a node itself.

If [incode]message[/incode] was a subtree (fragment or node) taken from the original XML file, then you would simply append it without having to create a new node.

But if you did want to create a new node -- say, to encapsulate even the text node above -- then you would use the [incode]createElement[/incode] method.

Smiling

He has: 9 posts

Joined: Dec 2006

Thanks. That change did indeed add the message text to the iframe. But I have the problem that it continually appends text for each message. How can I clear the frame before each new messages is appended?

Also can I apply a stylesheet by simply including [="Courier New"][/] somewhere in the string to write out?

function constructMsgBody()
{
    // write out message contents to iframe on view dialog
    var message =  msgsfile.getElementsByTagName("message")[msg]
.firstChild.nodeValue;
    var writemsg = parent.frames['msgframe'];
    var writedoc = writemsg.document;
    var writebody = writedoc.getElementsByTagName("body")[0];
    writebody.appendChild(writedoc.createTextNode(message));
}
'

Abhishek Reddy's picture

He has: 3,348 posts

Joined: Jul 2001

Samji;214136 wrote: Thanks. That change did indeed add the message text to the iframe. But I have the problem that it continually appends text for each message. How can I clear the frame before each new messages is appended?

It was just a guide. You'll have to use other DOM methods documented in my link above. Look up [incode]replaceChild[/incode], [incode]removeChild[/incode] and [incode]hasChildNodes[/incode]. Smiling

Samji;214136 wrote: Also can I apply a stylesheet by simply including [="Courier New"][/] somewhere in the string to write out?

That won't work, as the DOM methods modify the document tree, not the page's source text. The easiest way would be to add that [incode]link[/incode] tag to the page's markup manually and leave it there. There's no reason to alter the style information via scripting.

Smiling

He has: 9 posts

Joined: Dec 2006

Thanks.

I have the problem that my stylesheet for my XML document is ignored with either using [="Courier New"]<?xml-stylesheet href="mystylesheet.css" type="text/css"?>[/] or by using an XHTML namespace with [="Courier New"][/].

Why is this? Thanks again.

Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.