My department has been using a custom-built SCORM Learning Module template for developing our corporate training. The template permits a variety of page widths and flexible height throughout, and has features such as branching,  dynamic pdf generation,  in-module text search, and aggregation of all sorts of interactive quizzes: Captivate,  Javascript, Questionmark and Qualtrics quizzes. The template handles all the SCORM functions and keeps track of what the learner has accomplished so far.

The structure of the template is a fairly traditional setup: A hidden, persistent frame is used to store state data which can be accessed by all pages as the user navigates through the content.


But due to device and browser changes, this design has begun to show its age. The most pressing problem is the template’s use of  iFrames to display quizzes that are hosted in remote domains. iFrames are necessary for cross-domain communication of score and status data that does not disrupt the persistent frame.

html template hidden frame remote quiz

iFrames are the source of  two major problems for our users. The iFrame’s scrollbars often fail to show up on modern browsers (no matter how long the source content, and no matter what CSS fixes we put in place). Also, iFrames do not resize to adapt to different screen sizes and varying content sizes. It is possible to fix this, but the template structure needed to be redesigned for other reasons as well. The revised learning module template structure does not include iFrames, persistent data frames nor indeed any frameset at all. Data is stored in namespaced browser local storage, which can be accessed by all the pages in a learning module. Most of the content is simply loaded into a single page via ajax, but some discrete pages are still required, principally for remote-hosted content.



Remote-domain quizzes are accessed by redirecting specially designed intermediate pages to the remote quiz and back. The quizzes are designed with a final link that sends an encrypted score and status back to the intermediate page, which relays it on to the main module content container page. All pages including quizzes are now completely responsive and there are  no scrollbar issues.

new module setup.jpg

There was an interesting challenge with this design, however: retaining the location of the SCORM API across all pages.

When a SCORM module first launches, it executes a function to find and store the location of the SCORM API Adaptor for the rest of the session.

g_objAPI = FindAPI(window.opener)

Once it does, that pointer to the API is is used whenever any SCORM functions are called.

function SCOGetValue(nam) {
     return ((APIOK())?g_objAPI.LMSGetValue(nam.toString()):"")

When I removed the persistent data frame and frameset, I removed that persistent pointer. Local Storage could be used to store that, but it turned out to be just as easy to call the FindAPI function again when one of the discrete pages launches.

For example, putting this after the new page loads will re-enable calls to SCORM functions.

var g_objAPI = FindAPI(window.parent);

It is not necessary to call LMSInitialize again: the SCORM session is still open in the LMS-provided frameset or window tree, even if no module page ever persists.

 If you’d like to try the new version of the template, get it from GitHub: