Archive

Archive for the ‘SCORM’ Category

JavaScript preg_match

September 28, 2010 5 comments

In the context of a nasty (wrong) SCORM package, I had to find a method of quickly parsing a time representation like “PT03H23M34S” and transform it into “03:23:34”.

After a few quick searches on how to do user string.replace(), I had to change the method, because apparently replace() doesn’t allow for selection identifiers (\2 and the likes) in the replacement string, or at least I didn’t find how to do it.

So I ended up with this:

if (/[A-Z]{2}\d{2}H\d{2}M\d{2}S/i.test(param)) { param = param.split(/\D+/).join(' ').trim().split(/\S/).join(':');}

It *is* kind of a one-liner. Not very beautiful but it seems to do the trick.

On my way finding the solution, I had the opportunity to play a little with the JavaScript console of Firebug. Nice!


			

Easy SCORM 1.2 creation – Extending the Dokeos export

January 6, 2009 15 comments

Today I had to explain to a customer how to register time and completeness in a SCORM learning path, considering he’s got Flash content and he doesn’t know anything about SCORM.

This is what I answered (with little changes)

The idea is that Dokeos deals with SCORM contents by providing a JavaScript API (a library that can be called from the Flash) to enable SCORM features.

To enable this, there are various steps that need to be taken…
1. Your content should be a SCORM package.
2. Each step of your content should send a LMSInitialize() call to the Dokeos SCORM API when opened.
3. Each step of your content should send a LMSSetValue(‘cmi.core.lesson_status’,’completed’) upon reaching the end of the last slide
4. Each step of your content should send a LMSFinish() call upon closure (or change of page), or could do it directly after the LMSSetValue() call

Now each of these steps require a considerable amount of time to execute. This is why I didn’t enter into the details previously. This is the cost to pay to have a fully-trackable course (think that you’ll have to do that only once and you’ll be able to track all your learners’ progress)

1. Your content should be a SCORM package

Although there ae ways to go around this, they are all more or less as complicated as making your package SCORM compliant. I am attaching a very simple SCORM course. The important thing is that you understand that you need a directory to include an XML file (called the imsmanifest.xml) and that that XML file needs to give a list of all elements in your package. Finally, you have to zip this directory and this will be a (acceptable but not compliant) SCORM package.

One quick way to get there is to create your content in Dokeos, export it as SCORM, then go into the zip and into the imsmanifest.xml file and change items types from “asset” to “sco”. This will enable the Dokeos SCORM JavaScript library.
Before you do that, make sure you define your prerequisites in Dokeos. This will save you some time later on.

If you need help on the format of your SCORM package, look for the SCORM 1.2 CAM document (Content Aggregation Model).

2. Each step of your content should send a LMSInitialize() call

To do this, there is a first initial step which is to define a small library on the side of your content (along with the Flash or included into the Flash) that will communicate, in JavaScript, with Dokeos.
As you will find in various websites (one interesting resource is http://www.ostyn.com/resscormtech.htm ), and in the APIWrapper.js file coming from a public SCORM course, you need to define in your Flash a way to get an attachment point to the SCORM library on the Dokeos side. This is done, in the APIWrapper.js, by the function getAPIHandle().

There is an alternative version of the APIWrapper.js available here: http://pipwerks.com/lab/scorm/ which has been improved starting from the basic version linked above and MIT-licensed (= you’re pretty much free to do anything with it), as Philip kindly told me in a comment to this article.

I recommend you use this APIWrapper.js (or the one from Philip) and use it for all the calls you need to do from your Flash content. The only element I don’t know well here is how exactly you call or include the JavaScript from your Flash content. This will considerably reduce your efforts.
Once you’ve done that, you need to ensure that you content sends the LMSInitialize() call, which is done, using APIWrapper.js, by calling doLMSInitialize().

3. Call LMSSetValue(‘cmi.core.lesson_status’,’completed’)

You can do this, using APIWrapper.js, by issuing a call like this:

doLMSSetValue(‘cmi.core.lesson_status’,’completed’);

This will set the lesson as completed. However, you might as well want to set the time used for this entire Flash. To do that, you can use:

doLMSSetValue(‘cmi.core.session_time’,’completed’);

There are multiple other calls that you can do to get or set other values, but I won’t go into the details here.

4. Call the LMSFinish()

Finally, you have to call LMSFinish() to finish the process of your SCORM. Technically, you have to call LMSCommit() first (to save your changes to the Dokeos database).

This is it. After following these steps, your content should be SCORM-compliant (or almost so) and record both the time and the status.

Now if you want the second step to be dependent on the completeness of the first, then the imsmanifest.xml should define such dependency.
Normally, it is already the case because you exported your content from Dokeos *after* defining pre-requisites.

You should now be able to import your course into Dokeos again, but this time as SCORM, with time and status tracking included.

eLML

I sure am discovering a lot of interesting stuff on the net this week. I’m just done reading and watching a video on the eLML website. First reaction: interesting project.

Apparently, some of the developers of fellow e-learning management system OLAT are involved in the development of eLML as well.

eLML is just an XML schema for writing learning content. It’s pretty much the same kind of stuff as SCORM, but it actually allows exports to SCORM, IMS, PDF and website-presentation (with YAML). Considering it was shouting loud that the export formats had been tested with Moodle, I thought we might try it and see if that worked with Dokeos as well, so I downloaded an example on their website and tried to import it to Dokeos and it worked out of the box.

Importing eLML example as SCORM into Dokeos learning path

Importing eLML example as SCORM into Dokeos learning path

The provided SCORM export doesn’t seem to offer the necessary JavaScript interface though, so it doesn’t generate any reporting in Dokeos but it still looks like an interesting initiative to me… Maybe it would be interesting to have an eLML export feature in Dokeos, so courses generated in Dokeos could be exported to PDF (indirectly)?

Moving SCORM API from XAJAX to jQuery

December 8, 2008 2 comments

Yesterday I finished a 20 hours job of moving the SCORM API in Dokeos 1.8.6 from XAJAX to jQuery. The problem with XAJAX is that version 0.5 represents an important change in comparison to version 0.2, that version 0.5 is the only one implementing synchronous AJAX calls, and that upgrading was obviously going to take me some time (possibly very long).

We also decided to go with jQuery uniformally in Dokeos 1.8 and 2.0, so I decided, following a suggestion by Eric Marguin, to move it to jQuery.

The problem there is that, if jQuery allows you to execute GET/POST requests easily, the documentation isn’t clear as to how to pass array variables to the resulting PHP script. So I had to implement a array-serializer of my own. The result looks something like this ugly piece of code:

params=”;
params += ‘lid=’+lms_lp_id+’&uid=’+lms_user_id+’&vid=’+lms_view_id;
params += ‘&iid=’+lms_item_id;
obj_string = ”;
for (i in item_objectives){
obj_string += ‘&objectives[‘+i+’]=’;
obj_temp = ‘[‘;
for (j in item_objectives[i]) {
obj_temp += item_objectives[i][j]+’,’;
}
obj_temp = obj_temp.substr(0,(obj_temp.length-2)) + ‘]’;
obj_string += encodeURIComponent(obj_temp);
}
params += obj_string;
$.ajax({
type: “GET”,
data: params,
url: “lp_ajax_save_objectives.php”,
dataType: “script”,
async: false
});

Where item_objectives is an indexed array.

All in all, the implementation seems to work much better than the previous one (because the async: false param allows me to set the AJAX query as synchronous), but I still want to test it a little more before integrating it into Dokeos.

For the curious about the changes applied, they can be seen in an SVN branch: http://dokeos.svn.sourceforge.net/viewvc/dokeos?view=rev&revision=17130