frames

48 views
Skip to first unread message

SrinivasNS

unread,
Feb 27, 2013, 10:12:05 PM2/27/13
to js...@googlegroups.com
I am trying to load a page that has two frames and look at the content of the document. I can see that there are two frames. When I try to access the frame, I always get null. Here is the sample code.

var jsdom = require("jsdom");

jsdom.env({
  features : {
    FetchExternalResources   : ['script', 'frame'],
    ProcessExternalResources : ['script', 'frame']
  },
  done: function(errors, window) {
var document = window.document;
setTimeout(function() {
try {
        var x = window.document.getElementsByName('leftFrame');
        var fr = x[0];
        console.log("fr.contentDocument: " + fr.contentDocument);
} catch (e) {}
}, 3000);
}  
});

And the content of the page is 

<HTML><title>Frame Example 01</title>
<FRAMESET COLS="80%,20%"> 
    <FRAME NAME="leftFrame" SRC="leftFrame.html"> 
    <FRAME NAME="rightFrame" SRC="frame00.html"> 
</FRAMESET> 

This page loads fine in regular browser. I tried with and without setTimeout() but it did not work. What I am doing wrong here?


Chad Walker

unread,
Feb 28, 2013, 10:03:07 AM2/28/13
to js...@googlegroups.com
It's actually not null, but the string '[ null ]'. This is because you are casting the document into a string. The HTMLDocument class doesn't have a toString() method, so it falls back ultimately to Node.prototype.toString, which tries to make a string that looks like '[' + <tagName>[#id][.className[.className...]] + ']' The document node has a null tagName property and no id or class names set, so you get: '[' + null + ']'. I ran the code below and got a dump of the left frame document.

'use strict';
var jsdom = require('jsdom');

jsdom.env({
    html: '/Users/chad/Projects/foo/frameExample01.html',
    features: {
        FetchExternalResources   : ['script', 'frame'],
        ProcessExternalResources : ['script', 'frame']
    },
    done: function (errors, window) {
        var doc = window.document;
        var leftFrame = doc.getElementsByName('leftFrame')[0];
        console.log('leftFrame:', leftFrame.contentDocument);
    }
});


-chad


--
You received this message because you are subscribed to the Google Groups "jsdom" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsdom+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

SrinivasNS

unread,
Feb 28, 2013, 2:08:39 PM2/28/13
to js...@googlegroups.com
Chad, 

Thanks for the reply to my newbie question.  I have another question. When I ran your code I could not access the document. 
For example 
        console.log("fr.contentDocument: " , leftFrame.contentWindow.document.documentElement.innerHTML);
throws the exception
       TypeError: Cannot read property 'innerHTML' of null
I see that document's readystate is "loading". But when I use the the setTimeout() with a second or two delay, it works. Is there a way to set so that my callback gets called only when all the frames are loaded?

Srinivas

Chad Walker

unread,
Feb 28, 2013, 3:09:06 PM2/28/13
to js...@googlegroups.com
You need to listen for the DOMContentLoaded event on the frame's contentDocument. I made a gist (so I stop pasting everything in here): https://gist.github.com/chad3814/5059671

Essentially you need to check the .readyState property, and if it's not 'completed' you need to set an event to be fired once it is.

Without the <script> tag in the left frame, document is ready right away.

-chad

SrinivasNS

unread,
Feb 28, 2013, 7:42:43 PM2/28/13
to js...@googlegroups.com
Thanks Chad.
Reply all
Reply to author
Forward
0 new messages