Detecting if iframe doc has loaded

Workarounds and usability notes.

Detecting if iframe doc has loaded

Postby John Robin Dove » Sun Dec 27, 2020 8:44 am

Hi Clifton,
I'm pretty sure this one is a lost cause so don't waste any time on it. I would like to know if and when a web page has been loaded after pgGotoURL. The web page is a document chosen by a teacher it can be literally anything that is loadable in an iframe. For pages that are not loadable I have a plan B as I have already mentioned if you remember.

It would be useful to detect the load because teachers may program tasks to be done in limited time. I have tried this.

Code: Select all
 <function name="myClick" event="click" params="" useTB="true">
  <![CDATA[
   var iframeDoc = keys.winObj.contentDocument || keys.winObj.contentWindow.document;
    if (iframeDoc)
    {
    alert("Yes");
    //alert(iframeDoc.readyState);      //SecurityError: Permission denied to access property "document" on cross-origin object (line number 3)
    }
    else
    {
    alert("No");
    }
 
  ]]>   
  </function>
  </textDisplayBar>

although it would not be a click in the finished version but a user event sent by a timer. I get neither Yes or No but the Security error. As I said I think there is no way round this except to advise teachers not to create tasks to be done in linited time when using a web page. However I thought I would get your opinion before continuing.

John
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: Detecting if iframe doc has loaded

Postby Clifton » Sun Dec 27, 2020 10:01 am

This is pretty difficult, if not impossible to get working.
pgExecuteRemote() will use POST MESSAGE to send to cross-domain windows and this will not trigger a security warning. However, while the window will receive the message, it won't respond back unless code exists in the cross-domain page to handle it. Since you are probably using various web resources for teaching, then getting any response from another domain's page is virtually impossible.

If you can use AutoIT with your application, then AutoIT can bridge the gaps and get basic information about cross-domain windows. The problem here is that AutoIT is a Windows-based executable and the user would have to run the AutoIT process in the background so it can access web pages.

Some users have recommended using a broad timer to assume the remote pages have loaded, but obviously that is an inexact science.

If you come with something, please post it here so we can all benefit.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Detecting if iframe doc has loaded

Postby John Robin Dove » Sun Dec 27, 2020 10:26 am

OK thanks. That confirms what I thought. I had thought about using the inexact timer option. I guess I'll have to settle for that. It's a bit frustrating because there is no problem on the VS Windows version. You just get a document loaded message wherever you go because the VS webBrowser object is just a version of IE.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: Detecting if iframe doc has loaded

Postby Clifton » Sun Dec 27, 2020 7:21 pm

It only works in the VS version because you are actually running the application from the client computer. In this case it knows nothing about cross domain issues. A similar thing could have been accomplished with AutoIt too. But of course, all of these other options would not work in other platforms—which are becoming more and more popular nowadays.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Detecting if iframe doc has loaded

Postby John Robin Dove » Tue Dec 29, 2020 9:40 am

I think I may have a solution. The security error is not triggered if the document is not cross-domain. So when the containing page is loaded I use pgGotoURL to go to a 'placeholder' document on the server. Before navigating to an off-domain document in the same iframe, I start a 100 ms timer to check the availability of the contentDocument like this
<doc>
<function name="myUser" event="user" params="evt,value" useTB="true">
<![CDATA[
try
{
var iframeDoc = keys.winObj.contentDocument || keys.winObj.contentWindow.document;
}
catch(err)
{
tbfunction_pgTimer("", "", "doc", true); //stop the timer (and maybe add another delay for good measure)
//start the educational tasks to be done for this document (which may have to be done in limited time)
}
]]>
</function>
</doc>

As soon as the off-domain document is loaded (or is starting to load?) the error appears and used to signal the change of contentDocument. Obviously it's not very accurate but it seems to work.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: Detecting if iframe doc has loaded

Postby Clifton » Tue Dec 29, 2020 10:31 am

Thank you for posting this possible solution.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Detecting if iframe doc has loaded

Postby John Robin Dove » Thu Jan 07, 2021 7:00 am

Conclusion

Actually this system is slightly more complicated than the post above suggests. In order to make it work I need to first load the 'placeholder' document which is on my server and then load the document chosen for exploitation by the teacher which is on a different server i.e. cross- domain. However, just loading the two documents one after the other, using pgGotoURL, produces an error because the first document is not properly loaded before the second one arrives. To avoid this I use a global variable sharedActions.docLoaded, set it to false and start a 100 ms timer in an object called docTimer1

<docTimer1>
<function name="myUser" event="user" params="evt,value" useTB="true">
<![CDATA[
if (sharedActions.docLoaded == true)
{
sharedActions.docLoaded = false;
tbfunction_pgTimer("", "", "docTimer1", true); //stop the timer
sharedActions.showWebPage(sharedActions.holdAddress, true); //loads second document
}
]]>
</function>
</docTimer1>


and put a script in the 'placeholder' document like this:

window.onload = relay();

function relay() {
top.tbfunction_pgTBObjSet("keys","forwardViaMain", ["sharedActions","setDocLoaded"]);
};


As soon as the entire window has loaded it calls this function:

<function name="setDocLoaded" event="" params="">
<![CDATA[
sharedActions.docLoaded = true;
]]>
</function>
which causes docTimer1 to load the second document and start docTimer2
docTimer2 uses the method described in the previous post to detect the loading of the second document like this:

<docTimer2>
<function name="myUser" event="user" params="evt,value" useTB="true">
<![CDATA[
try
{
var iframeDoc = keys.winObj.contentDocument || keys.winObj.contentWindow.document;
}
catch(err)
{
tbfunction_pgTimer("", "", "docTimer2", true);
var fct = function()
{
if (keys.restart == true)
{
sharedActions.playAudio();
}
tbfunction_pgTBObjSet("pleaseWait", "visible", false);
sharedActions.doAction1(); //continues the educational exploitation of the document programmed by the teacher.
}
setTimeout(fct, 1000);
}
]]>
</function>
</docTimer2>
It is complicated but so far so good. It seems to do the job. :)
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 3 guests

cron