<?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>VS SCORM</title>
	<atom:link href="http://www.vsscorm.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.vsscorm.net</link>
	<description>A Very Simple SCORM Interface</description>
	<lastBuildDate>Fri, 22 Jan 2010 21:23:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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[VS SCORM 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 sure that none of the API functions are processed after the session has been closed.
In [...]]]></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>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>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> flagFinished <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> flagInitiaized <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre></div></div>

<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>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSInitialize<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// already initialized or already finished</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>flagInitialized<span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>flagFinished<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;false&quot;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// set initialization flag</span>
  flagInitialized <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// return success value</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<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>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSFinish<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// not initialized or already finished</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span> flagInitialized<span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>flagFinished<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;false&quot;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
  ...
  ...
&nbsp;
  <span style="color: #006600; font-style: italic;">// set finish flag</span>
  flagFinished <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// return to calling program</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<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>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">  <span style="color: #006600; font-style: italic;">// not initialized or already finished</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span> flagInitialized<span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>flagFinished<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;false&quot;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<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>0</slash:comments>
		</item>
		<item>
		<title>Bug in VS SCORM 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[VS SCORM 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&#40;'cmi.score.raw'&#41;;

It should read:

$rawscore = readElement&#40;'cmi.core.score.raw'&#41;;

I&#8217;ll incorporate this fix in a new release of the RTE once I&#8217;ve made a few other improvements.
]]></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>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$rawscore</span> <span style="color: #339933;">=</span> readElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.score.raw'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>It should read:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$rawscore</span> <span style="color: #339933;">=</span> readElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.score.raw'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<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[Admin & Notes]]></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. It&#8217;s 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 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 [...]]]></description>
			<content:encoded><![CDATA[<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>If you want a <b>very</b> simple test case, you can use <a href="/docs/SimpleTest.zip">this content package</a>. It&#8217;s 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>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>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>
		<item>
		<title>Download VS SCORM 1.2 RTE Rev 2.0 (Caching Version)</title>
		<link>http://www.vsscorm.net/2009/12/02/download-vs-scorm-1-2-rte-rev-2-0-caching-version/</link>
		<comments>http://www.vsscorm.net/2009/12/02/download-vs-scorm-1-2-rte-rev-2-0-caching-version/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 18:32:32 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1207</guid>
		<description><![CDATA[Rev 2.0 of the VS SCORM RTE &#8211; the first version with client-side caching &#8211; is now available for you to download.



You can download the code bundle using this link.


&#160;
NOTES 
1. Installation and configuration information is included in the &#8216;install.txt&#8217; file in the code bundle. 
2. The utils/cleardb.php and utils/showdb.php files are both written for [...]]]></description>
			<content:encoded><![CDATA[<p>Rev 2.0 of the VS SCORM RTE &#8211; the first version with client-side caching &#8211; is now available for you to download.</p>
<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_0.zip">this link</a>.</td>
</tr>
</table>
<p>&nbsp;</center></p>
<p><i>NOTES </p>
<p>1. Installation and configuration information is included in the &#8216;install.txt&#8217; file in the code bundle. </p>
<p>2. The utils/cleardb.php and utils/showdb.php files are both written for use with MySQL. If you plan to use them, you may need to translate them to suit the database that you&#8217;re using.</p>
<p>3. As before, this is a technology demonstrator &#8211; not production-standard code &#8211; so please don&#8217;t blame me if you find bugs! You can let me know what you find using <a href="/contact/">the contact form</a> on this blog, or by posting a comment.</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/12/02/download-vs-scorm-1-2-rte-rev-2-0-caching-version/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Download VS SCORM 1.2 Manifest Reader Rev 1.1</title>
		<link>http://www.vsscorm.net/2009/11/30/download-vs-scorm-1-2-manifest-reader-rev-1-1/</link>
		<comments>http://www.vsscorm.net/2009/11/30/download-vs-scorm-1-2-manifest-reader-rev-1-1/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 00:26:05 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Manifest Reader]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1094</guid>
		<description><![CDATA[A reader has identified a problem with Rev 1.0 of the IMS Manifest File Reader which causes the parser to fail when there&#8217;s a resource that doesn&#8217;t have any files associated with it. Rev 1.1 corrects this bug. The only changes are to the resolveIMSManifestDependencies() function in subs.php, and deal with the case where $file [...]]]></description>
			<content:encoded><![CDATA[<p>A reader has identified a problem with Rev 1.0 of the IMS Manifest File Reader which causes the parser to fail when there&#8217;s a resource that doesn&#8217;t have any files associated with it. Rev 1.1 corrects this bug. The only changes are to the resolveIMSManifestDependencies() function in <b>subs.php</b>, and deal with the case where $file is not an array. </p>
<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_cam12_1_1.zip">this link</a>.</td>
</tr>
</table>
<p>&nbsp;</center></p>
<p>All other details &#8211; including system requirements &#8211; are the same as for <a href="/2009/11/07/download-vs-scorm-1-2-manifest-reader-rev-1-0/">Rev 1.0.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/30/download-vs-scorm-1-2-manifest-reader-rev-1-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 50 &#8211; Testing the Caching VSSCORM 1.2 RTE</title>
		<link>http://www.vsscorm.net/2009/11/30/step-50-testing-the-caching-vsscorm-1-2-rte/</link>
		<comments>http://www.vsscorm.net/2009/11/30/step-50-testing-the-caching-vsscorm-1-2-rte/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 20:44:54 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1084</guid>
		<description><![CDATA[Time to run a few tests. I start with the test case that I&#8217;ve been using since Step 3. Just to make sure that everything is working, I run it part-way through then close the window using the &#8216;x&#8217; at the top of the window to make sure that my LMSCommit() and LMSFinish() calls are [...]]]></description>
			<content:encoded><![CDATA[<p>Time to run a few tests. I start with the test case that I&#8217;ve been using since <a href="/2009/06/03/the-first-test/">Step 3</a>. Just to make sure that everything is working, I run it part-way through then close the window using the &#8216;x&#8217; at the top of the window to make sure that my LMSCommit() and LMSFinish() calls are operating as expected.</p>
<p><img src="http://www.vsscorm.net/wp-content/uploads/2009/06/testcourse.GIF" alt="The Test Course" title="The Test Course" width="691" height="562" class="aligncenter size-full wp-image-314" /></p>
<p>It works as I&#8217;d hoped. It&#8217;s difficult to gauge any speed improvements because of intentional (i.e. developer-programmed) time delays in the Flash file(s) while they&#8217;re displaying. The display time is also affected by server-side caching of files. But it would be fair to say that it seems slightly more responsive, especially when displaying the application simulation exercise. And, when I look at the database contents after closing the window, this is what I see:</p>
<p><center><br />
<table cellpadding=3 cellspacing=0 border=1>
<tr>
<td valign=top align=left nowrap><b>varName</b></td>
<td valign=top align=left><b>varValue</b></td>
</tr>
<tr>
<td valign=top align=left nowrap>adlcp:masteryscore</td>
<td valign=top align=left>0</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.credit</td>
<td valign=top align=left>credit</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.entry</td>
<td valign=top align=left>&nbsp;</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.exit</td>
<td valign=top align=left>&nbsp;</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.lesson_location</td>
<td valign=top align=left>3</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.lesson_status</td>
<td valign=top align=left>failed</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.score.raw</td>
<td valign=top align=left>25</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.score._children</td>
<td valign=top align=left>raw</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.session_time</td>
<td valign=top align=left>00:00:22</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.student_id</td>
<td valign=top align=left>007</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.student_name</td>
<td valign=top align=left>Addison, Steve</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core.total_time</td>
<td valign=top align=left>0000:00:22</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.core._children</td>
<td valign=top align=left>student_id,student_name,lesson_location, &#8230;</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.launch_data</td>
<td valign=top align=left>&nbsp;</td>
</tr>
<tr>
<td valign=top align=left nowrap>cmi.suspend_data</td>
<td valign=top align=left>D01BA000CA%7E%24VS%2AKcfuG110BBBB1 &#8230;</td>
</tr>
</table>
<p></center></p>
<p>Closing the window manually (rather than using an exit button in the course) has called LMSFinish() and triggered the <b>finish.php</b> code correctly, and things look as I&#8217;d expected.</p>
<p>Now I try the problem course that I mentioned in <a href="/2009/11/17/step-43-the-need-for-speed/">Step 43</a>. I can&#8217;t show you the course because it&#8217;s client-specific, but the speed improvement seems to be significant. Once again, it&#8217;s difficult to get an exact figure, but I&#8217;d say that page loads (including SCORM API calls by the SCO) were at least 2 to 3 times faster &#8211; perhaps even more.</p>
<p>Although not definitive, I think that&#8217;s fairly reassuring. Next time, I&#8217;ll post a copy of the code for you to play around with, and you can tell me if you see similar results.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/30/step-50-testing-the-caching-vsscorm-1-2-rte/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Step 49 &#8211; SCO Initialization</title>
		<link>http://www.vsscorm.net/2009/11/27/step-49-sco-initialization/</link>
		<comments>http://www.vsscorm.net/2009/11/27/step-49-sco-initialization/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 01:06:58 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1076</guid>
		<description><![CDATA[I&#8217;ve addressed handling of the LMSSetValue() and LMSGetValue(), LMSCommit(), and LMSFinish() calls. The remaining piece of the puzzle is to look at how the RTE is initialized.
In Rev 1 of the code, the course/SCO call to LMSInitialize() caused an AJAX request to be sent to the server where a script called initialize.php was executed. The [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve addressed handling of the LMSSetValue() and LMSGetValue(), LMSCommit(), and LMSFinish() calls. The remaining piece of the puzzle is to look at how the RTE is initialized.</p>
<p>In Rev 1 of the code, the course/SCO call to LMSInitialize() caused an AJAX request to be sent to the server where a script called <b>initialize.php</b> was executed. The one thing that this doesn&#8217;t do is to transfer all of the data element values from the database into the local cache. In theory, I could simply use one or more additional AJAX calls to transfer the data from the server to the local cache. But I think there&#8217;s a better way.</p>
<p>I&#8217;m going to start by modifying my <b>api.php</b> code by adding the following lines of code.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//  read database login information and connect</span>
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">&quot;config.php&quot;</span><span style="color: #339933;">;</span>
dbConnect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// initialize data elements in the database if they're not already set, and</span>
<span style="color: #666666; font-style: italic;">// dynamically create the javascript code to initialize the local cache</span>
<span style="color: #000088;">$initializeCache</span> <span style="color: #339933;">=</span> initializeSCO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Lines 2 and 3 load the database configuration information, and connect to the database. Then, line 7 calls a function in <b>subs.php</b> that will initialize the SCO. The value returned from the function is stored in a PHP variable called $initializeCache &#8211; I&#8217;ll talk about what it&#8217;s used for later.</p>
<p>Here&#8217;s my new initializeSCO() function in <b>subs.php</b>.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> initializeSCO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$link</span><span style="color: #339933;">;</span>
  <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$SCOInstanceID</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// has the SCO previously been initialized?</span>
  <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;select count(VarName) from scormvars where (SCOInstanceID=<span style="color: #006699; font-weight: bold;">$SCOInstanceID</span>)&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$count</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_row</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// not yet initialized - initialize all elements</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span> <span style="color: #000088;">$count</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// elements that tell the SCO which other elements are supported by this API</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core._children'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,exit,session_time'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.score._children'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'raw'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// student information</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.student_name'</span><span style="color: #339933;">,</span>getFromLMS<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.student_name'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.student_id'</span><span style="color: #339933;">,</span>getFromLMS<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.student_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// test score</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.score.raw'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'adlcp:masteryscore'</span><span style="color: #339933;">,</span>getFromLMS<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'adlcp:masteryscore'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// SCO launch and suspend data</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.launch_data'</span><span style="color: #339933;">,</span>getFromLMS<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.launch_data'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.suspend_data'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// progress and completion tracking</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.lesson_location'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.credit'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'credit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.lesson_status'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'not attempted'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.entry'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'ab initio'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.exit'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// seat time</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.total_time'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'0000:00:00'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    initializeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.session_time'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// new session so clear pre-existing session time</span>
  writeElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cmi.core.session_time'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// create the javascript code that will be used to set up the javascript cache, </span>
  <span style="color: #000088;">$initializeCache</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;var cache = new Object();<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;select VarName,VarValue from scormvars where (SCOInstanceID=<span style="color: #006699; font-weight: bold;">$SCOInstanceID</span>)&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">list</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$varname</span><span style="color: #339933;">,</span><span style="color: #000088;">$varvalue</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_row</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// make the value safe by escaping quotes and special characters</span>
    <span style="color: #000088;">$jvarvalue</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$varvalue</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// javascript to set the initial cache value</span>
    <span style="color: #000088;">$initializeCache</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;cache['<span style="color: #006699; font-weight: bold;">$varname</span>'] = '<span style="color: #006699; font-weight: bold;">$jvarvalue</span>';<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// return javascript for cache initialization to the calling program</span>
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$initializeCache</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Here&#8217;s how it breaks down &#8211; line-by-line:</p>
<ul>
<li><b>Lines 7 and 8</b> &#8211; I&#8217;m testing for whether this SCO has already been initialized in my LMS database table by counting the number of data elements corresponding to this SCOInstanceID.<br />&nbsp;
<li><b>Lines 11 through 40</b> &#8211; These lines are only executed if the SCO hasn&#8217;t yet been initialized. They&#8217;re pretty much the same as were in the <b>initialize.php</b> code in Rev 1, and they set the initial database values for all of the SCORM data elements that I&#8217;m supporting.<br />&nbsp;
<li><b>Line 43</b> &#8211; I clear any previous setting for the SCO session time data element.<br />&nbsp;
<li><b>Lines 46 through 57</b> &#8211; Here, I&#8217;m going to create a set of JavaScript statements that will initialize the local cache. Now, obviously, I can&#8217;t do this using directly from the <b>subs.php</b> code since that&#8217;s being executed on the server. But, I&#8217;ll save them into a PHP variable and return them to the calling program where they can be executed on the client side.<br />&nbsp;
</ul>
<p>So, when called, the initializeSCO() function sets up the initial database entries (if required) and then created the JavaScript initialization code. So, in <b>api.php</b>, I add the following.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">print</span> <span style="color: #000088;">$initializeCache</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>which, will result in the student&#8217;s browser seeing something like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> cache <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Object<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core._children'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,exit,session_time'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.score._children'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'raw'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.student_name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'Addison, Steve'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.student_id'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'007'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.score.raw'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'adlcp:masteryscore'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'0'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.launch_data'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.suspend_data'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.lesson_location'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.credit'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'credit'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.lesson_status'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'not attempted'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.entry'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'ab initio'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.exit'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.total_time'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'0000:00:00'</span><span style="color: #339933;">;</span>
cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.session_time'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>And, if you refer back to <a href="/2009/11/19/retracing-step-45-using-a-javascript-object-as-the-cache/">one of my earlier posts</a>, you&#8217;ll see that this creates the local cache as a JavaScript object containing the initial values from the database.</p>
<p>Finally, I can get rid of the LMSInitialize() code, and modified form of <b>api.php</b> now looks like this.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
&nbsp;
<span style="color: #666666; font-style: italic;">/* 
&nbsp;
VS SCORM - JavaScript SCORM 1.2 RTE API
Rev 4.0 - Friday, November 27, 2009
Copyright (C) 2009, Addison Robson LLC
&nbsp;
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.
&nbsp;
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.
&nbsp;
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.
&nbsp;
*/</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//  essential functions</span>
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">&quot;subs.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// input data</span>
<span style="color: #000088;">$SCOInstanceID</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'SCOInstanceID'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//  read database login information and connect</span>
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">&quot;config.php&quot;</span><span style="color: #339933;">;</span>
dbConnect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// initialize data elements in the database if they're not already set, and</span>
<span style="color: #666666; font-style: italic;">// dynamically create the javascript code to initialize the local cache</span>
<span style="color: #000088;">$initializeCache</span> <span style="color: #339933;">=</span> initializeSCO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span>
<span style="color: #339933;">&lt;</span>html<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>head<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>title<span style="color: #339933;">&gt;&lt;/</span>title<span style="color: #339933;">&gt;</span>
<span style="color: #000000; font-weight: bold;">&lt;script language</span><span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;javascript&quot;</span><span style="color: #339933;">&gt;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #666666; font-style: italic;">//   Status Flags</span>
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">var</span> flagFinished <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #666666; font-style: italic;">//   SCO Data Cache - Initialization</span>
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">print</span> <span style="color: #000088;">$initializeCache</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #666666; font-style: italic;">//   SCORM RTE Functions - Initialization</span>
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">function</span> LMSInitialize<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">&quot;true&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #666666; font-style: italic;">//   SCORM RTE Functions - Getting and Setting Values</span>
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">function</span> LMSGetValue<span style="color: #009900;">&#40;</span>varname<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">return</span> cache<span style="color: #009900;">&#91;</span>varname<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> LMSSetValue<span style="color: #009900;">&#40;</span>varname<span style="color: #339933;">,</span>varvalue<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  cache<span style="color: #009900;">&#91;</span>varname<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> varvalue<span style="color: #339933;">;</span>
  <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">&quot;true&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #666666; font-style: italic;">//   SCORM RTE Functions - Saving the Cache to the Database</span>
<span style="color: #666666; font-style: italic;">// ------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">function</span> LMSCommit<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// create request object</span>
  <span style="color: #000000; font-weight: bold;">var</span> req <span style="color: #339933;">=</span> createRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// code to prevent caching</span>
  <span style="color: #000000; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #990000;">Date</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// set up request parameters - uses POST method</span>
  req<span style="color: #339933;">.</span>open<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'POST'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'commit.php'</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// create a POST-formatted list of cached data elements </span>
  <span style="color: #666666; font-style: italic;">// include only SCO-writeable data elements</span>
  <span style="color: #000000; font-weight: bold;">var</span> params <span style="color: #339933;">=</span> <span style="color: #0000ff;">'SCOInstanceID=&lt;?php print $SCOInstanceID; ?&gt;</span>&amp;code='+d.getTime();
  params += &quot;&amp;data[cmi.core.lesson_location]=&quot;+urlencode(cache['cmi.core.lesson_location']);
  params += &quot;&amp;data[cmi.core.lesson_status]=&quot;+urlencode(cache['cmi.core.lesson_status']);
  params += &quot;&amp;data[cmi.core.exit]=&quot;+urlencode(cache['cmi.core.exit']);
  params += &quot;&amp;data[cmi.core.session_time]=&quot;+urlencode(cache['cmi.core.session_time']);
  params += &quot;&amp;data[cmi.core.score.raw]=&quot;+urlencode(cache['cmi.core.score.raw']);
  params += &quot;&amp;data[cmi.suspend_data]=&quot;+urlencode(cache['cmi.suspend_data']);
&nbsp;
  // request headers
  req.setRequestHeader(&quot;Content-type&quot;, &quot;application/x-www-form-urlencoded&quot;);
  req.setRequestHeader(&quot;Content-length&quot;, params.length);
  req.setRequestHeader(&quot;Connection&quot;, &quot;close&quot;);
&nbsp;
  // submit to the server for processing
  req.send(params);
&nbsp;
  // process returned data - error condition
  if (req.status != 200) {
    alert('Problem with AJAX Request in LMSCommit()');
    return &quot;false&quot;;
  }
&nbsp;
  // process returned data - OK
  else {
    return &quot;true&quot;;
  }
&nbsp;
}
&nbsp;
// ------------------------------------------
//   SCORM RTE Functions - Closing The Session
// ------------------------------------------
function LMSFinish(dummyString) {
&nbsp;
  // already finished - prevent repeat call
  if (flagFinished) {
    return &quot;true&quot;;
  }
&nbsp;
  // commit cached values to the database
  LMSCommit('');
&nbsp;
  // create request object
  var req = createRequest();
&nbsp;
  // code to prevent caching
  var d = new Date();
&nbsp;
  // set up request parameters - uses GET method
  req.open('GET','finish.php?SCOInstanceID=<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">print</span> <span style="color: #000088;">$SCOInstanceID</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&amp;code='+d.getTime(),false);
&nbsp;
  // submit to the server for processing
  req.send(null);
&nbsp;
  // process returned data - error condition
  if (req.status != 200) {
    alert('Problem with AJAX Request in LMSFinish()');
    return &quot;&quot;;
  }
&nbsp;
  // set finish flag
  flagFinished = true;
&nbsp;
  // return to calling program
  return &quot;true&quot;;
&nbsp;
}
&nbsp;
// ------------------------------------------
//   SCORM RTE Functions - Error Handling
// ------------------------------------------
function LMSGetLastError() {
  return 0;
}
&nbsp;
function LMSGetDiagnostic(errorCode) {
  return &quot;diagnostic string&quot;;
}
&nbsp;
function LMSGetErrorString(errorCode) {
  return &quot;error string&quot;;
}
&nbsp;
// ------------------------------------------
//   AJAX Request Handling
// ------------------------------------------
function createRequest() {
&nbsp;
  ...
  ...
  ...
&nbsp;
}
&nbsp;
// ------------------------------------------
//   URL Encoding
// ------------------------------------------
function urlencode( str ) {
&nbsp;
  ...
  ...
  ...
&nbsp;
}
&nbsp;
&lt;/script&gt;
&nbsp;
&lt;/head&gt;
&lt;body&gt;
&nbsp;
&amp;nbsp;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Note that I&#8217;ve omitted the code for the createRequest() and urlencode() functions for clarity.</p>
<p>Next step &#8211; give it a trial run and see what happens.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/27/step-49-sco-initialization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 48 &#8211; LMSFinish(), and Unexpected Closure</title>
		<link>http://www.vsscorm.net/2009/11/25/step-48-lmsfinish-and-unexpected-closure/</link>
		<comments>http://www.vsscorm.net/2009/11/25/step-48-lmsfinish-and-unexpected-closure/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 15:49:10 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1024</guid>
		<description><![CDATA[In theory, the way that I handle the LMSFinish() API call should be pretty much the same as for Rev 1 of my code. I simply generate an AJAX request to the server which runs a PHP script that carries out a series of actions on the data elements stored in the LMS database (persistent [...]]]></description>
			<content:encoded><![CDATA[<p>In theory, the way that I handle the LMSFinish() API call should be pretty much the same as for Rev 1 of my code. I simply generate an AJAX request to the server which runs a PHP script that carries out a series of actions on the data elements stored in the LMS database (persistent storage). But the use of the cache introduces some wrinkles.</p>
<p><b>Wrinkle #1: LMSCommit() Not Called Before LMSFinish()</b></p>
<p>In Rev 1 of the code, all API calls were carried out immediately they were invoked which meant that the LMS database was always up-to-date with the information being set by the course. Therefore, when the course called LMSFinish(), I knew that I was operating on up-to-date values for each of the data elements.</p>
<p>In Rev 2 of the code, values of the data elements are cached in the students&#8217; browsers until the course developer chooses to invoke the LMSCommit() API call. A smart course developer will do this relatively often &#8211; certainly after any major change in the values of the data elements. However, I can&#8217;t rely on all courses being developed by smart developers. So I need to add a call to LMSCommit() to the top of my LMSFinish() API code to ensure that it&#8217;s going to be operating on the final set of data values:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSFinish<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// commit cached values to the database</span>
  LMSCommit<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  ...</pre></div></div>

<p>That&#8217;s straightforward enough.</p>
<p><b>Wrinkle #2: Course Window May Be Closed Unexpectedly</b></p>
<p>While it would be nice to think that students will always use the navigation buttons that the developer provides in his/her course, you and I know that this isn&#8217;t going to happen. Students will sometimes choose to close the course window by clicking on the &#8216;x&#8217; at the top of the window.</p>
<p>OK &#8211; technically, this wrinkle existed in Rev 1 of the code as well, but I just didn&#8217;t worry about it as much since I knew that the database would always have an up-to-date copy of the data element values, and thus the course would be able to re-start fairly easily. To handle this with my caching version of the API, I have to make sure that the course invokes LMSFinish() when the browser window is closed for any reason.</p>
<p>In theory, the course developer should try to handle this. As Claude Ostyn says on page 9 of <a href="http://www.scorm.com/wp-content/assets/cookbook/CookingUpASCORM_v1_2.pdf" target="_blank">his SCORM Cookbook</a> (with my emphasis):</p>
<blockquote><p>To ensure that LMSFinish will be called even if the SCO is unloaded expectedly, <b>a properly initialized SCO</b> should be coded to call LMSFinish at the following times, and under the following circumstances:</p>
<ul>
<li>When it no longer needs to communicate with the runtime service. For example, when the user clicks a &#8220;submit&#8221; button at the end of a test and the user will not be allowed to change responses, a SCO may upload the results of the test with LMSSetValue, then call LMSFinish.<br />&nbsp;</li>
<li>If LMSFinish has not been called successfully yet, when an onbeforeunload browser event is processed (typically, this will only happen if the browser is Internet Explorer).<br />&nbsp;</li>
<li>If LMSFinish has not been called successfully yet, when an onunload browser event is processed.<br />&nbsp;</li>
</ul>
</blockquote>
<p>However, I can&#8217;t rely on course developers always being responsible. So I can help myself out by modifying my <b>rte.php</b> code like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;VS SCORM&lt;/title&gt;
&lt;/head&gt;
&lt;frameset frameborder=&quot;0&quot; framespacing=&quot;0&quot; border=&quot;0&quot; rows=&quot;50,*&quot; cols=&quot;*&quot; 
            onbeforeunload=&quot;API.LMSFinish('');&quot; onunload=&quot;API.LMSFinish('');&quot;&gt;
  &lt;frame src=&quot;api.php?SCOInstanceID=<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">print</span> <span style="color: #000088;">$SCOInstanceID</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; name=&quot;API&quot; noresize&gt;
  &lt;frame src=&quot;../course/index.html&quot; name=&quot;course&quot;&gt;
&lt;/frameset&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>In the frameset tag, you&#8217;ll see that I&#8217;ve added an onunload() action, and an onbeforeunload() action. In each case, the action calls LMSFinish() to try to make sure that everything is nicely wrapped-up should the student close the course/SCO window in some way other than using the course/SCO navigation buttons.</p>
<p>Why both onbeforeunload() and onunload()? It&#8217;s difficult to find a definitive statement on the Internet but, according to what I&#8217;ve read, it seems that onbeforeunload() is a Microsoft extension that&#8217;s supported in Internet Explorer, and in recent versions of other browsers (Safari, FireFox). However, Opera doesn&#8217;t support it (please let me know if I&#8217;m wrong), and I&#8217;m not sure about Chrome. So, by using both onbeforeunload() and onunload(), I have a pretty good chance of one or both of them being triggered by the frameset closing.</p>
<p><b>Wrinkle #3: Multiple Calls to LMSFinish()</b></p>
<p>The solution to wrinkle #2 causes another wrinkle. It&#8217;s now possible that LMSFinish() could be called more than once. The SCORM 1.2 RTE specification is clear about this &#8211; LMSFinish() should be called once, and only once, at the end of the course/SCO session.</p>
<p>To handle this, I&#8217;m going to introduce a JavaScript variable into <b>api.php</b> to act as a &#8216;flag&#8217;:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> flagFinished <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span></pre></div></div>

<p>Initially set to &#8216;false&#8217;, I&#8217;m going to make sure that, when called, LMSFinish() &#8230;</p>
<ol>
<li>Tests to see if flagFinished is set to &#8216;true&#8217; and, if so, aborts processing.
<li>If flagFinished is set to &#8216;false&#8217;, processes the data element values as usual.
<li>Sets flagFinished to &#8216;true&#8217; before exiting.
</ol>
<p>In the next section, I&#8217;ll show you how I do that.</p>
<p><b>So, What Does The Code Look Like?</b></p>
<p>Even including all of the changes I&#8217;ve outlined above, the basic form of the LMSFinish() API function in <b>api.php</b> is little changed from <a href="/2009/08/10/step-26-getting-data-from-the-lms/">my previous version</a>. It looks like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSFinish<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// already finished - prevent repeat call</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>flagFinished<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// commit cached values to the database</span>
  LMSCommit<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// create request object</span>
  <span style="color: #003366; font-weight: bold;">var</span> req <span style="color: #339933;">=</span> createRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// code to prevent caching</span>
  <span style="color: #003366; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// set up request parameters - uses GET method</span>
  req.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'GET'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'finish.php?SCOInstanceID=&lt;?php print $SCOInstanceID; ?&gt;&amp;code='</span><span style="color: #339933;">+</span>d.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// submit to the server for processing</span>
  req.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// process returned data - error condition</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #000066;">status</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Problem with AJAX Request in LMSFinish()'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// set finish flag</span>
  flagFinished <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// return to calling program</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The differences from the Rev 1 code are as follows:</p>
<ul>
<li><b>Lines 4 through 6</b> &#8211; I&#8217;m going to check the JavaScript variable &#8216;flagFinshed&#8217; in <b>api.php</b> to see if LMSFinish() has previously been called. If so, it aborts processing.<br />&nbsp;</li>
<li><b>Line 9</b> &#8211; Calls LMSCommit() to make sure that all data element values have been transferred to the LMS database before I invoke the <b>finish.php</b> code, and the course closes.<br />&nbsp;</li>
<li><b>Line 30</b> &#8211; I set the flag to show that I&#8217;ve successfully finished the LMSFinish() process, and that communication between the SCO and the LMS is now closed.<br />&nbsp;</li>
</ul>
<p>That was a fairly complex topic with a relatively simple resolution. Next time, I&#8217;ll look at the other end of the course/SCO session &#8211; initialization.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/25/step-48-lmsfinish-and-unexpected-closure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 47 &#8211; LMSCommit()</title>
		<link>http://www.vsscorm.net/2009/11/23/step-47-lmscommit/</link>
		<comments>http://www.vsscorm.net/2009/11/23/step-47-lmscommit/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 14:14:17 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1017</guid>
		<description><![CDATA[The LMSCommit() API call is a little more complicated, but it bears a strong resemblence to the way that I handled LMSSetValue() in Rev 1 of the code &#8211; see this post for more details. What I&#8217;m going to do is to create a POST request and submit it to the server. But, where the [...]]]></description>
			<content:encoded><![CDATA[<p>The LMSCommit() API call is a little more complicated, but it bears a strong resemblence to the way that I handled LMSSetValue() in Rev 1 of the code &#8211; see <a href="/2009/06/14/the-lmssetvalue-function/">this post</a> for more details. What I&#8217;m going to do is to create a POST request and submit it to the server. But, where the old LMSSetValue() code only passed one variable value across, here I&#8217;m going to be passing all of the SCO-writeable data element values.</p>
<p>Here&#8217;s the JavaScript code that will be included in the <b>api.php</b> file:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSCommit<span style="color: #009900;">&#40;</span>dummyString<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// create request object</span>
  <span style="color: #003366; font-weight: bold;">var</span> req <span style="color: #339933;">=</span> createRequest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// code to prevent caching</span>
  <span style="color: #003366; font-weight: bold;">var</span> d <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// set up request parameters - uses POST method</span>
  req.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'POST'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'commit.php'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// create a POST-formatted list of cached data elements </span>
  <span style="color: #006600; font-style: italic;">// include only SCO-writeable data elements</span>
  <span style="color: #003366; font-weight: bold;">var</span> params <span style="color: #339933;">=</span> <span style="color: #3366CC;">'SCOInstanceID=&lt;?php print $SCOInstanceID; ?&gt;&amp;code='</span><span style="color: #339933;">+</span>d.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.core.lesson_location]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.lesson_location'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.core.lesson_status]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.lesson_status'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.core.exit]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.exit'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.core.session_time]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.session_time'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.core.score.raw]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.core.score.raw'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  params <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;&amp;data[cmi.suspend_data]=&quot;</span><span style="color: #339933;">+</span>urlencode<span style="color: #009900;">&#40;</span>cache<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'cmi.suspend_data'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// request headers</span>
  req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Content-type&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;application/x-www-form-urlencoded&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Content-length&quot;</span><span style="color: #339933;">,</span> params.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Connection&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;close&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// submit to the server for processing</span>
  req.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span>params<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// process returned data - error condition</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #000066;">status</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">200</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Problem with AJAX Request in LMSCommit()'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;false&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// process returned data - OK</span>
  <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Line-by-line:</p>
<ul>
<li><strong>Line 4</strong> &#8211; Sets up an AJAX request object.<br />&nbsp;
<li><strong>Line 7</strong> &#8211; Creates a date object that I&#8217;ll use to make sure that the server treats this as a new request, and doesn&#8217;t cache it.<br />&nbsp;
<li><strong>Line 10</strong> &#8211; I&#8217;m going to send this AJAX request to a new file called <b>commit.php</b>, and it&#8217;s going to include POST data rather than GET data because I don&#8217;t know whether or not it would be small enough to pass as GET data. As before, the third parameter is set to &#8216;false&#8217; so the request is treated as synchronous &#8211; the JavaScript will wait for it to return a response.<br />&nbsp;
<li><strong>Lines 14 through 20</strong> &#8211; I&#8217;m creating a JavaScript variable called &#8216;params&#8217; which will hold (temporarily) all of the data that I&#8217;m going to transfer.<br />&nbsp;
<ul>
<li>The first two variables &#8211; <b>SCOInstanceID</b> and <b>code</b> &#8211; should be familiar from my previous work.<br />&nbsp;
<li>The subsequent variables are transferring the data from the cache to <b>commit.php</b> as an associative array where the keys are the data element names. Note that I&#8217;m only transferring a subset of the data from the cache &#8211; these are the data elements that are SCO-writeable &#8211; see <a href="/2009/08/05/step-25-review-table-of-mandatory-data-elements/">this post</a> if you need a reminder.
</ul>
<p>&nbsp;</p>
<li><strong>Lines 23 through 25</strong> &#8211; I set up the request headers that will be sent to the LMS server to tell it that POST data is being submitted.<br />&nbsp;
<li><strong>Line 28</strong> &#8211; I submit the request to the server along with the data to be stored in the LMS database.<br />&nbsp;
</ul>
<p>Now to put together the code that will handle things at the server end of things. This is going to be a new file called <b>commit.php</b>.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> 
&nbsp;
<span style="color: #666666; font-style: italic;">/*
&nbsp;
VS SCORM - commit.php
Rev 1.0 - Thursday, November 19, 2009
Copyright (C) 2009, Addison Robson LLC
&nbsp;
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.
&nbsp;
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.
&nbsp;
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.
&nbsp;
*/</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//  essential functions</span>
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">&quot;subs.php&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//  read database login information and connect</span>
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">&quot;config.php&quot;</span><span style="color: #339933;">;</span>
dbConnect<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// read SCOInstanceID</span>
<span style="color: #000088;">$SCOInstanceID</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'SCOInstanceID'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_REQUEST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'data'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span> <span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// iterate through the data elements</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$varname</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$varvalue</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// save data to the 'scormvars' table</span>
  writeElement<span style="color: #009900;">&#40;</span><span style="color: #000088;">$varname</span><span style="color: #339933;">,</span><span style="color: #000088;">$varvalue</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// return value to the calling program</span>
<span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;true&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>Again, line-by-line:</p>
<ul>
<li><strong>Lines 34 to 36</strong> &#8211; Read the data that&#8217;s been passed to the script. Note that, in line 36, I make sure that the &#8216;data&#8217; variable is handled as an array &#8211; probably superfluous, but may as well make sure!<br />&nbsp;
<li><strong>Lines 39 through 44</strong> &#8211; I loop through the $data array and update the values stored in the LMS database using the writeElement() function that&#8217;s in subs.php. <br />&nbsp;
</ul>
<p>And that&#8217;s it. Next time &#8211; LMSFinish() and some of the issues that arise from the student closing the window unexpectedly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/23/step-47-lmscommit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Step 46 &#8211; Making LMSSetValue() and LMSGetValue() Talk to the Cache</title>
		<link>http://www.vsscorm.net/2009/11/20/step-46-making-lmssetvalue-and-lmsgetvalue-talk-to-the-cache/</link>
		<comments>http://www.vsscorm.net/2009/11/20/step-46-making-lmssetvalue-and-lmsgetvalue-talk-to-the-cache/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 14:29:08 +0000</pubDate>
		<dc:creator>Steve Addison</dc:creator>
				<category><![CDATA[VS SCORM Run-Time Environment]]></category>

		<guid isPermaLink="false">http://www.vsscorm.net/?p=1002</guid>
		<description><![CDATA[Unless I&#8217;m missing something obvious, reading from and writing to the cache is pretty simple &#8211; certainly a lot simpler than the AJAX calls that I was having to make!

function LMSGetValue&#40;varname&#41; &#123;
  return cache&#91;varname&#93;;
&#125;
&#160;
function LMSSetValue&#40;varname,varvalue&#41; &#123;
  cache&#91;varname&#93; = varvalue;
  return &#34;true&#34;;
&#125;

Much less stressful than I&#8217;d anticipated. Next time, something a little more [...]]]></description>
			<content:encoded><![CDATA[<p>Unless I&#8217;m missing something obvious, reading from and writing to the cache is pretty simple &#8211; certainly a lot simpler than the AJAX calls that I was having to make!</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> LMSGetValue<span style="color: #009900;">&#40;</span>varname<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">return</span> cache<span style="color: #009900;">&#91;</span>varname<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> LMSSetValue<span style="color: #009900;">&#40;</span>varname<span style="color: #339933;">,</span>varvalue<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  cache<span style="color: #009900;">&#91;</span>varname<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> varvalue<span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;true&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Much less stressful than I&#8217;d anticipated. Next time, something a little more complicated &#8211; handling LMSCommit().</p>
]]></content:encoded>
			<wfw:commentRss>http://www.vsscorm.net/2009/11/20/step-46-making-lmssetvalue-and-lmsgetvalue-talk-to-the-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
