Closing a SCORM window with JavaScript

Closing a SCORM window with JavaScript

Ian Wright -
回帖数:12

It used to be that a SCORM activity could be closed with some variation of window.close() in the activity's HTML/JavaScript host page, but this no longer works for me in the Moodle 2 SCORM environment.  This appears to be because the SCORM plug-in generates an HTML/JavaScript page based on YUI, and the html content of the SCO is no longer like the html included in the content package file.

In any event, tightening browser security looks like breaking the windows.close() method as "there are certain security restrictions for using the close() method. The close method closes only windows opened by JavaScript using the open method." (from Javascript-Coder.com).  This isn't yet entirely consistent across browsers, it seems, as I observe IE9 will close a window after asking for confirmation, but neither Firefox 6 or Google Chrome will respond to window.close() unless it is in a pop-up that was opened by JavaScript.

After some experimentation based on the DOM of the html/JavaScript generated by the SCORM plug-in, I have found that the following will close a Moodle 2 SCORM pop-up when called by the SCO:

<script Xlanguage="JavaScript" type="text/JavaScript">
  function closeTheWindow() {
    var e = new Object();
    e.preventDefault = false;
    content.close_window(e);
} 
  </script>
However (a) this is a kluge with no guarantee of future-proofness, and (b) it contradicts the principle of transportability between SCORM LMSs.

This post is made in the hope that you have a better solution for closing a Moodle 2 SCORM activity from within the activity's HTML/JavaScript host, that you're willing to share.

 

回复Ian Wright

Re: Closing a SCORM window with JavaScript

Ian Wright -

Spoke too soon on this:

The test SCORM page closes as described above with Firefox 6, but content.close_window() fails (silently) in both IE9 and Google Chrome.

But on the other hand, a full SCORM lesson launches correctly in Google Chrome, but fails to get past a blank launch window in both Firefox 6 and IE9.  The exit from the Chrome lesson fails as is consistent with the test page; of course, as launch fails in both Firefox and IE there's no observation for exiting from these browsers.

Updates to this post to follow...

回复Ian Wright

Re: Closing a SCORM window with JavaScript

Amy Groshek -
Holy Gordian knot. Travel safely into that Dark Land, Brave Son. We await your Missives. ;)
回复Amy Groshek

Re: Closing a SCORM window with JavaScript

Ian Wright -

Thank you, Amy.  Failing an Alexandrian solution, I fear I shall bide my time until Cap'n Dan can rescue me, for 'tis his knot to that ties me.

But do tell... how would you have a SWF close it's parent SCORM player window?  Have I got the wrong end of this Gordian knot? 眨眼

回复Amy Groshek

Re: Closing a SCORM window with JavaScript

Ian Wright -

Hi Amy,

I think we are talking about the same thing.  The security issue was as mentioned in your dontnetslackers reference (mine was from JavaScript-Coders.com).

What I have is a Flash course with each module having an Exit button to call a JavaScript function in the launch page.  The JS function has for a long time called window.close(), preceded by window.opener = self to get around the browser confirmation alert.  I imaging this is a pretty common approach (which continues to work well in another LMS that I use).

I have just updated from Moodle 2.1.1 to 2.1.1+ (Build: 20110131) to check out any changes and also the window.open('','_self',''); variation in your second reference.  There's no change to the original problem.

To enlarge on the original problem, I noticed that the source code of the SCORM pop-up launch page was full of YUI functionality, nothing like the packaged HTML launch page, and beyond me as to reverse-engineering it to figure out what was going on. 

I created a simple HTML page with an INPUT button to call the close_window(e) function which I noticed in FireFox 6 with Firebug, and by fudging the event parameter was able to close the window that way (in FireFox).  So far, so good - until the further observations that led to my second post.

To expand on the second post:

  1. Google Chrome will successfully launch a production SCORM module.  All initial LMSGetValue() functionality works, pre-exit LMSSetValue() functionality works, the JS exit function in the launch page (in its YUI form) is called, but the window does not close.
  2. FireFox 6 opens the SCORM plug-in window, successfully makes all 35 LMSGetValue() calls, and then hangs before displaying the SWF. The Firebug Object inspector (Firebug) shows:
    <object id="scorm_object" type="text/html" data="http://localhost/mod/scorm/loadSCO.php?a=9&amp;scoid=628&amp;currentorg=course1&amp;attempt=3" style="width: 961px; height: 590px;" name="scorm_object"></object>
  3. IE 9 opens the SCORM plug-in window, making just 2 LMSGetValue() calls (successfully) before hanging.   Right clicking the window reports "Movie not loaded... / Show redraw regions / Debugger /  About Adobe Flash Player 10.2.153.1 ...: and the load activity status shows continuous loading. (The grey text is greyed out in the dialog.)

Thus these results are consistent with your result for Chrome (but not FireFox): i.e. setting a SCORM to open in a new window, then running window.close() - if your window.close() call is triggered from within the page, and not an embedded object. That is what I was referring to.

Unless there is something really weird with my Vista/IIS7 local test site that only affects Moodle 2.1.1 (as everything else is OK), I have to be suspicious of the YUI code generated for the launch of the SCO.  For the record, the SCORM plug-in is version 2011021403.

Also for the record, the source code that launches the SCO is attached.  There is no sign of the JavaScript function to close the window in here, so presumably it lies elsewhere as a reference (as the function is indeed called - it just doesn't close the window).

And if it is that this is a functional problem, perhaps the failure of the SWF SCO to open when launched with IE9 or FireFox 6 has the same root cause as that which prevents the Google instance from closing?  Or can there be a problem with this content package that somehow IE9 and FireFox pick up, but somehow doesn't bother Google Chrome until it comes time to close the window?  惊讶 And does that mean my test SCO package is defective in some way that IE9 and Chrome object to, but FireFox find OK? 思考

 

回复Ian Wright

Re: Closing a SCORM window with JavaScript

Amy Groshek -
Hi Ian,

Can I see your samples?

Not clear on what you mean by "packaged html launch page"... there is player.php, and it loads loadSCO.php. Which one are you referring to?

M2 has been placing loadSCO in an object tag for a long time now... though it does maybe have an impact on the scope of window.close(), as opposed to an iframe, it's not a new change.

Not seeing how Flash hanging, unless you can correlate this with some sort of JS error occurring in the page, is related. Might be a separate issue? Also, there is a debugger player for v10.3. Might be related to the hang?

Regards,
A
回复Amy Groshek

Re: Closing a SCORM window with JavaScript

Ian Wright -

Hi Amy,

Two samples as per separate message.

By "packaged html launch page" I mean the HTML page that has the Flash movie content embedded as an object, plus API interface calls and miscellaneous JS support functions.  Call this page in a browser, and the SCO should launch.  For the close-function exploration/test package this page simply contained a JS window.close() (and other variants), but it was set up as a normal SCORM lesson.

The difference is apparent when looking at the delivered SCO browser page - it's nothing like the original HTML, and contains a lot of YUI functionality.  I'm a bit bemused by the need for this - I do use another LMS that simply delivers the HTML page to the browser as written (with a hidden frame containing a JS API object), and it works fine.  If it ain't broke, why fix it?

By putting a JS alert in the close function I could see that the close function is actually being called (so the scope is OK), but the window.close() (and variants) call does nothing, even though its in the same function as the alert.  Suggesting a broken parent/scope relationship in YUI?

I don't see that the Flash movie is hanging because of a problem in the movie.  I normally use the debug version for development in IE, but have upgraded from v10.2 to v10.3 in both debug and normal versions, and the IE9 result remains the same as described regardless.  Where the IE attempt stops is at the point where an API call is made for cmi.core._children - this is where the SCORM activity trace stops.  This works fine in both Firefox and Chrome (although the movie fails to display in Firefox).  I don't see a JS error notification on the IE page, and the Flash player debug version sees nothing to complain about.

I guess what I find most troubling is that three different browsers give three different results.  Whatever the state of IMS conformance of the content packages might be (and I'm looking into this), that simply should not happen.


Regards

Ian

回复Ian Wright

Re: Closing a SCORM window with JavaScript

Amy Groshek -

Hi Ian,

I just looked at your sample SCOcloseTest_10.zip. I think there is a syntax there there. You have no ending semicolon on

var answer = confirm("Confirm exit?")


Once I add a semicolon there, I get a runtime error:
33Uncaught ReferenceError: content is not defined
closeTheWindowSCOcloseTest.html:33
(anonymous function)SCOcloseTest.html:10
onclick

When I use a plain old window.close(); call wrapped in a function, within your sample, it works just fine, in both FF and Chrome...

The function which opens the SCORM content's root page is loaded to player.php, and is available there, and not in the new opened window. If you want to look at this function, it's in /mod/scorm/player.js, and it's the only function there. YUI is not being used in any way in this function. The only way you would have YUI collisions is if you were using $ in your own JS some way that interfered with the YUI namespace. But obv since YUI is not used in scorm_openpopup() it would not be connected to what we're disucssing here.


function scorm_openpopup(url,name,options,width,height) {
fullurl = M.cfg.wwwroot + '/mod/scorm/' + url;
windowobj = window.open(fullurl,name,options);
if (!windowobj) {
return;
}
if ((width==100) && (height==100)) {
// Fullscreen
windowobj.moveTo(0,0);
}
if (width<=100) {<%1%0%> width = Math.round(screen.availWidth * width / 100);
}
if (height<=100) {<%1%0%> height = Math.round(screen.availHeight * height / 100);
}
windowobj.resizeTo(width,height);
windowobj.focus();
return windowobj;
}


Attaching your test page with my modifications. doClose() seems to work just fine on Moodle 2.1.1+ (Build: 20110803).

Regards,
Amy
回复Amy Groshek

Re: Closing a SCORM window with JavaScript

Ian Wright -

Hi Amy,

First of all, thank you for taking time to explore this, and test and propose a fix.

Unhappily, there appears to be even more twists in this than a Gordian knot, and I fear this is getting to be a very dark place.

I have taken your script (as attached to your post), and the following are the results I get – which are different from yours.  First, I’ll just repeat my environment details:

  • Moodle 2.1.1+ (Build 20110907 (2011070101.08)) updated today
  • Two IIS7 servers: local on Vista Business SP2, remote on a dedicated Windows 2008 x64 Server Web Edition
  • MySQL 5.5.14 and PHP 5.3.6
  • Browsers: IE9, Firefox 6.0.1 with Firebug, Google Chrome with Firebug Lite

Issue 1: Different results: I repackaged the script attached to your post, and got identical results on both local and remote servers:

  •  IE9: Neither doClose() (your function) nor content.close_window(e) (my “solution”) close the SCORM player window.
  •  Google Chrome: Neither doClose() nor content.close_window(e) close the SCORM player window.
  • Firefox: doClose() fails to close the SCORM player window, but content.close_window(e) does, just as described in my initial post.

Question: why does doClose() work in your environment, but not in mine?  Are you on Linux?  Do you use a Mac?

Question: why does Firefox close on a content.close_window(e) call, but IE9 and Chrome won't?

Issue 2: The “missing” semicolon: ECMA-262 (the specification for JavaScript) specifies “Automatic Semicolon Insertion” (ASI) which in effect means that semicolons are optional (except in a small number of extreme examples which may result in unexpected results).  True, there is debate, and sometimes strong opinion, about whether programmers ”must” terminate statements with semicolons, but the fact is, javaScript interpreters are required to insert semicolons where appropriate, and I cannot image that the three browsers I use have got this wrong.

Question: Why does the addition of a semicolon as you describe throw an error for you?

Comment: Given ASI, the omission of a semicolon at that point should not be a problem, as indeed has been the case for several years using this particular bit of HTML/JS code in another LMS.  As a corollary, why should its addition throw the error in your environment? 

Also, after the preceding tests (Issue 1) I added a semicolon to the script you provided, and no error was observed in any of the three browsers (this was only checked on the local server).

Question: Why do you get an error, and I don't?

Issue 3: YUI: It may well be the case that YUI is not being used in /mod/scorm/player.js, but is certainly is before the actual SCO is called – even for this naively simple test SCO. After the player window is called by http://localhost/mod/scorm/player.php?scoid=636&cm=23&currentorg=course1&display=popup, there are 31 requests recorded by Firebug before the SCO itself is called; of these, 20 requests are for JS, and of those 14 are to yui_combo functions. The list of these requests is attached for info (unfortunately the full names are truncated in the Firebug listing).

Question: Why do we need all this stuff?  Why not just add a hidden frame containing the API into the source HTML, and send the page to the browser?

Issue 4: More YUI: The entire HTML script in SCOcloseTest.html is 828 characters (with comments removed).  The actual browser window source code can then be inspected by right-clicking the page and selecting source code from the context menu. When delivered to the SCORM player window, the original 828 characters of source code is blown out to 21,621 characters, full of unintelligible (for me) YUI calls.  That's 2,611% inflation!

Question:  What on earth is going on here?

Amy, I’ll send you access details for my remote server so you can check this out, if you’d be so kind.  I really would be interested in your take (and of course anyone else's).

回复Ian Wright

Re: Closing a SCORM window with JavaScript

Jim Cook -

Ian & Amy,

I have read each of your posts on this topic with great interest.  I thought Ian had the answer until his last post 伤心  To your knowledge is there any way to ensure that a SCORM window closes when the module finishes playing and make it bowser independent?  We use Captivate (just tried 5.5) and (close to) the latest build of Moodle 2.

This was working great for us a few months ago and then SOMETHING changed. 

Jim 

回复Jim Cook

Re: Closing a SCORM window with JavaScript

Michael McCarthy -

I have had the same issue, and am saddened to see no solution yet discovered. Up until just recently, my window.close() method had worked just fine. Then we updated Moodle, and it no longer works.