<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>VSSCORM</title>
	
	<link>http://www.vsscorm.net</link>
	<description>A Very Simple SCORM Interface</description>
	<lastBuildDate>Thu, 08 Sep 2011 14:45:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/VSSCORM" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="vsscorm" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">VSSCORM</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Step 61 – Error Checking in LMSSetValue and LMSGetValue</title>
		<link>http://www.vsscorm.net/2011/09/08/step-61-error-checking-in-lmssetvalue-and-lmsgetvalue/</link>
		<comments>http://www.vsscorm.net/2011/09/08/step-61-error-checking-in-lmssetvalue-and-lmsgetvalue/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 14:45:52 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1670</guid>
		<description><![CDATA[I want to carry a couple of basic tests within LMSSetValue and LMSGetValue to see: whether the specified data element is supported; and whether it has the necessary read or write privileges and then set the error code appropriately. This &#8230; <a href="http://www.vsscorm.net/2011/09/08/step-61-error-checking-in-lmssetvalue-and-lmsgetvalue/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I want to carry a couple of basic tests within LMSSetValue and LMSGetValue to see:</p>
<ol>
<li>whether the specified data element is supported; and</li>
<li>whether it has the necessary read or write privileges</li>
</ol>
<p>and then set the error code appropriately. This is a pretty minimal set of tests &#8211; I&#8217;m probably going to have to add some others later &#8211; but it&#8217;s a starting point. Here&#8217;s the code.</p>
<p><span id="more-1670"></span></p>
<pre class="brush:php; first-line: 1; html-script: false;">
function LMSGetValue(varname) {

  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) {
    errorCode = '301';
    return '';
  }

  // not implemented
  if ( ! isSupported(varname) ) {
    errorCode = '401';
    return '';
  }

  // not readable
  if ( ! dataElementRead ) {
    errorCode = '404';
    return '';
  }

  // otherwise, return the requested data
  errorCode = '0';
  return cache[varname];

}

// --------------------------------------------------------

function LMSSetValue(varname,varvalue) {

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

  // not implemented
  if ( ! isSupported(varname) ) {
    errorCode = '401';
    return 'false';
  }

  // not writeable
  if ( ! dataElementWrite ) {
    errorCode = '403';
    return 'false';
  }

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

}
</pre>
<p>The additions are pretty straightforward.</p>
<ul>
<li><strong>Lines 9 to 13</strong>, and <strong>37 to 41</strong> check to see whether the data element specified by the SCO is actually implemented (if you remember, I&#8217;m currently supporting all of the mandatory data elements, but only two of the optional elements). If the data element isn&#8217;t supported, the error code is set to &#8217;401&#8242;. <br />&nbsp;
<li><strong>Lines 15 to 19</strong>, and <strong>43 to 47</strong> test whether the data element is readable (for the LMSGetValue function) or writeable (for the LMSSetValue function) and, if it fails, sets error code &#8217;404&#8242; or &#8217;403&#8242; respecively.<br />&nbsp;
</ul>
<p>Note that, if the functions are successful, the error code is set to &#8217;0&#8242; before exit to indicate success. According to the SCORM RTE specification, every call to an API function must result in the error code being set &#8211; whether it&#8217;s successful or not.</p>
<p>Next time, I&#8217;m going to step away from the main VSSCORM code and do some work on a test harness that will allow me to monitor the SCO-LMS communications in order to make sure that all of this is working.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/08/step-61-error-checking-in-lmssetvalue-and-lmsgetvalue/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Step 60 – Supported Data Elements</title>
		<link>http://www.vsscorm.net/2011/09/06/step-60-supported-data-elements/</link>
		<comments>http://www.vsscorm.net/2011/09/06/step-60-supported-data-elements/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 14:55:06 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1658</guid>
		<description><![CDATA[One of the things that has caught me out in a couple of recent cases is that the SCORM standard makes SCO developers rely on error codes to determine whether or not certain elements are supported. I describe one specific &#8230; <a href="http://www.vsscorm.net/2011/09/06/step-60-supported-data-elements/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the things that has caught me out in a couple of recent cases is that the SCORM standard makes SCO developers rely on error codes to determine whether or not certain elements are supported. I describe one specific example in an earlier post &#8211; <a href="http://www.vsscorm.net/2010/07/13/step-54-error-handling/" title="Step 54 – Error Handling?">Step 54 &#8211; Error Handling</a>. </p>
<p>In a sensible system, the initialization process would provide the SCO with a complete list of supported elements so that it wouldn&#8217;t have to go through all this rigmarole. But that&#8217;s too much to hope for, so I need a simple way to check whether a data element is supported or not, and I&#8217;ll also need to check whether it&#8217;s readable and/or writeable.</p>
<p><span id="more-1658"></span></p>
<p>I&#8217;m going to start with my favorite weapon of choice &#8211; a JavaScript object (associative array for the perl and PHP fans). Here it is:</p>
<pre class="brush:php; first-line: 1; html-script: false;">
var dataElements = new Object();

dataElements['cmi.core._children'] = 'RO';

dataElements['cmi.core.student_id'] = 'RO';
dataElements['cmi.core.student_name'] = 'RO';

dataElements['cmi.core.lesson_location'] = 'RW';
dataElements['cmi.core.credit'] = 'RO';
dataElements['cmi.core.lesson_status'] = 'RW';
dataElements['cmi.core.entry'] = 'RO';
dataElements['cmi.core.exit'] = 'WO';

dataElements['cmi.core.score._children'] = 'RO';
dataElements['cmi.core.score.raw'] = 'RW';
dataElements['cmi.core.score.max'] = 'RW';
dataElements['cmi.core.score.min'] = 'RW';

dataElements['cmi.core.total_time'] = 'RO';
dataElements['cmi.core.session_time'] = 'WO';

dataElements['cmi.suspend_data'] = 'RW';
dataElements['cmi.launch_data'] = 'RO';

dataElements['cmi.comments'] = 'RW';
dataElements['cmi.comments_from_lms'] = 'RO';
</pre>
<p>This is nothing more than a list of the supported elements with their read/write status.</p>
<p>Then, to make life a little neater when I come to plug this into the actual code, I&#8217;m going to define a simple little function:</p>
<pre class="brush:php; first-line: 1; html-script: false;">
function isSupported(dataElementName) {

  // flags
  dataElementSupported = false;
  dataElementRead = false;
  dataElementWrite = false;

  // if the data element is in the list of supported elements
  if (dataElementName in dataElements) {

    rights = dataElements[dataElementName];
    dataElementSupported = true;

    if ( (rights == 'RW') || (rights == 'RO') ) { dataElementRead = true; }
    if ( (rights == 'RW') || (rights == 'WO') ) { dataElementWrite = true; }

  }

  return dataElementSupported;

}
</pre>
<p>This function simply sets three flags that are available to the LMSSetValue and LMSGetValue functions so that they can test the SCO-supplied input, and generate appropriate error codes.</p>
<p>Next, I&#8217;m going to add this to the LMSSetValue and LMSGetValue functions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/06/step-60-supported-data-elements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 59 – LMSGetLastError, LMSGetErrorString and LMSGetDiagnostic</title>
		<link>http://www.vsscorm.net/2011/09/02/step-59-lmsgetlasterror-lmsgeterrorstring-and-lmsgetdiagnostic/</link>
		<comments>http://www.vsscorm.net/2011/09/02/step-59-lmsgetlasterror-lmsgeterrorstring-and-lmsgetdiagnostic/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 23:54:51 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1652</guid>
		<description><![CDATA[The three API functions that return information to the SCO can now be connected to the error code variable that I implemented in Step 58, and to the error messages that I set up in Step 57. Here they are: &#8230; <a href="http://www.vsscorm.net/2011/09/02/step-59-lmsgetlasterror-lmsgeterrorstring-and-lmsgetdiagnostic/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The three API functions that return information to the SCO can now be connected to the error code variable that I implemented in <a href="http://www.vsscorm.net/2011/09/02/step-58-setting-and-storing-the-error-code/" title="Step 58 – Setting and Storing the Error Code">Step 58</a>, and to the error messages that I set up in <a href="http://www.vsscorm.net/2011/09/02/step-57-error-codes/" title="Step 57 – Error Codes">Step 57</a>.</p>
<p><span id="more-1652"></span></p>
<p>Here they are:</p>
<pre class="brush:php; first-line: 1; html-script: false;">
function LMSGetLastError() {
  return errorCode;
}

function LMSGetErrorString(thisErrorCode) {
  return errorMessages[thisErrorCode];
}

function LMSGetDiagnostic(thisErrorCode) {
  return errorMessages[thisErrorCode];
}
</pre>
<p>Pretty simple so far. Next step &#8211; testing whether variables are supported and, if so, are they readable and/or writeable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/02/step-59-lmsgetlasterror-lmsgeterrorstring-and-lmsgetdiagnostic/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Step 58 – Setting and Storing the Error Code</title>
		<link>http://www.vsscorm.net/2011/09/02/step-58-setting-and-storing-the-error-code/</link>
		<comments>http://www.vsscorm.net/2011/09/02/step-58-setting-and-storing-the-error-code/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 23:44:43 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1641</guid>
		<description><![CDATA[OK &#8211; an easy step here. I want a place to store the error code, so I introduce a new variable called &#8216;errorCode&#8217; into api.php. // ------------------------------------------ // Status Flags // ------------------------------------------ var flagFinished = false; var flagInitialized = false; &#8230; <a href="http://www.vsscorm.net/2011/09/02/step-58-setting-and-storing-the-error-code/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>OK &#8211; an easy step here. I want a place to store the error code, so I introduce a new variable called &#8216;errorCode&#8217; into api.php.</p>
<p><span id="more-1641"></span></p>
<pre class="brush:php; first-line: 1; html-script: false;">
// ------------------------------------------
//   Status Flags
// ------------------------------------------
var flagFinished = false;
var flagInitialized = false;
var errorCode = '0';
</pre>
<p>Pretty simple. This variable is accessible to all of the functions that I&#8217;ve defined in api.php. So setting an error code is as simple as this (using LMSGetValue as an example):</p>
<pre class="brush:php; first-line: 1; html-script: false;">
function LMSGetValue(varname) {

  // not initialized or already finished
  if ((! flagInitialized) || (flagFinished)) {
    errorCode = '301';
    return '';
  }

  // otherwise, return the requested data
  errorCode = '0';
  return cache[varname];

}
</pre>
<p>You&#8217;ll see that I set &#8217;301&#8242; if (for some reason) the API hasn&#8217;t been initialized, and &#8217;0&#8242; if the call is successful. Obviously, there are a lot more tests and checks that I need to implement &#8211; for example, is the data element readable or not? And is it even supported by the API? I&#8217;ll get on to that later.</p>
<p>Next &#8211; setting up the API calls to handle the error code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/02/step-58-setting-and-storing-the-error-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Step 57 – Error Codes</title>
		<link>http://www.vsscorm.net/2011/09/02/step-57-error-codes/</link>
		<comments>http://www.vsscorm.net/2011/09/02/step-57-error-codes/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 19:47:56 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Run Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1627</guid>
		<description><![CDATA[The SCORM 1.2 Runtime Environment (RTE) uses a system of error codes that are set by the API, and which can be read by the SCO using three API functions: LMSGetLastError() LMSGetErrorString() LMSGetDiagnostic() I&#8217;ve already implemented &#8220;stubs&#8221; for these functions &#8230; <a href="http://www.vsscorm.net/2011/09/02/step-57-error-codes/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The SCORM 1.2 Runtime Environment (RTE) uses a system of error codes that are set by the API, and which can be read by the SCO using three API functions:</p>
<ul>
<li>LMSGetLastError()</li>
<li>LMSGetErrorString()</li>
<li>LMSGetDiagnostic()</li>
</ul>
<p>I&#8217;ve already implemented &#8220;stubs&#8221; for these functions in my api.php code as noted in <a href="http://www.vsscorm.net/2009/06/19/other-scorm-api-functions/">Step 10 &#8211; Other SCORM API Fuctions</a>. But, before I make these functions active, I need to set up the error codes and related messages in the API code. </p>
<p><span id="more-1627"></span></p>
<p>The error codes are all detailed in the <a href="http://www.vsscorm.net/docs/SCORM_1.2_RunTimeEnv.pdf" target="_blank">SCORM 1.2 Runtime Environment specification</a> &#8211; section 3.3.3. So, I&#8217;m going to set up a JavaScript object (which,having been brought up on perl and PHP, I tend to think of as an &#8216;associative array&#8217;) in the api.php code:</p>
<pre class="brush:php; first-line: 1; html-script: false;">
var errorMessages = new Object();
errorMessages['0'] = 'No Error';
errorMessages['101'] = 'General Exception';
errorMessages['201'] = 'Invalid Argument';
errorMessages['202'] = 'Element Cannot Have Children';
errorMessages['203'] = 'Element Not an Array - Cannot Have Children';
errorMessages['301'] = 'API Not Initialized';
errorMessages['401'] = 'Data Model Element Not Implemented';
errorMessages['402'] = 'Invalid Set Value - Element is a Keyword';
errorMessages['403'] = 'Invalid Set Value - Element is Read Only';
errorMessages['404'] = 'Invalid Get Value - Element is Write Only';
errorMessages['405'] = 'Invalid Set Value - Incorrect Data Type';
</pre>
<p>Why am I using strings e.g. &#8217;201&#8242; rather than numbers as indices? Because it&#8217;s one of the (many) idiosyncrasies of the SCORM standard!</p>
<p>Next time, setting and storing the error code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/02/step-57-error-codes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>After Some Time Off, Starting Up Again</title>
		<link>http://www.vsscorm.net/2011/09/02/after-some-time-off-starting-up-again/</link>
		<comments>http://www.vsscorm.net/2011/09/02/after-some-time-off-starting-up-again/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 19:09:17 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Admin & Notes]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1616</guid>
		<description><![CDATA[It&#8217;s been a while since I last posted to the VSSCORM blog which is both good news &#8211; the services that I&#8217;ve set up using the VSSCORM code have been running pretty successfully &#8211; and bad news &#8211; I haven&#8217;t &#8230; <a href="http://www.vsscorm.net/2011/09/02/after-some-time-off-starting-up-again/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I last posted to the VSSCORM blog which is both good news &#8211; the services that I&#8217;ve set up using the VSSCORM code have been running pretty successfully &#8211; and bad news &#8211; I haven&#8217;t been moving the development forward as quickly as I&#8217;d like.</p>
<p>Now, it&#8217;s time to start up again and tackle a couple of issues that I&#8217;ve been wanting to deal with:</p>
<ul>
<li>error codes and error messages;</li>
<li>a logging capability to help diagnose SCO to LMS communication problems.</li>
</ul>
<p>So, with that in mind, in my next post I&#8217;m going to start attacking the error codes and messages.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2011/09/02/after-some-time-off-starting-up-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 56 – 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>2</slash:comments>
		</item>
		<item>
		<title>Step 55 – 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>4</slash:comments>
		</item>
		<item>
		<title>Step 54 – 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>1</slash:comments>
		</item>
		<item>
		<title>Follow VSSCORM on Twitter</title>
		<link>http://www.vsscorm.net/2010/07/11/follow-vsscorm-on-twitter/</link>
		<comments>http://www.vsscorm.net/2010/07/11/follow-vsscorm-on-twitter/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 06:57:20 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[Admin & Notes]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1585</guid>
		<description><![CDATA[You can now follow the progress of VSSCORM on Twitter &#8211; search for username VSSCORM, or click on this link: http://twitter.com/VSSCORM]]></description>
			<content:encoded><![CDATA[<p>You can now follow the progress of VSSCORM on Twitter &#8211; search for username VSSCORM, or click on this link: <a href="http://twitter.com/VSSCORM" target="_blank">http://twitter.com/VSSCORM</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2010/07/11/follow-vsscorm-on-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

