<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>VSSCORM &#187; Run Time Environment</title>
	<atom:link href="http://www.vsscorm.net/category/scorm-rte/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.vsscorm.net</link>
	<description>A Very Simple SCORM Interface</description>
	<lastBuildDate>Tue, 20 Jul 2010 17:08:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Step 56 &#8211; mysql_escape_string</title>
		<link>http://www.vsscorm.net/2010/07/19/step-56-mysql_escape_string/</link>
		<comments>http://www.vsscorm.net/2010/07/19/step-56-mysql_escape_string/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 14:05:55 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1514</guid>
		<description><![CDATA[I don&#8217;t refer to the PHP manual very much for commonly used functions, so I almost missed this one. The &#8216;mysql_escape_string&#8217; function that&#8217;s used in subs.php to prepare data for insertion into the database is deprecated as of PHP 5.3 &#8230; <a href="http://www.vsscorm.net/2010/07/19/step-56-mysql_escape_string/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t refer to the PHP manual very much for commonly used functions, so I almost missed this one. The &#8216;mysql_escape_string&#8217; function that&#8217;s used in subs.php to prepare data for insertion into the database is deprecated as of PHP 5.3 and should be replaced with &#8216;mysql_real_escape_string&#8217;. </p>
<p><span id="more-1514"></span></p>
<p>From the PHP manual:</p>
<blockquote><p>This function [<a href="http://www.php.net/manual/en/function.mysql-escape-string.php" target="_blank">mysql_escape_string()</a>] is identical to <a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php" target="_blank">mysql_real_escape_string()</a> except that mysql_real_escape_string() takes a connection handler and escapes the string according to the current character set. mysql_escape_string() does not take a connection argument and does not respect the current charset setting.</p></blockquote>
<p>The new function &#8211; mysql_real_escape_string &#8211; has been available since PHP 4.3 and, quite frankly, you really shouldn&#8217;t be running on anything older than that! So, at the next release of the RTE, I&#8217;ll be changing the database functions in subs.php to reflect this change.</p>
<p>On a final note, it&#8217;s still my intention to convert the code to run on a database abstraction layer, but I just haven&#8217;t had the time to do that yet!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/19/step-56-mysql_escape_string/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 55 &#8211; Delaying Loading of the SCO</title>
		<link>http://www.vsscorm.net/2010/07/16/step-55-delaying-loading-of-the-sco/</link>
		<comments>http://www.vsscorm.net/2010/07/16/step-55-delaying-loading-of-the-sco/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 13:45:07 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1554</guid>
		<description><![CDATA[In the past, I&#8217;ve had some intermittent problems with a SCO loading but showing a Javascript error. Although I couldn&#8217;t pin it down conclusively, it seemed to result from an incomplete download of some kind. Since forcing a reload with &#8230; <a href="http://www.vsscorm.net/2010/07/16/step-55-delaying-loading-of-the-sco/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the past, I&#8217;ve had some intermittent problems with a SCO loading but showing a Javascript error. Although I couldn&#8217;t pin it down conclusively, it seemed to result from an incomplete download of some kind. Since forcing a reload with CTRL-R or CTRL-F5 usually solved the problem, I just put it down to something that I had to live with because SCORM forces us to use Javascript which can be very fickle.</p>
<p>But, recently, reader &#8216;deighvan&#8217; reported <a href="http://www.vsscorm.net/2010/04/30/download-vs-scorm-1-2-rte-rev-2-1/comment-page-1/#comment-62">a similar problem</a> and, even better, came up with a simple solution. So I&#8217;ve incorporated a slightly modified form of this solution in a new version of the rte.php file. </p>
<p><span id="more-1554"></span></p>
<p>Here it is:</p>
<pre class="brush:php; first-line: 1; html-script: false;">&lt;?php 

/*

VS SCORM 1.2 RTE - rte.php
Rev XXXXXXXXXXX was 2009-11-30-01
Copyright (C) 2010, Addison Robson LLC

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA  02110-1301, USA.

*/

// read SCOInstanceID from the GET parameters
$SCOInstanceID = $_GET['SCOInstanceID'] * 1;

?>
&lt;html>
&lt;head>
  &lt;title>VS SCORM&lt;/title>
  &lt;script language="javascript">

    var started = false;

    function loadSCO() {
      if (! started) {
        SCO.location.href = '... location of the SCO ...';
      }
      started = true;
    }

    function unloadSCO() {
      setTimeout('API.LMSFinish("");',2000);
    }

  &lt;/script>
&lt;/head>
&lt;frameset frameborder="0" framespacing="0" border="0" rows="50,*" cols="*" onbeforeunload="unloadSCO();" onunload="unloadSCO();">
  &lt;frame src="api.php?SCOInstanceID=&lt;?php print $SCOInstanceID; ?>" name="API" id="API" noresize onload="loadSCO();">
  &lt;frame src="blank.html" name="SCO" id="SCO">
&lt;/frameset>
&lt;/html></pre>
<p>And here are the changes &#8230; line-by-line:</p>
<ul>
<li><strong>Line 35</strong> &#8211; I define a Javascript variable called &#8216;started&#8217; and set it to false. This will be used to prevent the SCO being started twice.<br />&nbsp;
<li><strong>Lines 37 to 42</strong> &#8211; I&#8217;ve added a new Javascript function that, when called, will load the SCO into the &#8216;SCO&#8217; frame.<br />&nbsp;
<li><strong>Line 51</strong> &#8211; I&#8217;ve added an &#8216;onload&#8217; action. When the api.php code has completely loaded into the frame, this will call loadSCO() which will start the SCO.<br />&nbsp;
<li><strong>Line 52</strong> &#8211; When the frameset starts, I&#8217;m going to load a blank document into the &#8216;SCO&#8217; frame. Why not just start with an empty frame (i.e. src=&#8221;)? Because, if I&#8217;m going to be running over an SSL connection, Internet Explorer considers an empty frame to be an insecure document and will pop up a warning message that&#8217;s annoying, and also worrying to many students.<br />&nbsp;
</ul>
<p>So I try it out, and it seems to work much more smoothly than before. Once again, thanks to reader &#8216;deighvan&#8217; for the suggestion.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/16/step-55-delaying-loading-of-the-sco/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Step 54 &#8211; Error Handling?</title>
		<link>http://www.vsscorm.net/2010/07/13/step-54-error-handling/</link>
		<comments>http://www.vsscorm.net/2010/07/13/step-54-error-handling/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 14:52:31 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1507</guid>
		<description><![CDATA[The problem SCO described in Step 52 is now working correctly, so why do I need to look any further? There&#8217;s a more subtle problem. The &#8216;datamodel.element._children&#8217; mechanism described in the SCORM RTE specification seems to have been developed so &#8230; <a href="http://www.vsscorm.net/2010/07/13/step-54-error-handling/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The problem SCO described in <a href="http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/">Step 52</a> is now working correctly, so why do I need to look any further? There&#8217;s a more subtle problem.</p>
<p>The &#8216;datamodel.element._children&#8217; mechanism described in the SCORM RTE specification seems to have been developed so that there&#8217;s a way for a SCO to determine which data elements are supported. </p>
<p><span id="more-1507"></span></p>
<p><a href="http://www.vsscorm.net/wp-content/uploads/2010/07/children.jpg"><img src="http://www.vsscorm.net/wp-content/uploads/2010/07/children.jpg" alt="" title="_children" width="697" height="189" class="aligncenter size-full wp-image-1572" /></a></p>
<p><center><a href="/docs/SCORM_1.2_RunTimeEnv.pdf" target="_blank">SCORM 1.2 RTE Specification</a> &#8211; Page 3-9</center></p>
<p>For example, if the SCO was to do this:</p>
<pre class="brush:javascript; first-line: 1">var supported = LMSGetValue('cmi.core._children');</pre>
<p>the variable &#8216;supported&#8217; would be set to &#8216;student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,exit,session_time&#8217; which is a list of the data elements in the <b>cmi.core</b> group that the LMS supports. This allows a SCO to determine whether or not it can use a particular data element before it tries to do so. And this is all well and good except &#8230;</p>
<p>&#8230; it doesn&#8217;t cover all of the optional data elements. The data element that the problem SCO was trying to use &#8211; <b>cmi.comments</b> &#8211; is not part of the <b>cmi.core</b> group of data elements, so looking at the value of <b>cmi.core._children</b> wouldn&#8217;t have helped. In fact, <b>cmi.comments</b> isn&#8217;t part of any group at all.</p>
<p>Now, the SCORM 1.2 RTE says that:</p>
<ul>
<li>If an element IS supported but contains no child elements, <b>an empty string is returned</b>.
<li>If an element IS NOT supported, <b>an empty string is returned</b>.
</ul>
<p>So there would be no way to use &#8216;_children&#8217; to determine if <b>cmi.comments</b> was supported since:</p>
<pre class="brush:javascript; first-line: 1">var supported = LMSGetValue('cmi.comments._children');</pre>
<p>would always return an empty string. Instead, according to the specification, one has to look at the error codes:</p>
<p><a href="http://www.vsscorm.net/wp-content/uploads/2010/07/children2.jpg"><img src="http://www.vsscorm.net/wp-content/uploads/2010/07/children2.jpg" alt="" title="_children2" width="840" height="329" class="aligncenter size-full wp-image-1573" /></a></p>
<p><center><a href="/docs/SCORM_1.2_RunTimeEnv.pdf" target="_blank">SCORM 1.2 RTE Specification</a> &#8211; Page 3-9</center></p>
<p>So, if I execute the following:</p>
<pre class="brush:javascript; first-line: 1">var supported = LMSGetValue('cmi.comments._children');
var lasterror = LMSGetLastError();</pre>
<p>then variable &#8216;lasterror&#8217; is set to 401, and I know that the <b>cmi.comments</b> element is NOT supported.</p>
<p>OK &#8211; it seems pretty odd to me that a system would be designed to cover some, but not all, of the optional data elements. But there it is &#8211; we&#8217;re going to have to live with it.</p>
<p>And it highlights a more fundamental issue that I need to fix &#8211; I&#8217;ve been very lax with my handling of the error codes so far &#8211; that has to change!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/13/step-54-error-handling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 53 &#8211; Delaying the Closing Sequence</title>
		<link>http://www.vsscorm.net/2010/07/11/step-53-delaying-the-closing-sequence/</link>
		<comments>http://www.vsscorm.net/2010/07/11/step-53-delaying-the-closing-sequence/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 21:21:38 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1505</guid>
		<description><![CDATA[I&#8217;m still trying to fix the problem that my reader&#8217;s SCO highlighted (described in this post). I&#8217;ve implemented the optional data element that it&#8217;s trying to use &#8211; cmi.comments &#8211; but that hasn&#8217;t fixed the problem. So I need to &#8230; <a href="http://www.vsscorm.net/2010/07/11/step-53-delaying-the-closing-sequence/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still trying to fix the problem that my reader&#8217;s SCO highlighted (described in <a href="http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/">this post</a>). I&#8217;ve implemented the optional data element that it&#8217;s trying to use &#8211; <b>cmi.comments</b> &#8211; but that hasn&#8217;t fixed the problem. So I need to look elsewhere.</p>
<p>The SCO is trying to save the user&#8217;s comments to the LMS database when the SCO is closed. So, perhaps, the API code isn&#8217;t being given enough time to commit all of the data values to the database before everything shuts down.</p>
<p><span id="more-1505"></span></p>
<p>To try to fix this, I&#8217;m going to add a delay to the closing sequence. As a reminder, here&#8217;s what my rte.php looks like right now.</p>
<pre class="brush:php; first-line: 1; html-script: false;">&lt;?php 

/*

VS SCORM 1.2 RTE - rte.php
Rev 2009-11-30-01
Copyright (C) 2009, Addison Robson LLC

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA	02110-1301, USA.

*/

// read SCOInstanceID from the GET parameters
$SCOInstanceID = $_GET['SCOInstanceID'] * 1;

?>
&lt;html>
&lt;head>
	&lt;title>VS SCORM&lt;/title>
&lt;/head>
&lt;frameset
  frameborder="0"
  framespacing="0"
  border="0"
  rows="100,*"
  cols="*"
  onbeforeunload="API.LMSFinish('');"
  onunload="API.LMSFinish('');">
	&lt;frame src="api.php?SCOInstanceID=&lt;?php print $SCOInstanceID; ?>" name="API">
	&lt;frame src="... location of the course ..." name="course">
&lt;/frameset>
&lt;/html></pre>
<p>In lines 40 and 41 of the listing above, you&#8217;ll see that I&#8217;ve arranged for the LMSFinish() function to be called directly when the frameset tries to close down. I&#8217;m now going to change this by making the frameset call a Javascript function called unloadSCO() which, in turn, calls LMSFinish() after a delay. I&#8217;ve also taken the opportunity to re-name the frame from &#8216;course&#8217; to &#8216;SCO&#8217; to make the SCORM purists happy!</p>
<pre class="brush:php; first-line: 1; html-script: false;">&lt;?php 

/*

VS SCORM 1.2 RTE - rte.php
Rev XXXXXXXXXXX was 2009-11-30-01
Copyright (C) 2010, Addison Robson LLC

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA	02110-1301, USA.

*/

// read SCOInstanceID from the GET parameters
$SCOInstanceID = $_GET['SCOInstanceID'] * 1;

?>
&lt;html>
&lt;head>
	&lt;title>VS SCORM&lt;/title>
	&lt;script language="javascript">
		function unloadSCO() {
			setTimeout('API.LMSFinish("");',2000);
		}
	&lt;/script>
&lt;/head>
&lt;frameset
  frameborder="0"
  framespacing="0"
  border="0"
  rows="50,*"
  cols="*"
  onbeforeunload="unloadSCO();"
  onunload="unloadSCO();">
	&lt;frame src="api.php?SCOInstanceID=&lt;?php print $SCOInstanceID; ?>" name="API" id="API" noresize">
	&lt;frame src="... location of the course ..." name="SCO" id="SCO">
&lt;/frameset>
&lt;/html></pre>
<p>I now try it again, and it works! The students can write notes and they&#8217;re successfully saved to the database when the course closes. </p>
<p>But that&#8217;s not the end of things &#8230; </p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/11/step-53-delaying-the-closing-sequence/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Step 52 &#8211; cmi.comments and cmi.comments_from_lms</title>
		<link>http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/</link>
		<comments>http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 00:33:24 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1500</guid>
		<description><![CDATA[A reader recently contacted me with a problem that raised some interesting issues. Hopefully, we&#8217;ve now resolved the problem but, since the issues might well occur with other SCOs, what I&#8217;d like to do is to walk through the process &#8230; <a href="http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A reader recently contacted me with a problem that raised some interesting issues. Hopefully, we&#8217;ve now resolved the problem but, since the issues might well occur with other SCOs, what I&#8217;d like to do is to walk through the process and show how the VSSCORM RTE has to be modified to deal with this situation.</p>
<p>Here&#8217;s what was happening. The SCO in question was a technical training course &#8211; the subject is unimportant &#8211; and it ran OK except for one problem. The SCO author(s) had very helpfully provided a small text area on the SCO screens where a student could write notes and have them saved between sessions &#8211; in effect, online &#8216;PostIt&#8217; notes. The problem was that the notes weren&#8217;t being saved to the database when the SCO was closed.</p>
<p><span id="more-1500"></span></p>
<p>After digging around in the code, it became obvious that the SCO was storing all of the notes on the client side while the SCO was running &#8211; probably in a cookie, or maybe in a Javascript variable &#8211; until the SCO window was closed at which point it attempted to save them to the LMS database. Here&#8217;s the Javascript from the SCO (not the RTE) that seems to be failing.</p>
<pre class="brush:javascript; first-line: 1">function getCommentsData() {
  return scormGetValue("cmi.comments");
}

function setCommentsData(sSuspend) {
  scormSetValue("cmi.comments", sSuspend+"");
}</pre>
<p>The first thing that to note is that the SCO is using the (optional) <b>cmi.comments</b> data element rather than the (mandatory) <b>cmi.suspend_data</b> element. And, to be fair, that&#8217;s what the <b>cmi.comments</b> data element is provided for.</p>
<p><a href="http://www.vsscorm.net/wp-content/uploads/2010/07/cmi_comments.jpg"><img src="http://www.vsscorm.net/wp-content/uploads/2010/07/cmi_comments.jpg" alt="" title="cmi_comments" width="555" height="219" class="aligncenter size-full wp-image-1521" /></a></p>
<p><center><a href="/docs/SCORM_1.2_RunTimeEnv.pdf" target="_blank">SCORM 1.2 RTE Specification</a> &#8211; Page 3-35</center></p>
<p>So, as the first step in trying to fix the problem, I&#8217;m going to add the optional element <b>cmi.comments</b> and, while I&#8217;m at it, the related data element <b>cmi.comments_from_lms</b>.</p>
<p><a href="http://www.vsscorm.net/wp-content/uploads/2010/07/cmi_comments_from_lms.jpg"><img src="http://www.vsscorm.net/wp-content/uploads/2010/07/cmi_comments_from_lms.jpg" alt="" title="cmi_comments_from_lms" width="554" height="207" class="aligncenter size-full wp-image-1528" /></a></p>
<p><center><a href="/docs/SCORM_1.2_RunTimeEnv.pdf" target="_blank">SCORM 1.2 RTE Specification</a> &#8211; Page 3-36</center></p>
<p>I&#8217;m going to start with the LMSSetValue() function in the api.php file where I have to declare the <b>cmi.comments</b> data element as writeable (line 14):</p>
<pre class="brush:javascript; first-line: 1">function LMSSetValue(varname,varvalue) {

  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) { return "false"; }

  // is this a writeable data element?
  if (
    (varname=='cmi.core.lesson_location') ||
    (varname=='cmi.core.lesson_status') ||
    (varname=='cmi.core.exit') ||
    (varname=='cmi.core.session_time') ||
    (varname=='cmi.core.score.raw') ||
    (varname=='cmi.core.suspend_data') ||
    (varname=='cmi.comments')
  ) {

    // set the requested data, and return success value
    cache[varname] = varvalue;
    return "true";

  }

  // not a writeable data element
  else {

    // return failure value
    return "false";

  }

}</pre>
<p>Note that I don&#8217;t have to do anything with the <b>cmi.comments_from_lms</b> data element since it&#8217;s read-only. Now, in the LMSCommit() function, I make a corresponding change to add <b>cmi.comments</b> to the data being transferred to the LMS (line 24):</p>
<pre class="brush:javascript; first-line: 1">function LMSCommit(dummyString) {

  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) { return "false"; }

  // create request object
  var req = createRequest();

  // code to prevent caching
  var d = new Date();

  // set up request parameters - uses POST method
  req.open('POST','commit.php',false);

  // create a POST-formatted list of cached data elements
  // include only SCO-writeable data elements
  var params = 'SCOInstanceID=<?php print $SCOInstanceID; ?>&#038;code='+d.getTime();
  params += "&#038;data[cmi.core.lesson_location]="+urlencode(cache['cmi.core.lesson_location']);
  params += "&#038;data[cmi.core.lesson_status]="+urlencode(cache['cmi.core.lesson_status']);
  params += "&#038;data[cmi.core.exit]="+urlencode(cache['cmi.core.exit']);
  params += "&#038;data[cmi.core.session_time]="+urlencode(cache['cmi.core.session_time']);
  params += "&#038;data[cmi.core.score.raw]="+urlencode(cache['cmi.core.score.raw']);
  params += "&#038;data[cmi.suspend_data]="+urlencode(cache['cmi.suspend_data']);
  params += "&#038;data[cmi.comments]="+urlencode(cache['cmi.comments']);

  // request headers
  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  req.setRequestHeader("Content-length", params.length);
  req.setRequestHeader("Connection", "close");

  // submit to the server for processing
  req.send(params);

  // process returned data - error condition
  if (req.status != 200) {
    alert('Problem with AJAX Request in LMSCommit()');
    return "false";
  }

  // process returned data - OK
  else {
    return "true";
  }

}</pre>
<p>Now to look at subs.php where I need to add both of these elements to the list so that they&#8217;re initialized when the SCO first starts. Pretty simple &#8211; I add the following lines to the initializeSCO() function (omitting most of the other lines for clarity):</p>
<pre class="brush:php; first-line: 1; html-script: false">function initializeSCO() {

  ...
  ...

  // comments
  initializeElement('cmi.comments','');
  initializeElement('cmi.comments_from_lms',getFromLMS('cmi.comments_from_lms'));

  ...
  ...

}</pre>
<p><b>cmi.comments</b> starts out as an empty string, but the <b>cmi.comments_from_lms</b> data element needs to be initialized with a value from the LMS. So my final task is to change the getFromLMS() function:</p>
<pre class="brush:php; first-line: 1">function getFromLMS($varname) {

  switch ($varname) {

    ...
    ...

    case 'cmi.comments_from_lms':
      $varvalue = "";
      break;

    ...
    ...

  }

  return $varvalue;

}</pre>
<p>Now, I&#8217;ve added the new data elements and I run the SCO again. No good &#8211; the problem is still there. There must be another problem that I haven&#8217;t spotted.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/09/step-52-cmi-comments-and-cmi-comments_from_lms/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Download VS SCORM 1.2 RTE Rev 2.1</title>
		<link>http://www.vsscorm.net/2010/04/30/download-vs-scorm-1-2-rte-rev-2-1/</link>
		<comments>http://www.vsscorm.net/2010/04/30/download-vs-scorm-1-2-rte-rev-2-1/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 07:39:21 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1254</guid>
		<description><![CDATA[After a somewhat longer time than I&#8217;d planned, here&#8217;s Rev 2.1 of the VSSCORM 1.2 RTE. It includes the following changes from Rev 2.0: Fix for the &#8220;cmi.score.raw&#8221; bug described in this post. Fix for the &#8220;ab initio&#8221; bug described &#8230; <a href="http://www.vsscorm.net/2010/04/30/download-vs-scorm-1-2-rte-rev-2-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After a somewhat longer time than I&#8217;d planned, here&#8217;s Rev 2.1 of the VSSCORM 1.2 RTE. It includes the following changes from Rev 2.0:</p>
<p><span id="more-1254"></span></p>
<ol>
<li>Fix for the &#8220;cmi.score.raw&#8221; bug described in <a href="/2010/01/20/bug-in-vs-scorm-1-2-rte-rev-2-0/">this post</a>.
<li>Fix for the &#8220;ab initio&#8221; bug described in <a href="/2010/03/19/another-bug-in-vs-scorm-1-2-rte-rev-2-0/">this post</a>.
<li>Adds the &#8220;flagFinished&#8221; and &#8220;flagInitialized&#8221; variables to store API state information as discussed in <a href="http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/">this post</a>.
</ol>
<p><center><br />
<table cellpadding=15 cellspacing=0 border=2>
<tr>
<td valign=top align=center>You can download the code bundle using <a href="/docs/vsscorm_rte12_2_1.zip">this link</a>.</td>
</tr>
</table>
<p>&nbsp;</center></p>
<p>If you&#8217;re upgrading, it should be pretty simple since the new files simply replace the old ones &#8211; no need to change the database or file structure.</p>
<p>Next time, some thoughts on where this project is taking me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/04/30/download-vs-scorm-1-2-rte-rev-2-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Another Bug in VS SCORM 1.2 RTE Rev 2.0</title>
		<link>http://www.vsscorm.net/2010/03/19/another-bug-in-vs-scorm-1-2-rte-rev-2-0/</link>
		<comments>http://www.vsscorm.net/2010/03/19/another-bug-in-vs-scorm-1-2-rte-rev-2-0/#comments</comments>
		<pubDate>Fri, 19 Mar 2010 19:22:38 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1244</guid>
		<description><![CDATA[An eagle-eyed reader of the blog has brought the following bug to my attention. In all cases in the php code, you use the string &#8220;ab initio&#8221; as the value for cmi.core.entry when it is the first time a SCO &#8230; <a href="http://www.vsscorm.net/2010/03/19/another-bug-in-vs-scorm-1-2-rte-rev-2-0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>An eagle-eyed reader of the blog has brought the following bug to my attention.</p>
<blockquote><p>In all cases in the php code, you use the string &#8220;ab initio&#8221; as the value for cmi.core.entry when it is the first time a SCO is used.</p>
<p>According to the SCORM 1.2 spec doc, SCORM_1.2_RunTimeEnv.pdf &#8211; page 3-22, (page 34 of the file), the value should be &#8220;ab-initio&#8221; with a hyphen.</p></blockquote>
<p><span id="more-1244"></span></p>
<p>This affects line 124 of subs.php in VS SCORM 1.2 RTE Rev 2.0:</p>
<pre class="brush:php; first-line: 124">initializeElement('cmi.core.entry','ab initio');</pre>
<p>which should read:</p>
<pre class="brush:php; first-line: 124">initializeElement('cmi.core.entry','ab-initio');</pre>
<p>I haven&#8217;t check the Rev 1.x release, but it shouldn&#8217;t be too hard to do a quick search of the code if you haven&#8217;t upgraded to Rev 2.0 (strongly recommended for speed reasons alone).</p>
<p>The fix will be in Rev 2.1 of the RTE which I&#8217;ll try to post next week.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/03/19/another-bug-in-vs-scorm-1-2-rte-rev-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 51 &#8211; Testing for API Session State</title>
		<link>http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/</link>
		<comments>http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 21:23:26 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/</guid>
		<description><![CDATA[In Step 48, I introduced a flag to indicate whether a session had been finished or not. In that post, it was used to ensure that LMSFinish wasn&#8217;t called multiple times. But I really ought to extend it to make &#8230; <a href="http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="/2009/11/25/step-48-lmsfinish-and-unexpected-closure/">Step 48</a>, I introduced a flag to indicate whether a session had been finished or not. In that post, it was used to ensure that LMSFinish wasn&#8217;t called multiple times. But I really ought to extend it to make sure that none of the API functions are processed after the session has been closed.</p>
<p><span id="more-1243"></span></p>
<p>In addition, I should probably make sure that no API calls are processed before the API session has been initialized. This isn&#8217;t as much of a problem as long as the SCO has been well-written since, according to the SCORM standard, LMSInitialize should always be the first API function called by the SCO/course.</p>
<p>So, building on the work I did in Step 48, I&#8217;m going to introduce a second JavaScript variable &#8211; flagInitialized &#8211; into api.php:</p>
<pre class="brush:javascript">var flagFinished = false;
var flagInitialized = false;</pre>
<p>There are now five API calls to be changed so that they test for appropriate values of flagInitialized and flagFinished.</p>
<p><b>1. LMSInitialize</b></p>
<p>This API call can only be executed if the session HASN&#8217;T already been initialized, and the session HASN&#8217;T been closed. So I modify my code like this:</p>
<pre class="brush:javascript">function LMSInitialize(dummyString) {

  // already initialized or already finished
  if ((flagInitialized) || (flagFinished)) {
    return "false";
  }

  // set initialization flag
  flagInitialized = true;

  // return success value
  return "true";

}</pre>
<p>If either flagInitialized or flagFinished is set to &#8216;true&#8217;, execution of the function will be aborted. If it proceeds, line 7 sets the &#8216;flagInitialized&#8217; variable so that other API calls know that the session is initialized.</p>
<p><b>2. LMSFinish</b></p>
<p>This API call can only be executed if the session HAS been initialized but HAS NOT yet been closed. So the code looks like this </p>
<pre class="brush:javascript">function LMSFinish(dummyString) {

  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) {
    return "false";
  }

  ...
  ...

  // set finish flag
  flagFinished = true;

  // return to calling program
  return "true";

}</pre>
<p>Very similar to LMSInitialize except that I only allow the code to run if flagInitialized is set to &#8216;true&#8217;, and flagFinished is set to &#8216;false&#8217;. If the function executes correctly, line 10 sets flagFinished to &#8216;true&#8217; so that there can be no further communication between the SCO/course and the LMS.</p>
<p><b>3. LMSGetValue, LMSSetValue and LMSCommit</b></p>
<p>Finally, I need to add the following code to each of these three API calls to ensure that the code is only executed if the session HAS been initialized, but HAS NOT been closed.</p>
<pre class="brush:javascript">  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) {
    return "false";
  }</pre>
<p>And that&#8217;s it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/01/22/step-51-testing-for-api-session-state/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bug in VSSCORM 1.2 RTE Rev 2.0</title>
		<link>http://www.vsscorm.net/2010/01/20/bug-in-vs-scorm-1-2-rte-rev-2-0/</link>
		<comments>http://www.vsscorm.net/2010/01/20/bug-in-vs-scorm-1-2-rte-rev-2-0/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 19:38:10 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1226</guid>
		<description><![CDATA[I recently spotted a bug in VS SCORM 1.2 RTE Rev 2.0. Line 54 of finish.php reads: $rawscore = readElement('cmi.score.raw'); It should read: $rawscore = readElement('cmi.core.score.raw'); I&#8217;ll incorporate this fix in a new release of the RTE once I&#8217;ve made &#8230; <a href="http://www.vsscorm.net/2010/01/20/bug-in-vs-scorm-1-2-rte-rev-2-0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I recently spotted a bug in VS SCORM 1.2 RTE Rev 2.0. Line 54 of finish.php reads:</p>
<pre class="brush:php; first-line: 54">$rawscore = readElement('cmi.score.raw');</pre>
<p>It should read:</p>
<pre class="brush:php; first-line: 54">$rawscore = readElement('cmi.core.score.raw');</pre>
<p>I&#8217;ll incorporate this fix in a new release of the RTE once I&#8217;ve made a few other improvements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/01/20/bug-in-vs-scorm-1-2-rte-rev-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Simple SCORM 1.2 Content Package</title>
		<link>http://www.vsscorm.net/2010/01/20/a-simple-scorm-1-2-content-package/</link>
		<comments>http://www.vsscorm.net/2010/01/20/a-simple-scorm-1-2-content-package/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 19:11:56 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Content Aggregation Model]]></category>
		<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1212</guid>
		<description><![CDATA[If you want a very simple test case, you can use this content package &#8211; a single SCO consisting of: a title page; 3 test questions (the correct answer in each case is &#8220;true&#8221;); and a results page. It was &#8230; <a href="http://www.vsscorm.net/2010/01/20/a-simple-scorm-1-2-content-package/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you want a <b>very</b> simple test case, you can use this content package &#8211; a single SCO consisting of:</p>
<ul>
<li>a title page;</li>
<li>3 test questions (the correct answer in each case is &#8220;true&#8221;); and</li>
<li>a results page.</li>
</ul>
<p><span id="more-1212"></span></p>
<p><a href="http://www.vsscorm.net/wp-content/uploads/2010/01/simpletest.gif"><img src="http://www.vsscorm.net/wp-content/uploads/2010/01/simpletest.gif" alt="" title="simpletest" width="600" height="440" class="aligncenter size-full wp-image-1220" /></a></p>
<p>It was created using Lectora, runs in a 760 x 550 window, and sets &#8216;cmi.core.lesson_status&#8217; to &#8220;passed&#8221; to indicate completion. The SCO entry point is &#8216;a001index.html&#8217;.</p>
<p><center>You can download it from <a href="/docs/SimpleTest.zip">here</a></center></p>
<p>Hope it helps! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/01/20/a-simple-scorm-1-2-content-package/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
