unable to get importNode working

Y

yawnmoth

I wrote the following in an attempt ot better understand importNode:

<script>
f1=document.createElement("iframe");
f1.src=unescape("http://www.domain.tld/test.txt");
f2=document.importNode(f1,true);
document.innerHTML=f2.innerHTML;
</script>

text.txt's contents are as follows:
<script>
alert("hello, world!");
</script>

I'm expecting a javascript popup saying "hello, world" to appear but
instead, I'm getting nothing.

I'm using FireFox 1.5, if that makes a different.

Any ideas as to what's wrong?
 
J

Jeremy

yawnmoth said:
I wrote the following in an attempt ot better understand importNode:

<script>
f1=document.createElement("iframe");
f1.src=unescape("http://www.domain.tld/test.txt");
f2=document.importNode(f1,true);
document.innerHTML=f2.innerHTML;
</script>

text.txt's contents are as follows:
<script>
alert("hello, world!");
</script>

I'm expecting a javascript popup saying "hello, world" to appear but
instead, I'm getting nothing.

I'm using FireFox 1.5, if that makes a different.

Any ideas as to what's wrong?

First of all, you are probably mis-using the iframe. There is no way to
reliably get the contents of that iframe if the page containing this
script is not in the same domain as test.txt. Any secure user-agent
will disallow this.

Now then, assuming test.txt IS on the same server, there are a couple
things you can do. First of all, importNode will only import a DOM node
- this means that the document containing the node you want to import
must be either an XML or HTML document. I doubt that test.txt is being
served as text/xml or text/html - therefore, this won't work.

Why don't you clarify what you want to do? If all you want is to add a
<script> element dynamically after the page has loaded, why don't you
just place the script you want to add in standalone .js file and use
document.createElement to make a script element that refers to this file?

Example:
test.js contains ONLY this:

alert("Hello, world!");

(note the lack of surrounding <script> tags)

and your main document contains this:

<script type="text/javascript">
var myScript = document.createElement("script");
myScript.src = "http://www.domain.tld/test.js";
document.body.appendChild(myScript);
</script>


If you actually want to import a VALID document contained in an iframe:

// the 'true' makes it import child nodes as well
var importedNode = document.importNode(myIFrame.contentDocument, true);

document.body.appendChild(importedNode); //or do something else



Jeremy
 
Y

yawnmoth

Jeremy said:
<snip>
First of all, you are probably mis-using the iframe. There is no way to
reliably get the contents of that iframe if the page containing this
script is not in the same domain as test.txt. Any secure user-agent
will disallow this.
You mean browser? I don't see why the User-Agent part of the http
request would have any influence over this..
Why don't you clarify what you want to do? If all you want is to add a
<script> element dynamically after the page has loaded, why don't you
just place the script you want to add in standalone .js file and use
document.createElement to make a script element that refers to this file?
I'm just trying to get a better understanding of what importNode
does...

Anyway, here's another example that doesn't seem to do what I'd expect
(they're both hosted on 127.0.0.1):

test.htm:
<body id="container">
<iframe src="http://127.0.0.1/test.htm"></iframe>
</body>

<script>
var iframe = document.getElementsByTagName("iframe")[0];
var oldNode = iframe.contentDocument.getElementById("myNode");
var newNode = document.importNode(oldNode,true);
document.getElementById("container").appendChild(newNode);
</script>

test2.htm:
<body id="myNode">
hello, world!
</body>

I'd expect "hello, world" to appear twice on the page - once in the
iframe and once outside of it. Yet it only appears once...
 
J

Jeremy

yawnmoth said:
You mean browser? I don't see why the User-Agent part of the http
request would have any influence over this..

User-agent is a generic term for software that accesses documents on the
web. This includes browsers, and that's what I was referring to.
I'm just trying to get a better understanding of what importNode
does...

When the user-agent loads a document, it checks the document's content
type. If that content type is HTML or XML, the user agent *should*
parse it and create a DOM tree consisting of a node hierarchy.
importNode takes a node from a different document's DOM tree and makes
it available to the current document.

See the W3 DOM specification for more info:
Anyway, here's another example that doesn't seem to do what I'd expect
(they're both hosted on 127.0.0.1):

test.htm:
<body id="container">
<iframe src="http://127.0.0.1/test.htm"></iframe>
</body>

<script>
var iframe = document.getElementsByTagName("iframe")[0];
var oldNode = iframe.contentDocument.getElementById("myNode");
var newNode = document.importNode(oldNode,true);
document.getElementById("container").appendChild(newNode);
</script>

There are a lot of problems with this example. First of all, neither of
your documents are valid HTML, and I would not expect anything to work
properly if the documents in question are not valid. Second, even if
the documents were successfully parsed, you would be trying to append a
<body> element into a <body> element. Third, even if the script in
test.htm gets executed (which it shouldn't, since it's outside the
<body> and non-existent <head>), there is no guarantee that the contents
of the iframe have been loaded.

And fourth, I'm not sure if this is a typo or not, but test.htm's iframe
is pointing to test.htm rather than test2.htm.
test2.htm:
<body id="myNode">
hello, world!
</body>

I'd expect "hello, world" to appear twice on the page - once in the
iframe and once outside of it. Yet it only appears once...

Try this.

test.htm:
<html>
<head>
<title>My DOM Test</title>
</head>
<body>
<iframe id="myIFrame" src="test1.htm"></iframe>
<script type="text/javascript">
function loadMyNode()
{
var iframeDoc = (iframe.contentWindow || iframe.contentDocument);
if(iframeDoc.document)
iframeDoc = iframeDoc.document;
if(!iframeDoc)
return false;

var myNode = document.importNode(iframeDoc.getElementById("myNode"),
true);
if(myNode)
document.body.appendChild(myNode);
else return false;
}

var iframe = document.getElementById("myIFrame");

try
{
if(!loadMyNode())
iframe.onload = loadMyNode;
}
catch(e)
{
iframe.onload = loadMyNode;
}

</script>
</body>
</html>

test1.htm:
<html>
<head>
<title>External Document</title>
</head>
<body>
<p id="myNode">Hello, world!</p>
</body>
</html>


Works for me.

Jeremy
 
J

Jeremy

Now that I think of it, perhaps some explanation is in order:
var iframeDoc = (iframe.contentWindow ||
iframe.contentDocument);
if(iframeDoc.document)
iframeDoc = iframeDoc.document;
if(!iframeDoc)
return false;

That last bit of code gets the DOM document that's contained in the
iframe. Because of the different ways that different user-agents expose
this functionality, you have to try a few different things to see which
works. In my previous example I only used contentDocument - because
that's what firefox uses. But you really ought to go cross-browser.
var myNode =
document.importNode(iframeDoc.getElementById("myNode"), true);
if(myNode)
document.body.appendChild(myNode);
else return false;

That part actually does the importing of the node.
var iframe = document.getElementById("myIFrame");

This just makes the iframe available to the script in a global scope.
Not the best way, but good enough for this example.
try
{
if(!loadMyNode())
iframe.onload = loadMyNode;
}
catch(e)
{
iframe.onload = loadMyNode;
}

That try/catch block should keep things from going awry if the iframe
hasn't yet loaded its document when the script gets executed. If it's
unable to get the node, it will try again when the iframe finishes loading.


Hope that helps you,
Jeremy
 
M

Martin Honnen

yawnmoth said:
I wrote the following in an attempt ot better understand importNode:

<script>
f1=document.createElement("iframe");

So f1 is now an iframe element in the current document.

f2=document.importNode(f1,true);

Why would you want to import f1 into the document it already belongs to?

Here is a simple example that uses importNode where it is supported to
import a p element from one frame document into the document containing
the frame:
<http://home.arcor.de/martin.honnen/javascript/2006/08/test2006082301.html>

Opera 9 also supports the W3C DOM Level 3 adoptNode method but Mozilla
so far not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top