]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-7097 - API debug. Add ability to manually poke the SCORM API for 1.2 and 2004.
authorpiers <piers>
Mon, 15 Sep 2008 19:56:36 +0000 (19:56 +0000)
committerpiers <piers>
Mon, 15 Sep 2008 19:56:36 +0000 (19:56 +0000)
mod/scorm/datamodels/debug.js.php

index e8a64730ad6b15124a19e69c7424c647c7b42df8..c0282b5dca73000530cd0395c8eee7cd84cde90c 100644 (file)
@@ -58,8 +58,142 @@ function toggleLog () {
 var logString = "";
 var logRow = 0;
 var logPopUpWindow = "N";
+var debugSCORMVersion = '<?php echo $scorm->version; ?>';
+<?php 
+   $LMS_prefix = $scorm->version == 'scorm_12' ? 'LMS' : '';
+   $LMS_api = $scorm->version == 'scorm_12' ? 'API' : 'API_1484_11';
+   
+   $LMS_elements = array();
+   if ($scorm->version == 'scorm_12') {
+       $LMS_elements = array(   'cmi.core._children',
+                                'cmi.core.student_id',
+                                'cmi.core.student_name',
+                                'cmi.core.lesson_location',
+                                'cmi.core.credit',
+                                'cmi.core.lesson_status',
+                                'cmi.core.entry',
+                                'cmi.core._children',
+                                'cmi.core.score.raw',
+                                'cmi.core.score.max',
+                                'cmi.core.score.min',
+                                'cmi.core.total_time',
+                                'cmi.core.lesson_mode',
+                                'cmi.core.exit',
+                                'cmi.core.session_time',
+                                'cmi.suspend_data',
+                                'cmi.launch_data',
+                                'cmi.comments',
+                                'cmi.comments_from_lms',
+                                'cmi.objectives._count',
+                                'cmi.objectives._children',
+                                'cmi.objectives.n.id',
+                                'cmi.objectives.n.score._children',
+                                'cmi.objectives.n.score.raw',
+                                'cmi.objectives.n.score.min',
+                                'cmi.objectives.n.score.max',
+                                'cmi.objectives.n.status',
+                                'cmi.student_data._children',
+                                'cmi.student_data.mastery_score',
+                                'cmi.student_data.max_time_allowed',
+                                'cmi.student_data.time_limit_action',
+                                'cmi.student_preference._children',
+                                'cmi.student_preference.audio',
+                                'cmi.student_preference.language',
+                                'cmi.student_preference.speed',
+                                'cmi.student_preference.text',
+                                'cmi.interactions._children',
+                                'cmi.interactions._count',
+                                'cmi.interactions.n.id',
+                                'cmi.interactions.n.objectives._count',
+                                'cmi.interactions.n.objectives.m.id',
+                                'cmi.interactions.n.time',
+                                'cmi.interactions.n.type',
+                                'cmi.interactions.n.correct_responses._count',
+                                'cmi.interactions.n.correct_responses.m.pattern',
+                                'cmi.interactions.n.weighting',
+                                'cmi.interactions.n.student_response',
+                                'cmi.interactions.n.result',
+                                'cmi.interactions.n.latency');
+   } else {
+       $LMS_elements = array(   'cmi._children',
+                                'cmi._version',
+                                'cmi.learner_id',
+                                'cmi.learner_name',
+                                'cmi.location',
+                                'cmi.completion_status',
+                                'cmi.completion_threshold',
+                                'cmi.scaled_passing_score',
+                                'cmi.progressive_measure',
+                                'cmi.score._children',
+                                'cmi.score.raw',
+                                'cmi.score.max',
+                                'cmi.score.min',
+                                'cmi.score.scaled',
+                                'cmi.total_time',
+                                'cmi.time_limit_action',
+                                'cmi.max_time_allowed',
+                                'cmi.session_time',
+                                'cmi.success_status',
+                                'cmi.lesson_mode',
+                                'cmi.entry',
+                                'cmi.exit',
+                                'cmi.credit',
+                                'cmi.mode',
+                                'cmi.suspend_data',
+                                'cmi.launch_data',
+                                'cmi.comments',
+                                'cmi.comments_from_lms._children',
+                                'cmi.comments_from_lms._count',
+                                'cmi.comments_from_lms.n.comment',
+                                'cmi.comments_from_lms.n.location',
+                                'cmi.comments_from_lms.n.timestamp',
+                                'cmi.comments_from_learner._children',
+                                'cmi.comments_from_learner._count',
+                                'cmi.comments_from_learner.n.comment',
+                                'cmi.comments_from_learner.n.location',
+                                'cmi.comments_from_learner.n.timestamp',
+                                'cmi.objectives._count',
+                                'cmi.objectives._children',
+                                'cmi.objectives.n.id',
+                                'cmi.objectives.n.score._children',
+                                'cmi.objectives.n.score.raw',
+                                'cmi.objectives.n.score.min',
+                                'cmi.objectives.n.score.max',
+                                'cmi.objectives.n.score.scaled',
+                                'cmi.objectives.n.success_status',
+                                'cmi.objectives.n.completion_status',
+                                'cmi.objectives.n.progress_measure',
+                                'cmi.objectives.n.description',
+                                'cmi.student_data._children',
+                                'cmi.student_data.mastery_score',
+                                'cmi.student_data.max_time_allowed',
+                                'cmi.student_data.time_limit_action',
+                                'cmi.student_preference._children',
+                                'cmi.student_preference.audio',
+                                'cmi.student_preference.language',
+                                'cmi.student_preference.speed',
+                                'cmi.student_preference.text',
+                                'cmi.interactions._children',
+                                'cmi.interactions._count',
+                                'cmi.interactions.n.id',
+                                'cmi.interactions.n.objectives._count',
+                                'cmi.interactions.n.objectives.m.id',
+                                'cmi.interactions.n.time',
+                                'cmi.interactions.n.type',
+                                'cmi.interactions.n.correct_responses._count',
+                                'cmi.interactions.n.correct_responses.m.pattern',
+                                'cmi.interactions.n.weighting',
+                                'cmi.interactions.n.learner_response',
+                                'cmi.interactions.n.result',
+                                'cmi.interactions.n.latency',
+                                'cmi.interactions.n.description',
+                                'adl.nav.request');
+   }
+?>
 
 // add each entry to the log, or setup the log pane first time round
+// The code written into the header is based on the ADL test suite API interaction code
+// and various examples of test wrappers out in the community
 function UpdateLog(s) {
     var s1 = '<html><head><style>\n'
         + 'body {font-family: Arial, Helvetica, Sans-Serif;font-size: xx-small;'
@@ -68,9 +202,446 @@ function UpdateLog(s) {
         + '.even {background-color: ffffff; width: 100%;}\n'
         + '.odd {background-color: e8f2fe; width: 100%;}\n'
         + '.error {background-color: ffffff; color: red; width: 100%;}\n'
-        + '<\/style><\/head><body STYLE="background-color: ffffff; color: black"'
+        + '<\/style>'
+        + '<script>\n'
+        + 'var LMSVersion = \'<?php echo $scorm->version; ?>\';\n'
+        + ' \n'
+        + 'function checkLMSVersion() {  \n'
+        + '    if (this.document.body.childNodes.length > 0) { \n'
+        + '        if (this.document.body.lastChild.id == LMSVersion) { \n'
+        + '            return true; \n'
+        + '        } \n'
+        + '    }; \n'
+        + '    alert(\'LMS Version: \' + this.document.body.lastChild.id + \n'
+        + '          \' does not equal: \' + LMSVersion +  \n'
+        + '          \' so API calls will fail - did navigate to another SCORM package?\'); \n'
+        + '    return false; \n'
+        + '} \n'
+        + ' \n'
+        + 'var saveElement = ""; \n'
+        + 'function setAPIValue() {  \n'
+        + '  document.elemForm.API_ELEMENT.value = document.elemForm.ELEMENT_LIST.value; \n'
+        + '  saveElement = document.elemForm.API_ELEMENT.value; \n'
+        + '} \n'
+        + '  \n'
+        + 'var _Debug = false;  // set this to false to turn debugging off  \n'
+        + '  \n'
+        + '// Define exception/error codes  \n'
+        + 'var _NoError = 0;  \n'
+        + 'var _GeneralException = 101;  \n'
+        + 'var _ServerBusy = 102;  \n'
+        + 'var _InvalidArgumentError = 201;  \n'
+        + 'var _ElementCannotHaveChildren = 202;  \n'
+        + 'var _ElementIsNotAnArray = 203;  \n'
+        + 'var _NotInitialized = 301;  \n'
+        + 'var _NotImplementedError = 401;  \n'
+        + 'var _InvalidSetValue = 402;  \n'
+        + 'var _ElementIsReadOnly = 403;  \n'
+        + 'var _ElementIsWriteOnly = 404;  \n'
+        + 'var _IncorrectDataType = 405;  \n'
+        + '  \n'
+        + '// local variable definitions  \n'
+        + 'var apiHandle = null;  \n'
+        + 'var API = null;  \n'
+        + 'var findAPITries = 0;  \n'
+        + '  \n'
+        + '  \n'
+        + 'function doLMSInitialize() { \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSInitialize was not successful.");  \n'
+        + '      return "false";  \n'
+        + '   }  \n'
+        + '   var result = api.<?echo $LMS_prefix; ?>Initialize("");  \n'
+        + '   if (result.toString() != "true") {  \n'
+        + '      var err = ErrorHandler();  \n'
+        + '   }  \n'
+        + '   return result.toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSFinish() {  \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSFinish was not successful.");  \n'
+        + '      return "false";  \n'
+        + '   } else {  \n'
+        + '      // call the LMSFinish function that should be implemented by the API  \n'
+        + '      var result = api.<?echo $LMS_prefix; ?>Finish("");  \n'
+        + '      if (result.toString() != "true") {  \n'
+        + '         var err = ErrorHandler();  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '   return result.toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSTerminate() {  \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nTerminate was not successful.");  \n'
+        + '      return "false";  \n'
+        + '   } else {  \n'
+        + '      // call the Terminate function that should be implemented by the API  \n'
+        + '      var result = api.Terminate("");  \n'
+        + '      if (result.toString() != "true") {  \n'
+        + '         var err = ErrorHandler();  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '   return result.toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSGetValue(name) {  \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetValue was not successful.");  \n'
+        + '      return "";  \n'
+        + '   } else {  \n'
+        + '      var value = api.<?echo $LMS_prefix; ?>GetValue(name);  \n'
+        + '      var errCode = api.<?echo $LMS_prefix; ?>GetLastError().toString();  \n'
+        + '      if (errCode != _NoError) {  \n'
+        + '         // an error was encountered so display the error description  \n'
+        + '         var errDescription = api.<?echo $LMS_prefix; ?>GetErrorString(errCode);  \n'
+        + '         alert("<?echo $LMS_prefix; ?>GetValue("+name+") failed. \\n"+ errDescription);  \n'
+        + '         return "";  \n'
+        + '      } else {  \n'
+        + '         return value.toString();  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSSetValue(name, value) {  \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSSetValue was not successful.");  \n'
+        + '      return;  \n'
+        + '   } else {  \n'
+        + '      var result = api.<?echo $LMS_prefix; ?>SetValue(name, value);  \n'
+        + '      if (result.toString() != "true") {  \n'
+        + '         var err = ErrorHandler();  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '   return;  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSCommit() {  \n'
+        + '   checkLMSVersion(); \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSCommit was not successful.");  \n'
+        + '      return "false";  \n'
+        + '   } else {  \n'
+        + '      var result = api.<?echo $LMS_prefix; ?>Commit("");  \n'
+        + '      if (result != "true") {  \n'
+        + '         var err = ErrorHandler();  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '   return result.toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSGetLastError() {  \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetLastError was not successful.");  \n'
+        + '      //since we can\'t get the error code from the LMS, return a general error  \n'
+        + '      return _GeneralError;  \n'
+        + '   }  \n'
+        + '   return api.<?echo $LMS_prefix; ?>GetLastError().toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSGetErrorString(errorCode) {  \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetErrorString was not successful.");  \n'
+        + '   }  \n'
+        + '   return api.<?echo $LMS_prefix; ?>GetErrorString(errorCode).toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function doLMSGetDiagnostic(errorCode) {  \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetDiagnostic was not successful.");  \n'
+        + '   }  \n'
+        + '   return api.<?echo $LMS_prefix; ?>GetDiagnostic(errorCode).toString();  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function LMSIsInitialized() {  \n'
+        + '   // there is no direct method for determining if the LMS API is initialized  \n'
+        + '   // for example an LMSIsInitialized function defined on the API so we\'ll try  \n'
+        + '   // a simple LMSGetValue and trap for the LMS Not Initialized Error  \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSIsInitialized() failed.");  \n'
+        + '      return false;  \n'
+        + '   } else {  \n'
+        + '      var value = api.<?echo $LMS_prefix; ?>GetValue("cmi.core.student_name");  \n'
+        + '      var errCode = api.<?echo $LMS_prefix; ?>GetLastError().toString();  \n'
+        + '      if (errCode == _NotInitialized) {  \n'
+        + '         return false;  \n'
+        + '      } else {  \n'
+        + '         return true;  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function ErrorHandler() {  \n'
+        + '   var api = getAPIHandle();  \n'
+        + '   if (api == null) {  \n'
+        + '      alert("Unable to locate the LMS\'s API Implementation.\\nCannot determine LMS error code.");  \n'
+        + '      return;  \n'
+        + '   }  \n'
+        + '   // check for errors caused by or from the LMS  \n'
+        + '   var errCode = api.<?echo $LMS_prefix; ?>GetLastError().toString();  \n'
+        + '   if (errCode != _NoError) {  \n'
+        + '      // an error was encountered so display the error description  \n'
+        + '      var errDescription = api.<?echo $LMS_prefix; ?>GetErrorString(errCode);  \n'
+        + '      if (_Debug == true) {  \n'
+        + '         errDescription += "\\n";  \n'
+        + '         errDescription += api.<?echo $LMS_prefix; ?>GetDiagnostic(null);  \n'
+        + '         // by passing null to LMSGetDiagnostic, we get any available diagnostics  \n'
+        + '         // on the previous error.  \n'
+        + '      }  \n'
+        + '      alert(errDescription);  \n'
+        + '   }  \n'
+        + '   return errCode;  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function getAPIHandle() {  \n'
+        + '   if (apiHandle == null) {  \n'
+        + '      apiHandle = getAPI();  \n'
+        + '   }  \n'
+        + '   return apiHandle;  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function findAPI(win) {  \n'
+        + '   while ((win.<?echo $LMS_api; ?> == null) && (win.parent != null) && (win.parent != win)) {  \n'
+        + '      findAPITries++;  \n'
+        + '      // Note: 7 is an arbitrary number, but should be more than sufficient  \n'
+        + '      if (findAPITries > 7) {  \n'
+        + '         alert("Error finding API -- too deeply nested.");  \n'
+        + '         return null;  \n'
+        + '      }  \n'
+        + '      win = win.parent;  \n'
+        + '   }  \n'
+        + '   return win.<?echo $LMS_api; ?>;  \n'
+        + '}  \n'
+        + '  \n'
+        + 'function getAPI() {  \n'
+        + '   var theAPI = findAPI(window);  \n'
+        + '   if ((theAPI == null) && (window.opener != null) && (typeof(window.opener) != "undefined")) {  \n'
+        + '      theAPI = findAPI(window.opener);  \n'
+        + '   }  \n'
+        + '   if (theAPI == null) {  \n'
+        + '      alert("Unable to find an API adapter");  \n'
+        + '   }  \n'
+        + '   return theAPI  \n'
+        + '}  \n'
+        + '  \n'
+        + '   function tryLMSInitialize() {  \n'
+        + '      var result = doLMSInitialize();  \n'
+        + '      var msg;  \n'
+        + '      if(result == "true") {  \n'
+        + '         msg = "<?echo $LMS_prefix; ?>Initialize Successful!";  \n'
+        + '      } else {  \n'
+        + '         var err = doLMSGetLastError();  \n'
+        + '         var errString = doLMSGetErrorString(err);  \n'
+        + '         msg = "<?echo $LMS_prefix; ?>Initialize Failed! Error Code: "+err;  \n'
+        + '         msg += " Error Description: " + errString;  \n'
+        + '      }  \n'
+        + '      document.initForm.msgtxt.value= msg;  \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSCommit() {  \n'
+        + '      var result = doLMSCommit();  \n'
+        + '      var msg;  \n'
+        + '      if(result == "true") {  \n'
+        + '         msg = "<?echo $LMS_prefix; ?>Commit was Successful!";  \n'
+        + '      } else {  \n'
+        + '         var err = doLMSGetLastError();  \n'
+        + '         var errString = doLMSGetErrorString(err);  \n'
+        + '         var msg = "<?echo $LMS_prefix; ?>Commit Failed! Error Code: "+err;  \n'
+        + '         msg += " Error Description: " + errString;  \n'
+        + '      }  \n'
+        + '      document.otherForm.msgtxt.value = msg; \n'
+        + '      document.elemForm.API_ELEMENT.value = saveElement; \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSFinish() {  \n'
+        + '      // set now, in case the SCO is unloaded on LMSFinish  \n'
+        + '      doLMSSetValue("cmi.core.lesson_status", "completed");  \n'
+        + '      doLMSSetValue("cmi.core.exit", "");  \n'
+        + '      doLMSSetValue("cmi.core.session_time", "00:00:30");  \n'
+        + '      var result = doLMSFinish();  \n'
+        + '      var msg;  \n'
+        + '      if(result == "true") {  \n'
+        + '         msg = "LMSFinish Successful!";  \n'
+        + '         document.otherForm.msgtxt.value = msg;  \n'
+        + '      } else {  \n'
+        + '         var err = doLMSGetLastError();  \n'
+        + '         var errString = doLMSGetErrorString(err);  \n'
+        + '         var msg = "LMSFinish Failed! Error Code: "+err;  \n'
+        + '         msg += " Error Description: " + errString;  \n'
+        + '         document.otherForm.msgtxt.value = msg;  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSTerminate() {  \n'
+        + '      var result = doLMSTerminate();  \n'
+        + '      var msg;  \n'
+        + '      if(result == "true") {  \n'
+        + '         msg = "Terminate Successful!";  \n'
+        + '         document.otherForm.msgtxt.value = msg;  \n'
+        + '      } else {  \n'
+        + '         var err = doLMSGetLastError();  \n'
+        + '         var errString = doLMSGetErrorString(err);  \n'
+        + '         var msg = "Terminate Failed! Error Code: "+err;  \n'
+        + '         msg += " Error Description: " + errString;  \n'
+        + '         document.otherForm.msgtxt.value = msg;  \n'
+        + '      }  \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSGetValue() {  \n'
+        + '     var value = document.elemForm.API_ELEMENT.value;  \n'
+        + '     var msg;  \n'
+        + '     var result = doLMSGetValue(value);  \n'
+        + '     var err = doLMSGetLastError();  \n'
+        + '     var errString = doLMSGetErrorString(err);  \n'
+        + '     msg = "<?echo $LMS_prefix; ?>GetValue Returned: " + result;  \n'
+        + '     msg += "\\nError Code: " + err;  \n'
+        + '     msg += "\\nError Description: " + errString;  \n'
+        + '     document.elemForm.msgtxt.value = msg;  \n'
+        + '     document.elemForm.API_ELEMENT.value = saveElement; \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSSetValue() {  \n'
+        + '     // Get the element that is to be set  \n'
+        + '     var setValue = document.elemForm.SET_VAL.value;  \n'
+        + '     var item = document.elemForm.API_ELEMENT.value;  \n'
+        + '     var msg;  \n'
+        + '     var api = getAPIHandle();  \n'
+        + '     if (api == null) {  \n'
+        + '        alert("Unable to locate the LMS\'s API Implementation.\\n"+  \n'
+        + '              "<?echo $LMS_prefix; ?>SetValue was not successful.");  \n'
+        + '        return false;  \n'
+        + '     }  \n'
+        + '     // Try to set the element  \n'
+        + '     var result = api.<?echo $LMS_prefix; ?>SetValue( item, setValue );  \n'
+        + '     var err = doLMSGetLastError();  \n'
+        + '     var errString = doLMSGetErrorString(err);  \n'
+        + '     msg = "<?echo $LMS_prefix; ?>SetValue returned: " + result;  \n'
+        + '     msg += "\\nError Code: " + err;  \n'
+        + '     msg += "\\nError Description: " + errString;  \n'
+        + '     document.elemForm.msgtxt.value = msg;  \n'
+        + '     document.elemForm.API_ELEMENT.value = saveElement; \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSGetLastError() {  \n'
+        + '      var err = doLMSGetLastError();  \n'
+        + '      document.otherForm.msgtxt.value = "<?echo $LMS_prefix; ?>GetLastError returned Error Code:  " + err;  \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSGetErrorString() {  \n'
+        + '      var err = doLMSGetLastError();  \n'
+        + '      var errString = doLMSGetErrorString(err);  \n'
+        + '      document.otherForm.msgtxt.value = "<?echo $LMS_prefix; ?>GetErrorString returned:  " + errString;  \n'
+        + '   }  \n'
+        + '  \n'
+        + '   function tryLMSGetDiagnostic() {  \n'
+        + '      var err = doLMSGetLastError();  \n'
+        + '      var diagnostic = doLMSGetDiagnostic(err);  \n'
+        + '      document.otherForm.msgtxt.value = "<?echo $LMS_prefix; ?>GetDiagnostic returned:  " + diagnostic;  \n'
+        + '   } \n'
+        + ' \n'
+        + '</script>\n'
+        + '<\/head><body STYLE="background-color: ffffff; color: black"'
         + 'marginwidth="0" leftmargin="0" hspace="0">'
+        + '<h1>SCORM Debugging interface</h1>'
+        + '<h2>SCORM Version Detected: <?php echo $scorm->version; ?></h2>'
         + '<input type="hidden" id="mod-scorm-logstate" name="mod-scorm-logstate" value="A" \/>'
+        + '<form name="initForm" onsubmit="return false;">'
+        + '   <table width="100%" border="0">'
+        + '      <tr>'
+        + '         <td>'
+        + '            <input type = "button" value = "Call <?echo $LMS_prefix; ?>Initialize()" onclick = "tryLMSInitialize();" id="Initialize" name="Initialize" />'
+        + '         </td>'
+        + '         <td>'
+        + '            <label>Result: </label><input type="text" name="msgtxt" id="msgtxt" size="80" readonly value="NotCalled" />'
+        + '         </td>'
+        + '      </tr>'
+        + '   </table>'
+        + '</form>'
+        + '<hr />'
+        + '<form name="elemForm" id="elemForm" onsubmit="return false;">'
+        + '   <table width="100%" border="0">'
+        + '      <tr>'
+        + '         <td><b>Select Data Model Element to Get or Set</b> &nbsp;&nbsp;&nbsp;&nbsp;'
+        + '            <select name = "ELEMENT_LIST" id="ELEMENT_LIST" onchange="setAPIValue()">'
+        + '               <option value="NONE">--None Selected--</option> <option value="">******************************************</option>'
+<?php
+                          foreach ($LMS_elements as $element) {
+                              echo ' + \'               <option value="'.$element.'">'.$element.'</option>\\n\'';
+                          }
+?>
+        + '            </select>'
+        + '            <input type="text" name="API_ELEMENT" id="API_ELEMENT" size="40"><br />'
+        + '            <br />'
+        + '            <label><b>Select API Function to Call</b></label> &nbsp;&nbsp;&nbsp;&nbsp; <input type = "button" value = "<?echo $LMS_prefix; ?>GetValue()"'
+        + '                         onclick = "tryLMSGetValue();" id="lmsGetButton"'
+        + '                         name="lmsGetButton">&nbsp;&nbsp;-- OR --&nbsp;&nbsp;'
+        + '            <input type="button" value="<?echo $LMS_prefix; ?>SetValue()"'
+        + '                          onclick="tryLMSSetValue();" id="lmsSetButton"'
+        + '                          name="lmsSetButton">'
+        + '            <label><b>&nbsp; value to Set: </b></label>&nbsp; <input type="text" name="SET_VAL" id="SET_VAL" size="25">'
+        + '            <br />'
+        + '            <label>Result: </label><br />'
+        + '            <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>'
+        + '         </td>'
+        + '      </tr>'
+        + '   </table>'
+        + '</form>'
+        + '<hr />'
+        + '<form name="otherForm" onsubmit="return false;">'
+        + '   <h3>Additional API Functions</h3>'
+        + '   <table width="100%" border="0">'
+        + '      <tr>'
+        + '         <td><input type="button"'
+        + '             value="<?php echo $LMS_prefix; ?>GetLastError()  "'
+        + '             onclick="tryLMSGetLastError();"'
+        + '             id="lastErrorButton"'
+        + '             name="lastErrorButton">'
+        + '            <input type="button"'
+        + '             value="<?php echo $LMS_prefix; ?>GetErrorString()  "'
+        + '             onclick="tryLMSGetErrorString();"'
+        + '             id="getErrorStringButton"'
+        + '             name="getErrorStringButton">'
+        + '            <input type="button"'
+        + '             value="<?php echo $LMS_prefix; ?>GetDiagnostic()  "'
+        + '             onclick="tryLMSGetDiagnostic();"'
+        + '             id="getDiagnosticButton"'
+        + '             name="getDiagnosticButton">'
+        + '            <input type="button"'
+        + '             value="<?php echo $LMS_prefix; ?>Commit()  "'
+        + '             onclick="tryLMSCommit();"'
+        + '             id="commitButton"'
+        + '             name="commitButton">'
+        + '            <input type="button"'
+        + '             value="<?php echo $scorm->version == 'scorm_12' ? 'LMSFinish' : 'Terminate'; ?>()  "'
+        + '             onclick="try<?php echo $scorm->version == 'scorm_12' ? 'LMSFinish' : 'LMSTerminate'; ?>();"'
+        + '             id="finishButton"'
+        + '             name="finishButton">'
+        + '         </td>'
+        + '    </tr>'
+        + '    <tr>'
+        + '         <td>'
+        + '         <label>Result: </label><br />'
+        + '            <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>'
+        + '     </td>'
+        + '      </tr>'
+        + '   </table>'
+        + '</form>'
         + '<h3 id="mod-scorm-marker">SCORM API Activity Log<\/h3>';
 
     // Is logging active?
@@ -84,7 +655,7 @@ function UpdateLog(s) {
         popupdoc = logPopUpWindow.document;
         popupdoc.body.innerHTML += s;
     } else {
-        logPopUpWindow = open( '', 'logpopupwindow', '' );
+        logPopUpWindow = open( '', 'scormlogpopupwindow', '' );
         popupdoc = logPopUpWindow.document;
         // Is logging active?
         var marker = safeGetElement(popupdoc, 'mod-scorm-marker');
@@ -100,7 +671,7 @@ function UpdateLog(s) {
             logPopUpWindow.focus();
         }
     }
-    if (popupdoc.body.childNodes.length > 0) {
+    if (popupdoc.body && popupdoc.body.childNodes.length > 0) {
         popupdoc.body.lastChild.scrollIntoView();
     };
 }
@@ -111,14 +682,14 @@ function AppendToLog(s, rc) {
     if (rc != 0) {
         sStyle = 'class="error';
     } else if (logRow % 2 != 0) {
-        sStyle = 'class="even';
+        sStyle = 'class="even"';
     } else {
-        sStyle = 'class="odd';
+        sStyle = 'class="odd"';
     }
     sStyle += '"';
     var now = new Date();
     now.setTime( now.getTime() );
-    s = '<div ' + sStyle + '>' + now.toGMTString() + ': ' + s + '<\/div>';
+    s = '<div ' + sStyle + ' id="<?php echo $scorm->version;?>">' + now.toGMTString() + ': ' + s + '<\/div>';
     UpdateLog(s);
     // switch colours for a new section of work
     if (s.match(/Commit|Loaded|Initialize|Terminate|Finish|Moodle SCORM|Moodle Logging/)) {