Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  echo html_writer::start_tag('script');
  18  ?>
  19  
  20  <!--// hopefully fool ie IE proof way of getting DOM element
  21  function safeGetElement(doc, el) {
  22      return doc.ids ? doc.ids[el] : doc.getElementById ? doc.getElementById(el) : doc.all[el];
  23  }
  24  // Find elements by class name
  25  var aryClassElements = new Array();
  26  function getNextElementByClassName( strClassName, obj ) {
  27      if ( obj.className == strClassName ) {
  28          aryClassElements[aryClassElements.length] = obj;
  29      }
  30      for ( var i = 0; i < obj.childNodes.length; i++ )
  31          getNextElementByClassName( strClassName, obj.childNodes[i] );
  32  }
  33  
  34  function getElementsByClassName( strClassName, obj ) {
  35      aryClassElements = new Array();
  36      getNextElementByClassName( strClassName, obj );
  37      if (aryClassElements.length > 0) {
  38          return aryClassElements[0];
  39      }
  40      else {
  41          return null;
  42      }
  43  }
  44  
  45  // retrieve cookie data
  46  function getCookie (cookie_name){
  47      var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );
  48      if ( results ) {
  49          return (unescape(results[2]));
  50      } else {
  51          return null;
  52      }
  53  }
  54  
  55  // retrieve the logging flag from a Cookie
  56  function getLoggingActive () {
  57      var loggingActive = getCookie('SCORMLoggingActive');
  58      if (!loggingActive) {
  59          loggingActive = 'A';
  60      }
  61      return loggingActive;
  62  }
  63  
  64  // set the logging flag in a cookie
  65  function setLoggingActive (flag) {
  66      new cookie("SCORMLoggingActive", flag, 365, "/").set();
  67  }
  68  
  69  // toggle the logging
  70  function toggleLog () {
  71      if (getLoggingActive() == "A") {
  72          AppendToLog("Moodle Logging Deactivated", 0);
  73          setLoggingActive('N');
  74          logButton.innerHTML = '-><?php echo addslashes_js(get_string('scormloggingoff', 'scorm')); ?>';
  75      } else {
  76          setLoggingActive('A');
  77          AppendToLog("Moodle Logging Activated", 0);
  78          logButton.innerHTML = '<?php echo addslashes_js(get_string('scormloggingon', 'scorm')); ?>';
  79          logPopUpWindow.focus();
  80      }
  81  }
  82  
  83  // globals for the log accumulation
  84  var logString = "";
  85  var logRow = 0;
  86  var logPopUpWindow = "N";
  87  var debugSCORMVersion = '<?php echo $scorm->version; ?>';
  88  <?php
  89  $lmsprefix = (scorm_version_check($scorm->version, SCORM_12) || empty($scorm->version)) ? 'LMS' : '';
  90  $lmsapi = (scorm_version_check($scorm->version, SCORM_12) || empty($scorm->version)) ? 'API' : 'API_1484_11';
  91  
  92  $lmselements = array();
  93  if (scorm_version_check($scorm->version, SCORM_12) || empty($scorm->version)) {
  94      $lmselements = array(   'cmi.core._children',
  95                              'cmi.core.student_id',
  96                              'cmi.core.student_name',
  97                              'cmi.core.lesson_location',
  98                              'cmi.core.credit',
  99                              'cmi.core.lesson_status',
 100                              'cmi.core.entry',
 101                              'cmi.core._children',
 102                              'cmi.core.score.raw',
 103                              'cmi.core.score.max',
 104                              'cmi.core.score.min',
 105                              'cmi.core.total_time',
 106                              'cmi.core.lesson_mode',
 107                              'cmi.core.exit',
 108                              'cmi.core.session_time',
 109                              'cmi.suspend_data',
 110                              'cmi.launch_data',
 111                              'cmi.comments',
 112                              'cmi.comments_from_lms',
 113                              'cmi.objectives._count',
 114                              'cmi.objectives._children',
 115                              'cmi.objectives.n.id',
 116                              'cmi.objectives.n.score._children',
 117                              'cmi.objectives.n.score.raw',
 118                              'cmi.objectives.n.score.min',
 119                              'cmi.objectives.n.score.max',
 120                              'cmi.objectives.n.status',
 121                              'cmi.student_data._children',
 122                              'cmi.student_data.mastery_score',
 123                              'cmi.student_data.max_time_allowed',
 124                              'cmi.student_data.time_limit_action',
 125                              'cmi.student_preference._children',
 126                              'cmi.student_preference.audio',
 127                              'cmi.student_preference.language',
 128                              'cmi.student_preference.speed',
 129                              'cmi.student_preference.text',
 130                              'cmi.interactions._children',
 131                              'cmi.interactions._count',
 132                              'cmi.interactions.n.id',
 133                              'cmi.interactions.n.objectives._count',
 134                              'cmi.interactions.n.objectives.m.id',
 135                              'cmi.interactions.n.time',
 136                              'cmi.interactions.n.type',
 137                              'cmi.interactions.n.correct_responses._count',
 138                              'cmi.interactions.n.correct_responses.m.pattern',
 139                              'cmi.interactions.n.weighting',
 140                              'cmi.interactions.n.student_response',
 141                              'cmi.interactions.n.result',
 142                              'cmi.interactions.n.latency');
 143  } else {
 144      $lmselements = array(   'cmi._children',
 145                              'cmi._version',
 146                              'cmi.learner_id',
 147                              'cmi.learner_name',
 148                              'cmi.location',
 149                              'cmi.completion_status',
 150                              'cmi.completion_threshold',
 151                              'cmi.scaled_passing_score',
 152                              'cmi.progressive_measure',
 153                              'cmi.score._children',
 154                              'cmi.score.raw',
 155                              'cmi.score.max',
 156                              'cmi.score.min',
 157                              'cmi.score.scaled',
 158                              'cmi.total_time',
 159                              'cmi.time_limit_action',
 160                              'cmi.max_time_allowed',
 161                              'cmi.session_time',
 162                              'cmi.success_status',
 163                              'cmi.lesson_mode',
 164                              'cmi.entry',
 165                              'cmi.exit',
 166                              'cmi.credit',
 167                              'cmi.mode',
 168                              'cmi.suspend_data',
 169                              'cmi.launch_data',
 170                              'cmi.comments',
 171                              'cmi.comments_from_lms._children',
 172                              'cmi.comments_from_lms._count',
 173                              'cmi.comments_from_lms.n.comment',
 174                              'cmi.comments_from_lms.n.location',
 175                              'cmi.comments_from_lms.n.timestamp',
 176                              'cmi.comments_from_learner._children',
 177                              'cmi.comments_from_learner._count',
 178                              'cmi.comments_from_learner.n.comment',
 179                              'cmi.comments_from_learner.n.location',
 180                              'cmi.comments_from_learner.n.timestamp',
 181                              'cmi.objectives._count',
 182                              'cmi.objectives._children',
 183                              'cmi.objectives.n.id',
 184                              'cmi.objectives.n.score._children',
 185                              'cmi.objectives.n.score.raw',
 186                              'cmi.objectives.n.score.min',
 187                              'cmi.objectives.n.score.max',
 188                              'cmi.objectives.n.score.scaled',
 189                              'cmi.objectives.n.success_status',
 190                              'cmi.objectives.n.completion_status',
 191                              'cmi.objectives.n.progress_measure',
 192                              'cmi.objectives.n.description',
 193                              'cmi.student_data._children',
 194                              'cmi.student_data.mastery_score',
 195                              'cmi.student_data.max_time_allowed',
 196                              'cmi.student_data.time_limit_action',
 197                              'cmi.student_preference._children',
 198                              'cmi.student_preference.audio',
 199                              'cmi.student_preference.language',
 200                              'cmi.student_preference.speed',
 201                              'cmi.student_preference.text',
 202                              'cmi.interactions._children',
 203                              'cmi.interactions._count',
 204                              'cmi.interactions.n.id',
 205                              'cmi.interactions.n.objectives._count',
 206                              'cmi.interactions.n.objectives.m.id',
 207                              'cmi.interactions.n.time',
 208                              'cmi.interactions.n.type',
 209                              'cmi.interactions.n.correct_responses._count',
 210                              'cmi.interactions.n.correct_responses.m.pattern',
 211                              'cmi.interactions.n.weighting',
 212                              'cmi.interactions.n.learner_response',
 213                              'cmi.interactions.n.result',
 214                              'cmi.interactions.n.latency',
 215                              'cmi.interactions.n.description',
 216                              'adl.nav.request');
 217  }
 218  ?>
 219  
 220  // add each entry to the log, or setup the log pane first time round
 221  // The code written into the header is based on the ADL test suite API interaction code
 222  // and various examples of test wrappers out in the community
 223  function UpdateLog(s) {
 224      var s1 = '<html><head><style>\n'
 225          + 'body {font-family: Arial, Helvetica, Sans-Serif;font-size: xx-small;'
 226          + 'margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; '
 227          + 'background-color: ffffff;}\n'
 228          + '.even {background-color: ffffff; width: 100%;}\n'
 229          + '.odd {background-color: e8f2fe; width: 100%;}\n'
 230          + '.error {background-color: ffffff; color: red; width: 100%;}\n'
 231          + '<\/style>'
 232          + '<script>\n'
 233          + 'var LMSVersion = \'<?php echo $scorm->version; ?>\';\n'
 234          + ' \n'
 235          + 'function checkLMSVersion() {  \n'
 236          + '    if (this.document.body.childNodes.length > 0) { \n'
 237          + '        if (this.document.body.lastChild.id == LMSVersion) { \n'
 238          + '            return true; \n'
 239          + '        } \n'
 240          + '    }; \n'
 241          + '    alert(\'LMS Version: \' + this.document.body.lastChild.id + \n'
 242          + '          \' does not equal: \' + LMSVersion +  \n'
 243          + '          \' so API calls will fail - did navigate to another SCORM package?\'); \n'
 244          + '    return false; \n'
 245          + '} \n'
 246          + ' \n'
 247          + 'var saveElement = ""; \n'
 248          + 'function setAPIValue() {  \n'
 249          + '  document.elemForm.API_ELEMENT.value = document.elemForm.ELEMENT_LIST.value; \n'
 250          + '  saveElement = document.elemForm.API_ELEMENT.value; \n'
 251          + '} \n'
 252          + '  \n'
 253          + 'var _Debug = false;  // set this to false to turn debugging off  \n'
 254          + '  \n'
 255          + '// Define exception/error codes  \n'
 256          + 'var _NoError = 0;  \n'
 257          + 'var _GeneralException = 101;  \n'
 258          + 'var _ServerBusy = 102;  \n'
 259          + 'var _InvalidArgumentError = 201;  \n'
 260          + 'var _ElementCannotHaveChildren = 202;  \n'
 261          + 'var _ElementIsNotAnArray = 203;  \n'
 262          + 'var _NotInitialized = 301;  \n'
 263          + 'var _NotImplementedError = 401;  \n'
 264          + 'var _InvalidSetValue = 402;  \n'
 265          + 'var _ElementIsReadOnly = 403;  \n'
 266          + 'var _ElementIsWriteOnly = 404;  \n'
 267          + 'var _IncorrectDataType = 405;  \n'
 268          + '  \n'
 269          + '// local variable definitions  \n'
 270          + 'var apiHandle = null;  \n'
 271          + 'var API = null;  \n'
 272          + 'var findAPITries = 0;  \n'
 273          + '  \n'
 274          + '  \n'
 275          + 'function doLMSInitialize() { \n'
 276          + '   checkLMSVersion(); \n'
 277          + '   var api = getAPIHandle();  \n'
 278          + '   if (api == null) {  \n'
 279          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSInitialize was not successful.");  \n'
 280          + '      return "false";  \n'
 281          + '   }  \n'
 282          + '   var result = api.<?php echo $lmsprefix; ?>Initialize("");  \n'
 283          + '   if (result.toString() != "true") {  \n'
 284          + '      var err = ErrorHandler();  \n'
 285          + '   }  \n'
 286          + '   return result.toString();  \n'
 287          + '}  \n'
 288          + '  \n'
 289          + 'function doLMSFinish() {  \n'
 290          + '   checkLMSVersion(); \n'
 291          + '   var api = getAPIHandle();  \n'
 292          + '   if (api == null) {  \n'
 293          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSFinish was not successful.");  \n'
 294          + '      return "false";  \n'
 295          + '   } else {  \n'
 296          + '      // call the LMSFinish function that should be implemented by the API  \n'
 297          + '      var result = api.<?php echo $lmsprefix; ?>Finish("");  \n'
 298          + '      if (result.toString() != "true") {  \n'
 299          + '         var err = ErrorHandler();  \n'
 300          + '      }  \n'
 301          + '   }  \n'
 302          + '   return result.toString();  \n'
 303          + '}  \n'
 304          + '  \n'
 305          + 'function doLMSTerminate() {  \n'
 306          + '   checkLMSVersion(); \n'
 307          + '   var api = getAPIHandle();  \n'
 308          + '   if (api == null) {  \n'
 309          + '      alert("Unable to locate the LMS\'s API Implementation.\\nTerminate was not successful.");  \n'
 310          + '      return "false";  \n'
 311          + '   } else {  \n'
 312          + '      // call the Terminate function that should be implemented by the API  \n'
 313          + '      var result = api.Terminate("");  \n'
 314          + '      if (result.toString() != "true") {  \n'
 315          + '         var err = ErrorHandler();  \n'
 316          + '      }  \n'
 317          + '   }  \n'
 318          + '   return result.toString();  \n'
 319          + '}  \n'
 320          + '  \n'
 321          + 'function doLMSGetValue(name) {  \n'
 322          + '   checkLMSVersion(); \n'
 323          + '   var api = getAPIHandle();  \n'
 324          + '   if (api == null) {  \n'
 325          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetValue was not successful.");  \n'
 326          + '      return "";  \n'
 327          + '   } else {  \n'
 328          + '      var value = api.<?php echo $lmsprefix; ?>GetValue(name);  \n'
 329          + '      var errCode = api.<?php echo $lmsprefix; ?>GetLastError().toString();  \n'
 330          + '      if (errCode != _NoError) {  \n'
 331          + '         // an error was encountered so display the error description  \n'
 332          + '         var errDescription = api.<?php echo $lmsprefix; ?>GetErrorString(errCode);  \n'
 333          + '         alert("<?php echo $lmsprefix; ?>GetValue("+name+") failed. \\n"+ errDescription);  \n'
 334          + '         return "";  \n'
 335          + '      } else {  \n'
 336          + '         return value.toString();  \n'
 337          + '      }  \n'
 338          + '   }  \n'
 339          + '}  \n'
 340          + '  \n'
 341          + 'function doLMSSetValue(name, value) {  \n'
 342          + '   checkLMSVersion(); \n'
 343          + '   var api = getAPIHandle();  \n'
 344          + '   if (api == null) {  \n'
 345          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSSetValue was not successful.");  \n'
 346          + '      return;  \n'
 347          + '   } else {  \n'
 348          + '      var result = api.<?php echo $lmsprefix; ?>SetValue(name, value);  \n'
 349          + '      if (result.toString() != "true") {  \n'
 350          + '         var err = ErrorHandler();  \n'
 351          + '      }  \n'
 352          + '   }  \n'
 353          + '   return;  \n'
 354          + '}  \n'
 355          + '  \n'
 356          + 'function doLMSCommit() {  \n'
 357          + '   checkLMSVersion(); \n'
 358          + '   var api = getAPIHandle();  \n'
 359          + '   if (api == null) {  \n'
 360          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSCommit was not successful.");  \n'
 361          + '      return "false";  \n'
 362          + '   } else {  \n'
 363          + '      var result = api.<?php echo $lmsprefix; ?>Commit("");  \n'
 364          + '      if (result != "true") {  \n'
 365          + '         var err = ErrorHandler();  \n'
 366          + '      }  \n'
 367          + '   }  \n'
 368          + '   return result.toString();  \n'
 369          + '}  \n'
 370          + '  \n'
 371          + 'function doLMSGetLastError() {  \n'
 372          + '   var api = getAPIHandle();  \n'
 373          + '   if (api == null) {  \n'
 374          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetLastError was not successful.");  \n'
 375          + '      //since we can\'t get the error code from the LMS, return a general error  \n'
 376          + '      return _GeneralError;  \n'
 377          + '   }  \n'
 378          + '   return api.<?php echo $lmsprefix; ?>GetLastError().toString();  \n'
 379          + '}  \n'
 380          + '  \n'
 381          + 'function doLMSGetErrorString(errorCode) {  \n'
 382          + '   var api = getAPIHandle();  \n'
 383          + '   if (api == null) {  \n'
 384          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetErrorString was not successful.");  \n'
 385          + '   }  \n'
 386          + '   return api.<?php echo $lmsprefix; ?>GetErrorString(errorCode).toString();  \n'
 387          + '}  \n'
 388          + '  \n'
 389          + 'function doLMSGetDiagnostic(errorCode) {  \n'
 390          + '   var api = getAPIHandle();  \n'
 391          + '   if (api == null) {  \n'
 392          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSGetDiagnostic was not successful.");  \n'
 393          + '   }  \n'
 394          + '   return api.<?php echo $lmsprefix; ?>GetDiagnostic(errorCode).toString();  \n'
 395          + '}  \n'
 396          + '  \n'
 397          + 'function LMSIsInitialized() {  \n'
 398          + '   // there is no direct method for determining if the LMS API is initialized  \n'
 399          + '   // for example an LMSIsInitialized function defined on the API so we\'ll try  \n'
 400          + '   // a simple LMSGetValue and trap for the LMS Not Initialized Error  \n'
 401          + '   var api = getAPIHandle();  \n'
 402          + '   if (api == null) {  \n'
 403          + '      alert("Unable to locate the LMS\'s API Implementation.\\nLMSIsInitialized() failed.");  \n'
 404          + '      return false;  \n'
 405          + '   } else {  \n'
 406          + '      var value = api.<?php echo $lmsprefix; ?>GetValue("cmi.core.student_name");  \n'
 407          + '      var errCode = api.<?php echo $lmsprefix; ?>GetLastError().toString();  \n'
 408          + '      if (errCode == _NotInitialized) {  \n'
 409          + '         return false;  \n'
 410          + '      } else {  \n'
 411          + '         return true;  \n'
 412          + '      }  \n'
 413          + '   }  \n'
 414          + '}  \n'
 415          + '  \n'
 416          + 'function ErrorHandler() {  \n'
 417          + '   var api = getAPIHandle();  \n'
 418          + '   if (api == null) {  \n'
 419          + '      alert("Unable to locate the LMS\'s API Implementation.\\nCannot determine LMS error code.");  \n'
 420          + '      return;  \n'
 421          + '   }  \n'
 422          + '   // check for errors caused by or from the LMS  \n'
 423          + '   var errCode = api.<?php echo $lmsprefix; ?>GetLastError().toString();  \n'
 424          + '   if (errCode != _NoError) {  \n'
 425          + '      // an error was encountered so display the error description  \n'
 426          + '      var errDescription = api.<?php echo $lmsprefix; ?>GetErrorString(errCode);  \n'
 427          + '      if (_Debug == true) {  \n'
 428          + '         errDescription += "\\n";  \n'
 429          + '         errDescription += api.<?php echo $lmsprefix; ?>GetDiagnostic(null);  \n'
 430          + '         // by passing null to LMSGetDiagnostic, we get any available diagnostics  \n'
 431          + '         // on the previous error.  \n'
 432          + '      }  \n'
 433          + '      alert(errDescription);  \n'
 434          + '   }  \n'
 435          + '   return errCode;  \n'
 436          + '}  \n'
 437          + '  \n'
 438          + 'function getAPIHandle() {  \n'
 439          + '   if (apiHandle == null) {  \n'
 440          + '      apiHandle = getAPI();  \n'
 441          + '   }  \n'
 442          + '   return apiHandle;  \n'
 443          + '}  \n'
 444          + '  \n'
 445          + 'function findAPI(win) {  \n'
 446          + '   while ((win.<?php echo $lmsapi; ?> == null) && (win.parent != null) && (win.parent != win)) {  \n'
 447          + '      findAPITries++;  \n'
 448          + '      // Note: 7 is an arbitrary number, but should be more than sufficient  \n'
 449          + '      if (findAPITries > 7) {  \n'
 450          + '         alert("Error finding API -- too deeply nested.");  \n'
 451          + '         return null;  \n'
 452          + '      }  \n'
 453          + '      win = win.parent;  \n'
 454          + '   }  \n'
 455          + '   return win.<?php echo $lmsapi; ?>;  \n'
 456          + '}  \n'
 457          + '  \n'
 458          + 'function getAPI() {  \n'
 459          + '   var theAPI = findAPI(window);  \n'
 460          + '   if ((theAPI == null) && (window.opener != null) && (typeof(window.opener) != "undefined")) {  \n'
 461          + '      theAPI = findAPI(window.opener);  \n'
 462          + '   }  \n'
 463          + '   if (theAPI == null) {  \n'
 464          + '      alert("Unable to find an API adapter");  \n'
 465          + '   }  \n'
 466          + '   return theAPI  \n'
 467          + '}  \n'
 468          + '  \n'
 469          + '   function tryLMSInitialize() {  \n'
 470          + '      var result = doLMSInitialize();  \n'
 471          + '      var msg;  \n'
 472          + '      if(result == "true") {  \n'
 473          + '         msg = "<?php echo $lmsprefix; ?>Initialize Successful!";  \n'
 474          + '      } else {  \n'
 475          + '         var err = doLMSGetLastError();  \n'
 476          + '         var errString = doLMSGetErrorString(err);  \n'
 477          + '         msg = "<?php echo $lmsprefix; ?>Initialize Failed! Error Code: "+err;  \n'
 478          + '         msg += " Error Description: " + errString;  \n'
 479          + '      }  \n'
 480          + '      document.initForm.msgtxt.value= msg;  \n'
 481          + '   }  \n'
 482          + '  \n'
 483          + '   function tryLMSCommit() {  \n'
 484          + '      var result = doLMSCommit();  \n'
 485          + '      var msg;  \n'
 486          + '      if(result == "true") {  \n'
 487          + '         msg = "<?php echo $lmsprefix; ?>Commit was Successful!";  \n'
 488          + '      } else {  \n'
 489          + '         var err = doLMSGetLastError();  \n'
 490          + '         var errString = doLMSGetErrorString(err);  \n'
 491          + '         var msg = "<?php echo $lmsprefix; ?>Commit Failed! Error Code: "+err;  \n'
 492          + '         msg += " Error Description: " + errString;  \n'
 493          + '      }  \n'
 494          + '      document.otherForm.msgtxt.value = msg; \n'
 495          + '      document.elemForm.API_ELEMENT.value = saveElement; \n'
 496          + '   }  \n'
 497          + '  \n'
 498          + '   function tryLMSFinish() {  \n'
 499          + '      // set now, in case the SCO is unloaded on LMSFinish  \n'
 500          + '      doLMSSetValue("cmi.core.lesson_status", "completed");  \n'
 501          + '      doLMSSetValue("cmi.core.exit", "");  \n'
 502          + '      doLMSSetValue("cmi.core.session_time", "00:00:30");  \n'
 503          + '      var result = doLMSFinish();  \n'
 504          + '      var msg;  \n'
 505          + '      if(result == "true") {  \n'
 506          + '         msg = "LMSFinish Successful!";  \n'
 507          + '         document.otherForm.msgtxt.value = msg;  \n'
 508          + '      } else {  \n'
 509          + '         var err = doLMSGetLastError();  \n'
 510          + '         var errString = doLMSGetErrorString(err);  \n'
 511          + '         var msg = "LMSFinish Failed! Error Code: "+err;  \n'
 512          + '         msg += " Error Description: " + errString;  \n'
 513          + '         document.otherForm.msgtxt.value = msg;  \n'
 514          + '      }  \n'
 515          + '   }  \n'
 516          + '  \n'
 517          + '   function tryLMSTerminate() {  \n'
 518          + '      var result = doLMSTerminate();  \n'
 519          + '      var msg;  \n'
 520          + '      if(result == "true") {  \n'
 521          + '         msg = "Terminate Successful!";  \n'
 522          + '         document.otherForm.msgtxt.value = msg;  \n'
 523          + '      } else {  \n'
 524          + '         var err = doLMSGetLastError();  \n'
 525          + '         var errString = doLMSGetErrorString(err);  \n'
 526          + '         var msg = "Terminate Failed! Error Code: "+err;  \n'
 527          + '         msg += " Error Description: " + errString;  \n'
 528          + '         document.otherForm.msgtxt.value = msg;  \n'
 529          + '      }  \n'
 530          + '   }  \n'
 531          + '  \n'
 532          + '   function tryLMSGetValue() {  \n'
 533          + '     var value = document.elemForm.API_ELEMENT.value;  \n'
 534          + '     var msg;  \n'
 535          + '     var result = doLMSGetValue(value);  \n'
 536          + '     var err = doLMSGetLastError();  \n'
 537          + '     var errString = doLMSGetErrorString(err);  \n'
 538          + '     msg = "<?php echo $lmsprefix; ?>GetValue Returned: " + result;  \n'
 539          + '     msg += "\\nError Code: " + err;  \n'
 540          + '     msg += "\\nError Description: " + errString;  \n'
 541          + '     document.elemForm.msgtxt.value = msg;  \n'
 542          + '     document.elemForm.API_ELEMENT.value = saveElement; \n'
 543          + '   }  \n'
 544          + '  \n'
 545          + '   function tryLMSSetValue() {  \n'
 546          + '     // Get the element that is to be set  \n'
 547          + '     var setValue = document.elemForm.SET_VAL.value;  \n'
 548          + '     var item = document.elemForm.API_ELEMENT.value;  \n'
 549          + '     var msg;  \n'
 550          + '     var api = getAPIHandle();  \n'
 551          + '     if (api == null) {  \n'
 552          + '        alert("Unable to locate the LMS\'s API Implementation.\\n"+  \n'
 553          + '              "<?php echo $lmsprefix; ?>SetValue was not successful.");  \n'
 554          + '        return false;  \n'
 555          + '     }  \n'
 556          + '     // Try to set the element  \n'
 557          + '     var result = api.<?php echo $lmsprefix; ?>SetValue( item, setValue );  \n'
 558          + '     var err = doLMSGetLastError();  \n'
 559          + '     var errString = doLMSGetErrorString(err);  \n'
 560          + '     msg = "<?php echo $lmsprefix; ?>SetValue returned: " + result;  \n'
 561          + '     msg += "\\nError Code: " + err;  \n'
 562          + '     msg += "\\nError Description: " + errString;  \n'
 563          + '     document.elemForm.msgtxt.value = msg;  \n'
 564          + '     document.elemForm.API_ELEMENT.value = saveElement; \n'
 565          + '   }  \n'
 566          + '  \n'
 567          + '   function tryLMSGetLastError() {  \n'
 568          + '      var err = doLMSGetLastError();  \n'
 569          + '      document.otherForm.msgtxt.value = "<?php echo $lmsprefix; ?>GetLastError returned Error Code:  " + err;  \n'
 570          + '   }  \n'
 571          + '  \n'
 572          + '   function tryLMSGetErrorString() {  \n'
 573          + '      var err = doLMSGetLastError();  \n'
 574          + '      var errString = doLMSGetErrorString(err);  \n'
 575          + '      document.otherForm.msgtxt.value = "<?php echo $lmsprefix; ?>GetErrorString returned:  " + errString;  \n'
 576          + '   }  \n'
 577          + '  \n'
 578          + '   function tryLMSGetDiagnostic() {  \n'
 579          + '      var err = doLMSGetLastError();  \n'
 580          + '      var diagnostic = doLMSGetDiagnostic(err);  \n'
 581          + '      document.otherForm.msgtxt.value = "<?php echo $lmsprefix; ?>GetDiagnostic returned:  " + diagnostic;  \n'
 582          + '   } \n'
 583          + ' \n'
 584          + '</script>\n'
 585          + '<\/head><body STYLE="background-color: ffffff; color: black"'
 586          + 'marginwidth="0" leftmargin="0" hspace="0">'
 587          + '<h1>SCORM Debugging interface</h1>'
 588          + '<h2>SCORM Version Detected: <?php echo $scorm->version; ?></h2>'
 589          + '<input type="hidden" id="mod-scorm-logstate" name="mod-scorm-logstate" value="A" \/>'
 590          + '<form name="initForm" onsubmit="return false;">'
 591          + '   <table width="100%" border="0">'
 592          + '      <tr>'
 593          + '         <td>'
 594          + '            <input type = "button" value = "Call <?php echo $lmsprefix; ?>Initialize()"'
 595          + '             onclick = "tryLMSInitialize();" id="Initialize" name="Initialize" />'
 596          + '         </td>'
 597          + '         <td>'
 598          + '            <label>Result: </label><input type="text" name="msgtxt" id="msgtxt" size="80" readonly value="NotCalled" />'
 599          + '         </td>'
 600          + '      </tr>'
 601          + '   </table>'
 602          + '</form>'
 603          + '<hr />'
 604          + '<form name="elemForm" id="elemForm" onsubmit="return false;">'
 605          + '   <table width="100%" border="0">'
 606          + '      <tr>'
 607          + '         <td><b>Select Data Model Element to Get or Set</b> &nbsp;&nbsp;&nbsp;&nbsp;'
 608          + '            <select name = "ELEMENT_LIST" id="ELEMENT_LIST" onchange="setAPIValue()">'
 609          + '               <option value="NONE">--None Selected--</option>'
 610          + '               <option value="">******************************************</option>'
 611  <?php
 612  
 613  foreach ($lmselements as $element) {
 614      echo ' + \'               <option value="'.$element.'">'.$element.'</option>\\n\'';
 615  }
 616  
 617  ?>
 618          + '            </select>'
 619          + '            <input type="text" name="API_ELEMENT" id="API_ELEMENT" size="40"><br />'
 620          + '            <br />'
 621          + '            <label><b>Select API Function to Call</b></label> &nbsp;&nbsp;&nbsp;&nbsp;'
 622          + '            <input type = "button" value = "<?php echo $lmsprefix; ?>GetValue()"'
 623          + '             onclick = "tryLMSGetValue();" id="lmsGetButton"'
 624          + '             name="lmsGetButton">&nbsp;&nbsp;-- OR --&nbsp;&nbsp;'
 625          + '            <input type="button" value="<?php echo $lmsprefix; ?>SetValue()"'
 626          + '             onclick="tryLMSSetValue();" id="lmsSetButton"'
 627          + '             name="lmsSetButton">'
 628          + '            <label><b>&nbsp; value to Set: </b></label>&nbsp; <input type="text" name="SET_VAL" id="SET_VAL" size="25">'
 629          + '            <br />'
 630          + '            <label>Result: </label><br />'
 631          + '            <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>'
 632          + '         </td>'
 633          + '      </tr>'
 634          + '   </table>'
 635          + '</form>'
 636          + '<hr />'
 637          + '<form name="otherForm" onsubmit="return false;">'
 638          + '   <h3>Additional API Functions</h3>'
 639          + '   <table width="100%" border="0">'
 640          + '      <tr>'
 641          + '         <td><input type="button"'
 642          + '             value="<?php echo $lmsprefix; ?>GetLastError()  "'
 643          + '             onclick="tryLMSGetLastError();"'
 644          + '             id="lastErrorButton"'
 645          + '             name="lastErrorButton">'
 646          + '            <input type="button"'
 647          + '             value="<?php echo $lmsprefix; ?>GetErrorString()  "'
 648          + '             onclick="tryLMSGetErrorString();"'
 649          + '             id="getErrorStringButton"'
 650          + '             name="getErrorStringButton">'
 651          + '            <input type="button"'
 652          + '             value="<?php echo $lmsprefix; ?>GetDiagnostic()  "'
 653          + '             onclick="tryLMSGetDiagnostic();"'
 654          + '             id="getDiagnosticButton"'
 655          + '             name="getDiagnosticButton">'
 656          + '            <input type="button"'
 657          + '             value="<?php echo $lmsprefix; ?>Commit()  "'
 658          + '             onclick="tryLMSCommit();"'
 659          + '             id="commitButton"'
 660          + '             name="commitButton">'
 661          + '            <input type="button"'
 662          + '             value="<?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'Terminate'; ?>()  "'
 663          + '             onclick="try'
 664          + '             <?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'LMSTerminate'; ?>();"'
 665          + '             id="finishButton"'
 666          + '             name="finishButton">'
 667          + '         </td>'
 668          + '    </tr>'
 669          + '    <tr>'
 670          + '         <td>'
 671          + '         <label>Result: </label><br />'
 672          + '            <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>'
 673          + '     </td>'
 674          + '      </tr>'
 675          + '   </table>'
 676          + '</form>'
 677          + '<h3 id="mod-scorm-marker">SCORM API Activity Log<\/h3>';
 678  
 679      // Is logging active?
 680      if (getLoggingActive() != "A") {
 681          return;
 682      }
 683  
 684      var popupdoc = '';
 685      logString += s;
 686      if (logPopUpWindow != 'N' && !logPopUpWindow.closed) {
 687          popupdoc = logPopUpWindow.document;
 688          popupdoc.body.innerHTML += s;
 689      } else {
 690          logPopUpWindow = open( '', 'scormlogpopupwindow', '' );
 691          popupdoc = logPopUpWindow.document;
 692          // Is logging active?
 693          var marker = safeGetElement(popupdoc, 'mod-scorm-marker');
 694          if (marker) {
 695              popupdoc.body.innerHTML += s;
 696          } else {
 697              popupdoc.open();
 698              popupdoc.write(s1);
 699              popupdoc.write(logString);
 700              popupdoc.write('<\/body><\/html>')
 701              popupdoc.close();
 702              popupdoc.title = 'SCORM API Activity Log';
 703              logPopUpWindow.focus();
 704          }
 705      }
 706      if (popupdoc.body && popupdoc.body.childNodes.length > 0) {
 707          popupdoc.body.lastChild.scrollIntoView();
 708      };
 709  }
 710  
 711  //add an individual log entry
 712  function AppendToLog(s, rc) {
 713      var sStyle = '';
 714      if (rc != 0) {
 715          sStyle = 'class="error"';
 716      } else if (logRow % 2 != 0) {
 717          sStyle = 'class="even"';
 718      } else {
 719          sStyle = 'class="odd"';
 720      }
 721      var now = new Date();
 722      now.setTime( now.getTime() );
 723      s = '<div ' + sStyle + ' id="<?php echo $scorm->version; ?>">' + now.toGMTString() + ': ' + s + '<\/div>';
 724      UpdateLog(s);
 725      // switch colours for a new section of work
 726      if (s.match(/Commit|Loaded|Initialize|Terminate|Finish|Moodle SCORM|Moodle Logging/)) {
 727          logRow++;
 728      }
 729  }
 730  
 731  // format a log entry
 732  function LogAPICall(func, nam, val, rc) {
 733      // drop call to GetLastError for the time being - it produces too much chatter
 734      if (func.match(/GetLastError/)) {
 735          return;
 736      }
 737      var s = func + '("' + nam + '"';
 738      if (val != null && ! (func.match(/GetValue|GetLastError/))) {
 739          s += ', "' + val + '"';
 740      }
 741      s += ')';
 742      if (func.match(/GetValue/)) {
 743          s += ' - ' + val;
 744      }
 745      s += ' => ' + String(rc) + "   scoid = " + scorm_current_node.scoid;
 746      AppendToLog(s, rc);
 747  <?php
 748  if (scorm_debugging($scorm) && ($sco->scormtype == 'asset')) {
 749  ?>
 750      hint = 'Item <?php echo $sco->identifier; ?> has been defined as an Asset: it should never call the SCORM API';
 751      AppendToLog(hint, 101);
 752  <?php
 753  }
 754  ?>
 755  }
 756  
 757  
 758  // Add in a JS controlled link for toggling the Debug logging
 759  if (!document.getElementById('mod-scorm-log-toggle')) {
 760      var logButton = document.createElement('a');
 761      logButton.id = 'mod-scorm-log-toggle';
 762      logButton.name = 'logToggle';
 763      logButton.href = 'javascript:toggleLog();';
 764      if (getLoggingActive() == "A") {
 765          logButton.innerHTML = '<?php echo addslashes_js(get_string('scormloggingon', 'scorm')); ?>';
 766      } else {
 767          logButton.innerHTML = '<?php echo addslashes_js(get_string('scormloggingoff', 'scorm')); ?>';
 768      }
 769      var content = safeGetElement(document, 'scormpage');
 770      content.insertBefore(logButton, content.firstChild);
 771  }
 772  -->
 773  
 774  <?php
 775  echo html_writer::end_tag('script');