A SCORM wrapper is JavaScript library that serves as an abstraction layer between the SCORM API and your course. If you’ve ever used jQuery, you can think of a SCORM wrapper’s relationship to the SCORM API as being very similar to jQuery’s relationship with a web browser’s DOM — the library’s goal is to help you write shorter, more concise JavaScript while helping you avoid some of the more painful parts of the underlying system. (The jQuery motto is “Write less, do more.”)
There are many SCORM wrappers available to you; they are not all created equal, and often handle tasks differently. For the purposes of this SCORM for Developers series, I will use the pipwerks SCORM wrapper, which I created back in 2008. While not perfect, it’s very reliable — it has been used in thousands of courses around the world over the fifteen years — and is open-source.
The ADL SCORM Wrapper
ADL provided a sample SCORM 1.2 wrapper when they released SCORM 1.2 in October 2001. Their wrapper became very popular and has been very widely used. I’m sure you can still find a number of courses using it. ADL’s wrapper was never intended to be THE wrapper — by their own admission, it was created as an example of what was possible. They expected others to extend and improve it. The comments in their wrapper mention “This is just one possible example for implementing the API guidelines for runtime communication between an LMS and executable content components. There are several other possible implementations.”
When I used the ADL wrapper in my courses, I found myself frustrated by writing the same chunks of SCORM code over and over, such as error-checking and exit handling. I figured if I could stick all of these items into a new wrapper, I would save myself a lot of time and typing. It would also allow me to clean up the JavaScript global space by eliminating all of the global variables used in the ADL wrapper.
If you don’t quite understand what all of that means, it’s okay, we’ll touch on these topics as we build our next sample course.
The pipwerks SCORM wrapper
The pipwerks SCORM wrapper was designed to make course development easier, so you can focus more on your course and less on the nit-picky SCORM stuff. The wrapper will help you with a number of tasks:
- Find the SCORM API and initialize the SCORM session
- Keep the global namespace clean
- Keep your code concise (shorter syntax, easier to understand naming conventions, helper functions, automation)
- Check for errors (e.g., was a SCORM call successful, or did the LMS return an error?)
- Keep your course abstracted (easily switch between SCORM 1.2 and SCORM 2004 if needed)
Find the SCORM API and initialize the SCORM session
If you’re working without a wrapper and writing your SCORM code directly, as we did in our example course at the beginning of this SCORM for Developers series, you would need to write quite a chunk of code. For starters, you’d need a function that locates the SCORM API. It can be tricky to find the SCORM API in some LMSs: Is it in the course window? The parent window? A frameset? A popup window? (Believe it or not, sometimes the answer is “all of the above.”)
Then once the API is found, you’d need to make it available to your course, then initialize the SCORM session using API.LMSInitialize. You’d need to verify whether or not the initialization was successful, and in most cases, will want to immediately set the course completion status to “incomplete”, then invoke LMSCommit.
I got tired of re-writing all of that code over and over, so I incorporated it into the pipwerks wrapper’s init routine. Now you can just write:
pipwerks.SCORM.init();
Code language: JavaScript (javascript)
Keep the global namespace clean
Unlike other SCORM wrappers, all of the SCORM code in the pipwerks wrapper, including utility functions, getters/setters, debugging, etc., is contained under one global variable: pipwerks
. This keeps the global namespace clean, which is important for preventing errors due to naming conflicts, and is a generally accepted best practice.
I will typically add a second global variable named scorm
to my courses for convenience; it’s much easier to write scorm.doSomething()
than pipwerks.SCORM.doSomething()
.
var scorm = pipwerks.SCORM; //shorthand
scorm.init();
scorm.set("cmi.core.lesson_status", "completed");
scorm.save();
Code language: JavaScript (javascript)
This means at most I have only added two global variables to the page, which is a nice, clean way of working.
Keep your code concise
You’ve already seen how the pipwerks wrapper can save you some typing, but it is also designed to make your course code more readable. Instead of typing
API.LMSSetValue("cmi.core.lesson_status", "completed");
API.LMSCommit("");
Code language: JavaScript (javascript)
You can just type
scorm.set("cmi.core.lesson_status", "completed");
scorm.save();
Code language: JavaScript (javascript)
As you can see, I use slightly different syntax; I shortened LMSSetValue
to set
, and changed LMSCommit
to save
, without requiring the nonsensical empty quotes required by LMSCommit("")
. I find these terms easier to remember, easier to type, and easier to scan when I’m writing my course code.
Also, don’t forget the pipwerks wrapper has additional automation running under the hood; in the example above, the scorm.set
function first checks to ensure the connection is active, then attempts to set the value. If the connection is not active, or if the call is not successful, the pipwerks wrapper will ping the LMS to get the error code and display the error in your JavaScript console.
Although the examples above look nearly identical, the second example is giving you much more functionality than the first example.
Check for errors
As mentioned in the SCORM API lesson, most SCORM functions return a value indicating whether or not they were successful. These values are booleans, but presented as the strings “true” and “false”. The pipwerks wrapper automatically converts them to authentic booleans, making them much easier to work with.
To illustrate, we can modify the example given above to verify whether the SCORM calls were successful:
var scorm = pipwerks.SCORM;
var wasSetSuccessful = scorm.set("cmi.core.lesson_status", "completed");
var wasSaveSuccessful = scorm.save();
if(wasSetSuccessful && wasSaveSuccessful){
alert("The LMS likes you!");
} else {
alert("The LMS is not pleased.");
}
Code language: JavaScript (javascript)
The wrapper also provides some preventative measures, such as automatically ensuring the SCORM session is still active before trying to get or set data.
When a SCORM API call is not successful, the LMS provides an error message providing more information. Retrieving this error code requires additional SCORM calls: LMSGetLastError
and LMSGetErrorString
. The pipwerks wrapper handles these via debug.getCode
and debug.getInfo
.
var scorm = pipwerks.SCORM;
var wasSetSuccessful = scorm.set("cmi.core.lesson_status", "completed");
var wasSaveSuccessful = scorm.save();
if(wasSetSuccessful && wasSaveSuccessful){
alert("The LMS likes you!");
} else {
var message = scorm.debug.getInfo(scorm.debug.getCode());
alert("The LMS is not pleased. It says " + message);
}
Code language: JavaScript (javascript)
For convenience, all SCORM error messages are automatically displayed in the browser’s JavaScript console — no need to write a bazillion alert()
or console.log()
statements! If you prefer not to display error messages in the JavaScript console, you can easily turn them off with one line of JavaScript:
pipwerks.debug.isActive = false;
Code language: JavaScript (javascript)
Keep your course abstracted
The pipwerks SCORM wrapper has one other nifty feature missing from most wrappers: it supports both SCORM 1.2 and 2004. SCORM 2004 uses slightly different syntax than SCORM 1.2, such as API.Initialize
instead of API.LMSInitialize
and API.Terminate
instead of API.LMSFinish
. The pipwerks wrapper will look to see which version of SCORM is being used by the course, and will select the appropriate syntax.
If you ever decide to convert a course from SCORM 1.2 to 2004 (or vice-versa) you would just need to change the CMI fields in your gets/sets, such as “cmi.learner_name” instead of “cmi.core.student_name”.
Since this SCORM for Developers series is focusing on SCORM 1.2, the ability to jump to SCORM 2004 will not have much impact here, but it’s worth mentioning in case you ever decide to give SCORM 2004 a whirl.