@ -2,7 +2,7 @@
/* For licensing terms, see /license.txt */
/**
* API event handler functions for Scorm 1.1 and 1.2 and 1.3
* API event handler functions for Scorm 1.1 and 1.2 and 1.3 (latter not fully supported)
* This script is divided into three sections.
* The first section (below) is the initialisation part.
* The second section is the SCORM object part
@ -10,7 +10,7 @@
* and frames refresh
* @author Denes Nagy < darkden @ freemail . hu > (original author - 2003-2004)
* @author Yannick Warnier < ywarnier @ beeznest . org > (extended and maintained - 2005-2014)
* @version v 1.1
* @version v 1.2
* @access public
* @package chamilo.learnpath.scorm
*/
@ -35,7 +35,7 @@ $oLP = unserialize($_SESSION['lpobject']);
$oItem = isset($oLP->items[$oLP->current]) ? $oLP->items[$oLP->current] : null;
if (!is_object($oItem)) {
error_log('New LP - scorm_api - Could not load oItem item',0);
error_log('New LP - scorm_api - Could not load oItem item', 0);
exit;
}
$autocomplete_when_80pct = 0;
@ -112,7 +112,8 @@ var olms = new Object();
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
//this is not necessary and is only provided to make bad Articulate contents shut up (and not trigger useless JS messages)
//this is not necessary and is only provided to make bad Articulate contents
// shut up (and not trigger useless JS messages)
olms.G_LastErrorString = 'No error';
//these variables are provided for better control of the current status in the
@ -140,6 +141,10 @@ olms.variable_to_send=new Array();
// temporary list of variables (gets set to true when set through LMSSetValue)
olms.updatable_vars_list = new Array();
// marker of whether the LMSFinish() function was called, which is important for SCORM behaviour
olms.finishSignalReceived = 0;
// marker to remember if the SCO has calles a "set" on lesson_status
olms.statusSignalReceived = 0;
// Strictly scorm variables
olms.score=<?php echo $oItem -> get_score (); ?> ;
@ -182,11 +187,12 @@ olms.lms_item_core_exit = '<?php echo $oItem->get_core_exit();?>';
olms.lms_course_id = '<?php echo $oLP -> get_course_int_id (); ?> ';
olms.lms_session_id = '<?php echo api_get_session_id (); ?> ';
olms.lms_course_code = '<?php echo $oLP -> getCourseCode (); ?> ';
olms.lms_course_id = '<?php echo $oLP -> get_course_int_id (); ?> ';
<?php echo $oLP -> get_items_details_as_js ( 'olms.lms_item_types' ); ?>
olms.asset_timer = 0;
olms.userfname = '<?php echo str_replace ( "'" , " \\ '" , $user [ 'firstname' ]); ?> ';
olms.userlname = '<?php echo str_replace ( "'" , " \\ '" , $user [ 'lastname' ]); ?> ';
olms.userfname = '<?php echo str_replace ( "'" , " \\ '" , $user [ 'firstname' ]); ?> ';
olms.userlname = '<?php echo str_replace ( "'" , " \\ '" , $user [ 'lastname' ]); ?> ';
olms.execute_stats = false;
@ -198,27 +204,33 @@ addEvent(window, 'load', addListeners, false);
// Initialize stuff when the page is loaded
$(document).ready(function() {
logit_lms('document.ready start');
logit_lms('document.ready event starts');
logit_lms('These logs are generated by the main/newscorm/scorm_api.php JS '
+ 'library when the admin has clicked on the debug icon in the '
+ 'learning paths list: '
+ 'lines prefixed with "LMS:" refer to actions taken on the LMS side, '
+ 'while lines prefixed with "SCORM:" refer to actions taken to match '
+ 'the SCORM standard at the JS level.', 3);
logit_scorm('LMSSetValue calls are shown in red for better visibility.', 0);
logit_scorm('Other SCORM calls are shown in orange.', 1);
logit_lms('To add new messages to these logs, use logit_lms() or logit_scorm().');
olms.info_lms_item[0] = '<?php echo $oItem -> get_id (); ?> ';
olms.info_lms_item[1] = '<?php echo $oItem -> get_id (); ?> ';
$("#content_id").load(function() {
logit_lms('#content_id on load executing: ');
logit_lms('#content_id load event starts ');
olms.info_lms_item[0] = olms.info_lms_item[1];
// Only trigger the LMSInitialize automatically if not SCO
if (olms.lms_item_types['i'+olms.info_lms_item[1]] != 'sco') {
LMSInitialize();
} else {
logit_lms('Cant execute LMSInitialize() (type is sco) ',2);
logit_lms('Content type is SCO and is responsible to launch LMSInitialize() on its own - Skipping ',2);
}
});
});
//Seems that this objs are not used
//oXAJAX = new XAJAXobject();
//oxajax = new XAJAXobject();
// This code was moved inside LMSInitialize()
if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
xajax_start_timer();
@ -246,10 +258,12 @@ function LMSInitialize() {
olms.G_LastErrorMessage = 'No error';
olms.lms_initialized = 0;
olms.finishSignalReceived = 0;
olms.statusSignalReceived = 0;
// if there are more parameters than ""
if (arguments.length > 1) {
olms.G_LastError = G_InvalidArgumentError;
olms.G_LastErrorMessage = G_InvalidArgumentErrorMessage;
olms.G_LastError = G_InvalidArgumentError;
olms.G_LastErrorMessage = G_InvalidArgumentErrorMessage;
logit_scorm('Error '+ G_InvalidArgumentError + G_InvalidArgumentErrorMessage, 0);
return('false');
} else {
@ -294,11 +308,13 @@ function LMSInitialize() {
+ '\nlms_lp_id : '+ olms.lms_lp_id
+ '\nlms_user_id : '+ olms.lms_user_id
+ '\nlms_view_id : '+ olms.lms_view_id
+ '\nfinishSignalReceived : '+ olms.finishSignalReceived
+ '\nstatusSignalReceived : '+ olms.statusSignalReceived
;
logit_scorm('LMSInitialize() with params: '+log);
if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
xajax_start_timer();
}
@ -312,7 +328,7 @@ function LMSInitialize() {
} else {
attach_glossary_into_scorm('manual');
}
<?php } elseif ( api_get_setting ( 'show_glossary_in_documents' ) == 'isautomatic' ) { ?>
<?php } elseif ( api_get_setting ( 'show_glossary_in_documents' ) == 'isautomatic' ) { ?>
attach_glossary_into_scorm('automatic');
<?php } ?>
return('true');
@ -549,7 +565,7 @@ function LMSGetValue(param) {
} else if(param == 'cmi.interactions._children'){
// ---- cmi.interactions._children
result = 'id,time,type,correct_responses,weighting,student_response,result,latency';
} else {
} else{
// ---- anything else
// Invalid argument error
olms.G_LastError = G_InvalidArgumentError ;
@ -582,6 +598,7 @@ function LMSSetValue(param, val) {
olms.commit = true; //value has changed, need to re-commit
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
return_value = 'false';
if ( param == "cmi.core.score.raw" ) {
@ -603,6 +620,7 @@ function LMSSetValue(param, val) {
} else if ( param == "cmi.core.lesson_status" ) {
olms.lesson_status = val;
olms.updatable_vars_list['cmi.core.lesson_status'] = true;
olms.statusSignalReceived = 1;
return_value='true';
} else if ( param == "cmi.completion_status" ) {
olms.lesson_status = val;
@ -693,8 +711,8 @@ function LMSSetValue(param, val) {
return_value='true';
break;
case "correct_responses":
//do nothing yet
olms.interactions[elem_id][4].push(val) ;
// Add at the end of the array
olms.interactions[elem_id][4][olms.interactions[elem_id][4].length] = val ;
logit_scorm("Interaction "+elem_id+"'s correct_responses not updated",2);
return_value='true';
break;
@ -800,12 +818,10 @@ function SetValue(param, val) {
/**
* Saves the current data from JS memory to the LMS database
* @param string The origin of the call to save the data ('commit','finish', 'unload' or 'terminate')
* @note origin actually seems deprecated now
*/
function savedata(origin ) {
function savedata() {
//origin can be 'commit', 'finish' or 'terminate' (depending on the calling function)
logit_lms('function savedata() with origin: ' + origin , 3);
logit_lms('function savedata()', 3);
//Status is NOT modified here see the lp_ajax_save_item.php file
@ -830,11 +846,27 @@ function savedata(origin) {
//xajax_save_item_scorm(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, old_item_id);
//Modified version
xajax_save_item_scorm(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, item_to_save);
xajax_save_item_scorm(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
item_to_save,
olms.session_id,
olms.course_id,
olms.finishSignalReceived,
olms.userNavigatesAway,
olms.statusSignalReceived
);
olms.info_lms_item[1] = olms.lms_item_id;
if (olms.item_objectives.length > 0) {
xajax_save_objectives(olms.lms_lp_id,olms.lms_user_id,olms.lms_view_id, old_item_id, olms.item_objectives);
xajax_save_objectives(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
old_item_id,
olms.item_objectives
);
}
olms.execute_stats = false;
//clean array
@ -854,10 +886,11 @@ function LMSCommit(val) {
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
savedata('commit' );
savedata();
reinit_updatable_vars_list();
//commit = 'false' ; //now changes have been commited, no need to update until next SetValue()
//now changes have been commited, no need to update until next SetValue()
//commit = 'false' ;
return('true');
}
@ -880,17 +913,16 @@ function Commit(val) {
function LMSFinish(val) {
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
olms.finishSignalReceived = 1;
// if olms.commit == false, then the SCORM didn't ask for a commit, so we
// should at least report that
if ( !olms.commit ) {
logit_scorm('LMSFinish() (no LMSCommit())',1);
}
//if ( olms.commit ) {
logit_scorm('LMSFinish() called',1);
savedata('finish');
olms.commit = false;
//}
logit_scorm('LMSFinish() called',1);
savedata();
olms.commit = false;
//reinit the list of modified variables
reinit_updatable_vars_list();
@ -971,7 +1003,7 @@ function Terminate() {
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
olms.commit = true;
savedata('terminate' );
savedata();
return ('true');
}
}
@ -1064,9 +1096,32 @@ function lms_save_asset() {
if (olms.lms_lp_type == 1 || olms.lms_item_type == 'asset' || olms.lms_item_type == 'document') {
logit_lms('lms_save_asset');
logit_lms('execute_stats :'+ olms.execute_stats);
xajax_save_item(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, olms.lms_item_id, olms.score, olms.max, olms.min, olms.lesson_status, olms.session_time, olms.suspend_data, olms.lesson_location, olms.interactions, olms.lms_item_core_exit, olms.lms_item_type);
xajax_save_item(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.score,
olms.max,
olms.min,
olms.lesson_status,
olms.session_time,
olms.suspend_data,
olms.lesson_location,
olms.interactions,
olms.lms_item_core_exit,
olms.lms_item_type,
olms.session_id,
olms.course_id
);
if (olms.item_objectives.length>0) {
xajax_save_objectives(olms.lms_lp_id,olms.lms_user_id,olms.lms_view_id,olms.lms_item_id,olms.item_objectives);
xajax_save_objectives(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.item_objectives
);
}
}
}
@ -1236,7 +1291,11 @@ function update_stats_page() {
*/
function update_progress_bar(nbr_complete, nbr_total, mode) {
logit_lms('update_progress_bar('+nbr_complete+', '+nbr_total+', '+mode+')',3);
logit_lms('update_progress_bar with params: lms_lp_id= '+olms.lms_lp_id+', lms_view_id= '+olms.lms_view_id+' lms_user_id= '+olms.lms_user_id,3);
logit_lms(
'update_progress_bar with params: lms_lp_id= ' + olms.lms_lp_id +
', lms_view_id= '+ olms.lms_view_id + ' lms_user_id= '+ olms.lms_user_id,
3
);
if (mode == '') {
mode='%';
@ -1344,20 +1403,67 @@ function switch_item(current_item, next_item){
} else {
logit_lms('Case 2 - current != sco but next == sco');
}
xajax_save_item(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, olms.lms_item_id, olms.score, olms.max, olms.min, olms.lesson_status, olms.asset_timer, olms.suspend_data, olms.lesson_location,olms.interactions, olms.lms_item_core_exit, orig_item_type);
xajax_switch_item_details(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, olms.lms_item_id, next_item);
xajax_save_item(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.score,
olms.max,
olms.min,
olms.lesson_status,
olms.asset_timer,
olms.suspend_data,
olms.lesson_location,
olms.interactions,
olms.lms_item_core_exit,
olms.session_id,
olms.course_id,
olms.finishSignalReceived,
1,
olms.statusSignalReceived
);
xajax_switch_item_details(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
next_item
);
} else {
if (next_item_type != 'sco') {
logit_lms('Case 3 - current == sco but next != sco');
} else {
logit_lms('Case 4 - current == sco and next == sco');
}
xajax_save_item_scorm(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, olms.lms_item_id);
xajax_save_item_scorm(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.session_id,
olms.course_id,
olms.finishSignalReceived,
1,
olms.statusSignalReceived
);
reinit_updatable_vars_list();
xajax_switch_item_toc(olms.lms_lp_id,olms.lms_user_id,olms.lms_view_id,olms.lms_item_id,next_item);
xajax_switch_item_toc(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
next_item
);
if (olms.item_objectives.length>0) {
xajax_save_objectives(olms.lms_lp_id,olms.lms_user_id,olms.lms_view_id,olms.lms_item_id,olms.item_objectives);
xajax_save_objectives(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.item_objectives
);
}
}
@ -1375,18 +1481,42 @@ function switch_item(current_item, next_item){
* because another onunload event can be triggered by the SCO itself,
* which can set, for example, the status to incomplete while the
* status has already been set to "completed" by the hand-made
* savedata(unload ) (and then the status cannot be "incompleted"
* savedata() (and then the status cannot be "incompleted"
* anymore)
*/
/*
if (olms.lms_item_type=='sco' & & olms.lesson_status != 'completed' & & olms.lesson_status != 'passed' & & olms.lesson_status != 'browsed' & & olms.lesson_status != 'incomplete' & & olms.lesson_status != 'failed') {
// savedata('finish') treats the special condition and saves the
// new status to the database, so switch_item_details() enjoys the
// new status
savedata('finish');
if (olms.lms_item_type=='sco' & &
olms.lesson_status != 'completed' & &
olms.lesson_status != 'passed' & &
olms.lesson_status != 'browsed' & &
olms.lesson_status != 'incomplete' & &
olms.lesson_status != 'failed'
) {
// savedata() with olms.finishSignalReceived == 1 treats the special
// condition and saves the new status to the database, so
// switch_item_details() enjoys the new status
savedata();
}
xajax_save_item(olms.lms_lp_id, olms.lms_user_id, olms.lms_view_id, olms.lms_item_id, olms.score, olms.max, olms.min, olms.lesson_status, olms.session_time, olms.suspend_data, olms.lesson_location,olms.interactions, olms.lms_item_core_exit, olms.lms_item_type);
xajax_save_item(
olms.lms_lp_id,
olms.lms_user_id,
olms.lms_view_id,
olms.lms_item_id,
olms.score, olms.max,
olms.min,
olms.lesson_status,
olms.session_time,
olms.suspend_data,
olms.lesson_location,
olms.interactions,
olms.lms_item_core_exit,
olms.session_id,
olms.course_id,
olms.finishSignalReceived,
1,
olms.statusSignalReceived
);
*/
olms.execute_stats = false;
@ -1431,17 +1561,18 @@ function switch_item(current_item, next_item){
break;
}
var mysrc = 'lp_controller.php?action=content&lp_id='+olms.lms_lp_id+'&item_id='+next_item+'&cidReq='+olms.lms_course_code;
var mysrc = 'lp_controller.php?action=content& lp_id=' + olms.lms_lp_id +
'& item_id=' + next_item + '& cidReq=' + olms.lms_course_code;
var cont_f = $("#content_id");
<?php if ( $oLP -> mode == 'fullscreen' ) { ?>
cont_f = window.open(''+mysrc,'content_id','toolbar=0,location=0,status=0,scrollbars=1,resizable=1');
cont_f.onload=function(){
olms.info_lms_item[0]=olms.info_lms_item[1];
}
cont_f.onunload=function(){
olms.info_lms_item[0]=olms.info_lms_item[1];
}
cont_f = window.open('' + mysrc, 'content_id', 'toolbar=0,location=0,status=0,scrollbars=1,resizable=1');
cont_f.onload=function(){
olms.info_lms_item[0]=olms.info_lms_item[1];
}
cont_f.onunload=function(){
olms.info_lms_item[0]=olms.info_lms_item[1];
}
<?php } else { ?>
log_in_log('loading '+mysrc+' in frame');
@ -1513,7 +1644,10 @@ function xajax_save_item(
lms_item_core_exit,
item_type,
session_id,
course_id) {
course_id,
finishSignalReceived = 0,
userNavigatesAway = 0,
statusSignalReceived = 0) {
var params = '';
params += 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id;
params += '&iid='+lms_item_id+'&s='+score+'&max='+max+'&min='+min;
@ -1522,6 +1656,10 @@ function xajax_save_item(
params += '&core_exit='+lms_item_core_exit;
params += '&session_id='+session_id;
params += '&course_id='+course_id;
params += '&finishSignalReceived='+finishSignalReceived;
params += '&userNavigatesAway='+userNavigatesAway;
params += '&statusSignalReceived='+statusSignalReceived;
//console.info(session_time);
if (olms.lms_lp_type == 1 || item_type == 'document') {
logit_lms('xajax_save_item with params:' + params,3);
@ -1543,13 +1681,35 @@ function xajax_save_item(
* @param int ID of the user
* @param int ID of the view
* @param int ID of the item
* @param bool 1 if this call comes from a "LMSFinish()" call, 0 or nothing otherwise
* @return void
* @uses olms.updatable_vars_list
* @uses lp_ajax_save_item.php through an AJAX call
*/
function xajax_save_item_scorm(lms_lp_id, lms_user_id, lms_view_id, lms_item_id) {
function xajax_save_item_scorm(
lms_lp_id,
lms_user_id,
lms_view_id,
lms_item_id,
session_id,
course_id,
finishSignalReceived = 0,
userNavigatesAway = 0,
statusSignalReceived = 0
)
{
if (typeof(finish) == 'undefined') {
finish = 0;
}
var is_interactions='false';
var params = 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id+'&iid='+lms_item_id;
// The missing arguments will be ignored by lp_ajax_save_item.php
//params += '&s=&max=&min=&status=&t=&suspend=&loc=&interact=&core_exit=';
params += '&session_id='+session_id;
params += '&course_id='+course_id;
params += '&finishSignalReceived='+finishSignalReceived;
params += '&userNavigatesAway='+userNavigatesAway;
params += '&statusSignalReceived='+statusSignalReceived;
var my_scorm_values = new Array();
my_scorm_values = process_scorm_values();
@ -1624,7 +1784,7 @@ function xajax_save_item_scorm(lms_lp_id, lms_user_id, lms_view_id, lms_item_id)
/**
* Starts the timer with the server clock time.
* @return void
* @todo check the timer stuff really works
* @todo check the timer stuff really works and rename function to startTimer()
* @uses lp_ajax_start_timer.php
*/
function xajax_start_timer() {
@ -1744,7 +1904,7 @@ function xajax_switch_item_toc(lms_lp_id, lms_user_id, lms_view_id, lms_item_id,
/**
* Allow attach the glossary terms into html document of scorm. This has
* nothing to do with SCORM itself, and should not interfere w/ SCORM either.
* @param string automatic or manual values are allowed
* @param string automatic or manual values are allowed
*/
function attach_glossary_into_scorm(type) {
var f = $('#content_id')[0];
@ -1819,7 +1979,8 @@ function attach_glossary_into_scorm(type) {
div_show_id="div_show_id";
div_content_id="div_content_id";
$("iframe").contents().find("body").append('< div id = "div_show_id" > < div id = "div_content_id" > < / div > < / div > ');
$("iframe").contents().find("body").
append('< div id = "div_show_id" > < div id = "div_content_id" > < / div > < / div > ');
show_dialog = $("iframe").contents().find("div#"+div_show_id);
show_description = $("iframe").contents().find("div#"+div_content_id);
@ -1868,7 +2029,8 @@ function attach_glossary_into_scorm(type) {
div_show_id="div_show_id";
div_content_id="div_content_id";
$("iframe").contents().find("body").append('< div id = "div_show_id" > < div id = "div_content_id" > < / div > < / div > ');
$("iframe").contents().find("body").
append('< div id = "div_show_id" > < div id = "div_content_id" > < / div > < / div > ');
show_dialog = $("iframe").contents().find("div#"+div_show_id);
show_description = $("iframe").contents().find("div#"+div_content_id);
@ -1893,9 +2055,6 @@ function attach_glossary_into_scorm(type) {
}
});
//$("iframe").contents().find("div#"+div_show_id).attr("style","display:inline;float:left;position:absolute;background-color:#F2F2F2;border-bottom: 1px solid #2E2E2E;border-right: 1px solid #2E2E2E;border-left: 1px solid #2E2E2E;border-top: 1px solid #2E2E2E;color:#305582;margin-left:5px;margin-right:5px;");
//$("iframe").contents().find("div#"+div_content_id).attr("style","background-color:#F2F2F2;color:#0B3861;margin-left:8px;margin-right:8px;margin-top:5px;margin-bottom:5px;");
$.ajax({
contentType: "application/x-www-form-urlencoded",
type: "POST",